diff --git a/src/models.c b/src/models.c index f5872921d..342e89e8a 100644 --- a/src/models.c +++ b/src/models.c @@ -130,6 +130,7 @@ static void BindGLTFPrimitiveToBones(Model *model, cgltf_node *node, const cgltf static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount); static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable); static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting); +static Matrix GetNodeTransformationMatrix(cgltf_node *node, Matrix current); #endif //---------------------------------------------------------------------------------- @@ -1608,6 +1609,21 @@ ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount) // NOTE: Updated data is uploaded to GPU void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) { + Mesh cyl = GenMeshSphere(0.05, 10, 10); + Material redMaterial = LoadMaterialDefault(); + redMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RED; + Material greenMaterial = LoadMaterialDefault(); + greenMaterial.maps[MATERIAL_MAP_DIFFUSE].color = GREEN; +// for (int i = 0; i < anim.boneCount; i++) +// { +// Vector3 tv = anim.framePoses[frame%anim.frameCount][i].translation; +// Quaternion rv = anim.framePoses[frame%anim.frameCount][i].rotation; +// Matrix tm = MatrixTranslate(tv.x, tv.y, tv.z); +// Matrix rm = QuaternionToMatrix(rv); +// Matrix boneMat = MatrixMultiply(tm, rm); +// DrawMesh(cyl, material, boneMat); +// } + printf("UpdateModelAnimation\n"); if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL)) { @@ -1660,6 +1676,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) for (int j = 0; j < 4; j++, boneCounter++) { boneWeight = mesh.boneWeights[boneCounter]; +// printf(" Bone Weight: %f", boneWeight); // early stop when no transformation will be applied if(boneWeight==0.0f) { @@ -1667,6 +1684,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) continue; } boneId = mesh.boneIds[boneCounter]; + int boneIdParent = model.bones[boneId].parent; // printf("%3i Bone %s\n",boneCounter,model.bones[boneId].name); inTranslation = model.bindPose[boneId].translation; inRotation = model.bindPose[boneId].rotation; @@ -1681,6 +1699,27 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) // if(angle==0.0 && length==0.0){ // continue; // } +// printf("Boneweight %f\n",boneWeight); + Matrix parentTransform = MatrixIdentity(); + if(boneIdParent != -1) + { + Vector3 tv = anim.framePoses[frame][boneIdParent].translation; + Quaternion rv = anim.framePoses[frame][boneIdParent].rotation; + Matrix tm = MatrixTranslate(tv.x, tv.y, tv.z); + Matrix rm = QuaternionToMatrix(rv); + parentTransform = MatrixMultiply(tm, rm); + } + + Matrix tm = MatrixTranslate(outTranslation.x, outTranslation.y, outTranslation.z); + Matrix rm = QuaternionToMatrix((Quaternion){outRotation.x, outRotation.y, outRotation.z, outRotation.w}); + Matrix boneMat = MatrixMultiply(tm, rm); +// boneMat = MatrixMultiply(parentTransform, boneMat); + DrawMesh(cyl, redMaterial, boneMat); + + tm = MatrixTranslate(inTranslation.x, inTranslation.y, inTranslation.z); + rm = QuaternionToMatrix((Quaternion){inRotation.x, inRotation.y, inRotation.z, inRotation.w}); + boneMat = MatrixMultiply(tm, rm); +// DrawMesh(cyl, greenMaterial, boneMat); // Vertices processing // NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position) @@ -1689,10 +1728,11 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) animVertex = Vector3Subtract(animVertex, inTranslation); animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation))); animVertex = Vector3Add(animVertex, outTranslation); +// animVertex = Vector3Transform(animVertex, model.transform); mesh.animVertices[vCounter] += animVertex.x*boneWeight; mesh.animVertices[vCounter + 1] += animVertex.y*boneWeight; mesh.animVertices[vCounter + 2] += animVertex.z*boneWeight; - printf("Vertex %.1f %.1f %.1f\n",animVertex.x, animVertex.y, animVertex.z); +// printf("Vertex %.1f %.1f %.1f\n",animVertex.x, animVertex.y, animVertex.z); updated = true; // Normals processing @@ -3067,6 +3107,8 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) model.transform = MatrixMultiply(model.transform, matTransform); + + for (int i = 0; i < model.meshCount; i++) { Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color; @@ -3081,6 +3123,19 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform); model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = color; } +// Mesh cyl = GenMeshCylinder(0.001, 0.5, 8); +// Material material = LoadMaterialDefault(); +// for (int i = 0; i < model.boneCount; i++) +// { +// Vector3 tv = model.bindPose[i].translation; +// Quaternion rv = model.bindPose[i].rotation; +// Matrix tm = MatrixTranslate(tv.x, tv.y, tv.z); +// Matrix rm = QuaternionToMatrix(rv); +// Matrix boneMat = MatrixMultiply(tm, rm); +// material.maps[MATERIAL_MAP_DIFFUSE].color = RED; +// DrawMesh(cyl, material, boneMat); +// +// } } // Draw a model wires (with texture if set) @@ -5256,13 +5311,16 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo translationStart.y = values[1]; translationStart.z = values[2]; - success = ReadGLTFValue(sampler->output, outputMax, values) || success; + success = ReadGLTFValue(sampler->output, outputMax, values) && success; translationEnd.x = values[0]; translationEnd.y = values[1]; translationEnd.z = values[2]; - if (success) output->framePoses[frame][boneId].translation = Vector3Lerp(translationStart, translationEnd, lerpPercent); + if (success) + { + output->framePoses[frame][boneId].translation = Vector3Lerp(translationStart, translationEnd, lerpPercent); + } } if (channel->target_path == cgltf_animation_path_type_rotation) { @@ -5278,7 +5336,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo rotationStart.z = values[2]; rotationStart.w = values[3]; - success = ReadGLTFValue(sampler->output, outputMax, &values) || success; + success = ReadGLTFValue(sampler->output, outputMax, &values) && success; rotationEnd.x = values[0]; rotationEnd.y = values[1]; @@ -5303,13 +5361,16 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo scaleStart.y = values[1]; scaleStart.z = values[2]; - success = ReadGLTFValue(sampler->output, outputMax, &values) || success; + success = ReadGLTFValue(sampler->output, outputMax, &values) && success; scaleEnd.x = values[0]; scaleEnd.y = values[1]; scaleEnd.z = values[2]; - if (success) output->framePoses[frame][boneId].scale = Vector3Lerp(scaleStart, scaleEnd, lerpPercent); + if (success) + { + output->framePoses[frame][boneId].scale = Vector3Lerp(scaleStart, scaleEnd, lerpPercent); + } } } } @@ -5320,12 +5381,18 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo { bool *completedBones = RL_CALLOC(output->boneCount, sizeof(bool)); int numberCompletedBones = 0; - + /* + * TODO: Well, the speed of this could certrainly be improved by a lot. + * Theres no need for 208 iterations on this if there are only 26 nodes. This is ridiculous. + */ while (numberCompletedBones < output->boneCount) { for (int i = 0; i < output->boneCount; i++) { - if (completedBones[i]) continue; + if (completedBones[i]) + { + continue; + } if (output->bones[i].parent < 0) { @@ -5334,8 +5401,32 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo continue; } - if (!completedBones[output->bones[i].parent]) continue; + if (!completedBones[output->bones[i].parent]) + { + continue; + } +// Vector4 outRotation = output->framePoses[frame][i].rotation; +// Vector4 parentRotation = output->framePoses[frame][output->bones[i].parent].rotation; +// if(data->nodes[i].skin){ +// const int32_t jointCount = data->nodes[i].skin->joints_count; +// cgltf_skin* skin = data->nodes[i].skin; +// cgltf_accessor *acc = skin->inverse_bind_matrices; +// printf("Loading Node:%10s \t %i\n",data->nodes[i].name, jointCount); +// printf("Parent %s\n",data->nodes[i].parent->name); +// for(int joinId = 0; joinId < jointCount; joinId++){ +// printf("\tSkin joint: %s\n",skin->joints[joinId]->name); +// Matrix inv; +// ReadGLTFValue(acc, joinId, &inv.m0); +// // Print shit +// printf("\t%.1f %.1f %.1f %.1f \n", inv.m0, inv.m1, inv.m2, inv.m3); +// printf("\t%.1f %.1f %.1f %.1f \n", inv.m4, inv.m5, inv.m6, inv.m7); +// printf("\t%.1f %.1f %.1f %.1f \n", inv.m8, inv.m9, inv.m10, inv.m11); +// printf("\t%.1f %.1f %.1f %.1f \n", inv.m12, inv.m13, inv.m14, inv.m15); +// parentRotation = QuaternionTransform(parentRotation, inv); +// } +// +// } output->framePoses[frame][i].rotation = QuaternionMultiply(output->framePoses[frame][output->bones[i].parent].rotation, output->framePoses[frame][i].rotation); output->framePoses[frame][i].translation = Vector3RotateByQuaternion(output->framePoses[frame][i].translation, output->framePoses[frame][output->bones[i].parent].rotation); output->framePoses[frame][i].translation = Vector3Add(output->framePoses[frame][i].translation, output->framePoses[frame][output->bones[i].parent].translation); @@ -5344,8 +5435,48 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo numberCompletedBones++; } } - RL_FREE(completedBones); + + +// bool *completedJoints = RL_CALLOC(data->nodes_count, sizeof(bool)); +// for(int skinId = 0; skinId < data->skins_count; skinId++) +// { +// cgltf_skin skin = data->skins[skinId]; +// cgltf_accessor *acc = skin.inverse_bind_matrices; +// printf("Processing Skin %i\n",skinId); +// for(int jointCounter = 0; jointCounter < skin.joints_count; jointCounter++) +// { +// cgltf_node* joint = skin.joints[jointCounter]; +// int jointId = joint - data->nodes; +// if(completedJoints[jointId]) +// continue; +// completedJoints[jointId] = true; +// +// Vector3 tv = output->framePoses[frame][jointId].translation; +// Quaternion rv = output->framePoses[frame][jointId].rotation; +// Vector3 sv = output->framePoses[frame][jointId].scale; +// Matrix tm = MatrixTranslate(tv.x,tv.y,tv.z); +// Matrix rm = QuaternionToMatrix(rv); +// Matrix sm = MatrixScale(sv.x,sv.y,sv.z); +// Matrix globalTransform = MatrixMultiply(MatrixMultiply(tm,rm),sm); +// +// Matrix inv; +// ReadGLTFValue(acc, jointCounter, &inv.m0); +// Matrix jointMatrix = MatrixMultiply(inv,globalTransform); +// tv = (Vector3){jointMatrix.m3, jointMatrix.m7, jointMatrix.m11}; +// jointMatrix = MatrixMultiply(MatrixInvert(tm),jointMatrix); +// rv = QuaternionFromMatrix(jointMatrix); +// jointMatrix = MatrixMultiply(MatrixInvert(rm),jointMatrix); +// sv = (Vector3){jointMatrix.m0,jointMatrix.m5,jointMatrix.m10}; +// +// output->framePoses[frame][jointId].translation = tv; +// output->framePoses[frame][jointId].rotation = rv; +// output->framePoses[frame][jointId].scale = sv; +// printf("\t Joint %i %10s\n",jointId,joint->name); +// } +// } +// RL_FREE(completedJoints); +// printf("-------\n"); } }