diff --git a/examples/models/models_gltf_animation.c b/examples/models/models_gltf_animation.c index 4bcec5893..2cc8dafb5 100644 --- a/examples/models/models_gltf_animation.c +++ b/examples/models/models_gltf_animation.c @@ -39,7 +39,7 @@ int main(void) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type - Model model = LoadModel("resources/models/rigged_figure.glb"); // Load the animated model mesh and + Model model = LoadModel("resources/rigged_figure/rigged_figure.glb"); // Load the animated model mesh and // basic data // Texture2D texture = LoadTexture("resources/guy/guytex.png"); // Load model texture and set material // SetMaterialTexture(&model.materials[0], MAP_DIFFUSE, texture); // Set model material map texture @@ -48,7 +48,7 @@ int main(void) // Load animation data int animsCount = 0; - ModelAnimation *anims = LoadModelAnimations("resources/models/rigged_figure.glb", &animsCount); + ModelAnimation *anims = LoadModelAnimations("resources/rigged_figure/rigged_figure.glb", &animsCount); int animFrameCounter = 0; SetCameraMode(camera, CAMERA_FREE); // Set free camera mode @@ -92,7 +92,7 @@ int main(void) EndMode3D(); DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, 10, 20, MAROON); - DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY); + DrawText("(cc4) Rigged Figure by @Cesium", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/models/resources/rigged_figure/LICENSE b/examples/models/resources/rigged_figure/LICENSE new file mode 100644 index 000000000..e6ab2956c --- /dev/null +++ b/examples/models/resources/rigged_figure/LICENSE @@ -0,0 +1,6 @@ +Rigged Figure model has been created by Cesium (https://cesium.com/cesiumjs/), +and licensed as Creative Commons Attribution 4.0 International License. + +It was donated to GLTF sample models for testing (https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/RiggedFigure) + +Check for details: http://creativecommons.org/licenses/by/4.0/ diff --git a/examples/models/resources/models/rigged_figure.glb b/examples/models/resources/rigged_figure/rigged_figure.glb similarity index 100% rename from examples/models/resources/models/rigged_figure.glb rename to examples/models/resources/rigged_figure/rigged_figure.glb diff --git a/src/models.c b/src/models.c index a5e5aabbd..07570430e 100644 --- a/src/models.c +++ b/src/models.c @@ -3781,8 +3781,9 @@ static Model LoadGLTF(const char *fileName) int primitivesCount = 0; - for (unsigned int i = 0; i < data->meshes_count; i++) primitivesCount += (int)data->meshes[i].primitives_count; - + for (unsigned int i = 0; i < data->meshes_count; i++) + primitivesCount += (int)data->meshes[i].primitives_count; + // Process glTF data and map to model model.meshCount = primitivesCount; model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh)); @@ -3793,13 +3794,60 @@ static Model LoadGLTF(const char *fileName) model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo)); model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform)); - for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); + for (int i = 0; i < model.meshCount; i++) + model.meshes[i].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); for (unsigned int j = 0; j < data->nodes_count; j++) { strcpy(model.bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name); model.bones[j].parent = j != 0 ? data->nodes[j].parent - data->nodes : 0; } + + for (unsigned int i = 0; i < data->nodes_count; i++) + { + if(data->nodes[i].has_translation) + { + memcpy(&model.bindPose[i].translation, data->nodes[i].translation, 3 * sizeof(float)); + } + else + { + model.bindPose[i].translation = Vector3Zero(); + } + + if(data->nodes[i].has_rotation) + { + memcpy(&model.bindPose[i].rotation, data->nodes[i].rotation, 4 * sizeof(float)); + } + else + { + model.bindPose[i].rotation = QuaternionIdentity(); + } + model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation); + + if(data->nodes[i].has_scale) + { + memcpy(&model.bindPose[i].scale, data->nodes[i].scale, 3 * sizeof(float)); + } + else + { + model.bindPose[i].scale = Vector3One(); + } + } + + for (int i = 0; i < model.boneCount; i++) + { + Transform* currentTransform = model.bindPose + i; + BoneInfo* currentBone = model.bones + i; + Transform* parentTransform = model.bindPose + currentBone->parent; + + if (currentBone->parent >= 0) + { + currentTransform->rotation = QuaternionMultiply(parentTransform->rotation, currentTransform->rotation); + currentTransform->translation = Vector3RotateByQuaternion(currentTransform->translation, parentTransform->rotation); + currentTransform->translation = Vector3Add(currentTransform->translation, parentTransform->translation); + currentTransform->scale = Vector3Multiply(parentTransform->scale, parentTransform->scale); + } + } for (int i = 0; i < model.materialCount - 1; i++) { @@ -3881,18 +3929,22 @@ static Model LoadGLTF(const char *fileName) { cgltf_accessor *acc = data->meshes[i].primitives[p].attributes[j].data; model.meshes[primitiveIndex].vertexCount = (int)acc->count; - model.meshes[primitiveIndex].vertices = RL_MALLOC(model.meshes[primitiveIndex].vertexCount*3*sizeof(float)); - model.meshes[primitiveIndex].animVertices = RL_MALLOC(model.meshes[primitiveIndex].vertexCount*3*sizeof(float)); + int bufferSize = model.meshes[primitiveIndex].vertexCount * 3 * sizeof(float); + model.meshes[primitiveIndex].vertices = RL_MALLOC(bufferSize); + model.meshes[primitiveIndex].animVertices = RL_MALLOC(bufferSize); - LOAD_ACCESSOR(float, 3, acc, model.meshes[primitiveIndex].vertices) + LOAD_ACCESSOR(float, 3, acc, model.meshes[primitiveIndex].vertices); + memcpy(model.meshes[primitiveIndex].animVertices, model.meshes[primitiveIndex].vertices, bufferSize); } else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_normal) { cgltf_accessor *acc = data->meshes[i].primitives[p].attributes[j].data; - model.meshes[primitiveIndex].normals = RL_MALLOC(acc->count*3*sizeof(float)); - model.meshes[primitiveIndex].animNormals = RL_MALLOC(acc->count*3*sizeof(float)); + int bufferSize = acc->count*3*sizeof(float); + model.meshes[primitiveIndex].normals = RL_MALLOC(bufferSize); + model.meshes[primitiveIndex].animNormals = RL_MALLOC(bufferSize); - LOAD_ACCESSOR(float, 3, acc, model.meshes[primitiveIndex].normals) + LOAD_ACCESSOR(float, 3, acc, model.meshes[primitiveIndex].normals); + memcpy(model.meshes[primitiveIndex].animNormals, model.meshes[primitiveIndex].normals, bufferSize); } else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) {