Skip to content

Commit 49b52e9

Browse files
author
Vito Tringolo
committed
Fix GLTF animations
1 parent 37205bb commit 49b52e9

File tree

2 files changed

+73
-26
lines changed

2 files changed

+73
-26
lines changed

src/raymath.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2525,4 +2525,54 @@ RMAPI int QuaternionEquals(Quaternion p, Quaternion q)
25252525
return result;
25262526
}
25272527

2528+
// Decompose a transformation matrix into its rotational, translational and scaling components
2529+
RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotation, Vector3 *scale)
2530+
{
2531+
// Extract translation.
2532+
translation->x = mat.m12;
2533+
translation->y = mat.m13;
2534+
translation->z = mat.m14;
2535+
2536+
// Extract upper-left for determinant computation.
2537+
const float a = mat.m0;
2538+
const float b = mat.m4;
2539+
const float c = mat.m8;
2540+
const float d = mat.m1;
2541+
const float e = mat.m5;
2542+
const float f = mat.m9;
2543+
const float g = mat.m2;
2544+
const float h = mat.m6;
2545+
const float i = mat.m10;
2546+
const float A = e * i - f * h;
2547+
const float B = f * g - d * i;
2548+
const float C = d * h - e * g;
2549+
2550+
// Extract scale.
2551+
const float det = a * A + b * B + c * C;
2552+
float scalex = Vector3Length((Vector3) {a, b, c});
2553+
float scaley = Vector3Length((Vector3) {d, e, f});
2554+
float scalez = Vector3Length((Vector3) {g, h, i});
2555+
Vector3 s = {scalex, scaley, scalez};
2556+
2557+
if (det < 0) s = Vector3Negate(s);
2558+
2559+
*scale = s;
2560+
2561+
// Remove scale from the matrix if it is not close to zero.
2562+
Matrix clone = mat;
2563+
if (!FloatEquals(det, 0))
2564+
{
2565+
clone.m0 /= s.x;
2566+
clone.m5 /= s.y;
2567+
clone.m10 /= s.z;
2568+
// Extract rotation
2569+
*rotation = QuaternionFromMatrix(clone);
2570+
}
2571+
else
2572+
{
2573+
// Set to identity if close to zero
2574+
*rotation = QuaternionIdentity();
2575+
}
2576+
}
2577+
25282578
#endif // RAYMATH_H

src/rmodels.c

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4878,13 +4878,13 @@ static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
48784878
}
48794879

48804880
// Find parent bone index
4881-
unsigned int parentIndex = -1;
4881+
int parentIndex = -1;
48824882

48834883
for (unsigned int j = 0; j < skin.joints_count; j++)
48844884
{
48854885
if (skin.joints[j] == node.parent)
48864886
{
4887-
parentIndex = j;
4887+
parentIndex = (int)j;
48884888
break;
48894889
}
48904890
}
@@ -5113,16 +5113,15 @@ static Model LoadGLTF(const char *fileName)
51135113
if (!mesh)
51145114
continue;
51155115

5116+
51165117
cgltf_float worldTransform[16];
51175118
cgltf_node_transform_world(node, worldTransform);
5118-
51195119
Matrix worldMatrix = {
5120-
worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],
5121-
worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],
5122-
worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],
5123-
worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]
5120+
worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],
5121+
worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],
5122+
worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],
5123+
worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]
51245124
};
5125-
51265125
Matrix worldMatrixNormals = MatrixTranspose(MatrixInvert(worldMatrix));
51275126

51285127
for (unsigned int p = 0; p < mesh->primitives_count; p++)
@@ -5459,22 +5458,17 @@ static Model LoadGLTF(const char *fileName)
54595458

54605459
for (int i = 0; i < model.boneCount; i++)
54615460
{
5462-
cgltf_node node = *skin.joints[i];
5463-
model.bindPose[i].translation.x = node.translation[0];
5464-
model.bindPose[i].translation.y = node.translation[1];
5465-
model.bindPose[i].translation.z = node.translation[2];
5466-
5467-
model.bindPose[i].rotation.x = node.rotation[0];
5468-
model.bindPose[i].rotation.y = node.rotation[1];
5469-
model.bindPose[i].rotation.z = node.rotation[2];
5470-
model.bindPose[i].rotation.w = node.rotation[3];
5471-
5472-
model.bindPose[i].scale.x = node.scale[0];
5473-
model.bindPose[i].scale.y = node.scale[1];
5474-
model.bindPose[i].scale.z = node.scale[2];
5461+
cgltf_node* node = skin.joints[i];
5462+
cgltf_float worldTransform[16];
5463+
cgltf_node_transform_world(node, worldTransform);
5464+
Matrix worldMatrix = {
5465+
worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],
5466+
worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],
5467+
worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],
5468+
worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]
5469+
};
5470+
MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));
54755471
}
5476-
5477-
BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);
54785472
}
54795473
else if (data->skins_count > 1)
54805474
{
@@ -5651,6 +5645,9 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_
56515645
}
56525646
}
56535647

5648+
// Constant animation, no need to interpolate
5649+
if (FloatEquals(tend, tstart)) return false;
5650+
56545651
float duration = fmaxf((tend - tstart), EPSILON);
56555652
float t = (time - tstart)/duration;
56565653
t = (t < 0.0f)? 0.0f : t;
@@ -5880,9 +5877,9 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
58805877

58815878
for (int k = 0; k < animations[i].boneCount; k++)
58825879
{
5883-
Vector3 translation = {0, 0, 0};
5884-
Quaternion rotation = {0, 0, 0, 1};
5885-
Vector3 scale = {1, 1, 1};
5880+
Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
5881+
Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
5882+
Vector3 scale = {skin.joints[k]->scale[0], skin.joints[k]->scale[1], skin.joints[k]->scale[2]};
58865883

58875884
if (boneChannels[k].translate)
58885885
{

0 commit comments

Comments
 (0)