VOXELFORMAT: fixed some palette related issues

master
Martin Gerhardy 2022-05-20 19:27:23 +02:00
parent 0a45bbb41e
commit 464098270f
34 changed files with 161 additions and 143 deletions

View File

@ -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 << "]";
}
}
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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))

View File

@ -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;
};

View File

@ -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));
/**

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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 &sections, 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;
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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) {

View File

@ -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;
};

View File

@ -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);

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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);

View File

@ -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;
};

View File

@ -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]))

View File

@ -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;
};

View File

@ -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]))

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -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);

View File

@ -11,7 +11,7 @@ class CSMFormatTest: public AbstractVoxFormatTest {
};
TEST_F(CSMFormatTest, testLoad) {
canLoad("chronovox-studio.csm");
canLoad("chronovox-studio.csm", 11);
}
}

View File

@ -13,7 +13,7 @@ class QBCLFormatTest: public AbstractVoxFormatTest {
};
TEST_F(QBCLFormatTest, testLoad) {
canLoad("qubicle.qbcl");
canLoad("qubicle.qbcl", 30);
}
TEST_F(QBCLFormatTest, testSaveSmallVoxel) {

View File

@ -12,7 +12,7 @@ class QBFormatTest: public AbstractVoxFormatTest {
};
TEST_F(QBFormatTest, testLoad) {
canLoad("qubicle.qb");
canLoad("qubicle.qb", 10);
}
TEST_F(QBFormatTest, testLoadRGB) {

View File

@ -13,7 +13,7 @@ class QBTFormatTest: public AbstractVoxFormatTest {
};
TEST_F(QBTFormatTest, testLoad) {
canLoad("qubicle.qbt");
canLoad("qubicle.qbt", 17);
}
TEST_F(QBTFormatTest, testSaveSingleVoxel) {