diff --git a/examples/models/models_loading_m3d.c b/examples/models/models_loading_m3d.c index ca77d360a..f67ba5e57 100644 --- a/examples/models/models_loading_m3d.c +++ b/examples/models/models_loading_m3d.c @@ -18,13 +18,14 @@ #include "raylib.h" #include +#include //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ int main(int argc, char **argv) { - char *model_fn = argc > 1 ? argv[1] : "resources/models/m3d/suzanne.m3d"; + char *model_fn = argc > 1 ? argv[1] : "resources/models/m3d/seagull.m3d"; // Initialization //-------------------------------------------------------------------------------------- @@ -46,7 +47,7 @@ int main(int argc, char **argv) Model model = LoadModel(model_fn); // Load the animated model mesh and basic data // Load animation data - unsigned int animsCount = 0; + unsigned int animsCount = 0, animsSkel = 1, animsMesh = 1; ModelAnimation *anims = LoadModelAnimations(model_fn, &animsCount); int animFrameCounter = 0, animId = 0; @@ -71,6 +72,15 @@ int main(int argc, char **argv) animFrameCounter++; UpdateModelAnimation(model, anims[animId], animFrameCounter); if (animFrameCounter >= anims[animId].frameCount) animFrameCounter = 0; + //printf("anim %u, frame %u / %u\n",animId,animFrameCounter,anims[animId].frameCount); + } + if (IsKeyDown(KEY_S)) + { + animsSkel ^= 1; + } + if (IsKeyDown(KEY_M)) + { + animsMesh ^= 1; } // Select animation on mouse click @@ -92,11 +102,16 @@ int main(int argc, char **argv) BeginMode3D(camera); - DrawModel(model, position, 1.0f, WHITE); // Draw 3d model with texture - if(anims) + if (animsMesh) + DrawModel(model, position, 1.0f, WHITE); // Draw 3d model with texture + + if (anims && animsSkel) for (int i = 0; i < model.boneCount; i++) { - DrawCube(anims[animId].framePoses[animFrameCounter][i].translation, 0.2f, 0.2f, 0.2f, RED); + DrawCube(anims[animId].framePoses[animFrameCounter][i].translation, 0.05f, 0.05f, 0.05f, RED); + if (anims[animId].bones[i].parent >= 0) + DrawLine3D(anims[animId].framePoses[animFrameCounter][i].translation, + anims[animId].framePoses[animFrameCounter][anims[animId].bones[i].parent].translation, RED); } DrawGrid(10, 1.0f); // Draw a grid @@ -105,7 +120,7 @@ int main(int argc, char **argv) DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, GetScreenHeight() - 30, 10, MAROON); DrawText("MOUSE LEFT BUTTON to CYCLE THROUGH ANIMATIONS", 10, GetScreenHeight() - 20, 10, DARKGRAY); - DrawText("(c) Suzanne 3D model by blender", screenWidth - 200, screenHeight - 20, 10, GRAY); + DrawText("(c) Seagull model by Scorched3D", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/models/models_loading_m3d.png b/examples/models/models_loading_m3d.png new file mode 100644 index 000000000..80c859fee Binary files /dev/null and b/examples/models/models_loading_m3d.png differ diff --git a/src/rmodels.c b/src/rmodels.c index d1ead9373..d6e73c07f 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5371,6 +5371,15 @@ static Model LoadM3D(const char *fileName) // TODO: if the orientation quaternion not normalized, then that's encoding scaling model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation); model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f; + + // Child bones are stored in parent bone relative space, convert that into model space + if (model.bones[i].parent >= 0) + { + model.bindPose[i].rotation = QuaternionMultiply(model.bindPose[model.bones[i].parent].rotation, model.bindPose[i].rotation); + model.bindPose[i].translation = Vector3RotateByQuaternion(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].rotation); + model.bindPose[i].translation = Vector3Add(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].translation); + model.bindPose[i].scale = Vector3Multiply(model.bindPose[i].scale, model.bindPose[model.bones[i].parent].scale); + } } } @@ -5463,6 +5472,15 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int animations[a].framePoses[i][j].rotation.w = m3d->vertex[pose[j].ori].w; animations[a].framePoses[i][j].rotation = QuaternionNormalize(animations[a].framePoses[i][j].rotation); animations[a].framePoses[i][j].scale.x = animations[a].framePoses[i][j].scale.y = animations[a].framePoses[i][j].scale.z = 1.0f; + + // Child bones are stored in parent bone relative space, convert that into model space + if (animations[a].bones[j].parent >= 0) + { + animations[a].framePoses[i][j].rotation = QuaternionMultiply(animations[a].framePoses[i][animations[a].bones[j].parent].rotation, animations[a].framePoses[i][j].rotation); + animations[a].framePoses[i][j].translation = Vector3RotateByQuaternion(animations[a].framePoses[i][j].translation, animations[a].framePoses[i][animations[a].bones[j].parent].rotation); + animations[a].framePoses[i][j].translation = Vector3Add(animations[a].framePoses[i][j].translation, animations[a].framePoses[i][animations[a].bones[j].parent].translation); + animations[a].framePoses[i][j].scale = Vector3Multiply(animations[a].framePoses[i][j].scale, animations[a].framePoses[i][animations[a].bones[j].parent].scale); + } } RL_FREE(pose); }