VOXELFORMAT: allow to load minecraft schematic files
parent
70b5d3bd93
commit
77df9b968b
|
@ -11,6 +11,7 @@
|
|||
| Goxel | gox | X | X | X | | X | |
|
||||
| MagicaVoxel | vox | X | X | X | X | X | ttps://github.com/ephtracy/voxel-model |
|
||||
| Minecraft Region | mcr | X | | X | X | X | https://minecraft.gamepedia.com/Region_file_format |
|
||||
| Minecraft Schematics | schematic | X | | X | X | X | https://minecraft.fandom.com/wiki/Schematic_file_format |
|
||||
| Nick's Voxel Model | nvm | X | | X | | X | |
|
||||
| Qubicle Exchange | qef | X | X | X | | | https://getqubicle.com/qubicle/documentation/docs/file/qef/ |
|
||||
| Qubicle Binary Tree | qbt | X | X | X | | X | https://getqubicle.com/qubicle/documentation/docs/file/qbt/ |
|
||||
|
|
|
@ -5,6 +5,7 @@ set(SRCS
|
|||
external/tiny_gltf.h
|
||||
external/json.hpp
|
||||
|
||||
private/MinecraftPaletteMap.h private/MinecraftPaletteMap.cpp
|
||||
private/NamedBinaryTag.h private/NamedBinaryTag.cpp
|
||||
private/PaletteLookup.h
|
||||
|
||||
|
@ -36,6 +37,7 @@ set(SRCS
|
|||
SceneGraphNode.h SceneGraphNode.cpp
|
||||
SceneGraphUtil.h SceneGraphUtil.cpp
|
||||
SproxelFormat.h SproxelFormat.cpp
|
||||
SchematicFormat.h SchematicFormat.cpp
|
||||
STLFormat.h STLFormat.cpp
|
||||
VolumeCache.h VolumeCache.cpp
|
||||
VoxFormat.h VoxFormat.cpp
|
||||
|
@ -63,6 +65,7 @@ set(TEST_SRCS
|
|||
tests/QBCLFormatTest.cpp
|
||||
tests/QEFFormatTest.cpp
|
||||
tests/SceneGraphTest.cpp
|
||||
tests/SchematicFormatTest.cpp
|
||||
tests/SproxelFormatTest.cpp
|
||||
tests/STLFormatTest.cpp
|
||||
tests/VoxFormatTest.cpp
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "io/MemoryReadStream.h"
|
||||
#include "io/ZipReadStream.h"
|
||||
#include "private/NamedBinaryTag.h"
|
||||
#include "private/MinecraftPaletteMap.h"
|
||||
#include "voxel/MaterialColor.h"
|
||||
#include "voxel/RawVolumeWrapper.h"
|
||||
#include "voxelutil/VolumeCropper.h"
|
||||
|
@ -384,324 +385,6 @@ voxel::RawVolume *MCRFormat::parseLevelCompound(int dataVersion, const priv::Nam
|
|||
return finalize(volumes, xPos, zPos);
|
||||
}
|
||||
|
||||
using PaletteMap = core::StringMap<int>;
|
||||
|
||||
// this list was found in enkiMI by Doug Binks and extended
|
||||
static const PaletteMap &getPaletteMap() {
|
||||
static const PaletteMap mcPalette{{"air", 0},
|
||||
{"stone", 1},
|
||||
{"andesite", 1},
|
||||
{"seagrass", 2},
|
||||
{"grass", 2},
|
||||
{"grass_block", 2},
|
||||
{"dirt", 3},
|
||||
{"cobblestone", 4},
|
||||
{"oak_planks", 5},
|
||||
{"oak_sapling", 6},
|
||||
{"bedrock", 7},
|
||||
{"flowing_water", 8},
|
||||
{"water", 9},
|
||||
{"flowing_lava", 10},
|
||||
{"lava", 11},
|
||||
{"sand", 12},
|
||||
{"gravel", 13},
|
||||
{"gold_ore", 14},
|
||||
{"iron_ore", 15},
|
||||
{"coal_ore", 16},
|
||||
{"oak_log", 17},
|
||||
{"acacia_leaves", 18},
|
||||
{"spruce_leaves", 18},
|
||||
{"oak_leaves", 18},
|
||||
{"jungle_leaves", 18},
|
||||
{"birch_leaves", 18},
|
||||
{"sponge", 19},
|
||||
{"glass", 20},
|
||||
{"lapis_ore", 21},
|
||||
{"lapis_block", 22},
|
||||
{"dispenser", 23},
|
||||
{"sandstone", 24},
|
||||
{"note_block", 25},
|
||||
{"red_bed", 26},
|
||||
{"powered_rail", 27},
|
||||
{"detector_rail", 28},
|
||||
{"sticky_piston", 29},
|
||||
{"cobweb", 30},
|
||||
{"tall_grass", 31},
|
||||
{"tall_seagrass", 31},
|
||||
{"dead_bush", 32},
|
||||
{"piston", 33},
|
||||
{"piston_head", 34},
|
||||
{"white_concrete", 35},
|
||||
{"dandelion", 37},
|
||||
{"poppy", 38},
|
||||
{"brown_mushroom", 39},
|
||||
{"red_mushroom", 40},
|
||||
{"gold_block", 41},
|
||||
{"iron_block", 42},
|
||||
{"smooth_stone_slab", 43},
|
||||
{"stone_slab", 44},
|
||||
{"brick_wall", 45},
|
||||
{"bricks", 45},
|
||||
{"tnt", 46},
|
||||
{"bookshelf", 47},
|
||||
{"mossy_cobblestone", 48},
|
||||
{"obsidian", 49},
|
||||
{"torch", 50},
|
||||
{"fire", 51},
|
||||
{"spawner", 52},
|
||||
{"oak_stairs", 53},
|
||||
{"chest", 54},
|
||||
{"redstone_wire", 55},
|
||||
{"diamond_ore", 56},
|
||||
{"diamond_block", 57},
|
||||
{"crafting_table", 58},
|
||||
{"wheat", 59},
|
||||
{"farmland", 60},
|
||||
{"furnace", 61},
|
||||
{"campfire", 62},
|
||||
{"oak_sign", 63},
|
||||
{"oak_door", 64},
|
||||
{"ladder", 65},
|
||||
{"rail", 66},
|
||||
{"stone_stairs", 67},
|
||||
{"oak_wall_sign", 68},
|
||||
{"lever", 69},
|
||||
{"stone_pressure_plate", 70},
|
||||
{"iron_door", 71},
|
||||
{"oak_pressure_plate", 72},
|
||||
{"redstone_ore", 73},
|
||||
{"red_concrete", 74},
|
||||
{"redstone_wall_torch", 75},
|
||||
{"redstone_torch", 76},
|
||||
{"stone_button", 77},
|
||||
{"snow_block", 78},
|
||||
{"ice", 79},
|
||||
{"snow", 80},
|
||||
{"cactus", 81},
|
||||
{"clay", 82},
|
||||
{"bamboo", 83},
|
||||
{"jukebox", 84},
|
||||
{"oak_fence", 85},
|
||||
{"pumpkin", 86},
|
||||
{"netherrack", 87},
|
||||
{"soul_sand", 88},
|
||||
{"glowstone", 89},
|
||||
{"portal", 90},
|
||||
{"carved_pumpkin", 91},
|
||||
{"cake", 92},
|
||||
{"repeater", 93},
|
||||
{"skeleton_skull", 94},
|
||||
{"white_stained_glass", 95},
|
||||
{"oak_trapdoor", 96},
|
||||
{"turtle_egg", 97},
|
||||
{"stone_bricks", 98},
|
||||
{"brown_mushroom_block", 99},
|
||||
{"red_mushroom_block", 100},
|
||||
{"iron_bars", 101},
|
||||
{"light_blue_stained_glass_pane", 102},
|
||||
{"melon", 103},
|
||||
{"pumpkin_stem", 104},
|
||||
{"melon_stem", 105},
|
||||
{"vine", 106},
|
||||
{"oak_fence_gate", 107},
|
||||
{"brick_stairs", 108},
|
||||
{"stone_brick_stairs", 109},
|
||||
{"mycelium", 110},
|
||||
{"light_gray_concrete", 111},
|
||||
{"nether_brick", 112},
|
||||
{"nether_brick_fence", 113},
|
||||
{"nether_brick_stairs", 114},
|
||||
{"nether_wart", 115},
|
||||
{"enchanting_table", 116},
|
||||
{"brewing_stand", 117},
|
||||
{"cauldron", 118},
|
||||
{"end_portal", 119},
|
||||
{"end_portal_frame", 120},
|
||||
{"end_stone", 121},
|
||||
{"dragon_egg", 122},
|
||||
{"redstone_lamp", 123},
|
||||
{"shroomlight", 124},
|
||||
{"oak_wood", 125},
|
||||
{"oak_slab", 126},
|
||||
{"cocoa", 127},
|
||||
{"sandstone_stairs", 128},
|
||||
{"emerald_ore", 129},
|
||||
{"ender_chest", 130},
|
||||
{"tripwire_hook", 131},
|
||||
{"tripwire", 132},
|
||||
{"emerald_block", 133},
|
||||
{"spruce_stairs", 134},
|
||||
{"birch_stairs", 135},
|
||||
{"jungle_stairs", 136},
|
||||
{"command_block", 137},
|
||||
{"beacon", 138},
|
||||
{"cobblestone_wall", 139},
|
||||
{"flower_pot", 140},
|
||||
{"carrots", 141},
|
||||
{"potatoes", 142},
|
||||
{"oak_button", 143},
|
||||
{"skeleton_wall_skull", 144},
|
||||
{"anvil", 145},
|
||||
{"trapped_chest", 146},
|
||||
{"light_weighted_pressure_plate", 147},
|
||||
{"heavy_weighted_pressure_plate", 148},
|
||||
{"comparator", 149},
|
||||
{"chain", 150},
|
||||
{"daylight_detector", 151},
|
||||
{"redstone_block", 152},
|
||||
{"nether_quartz_ore", 153},
|
||||
{"hopper", 154},
|
||||
{"quartz_block", 155},
|
||||
{"quartz_stairs", 156},
|
||||
{"activator_rail", 157},
|
||||
{"dropper", 158},
|
||||
{"pink_stained_glass", 159},
|
||||
{"white_stained_glass_pane", 160},
|
||||
{"dead_brain_coral", 161},
|
||||
{"acacia_planks", 162},
|
||||
{"acacia_stairs", 163},
|
||||
{"dark_oak_stairs", 164},
|
||||
{"slime_block", 165},
|
||||
{"barrier", 166},
|
||||
{"iron_trapdoor", 167},
|
||||
{"prismarine", 168},
|
||||
{"sea_lantern", 169},
|
||||
{"hay_block", 170},
|
||||
{"white_carpet", 171},
|
||||
{"coarse_dirt", 172},
|
||||
{"coal_block", 173},
|
||||
{"packed_ice", 174},
|
||||
{"orange_concrete", 175},
|
||||
{"white_banner", 176},
|
||||
{"white_wall_banner", 177},
|
||||
{"white_concrete_powder", 178},
|
||||
{"red_sandstone", 179},
|
||||
{"red_sandstone_stairs", 180},
|
||||
{"red_sandstone_wall", 181},
|
||||
{"red_sandstone_slab", 182},
|
||||
{"spruce_fence_gate", 183},
|
||||
{"birch_fence_gate", 184},
|
||||
{"jungle_fence_gate", 185},
|
||||
{"dark_oak_fence_gate", 186},
|
||||
{"acacia_fence_gate", 187},
|
||||
{"spruce_fence", 188},
|
||||
{"birch_fence", 189},
|
||||
{"jungle_fence", 190},
|
||||
{"dark_oak_fence", 191},
|
||||
{"acacia_fence", 192},
|
||||
{"spruce_door", 193},
|
||||
{"birch_door", 194},
|
||||
{"jungle_door", 195},
|
||||
{"acacia_door", 196},
|
||||
{"dark_oak_door", 197},
|
||||
{"end_rod", 198},
|
||||
{"chorus_plant", 199},
|
||||
{"chorus_flower", 200},
|
||||
{"purpur_block", 201},
|
||||
{"purpur_pillar", 202},
|
||||
{"purpur_stairs", 203},
|
||||
{"purple_stained_glass", 204},
|
||||
{"purpur_slab", 205},
|
||||
{"end_stone_bricks", 206},
|
||||
{"beetroots", 207},
|
||||
{"grass_path", 208},
|
||||
{"end_gateway", 209},
|
||||
{"repeating_command_block", 210},
|
||||
{"chain_command_block", 211},
|
||||
{"frosted_ice", 212},
|
||||
{"magma_block", 213},
|
||||
{"nether_wart_block", 214},
|
||||
{"red_nether_bricks", 215},
|
||||
{"bone_block", 216},
|
||||
{"structure_void", 217},
|
||||
{"observer", 218},
|
||||
{"white_shulker_box", 219},
|
||||
{"orange_shulker_box", 220},
|
||||
{"magenta_shulker_box", 221},
|
||||
{"light_blue_shulker_box", 222},
|
||||
{"yellow_shulker_box", 223},
|
||||
{"lime_shulker_box", 224},
|
||||
{"pink_shulker_box", 225},
|
||||
{"gray_shulker_box", 226},
|
||||
{"light_gray_shulker_box", 227},
|
||||
{"cyan_shulker_box", 228},
|
||||
{"purple_shulker_box", 229},
|
||||
{"blue_shulker_box", 230},
|
||||
{"brown_shulker_box", 231},
|
||||
{"green_shulker_box", 232},
|
||||
{"red_shulker_box", 233},
|
||||
{"black_shulker_box", 234},
|
||||
{"white_glazed_terracotta", 235},
|
||||
{"orange_glazed_terracotta", 236},
|
||||
{"magenta_glazed_terracotta", 237},
|
||||
{"light_blue_glazed_terracotta", 238},
|
||||
{"yellow_glazed_terracotta", 239},
|
||||
{"lime_glazed_terracotta", 240},
|
||||
{"pink_glazed_terracotta", 241},
|
||||
{"gray_glazed_terracotta", 242},
|
||||
{"light_gray_glazed_terracotta", 243},
|
||||
{"cyan_glazed_terracotta", 244},
|
||||
{"purple_glazed_terracotta", 245},
|
||||
{"blue_glazed_terracotta", 246},
|
||||
{"brown_glazed_terracotta", 247},
|
||||
{"green_glazed_terracotta", 248},
|
||||
{"red_glazed_terracotta", 249},
|
||||
{"black_glazed_terracotta", 250},
|
||||
{"gray_concrete", 251},
|
||||
{"gray_concrete_powder", 252},
|
||||
{"deepslate_redstone_ore", 1}, // TODO
|
||||
{"deepslate_iron_ore", 1}, // TODO
|
||||
{"kelp", 1}, // TODO
|
||||
{"deepslate", 1}, // TODO
|
||||
{"moss_carpet", 1}, // TODO
|
||||
{"granite", 1}, // TODO
|
||||
{"diorite", 1}, // TODO
|
||||
{"glow_lichen", 1}, // TODO
|
||||
{"copper_ore", 1}, // TODO
|
||||
{"tuff", 1}, // TODO
|
||||
{"deepslate_gold_ore", 1}, // TODO
|
||||
{"flowering_azalea", 1}, // TODO
|
||||
{"azalea", 1}, // TODO
|
||||
{"cave_vines", 1}, // TODO
|
||||
{"cave_vines_plant", 1}, // TODO
|
||||
{"big_dripleaf", 1}, // TODO
|
||||
{"big_dripleaf_stem", 1}, // TODO
|
||||
{"spore_blossom", 1}, // TODO
|
||||
{"deepslate_diamond_ore", 1}, // TODO
|
||||
{"budding_amethyst", 1}, // TODO
|
||||
{"smooth_basalt", 1}, // TODO
|
||||
{"birch_log", 1}, // TODO
|
||||
{"cave_air", 1}, // TODO
|
||||
{"kelp_plant", 1}, // TODO
|
||||
{"deepslate_lapis_ore", 1}, // TODO
|
||||
{"deepslate_copper_ore", 1}, // TODO
|
||||
{"moss_block", 1}, // TODO
|
||||
{"small_amethyst_bud", 1}, // TODO
|
||||
{"calcite", 1}, // TODO
|
||||
{"amethyst_block", 1}, // TODO
|
||||
{"medium_amethyst_bud", 1}, // TODO
|
||||
{"large_amethyst_bud", 1}, // TODO
|
||||
{"amethyst_cluster", 1}, // TODO
|
||||
{"mossy_stone_bricks", 1}, // TODO
|
||||
{"cracked_stone_bricks", 1}, // TODO
|
||||
{"small_dripleaf", 1}, // TODO
|
||||
{"deepslate_coal_ore", 1}, // TODO
|
||||
{"fern", 1}, // TODO
|
||||
{"raw_copper_block", 1}, // TODO
|
||||
{"raw_iron_block", 1}, // TODO
|
||||
{"jungle_log", 1}, // TODO
|
||||
{"wall_torch", 1}, // TODO
|
||||
{"raw_iron_block", 1}, // TODO
|
||||
{"polished_granite", 1}, // TODO
|
||||
{"cut_sandstone", 1}, // TODO
|
||||
{"oxeye_daisy", 1}, // TODO
|
||||
{"sugar_cane", 1}, // TODO
|
||||
{"azure_bluet", 1}, // TODO
|
||||
{"cornflower", 1}, // TODO
|
||||
{"structure_block", 255}};
|
||||
return mcPalette;
|
||||
}
|
||||
|
||||
bool MCRFormat::parsePaletteList(int dataVersion, const priv::NamedBinaryTag &palette, MinecraftSectionPalette §ionPal) {
|
||||
// prior to 1.16 (2556) the palette entries used multiple 64bit fields
|
||||
// TODO const bool paletteMultiBits = dataVersion < 2556;
|
||||
|
@ -736,7 +419,7 @@ bool MCRFormat::parsePaletteList(int dataVersion, const priv::NamedBinaryTag &pa
|
|||
continue;
|
||||
}
|
||||
// skip minecraft:
|
||||
const core::String key = value->substr(10);
|
||||
const core::String key = value->contains("minecraft:") ? value->substr(10) : *value;
|
||||
auto iter = map.find(key);
|
||||
if (iter == map.end()) {
|
||||
Log::debug("Could not find a color mapping for '%s'", key.c_str());
|
||||
|
@ -752,4 +435,4 @@ bool MCRFormat::parsePaletteList(int dataVersion, const priv::NamedBinaryTag &pa
|
|||
|
||||
#undef wrap
|
||||
|
||||
} // namespace voxel
|
||||
} // namespace voxelformat
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "SchematicFormat.h"
|
||||
#include "core/Color.h"
|
||||
#include "core/Common.h"
|
||||
#include "core/Log.h"
|
||||
#include "core/StringUtil.h"
|
||||
#include "core/collection/DynamicArray.h"
|
||||
#include "core/collection/StringMap.h"
|
||||
#include "io/File.h"
|
||||
#include "io/MemoryReadStream.h"
|
||||
#include "io/ZipReadStream.h"
|
||||
#include "private/MinecraftPaletteMap.h"
|
||||
#include "private/NamedBinaryTag.h"
|
||||
#include "voxel/MaterialColor.h"
|
||||
#include "voxel/Palette.h"
|
||||
#include "voxel/RawVolume.h"
|
||||
#include "voxel/RawVolumeWrapper.h"
|
||||
#include "voxel/Region.h"
|
||||
#include "voxel/Voxel.h"
|
||||
#include "voxelutil/VolumeCropper.h"
|
||||
#include "voxelutil/VolumeMerger.h"
|
||||
|
||||
#include <glm/common.hpp>
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
|
||||
_palette.minecraft();
|
||||
const voxel::Palette &palette = voxel::getPalette();
|
||||
for (size_t i = 0; i < _palette.size(); ++i) {
|
||||
_paletteMapping[i] = palette.getClosestMatch(core::Color::fromRGBA(_palette.colors[i]));
|
||||
}
|
||||
io::ZipReadStream zipStream(stream);
|
||||
priv::NamedBinaryTagContext ctx;
|
||||
ctx.stream = &zipStream;
|
||||
const priv::NamedBinaryTag &schematic = priv::NamedBinaryTag::parse(ctx);
|
||||
if (!schematic.valid()) {
|
||||
Log::error("Could not find 'Schematic' tag");
|
||||
return false;
|
||||
}
|
||||
|
||||
const int16_t width = schematic.get("Width").int16();
|
||||
const int16_t height = schematic.get("Height").int16();
|
||||
const int16_t depth = schematic.get("Length").int16();
|
||||
voxel::RawVolume *volume = new voxel::RawVolume(voxel::Region(0, 0, 0, width, height, depth));
|
||||
const priv::NamedBinaryTag &blocks = schematic.get("Blocks");
|
||||
if (!blocks.valid()) {
|
||||
Log::error("Could not find 'Blocks' tag");
|
||||
return false;
|
||||
}
|
||||
|
||||
// const int8_t itemStackVersion = schematic.get("itemStackVersion").int8(); // MCEdit2
|
||||
|
||||
core::Buffer<int> pal;
|
||||
pal.resize(voxel::PaletteMaxColors);
|
||||
int paletteEntry = 0;
|
||||
const priv::NamedBinaryTag &blockIds = schematic.get("BlockIDs"); // MCEdit2
|
||||
if (blockIds.valid()) {
|
||||
const int blockCnt = (int)blockIds.compound()->size();
|
||||
const PaletteMap &map = getPaletteMap();
|
||||
for (int i = 0; i < blockCnt; ++i) {
|
||||
const priv::NamedBinaryTag &nbt = blockIds.get(core::String::format("%i", i));
|
||||
const core::String *value = nbt.string();
|
||||
if (value == nullptr) {
|
||||
continue;
|
||||
}
|
||||
// skip minecraft:
|
||||
const core::String key = value->contains("minecraft:") ? value->substr(10) : *value;
|
||||
auto iter = map.find(key);
|
||||
if (iter == map.end()) {
|
||||
Log::debug("Could not find a color mapping for '%s'", key.c_str());
|
||||
pal[paletteEntry] = -1;
|
||||
} else {
|
||||
pal[paletteEntry] = iter->value;
|
||||
}
|
||||
++paletteEntry;
|
||||
}
|
||||
}
|
||||
|
||||
// const priv::NamedBinaryTag &materials = schematic.get("Materials");
|
||||
// Classic, Pocket, Alpha
|
||||
// const priv::NamedBinaryTag &schematicaMapping = schematic.get("SchematicaMapping");
|
||||
// const priv::NamedBinaryTag &data = schematic.get("Data");
|
||||
|
||||
for (int x = 0; x < width; ++x) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int z = 0; z < depth; ++z) {
|
||||
const int idx = (y * depth + z) * width + x;
|
||||
const uint8_t palIdx = (*blocks.byteArray())[idx];
|
||||
if (palIdx != 0u) {
|
||||
if (paletteEntry == 0) {
|
||||
volume->setVoxel(x, y, z, voxel::createVoxel(voxel::VoxelType::Generic, palIdx));
|
||||
} else {
|
||||
volume->setVoxel(x, y, z, voxel::createVoxel(voxel::VoxelType::Generic, pal[palIdx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int32_t x = schematic.get("x").int32();
|
||||
const int32_t y = schematic.get("y").int32();
|
||||
const int32_t z = schematic.get("z").int32();
|
||||
volume->translate(glm::ivec3(x, y, z));
|
||||
|
||||
SceneGraphNode node(SceneGraphNodeType::Model);
|
||||
node.setVolume(volume, true);
|
||||
sceneGraph.emplace(core::move(node));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace voxelformat
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Format.h"
|
||||
|
||||
namespace io {
|
||||
class ZipReadStream;
|
||||
}
|
||||
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
namespace priv {
|
||||
class NamedBinaryTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note https://minecraft.fandom.com/wiki/Schematic_file_format
|
||||
*/
|
||||
class SchematicFormat : public Format {
|
||||
public:
|
||||
bool loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) override;
|
||||
bool saveGroups(const SceneGraph& sceneGraph, const core::String &filename, io::SeekableWriteStream& stream) override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -39,6 +39,7 @@
|
|||
#include "voxelformat/OBJFormat.h"
|
||||
#include "voxelformat/VoxOldFormat.h"
|
||||
#include "voxelformat/GLTFFormat.h"
|
||||
#include "voxelformat/SchematicFormat.h"
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
|
@ -65,6 +66,7 @@ const io::FormatDescription SUPPORTED_VOXEL_FORMATS_LOAD[] = {
|
|||
{"Goxel", "gox", [] (uint32_t magic) {return magic == FourCC('G','O','X',' ');}, VOX_FORMAT_FLAG_SCREENSHOT_EMBEDDED},
|
||||
{"CubeWorld", "cub", nullptr, VOX_FORMAT_FLAG_PALETTE_EMBEDDED},
|
||||
{"Minecraft region", "mca", nullptr, VOX_FORMAT_FLAG_PALETTE_EMBEDDED},
|
||||
{"Minecraft schematic", "schematic", nullptr, VOX_FORMAT_FLAG_PALETTE_EMBEDDED},
|
||||
{"Sproxel csv", "csv", nullptr, 0u},
|
||||
{"Wavefront Object", "obj", nullptr, 0u},
|
||||
{"Standard Triangle Language", "stl", nullptr, 0u},
|
||||
|
@ -191,6 +193,8 @@ static core::SharedPtr<Format> getFormat(const io::FormatDescription *desc, uint
|
|||
format = core::make_shared<PLYFormat>();
|
||||
} else if (ext == "fbx") {
|
||||
format = core::make_shared<FBXFormat>();
|
||||
} else if (ext == "schematic") {
|
||||
format = core::make_shared<SchematicFormat>();
|
||||
} else if (ext == "gltf" || ext == "glb") {
|
||||
format = core::make_shared<GLTFFormat>();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "MinecraftPaletteMap.h"
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
const PaletteMap &getPaletteMap() {
|
||||
// https://github.com/mcedit/mcedit2/tree/master/src/mceditlib/blocktypes
|
||||
static const PaletteMap mcPalette{{"air", 0},
|
||||
{"stone", 1},
|
||||
{"andesite", 1},
|
||||
{"seagrass", 2},
|
||||
{"grass", 2},
|
||||
{"grass_block", 2},
|
||||
{"dirt", 3},
|
||||
{"cobblestone", 4},
|
||||
{"oak_planks", 5},
|
||||
{"oak_sapling", 6},
|
||||
{"bedrock", 7},
|
||||
{"flowing_water", 8},
|
||||
{"water", 9},
|
||||
{"flowing_lava", 10},
|
||||
{"lava", 11},
|
||||
{"sand", 12},
|
||||
{"gravel", 13},
|
||||
{"gold_ore", 14},
|
||||
{"iron_ore", 15},
|
||||
{"coal_ore", 16},
|
||||
{"oak_log", 17},
|
||||
{"acacia_leaves", 18},
|
||||
{"spruce_leaves", 18},
|
||||
{"oak_leaves", 18},
|
||||
{"jungle_leaves", 18},
|
||||
{"birch_leaves", 18},
|
||||
{"sponge", 19},
|
||||
{"glass", 20},
|
||||
{"lapis_ore", 21},
|
||||
{"lapis_block", 22},
|
||||
{"dispenser", 23},
|
||||
{"sandstone", 24},
|
||||
{"note_block", 25},
|
||||
{"red_bed", 26},
|
||||
{"powered_rail", 27},
|
||||
{"detector_rail", 28},
|
||||
{"sticky_piston", 29},
|
||||
{"cobweb", 30},
|
||||
{"tall_grass", 31},
|
||||
{"tall_seagrass", 31},
|
||||
{"dead_bush", 32},
|
||||
{"piston", 33},
|
||||
{"piston_head", 34},
|
||||
{"white_concrete", 35},
|
||||
{"dandelion", 37},
|
||||
{"poppy", 38},
|
||||
{"brown_mushroom", 39},
|
||||
{"red_mushroom", 40},
|
||||
{"gold_block", 41},
|
||||
{"iron_block", 42},
|
||||
{"smooth_stone_slab", 43},
|
||||
{"stone_slab", 44},
|
||||
{"brick_wall", 45},
|
||||
{"bricks", 45},
|
||||
{"tnt", 46},
|
||||
{"bookshelf", 47},
|
||||
{"mossy_cobblestone", 48},
|
||||
{"obsidian", 49},
|
||||
{"torch", 50},
|
||||
{"fire", 51},
|
||||
{"spawner", 52},
|
||||
{"oak_stairs", 53},
|
||||
{"chest", 54},
|
||||
{"redstone_wire", 55},
|
||||
{"diamond_ore", 56},
|
||||
{"diamond_block", 57},
|
||||
{"crafting_table", 58},
|
||||
{"wheat", 59},
|
||||
{"farmland", 60},
|
||||
{"furnace", 61},
|
||||
{"campfire", 62},
|
||||
{"oak_sign", 63},
|
||||
{"oak_door", 64},
|
||||
{"ladder", 65},
|
||||
{"rail", 66},
|
||||
{"stone_stairs", 67},
|
||||
{"oak_wall_sign", 68},
|
||||
{"lever", 69},
|
||||
{"stone_pressure_plate", 70},
|
||||
{"iron_door", 71},
|
||||
{"oak_pressure_plate", 72},
|
||||
{"redstone_ore", 73},
|
||||
{"red_concrete", 74},
|
||||
{"redstone_wall_torch", 75},
|
||||
{"redstone_torch", 76},
|
||||
{"stone_button", 77},
|
||||
{"snow_block", 78},
|
||||
{"ice", 79},
|
||||
{"snow", 80},
|
||||
{"cactus", 81},
|
||||
{"clay", 82},
|
||||
{"bamboo", 83},
|
||||
{"jukebox", 84},
|
||||
{"oak_fence", 85},
|
||||
{"pumpkin", 86},
|
||||
{"netherrack", 87},
|
||||
{"soul_sand", 88},
|
||||
{"glowstone", 89},
|
||||
{"portal", 90},
|
||||
{"carved_pumpkin", 91},
|
||||
{"cake", 92},
|
||||
{"repeater", 93},
|
||||
{"skeleton_skull", 94},
|
||||
{"white_stained_glass", 95},
|
||||
{"oak_trapdoor", 96},
|
||||
{"turtle_egg", 97},
|
||||
{"stone_bricks", 98},
|
||||
{"brown_mushroom_block", 99},
|
||||
{"red_mushroom_block", 100},
|
||||
{"iron_bars", 101},
|
||||
{"light_blue_stained_glass_pane", 102},
|
||||
{"melon", 103},
|
||||
{"pumpkin_stem", 104},
|
||||
{"melon_stem", 105},
|
||||
{"vine", 106},
|
||||
{"oak_fence_gate", 107},
|
||||
{"brick_stairs", 108},
|
||||
{"stone_brick_stairs", 109},
|
||||
{"mycelium", 110},
|
||||
{"light_gray_concrete", 111},
|
||||
{"nether_brick", 112},
|
||||
{"nether_brick_fence", 113},
|
||||
{"nether_brick_stairs", 114},
|
||||
{"nether_wart", 115},
|
||||
{"enchanting_table", 116},
|
||||
{"brewing_stand", 117},
|
||||
{"cauldron", 118},
|
||||
{"end_portal", 119},
|
||||
{"end_portal_frame", 120},
|
||||
{"end_stone", 121},
|
||||
{"dragon_egg", 122},
|
||||
{"redstone_lamp", 123},
|
||||
{"shroomlight", 124},
|
||||
{"oak_wood", 125},
|
||||
{"oak_slab", 126},
|
||||
{"cocoa", 127},
|
||||
{"sandstone_stairs", 128},
|
||||
{"emerald_ore", 129},
|
||||
{"ender_chest", 130},
|
||||
{"tripwire_hook", 131},
|
||||
{"tripwire", 132},
|
||||
{"emerald_block", 133},
|
||||
{"spruce_stairs", 134},
|
||||
{"birch_stairs", 135},
|
||||
{"jungle_stairs", 136},
|
||||
{"command_block", 137},
|
||||
{"beacon", 138},
|
||||
{"cobblestone_wall", 139},
|
||||
{"flower_pot", 140},
|
||||
{"carrots", 141},
|
||||
{"potatoes", 142},
|
||||
{"oak_button", 143},
|
||||
{"skeleton_wall_skull", 144},
|
||||
{"anvil", 145},
|
||||
{"trapped_chest", 146},
|
||||
{"light_weighted_pressure_plate", 147},
|
||||
{"heavy_weighted_pressure_plate", 148},
|
||||
{"comparator", 149},
|
||||
{"chain", 150},
|
||||
{"daylight_detector", 151},
|
||||
{"redstone_block", 152},
|
||||
{"nether_quartz_ore", 153},
|
||||
{"hopper", 154},
|
||||
{"quartz_block", 155},
|
||||
{"quartz_stairs", 156},
|
||||
{"activator_rail", 157},
|
||||
{"dropper", 158},
|
||||
{"pink_stained_glass", 159},
|
||||
{"white_stained_glass_pane", 160},
|
||||
{"dead_brain_coral", 161},
|
||||
{"acacia_planks", 162},
|
||||
{"acacia_stairs", 163},
|
||||
{"dark_oak_stairs", 164},
|
||||
{"slime_block", 165},
|
||||
{"barrier", 166},
|
||||
{"iron_trapdoor", 167},
|
||||
{"prismarine", 168},
|
||||
{"sea_lantern", 169},
|
||||
{"hay_block", 170},
|
||||
{"white_carpet", 171},
|
||||
{"coarse_dirt", 172},
|
||||
{"coal_block", 173},
|
||||
{"packed_ice", 174},
|
||||
{"orange_concrete", 175},
|
||||
{"white_banner", 176},
|
||||
{"white_wall_banner", 177},
|
||||
{"white_concrete_powder", 178},
|
||||
{"red_sandstone", 179},
|
||||
{"red_sandstone_stairs", 180},
|
||||
{"red_sandstone_wall", 181},
|
||||
{"red_sandstone_slab", 182},
|
||||
{"spruce_fence_gate", 183},
|
||||
{"birch_fence_gate", 184},
|
||||
{"jungle_fence_gate", 185},
|
||||
{"dark_oak_fence_gate", 186},
|
||||
{"acacia_fence_gate", 187},
|
||||
{"spruce_fence", 188},
|
||||
{"birch_fence", 189},
|
||||
{"jungle_fence", 190},
|
||||
{"dark_oak_fence", 191},
|
||||
{"acacia_fence", 192},
|
||||
{"spruce_door", 193},
|
||||
{"birch_door", 194},
|
||||
{"jungle_door", 195},
|
||||
{"acacia_door", 196},
|
||||
{"dark_oak_door", 197},
|
||||
{"end_rod", 198},
|
||||
{"chorus_plant", 199},
|
||||
{"chorus_flower", 200},
|
||||
{"purpur_block", 201},
|
||||
{"purpur_pillar", 202},
|
||||
{"purpur_stairs", 203},
|
||||
{"purple_stained_glass", 204},
|
||||
{"purpur_slab", 205},
|
||||
{"end_stone_bricks", 206},
|
||||
{"beetroots", 207},
|
||||
{"grass_path", 208},
|
||||
{"end_gateway", 209},
|
||||
{"repeating_command_block", 210},
|
||||
{"chain_command_block", 211},
|
||||
{"frosted_ice", 212},
|
||||
{"magma_block", 213},
|
||||
{"nether_wart_block", 214},
|
||||
{"red_nether_bricks", 215},
|
||||
{"bone_block", 216},
|
||||
{"structure_void", 217},
|
||||
{"observer", 218},
|
||||
{"white_shulker_box", 219},
|
||||
{"orange_shulker_box", 220},
|
||||
{"magenta_shulker_box", 221},
|
||||
{"light_blue_shulker_box", 222},
|
||||
{"yellow_shulker_box", 223},
|
||||
{"lime_shulker_box", 224},
|
||||
{"pink_shulker_box", 225},
|
||||
{"gray_shulker_box", 226},
|
||||
{"light_gray_shulker_box", 227},
|
||||
{"cyan_shulker_box", 228},
|
||||
{"purple_shulker_box", 229},
|
||||
{"blue_shulker_box", 230},
|
||||
{"brown_shulker_box", 231},
|
||||
{"green_shulker_box", 232},
|
||||
{"red_shulker_box", 233},
|
||||
{"black_shulker_box", 234},
|
||||
{"white_glazed_terracotta", 235},
|
||||
{"orange_glazed_terracotta", 236},
|
||||
{"magenta_glazed_terracotta", 237},
|
||||
{"light_blue_glazed_terracotta", 238},
|
||||
{"yellow_glazed_terracotta", 239},
|
||||
{"lime_glazed_terracotta", 240},
|
||||
{"pink_glazed_terracotta", 241},
|
||||
{"gray_glazed_terracotta", 242},
|
||||
{"light_gray_glazed_terracotta", 243},
|
||||
{"cyan_glazed_terracotta", 244},
|
||||
{"purple_glazed_terracotta", 245},
|
||||
{"blue_glazed_terracotta", 246},
|
||||
{"brown_glazed_terracotta", 247},
|
||||
{"green_glazed_terracotta", 248},
|
||||
{"red_glazed_terracotta", 249},
|
||||
{"black_glazed_terracotta", 250},
|
||||
{"gray_concrete", 251},
|
||||
{"gray_concrete_powder", 252},
|
||||
{"deepslate_redstone_ore", 1}, // TODO
|
||||
{"deepslate_iron_ore", 1}, // TODO
|
||||
{"kelp", 1}, // TODO
|
||||
{"deepslate", 1}, // TODO
|
||||
{"moss_carpet", 1}, // TODO
|
||||
{"granite", 1}, // TODO
|
||||
{"diorite", 1}, // TODO
|
||||
{"glow_lichen", 1}, // TODO
|
||||
{"copper_ore", 1}, // TODO
|
||||
{"tuff", 1}, // TODO
|
||||
{"deepslate_gold_ore", 1}, // TODO
|
||||
{"flowering_azalea", 1}, // TODO
|
||||
{"azalea", 1}, // TODO
|
||||
{"cave_vines", 1}, // TODO
|
||||
{"cave_vines_plant", 1}, // TODO
|
||||
{"big_dripleaf", 1}, // TODO
|
||||
{"big_dripleaf_stem", 1}, // TODO
|
||||
{"spore_blossom", 1}, // TODO
|
||||
{"deepslate_diamond_ore", 1}, // TODO
|
||||
{"budding_amethyst", 1}, // TODO
|
||||
{"smooth_basalt", 1}, // TODO
|
||||
{"birch_log", 1}, // TODO
|
||||
{"cave_air", 1}, // TODO
|
||||
{"kelp_plant", 1}, // TODO
|
||||
{"deepslate_lapis_ore", 1}, // TODO
|
||||
{"deepslate_copper_ore", 1}, // TODO
|
||||
{"moss_block", 1}, // TODO
|
||||
{"small_amethyst_bud", 1}, // TODO
|
||||
{"calcite", 1}, // TODO
|
||||
{"amethyst_block", 1}, // TODO
|
||||
{"medium_amethyst_bud", 1}, // TODO
|
||||
{"large_amethyst_bud", 1}, // TODO
|
||||
{"amethyst_cluster", 1}, // TODO
|
||||
{"mossy_stone_bricks", 1}, // TODO
|
||||
{"cracked_stone_bricks", 1}, // TODO
|
||||
{"small_dripleaf", 1}, // TODO
|
||||
{"deepslate_coal_ore", 1}, // TODO
|
||||
{"fern", 1}, // TODO
|
||||
{"raw_copper_block", 1}, // TODO
|
||||
{"raw_iron_block", 1}, // TODO
|
||||
{"jungle_log", 1}, // TODO
|
||||
{"wall_torch", 1}, // TODO
|
||||
{"raw_iron_block", 1}, // TODO
|
||||
{"polished_granite", 1}, // TODO
|
||||
{"cut_sandstone", 1}, // TODO
|
||||
{"oxeye_daisy", 1}, // TODO
|
||||
{"sugar_cane", 1}, // TODO
|
||||
{"azure_bluet", 1}, // TODO
|
||||
{"cornflower", 1}, // TODO
|
||||
{"structure_block", 255}};
|
||||
return mcPalette;
|
||||
}
|
||||
|
||||
} // namespace voxelformat
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "core/collection/StringMap.h"
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
using PaletteMap = core::StringMap<int>;
|
||||
|
||||
// this list was found in enkiMI by Doug Binks and extended
|
||||
const PaletteMap &getPaletteMap();
|
||||
|
||||
} // namespace voxelformat
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "voxelformat/SchematicFormat.h"
|
||||
#include "AbstractVoxFormatTest.h"
|
||||
#include "io/FileStream.h"
|
||||
#include "voxelformat/VolumeFormat.h"
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
class SchematicFormatTest : public AbstractVoxFormatTest {};
|
||||
|
||||
TEST_F(SchematicFormatTest, testLoad) {
|
||||
SchematicFormat f;
|
||||
// https://www.planetminecraft.com/project/viking-island-4911284/
|
||||
std::unique_ptr<voxel::RawVolume> volume(load("viking_island.schematic", f));
|
||||
ASSERT_NE(nullptr, volume) << "Could not load schematic file";
|
||||
}
|
||||
|
||||
} // namespace voxelformat
|
Loading…
Reference in New Issue