Skip to content

Commit 4bbd631

Browse files
committed
#4148 Skeleton Translation #2
1 parent b4fb66c commit 4bbd631

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

indra/newview/gltf/llgltfloader.cpp

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
7986
LLGLTFLoader::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+
11571241
bool LLGLTFLoader::parseMaterials()
11581242
{
11591243
if (!mGltfLoaded) return false;

indra/newview/gltf/llgltfloader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class LLGLTFLoader : public LLModelLoader
156156
bool mGltfLoaded;
157157
bool mMeshesLoaded;
158158
bool mMaterialsLoaded;
159+
bool mApplyXYRotation = false;
159160
U32 mGeneratedModelLimit;
160161

161162
std::vector<gltf_mesh> mMeshes;
@@ -190,6 +191,8 @@ class LLGLTFLoader : public LLModelLoader
190191
S32 findParentNode(S32 node) const;
191192
glm::mat4 buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF::Skin& gltf_skin) const;
192193
glm::mat4 computeGltfToViewerSkeletonTransform(const LL::GLTF::Skin& gltf_skin, S32 joint_index, const std::string& joint_name) const;
194+
bool checkForXYrotation(const LL::GLTF::Skin& gltf_skin, S32 joint_idx, S32 bind_indx);
195+
void checkForXYrotation(const LL::GLTF::Skin& gltf_skin);
193196
LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
194197

195198
void notifyUnsupportedExtension(bool unsupported);

0 commit comments

Comments
 (0)