|
@@ -2270,38 +2270,62 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
|
|
|
{
|
|
|
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
|
|
|
|
|
|
+ // Get first mesh which have bones
|
|
|
+ int firstMeshWithBones = -1;
|
|
|
+
|
|
|
for (int i = 0; i < model.meshCount; i++)
|
|
|
{
|
|
|
if (model.meshes[i].boneMatrices)
|
|
|
{
|
|
|
assert(model.meshes[i].boneCount == anim.boneCount);
|
|
|
+ if (firstMeshWithBones == -1)
|
|
|
+ {
|
|
|
+ firstMeshWithBones = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++)
|
|
|
+ // Update all bones and boneMatrices of first mesh with bones.
|
|
|
+ for (int boneId = 0; boneId < anim.boneCount; boneId++)
|
|
|
+ {
|
|
|
+ Vector3 inTranslation = model.bindPose[boneId].translation;
|
|
|
+ Quaternion inRotation = model.bindPose[boneId].rotation;
|
|
|
+ Vector3 inScale = model.bindPose[boneId].scale;
|
|
|
+
|
|
|
+ Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
|
|
|
+ Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
|
|
|
+ Vector3 outScale = anim.framePoses[frame][boneId].scale;
|
|
|
+
|
|
|
+ Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation));
|
|
|
+ Quaternion invRotation = QuaternionInvert(inRotation);
|
|
|
+ Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);
|
|
|
+
|
|
|
+ Vector3 boneTranslation = Vector3Add(
|
|
|
+ Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),
|
|
|
+ outRotation), outTranslation);
|
|
|
+ Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
|
|
|
+ Vector3 boneScale = Vector3Multiply(outScale, invScale);
|
|
|
+
|
|
|
+ Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
|
|
|
+ QuaternionToMatrix(boneRotation),
|
|
|
+ MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
|
|
|
+ MatrixScale(boneScale.x, boneScale.y, boneScale.z));
|
|
|
+
|
|
|
+ model.meshes[firstMeshWithBones].boneMatrices[boneId] = boneMatrix;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update remaining meshes with bones (Use Deep copy because shallow copy results in double free with 'UnloadModel()')
|
|
|
+ if (firstMeshWithBones != -1)
|
|
|
+ {
|
|
|
+ for (int i = firstMeshWithBones + 1; i < model.meshCount; i++)
|
|
|
+ {
|
|
|
+ if (model.meshes[i].boneMatrices)
|
|
|
{
|
|
|
- Vector3 inTranslation = model.bindPose[boneId].translation;
|
|
|
- Quaternion inRotation = model.bindPose[boneId].rotation;
|
|
|
- Vector3 inScale = model.bindPose[boneId].scale;
|
|
|
-
|
|
|
- Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
|
|
|
- Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
|
|
|
- Vector3 outScale = anim.framePoses[frame][boneId].scale;
|
|
|
-
|
|
|
- Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation));
|
|
|
- Quaternion invRotation = QuaternionInvert(inRotation);
|
|
|
- Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);
|
|
|
-
|
|
|
- Vector3 boneTranslation = Vector3Add(
|
|
|
- Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),
|
|
|
- outRotation), outTranslation);
|
|
|
- Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
|
|
|
- Vector3 boneScale = Vector3Multiply(outScale, invScale);
|
|
|
-
|
|
|
- Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
|
|
|
- QuaternionToMatrix(boneRotation),
|
|
|
- MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
|
|
|
- MatrixScale(boneScale.x, boneScale.y, boneScale.z));
|
|
|
-
|
|
|
- model.meshes[i].boneMatrices[boneId] = boneMatrix;
|
|
|
+ memcpy(
|
|
|
+ model.meshes[i].boneMatrices,
|
|
|
+ model.meshes[firstMeshWithBones].boneMatrices,
|
|
|
+ model.meshes[i].boneCount * sizeof(model.meshes[i].boneMatrices[0])
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
}
|