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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 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); }