@@ -251,6 +251,20 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
251251
252252 S32 skinIdx = nodeno.mSkin ;
253253
254+ // Pre-compute coordinate system rotation matrix (GLTF Y-up to SL Z-up)
255+ static const glm::mat4 coord_system_rotation = glm::rotate (glm::mat4 (1 .0f ), glm::radians (90 .0f ), glm::vec3 (1 .0f , 0 .0f , 0 .0f ));
256+
257+ // Compute final combined transform matrix (hierarchy + coordinate rotation)
258+ S32 node_index = static_cast <S32>(&nodeno - &mGLTFAsset .mNodes [0 ]);
259+ glm::mat4 hierarchy_transform;
260+ computeCombinedNodeTransform (mGLTFAsset , node_index, hierarchy_transform);
261+
262+ // Combine transforms: coordinate rotation applied to hierarchy transform
263+ const glm::mat4 final_transform = coord_system_rotation * hierarchy_transform;
264+
265+ // Pre-compute normal transform matrix (transpose of inverse of upper-left 3x3)
266+ const glm::mat3 normal_transform = glm::transpose (glm::inverse (glm::mat3 (final_transform)));
267+
254268 // Mark unsuported joints with '-1' so that they won't get added into weights
255269 // GLTF maps all joints onto all meshes. Gather use count per mesh to cut unused ones.
256270 std::vector<S32> gltf_joint_index_use_count;
@@ -286,11 +300,9 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
286300 // So primitives already have all of the data we need for a given face in SL land.
287301 // Primitives may only ever have a single material assigned to them - as the relation is 1:1 in terms of intended draw call
288302 // count. Just go ahead and populate faces direct from the GLTF primitives here. -Geenz 2025-04-07
289- LLVolumeFace face;
290- LLVolumeFace::VertexMapData::PointMap point_map;
291-
303+ LLVolumeFace face;
292304 std::vector<GLTFVertex> vertices;
293- std::vector<U16> indices;
305+ std::vector<U16> indices;
294306
295307 LLImportMaterial impMat;
296308 impMat.mDiffuseColor = LLColor4::white; // Default color
@@ -374,32 +386,19 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
374386 }
375387 }
376388
377- // Compute combined transform for this node considering parent hierarchy
378- S32 node_index = static_cast <S32>(&nodeno - &mGLTFAsset .mNodes [0 ]);
379- glm::mat4 combined_transform;
380- computeCombinedNodeTransform (mGLTFAsset , node_index, combined_transform);
381-
382- // Create coordinate system rotation matrix - GLTF is Y-up, SL is Z-up
383- glm::mat4 coord_system_rotation = glm::rotate (glm::mat4 (1 .0f ), glm::radians (90 .0f ), glm::vec3 (1 .0f , 0 .0f , 0 .0f ));
384-
385- // Apply coordinate system rotation to the combined transform
386- combined_transform = coord_system_rotation * combined_transform;
387-
388389 // Apply the global scale and center offset to all vertices
389390 for (U32 i = 0 ; i < prim.getVertexCount (); i++)
390391 {
391- // Transform vertex position with combined hierarchy transform (including coord rotation)
392+ // Use pre-computed final_transform
392393 glm::vec4 pos (prim.mPositions [i][0 ], prim.mPositions [i][1 ], prim.mPositions [i][2 ], 1 .0f );
393- glm::vec4 transformed_pos = combined_transform * pos;
394+ glm::vec4 transformed_pos = final_transform * pos;
394395
395- // Apply scaling and centering after hierarchy transform
396396 GLTFVertex vert;
397- vert.position = glm::vec3 (transformed_pos. x , transformed_pos. y , transformed_pos. z );
397+ vert.position = glm::vec3 (transformed_pos);
398398
399- // Also rotate the normal vector
400- glm::vec4 normal_vec (prim.mNormals [i][0 ], prim.mNormals [i][1 ], prim.mNormals [i][2 ], 0 .0f );
401- glm::vec4 transformed_normal = coord_system_rotation * normal_vec;
402- vert.normal = glm::normalize (glm::vec3 (transformed_normal));
399+ // Use pre-computed normal_transform
400+ glm::vec3 normal_vec (prim.mNormals [i][0 ], prim.mNormals [i][1 ], prim.mNormals [i][2 ]);
401+ vert.normal = glm::normalize (normal_transform * normal_vec);
403402
404403 vert.uv0 = glm::vec2 (prim.mTexCoords0 [i][0 ], -prim.mTexCoords0 [i][1 ]);
405404
@@ -610,19 +609,14 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
610609
611610 if (i < gltf_skin.mInverseBindMatricesData .size ())
612611 {
613- // Process bind matrix
612+ // Use pre-computed coord_system_rotation instead of recreating it
614613 LL::GLTF::mat4 gltf_mat = gltf_skin.mInverseBindMatricesData [i];
615614
616- // For inverse bind matrices, we need to:
617- // 1. Get the original bind matrix by inverting
618- // 2. Apply coordinate rotation to the original
619- // 3. Invert again to get the rotated inverse bind matrix
620615 glm::mat4 original_bind_matrix = glm::inverse (gltf_mat);
621- glm::mat4 coord_rotation = glm::rotate (glm::mat4 (1 .0f ), glm::radians (90 .0f ), glm::vec3 (1 .0f , 0 .0f , 0 .0f ));
622- glm::mat4 rotated_original = coord_rotation * original_bind_matrix;
616+ glm::mat4 rotated_original = coord_system_rotation * original_bind_matrix;
623617 glm::mat4 rotated_inverse_bind_matrix = glm::inverse (rotated_original);
624618
625- LLMatrix4 gltf_transform (glm::value_ptr (rotated_inverse_bind_matrix));
619+ LLMatrix4 gltf_transform = LLMatrix4 (glm::value_ptr (rotated_inverse_bind_matrix));
626620 skin_info.mInvBindMatrix .push_back (LLMatrix4a (gltf_transform));
627621
628622 LL_INFOS (" GLTF_DEBUG" ) << " mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL;
0 commit comments