From 3b0acdfbb21822c1504897025e51ef9d3d093feb Mon Sep 17 00:00:00 2001 From: Martin Gerhardy Date: Fri, 7 Jul 2023 17:10:23 +0200 Subject: [PATCH] VOXELFORMAT: VOX: refactored format to support references there are still problems with flip matrices and backside culling see pull request #296 and issue #255 This more or less opens #275 again --- .../scenegraph/CoordinateSystemUtil.cpp | 28 ++++--- src/modules/voxelformat/VoxFormat.cpp | 79 +++++++------------ .../voxelformat/private/MagicaVoxel.cpp | 10 ++- 3 files changed, 50 insertions(+), 67 deletions(-) diff --git a/src/modules/scenegraph/CoordinateSystemUtil.cpp b/src/modules/scenegraph/CoordinateSystemUtil.cpp index 1572ad26ef..d7960284dc 100644 --- a/src/modules/scenegraph/CoordinateSystemUtil.cpp +++ b/src/modules/scenegraph/CoordinateSystemUtil.cpp @@ -8,29 +8,31 @@ namespace scenegraph { +// +// Generate right, forward and up direction vectors to express the desired coordinate system as it would have been in opengl +// +// MV/VXL GL VENGI +// +// Z Y Y +// | Y | | Z +// |/ | |/ +// o----X o----X o----X +// / +// Z +// bool coordinateSystemToMatrix(CoordinateSystem sys, glm::mat4 &matrix) { glm::vec3 right; glm::vec3 up; glm::vec3 forward; switch (sys) { case CoordinateSystem::Vengi: - right = glm::right; - up = glm::up; - forward = glm::forward; + right = glm::vec3(1.0f, 0.0f, 0.0f); + up = glm::vec3(0.0f, 1.0f, 0.0f); + forward = glm::vec3(0.0f, 0.0f, 1.0f); break; case CoordinateSystem::MagicaVoxel: case CoordinateSystem::VXL: - // // Z-up coordinate system (like 3dsmax). - // - // MV GL - // - // Z Y - // | Y | - // |/ | - // o----X o----X - // / - // Z right = glm::vec3(1.0f, 0.0f, 0.0f); up = glm::vec3(0.0f, 0.0f, 1.0f); forward = glm::vec3(0.0f, 1.0f, 0.0f); diff --git a/src/modules/voxelformat/VoxFormat.cpp b/src/modules/voxelformat/VoxFormat.cpp index ebeb0274c4..bc9319a4a5 100644 --- a/src/modules/voxelformat/VoxFormat.cpp +++ b/src/modules/voxelformat/VoxFormat.cpp @@ -42,51 +42,28 @@ size_t VoxFormat::loadPalette(const core::String &filename, io::SeekableReadStre bool VoxFormat::loadInstance(const ogt_vox_scene *scene, uint32_t ogt_instanceIdx, scenegraph::SceneGraph &sceneGraph, int parent, core::DynamicArray &models, const voxel::Palette &palette) { const ogt_vox_instance &ogtInstance = scene->instances[ogt_instanceIdx]; - const ogt_vox_model *ogtModel = scene->models[ogtInstance.model_index]; - const glm::mat4 ogtMat = ogtTransformToMat(ogtInstance, 0, scene, ogtModel); - const glm::vec4 &ogtPivot = ogtVolumePivot(ogtModel); - const glm::ivec3 &ogtMins = calcTransform(ogtMat, glm::ivec3(0), ogtPivot); - const glm::ivec3 &ogtMaxs = calcTransform(ogtMat, ogtVolumeSize(ogtModel), ogtPivot); - const glm::ivec3 mins(-(ogtMins.x + 1), ogtMins.z, ogtMins.y); - const glm::ivec3 maxs(-(ogtMaxs.x + 1), ogtMaxs.z, ogtMaxs.y); - voxel::Region region(glm::min(mins, maxs), glm::max(mins, maxs)); - const glm::ivec3 shift = region.getLowerCorner(); - region.shift(-shift); - voxel::RawVolume *v = new voxel::RawVolume(region); - scenegraph::SceneGraphTransform transform; - transform.setWorldTranslation(shift); - - const uint8_t *ogtVoxel = ogtModel->voxel_data; - for (uint32_t k = 0; k < ogtModel->size_z; ++k) { - for (uint32_t j = 0; j < ogtModel->size_y; ++j) { - for (uint32_t i = 0; i < ogtModel->size_x; ++i, ++ogtVoxel) { - if (ogtVoxel[0] == 0) { - continue; - } - const voxel::Voxel voxel = voxel::createVoxel(palette, ogtVoxel[0] - 1); - const glm::ivec3 &ogtPos = calcTransform(ogtMat, glm::ivec3(i, j, k), ogtPivot); - const glm::ivec3 pos(-(ogtPos.x + 1), ogtPos.z, ogtPos.y); - v->setVoxel(pos - shift, voxel); - } - } + scenegraph::SceneGraphNodeType type = scenegraph::SceneGraphNodeType::Model; + if (models[ogtInstance.model_index].nodeId != InvalidNodeId) { + type = scenegraph::SceneGraphNodeType::ModelReference; } - - scenegraph::SceneGraphNode node(scenegraph::SceneGraphNodeType::Model); + scenegraph::SceneGraphNode node(type); loadKeyFrames(sceneGraph, node, ogtInstance, scene); - // TODO: we are overriding the keyframe data here - const scenegraph::KeyFrameIndex keyFrameIdx = 0; - node.setTransform(keyFrameIdx, transform); node.setColor(instanceColor(scene, ogtInstance)); node.setName(instanceName(scene, ogtInstance)); node.setVisible(!instanceHidden(scene, ogtInstance)); - node.setVolume(v, true); - // TODO: use already loaded models and create a model reference if needed - // TODO: node.setVolume(new voxel::RawVolume(models[ogtInstance.model_index].volume), true); - // TODO: set correct pivot - // TODO: node.setPivot({ogtPivot.x / (float)ogtModel->size_x, ogtPivot.z / (float)ogtModel->size_z, ogtPivot.y / (float)ogtModel->size_y}); - // TODO: node.setPivot({(ogtPivot.x + 0.5f) / (float)ogtModel->size_x, (ogtPivot.z + 0.5f) / (float)ogtModel->size_z, (ogtPivot.y + 0.5f) / (float)ogtModel->size_y}); + if (type == scenegraph::SceneGraphNodeType::ModelReference) { + node.setReference(models[ogtInstance.model_index].nodeId); + } else { + node.setVolume(models[ogtInstance.model_index].volume, true); + models[ogtInstance.model_index].volume = nullptr; + } node.setPalette(palette); - return sceneGraph.emplace(core::move(node), parent) != -1; + const int nodeId = sceneGraph.emplace(core::move(node), parent); + if (nodeId != InvalidNodeId) { + models[ogtInstance.model_index].nodeId = nodeId; + return true; + } + return false; } bool VoxFormat::loadGroup(const ogt_vox_scene *scene, uint32_t ogt_groupIdx, scenegraph::SceneGraph &sceneGraph, @@ -114,6 +91,18 @@ bool VoxFormat::loadGroup(const ogt_vox_scene *scene, uint32_t ogt_groupIdx, sce return false; } + for (uint32_t groupIdx = 0; groupIdx < scene->num_groups; ++groupIdx) { + const ogt_vox_group &group = scene->groups[groupIdx]; + Log::debug("group %u with parent: %u (searching for %u)", groupIdx, group.parent_group_index, ogt_groupIdx); + if (group.parent_group_index != ogt_groupIdx) { + continue; + } + Log::debug("Found matching group (%u) with scene graph parent: %i", groupIdx, groupId); + if (!loadGroup(scene, groupIdx, sceneGraph, groupId, models, addedInstances, palette)) { + return false; + } + } + for (uint32_t n = 0; n < scene->num_instances; ++n) { const ogt_vox_instance &ogtInstance = scene->instances[n]; if (ogtInstance.group_index != ogt_groupIdx) { @@ -127,18 +116,6 @@ bool VoxFormat::loadGroup(const ogt_vox_scene *scene, uint32_t ogt_groupIdx, sce } } - for (uint32_t groupIdx = 0; groupIdx < scene->num_groups; ++groupIdx) { - const ogt_vox_group &group = scene->groups[groupIdx]; - Log::debug("group %u with parent: %u (searching for %u)", groupIdx, group.parent_group_index, ogt_groupIdx); - if (group.parent_group_index != ogt_groupIdx) { - continue; - } - Log::debug("Found matching group (%u) with scene graph parent: %i", groupIdx, groupId); - if (!loadGroup(scene, groupIdx, sceneGraph, groupId, models, addedInstances, palette)) { - return false; - } - } - return true; } diff --git a/src/modules/voxelformat/private/MagicaVoxel.cpp b/src/modules/voxelformat/private/MagicaVoxel.cpp index b93446b828..9ea2f6eb2a 100644 --- a/src/modules/voxelformat/private/MagicaVoxel.cpp +++ b/src/modules/voxelformat/private/MagicaVoxel.cpp @@ -8,6 +8,8 @@ #include "core/GLMConst.h" #include "core/Log.h" #include "core/StandardLib.h" +#include "scenegraph/CoordinateSystem.h" +#include "scenegraph/CoordinateSystemUtil.h" #include "scenegraph/SceneGraph.h" #include "scenegraph/SceneGraphNode.h" #include "voxel/Palette.h" @@ -60,8 +62,7 @@ bool loadKeyFrames(scenegraph::SceneGraph &sceneGraph, scenegraph::SceneGraphNod sceneGraphKeyFrame.interpolation = scenegraph::InterpolationType::Linear; sceneGraphKeyFrame.longRotation = false; scenegraph::SceneGraphTransform &transform = sceneGraphKeyFrame.transform(); - // TODO: scenegraph::convertCoordinateSystem(scenegraph::CoordinateSystem::MagicaVoxel, ogtMat)); - transform.setWorldMatrix(ogtMat); + transform.setWorldMatrix(scenegraph::convertCoordinateSystem(scenegraph::CoordinateSystem::MagicaVoxel, ogtMat)); kf.push_back(sceneGraphKeyFrame); } return node.setKeyFrames(kf); @@ -235,10 +236,13 @@ core::DynamicArray loadModels(const ogt_vox_scene *scene, const v continue; } const voxel::Voxel voxel = voxel::createVoxel(palette, ogtVoxel[0] - 1); - v->setVoxel(region.getUpperX() - (int)x, (int)z, (int)y, voxel); + v->setVoxel((int)x, (int)z, (int)y, voxel); } } } + const glm::ivec3 shift(-(int)(ogtModel->size_x / 2), -(int)(ogtModel->size_z / 2), -(int)(ogtModel->size_y / 2)); + v->translate(shift); + models.emplace_back(v, InvalidNodeId); } return models;