VOXEL: more work on putting one palette into each node

master
Martin Gerhardy 2022-05-19 19:43:25 +02:00
parent d447100a23
commit 7beda6d3fc
37 changed files with 132 additions and 172 deletions

View File

@ -38,26 +38,28 @@ bool AnimationRenderer::init() {
return false;
}
const voxel::Palette &palette = voxel::getPalette();
core::DynamicArray<glm::vec4> materialColors;
palette.toVec4f(materialColors);
core::DynamicArray<glm::vec4> glowColors;
palette.glowToVec4f(glowColors);
const int shaderMaterialColorsArraySize = lengthof(shader::SkeletonData::MaterialblockData::materialcolor);
const int materialColorsArraySize = palette.colorCount;
const int materialColorsArraySize = voxel::PaletteMaxColors;
if (shaderMaterialColorsArraySize != materialColorsArraySize) {
Log::error("Shader parameters and material colors don't match in their size: %i - %i",
shaderMaterialColorsArraySize, materialColorsArraySize);
return false;
}
shader::SkeletonData::MaterialblockData materialBlock;
core_memcpy(materialBlock.materialcolor, &materialColors.front(), sizeof(materialBlock.materialcolor));
core_memcpy(materialBlock.glowcolor, &glowColors.front(), sizeof(materialBlock.glowcolor));
if (!_shaderData.create(materialBlock)) {
Log::error("Failed to create material buffer");
return false;
{
const voxel::Palette &palette = voxel::getPalette();
core::DynamicArray<glm::vec4> materialColors;
palette.toVec4f(materialColors);
core::DynamicArray<glm::vec4> glowColors;
palette.glowToVec4f(glowColors);
shader::SkeletonData::MaterialblockData materialBlock;
core_memcpy(materialBlock.materialcolor, &materialColors.front(), sizeof(materialBlock.materialcolor));
core_memcpy(materialBlock.glowcolor, &glowColors.front(), sizeof(materialBlock.glowcolor));
if (!_shaderData.create(materialBlock)) {
Log::error("Failed to create material buffer");
return false;
}
}
_vertices = _vbo.create();

View File

@ -51,24 +51,26 @@ bool ClientEntityRenderer::init() {
return false;
}
const voxel::Palette &palette = voxel::getPalette();
core::DynamicArray<glm::vec4> materialColors;
palette.toVec4f(materialColors);
core::DynamicArray<glm::vec4> glowColors;
palette.glowToVec4f(glowColors);
const int shaderMaterialColorsArraySize = lengthof(shader::SkeletonData::MaterialblockData::materialcolor);
const int materialColorsArraySize = palette.colorCount;
const int materialColorsArraySize = voxel::PaletteMaxColors;
if (shaderMaterialColorsArraySize != materialColorsArraySize) {
Log::error("Shader parameters and material colors don't match in their size: %i - %i",
shaderMaterialColorsArraySize, materialColorsArraySize);
return false;
}
shader::SkeletonData::MaterialblockData materialBlock;
core_memcpy(materialBlock.materialcolor, &materialColors.front(), sizeof(materialBlock.materialcolor));
core_memcpy(materialBlock.glowcolor, &glowColors.front(), sizeof(materialBlock.glowcolor));
_materialBlock.create(materialBlock);
{
const voxel::Palette &palette = voxel::getPalette();
core::DynamicArray<glm::vec4> materialColors;
palette.toVec4f(materialColors);
core::DynamicArray<glm::vec4> glowColors;
palette.glowToVec4f(glowColors);
shader::SkeletonData::MaterialblockData materialBlock;
core_memcpy(materialBlock.materialcolor, &materialColors.front(), sizeof(materialBlock.materialcolor));
core_memcpy(materialBlock.glowcolor, &glowColors.front(), sizeof(materialBlock.glowcolor));
_materialBlock.create(materialBlock);
}
video::TextureConfig textureCfg;
textureCfg.format(video::TextureFormat::D32F);

View File

@ -10,6 +10,7 @@
#include "core/collection/Map.h"
#include "core/Log.h"
#include "core/Color.h"
#include "voxel/MaterialColor.h"
#include "voxelutil/VolumeResizer.h"
#include "private/PaletteLookup.h"
#include <SDL_stdinc.h>
@ -167,6 +168,7 @@ bool AoSVXLFormat::loadMap(const core::String& filename, io::SeekableReadStream
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(filename);
node.setPalette(palLookup.palette());
sceneGraph.emplace(core::move(node));
return true;
}

View File

@ -100,6 +100,7 @@ bool CSMFormat::loadGroups(const core::String &filename, io::SeekableReadStream
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(name);
node.setPalette(palLookup.palette());
sceneGraph.emplace(core::move(node));
while (matrixIndex < voxels) {

View File

@ -72,11 +72,6 @@ bool CubFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
return false;
}
voxel::RawVolume *volume = new voxel::RawVolume(region);
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(filename);
sceneGraph.emplace(core::move(node));
PaletteLookup palLookup;
for (uint32_t h = 0u; h < height; ++h) {
for (uint32_t d = 0u; d < depth; ++d) {
@ -97,6 +92,11 @@ bool CubFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
}
}
}
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(filename);
node.setPalette(palLookup.palette());
sceneGraph.emplace(core::move(node));
return true;
}

View File

@ -22,16 +22,6 @@
namespace voxelformat {
uint8_t PaletteFormat::convertPaletteIndex(uint32_t paletteIndex) const {
if (paletteIndex >= (uint32_t)_palette.colorCount) {
if (_palette.colorCount > 0) {
return paletteIndex % _palette.colorCount;
}
return paletteIndex % _paletteMapping.size();
}
return _paletteMapping[paletteIndex];
}
static inline glm::vec4 transform(const glm::mat4x4 &mat, const glm::vec3 &pos, const glm::vec4 &pivot) {
return glm::floor(mat * (glm::vec4((float)pos.x + 0.5f, (float)pos.y + 0.5f, (float)pos.z + 0.5f, 1.0f) - pivot));
}

View File

@ -93,24 +93,6 @@ protected:
* and the colors will get matched to the in-use palette.
*/
voxel::Palette _palette;
/**
* @brief This array contains a mapping between the input colors of the particular format with the internal
* currently in-use palette indices.
* For example. You are loading a format that e.g. contains RGBA colors in a chunk and your particular file
* includes 256 colors as RGBA values. We now try to map the format input RGBA colors values to the ones from
* our own currently in-use palette. This is done by searching for a color in the current in-use palette that
* is very similar to the color from the input file you are loading. The found index in the in-use palette is
* then stored in this array for fast lookup when mapping the voxel data from the internal RGBA index of the
* input file to the currently in-use matching palette index.
*
* @sa findClosestIndex()
*/
core::Array<uint8_t, 256> _paletteMapping;
/**
* @brief Maps a custum palette index to our own 256 color palette by a closest match
*/
uint8_t convertPaletteIndex(uint32_t paletteIndex) const;
public:
size_t loadPalette(const core::String &filename, io::SeekableReadStream& stream, voxel::Palette &palette) override;
};

View File

@ -776,7 +776,7 @@ bool GLTFFormat::loadGltfNode_r(const core::String &filename, SceneGraph &sceneG
if (!subdivideShape(model, indices, vertices, textures, subdivided)) {
Log::error("Failed to subdivide node %i", gltfNodeIdx);
} else {
voxelizeTris(volume, subdivided);
voxelizeTris(node, subdivided);
newParent = sceneGraph.emplace(core::move(node));
}
for (int childId : gltfNode.children) {

View File

@ -298,6 +298,7 @@ bool GoxFormat::loadChunk_LAYR(State& state, const GoxChunk &c, io::SeekableRead
node.setVolume(voxelutil::mirrorAxis(layerVolume, math::Axis::Z), true);
node.setName(name);
node.setVisible(visible);
node.setPalette(palLookup.palette());
sceneGraph.emplace(core::move(node));
delete layerVolume;
return true;
@ -470,9 +471,9 @@ bool GoxFormat::saveChunk_LIGH(io::SeekableWriteStream& stream) {
return true; // not used
}
bool GoxFormat::saveChunk_MATE(io::SeekableWriteStream& stream) {
bool GoxFormat::saveChunk_MATE(io::SeekableWriteStream& stream, const SceneGraph &sceneGraph) {
GoxScopedChunkWriter scoped(stream, FourCC('M', 'A', 'T', 'E'));
const voxel::Palette& palette = voxel::getPalette();
const voxel::Palette& palette = sceneGraph.firstPalette();
for (int i = 0; i < palette.colorCount; ++i) {
const core::String& name = core::string::format("mat%i", i);
@ -605,7 +606,7 @@ bool GoxFormat::saveGroups(const SceneGraph &sceneGraph, const core::String &fil
wrapBool(saveChunk_PREV(stream))
int blocks = 0;
wrapBool(saveChunk_BL16(stream, sceneGraph, blocks))
wrapBool(saveChunk_MATE(stream))
wrapBool(saveChunk_MATE(stream, sceneGraph))
wrapBool(saveChunk_LAYR(stream, sceneGraph, blocks))
wrapBool(saveChunk_CAMR(stream, sceneGraph))
wrapBool(saveChunk_LIGH(stream))

View File

@ -109,7 +109,7 @@ private:
// Write all the blocks chunks.
bool saveChunk_BL16(io::SeekableWriteStream &stream, const SceneGraph &sceneGraph, int &blocks);
// Write all the materials.
bool saveChunk_MATE(io::SeekableWriteStream &stream);
bool saveChunk_MATE(io::SeekableWriteStream &stream, const SceneGraph &sceneGraph);
// Write all the layers.
bool saveChunk_LAYR(io::SeekableWriteStream &stream, const SceneGraph &sceneGraph, int numBlocks);
public:

View File

@ -9,6 +9,7 @@
#include "core/Color.h"
#include "core/FourCC.h"
#include "private/PaletteLookup.h"
#include "voxel/Palette.h"
#include <glm/common.hpp>
namespace voxelformat {
@ -67,13 +68,12 @@ bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream&
return false;
}
PaletteLookup palLookup;
if (stream.seek(32 + numvoxs * 8 + (xsiz << 2) + ((xsiz * ysiz) << 1)) != -1) {
if (stream.remaining() != 0) {
uint32_t palMagic;
wrap(stream.readUInt32(palMagic))
if (palMagic == FourCC('S','P','a','l')) {
_palette.colorCount = (int)_paletteMapping.size();
_palette.colorCount = voxel::PaletteMaxColors;
for (int i = 0; i < _palette.colorCount; ++i) {
uint8_t r, g, b;
wrap(stream.readUInt8(b))
@ -85,8 +85,6 @@ 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);
const int index = palLookup.findClosestIndex(color);
_paletteMapping[i] = index;
_palette.colors[i] = core::Color::getRGBA(color);
}
}
@ -95,18 +93,13 @@ bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream&
stream.seek(32);
voxel::RawVolume *volume = new voxel::RawVolume(region);
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(filename);
node.setTransform(0, transform, true);
node.setPalette(_palette);
sceneGraph.emplace(core::move(node));
typedef struct {
uint8_t z, col, vis, dir;
} voxtype;
voxtype voxdata[MAXVOXS];
PaletteLookup palLookup(_palette);
for (uint32_t c = 0u; c < numvoxs; ++c) {
uint8_t palr, palg, palb, pala;
wrap(stream.readUInt8(palb))
@ -160,6 +153,14 @@ bool KV6Format::loadGroups(const core::String &filename, io::SeekableReadStream&
}
}
}
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(filename);
node.setTransform(0, transform, true);
node.setPalette(palLookup.palette());
sceneGraph.emplace(core::move(node));
return true;
}

View File

@ -10,6 +10,7 @@
#include "core/Log.h"
#include "core/Color.h"
#include "private/PaletteLookup.h"
#include "voxel/Palette.h"
#include <glm/common.hpp>
namespace voxelformat {
@ -89,7 +90,7 @@ 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 = (int)_paletteMapping.size();
_palette.colorCount = voxel::PaletteMaxColors;
stream.seek(stream.size() - 3 * _palette.colorCount);
/**
@ -97,7 +98,6 @@ bool KVXFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
* The palette is in (Red:0, Green:1, Blue:2) order and intensities range
* from 0-63.
*/
PaletteLookup palLookup;
for (int i = 0; i < _palette.colorCount; ++i) {
uint8_t r, g, b;
wrap(stream.readUInt8(r))
@ -109,7 +109,6 @@ 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);
_paletteMapping[i] = palLookup.findClosestIndex(color);
_palette.colors[i] = core::Color::getRGBA(color);
}
stream.seek((int64_t)currentPos);
@ -171,7 +170,7 @@ bool KVXFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
for (uint8_t i = 0u; i < header.slabzleng; ++i) {
uint8_t col;
wrap(stream.readUInt8(col))
lastCol = voxel::createVoxel(voxel::VoxelType::Generic, convertPaletteIndex(col));
lastCol = voxel::createVoxel(voxel::VoxelType::Generic, col);
volume->setVoxel((int)x, (int)((zsiz - 1) - (header.slabztop + i)), (int)y, lastCol);
}

View File

@ -55,11 +55,6 @@ bool MCRFormat::loadGroups(const core::String &filename, io::SeekableReadStream
}
_palette.minecraft();
const voxel::Palette &palette = voxel::getPalette();
for (size_t i = 0; i < _palette.size(); ++i) {
_paletteMapping[i] = palette.getClosestMatch(core::Color::fromRGBA(_palette.colors[i]));
}
switch (type) {
case 'r':
case 'a': {
@ -250,8 +245,7 @@ bool MCRFormat::parseBlockStates(int dataVersion, const priv::NamedBinaryTag &da
return false;
}
if (color) {
const uint8_t index = convertPaletteIndex(color);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, index);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, color);
wrapper.setVoxel(sPos, voxel);
}
}
@ -269,8 +263,7 @@ bool MCRFormat::parseBlockStates(int dataVersion, const priv::NamedBinaryTag &da
return false;
}
if (color) {
const uint8_t index = convertPaletteIndex(color);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, index);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, color);
wrapper.setVoxel(sPos, voxel);
}
}

View File

@ -16,6 +16,7 @@
#include "voxel/IsQuadNeeded.h"
#include "voxel/MaterialColor.h"
#include "voxel/RawVolume.h"
#include "voxelformat/SceneGraphNode.h"
#include "voxelformat/private/PaletteLookup.h"
#include "voxelutil/VoxelUtil.h"
#include <SDL_timer.h>
@ -44,7 +45,7 @@ void MeshFormat::subdivideTri(const Tri &tri, TriCollection &tinyTris) {
const glm::vec3 &mins = tri.mins();
const glm::vec3 &maxs = tri.maxs();
const glm::vec3 size = maxs - mins;
if (size.x * size.y * size.z > 1.0f) {
if (glm::any(glm::greaterThan(size, glm::vec3(1.0f)))) {
Tri out[4];
tri.subdivide(out);
for (int i = 0; i < lengthof(out); ++i) {
@ -55,7 +56,7 @@ void MeshFormat::subdivideTri(const Tri &tri, TriCollection &tinyTris) {
tinyTris.push_back(tri);
}
void MeshFormat::voxelizeTris(voxel::RawVolume *volume, const TriCollection &subdivided) {
void MeshFormat::voxelizeTris(voxelformat::SceneGraphNode &node, const TriCollection &subdivided) {
struct PosSamplingEntry {
inline PosSamplingEntry(float _area, const glm::vec4 &_color) : area(_area), color(_color) {
}
@ -105,6 +106,7 @@ void MeshFormat::voxelizeTris(voxel::RawVolume *volume, const TriCollection &sub
}
}
Log::debug("create voxels");
voxel::RawVolume *volume = node.volume();
PaletteLookup palLookup;
for (const auto &entry : posMap) {
const PosSampling &pos = entry->second;
@ -113,6 +115,7 @@ void MeshFormat::voxelizeTris(voxel::RawVolume *volume, const TriCollection &sub
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, index);
volume->setVoxel(entry->first, voxel);
}
node.setPalette(palLookup.palette());
Log::debug("fill hollows");
voxelutil::fillHollow(*volume, voxel::Voxel(voxel::VoxelType::Generic, 2));
}

View File

@ -94,7 +94,7 @@ protected:
*/
static void subdivideTri(const Tri &tri, TriCollection &tinyTris);
static void voxelizeTris(voxel::RawVolume *volume, const TriCollection &tinyTris);
static void voxelizeTris(voxelformat::SceneGraphNode &node, const TriCollection &tinyTris);
struct MeshExt {
MeshExt(voxel::Mesh *mesh, const SceneGraphNode &node, bool applyTransform);

View File

@ -344,7 +344,7 @@ bool OBJFormat::loadGroups(const core::String &filename, io::SeekableReadStream
node.setName(shape.name.c_str());
TriCollection subdivided;
subdivideShape(shape.mesh, textures, attrib, materials, subdivided);
voxelizeTris(volume, subdivided);
voxelizeTris(node, subdivided);
return core::move(node);
};
if (shapes.size() > 1) {

View File

@ -120,7 +120,6 @@ bool PLYFormat::saveMeshes(const core::Map<int, int> &, const SceneGraph &sceneG
}
idxOffset += nv;
}
// TODO: palette from node
return voxel::getPalette().save(paletteName);
return sceneGraph.firstPalette().save(paletteName);
}
}

View File

@ -382,6 +382,7 @@ bool QBCLFormat::readMatrix(const core::String &filename, io::SeekableReadStream
}
SceneGraphNode node;
node.setVolume(volume, true);
node.setPalette(palLookup.palette());
if (name.empty()) {
node.setName("Matrix");
} else {

View File

@ -226,6 +226,7 @@ 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));
if (state._compressed == Compression::None) {
Log::debug("qb matrix uncompressed");

View File

@ -13,6 +13,7 @@
#include "io/BufferedZipReadStream.h"
#include "voxel/MaterialColor.h"
#include "core/Log.h"
#include "voxel/Palette.h"
#include "voxelformat/SceneGraphNode.h"
#include "voxelformat/private/PaletteLookup.h"
#include <glm/common.hpp>
@ -153,9 +154,8 @@ bool QBTFormat::saveMatrix(io::SeekableWriteStream& stream, const SceneGraphNode
return (size_t)datasize == chunkEndPos - chunkStartPos;
}
bool QBTFormat::saveColorMap(io::SeekableWriteStream& stream) const {
bool QBTFormat::saveColorMap(io::SeekableWriteStream& stream, const voxel::Palette& palette) const {
wrapSave(stream.writeString("COLORMAP", false));
const voxel::Palette& palette = voxel::getPalette();
wrapSave(stream.writeUInt32(palette.colorCount));
for (int i = 0; i < palette.colorCount; ++i) {
wrapSave(stream.writeUInt32(palette.colors[i]));
@ -202,7 +202,8 @@ bool QBTFormat::saveGroups(const SceneGraph& sceneGraph, const core::String &fil
wrapSave(stream.writeFloat(1.0f));
bool colorMap = false;
if (colorMap) {
if (!saveColorMap(stream)) {
const voxel::Palette& palette = sceneGraph.firstPalette();
if (!saveColorMap(stream, palette)) {
return false;
}
}
@ -348,7 +349,7 @@ bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGrap
Log::error("Invalid region");
return false;
}
PaletteLookup palLookup;
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++) {
@ -381,7 +382,7 @@ bool QBTFormat::loadMatrix(io::SeekableReadStream& stream, SceneGraph& sceneGrap
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(name);
node.setPalette(_palette);
node.setPalette(palLookup.palette());
node.setTransform(0, transform, true);
const int id = sceneGraph.emplace(core::move(node), parent);
return id != -1;
@ -459,12 +460,11 @@ bool QBTFormat::loadColorMap(io::SeekableReadStream& stream) {
uint32_t colorCount;
wrap(stream.readUInt32(colorCount));
Log::debug("Load color map with %u colors", colorCount);
if (colorCount > _paletteMapping.size()) {
if (colorCount > voxel::PaletteMaxColors) {
Log::error("Sanity check for max colors failed (%u)", colorCount);
return false;
}
_palette.colorCount = (int)colorCount;
const voxel::Palette &palette = voxel::getPalette();
for (uint32_t i = 0; i < colorCount; ++i) {
uint8_t colorByteR;
uint8_t colorByteG;
@ -482,8 +482,6 @@ bool QBTFormat::loadColorMap(io::SeekableReadStream& stream) {
const glm::vec4& color = core::Color::fromRGBA(red | green | blue | alpha);
_palette.colors[i] = core::Color::getRGBA(color);
const uint8_t index = palette.getClosestMatch(color);
_paletteMapping[i] = index;
}
return true;
}

View File

@ -27,7 +27,7 @@ private:
bool loadColorMap(io::SeekableReadStream& stream);
bool saveMatrix(io::SeekableWriteStream& stream, const SceneGraphNode& node, bool colorMap) const;
bool saveColorMap(io::SeekableWriteStream& stream) 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;

View File

@ -82,7 +82,6 @@ bool QEFFormat::loadGroups(const core::String &filename, io::SeekableReadStream
_palette.colorCount = paletteSize;
const voxel::Palette &palette = voxel::getPalette();
for (int i = 0; i < paletteSize; ++i) {
float r, g, b;
wrapBool(stream.readLine(sizeof(buf), buf))
@ -92,8 +91,6 @@ bool QEFFormat::loadGroups(const core::String &filename, io::SeekableReadStream
}
const glm::vec4 color(r, g, b, 1.0f);
_palette.colors[i] = core::Color::getRGBA(color);
const uint8_t index = palette.getClosestMatch(_palette.colors[i]);
_paletteMapping[i] = index;
}
voxel::RawVolume* volume = new voxel::RawVolume(region);
SceneGraphNode node;
@ -109,7 +106,7 @@ bool QEFFormat::loadGroups(const core::String &filename, io::SeekableReadStream
Log::error("Failed to parse voxel data line");
return false;
}
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, convertPaletteIndex(color));
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, color);
volume->setVoxel(x, y, z, voxel);
}

View File

@ -177,7 +177,7 @@ bool STLFormat::loadGroups(const core::String &filename, io::SeekableReadStream
node.setName(filename);
TriCollection subdivided;
subdivideShape(faces, subdivided);
voxelizeTris(volume, subdivided);
voxelizeTris(node, subdivided);
sceneGraph.emplace(core::move(node));
return true;
}

View File

@ -6,6 +6,7 @@
#include "core/Common.h"
#include "core/Log.h"
#include "core/Pair.h"
#include "voxel/MaterialColor.h"
#include "voxel/RawVolume.h"
#include "voxelformat/SceneGraphNode.h"
#include "voxelutil/VolumeMerger.h"
@ -64,6 +65,13 @@ bool SceneGraph::setActiveNode(int nodeId) {
return true;
}
voxel::Palette &SceneGraph::firstPalette() const {
for (SceneGraphNode& node : *this) {
return node.palette();
}
return voxel::getPalette();
}
void SceneGraph::foreachGroup(const std::function<void(int)>& f) {
int nodeId = activeNode();
if (node(nodeId).locked()) {

View File

@ -39,6 +39,10 @@ public:
int activeNode() const;
bool setActiveNode(int nodeId);
/**
* @brief Returns the first valid palette from any of the nodes
*/
voxel::Palette &firstPalette() const;
/**
* @brief Loops over the locked/groups (model) nodes with the given function that receives the node id
*/

View File

@ -22,6 +22,7 @@
#include "voxel/RawVolumeWrapper.h"
#include "voxel/Region.h"
#include "voxel/Voxel.h"
#include "voxelformat/private/PaletteLookup.h"
#include "voxelutil/VolumeCropper.h"
#include "voxelutil/VolumeMerger.h"
@ -31,10 +32,6 @@ namespace voxelformat {
bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
_palette.minecraft();
const voxel::Palette &palette = voxel::getPalette();
for (size_t i = 0; i < _palette.size(); ++i) {
_paletteMapping[i] = palette.getClosestMatch(core::Color::fromRGBA(_palette.colors[i]));
}
io::ZipReadStream zipStream(stream);
priv::NamedBinaryTagContext ctx;
ctx.stream = &zipStream;
@ -85,7 +82,7 @@ bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadS
}
}
_paletteMapping.fill(0xFF);
PaletteLookup palLookup(_palette);
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
for (int z = 0; z < depth; ++z) {
@ -93,19 +90,12 @@ bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadS
const uint8_t palIdx = (*blocks.byteArray())[idx];
if (palIdx != 0u) {
uint8_t currentPalIdx;
core::RGBA color;
if (paletteEntry == 0) {
currentPalIdx = palIdx;
color = _palette.colors[palIdx];
} else {
currentPalIdx = mcpal[palIdx];
color = _palette.colors[mcpal[palIdx]];
}
if (_paletteMapping[currentPalIdx] == 0xFF) {
_paletteMapping[currentPalIdx] = palette.getClosestMatch(color);
}
volume->setVoxel(x, y, z, voxel::createVoxel(voxel::VoxelType::Generic, _paletteMapping[currentPalIdx]));
volume->setVoxel(x, y, z, voxel::createVoxel(voxel::VoxelType::Generic, currentPalIdx));
}
}
}
@ -147,13 +137,9 @@ bool SchematicFormat::saveGroups(const SceneGraph& sceneGraph, const core::Strin
compound.put("z", (int32_t)mins.z);
compound.put("Materials", priv::NamedBinaryTag("Alpha"));
{
const voxel::Palette &palette = merged.second;
core::DynamicArray<int8_t> blocks;
blocks.resize(size.x * size.y * size.z);
_paletteMapping.fill(0xFF);
for (int x = 0; x < size.x; ++x) {
for (int y = 0; y < size.y; ++y) {
for (int z = 0; z < size.z; ++z) {
@ -163,11 +149,7 @@ bool SchematicFormat::saveGroups(const SceneGraph& sceneGraph, const core::Strin
blocks[idx] = 0;
} else {
const uint8_t currentPalIdx = voxel.getColor();
core::RGBA color = palette.colors[currentPalIdx];
if (_paletteMapping[currentPalIdx] == 0xFF) {
_paletteMapping[currentPalIdx] = _palette.getClosestMatch(color);
}
blocks[idx] = (int8_t)_paletteMapping[currentPalIdx];
blocks[idx] = (int8_t)currentPalIdx;
}
}
}

View File

@ -84,6 +84,7 @@ bool SproxelFormat::loadGroups(const core::String &filename, io::SeekableReadStr
SceneGraphNode node;
node.setVolume(volume, true);
node.setName(filename);
node.setPalette(palLookup.palette());
sceneGraph.emplace(core::move(node));
return true;
}

View File

@ -160,7 +160,7 @@ bool VXLFormat::writeHeader(io::SeekableWriteStream& stream, const SceneGraph& s
wrapBool(stream.writeUInt32(0)) // bodysize is filled later
wrapBool(stream.writeUInt16(0x1f10U))
const voxel::Palette &palette = voxel::getPalette();
const voxel::Palette &palette = sceneGraph.firstPalette();
for (int i = 0; i < palette.colorCount; ++i) {
const core::RGBA& rgba = palette.colors[i];
wrapBool(stream.writeUInt8(rgba.r))
@ -265,8 +265,7 @@ bool VXLFormat::readLimb(io::SeekableReadStream& stream, vxl_mdl& mdl, uint32_t
wrap(stream.readUInt8(color))
uint8_t normal;
wrap(stream.readUInt8(normal))
const uint8_t palIdx = convertPaletteIndex(color);
const voxel::Voxel v = voxel::createVoxel(voxel::VoxelType::Generic, palIdx);
const voxel::Voxel v = voxel::createVoxel(voxel::VoxelType::Generic, color);
volume->setVoxel(x, z, y, v);
++z;
}
@ -371,12 +370,9 @@ bool VXLFormat::readHeader(io::SeekableReadStream& stream, vxl_mdl& mdl) {
}
if (valid) {
// convert to our palette
PaletteLookup palLookup;
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]);
_paletteMapping[i] = palLookup.findClosestIndex(_palette.colors[i]);
}
} else {
_palette.colorCount = 0;

View File

@ -131,7 +131,7 @@ bool VXMFormat::saveGroups(const SceneGraph& sceneGraph, const core::String &fil
#endif
}
const voxel::Palette &palette = voxel::getPalette();
const voxel::Palette &palette = sceneGraph.firstPalette();
core::DynamicArray<glm::vec4> materialColors;
palette.toVec4f(materialColors);
@ -401,7 +401,6 @@ bool VXMFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
return false;
}
const voxel::Palette &palette = voxel::getPalette();
for (int i = 0; i < (int) materialAmount; ++i) {
uint8_t blue;
wrap(stream.readUInt8(blue));
@ -414,7 +413,6 @@ bool VXMFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
uint8_t emissive;
wrap(stream.readUInt8(emissive));
_palette.colors[i] = core::Color::getRGBA(red, green, blue, alpha);
_paletteMapping[i] = palette.getClosestMatch(_palette.colors[i]);
if (emissive) {
_palette.glowColors[i] = _palette.colors[i];
}
@ -458,8 +456,7 @@ bool VXMFormat::loadGroups(const core::String &filename, io::SeekableReadStream&
continue;
}
const uint8_t index = _paletteMapping[matIdx];
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, index);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, matIdx);
// left to right, bottom to top, front to back
for (int i = idx; i < idx + length; i++) {

View File

@ -138,7 +138,7 @@ bool VoxFormat::addInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx
if (ogtVoxel[0] == 0) {
continue;
}
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, _paletteMapping[ogtVoxel[0]]);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, ogtVoxel[0]);
const glm::ivec3 &pos = transform(ogtMat, glm::ivec3(i, j, k), pivot);
const glm::ivec3 &poszUp = transform(zUpMat, pos, glm::ivec4(0));
v->setVoxel(poszUp, voxel);
@ -229,7 +229,6 @@ bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream
}
_palette.colorCount = lengthof(scene->palette.color);
const voxel::Palette &palette = voxel::getPalette();
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);
@ -237,7 +236,6 @@ bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream
if (matl.type == ogt_matl_type_emit) {
_palette.glowColors[i] = _palette.colors[i];
}
_paletteMapping[i] = palette.getClosestMatch(_palette.colors[i]);
}
// rotation matrix to convert into our coordinate system (z pointing upwards)
const glm::mat4 zUpMat = glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));
@ -288,10 +286,9 @@ bool VoxFormat::loadGroups(const core::String &filename, io::SeekableReadStream
return true;
}
int VoxFormat::findClosestPaletteIndex() {
int VoxFormat::findClosestPaletteIndex(const voxel::Palette &palette) {
// we have to find a replacement for the first palette entry - as this is used
// as the empty voxel in magicavoxel
const voxel::Palette &palette = voxel::getPalette();
core::DynamicArray<glm::vec4> materialColors;
palette.toVec4f(materialColors);
const glm::vec4 first = materialColors[0];
@ -316,8 +313,8 @@ bool VoxFormat::saveGroups(const SceneGraph &sceneGraph, const core::String &fil
default_group.parent_group_index = k_invalid_group_index;
default_group.transform = ogt_identity_transform;
const voxel::Palette &palette = voxel::getPalette();
const int replacement = findClosestPaletteIndex();
const voxel::Palette &palette = sceneGraph.firstPalette();
const int replacement = findClosestPaletteIndex(palette);
core::Buffer<ogt_vox_model> models(modelCount);
core::Buffer<ogt_vox_layer> layers(modelCount);
core::Buffer<ogt_vox_instance> instances(modelCount);

View File

@ -22,7 +22,7 @@ namespace voxelformat {
*/
class VoxFormat : public PaletteFormat {
private:
int findClosestPaletteIndex();
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);
public:

View File

@ -42,7 +42,6 @@ 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;
const voxel::Palette &palette = voxel::getPalette();
for (int i = 0; i < _palette.colorCount; ++i) {
uint8_t r, g, b;
wrap(stream.readUInt8(r))
@ -50,7 +49,6 @@ bool VoxOldFormat::loadGroups(const core::String &filename, io::SeekableReadStre
wrap(stream.readUInt8(b))
_palette.colors[i] = core::Color::getRGBA(r, g, b);
_paletteMapping[i] = palette.getClosestMatch(_palette.colors[i]);
}
stream.seek(voxelPos);
@ -62,7 +60,7 @@ bool VoxOldFormat::loadGroups(const core::String &filename, io::SeekableReadStre
if (palIdx == 255) {
continue;
}
const voxel::Voxel& voxel = voxel::createVoxel(voxel::VoxelType::Generic, _paletteMapping[palIdx]);
const voxel::Voxel& voxel = voxel::createVoxel(voxel::VoxelType::Generic, palIdx);
// we have to flip depth with height for our own coordinate system
volume->setVoxel((int)w, (int)h, (int)d, voxel);
}

View File

@ -13,10 +13,20 @@ namespace voxelformat {
class PaletteLookup {
private:
voxel::Palette _palette;
core::Map<core::RGBA, uint8_t, 521> _paletteMap;
public:
PaletteLookup(const voxel::Palette &palette, int maxSize = 32768) : _palette(palette), _paletteMap(maxSize) {
if (_palette.colorCount <= 0) {
_palette.magicaVoxel();
}
}
PaletteLookup(int maxSize = 32768) : _paletteMap(maxSize) {
_palette.magicaVoxel();
}
inline const voxel::Palette &palette() const {
return _palette;
}
/**
@ -35,8 +45,7 @@ public:
uint8_t findClosestIndex(core::RGBA rgba) {
uint8_t paletteIndex = 0;
if (!_paletteMap.get(rgba, paletteIndex)) {
const voxel::Palette &palette = voxel::getPalette();
paletteIndex = palette.getClosestMatch(rgba);
paletteIndex = _palette.getClosestMatch(rgba);
if (_paletteMap.size() < _paletteMap.capacity()) {
_paletteMap.put(rgba, paletteIndex);
}
@ -45,4 +54,4 @@ public:
}
};
} // namespace voxel
} // namespace voxel

View File

@ -62,7 +62,7 @@ bool MeshRenderer::init() {
palette.glowToVec4f(glowColors);
const int shaderMaterialColorsArraySize = lengthof(shader::VoxelData::MaterialblockData::materialcolor);
const int materialColorsArraySize = palette.colorCount;
const int materialColorsArraySize = voxel::PaletteMaxColors;
if (shaderMaterialColorsArraySize != materialColorsArraySize) {
Log::error("Shader parameters and material colors don't match in their size: %i - %i",
shaderMaterialColorsArraySize, materialColorsArraySize);

View File

@ -95,12 +95,10 @@ bool RawVolumeRenderer::init() {
}
}
const voxel::Palette &palette = voxel::getPalette();
const int shaderMaterialColorsArraySize = lengthof(shader::VoxelData::MaterialblockData::materialcolor);
if (shaderMaterialColorsArraySize != palette.colorCount) {
if (shaderMaterialColorsArraySize != voxel::PaletteMaxColors) {
Log::error("Shader parameters and material colors don't match in their size: %i - %i",
shaderMaterialColorsArraySize, palette.colorCount);
shaderMaterialColorsArraySize, voxel::PaletteMaxColors);
return false;
}
@ -462,12 +460,10 @@ void RawVolumeRenderer::gray(int idx, bool gray) {
void RawVolumeRenderer::updatePalette(int idx) {
const voxel::Palette *palette;
// TODO: activate me
// const State &state = _state[idx];
// if (state._palette.hasValue()) {
// palette = state._palette.value();
// } else
{
const State &state = _state[idx];
if (state._palette.hasValue()) {
palette = state._palette.value();
} else {
palette = &voxel::getPalette();
}

View File

@ -443,7 +443,7 @@ bool VoxConvert::handleInputFile(const core::String &infile, voxelformat::SceneG
if (_exportPalette) {
const core::String &paletteFile = core::string::stripExtension(infile) + ".png";
voxel::getPalette().save(paletteFile.c_str());
sceneGraph.firstPalette().save(paletteFile.c_str());
if (!_srcPalette) {
Log::info(" .. not using the input file palette");
}

View File

@ -482,12 +482,11 @@ int SceneManager::activeNode() const {
}
voxel::Palette &SceneManager::activePalette() const {
// TODO: activate me - see RawVolumeRenderer::updatePalette
// const int nodeId = activeNode();
// if (!_sceneGraph.hasNode(nodeId)) {
return voxel::getPalette();
// }
// return _sceneGraph.node(nodeId).palette();
const int nodeId = activeNode();
if (!_sceneGraph.hasNode(nodeId)) {
return _sceneGraph.firstPalette();
}
return _sceneGraph.node(nodeId).palette();
}
voxel::RawVolume* SceneManager::activeVolume() {
@ -2474,6 +2473,7 @@ bool SceneManager::nodeActivate(int nodeId) {
return false;
}
_sceneGraph.setActiveNode(nodeId);
voxel::overridePalette(node.palette());
const voxel::Region& region = node.region();
updateGridRenderer(region);
updateAABBMesh();