Browse Source

Add support to pad skinned mesh buffers for the Skinning sample (#635)

* Add support to pad skinned mesh buffers for the Features/Skinning sample in order to make it compliant for Metal back end

Signed-off-by: moudgils <[email protected]>

* Minor removal of a header file

Signed-off-by: moudgils <[email protected]>

* Fixed a crash related to updating various sliders in the sample

Signed-off-by: moudgils <[email protected]>

* Address feedback

Signed-off-by: moudgils <[email protected]>

---------

Signed-off-by: moudgils <[email protected]>
moudgils 2 years ago
parent
commit
cb7060732e

+ 50 - 20
Gem/Code/Source/ProceduralSkinnedMesh.cpp

@@ -9,6 +9,7 @@
 #include <ProceduralSkinnedMesh.h>
 
 #include <AzCore/Math/MathUtils.h>
+#include <Atom/RPI.Reflect/Model/ModelAssetHelpers.h>
 
 const uint32_t maxInfluencesPerVertex = 4;
 
@@ -19,6 +20,11 @@ namespace AtomSampleViewer
         m_verticesPerSegment = skinnedMeshConfig.m_verticesPerSegment;
         m_segmentCount = static_cast<uint32_t>(skinnedMeshConfig.m_segmentCount);
         m_vertexCount = m_segmentCount * m_verticesPerSegment;
+
+        m_alignedVertCountForRGBStream = aznumeric_cast<uint32_t>(RPI::ModelAssetHelpers::GetAlignedCount<float>(m_vertexCount, RHI::Format::R32G32B32_FLOAT, RPI::SkinnedMeshBufferAlignment));
+
+        m_alignedVertCountForRGBAStream = aznumeric_cast<uint32_t>(RPI::ModelAssetHelpers::GetAlignedCount<float>(m_vertexCount, RHI::Format::R32G32B32A32_FLOAT, RPI::SkinnedMeshBufferAlignment));
+        
         m_boneCount = AZ::GetMax(1u, static_cast<uint32_t>(skinnedMeshConfig.m_boneCount));
         m_influencesPerVertex = AZ::GetMax(0u, AZ::GetMin(static_cast<uint32_t>(skinnedMeshConfig.m_influencesPerVertex), AZ::GetMin(m_boneCount, maxInfluencesPerVertex)));
         m_subMeshCount = skinnedMeshConfig.m_subMeshCount;
@@ -130,13 +136,21 @@ namespace AtomSampleViewer
             }
         }
 
-        m_positions.resize(m_vertexCount);
-        m_normals.resize(m_vertexCount);
-        m_tangents.resize(m_vertexCount);
-        m_bitangents.resize(m_vertexCount);
-        // We pack 16 bit joint id's into 32 bit uints, so use half the number of joints for the uint count
-        m_blendIndices.resize(m_vertexCount * m_influencesPerVertex / 2);
-        m_blendWeights.resize(m_vertexCount * m_influencesPerVertex);
+        m_positions.resize(m_alignedVertCountForRGBStream);
+        m_normals.resize(m_alignedVertCountForRGBStream);
+        m_bitangents.resize(m_alignedVertCountForRGBStream);
+        
+        size_t alignedTangentVertCount = RPI::ModelAssetHelpers::GetAlignedCount<float>(m_vertexCount, RPI::TangentFormat, RPI::SkinnedMeshBufferAlignment);
+        m_tangents.resize(alignedTangentVertCount);
+        
+        // We pack 16 bit joint id's into 32 bit uints.
+        uint32_t numVertInfluences = m_vertexCount * m_influencesPerVertex;
+        size_t alignedIndicesVertCount = RPI::ModelAssetHelpers::GetAlignedCount<uint32_t>(numVertInfluences, RPI::SkinIndicesFormat, RPI::SkinnedMeshBufferAlignment);
+        m_blendIndices.resize(alignedIndicesVertCount);
+
+        size_t alignedWeightsVertCount = RPI::ModelAssetHelpers::GetAlignedCount<float>(numVertInfluences, RPI::SkinWeightFormat, RPI::SkinnedMeshBufferAlignment);
+        m_blendWeights.resize(alignedWeightsVertCount);
+
         m_uvs.resize(m_vertexCount);
 
         for (uint32_t vertexIndex = 0; vertexIndex < m_vertexCount; ++vertexIndex)
@@ -147,19 +161,19 @@ namespace AtomSampleViewer
 
             // Get the x and y positions from a unit circle
             float vertexAngle = (AZ::Constants::TwoPi / static_cast<float>(m_verticesPerSegment - 1)) * static_cast<float>(indexWithinTheCurrentSegment);
-            m_positions[vertexIndex][0] = cosf(vertexAngle) * m_radius;
-            m_positions[vertexIndex][1] = sinf(vertexAngle) * m_radius;
-            m_positions[vertexIndex][2] = m_segmentHeightOffsets[segmentIndex];
+            m_positions[(vertexIndex * RPI::PositionFloatsPerVert) + 0] = cosf(vertexAngle) * m_radius;
+            m_positions[(vertexIndex * RPI::PositionFloatsPerVert) + 1] = sinf(vertexAngle) * m_radius;
+            m_positions[(vertexIndex * RPI::PositionFloatsPerVert) + 2] = m_segmentHeightOffsets[segmentIndex];
 
             // Normals are flat on the z-plane and point away from the origin in the direction of the vertex position
-            m_normals[vertexIndex][0] = m_positions[vertexIndex][0];
-            m_normals[vertexIndex][1] = m_positions[vertexIndex][1];
-            m_normals[vertexIndex][2] = 0.0f;
+            m_normals[(vertexIndex * RPI::PositionFloatsPerVert) + 0] = m_positions[(vertexIndex * RPI::PositionFloatsPerVert) + 0];
+            m_normals[(vertexIndex * RPI::PositionFloatsPerVert) + 1] = m_positions[(vertexIndex * RPI::PositionFloatsPerVert) + 1];
+            m_normals[(vertexIndex * RPI::PositionFloatsPerVert) + 2] = 0.0f;
 
             // Bitangent is straight down
-            m_bitangents[vertexIndex][0] = 0.0f;
-            m_bitangents[vertexIndex][1] = 0.0f;
-            m_bitangents[vertexIndex][2] = -1.0f;
+            m_bitangents[(vertexIndex * RPI::PositionFloatsPerVert)+0] = 0.0f;
+            m_bitangents[(vertexIndex * RPI::PositionFloatsPerVert)+1] = 0.0f;
+            m_bitangents[(vertexIndex * RPI::PositionFloatsPerVert)+2] = -1.0f;
 
             for (size_t i = 0; i < m_influencesPerVertex; ++i)
             {
@@ -200,10 +214,11 @@ namespace AtomSampleViewer
             uint32_t leftVertex = vertexIndex;
             // The last vertex of the segment will have the first vertex of the segment as its neighbor, not just the next vertex (which would be in the next segment)
             uint32_t rightVertex = (leftVertex + 1) % m_verticesPerSegment;
-            m_tangents[vertexIndex][0] = m_positions[leftVertex][0] - m_positions[rightVertex][0];
-            m_tangents[vertexIndex][1] = m_positions[leftVertex][1] - m_positions[rightVertex][1];
-            m_tangents[vertexIndex][2] = 0.0f;
-            m_tangents[vertexIndex][3] = 1.0f;
+            m_tangents[(vertexIndex * RPI::TangentFloatsPerVert)+0] = m_positions[(leftVertex * RPI::PositionFloatsPerVert) + 0] - m_positions[(rightVertex * RPI::PositionFloatsPerVert)+0];
+            m_tangents[(vertexIndex * RPI::TangentFloatsPerVert)+1] = m_positions[(leftVertex * RPI::PositionFloatsPerVert) + 1] - m_positions[(rightVertex * RPI::PositionFloatsPerVert)+1];
+
+            m_tangents[(vertexIndex * RPI::TangentFloatsPerVert)+2] = 0.0f;
+            m_tangents[(vertexIndex * RPI::TangentFloatsPerVert)+3] = 1.0f;
         }
     }
 
@@ -337,4 +352,19 @@ namespace AtomSampleViewer
             m_segmentHeightOffsets[segmentIndex] = currentSegmentHeight - heightOffset;
         }
     }
+
+    uint32_t ProceduralSkinnedMesh::GetVertexCount() const
+    {
+        return m_vertexCount;
+    }
+
+    uint32_t ProceduralSkinnedMesh::GetAlignedVertCountForRGBStream() const
+    {
+        return m_alignedVertCountForRGBStream;
+    }
+
+    uint32_t ProceduralSkinnedMesh::GetAlignedVertCountForRGBAStream() const
+    {
+        return m_alignedVertCountForRGBAStream;
+    }
 }

+ 9 - 4
Gem/Code/Source/ProceduralSkinnedMesh.h

@@ -36,15 +36,18 @@ namespace AtomSampleViewer
         uint32_t GetSubMeshCount() const;
         float GetSubMeshYOffset() const;
 
+        uint32_t GetVertexCount() const;
+        uint32_t GetAlignedVertCountForRGBStream() const;
+        uint32_t GetAlignedVertCountForRGBAStream() const;
         static const uint32_t MaxInfluencesPerVertex = 4;
 
         // Mesh data that's used for rendering
         AZ::Aabb m_aabb = AZ::Aabb::CreateNull();
         AZStd::vector<uint32_t> m_indices;
-        AZStd::vector< AZStd::array<float, 3>> m_positions;
-        AZStd::vector< AZStd::array<float, 3>> m_normals;
-        AZStd::vector< AZStd::array<float, 4>> m_tangents;
-        AZStd::vector< AZStd::array<float, 3>> m_bitangents;
+        AZStd::vector<float> m_positions;
+        AZStd::vector<float> m_normals;
+        AZStd::vector<float> m_tangents;
+        AZStd::vector<float> m_bitangents;
         AZStd::vector<uint32_t> m_blendIndices;
         AZStd::vector<float> m_blendWeights;
         AZStd::vector<AZStd::array<float, 2>> m_uvs;
@@ -64,6 +67,8 @@ namespace AtomSampleViewer
 
         uint32_t m_boneCount = 0;
         uint32_t m_vertexCount = 0;
+        uint32_t m_alignedVertCountForRGBStream = 0;
+        uint32_t m_alignedVertCountForRGBAStream = 0;
         uint32_t m_verticesPerSegment = 0;
         uint32_t m_segmentCount = 0;
         uint32_t m_influencesPerVertex = 0;

+ 49 - 38
Gem/Code/Source/ProceduralSkinnedMeshUtils.cpp

@@ -99,51 +99,53 @@ namespace AtomSampleViewer
         modelCreator.SetName(AZStd::string("ProceduralSkinnedMesh_" + assetId.m_guid.ToString<AZStd::string>()));
 
         uint32_t submeshCount = proceduralMesh.GetSubMeshCount();
-        uint32_t verticesPerSubmesh = aznumeric_caster(proceduralMesh.m_positions.size());
+        uint32_t verticesPerSubmesh = proceduralMesh.GetVertexCount();
         uint32_t totalVertices = verticesPerSubmesh * submeshCount;
 
-        uint32_t jointIdCountPerSubmesh = verticesPerSubmesh * proceduralMesh.GetInfluencesPerVertex();
-        uint32_t extraJointIdCount = AZ::RPI::CalculateJointIdPaddingCount(jointIdCountPerSubmesh);
-        uint32_t extraPackedIdCount = extraJointIdCount / 2;
-
         // Copy the original buffer data n-times to create the data for extra sub-meshes
         DuplicateVertices(proceduralMesh.m_indices, aznumeric_caster(proceduralMesh.m_indices.size()), submeshCount);
-        DuplicateVertices(proceduralMesh.m_positions, verticesPerSubmesh, submeshCount);
-        DuplicateVertices(proceduralMesh.m_normals, verticesPerSubmesh, submeshCount);
-        DuplicateVertices(proceduralMesh.m_tangents, verticesPerSubmesh, submeshCount);
-        DuplicateVertices(proceduralMesh.m_bitangents, verticesPerSubmesh, submeshCount);
-        DuplicateVertices(proceduralMesh.m_uvs, verticesPerSubmesh, submeshCount);
-        DuplicateVertices(proceduralMesh.m_blendWeights, verticesPerSubmesh * proceduralMesh.GetInfluencesPerVertex(), submeshCount);
+        DuplicateVertices(proceduralMesh.m_positions, proceduralMesh.GetAlignedVertCountForRGBStream(), submeshCount);
+        DuplicateVertices(proceduralMesh.m_normals, proceduralMesh.GetAlignedVertCountForRGBStream(), submeshCount);
+        DuplicateVertices(proceduralMesh.m_bitangents, proceduralMesh.GetAlignedVertCountForRGBStream(), submeshCount);
+        
+        size_t alignedTangentVertCount = RPI::ModelAssetHelpers::GetAlignedCount<float>(verticesPerSubmesh, RPI::TangentFormat, RPI::SkinnedMeshBufferAlignment);
+        DuplicateVertices(proceduralMesh.m_tangents, aznumeric_cast<uint32_t>(alignedTangentVertCount), submeshCount);
 
-        // Insert the jointId padding first before duplicating
-        AZStd::vector<uint32_t> extraIds(extraPackedIdCount, 0);
+        DuplicateVertices(proceduralMesh.m_uvs, verticesPerSubmesh, submeshCount);
 
-        // Track the count of 32-byte 'elements' (packed) and offsets for creating sub-mesh views
-        uint32_t jointIdElementCountPerSubmesh = aznumeric_caster(proceduralMesh.m_blendIndices.size());
-        uint32_t jointIdOffsetElementsPerSubmesh = jointIdElementCountPerSubmesh + extraPackedIdCount;
+        uint32_t numBlendWeights = verticesPerSubmesh * proceduralMesh.GetInfluencesPerVertex();
+        size_t alignedWeightsVertCount = RPI::ModelAssetHelpers::GetAlignedCount<float>(numBlendWeights, RPI::SkinWeightFormat, RPI::SkinnedMeshBufferAlignment);
+        DuplicateVertices(proceduralMesh.m_blendWeights, aznumeric_cast<uint32_t>(alignedWeightsVertCount), submeshCount);
 
-        proceduralMesh.m_blendIndices.insert(proceduralMesh.m_blendIndices.end(), extraIds.begin(), extraIds.end());
-        DuplicateVertices(
-            proceduralMesh.m_blendIndices, aznumeric_caster(proceduralMesh.m_blendIndices.size()), submeshCount);
+        uint32_t numBlendIndices = verticesPerSubmesh * proceduralMesh.GetInfluencesPerVertex();
+        size_t alignedIndicesVertCount = RPI::ModelAssetHelpers::GetAlignedCount<uint32_t>(numBlendIndices, RPI::SkinIndicesFormat, RPI::SkinnedMeshBufferAlignment);
+        DuplicateVertices(proceduralMesh.m_blendIndices, aznumeric_cast<uint32_t>(alignedIndicesVertCount), submeshCount);
 
         // Offset duplicate positions in the +y direction, so each sub-mesh ends up in a unique position
         for (uint32_t subMeshIndex = 1; subMeshIndex < submeshCount; ++subMeshIndex)
         {
-            for (uint32_t i = 0; i < verticesPerSubmesh; ++i)
+            for (uint32_t i = 0; i < proceduralMesh.GetVertexCount(); i ++)
             {
-                proceduralMesh.m_positions[subMeshIndex*verticesPerSubmesh + i][1] +=
-                    aznumeric_cast<float>(subMeshIndex) * proceduralMesh.GetSubMeshYOffset();
+                uint32_t yPosPerSubMesh = (proceduralMesh.GetAlignedVertCountForRGBStream() * subMeshIndex) + (i*3) + 1;
+                proceduralMesh.m_positions[yPosPerSubMesh] +=
+                        aznumeric_cast<float>(subMeshIndex) * proceduralMesh.GetSubMeshYOffset();
             }
         }
 
+        size_t positionStreamSize = proceduralMesh.m_positions.size() / RHI::GetFormatComponentCount(RPI::PositionFormat);
+        size_t normalStreamSize = proceduralMesh.m_normals.size() / RHI::GetFormatComponentCount(RPI::NormalFormat);
+        size_t tangentStreamSize = proceduralMesh.m_tangents.size() / RHI::GetFormatComponentCount(RPI::TangentFormat);
+        size_t bitangentStreamSize = proceduralMesh.m_bitangents.size() / RHI::GetFormatComponentCount(RPI::BitangentFormat);
+        
         auto indexBuffer = CreateTypedBufferAsset(proceduralMesh.m_indices.data(), proceduralMesh.m_indices.size(), AZ::RHI::Format::R32_FLOAT);
-        auto positionBuffer = CreateTypedBufferAsset(proceduralMesh.m_positions.data(), proceduralMesh.m_positions.size(), AZ::RHI::Format::R32G32B32_FLOAT);
-        auto normalBuffer = CreateTypedBufferAsset(proceduralMesh.m_normals.data(), proceduralMesh.m_normals.size(), AZ::RHI::Format::R32G32B32_FLOAT);
-        auto tangentBuffer = CreateTypedBufferAsset(proceduralMesh.m_tangents.data(), proceduralMesh.m_tangents.size(), AZ::RHI::Format::R32G32B32A32_FLOAT);
-        auto bitangentBuffer = CreateTypedBufferAsset(proceduralMesh.m_bitangents.data(), proceduralMesh.m_bitangents.size(), AZ::RHI::Format::R32G32B32_FLOAT);
-        auto uvBuffer = CreateTypedBufferAsset(proceduralMesh.m_uvs.data(), proceduralMesh.m_uvs.size(), AZ::RHI::Format::R32G32_FLOAT);
+        
+        auto positionBuffer = CreateTypedBufferAsset(proceduralMesh.m_positions.data(), positionStreamSize, RPI::PositionFormat);
+        auto normalBuffer = CreateTypedBufferAsset(proceduralMesh.m_normals.data(), normalStreamSize, RPI::NormalFormat);
+        auto tangentBuffer = CreateTypedBufferAsset(proceduralMesh.m_tangents.data(), tangentStreamSize, RPI::TangentFormat);
+        auto bitangentBuffer = CreateTypedBufferAsset(proceduralMesh.m_bitangents.data(), bitangentStreamSize, RPI::BitangentFormat);
+        auto uvBuffer = CreateTypedBufferAsset(proceduralMesh.m_uvs.data(), proceduralMesh.m_uvs.size(), RPI::UVFormat);
         auto skinJointIdBuffer = CreateRawBufferAsset(proceduralMesh.m_blendIndices.data(), proceduralMesh.m_blendIndices.size(), sizeof(proceduralMesh.m_blendIndices[0]));
-        auto skinJointWeightBuffer = CreateTypedBufferAsset(proceduralMesh.m_blendWeights.data(), proceduralMesh.m_blendWeights.size(), AZ::RHI::Format::R32_FLOAT);
+        auto skinJointWeightBuffer = CreateTypedBufferAsset(proceduralMesh.m_blendWeights.data(), proceduralMesh.m_blendWeights.size(), RPI::SkinWeightFormat);
 
         //
         // Lod
@@ -183,6 +185,8 @@ namespace AtomSampleViewer
             // Get the element count and offset for this sub-mesh
             uint32_t elementCount = verticesPerSubmesh;
             uint32_t elementOffset = verticesPerSubmesh * submeshIndex;
+            uint32_t alignedRGBElementOffset = (proceduralMesh.GetAlignedVertCountForRGBStream()/RHI::GetFormatComponentCount(RHI::Format::R32G32B32_FLOAT)) * submeshIndex;
+            uint32_t alignedRGBAElementOffset = (proceduralMesh.GetAlignedVertCountForRGBAStream()/RHI::GetFormatComponentCount(RHI::Format::R32G32B32A32_FLOAT)) * submeshIndex;
 
             // Include any truncated vertices if this is the last mesh
             if (submeshIndex == submeshCount - 1)
@@ -190,17 +194,24 @@ namespace AtomSampleViewer
                 elementCount += totalVertices % verticesPerSubmesh;
             }
 
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "POSITION" }, AZ::Name(), AZ::RPI::BufferAssetView{ positionBuffer, CreateSubmeshBufferViewDescriptor(positionBuffer, elementCount, elementOffset) });
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "NORMAL" }, AZ::Name(), AZ::RPI::BufferAssetView{ normalBuffer, CreateSubmeshBufferViewDescriptor(normalBuffer, elementCount, elementOffset) });
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "TANGENT" }, AZ::Name(), AZ::RPI::BufferAssetView{ tangentBuffer, CreateSubmeshBufferViewDescriptor(tangentBuffer, elementCount, elementOffset) });
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "BITANGENT" }, AZ::Name(), AZ::RPI::BufferAssetView{ bitangentBuffer, CreateSubmeshBufferViewDescriptor(bitangentBuffer, elementCount, elementOffset) });
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "UV" }, AZ::Name(), AZ::RPI::BufferAssetView{ uvBuffer, CreateSubmeshBufferViewDescriptor(uvBuffer, elementCount, elementOffset) });
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "SKIN_JOINTINDICES" }, AZ::Name(), AZ::RPI::BufferAssetView{ skinJointIdBuffer, CreateSubmeshBufferViewDescriptor(skinJointIdBuffer, jointIdElementCountPerSubmesh, jointIdOffsetElementsPerSubmesh * submeshIndex) });
-
-            uint32_t jointWeightElementCount = elementCount * proceduralMesh.GetInfluencesPerVertex();
-            uint32_t jointWeightOffset = elementOffset * proceduralMesh.GetInfluencesPerVertex();
-            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "SKIN_WEIGHTS" }, AZ::Name(), AZ::RPI::BufferAssetView{ skinJointWeightBuffer, CreateSubmeshBufferViewDescriptor(skinJointWeightBuffer, jointWeightElementCount, jointWeightOffset) });
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "POSITION" }, AZ::Name(), AZ::RPI::BufferAssetView{ positionBuffer, CreateSubmeshBufferViewDescriptor(positionBuffer, elementCount, alignedRGBElementOffset) });
+            
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "NORMAL" }, AZ::Name(), AZ::RPI::BufferAssetView{ normalBuffer, CreateSubmeshBufferViewDescriptor(normalBuffer, elementCount, alignedRGBElementOffset) });
+ 
 
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "TANGENT" }, AZ::Name(), AZ::RPI::BufferAssetView{ tangentBuffer, CreateSubmeshBufferViewDescriptor(tangentBuffer, elementCount, alignedRGBAElementOffset) });
+                        
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "BITANGENT" }, AZ::Name(), AZ::RPI::BufferAssetView{ bitangentBuffer, CreateSubmeshBufferViewDescriptor(bitangentBuffer, elementCount, alignedRGBElementOffset) });
+            
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "UV" }, AZ::Name(), AZ::RPI::BufferAssetView{ uvBuffer, CreateSubmeshBufferViewDescriptor(uvBuffer, elementCount, elementOffset) });
+            
+            //Divide by 2 as we are storing 16bit data into 32bit integers
+            uint32_t numIndices = numBlendIndices/2;
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "SKIN_JOINTINDICES" }, AZ::Name(), AZ::RPI::BufferAssetView{ skinJointIdBuffer, CreateSubmeshBufferViewDescriptor(skinJointIdBuffer, numIndices, aznumeric_cast<uint32_t>(alignedIndicesVertCount) * submeshIndex) });
+            
+            uint32_t jointWeightOffset = aznumeric_cast<uint32_t>(alignedWeightsVertCount) * submeshIndex;
+            modelLodCreator.AddMeshStreamBuffer(RHI::ShaderSemantic{ "SKIN_WEIGHTS" }, AZ::Name(), AZ::RPI::BufferAssetView{ skinJointWeightBuffer, CreateSubmeshBufferViewDescriptor(skinJointWeightBuffer, numBlendWeights, jointWeightOffset) });
+            
             AZ::Aabb localAabb = proceduralMesh.m_aabb;
             modelLodCreator.SetMeshAabb(AZStd::move(localAabb));