From 80fa61b45cbd95ddb3c9325b820a1c41ee892877 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 23 Jan 2025 17:09:09 +0000 Subject: [PATCH 1/3] chore: update xmodel dumper code style --- .../XModel/XModelDumper.cpp.template | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/ObjWriting/XModel/XModelDumper.cpp.template b/src/ObjWriting/XModel/XModelDumper.cpp.template index 971e5149..0af964b9 100644 --- a/src/ObjWriting/XModel/XModelDumper.cpp.template +++ b/src/ObjWriting/XModel/XModelDumper.cpp.template @@ -32,7 +32,9 @@ #include #include -namespace GAME +using namespace GAME; + +namespace { std::string GetFileNameForLod(const std::string& modelName, const unsigned lod, const std::string& extension) { @@ -223,10 +225,10 @@ namespace GAME bone.globalOffset[1] = baseMat.trans.y; bone.globalOffset[2] = baseMat.trans.z; bone.globalRotation = { - baseMat.quat.x, - baseMat.quat.y, - baseMat.quat.z, - baseMat.quat.w, + .x = baseMat.quat.x, + .y = baseMat.quat.y, + .z = baseMat.quat.z, + .w = baseMat.quat.w, }; if (boneNum < model->numRootBones) @@ -234,7 +236,7 @@ namespace GAME bone.localOffset[0] = 0; bone.localOffset[1] = 0; bone.localOffset[2] = 0; - bone.localRotation = {0, 0, 0, 1}; + bone.localRotation = {.x = 0, .y = 0, .z = 0, .w = 1}; } else { @@ -245,10 +247,10 @@ namespace GAME const auto& quat = model->quats[boneNum - model->numRootBones]; bone.localRotation = { - QuatInt16::ToFloat(quat.v[0]), - QuatInt16::ToFloat(quat.v[1]), - QuatInt16::ToFloat(quat.v[2]), - QuatInt16::ToFloat(quat.v[3]), + .x = QuatInt16::ToFloat(quat.v[0]), + .y = QuatInt16::ToFloat(quat.v[1]), + .z = QuatInt16::ToFloat(quat.v[2]), + .w = QuatInt16::ToFloat(quat.v[3]), }; } @@ -390,8 +392,8 @@ namespace GAME { const auto& vertList = surface.vertList[vertListIndex]; const auto boneWeightOffset = weightOffset; - - weightCollection.weights[weightOffset++] = XModelBoneWeight{vertList.boneOffset / sizeof(DObjSkelMat), 1.0f}; + + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = vertList.boneOffset / sizeof(DObjSkelMat), .weight = 1.0f}; for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++) { @@ -409,7 +411,7 @@ namespace GAME { const auto boneWeightOffset = weightOffset; const auto boneIndex0 = surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat); - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, 1.0f}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex0, .weight = 1.0f}; vertsBlendOffset += 1; @@ -424,9 +426,9 @@ namespace GAME const auto boneIndex1 = surface.vertInfo.vertsBlend[vertsBlendOffset + 1] / sizeof(DObjSkelMat); const auto boneWeight1 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]); const auto boneWeight0 = 1.0f - boneWeight1; - - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0}; - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex1, boneWeight1}; + + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex0, .weight = boneWeight0}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex1, .weight = boneWeight1}; vertsBlendOffset += 3; @@ -443,10 +445,10 @@ namespace GAME const auto boneIndex2 = surface.vertInfo.vertsBlend[vertsBlendOffset + 3] / sizeof(DObjSkelMat); const auto boneWeight2 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]); const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2; - - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0}; - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex1, boneWeight1}; - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex2, boneWeight2}; + + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex0, .weight = boneWeight0}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex1, .weight = boneWeight1}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex2, .weight = boneWeight2}; vertsBlendOffset += 5; @@ -465,11 +467,11 @@ namespace GAME const auto boneIndex3 = surface.vertInfo.vertsBlend[vertsBlendOffset + 5] / sizeof(DObjSkelMat); const auto boneWeight3 = BoneWeight16(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]); const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3; - - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0}; - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex1, boneWeight1}; - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex2, boneWeight2}; - weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex3, boneWeight3}; + + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex0, .weight = boneWeight0}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex1, .weight = boneWeight1}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex2, .weight = boneWeight2}; + weightCollection.weights[weightOffset++] = XModelBoneWeight{.boneIndex = boneIndex3, .weight = boneWeight3}; vertsBlendOffset += 7; @@ -724,7 +726,10 @@ namespace GAME const JsonDumper dumper(context, *assetFile); dumper.Dump(asset->Asset()); } +} // namespace +namespace GAME +{ void DumpXModel(AssetDumpingContext& context, XAssetInfo* asset) { DumpXModelJson(context, asset); From 708e759f8c35b2feb5487ac9e25ad96a8c21335a Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 23 Jan 2025 17:23:33 +0000 Subject: [PATCH 2/3] chore: update code style of gltf writer --- src/ObjWriting/XModel/Gltf/GltfWriter.cpp | 24 +++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/ObjWriting/XModel/Gltf/GltfWriter.cpp b/src/ObjWriting/XModel/Gltf/GltfWriter.cpp index 8d1017f5..b0a569c1 100644 --- a/src/ObjWriting/XModel/Gltf/GltfWriter.cpp +++ b/src/ObjWriting/XModel/Gltf/GltfWriter.cpp @@ -8,6 +8,7 @@ #include #pragma warning(pop) +#include #include using namespace gltf; @@ -131,8 +132,7 @@ namespace { JsonMeshPrimitives primitives; - if (object.materialIndex >= 0) - primitives.material = static_cast(object.materialIndex); + primitives.material = object.materialIndex; primitives.attributes.POSITION = m_position_accessor; primitives.attributes.NORMAL = m_normal_accessor; @@ -466,18 +466,12 @@ namespace vertex->coordinates[1] = commonVertex.coordinates[2]; vertex->coordinates[2] = -commonVertex.coordinates[1]; - if (minPosition[0] > vertex->coordinates[0]) - minPosition[0] = vertex->coordinates[0]; - if (minPosition[1] > vertex->coordinates[1]) - minPosition[1] = vertex->coordinates[1]; - if (minPosition[2] > vertex->coordinates[2]) - minPosition[2] = vertex->coordinates[2]; - if (maxPosition[0] < vertex->coordinates[0]) - maxPosition[0] = vertex->coordinates[0]; - if (maxPosition[1] < vertex->coordinates[1]) - maxPosition[1] = vertex->coordinates[1]; - if (maxPosition[2] < vertex->coordinates[2]) - maxPosition[2] = vertex->coordinates[2]; + minPosition[0] = std::min(minPosition[0], vertex->coordinates[0]); + minPosition[1] = std::min(minPosition[1], vertex->coordinates[1]); + minPosition[2] = std::min(minPosition[2], vertex->coordinates[2]); + maxPosition[0] = std::max(maxPosition[0], vertex->coordinates[0]); + maxPosition[1] = std::max(maxPosition[1], vertex->coordinates[1]); + maxPosition[2] = std::max(maxPosition[2], vertex->coordinates[2]); vertex->normal[0] = commonVertex.normal[0]; vertex->normal[1] = commonVertex.normal[2]; @@ -499,7 +493,7 @@ namespace { assert(xmodel.m_vertex_bone_weights.size() == xmodel.m_vertices.size()); - auto* joints = reinterpret_cast(&bufferData[currentBufferOffset]); + auto* joints = &bufferData[currentBufferOffset]; auto* weights = reinterpret_cast(&bufferData[currentBufferOffset + sizeof(uint8_t) * 4u * xmodel.m_vertex_bone_weights.size()]); for (const auto& commonVertexWeights : xmodel.m_vertex_bone_weights) { From 140eb7b7a4e1ae01e1d6c5b16ae5435ae0670572 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 23 Jan 2025 17:46:33 +0000 Subject: [PATCH 3/3] feat: dump objects into gltf meshes instead of primitives --- src/ObjWriting/XModel/Gltf/GltfWriter.cpp | 67 +++++++++++++---------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/src/ObjWriting/XModel/Gltf/GltfWriter.cpp b/src/ObjWriting/XModel/Gltf/GltfWriter.cpp index b0a569c1..18eaf323 100644 --- a/src/ObjWriting/XModel/Gltf/GltfWriter.cpp +++ b/src/ObjWriting/XModel/Gltf/GltfWriter.cpp @@ -42,13 +42,13 @@ namespace CreateJsonAsset(gltf.asset); CreateSkeletonNodes(gltf, xmodel); - CreateMeshNode(gltf, xmodel); + CreateMeshNodes(gltf, xmodel); CreateRootNode(gltf, xmodel); CreateMaterials(gltf, xmodel); CreateBufferViews(gltf, xmodel); CreateAccessors(gltf, xmodel); CreateSkin(gltf, xmodel); - CreateMesh(gltf, xmodel); + CreateMeshes(gltf, xmodel); CreateScene(gltf, xmodel); FillBufferData(gltf, xmodel, bufferData); CreateBuffer(gltf, xmodel, bufferData); @@ -69,39 +69,44 @@ namespace asset.generator = GLTF_GENERATOR; } - void CreateMeshNode(JsonRoot& gltf, const XModelCommon& xmodel) + void CreateMeshNodes(JsonRoot& gltf, const XModelCommon& xmodel) { - JsonNode meshNode; - - if (!xmodel.m_name.empty()) - meshNode.name = xmodel.m_name; - - // We only have one mesh - meshNode.mesh = 0u; - - // Only add skin if the model has bones - if (!xmodel.m_bones.empty()) - { - // We only have one skin - meshNode.skin = 0u; - } - if (!gltf.nodes.has_value()) gltf.nodes.emplace(); - m_mesh_node = gltf.nodes->size(); + m_first_mesh_node = gltf.nodes->size(); - if (xmodel.m_bones.empty()) - m_root_node = m_mesh_node; + auto meshIndex = 0u; + for (const auto& object : xmodel.m_objects) + { + JsonNode meshNode; - gltf.nodes->emplace_back(std::move(meshNode)); + if (!object.name.empty()) + meshNode.name = object.name; + + meshNode.mesh = meshIndex++; + + // Only add skin if the model has bones + if (!xmodel.m_bones.empty()) + { + // We only have one skin + meshNode.skin = 0u; + } + + gltf.nodes->emplace_back(std::move(meshNode)); + } + + // If we only have one mesh and no bones we don't need a dedicated root node + if (xmodel.m_bones.empty() && xmodel.m_objects.size() == 1) + m_root_node = m_first_mesh_node; } void CreateRootNode(JsonRoot& gltf, const XModelCommon& xmodel) { JsonNode rootNode; - if (xmodel.m_bones.empty()) + // If we have at most one mesh and no bones we don't need a dedicated root node + if (xmodel.m_bones.empty() && xmodel.m_objects.size() <= 1) return; if (!xmodel.m_name.empty()) @@ -111,25 +116,28 @@ namespace gltf.nodes.emplace(); rootNode.children.emplace(); - rootNode.children->push_back(m_mesh_node); + + const auto meshCount = xmodel.m_objects.size(); + for (auto meshIndex = 0u; meshIndex < meshCount; meshIndex++) + rootNode.children->push_back(m_first_mesh_node + meshIndex); + rootNode.children->push_back(m_first_bone_node); m_root_node = gltf.nodes->size(); gltf.nodes->emplace_back(std::move(rootNode)); } - void CreateMesh(JsonRoot& gltf, const XModelCommon& xmodel) + void CreateMeshes(JsonRoot& gltf, const XModelCommon& xmodel) { if (!gltf.meshes.has_value()) gltf.meshes.emplace(); - JsonMesh mesh; - const auto hasBoneWeightData = !xmodel.m_bone_weight_data.weights.empty(); auto objectIndex = 0u; for (const auto& object : xmodel.m_objects) { + JsonMesh mesh; JsonMeshPrimitives primitives; primitives.material = object.materialIndex; @@ -149,9 +157,8 @@ namespace mesh.primitives.emplace_back(primitives); objectIndex++; + gltf.meshes->emplace_back(std::move(mesh)); } - - gltf.meshes->emplace_back(std::move(mesh)); } static void CreateMaterials(JsonRoot& gltf, const XModelCommon& xmodel) @@ -604,7 +611,7 @@ namespace gltf.buffers->emplace_back(std::move(jsonBuffer)); } - unsigned m_mesh_node = 0u; + unsigned m_first_mesh_node = 0u; unsigned m_root_node = 0u; unsigned m_first_bone_node = 0u; unsigned m_position_accessor = 0u;