diff --git a/src/modules/voxelformat/private/magicavoxel/MagicaVoxel.cpp b/src/modules/voxelformat/private/magicavoxel/MagicaVoxel.cpp index 4cebf1174..7ec351d90 100644 --- a/src/modules/voxelformat/private/magicavoxel/MagicaVoxel.cpp +++ b/src/modules/voxelformat/private/magicavoxel/MagicaVoxel.cpp @@ -27,10 +27,10 @@ namespace voxelformat { glm::mat4 ogtTransformToMat(const ogt_vox_instance &ogtInstance, uint32_t frameIdx, const ogt_vox_scene *scene, const ogt_vox_model *ogtModel) { ogt_vox_transform t = ogt_vox_sample_instance_transform_global(&ogtInstance, frameIdx, scene); - const glm::vec4 col0(t.m00, t.m01, t.m02, t.m03); - const glm::vec4 col1(t.m10, t.m11, t.m12, t.m13); - const glm::vec4 col2(t.m20, t.m21, t.m22, t.m23); - const glm::vec4 col3(t.m30, t.m31, t.m32, t.m33); + const glm::vec4 col0(t.m00, t.m02, t.m01, t.m03); + const glm::vec4 col1(t.m20, t.m22, t.m21, t.m23); + const glm::vec4 col2(t.m10, t.m12, t.m11, t.m13); + const glm::vec4 col3(t.m30, t.m32, t.m31, t.m33); return glm::mat4{col0, col1, col2, col3}; } @@ -45,22 +45,17 @@ void _ogt_free(void *mem) { bool loadKeyFrames(scenegraph::SceneGraph &sceneGraph, scenegraph::SceneGraphNode &node, const ogt_vox_instance &ogtInstance, const ogt_vox_scene *scene) { scenegraph::SceneGraphKeyFrames kf; - - const ogt_vox_anim_transform &transformAnim = ogtInstance.transform_anim; - uint32_t numKeyframes = transformAnim.num_keyframes; + const uint32_t numKeyframes = ogtInstance.transform_anim.num_keyframes; Log::debug("Load %d keyframes", numKeyframes); kf.reserve(numKeyframes); - const ogt_vox_model *ogtModel = scene->models[ogtInstance.model_index]; for (uint32_t keyFrameIdx = 0; keyFrameIdx < numKeyframes; ++keyFrameIdx) { - const ogt_vox_keyframe_transform &keyFrameTransform = transformAnim.keyframes[keyFrameIdx]; - const uint32_t frameIdx = keyFrameTransform.frame_index; - const glm::mat4 ogtMat = ogtTransformToMat(ogtInstance, frameIdx, scene, ogtModel); + const uint32_t frameIdx = ogtInstance.transform_anim.keyframes[keyFrameIdx].frame_index; + const glm::mat4 &worldMatrix = ogtTransformToMat(ogtInstance, frameIdx, scene, scene->models[ogtInstance.model_index]); scenegraph::SceneGraphKeyFrame sceneGraphKeyFrame; sceneGraphKeyFrame.frameIdx = (scenegraph::FrameIndex)frameIdx; sceneGraphKeyFrame.interpolation = scenegraph::InterpolationType::Linear; sceneGraphKeyFrame.longRotation = false; - scenegraph::SceneGraphTransform &transform = sceneGraphKeyFrame.transform(); - transform.setWorldMatrix(scenegraph::convertCoordinateSystem(scenegraph::CoordinateSystem::MagicaVoxel, ogtMat)); + sceneGraphKeyFrame.transform().setWorldMatrix(worldMatrix); kf.push_back(sceneGraphKeyFrame); } return node.setKeyFrames(kf); diff --git a/src/modules/voxelformat/private/magicavoxel/VoxFormat.cpp b/src/modules/voxelformat/private/magicavoxel/VoxFormat.cpp index 083f43f10..d92e8bb99 100644 --- a/src/modules/voxelformat/private/magicavoxel/VoxFormat.cpp +++ b/src/modules/voxelformat/private/magicavoxel/VoxFormat.cpp @@ -46,58 +46,43 @@ 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 palette::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); - 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)); - if (ogtInstance.layer_index < scene->num_layers) { - const ogt_vox_layer &ogtLayer = scene->layers[ogtInstance.layer_index]; - if (ogtLayer.name != nullptr) { - node.setProperty("layer", ogtLayer.name); - } + const ogt_vox_layer &layer = scene->layers[ogtInstance.layer_index]; + const core::RGBA col(layer.color.r, layer.color.g, layer.color.b, layer.color.a); + const char *name = ogtInstance.name == nullptr ? layer.name : ogtInstance.name; + if (name == nullptr) { + name = ""; } - node.setProperty("layerId", core::string::toString(ogtInstance.layer_index)); - 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}); + + scenegraph::SceneGraphNode node(type); + node.setName(name); + node.setColor(col); + node.setVisible(!ogtInstance.hidden); node.setPalette(palette); - return sceneGraph.emplace(core::move(node), parent) != -1; + 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; + } + const glm::vec3 pivot(0.5f); + node.setPivot(pivot); + if (!loadKeyFrames(sceneGraph, node, ogtInstance, scene)) { + scenegraph::SceneGraphTransform transform; + const glm::mat4 &worldMatrix = ogtTransformToMat(ogtInstance, 0, scene, scene->models[ogtInstance.model_index]); + transform.setWorldMatrix(worldMatrix); + const scenegraph::KeyFrameIndex keyFrameIdx = 0; + node.setTransform(keyFrameIdx, transform); + } + 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, @@ -126,9 +111,9 @@ 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) { + const ogt_vox_group &ogtGroup = scene->groups[groupIdx]; + Log::debug("group %u with parent: %u (searching for %u)", groupIdx, ogtGroup.parent_group_index, ogt_groupIdx); + if (ogtGroup.parent_group_index != ogt_groupIdx) { continue; } Log::debug("Found matching group (%u) with scene graph parent: %i", groupIdx, groupId); @@ -345,6 +330,7 @@ void VoxFormat::saveNode(const scenegraph::SceneGraph &sceneGraph, scenegraph::S voxelutil::VisitAll(), voxelutil::VisitorOrder::YZmX); ctx.models.push_back(ogt_model); + ctx.nodeToModel.put(node.id(), (int)ctx.models.size() - 1); } saveInstance(sceneGraph, node, ctx, parentGroupIdx, layerIdx, ctx.models.size() - 1); for (int childId : node.children()) { @@ -370,6 +356,11 @@ bool VoxFormat::saveGroups(const scenegraph::SceneGraph &sceneGraph, const core: MVSceneContext ctx; const scenegraph::SceneGraphNode &root = sceneGraph.root(); saveNode(sceneGraph, sceneGraph.node(root.id()), ctx, k_invalid_group_index, 0); + for (auto iter = sceneGraph.begin(scenegraph::SceneGraphNodeType::ModelReference); iter != sceneGraph.end(); + ++iter) { + // TODO: parentGroupIdx, layerId and modelIdx + saveInstance(sceneGraph, *iter, ctx, 0, 0, 0); + } core::Buffer modelPtr; modelPtr.reserve(ctx.models.size());