From 23cc39a265d42c693f08c23b54a043d1648b8266 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 1 Sep 2022 10:27:16 +0200 Subject: [PATCH] Implemented latest .M3D improvements #2648 --- examples/models/models_loading_m3d.c | 27 +++++++++++++++++++------ examples/models/models_loading_m3d.png | Bin 0 -> 16992 bytes src/rmodels.c | 18 +++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 examples/models/models_loading_m3d.png 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 0000000000000000000000000000000000000000..80c859fee02548c70a84f42fd75584cf341d36e5 GIT binary patch literal 16992 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 literal 0 HcmV?d00001 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); }