From 1be630f71eefd689bc2c049ca20a3b5f9e07b9de Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 4 Sep 2024 00:05:57 +0200 Subject: [PATCH] chore: set vertex base index for all surfaces --- src/Common/Game/T6/T6_Assets.h | 2 +- .../Game/T6/XModel/JsonXModelLoader.cpp | 88 ++++++++++--------- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index edb7c063..624217dc 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -590,7 +590,7 @@ namespace T6 float dist; uint16_t numsurfs; uint16_t surfIndex; - int partBits[5]; + unsigned int partBits[5]; }; enum XModelLodRampType : unsigned char diff --git a/src/ObjLoading/Game/T6/XModel/JsonXModelLoader.cpp b/src/ObjLoading/Game/T6/XModel/JsonXModelLoader.cpp index 8fe97020..fc0813ea 100644 --- a/src/ObjLoading/Game/T6/XModel/JsonXModelLoader.cpp +++ b/src/ObjLoading/Game/T6/XModel/JsonXModelLoader.cpp @@ -566,65 +566,58 @@ namespace vertexIndices = std::move(reorderLookup); } - bool CreateXSurface(XSurface& surface, const XModelObject& commonObject, const XModelCommon& common) + bool CreateXSurface(XSurface& surface, const XModelObject& commonObject, const XModelCommon& common, unsigned& vertexOffset) { - std::vector vertexIndices; + std::vector xmodelToCommonVertexIndexLookup; std::unordered_map usedVertices; surface.triCount = static_cast(commonObject.m_faces.size()); - surface.triIndices = m_memory.Alloc(commonObject.m_faces.size()); + surface.triIndices = m_memory.Alloc(surface.triCount); - const auto faceCount = commonObject.m_faces.size(); - for (auto faceIndex = 0u; faceIndex < faceCount; faceIndex++) + for (auto faceIndex = 0u; faceIndex < surface.triCount; faceIndex++) { const auto& face = commonObject.m_faces[faceIndex]; auto& tris = surface.triIndices[faceIndex]; - for (auto faceVertexIndex = 0u; faceVertexIndex < std::extent_v; faceVertexIndex++) + for (auto triVertIndex = 0u; triVertIndex < std::extent_v; triVertIndex++) { - const auto vertexIndex = face.vertexIndex[faceVertexIndex]; - const auto existingVertex = usedVertices.find(vertexIndex); + const auto commonVertexIndex = face.vertexIndex[triVertIndex]; + const auto existingVertex = usedVertices.find(commonVertexIndex); if (existingVertex == usedVertices.end()) { - const auto newVertexIndex = vertexIndices.size(); - tris.i[faceVertexIndex] = static_cast(newVertexIndex); + const auto xmodelVertexIndex = xmodelToCommonVertexIndexLookup.size(); + tris.i[triVertIndex] = static_cast(xmodelVertexIndex); - vertexIndices.emplace_back(vertexIndex); - usedVertices.emplace(vertexIndex, newVertexIndex); + xmodelToCommonVertexIndexLookup.emplace_back(commonVertexIndex); + usedVertices.emplace(commonVertexIndex, xmodelVertexIndex); } else - tris.i[faceVertexIndex] = static_cast(existingVertex->second); + tris.i[triVertIndex] = static_cast(existingVertex->second); } } - ReorderVerticesByWeightCount(vertexIndices, surface, common); + ReorderVerticesByWeightCount(xmodelToCommonVertexIndexLookup, surface, common); - const auto vertexCount = vertexIndices.size(); - surface.vertCount = static_cast(vertexCount); - surface.verts0 = m_memory.Alloc(vertexCount); + surface.baseVertIndex = static_cast(vertexOffset); + surface.vertCount = static_cast(xmodelToCommonVertexIndexLookup.size()); + surface.verts0 = m_memory.Alloc(surface.vertCount); + vertexOffset += surface.vertCount; - for (auto vertexIndex = 0u; vertexIndex < vertexCount; vertexIndex++) + for (auto vertexIndex = 0u; vertexIndex < surface.vertCount; vertexIndex++) { - const auto& commonVertex = common.m_vertices[vertexIndices[vertexIndex]]; + const auto& commonVertex = common.m_vertices[xmodelToCommonVertexIndexLookup[vertexIndex]]; CreateVertex(surface.verts0[vertexIndex], commonVertex); } if (!common.m_bone_weight_data.weights.empty()) { // Since bone weights are sorted by weight count, the last must have the highest weight count - const auto hasVertsBlend = common.m_vertex_bone_weights[vertexIndices[vertexIndices.size() - 1]].weightCount > 1; + const auto hasVertsBlend = + common.m_vertex_bone_weights[xmodelToCommonVertexIndexLookup[xmodelToCommonVertexIndexLookup.size() - 1]].weightCount > 1; if (!hasVertsBlend) - CreateVertListData(surface, vertexIndices, common); + CreateVertListData(surface, xmodelToCommonVertexIndexLookup, common); else - CreateVertsBlendData(surface, vertexIndices, common); - } - - const auto boneCount = common.m_bones.size(); - for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++) - { - const auto partBitsIndex = boneIndex / 32u; - const auto shiftValue = 31u - (boneIndex % 32u); - surface.partBits[partBitsIndex] = 1 << (31u - shiftValue); + CreateVertsBlendData(surface, xmodelToCommonVertexIndexLookup, common); } return true; @@ -677,17 +670,32 @@ namespace materialAssets.push_back(assetInfo->Asset()); } - return std::ranges::all_of(common->m_objects, - [this, &common, &materialAssets](const XModelObject& commonObject) - { - XSurface surface{}; - if (!CreateXSurface(surface, commonObject, *common)) - return false; + auto vertexOffset = 0u; + const auto surfaceCreationSuccessful = std::ranges::all_of(common->m_objects, + [this, &common, &materialAssets, &vertexOffset](const XModelObject& commonObject) + { + XSurface surface{}; + if (!CreateXSurface(surface, commonObject, *common, vertexOffset)) + return false; - m_surfaces.emplace_back(surface); - m_materials.push_back(materialAssets[commonObject.materialIndex]); - return true; - }); + m_surfaces.emplace_back(surface); + m_materials.push_back(materialAssets[commonObject.materialIndex]); + return true; + }); + + if (!surfaceCreationSuccessful) + return false; + + // Lod part bits are the sum of part bits of all of its surfaces + static_assert(std::extent_v == std::extent_v); + for (auto surfaceOffset = 0u; surfaceOffset < lodInfo.numsurfs; surfaceOffset++) + { + const auto& surface = m_surfaces[lodInfo.surfIndex + surfaceOffset]; + for (auto i = 0u; i < std::extent_v; i++) + lodInfo.partBits[i] |= surface.partBits[i]; + } + + return true; } static void CalculateModelBounds(XModel& xmodel)