@@ -76,6 +76,13 @@ static const glm::mat4 coord_system_rotation(
7676);
7777
7878
79+ static const glm::mat4 coord_system_rotationxy (
80+ 0 .f, 1 .f, 0 .f, 0 .f,
81+ -1 .f, 0 .f, 0 .f, 0 .f,
82+ 0 .f, 0 .f, 1 .f, 0 .f,
83+ 0 .f, 0 .f, 0 .f, 1 .f
84+ );
85+
7986LLGLTFLoader::LLGLTFLoader (std::string filename,
8087 S32 lod,
8188 LLModelLoader::load_callback_t load_cb,
@@ -254,6 +261,11 @@ bool LLGLTFLoader::parseMeshes()
254261 node.makeMatrixValid ();
255262 }
256263
264+ if (mGLTFAsset .mSkins .size () > 0 )
265+ {
266+ checkForXYrotation (mGLTFAsset .mSkins [0 ]);
267+ }
268+
257269 // Populate the joints from skins first.
258270 // There's not many skins - and you can pretty easily iterate through the nodes from that.
259271 for (S32 i = 0 ; i < mGLTFAsset .mSkins .size (); i++)
@@ -461,7 +473,11 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
461473 computeCombinedNodeTransform (mGLTFAsset , node_index, hierarchy_transform);
462474
463475 // Combine transforms: coordinate rotation applied to hierarchy transform
464- const glm::mat4 final_transform = coord_system_rotation * hierarchy_transform;
476+ glm::mat4 final_transform = coord_system_rotation * hierarchy_transform;
477+ if (mApplyXYRotation )
478+ {
479+ final_transform = coord_system_rotationxy * final_transform;
480+ }
465481
466482 // Check if we have a negative scale (flipped coordinate system)
467483 bool hasNegativeScale = glm::determinant (final_transform) < 0 .0f ;
@@ -864,6 +880,10 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
864880 // This is very likely incomplete in some way.
865881 // Root shouldn't be the only one to need full coordinate fix
866882 joint_mat = coord_system_rotation * joint_mat;
883+ if (mApplyXYRotation )
884+ {
885+ joint_mat = coord_system_rotationxy * joint_mat;
886+ }
867887 }
868888 LLMatrix4 original_joint_transform (glm::value_ptr (joint_mat));
869889
@@ -1151,9 +1171,73 @@ glm::mat4 LLGLTFLoader::computeGltfToViewerSkeletonTransform(const LL::GLTF::Ski
11511171
11521172 // Compute transformation from GLTF space to viewer space
11531173 // This assumes both skeletons are in rest pose initially
1174+ if (mApplyXYRotation )
1175+ {
1176+ return viewer_joint_rest_pose * glm::inverse (gltf_joint_rest_pose);
1177+ }
11541178 return viewer_joint_rest_pose * glm::inverse (gltf_joint_rest_pose);
11551179}
11561180
1181+ bool LLGLTFLoader::checkForXYrotation (const LL::GLTF::Skin& gltf_skin, S32 joint_idx, S32 bind_indx)
1182+ {
1183+ glm::mat4 gltf_joint_rest = buildGltfRestMatrix (joint_idx, gltf_skin);
1184+ glm::mat4 test_mat = glm::inverse (gltf_joint_rest) * gltf_skin.mInverseBindMatricesData [bind_indx];
1185+ // Normally for shoulders it should be something close to
1186+ // {1,0,0,0;0,-1,0,0;0,0,-1,0;0,0,0,1}
1187+ // rotated one will look like
1188+ // {0,0,0,-1;1,0,0,0;0,-1,0,0;0,0,0,1}
1189+ // Todo: This is a cheap hack,
1190+ // figure out how rotation is supposed to work
1191+ return abs (test_mat[0 ][0 ]) < 0.5 && abs (test_mat[1 ][1 ]) < 0.5 && abs (test_mat[2 ][2 ]) < 0.5 ;
1192+ }
1193+
1194+ void LLGLTFLoader::checkForXYrotation (const LL::GLTF::Skin& gltf_skin)
1195+ {
1196+ // HACK: figure out model's rotation from shoulders' matrix.
1197+ // This is wrong on many levels:
1198+ // Too limited (only models that have shoulders),
1199+ // Will not work well with things that emulate 3 hands in some manner
1200+ // Only supports xy 90 degree rotation
1201+ // Todo: figure out how to find skeleton's orientation Correctly
1202+ // when model is rotated at a triangle level
1203+ constexpr char right_shoulder_str[] = " mShoulderRight" ;
1204+ constexpr char left_shoulder_str[] = " mShoulderLeft" ;
1205+
1206+ S32 size = (S32)gltf_skin.mJoints .size ();
1207+ S32 joints_found = 0 ;
1208+ for (S32 i= 0 ; i < size; i++)
1209+ {
1210+ S32 joint = gltf_skin.mJoints [i];
1211+ auto joint_node = mGLTFAsset .mNodes [joint];
1212+
1213+ // todo: we are doing this search thing everywhere,
1214+ // just pre-translate every joint
1215+ JointMap::iterator found = mJointMap .find (joint_node.mName );
1216+ if (found == mJointMap .end ())
1217+ {
1218+ // unsupported joint
1219+ continue ;
1220+ }
1221+ if (found->second == right_shoulder_str || found->second == left_shoulder_str)
1222+ {
1223+ if (checkForXYrotation (gltf_skin, joint, i))
1224+ {
1225+ joints_found++;
1226+ }
1227+ else
1228+ {
1229+ return ;
1230+ }
1231+ }
1232+ }
1233+
1234+ if (joints_found == 2 )
1235+ {
1236+ // Both joints in a weird position/rotation, assume rotated model
1237+ mApplyXYRotation = true ;
1238+ }
1239+ }
1240+
11571241bool LLGLTFLoader::parseMaterials ()
11581242{
11591243 if (!mGltfLoaded ) return false ;
0 commit comments