VOXELFORMAT: fixed some palette related issues
parent
0a45bbb41e
commit
464098270f
|
@ -69,18 +69,21 @@ inline void volumeComparator(const voxel::RawVolume& volume1, const voxel::Palet
|
|||
<< "Voxel differs at " << x1 << ":" << y1 << ":" << z1 << " in material - voxel1["
|
||||
<< voxel::VoxelTypeStr[(int)voxel1.getMaterial()] << ", " << (int)voxel1.getColor() << "], voxel2["
|
||||
<< voxel::VoxelTypeStr[(int)voxel2.getMaterial()] << ", " << (int)voxel2.getColor() << "]";
|
||||
if (voxel::isAir(voxel1.getMaterial())) {
|
||||
continue;
|
||||
}
|
||||
if (!includingColor) {
|
||||
continue;
|
||||
}
|
||||
const core::RGBA& c1 = pal1.colors[voxel1.getColor()];
|
||||
const core::RGBA& c2 = pal2.colors[voxel2.getColor()];
|
||||
const float delta = core::Color::getDistance(c1, c2);
|
||||
ASSERT_LT(delta, 1.0f) << "Voxel differs at " << x1 << ":" << y1 << ":" << z1
|
||||
<< " in material - voxel1[" << voxel::VoxelTypeStr[(int)voxel1.getMaterial()]
|
||||
<< ", " << (int)voxel1.getColor() << "], voxel2["
|
||||
<< voxel::VoxelTypeStr[(int)voxel2.getMaterial()] << ", "
|
||||
<< (int)voxel2.getColor() << "], color1[" << core::Color::toHex(c1) << "], color2["
|
||||
<< core::Color::toHex(c2) << "], delta[" << delta << "]";
|
||||
ASSERT_LT(delta, 0.001f) << "Voxel differs at " << x1 << ":" << y1 << ":" << z1
|
||||
<< " in material - voxel1[" << voxel::VoxelTypeStr[(int)voxel1.getMaterial()]
|
||||
<< ", " << (int)voxel1.getColor() << "], voxel2["
|
||||
<< voxel::VoxelTypeStr[(int)voxel2.getMaterial()] << ", "
|
||||
<< (int)voxel2.getColor() << "], color1[" << core::Color::toHex(c1)
|
||||
<< "], color2[" << core::Color::toHex(c2) << "], delta[" << delta << "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,8 +119,7 @@ size_t Format::loadPalette(const core::String &filename, io::SeekableReadStream&
|
|||
|
||||
size_t PaletteFormat::loadPalette(const core::String &filename, io::SeekableReadStream& stream, voxel::Palette &palette) {
|
||||
SceneGraph sceneGraph;
|
||||
loadGroups(filename, stream, sceneGraph);
|
||||
palette = _palette;
|
||||
loadGroupsPalette(filename, stream, sceneGraph, palette);
|
||||
return palette.colorCount;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,13 +84,14 @@ class NoColorFormat : public Format {
|
|||
|
||||
class PaletteFormat : public Format {
|
||||
protected:
|
||||
/**
|
||||
* This is the loaded palette from the input file. This is not the currently in-use palette. This might differ
|
||||
* and the colors will get matched to the in-use palette.
|
||||
*/
|
||||
voxel::Palette _palette;
|
||||
virtual bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph, voxel::Palette &palette) = 0;
|
||||
|
||||
public:
|
||||
size_t loadPalette(const core::String &filename, io::SeekableReadStream& stream, voxel::Palette &palette) override;
|
||||
bool loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) override {
|
||||
voxel::Palette palette;
|
||||
return loadGroupsPalette(filename, stream, sceneGraph, palette);
|
||||
}
|
||||
};
|
||||
|
||||
class RGBAFormat : public Format {
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace voxelformat {
|
|||
return false; \
|
||||
}
|
||||
|
||||
bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) {
|
||||
bool KV6Format::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
uint32_t magic;
|
||||
wrap(stream.readUInt32(magic))
|
||||
if (magic != FourCC('K','v','x','l')) {
|
||||
|
@ -73,8 +73,8 @@ bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
uint32_t palMagic;
|
||||
wrap(stream.readUInt32(palMagic))
|
||||
if (palMagic == FourCC('S','P','a','l')) {
|
||||
_palette.colorCount = voxel::PaletteMaxColors;
|
||||
for (int i = 0; i < _palette.colorCount; ++i) {
|
||||
palette.colorCount = voxel::PaletteMaxColors;
|
||||
for (int i = 0; i < palette.colorCount; ++i) {
|
||||
uint8_t r, g, b;
|
||||
wrap(stream.readUInt8(b))
|
||||
wrap(stream.readUInt8(g))
|
||||
|
@ -85,7 +85,7 @@ bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
const uint8_t nb = glm::clamp((uint32_t)glm::round(((float)b * 255.0f) / 63.0f), 0u, 255u);
|
||||
|
||||
const glm::vec4& color = core::Color::fromRGBA(nr, ng, nb, 255u);
|
||||
_palette.colors[i] = core::Color::getRGBA(color);
|
||||
palette.colors[i] = core::Color::getRGBA(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
} voxtype;
|
||||
|
||||
voxtype voxdata[MAXVOXS];
|
||||
PaletteLookup palLookup(_palette);
|
||||
PaletteLookup palLookup(palette);
|
||||
for (uint32_t c = 0u; c < numvoxs; ++c) {
|
||||
uint8_t palr, palg, palb, pala;
|
||||
wrap(stream.readUInt8(palb))
|
||||
|
|
|
@ -11,8 +11,9 @@ namespace voxelformat {
|
|||
* @brief Voxel sprite format used by the SLAB6 editor, voxlap and Ace of Spades
|
||||
*/
|
||||
class KV6Format : public PaletteFormat {
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace voxelformat {
|
|||
return false; \
|
||||
}
|
||||
|
||||
bool KVXFormat::loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) {
|
||||
bool KVXFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
// Total # of bytes (not including numbytes) in each mip-map level
|
||||
// but there is only 1 mip-map level
|
||||
uint32_t numbytes;
|
||||
|
@ -90,15 +90,15 @@ bool KVXFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
}
|
||||
// Read the color palette from the end of the file and convert to our palette
|
||||
const size_t currentPos = stream.pos();
|
||||
_palette.colorCount = voxel::PaletteMaxColors;
|
||||
stream.seek(stream.size() - 3 * _palette.colorCount);
|
||||
palette.colorCount = voxel::PaletteMaxColors;
|
||||
stream.seek(stream.size() - 3 * palette.colorCount);
|
||||
|
||||
/**
|
||||
* The last 768 bytes of the KVX file is a standard 256-color VGA palette.
|
||||
* The palette is in (Red:0, Green:1, Blue:2) order and intensities range
|
||||
* from 0-63.
|
||||
*/
|
||||
for (int i = 0; i < _palette.colorCount; ++i) {
|
||||
for (int i = 0; i < palette.colorCount; ++i) {
|
||||
uint8_t r, g, b;
|
||||
wrap(stream.readUInt8(r))
|
||||
wrap(stream.readUInt8(g))
|
||||
|
@ -109,7 +109,7 @@ bool KVXFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
const uint8_t nb = glm::clamp((uint32_t)glm::round(((float)b * 255.0f) / 63.0f), 0u, 255u);
|
||||
|
||||
const glm::vec4& color = core::Color::fromRGBA(nr, ng, nb, 255);
|
||||
_palette.colors[i] = core::Color::getRGBA(color);
|
||||
palette.colors[i] = core::Color::getRGBA(color);
|
||||
}
|
||||
stream.seek((int64_t)currentPos);
|
||||
|
||||
|
@ -118,7 +118,7 @@ bool KVXFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
node.setVolume(volume, true);
|
||||
node.setName(filename);
|
||||
node.setTransform(0, transform, true);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
sceneGraph.emplace(core::move(node));
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,8 +46,9 @@ namespace voxelformat {
|
|||
* @endcode
|
||||
*/
|
||||
class KVXFormat : public PaletteFormat {
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace voxelformat {
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
bool MCRFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
|
||||
bool MCRFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
const int64_t length = stream.size();
|
||||
if (length < SECTOR_BYTES) {
|
||||
Log::error("File does not contain enough data");
|
||||
|
@ -54,7 +54,7 @@ bool MCRFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
chunkZ = 0;
|
||||
}
|
||||
|
||||
_palette.minecraft();
|
||||
palette.minecraft();
|
||||
switch (type) {
|
||||
case 'r':
|
||||
case 'a': {
|
||||
|
@ -79,7 +79,7 @@ bool MCRFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
wrap(stream.readUInt32BE(lastModValue));
|
||||
}
|
||||
|
||||
const bool success = loadMinecraftRegion(sceneGraph, stream);
|
||||
const bool success = loadMinecraftRegion(sceneGraph, stream, palette);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ bool MCRFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MCRFormat::loadMinecraftRegion(SceneGraph &sceneGraph, io::SeekableReadStream &stream) {
|
||||
bool MCRFormat::loadMinecraftRegion(SceneGraph &sceneGraph, io::SeekableReadStream &stream, const voxel::Palette &palette) {
|
||||
for (int i = 0; i < SECTOR_INTS; ++i) {
|
||||
if (_offsets[i].sectorCount == 0u || _offsets[i].offset < sizeof(_offsets)) {
|
||||
continue;
|
||||
|
@ -98,7 +98,7 @@ bool MCRFormat::loadMinecraftRegion(SceneGraph &sceneGraph, io::SeekableReadStre
|
|||
if (stream.seek(_offsets[i].offset) == -1) {
|
||||
continue;
|
||||
}
|
||||
if (!readCompressedNBT(sceneGraph, stream, i)) {
|
||||
if (!readCompressedNBT(sceneGraph, stream, i, palette)) {
|
||||
Log::error("Failed to load minecraft chunk section %i for offset %u", i, (int)_offsets[i].offset);
|
||||
return false;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ bool MCRFormat::loadMinecraftRegion(SceneGraph &sceneGraph, io::SeekableReadStre
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MCRFormat::readCompressedNBT(SceneGraph &sceneGraph, io::SeekableReadStream &stream, int sector) {
|
||||
bool MCRFormat::readCompressedNBT(SceneGraph &sceneGraph, io::SeekableReadStream &stream, int sector, const voxel::Palette &palette) {
|
||||
uint32_t nbtSize;
|
||||
wrap(stream.readUInt32BE(nbtSize));
|
||||
if (nbtSize == 0) {
|
||||
|
@ -155,7 +155,7 @@ bool MCRFormat::readCompressedNBT(SceneGraph &sceneGraph, io::SeekableReadStream
|
|||
}
|
||||
SceneGraphNode node(SceneGraphNodeType::Model);
|
||||
node.setVolume(volume, true);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
sceneGraph.emplace(core::move(node));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -98,14 +98,15 @@ private:
|
|||
// old version (< 2844)
|
||||
voxel::RawVolume* parseLevelCompound(int dataVersion, const priv::NamedBinaryTag &root, int sector);
|
||||
|
||||
bool readCompressedNBT(SceneGraph& sceneGraph, io::SeekableReadStream &stream, int sector);
|
||||
bool loadMinecraftRegion(SceneGraph& sceneGraph, io::SeekableReadStream &stream);
|
||||
bool readCompressedNBT(SceneGraph& sceneGraph, io::SeekableReadStream &stream, int sector, const voxel::Palette &palette);
|
||||
bool loadMinecraftRegion(SceneGraph& sceneGraph, io::SeekableReadStream &stream, const voxel::Palette &palette);
|
||||
|
||||
bool saveSections(const voxelformat::SceneGraph &sceneGraph, priv::NBTList §ions, int sector);
|
||||
bool saveCompressedNBT(const voxelformat::SceneGraph &sceneGraph, io::SeekableWriteStream& stream, int sector);
|
||||
bool saveMinecraftRegion(const voxelformat::SceneGraph &sceneGraph, io::SeekableWriteStream& stream);
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -223,11 +223,6 @@ bool QBFormat::loadMatrix(State& state, io::SeekableReadStream& stream, SceneGra
|
|||
}
|
||||
|
||||
voxel::RawVolume* v = new voxel::RawVolume(region);
|
||||
SceneGraphNode node(SceneGraphNodeType::Model);
|
||||
node.setVolume(v, true);
|
||||
node.setName(name);
|
||||
node.setPalette(palLookup.palette());
|
||||
sceneGraph.emplace(core::move(node));
|
||||
if (state._compressed == Compression::None) {
|
||||
Log::debug("qb matrix uncompressed");
|
||||
for (uint32_t z = 0; z < size.z; ++z) {
|
||||
|
@ -238,6 +233,11 @@ bool QBFormat::loadMatrix(State& state, io::SeekableReadStream& stream, SceneGra
|
|||
}
|
||||
}
|
||||
}
|
||||
SceneGraphNode node(SceneGraphNodeType::Model);
|
||||
node.setVolume(v, true);
|
||||
node.setName(name);
|
||||
node.setPalette(palLookup.palette());
|
||||
sceneGraph.emplace(core::move(node));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -275,6 +275,11 @@ bool QBFormat::loadMatrix(State& state, io::SeekableReadStream& stream, SceneGra
|
|||
}
|
||||
++z;
|
||||
}
|
||||
SceneGraphNode node(SceneGraphNodeType::Model);
|
||||
node.setVolume(v, true);
|
||||
node.setName(name);
|
||||
node.setPalette(palLookup.palette());
|
||||
sceneGraph.emplace(core::move(node));
|
||||
Log::debug("Matrix read");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -243,12 +243,12 @@ bool QBTFormat::skipNode(io::SeekableReadStream& stream) {
|
|||
* ChildCount 4 bytes, uint, number of child nodes
|
||||
* Children ChildCount nodes currently of type Matrix or Compound
|
||||
*/
|
||||
bool QBTFormat::loadCompound(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent) {
|
||||
bool QBTFormat::loadCompound(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent, voxel::Palette &palette) {
|
||||
SceneGraphNode node(SceneGraphNodeType::Group);
|
||||
node.setName("Compound");
|
||||
int nodeId = sceneGraph.emplace(core::move(node), parent);
|
||||
|
||||
if (!loadMatrix(stream, sceneGraph, nodeId)) {
|
||||
if (!loadMatrix(stream, sceneGraph, nodeId, palette)) {
|
||||
return false;
|
||||
}
|
||||
uint32_t childCount;
|
||||
|
@ -261,7 +261,7 @@ bool QBTFormat::loadCompound(io::SeekableReadStream& stream, SceneGraph& sceneGr
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!loadNode(stream, sceneGraph, nodeId)) {
|
||||
if (!loadNode(stream, sceneGraph, nodeId, palette)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ bool QBTFormat::loadCompound(io::SeekableReadStream& stream, SceneGraph& sceneGr
|
|||
* The M byte is used to store visibility of the 6 faces of a voxel and whether as voxel is solid or air. If M is bigger than 0 then the voxel is solid. Even when a voxel
|
||||
* is solid is may not be needed to be rendered because it is a core voxel that is surrounded by 6 other voxels and thus invisible. If M = 1 then the voxel is a core voxel.
|
||||
*/
|
||||
bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent) {
|
||||
bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent, voxel::Palette &palette) {
|
||||
char name[1024];
|
||||
uint32_t nameLength;
|
||||
wrap(stream.readUInt32(nameLength));
|
||||
|
@ -349,7 +349,7 @@ bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGrap
|
|||
Log::error("Invalid region");
|
||||
return false;
|
||||
}
|
||||
PaletteLookup palLookup(_palette);
|
||||
PaletteLookup palLookup(palette);
|
||||
voxel::RawVolume* volume = new voxel::RawVolume(region);
|
||||
for (int32_t x = 0; x < (int)size.x; x++) {
|
||||
for (int32_t z = 0; z < (int)size.z; z++) {
|
||||
|
@ -365,7 +365,7 @@ bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGrap
|
|||
if (mask == 0u) {
|
||||
continue;
|
||||
}
|
||||
if (_palette.colorCount > 0) {
|
||||
if (palette.colorCount > 0) {
|
||||
const voxel::Voxel& voxel = voxel::createVoxel(voxel::VoxelType::Generic, red);
|
||||
volume->setVoxel(position.x + x, position.y + y, position.z + z, voxel);
|
||||
} else {
|
||||
|
@ -395,7 +395,7 @@ bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGrap
|
|||
* ChildCount 4 bytes, uint, number of child nodes
|
||||
* Children ChildCount nodes currently of type Matrix or Compound
|
||||
*/
|
||||
bool QBTFormat::loadModel(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent) {
|
||||
bool QBTFormat::loadModel(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent, voxel::Palette &palette) {
|
||||
uint32_t childCount;
|
||||
wrap(stream.readUInt32(childCount));
|
||||
if (childCount > 2048u) {
|
||||
|
@ -407,14 +407,14 @@ bool QBTFormat::loadModel(io::SeekableReadStream& stream, SceneGraph& sceneGraph
|
|||
node.setName("Model");
|
||||
int nodeId = sceneGraph.emplace(core::move(node), parent);
|
||||
for (uint32_t i = 0; i < childCount; i++) {
|
||||
if (!loadNode(stream, sceneGraph, nodeId)) {
|
||||
if (!loadNode(stream, sceneGraph, nodeId, palette)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QBTFormat::loadNode(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent) {
|
||||
bool QBTFormat::loadNode(io::SeekableReadStream& stream, SceneGraph& sceneGraph, int parent, voxel::Palette &palette) {
|
||||
uint32_t nodeTypeID;
|
||||
wrap(stream.readUInt32(nodeTypeID));
|
||||
uint32_t dataSize;
|
||||
|
@ -424,7 +424,7 @@ bool QBTFormat::loadNode(io::SeekableReadStream& stream, SceneGraph& sceneGraph,
|
|||
switch (nodeTypeID) {
|
||||
case qbt::NODE_TYPE_MATRIX: {
|
||||
Log::debug("Found matrix");
|
||||
if (!loadMatrix(stream, sceneGraph, parent)) {
|
||||
if (!loadMatrix(stream, sceneGraph, parent, palette)) {
|
||||
Log::error("Failed to load matrix");
|
||||
return false;
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ bool QBTFormat::loadNode(io::SeekableReadStream& stream, SceneGraph& sceneGraph,
|
|||
}
|
||||
case qbt::NODE_TYPE_MODEL:
|
||||
Log::debug("Found model");
|
||||
if (!loadModel(stream, sceneGraph, parent)) {
|
||||
if (!loadModel(stream, sceneGraph, parent, palette)) {
|
||||
Log::error("Failed to load model");
|
||||
return false;
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ bool QBTFormat::loadNode(io::SeekableReadStream& stream, SceneGraph& sceneGraph,
|
|||
break;
|
||||
case qbt::NODE_TYPE_COMPOUND:
|
||||
Log::debug("Found compound");
|
||||
if (!loadCompound(stream, sceneGraph, parent)) {
|
||||
if (!loadCompound(stream, sceneGraph, parent, palette)) {
|
||||
Log::error("Failed to load compound");
|
||||
return false;
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ bool QBTFormat::loadNode(io::SeekableReadStream& stream, SceneGraph& sceneGraph,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool QBTFormat::loadColorMap(io::SeekableReadStream& stream) {
|
||||
bool QBTFormat::loadColorMap(io::SeekableReadStream& stream, voxel::Palette &palette) {
|
||||
uint32_t colorCount;
|
||||
wrap(stream.readUInt32(colorCount));
|
||||
Log::debug("Load color map with %u colors", colorCount);
|
||||
|
@ -464,7 +464,7 @@ bool QBTFormat::loadColorMap(io::SeekableReadStream& stream) {
|
|||
Log::error("Sanity check for max colors failed (%u)", colorCount);
|
||||
return false;
|
||||
}
|
||||
_palette.colorCount = (int)colorCount;
|
||||
palette.colorCount = (int)colorCount;
|
||||
for (uint32_t i = 0; i < colorCount; ++i) {
|
||||
uint8_t colorByteR;
|
||||
uint8_t colorByteG;
|
||||
|
@ -481,12 +481,12 @@ bool QBTFormat::loadColorMap(io::SeekableReadStream& stream) {
|
|||
const uint32_t alpha = ((uint32_t)255) << 0;
|
||||
|
||||
const glm::vec4& color = core::Color::fromRGBA(red | green | blue | alpha);
|
||||
_palette.colors[i] = core::Color::getRGBA(color);
|
||||
palette.colors[i] = core::Color::getRGBA(color);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QBTFormat::loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) {
|
||||
bool QBTFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
uint32_t header;
|
||||
wrap(stream.readUInt32(header))
|
||||
constexpr uint32_t headerMagic = FourCC('Q','B',' ','2');
|
||||
|
@ -528,11 +528,11 @@ bool QBTFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
* ColorCount 4 bytes, uint, if this value is 0 then no color map is used
|
||||
* Colors ColorCount * 4 bytes, rgba
|
||||
*/
|
||||
if (!loadColorMap(stream)) {
|
||||
if (!loadColorMap(stream, palette)) {
|
||||
Log::error("Failed to load color map");
|
||||
return false;
|
||||
}
|
||||
if (_palette.colorCount == 0) {
|
||||
if (palette.colorCount == 0) {
|
||||
Log::debug("No color map found");
|
||||
} else {
|
||||
Log::debug("Color map loaded");
|
||||
|
@ -543,7 +543,7 @@ bool QBTFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
* SectionCaption 8 bytes = "DATATREE"
|
||||
* RootNode, can currently either be Model, Compound or Matrix
|
||||
*/
|
||||
if (!loadNode(stream, sceneGraph, sceneGraph.root().id())) {
|
||||
if (!loadNode(stream, sceneGraph, sceneGraph.root().id(), palette)) {
|
||||
Log::error("Failed to load node");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -20,17 +20,17 @@ namespace voxelformat {
|
|||
class QBTFormat : public PaletteFormat {
|
||||
private:
|
||||
bool skipNode(io::SeekableReadStream& stream);
|
||||
bool loadMatrix(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent);
|
||||
bool loadCompound(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent);
|
||||
bool loadModel(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent);
|
||||
bool loadNode(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent);
|
||||
bool loadMatrix(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent, voxel::Palette &palette);
|
||||
bool loadCompound(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent, voxel::Palette &palette);
|
||||
bool loadModel(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent, voxel::Palette &palette);
|
||||
bool loadNode(io::SeekableReadStream& stream, SceneGraph &sceneGraph, int parent, voxel::Palette &palette);
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
|
||||
bool loadColorMap(io::SeekableReadStream& stream);
|
||||
bool loadColorMap(io::SeekableReadStream& stream, voxel::Palette &palette);
|
||||
bool saveMatrix(io::SeekableWriteStream& stream, const SceneGraphNode& node, bool colorMap) const;
|
||||
bool saveColorMap(io::SeekableWriteStream& stream, const voxel::Palette& palette) const;
|
||||
bool saveModel(io::SeekableWriteStream& stream, const SceneGraph &sceneGraph, bool colorMap) const;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace voxelformat {
|
|||
return false; \
|
||||
}
|
||||
|
||||
bool QEFFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
|
||||
bool QEFFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
char buf[64];
|
||||
|
||||
wrapBool(stream.readLine(sizeof(buf), buf))
|
||||
|
@ -80,7 +80,7 @@ bool QEFFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
return false;
|
||||
}
|
||||
|
||||
_palette.colorCount = paletteSize;
|
||||
palette.colorCount = paletteSize;
|
||||
|
||||
for (int i = 0; i < paletteSize; ++i) {
|
||||
float r, g, b;
|
||||
|
@ -90,13 +90,13 @@ bool QEFFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
return false;
|
||||
}
|
||||
const glm::vec4 color(r, g, b, 1.0f);
|
||||
_palette.colors[i] = core::Color::getRGBA(color);
|
||||
palette.colors[i] = core::Color::getRGBA(color);
|
||||
}
|
||||
voxel::RawVolume* volume = new voxel::RawVolume(region);
|
||||
SceneGraphNode node;
|
||||
node.setVolume(volume, true);
|
||||
node.setName(filename);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
sceneGraph.emplace(core::move(node));
|
||||
|
||||
while (stream.remaining() > 0) {
|
||||
|
|
|
@ -20,8 +20,9 @@ namespace voxelformat {
|
|||
* https://getqubicle.com/qubicle/documentation/docs/file/qef/
|
||||
*/
|
||||
class QEFFormat : public PaletteFormat {
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
|
||||
namespace voxelformat {
|
||||
|
||||
bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
|
||||
_palette.minecraft();
|
||||
bool SchematicFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
palette.minecraft();
|
||||
io::ZipReadStream zipStream(stream);
|
||||
priv::NamedBinaryTagContext ctx;
|
||||
ctx.stream = &zipStream;
|
||||
|
@ -82,7 +82,7 @@ bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadS
|
|||
}
|
||||
}
|
||||
|
||||
PaletteLookup palLookup(_palette);
|
||||
PaletteLookup palLookup(palette);
|
||||
for (int x = 0; x < width; ++x) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int z = 0; z < depth; ++z) {
|
||||
|
@ -108,7 +108,7 @@ bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadS
|
|||
|
||||
SceneGraphNode node(SceneGraphNodeType::Model);
|
||||
node.setVolume(volume, true);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palLookup.palette());
|
||||
sceneGraph.emplace(core::move(node));
|
||||
return true;
|
||||
}
|
||||
|
@ -126,8 +126,6 @@ bool SchematicFormat::saveGroups(const SceneGraph& sceneGraph, const core::Strin
|
|||
|
||||
io::ZipWriteStream zipStream(stream);
|
||||
|
||||
_palette.minecraft();
|
||||
|
||||
priv::NBTCompound compound;
|
||||
compound.put("Width", (int16_t)size.x);
|
||||
compound.put("Height", (int16_t)size.y);
|
||||
|
|
|
@ -21,8 +21,9 @@ class NamedBinaryTag;
|
|||
* @note https://minecraft.fandom.com/wiki/Schematic_file_format
|
||||
*/
|
||||
class SchematicFormat : public PaletteFormat {
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ bool VXLFormat::saveGroups(const SceneGraph& sceneGraph, const core::String &fil
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VXLFormat::readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t limbIdx, SceneGraph& sceneGraph) const {
|
||||
bool VXLFormat::readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t limbIdx, SceneGraph& sceneGraph, voxel::Palette &palette) const {
|
||||
const vxl_limb_tailer &footer = mdl.limb_tailers[limbIdx];
|
||||
const vxl_limb_header &header = mdl.limb_headers[limbIdx];
|
||||
|
||||
|
@ -209,7 +209,7 @@ bool VXLFormat::readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t
|
|||
SceneGraphNode node;
|
||||
node.setVolume(volume, true);
|
||||
node.setName(header.limb_name);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
sceneGraph.emplace(core::move(node));
|
||||
++mdl.volumeIdx;
|
||||
|
||||
|
@ -277,11 +277,11 @@ bool VXLFormat::readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VXLFormat::readLimbs(io::SeekableReadStream& stream, vxl_mdl& mdl, SceneGraph& sceneGraph) const {
|
||||
bool VXLFormat::readLimbs(io::SeekableReadStream& stream, vxl_mdl& mdl, SceneGraph& sceneGraph, voxel::Palette &palette) const {
|
||||
const vxl_header& hdr = mdl.header;
|
||||
sceneGraph.reserve(hdr.n_limbs);
|
||||
for (uint32_t i = 0; i < hdr.n_limbs; ++i) {
|
||||
wrapBool(readLimb(stream, mdl, i, sceneGraph))
|
||||
wrapBool(readLimb(stream, mdl, i, sceneGraph, palette))
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ bool VXLFormat::readLimbFooters(io::SeekableReadStream& stream, vxl_mdl& mdl) co
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VXLFormat::readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl) {
|
||||
bool VXLFormat::readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl, voxel::Palette &palette) {
|
||||
vxl_header& hdr = mdl.header;
|
||||
wrapBool(stream.readString(sizeof(hdr.filetype), hdr.filetype))
|
||||
if (SDL_strcmp(hdr.filetype, "Voxel Animation") != 0) {
|
||||
|
@ -358,9 +358,9 @@ bool VXLFormat::readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl) {
|
|||
|
||||
Log::debug("Found %u limbs", hdr.n_limbs);
|
||||
|
||||
_palette.colorCount = voxel::PaletteMaxColors;
|
||||
palette.colorCount = voxel::PaletteMaxColors;
|
||||
bool valid = false;
|
||||
for (int i = 0; i < _palette.colorCount; ++i) {
|
||||
for (int i = 0; i < palette.colorCount; ++i) {
|
||||
wrap(stream.readUInt8(hdr.palette[i][0]))
|
||||
wrap(stream.readUInt8(hdr.palette[i][1]))
|
||||
wrap(stream.readUInt8(hdr.palette[i][2]))
|
||||
|
@ -370,12 +370,12 @@ bool VXLFormat::readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl) {
|
|||
}
|
||||
|
||||
if (valid) {
|
||||
for (int i = 0; i < _palette.colorCount; ++i) {
|
||||
for (int i = 0; i < palette.colorCount; ++i) {
|
||||
const uint8_t *p = hdr.palette[i];
|
||||
_palette.colors[i] = core::Color::getRGBA(p[0], p[1], p[2]);
|
||||
palette.colors[i] = core::Color::getRGBA(p[0], p[1], p[2]);
|
||||
}
|
||||
} else {
|
||||
_palette.colorCount = 0;
|
||||
palette.colorCount = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -390,15 +390,15 @@ bool VXLFormat::prepareModel(vxl_mdl& mdl) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VXLFormat::loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) {
|
||||
bool VXLFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph, voxel::Palette &palette) {
|
||||
vxl_mdl mdl;
|
||||
wrapBool(readHeader(stream, mdl))
|
||||
wrapBool(readHeader(stream, mdl, palette))
|
||||
wrapBool(prepareModel(mdl))
|
||||
|
||||
wrapBool(readLimbHeaders(stream, mdl))
|
||||
wrapBool(readLimbFooters(stream, mdl))
|
||||
|
||||
wrapBool(readLimbs(stream, mdl, sceneGraph))
|
||||
wrapBool(readLimbs(stream, mdl, sceneGraph, palette))
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -80,14 +80,15 @@ private:
|
|||
// reading
|
||||
bool readLimbHeader(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t limbIdx) const;
|
||||
bool readLimbFooter(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t limbIdx) const;
|
||||
bool readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t limbIdx, SceneGraph& sceneGraph) const;
|
||||
bool readLimbs(io::SeekableReadStream& stream, vxl_mdl& mdl, SceneGraph& sceneGraph) const;
|
||||
bool readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t limbIdx, SceneGraph& sceneGraph, voxel::Palette &palette) const;
|
||||
bool readLimbs(io::SeekableReadStream& stream, vxl_mdl& mdl, SceneGraph& sceneGraph, voxel::Palette &palette) const;
|
||||
bool readLimbFooters(io::SeekableReadStream& stream, vxl_mdl& mdl) const;
|
||||
bool readLimbHeaders(io::SeekableReadStream& stream, vxl_mdl& mdl) const;
|
||||
bool prepareModel(vxl_mdl& mdl) const;
|
||||
bool readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl);
|
||||
bool readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl, voxel::Palette &palette);
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ bool VXMFormat::saveGroups(const SceneGraph& sceneGraph, const core::String &fil
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VXMFormat::loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) {
|
||||
bool VXMFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph, voxel::Palette &palette) {
|
||||
uint8_t magic[4];
|
||||
wrap(stream.readUInt8(magic[0]))
|
||||
wrap(stream.readUInt8(magic[1]))
|
||||
|
@ -412,12 +412,12 @@ bool VXMFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
wrap(stream.readUInt8(alpha));
|
||||
uint8_t emissive;
|
||||
wrap(stream.readUInt8(emissive));
|
||||
_palette.colors[i] = core::Color::getRGBA(red, green, blue, alpha);
|
||||
palette.colors[i] = core::Color::getRGBA(red, green, blue, alpha);
|
||||
if (emissive) {
|
||||
_palette.glowColors[i] = _palette.colors[i];
|
||||
palette.glowColors[i] = palette.colors[i];
|
||||
}
|
||||
}
|
||||
_palette.colorCount = materialAmount;
|
||||
palette.colorCount = materialAmount;
|
||||
|
||||
const voxel::Region region(glm::ivec3(0), glm::ivec3(size) - 1);
|
||||
|
||||
|
@ -471,7 +471,7 @@ bool VXMFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
|
|||
node.setVolume(volume, true);
|
||||
node.setName(layerName);
|
||||
node.setVisible(visible);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
node.setProperty("version", core::string::toString(version));
|
||||
node.setProperty("filename", filename);
|
||||
node.setTransform(0, transform, true);
|
||||
|
|
|
@ -17,9 +17,9 @@ namespace voxelformat {
|
|||
class VXMFormat : public PaletteFormat {
|
||||
private:
|
||||
bool writeRLE(io::WriteStream &stream, int rleCount, voxel::Voxel &voxel, uint8_t emptyColorReplacement) const;
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
public:
|
||||
image::ImagePtr loadScreenshot(const core::String &filename, io::SeekableReadStream& stream) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -520,7 +520,7 @@ void VXRFormat::recursiveTransformVolume(const SceneGraph &sceneGraph, SceneGrap
|
|||
}
|
||||
}
|
||||
|
||||
bool VXRFormat::loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) {
|
||||
bool VXRFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph, voxel::Palette &) {
|
||||
uint8_t magic[4];
|
||||
wrap(stream.readUInt8(magic[0]))
|
||||
wrap(stream.readUInt8(magic[1]))
|
||||
|
|
|
@ -31,9 +31,9 @@ private:
|
|||
bool saveNodeProperties(const SceneGraphNode* node, io::SeekableWriteStream& stream);
|
||||
bool saveVXA(const SceneGraph& sceneGraph, const core::String &filename, io::SeekableWriteStream& stream, const core::String &animation);
|
||||
bool loadVXA(SceneGraph& sceneGraph, const core::String& vxaPath);
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
public:
|
||||
image::ImagePtr loadScreenshot(const core::String &filename, io::SeekableReadStream& stream) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace voxelformat {
|
|||
return false; \
|
||||
}
|
||||
|
||||
bool VXTFormat::loadGroups(const core::String &filename, io::SeekableReadStream &in, SceneGraph &sceneGraph) {
|
||||
bool VXTFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream &in, SceneGraph &sceneGraph, voxel::Palette &) {
|
||||
io::ZipReadStream stream(in, (int)in.size());
|
||||
uint8_t magic[4];
|
||||
wrap(stream.readUInt8(magic[0]))
|
||||
|
|
|
@ -12,8 +12,9 @@ namespace voxelformat {
|
|||
* @brief VXT files are tilesets of (static) vxm models
|
||||
*/
|
||||
class VXTFormat : public PaletteFormat {
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ static bool loadKeyFrames(voxelformat::SceneGraphNode& node, const ogt_vox_keyfr
|
|||
return node.setKeyFrames(kf);
|
||||
}
|
||||
|
||||
bool VoxFormat::addInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, bool groupHidden) {
|
||||
bool VoxFormat::addInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, const voxel::Palette &palette, bool groupHidden) {
|
||||
const ogt_vox_instance& ogtInstance = scene->instances[ogt_instanceIdx];
|
||||
const ogt_vox_transform& ogtTransform = ogtInstance.transform;
|
||||
const glm::vec4 ogtCol0(ogtTransform.m00, ogtTransform.m01, ogtTransform.m02, ogtTransform.m03);
|
||||
|
@ -159,11 +159,11 @@ bool VoxFormat::addInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx
|
|||
node.setName(name);
|
||||
node.setVisible(!ogtInstance.hidden && !groupHidden);
|
||||
node.setVolume(v, true);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
return sceneGraph.emplace(core::move(node), parent) != -1;
|
||||
}
|
||||
|
||||
bool VoxFormat::addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, core::Set<uint32_t> &addedInstances) {
|
||||
bool VoxFormat::addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, core::Set<uint32_t> &addedInstances, const voxel::Palette &palette) {
|
||||
const ogt_vox_group &ogt_group = scene->groups[ogt_parentGroupIdx];
|
||||
bool hidden = ogt_group.hidden;
|
||||
const char *name = "Group";
|
||||
|
@ -193,7 +193,7 @@ bool VoxFormat::addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx
|
|||
if (!addedInstances.insert(n)) {
|
||||
continue;
|
||||
}
|
||||
if (!addInstance(scene, n, sceneGraph, groupId, zUpMat, hidden)) {
|
||||
if (!addInstance(scene, n, sceneGraph, groupId, zUpMat, palette, hidden)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ bool VoxFormat::addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx
|
|||
continue;
|
||||
}
|
||||
Log::debug("Found matching group (%u) with scene graph parent: %i", groupIdx, groupId);
|
||||
if (!addGroup(scene, groupIdx, sceneGraph, groupId, zUpMat, addedInstances)) {
|
||||
if (!addGroup(scene, groupIdx, sceneGraph, groupId, zUpMat, addedInstances, palette)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ bool VoxFormat::addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx
|
|||
return groupId;
|
||||
}
|
||||
|
||||
bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
|
||||
bool VoxFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
const size_t size = stream.size();
|
||||
uint8_t *buffer = (uint8_t *)core_malloc(size);
|
||||
if (stream.read(buffer, size) == -1) {
|
||||
|
@ -228,13 +228,13 @@ bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
return false;
|
||||
}
|
||||
|
||||
_palette.colorCount = lengthof(scene->palette.color);
|
||||
for (int i = 0; i < _palette.colorCount; ++i) {
|
||||
palette.colorCount = lengthof(scene->palette.color);
|
||||
for (int i = 0; i < palette.colorCount; ++i) {
|
||||
const ogt_vox_rgba color = scene->palette.color[i];
|
||||
_palette.colors[i] = core::Color::getRGBA(color.r, color.g, color.b, color.a);
|
||||
palette.colors[i] = core::Color::getRGBA(color.r, color.g, color.b, color.a);
|
||||
const ogt_vox_matl &matl = scene->materials.matl[i];
|
||||
if (matl.type == ogt_matl_type_emit) {
|
||||
_palette.glowColors[i] = _palette.colors[i];
|
||||
palette.glowColors[i] = palette.colors[i];
|
||||
}
|
||||
}
|
||||
// rotation matrix to convert into our coordinate system (z pointing upwards)
|
||||
|
@ -250,7 +250,7 @@ bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
continue;
|
||||
}
|
||||
Log::debug("Add root group %u/%u", i, scene->num_groups);
|
||||
if (!addGroup(scene, i, sceneGraph, sceneGraph.root().id(), zUpMat, addedInstances)) {
|
||||
if (!addGroup(scene, i, sceneGraph, sceneGraph.root().id(), zUpMat, addedInstances, palette)) {
|
||||
ogt_vox_destroy_scene(scene);
|
||||
return false;
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream
|
|||
if (addedInstances.has(n)) {
|
||||
continue;
|
||||
}
|
||||
if (!addInstance(scene, n, sceneGraph, sceneGraph.root().id(), zUpMat)) {
|
||||
if (!addInstance(scene, n, sceneGraph, sceneGraph.root().id(), zUpMat, palette)) {
|
||||
ogt_vox_destroy_scene(scene);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@ namespace voxelformat {
|
|||
class VoxFormat : public PaletteFormat {
|
||||
private:
|
||||
int findClosestPaletteIndex(const voxel::Palette &palette);
|
||||
bool addInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, bool groupHidden = false);
|
||||
bool addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, core::Set<uint32_t> &addedInstances);
|
||||
bool addInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, const voxel::Palette &palette, bool groupHidden = false);
|
||||
bool addGroup(const ogt_vox_scene *scene, uint32_t ogt_parentGroupIdx, SceneGraph &sceneGraph, int parent, const glm::mat4 &zUpMat, core::Set<uint32_t> &addedInstances, const voxel::Palette &palette);
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
public:
|
||||
VoxFormat();
|
||||
size_t loadPalette(const core::String &filename, io::SeekableReadStream& stream, voxel::Palette &palette) override;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace voxelformat {
|
||||
|
||||
bool VoxOldFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
|
||||
bool VoxOldFormat::loadGroupsPalette(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph, voxel::Palette &palette) {
|
||||
uint32_t depth, height, width;
|
||||
wrap(stream.readUInt32(depth))
|
||||
wrap(stream.readUInt32(height))
|
||||
|
@ -41,14 +41,14 @@ bool VoxOldFormat::loadGroups(const core::String &filename, io::SeekableReadStre
|
|||
|
||||
const int64_t voxelPos = stream.pos();
|
||||
stream.skip((int64_t)width * height * depth);
|
||||
_palette.colorCount = voxel::PaletteMaxColors;
|
||||
for (int i = 0; i < _palette.colorCount; ++i) {
|
||||
palette.colorCount = voxel::PaletteMaxColors;
|
||||
for (int i = 0; i < palette.colorCount; ++i) {
|
||||
uint8_t r, g, b;
|
||||
wrap(stream.readUInt8(r))
|
||||
wrap(stream.readUInt8(g))
|
||||
wrap(stream.readUInt8(b))
|
||||
|
||||
_palette.colors[i] = core::Color::getRGBA(r, g, b);
|
||||
palette.colors[i] = core::Color::getRGBA(r, g, b);
|
||||
}
|
||||
|
||||
stream.seek(voxelPos);
|
||||
|
@ -69,7 +69,7 @@ bool VoxOldFormat::loadGroups(const core::String &filename, io::SeekableReadStre
|
|||
SceneGraphNode node;
|
||||
node.setVolume(volume, true);
|
||||
node.setName(filename);
|
||||
node.setPalette(_palette);
|
||||
node.setPalette(palette);
|
||||
sceneGraph.emplace(core::move(node));
|
||||
|
||||
return true;
|
||||
|
|
|
@ -12,8 +12,9 @@ namespace voxelformat {
|
|||
* @brief Old magicavoxel vox file format
|
||||
*/
|
||||
class VoxOldFormat : public PaletteFormat {
|
||||
protected:
|
||||
bool loadGroupsPalette(const core::String &filename, io::SeekableReadStream& stream, SceneGraph &sceneGraph, voxel::Palette &palette) override;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,13 @@ void AbstractVoxFormatTest::canLoad(const core::String &filename, size_t expecte
|
|||
ASSERT_EQ(expectedVolumes, sceneGraph.size());
|
||||
}
|
||||
|
||||
void AbstractVoxFormatTest::checkColor(core::RGBA c1, const voxel::Palette &palette, uint8_t index) {
|
||||
const core::RGBA c2 = palette.colors[index];
|
||||
const float delta = core::Color::getDistance(c1, c2);
|
||||
ASSERT_LT(delta, 0.001f) << "color1[" << core::Color::toHex(c1) << "], color2[" << core::Color::toHex(c2)
|
||||
<< "], delta[" << delta << "]";
|
||||
}
|
||||
|
||||
void AbstractVoxFormatTest::testRGB(const core::String &filename) {
|
||||
voxelformat::SceneGraph sceneGraph;
|
||||
const io::FilePtr& file = open(filename);
|
||||
|
@ -105,6 +112,10 @@ void AbstractVoxFormatTest::testRGB(const core::String &filename) {
|
|||
ASSERT_TRUE(voxelformat::loadFormat(filename, stream, sceneGraph));
|
||||
EXPECT_EQ(1u, sceneGraph.size());
|
||||
|
||||
const core::RGBA red = core::Color::getRGBA(core::Color::Red);
|
||||
const core::RGBA green = core::Color::getRGBA(core::Color::Green);
|
||||
const core::RGBA blue = core::Color::getRGBA(core::Color::Blue);
|
||||
|
||||
for (const voxelformat::SceneGraphNode &node : sceneGraph) {
|
||||
const voxel::RawVolume *volume = node.volume();
|
||||
EXPECT_EQ(voxel::VoxelType::Generic, volume->voxel( 0, 0, 0).getMaterial());
|
||||
|
@ -121,19 +132,9 @@ void AbstractVoxFormatTest::testRGB(const core::String &filename) {
|
|||
EXPECT_EQ(voxel::VoxelType::Generic, volume->voxel( 9, 0, 12).getMaterial());
|
||||
EXPECT_EQ(voxel::VoxelType::Generic, volume->voxel( 9, 0, 19).getMaterial());
|
||||
|
||||
EXPECT_EQ(245, volume->voxel( 0, 0, 0).getColor()) << "Expected to get the palette index 245";
|
||||
EXPECT_EQ(245, volume->voxel(31, 0, 0).getColor()) << "Expected to get the palette index 245";
|
||||
EXPECT_EQ(245, volume->voxel(31, 0, 31).getColor()) << "Expected to get the palette index 245";
|
||||
EXPECT_EQ(245, volume->voxel( 0, 0, 31).getColor()) << "Expected to get the palette index 245";
|
||||
|
||||
EXPECT_EQ( 1, volume->voxel( 0, 31, 0).getColor()) << "Expected to get the palette index 1";
|
||||
EXPECT_EQ( 1, volume->voxel(31, 31, 0).getColor()) << "Expected to get the palette index 1";
|
||||
EXPECT_EQ( 1, volume->voxel(31, 31, 31).getColor()) << "Expected to get the palette index 1";
|
||||
EXPECT_EQ( 1, volume->voxel( 0, 31, 31).getColor()) << "Expected to get the palette index 1";
|
||||
|
||||
EXPECT_EQ( 37, volume->voxel( 9, 0, 4).getColor()) << "Expected to get the palette index for red"; // red
|
||||
EXPECT_EQ(149, volume->voxel( 9, 0, 12).getColor()) << "Expected to get the palette index for green"; // green
|
||||
EXPECT_EQ(197, volume->voxel( 9, 0, 19).getColor()) << "Expected to get the palette index for blue"; // blue
|
||||
checkColor(red, node.palette(), volume->voxel( 9, 0, 4).getColor());
|
||||
checkColor(green, node.palette(), volume->voxel( 9, 0, 12).getColor());
|
||||
checkColor(blue, node.palette(), volume->voxel( 9, 0, 19).getColor());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "core/StringUtil.h"
|
||||
#include "io/FileStream.h"
|
||||
#include "voxel/Palette.h"
|
||||
#include "voxel/RawVolume.h"
|
||||
#include "voxel/tests/AbstractVoxelTest.h"
|
||||
#include "voxelformat/Format.h"
|
||||
|
@ -20,6 +21,8 @@ class AbstractVoxFormatTest: public voxel::AbstractVoxelTest {
|
|||
protected:
|
||||
static const voxel::Voxel Empty;
|
||||
|
||||
void checkColor(core::RGBA, const voxel::Palette &palette, uint8_t index);
|
||||
|
||||
void dump(const core::String& srcFilename, const SceneGraph &sceneGraph);
|
||||
void dump(const core::String& structName, voxel::RawVolume* v, const core::String& filename);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ class CSMFormatTest: public AbstractVoxFormatTest {
|
|||
};
|
||||
|
||||
TEST_F(CSMFormatTest, testLoad) {
|
||||
canLoad("chronovox-studio.csm");
|
||||
canLoad("chronovox-studio.csm", 11);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class QBCLFormatTest: public AbstractVoxFormatTest {
|
|||
};
|
||||
|
||||
TEST_F(QBCLFormatTest, testLoad) {
|
||||
canLoad("qubicle.qbcl");
|
||||
canLoad("qubicle.qbcl", 30);
|
||||
}
|
||||
|
||||
TEST_F(QBCLFormatTest, testSaveSmallVoxel) {
|
||||
|
|
|
@ -12,7 +12,7 @@ class QBFormatTest: public AbstractVoxFormatTest {
|
|||
};
|
||||
|
||||
TEST_F(QBFormatTest, testLoad) {
|
||||
canLoad("qubicle.qb");
|
||||
canLoad("qubicle.qb", 10);
|
||||
}
|
||||
|
||||
TEST_F(QBFormatTest, testLoadRGB) {
|
||||
|
|
|
@ -13,7 +13,7 @@ class QBTFormatTest: public AbstractVoxFormatTest {
|
|||
};
|
||||
|
||||
TEST_F(QBTFormatTest, testLoad) {
|
||||
canLoad("qubicle.qbt");
|
||||
canLoad("qubicle.qbt", 17);
|
||||
}
|
||||
|
||||
TEST_F(QBTFormatTest, testSaveSingleVoxel) {
|
||||
|
|
Loading…
Reference in New Issue