fixed id mismatch between animation and model

This commit is contained in:
MrDiver 2021-09-02 09:06:59 +02:00
parent 04d2219bea
commit 61c43066f3

View File

@ -123,10 +123,10 @@ static ModelAnimation *LoadIQMModelAnimations(const char *fileName, int *animCou
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount); // Load GLTF animation data static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount); // Load GLTF animation data
static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data); static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data);
static void LoadGLTFMesh(cgltf_data *data, cgltf_mesh *mesh, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName); static void LoadGLTFMesh(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName);
static void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName); static void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName);
static void InitGLTFBones(Model *model, const cgltf_data *data); static void InitGLTFBones(Model *model, const cgltf_data *data);
static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex); static void BindGLTFPrimitiveToBones(Model *model, cgltf_node *node, const cgltf_data *data, int primitiveIndex);
static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount); static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount);
static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable); static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable);
static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting); static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting);
@ -1608,6 +1608,7 @@ ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)
// NOTE: Updated data is uploaded to GPU // NOTE: Updated data is uploaded to GPU
void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
{ {
printf("UpdateModelAnimation\n");
if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL)) if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
{ {
if (frame >= anim.frameCount) frame = frame%anim.frameCount; if (frame >= anim.frameCount) frame = frame%anim.frameCount;
@ -1619,6 +1620,15 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation Mesh %i has no connection to bones",m); TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation Mesh %i has no connection to bones",m);
continue; continue;
} }
printf("Mesh %i %s\n",m,anim.bones[mesh.boneIds[0]].name);
// for(int i = 0; i < 4; i++){
// printf("%i, ",mesh.boneIds[i]);
// }
// printf("\n");
// for(int i = 0; i < 4; i++){
// printf("%.1f, ",mesh.boneWeights[i]);
// }
printf("\n");
bool updated = false; // set to true when anim vertex information is updated bool updated = false; // set to true when anim vertex information is updated
Vector3 animVertex = { 0 }; Vector3 animVertex = { 0 };
Vector3 animNormal = { 0 }; Vector3 animNormal = { 0 };
@ -1631,14 +1641,13 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
Quaternion outRotation = { 0 }; Quaternion outRotation = { 0 };
Vector3 outScale = { 0 }; Vector3 outScale = { 0 };
int vCounter = 0;
int boneCounter = 0;
int boneId = 0; int boneId = 0;
int boneCounter = 0;
float boneWeight = 0.0; float boneWeight = 0.0;
for (int i = 0; i < mesh.vertexCount; i++) const int vValues = mesh.vertexCount*3;
for (int vCounter = 0; vCounter < vValues; vCounter+=3)
{ {
vCounter = i*3;
mesh.animVertices[vCounter] = 0; mesh.animVertices[vCounter] = 0;
mesh.animVertices[vCounter + 1] = 0; mesh.animVertices[vCounter + 1] = 0;
mesh.animVertices[vCounter + 2] = 0; mesh.animVertices[vCounter + 2] = 0;
@ -1648,14 +1657,13 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
mesh.animNormals[vCounter + 1] = 0; mesh.animNormals[vCounter + 1] = 0;
mesh.animNormals[vCounter + 2] = 0; mesh.animNormals[vCounter + 2] = 0;
} }
for (int j = 0; j < 4; j++, boneCounter++)
for (int j = 0; j < 4; j++)
{ {
boneWeight = mesh.boneWeights[boneCounter]; boneWeight = mesh.boneWeights[boneCounter];
// early stop when no transformation will be applied // early stop when no transformation will be applied
if(boneWeight==0.0f) if(boneWeight==0.0f)
{ {
boneCounter += 1; // boneCounter += 1;
continue; continue;
} }
boneId = mesh.boneIds[boneCounter]; boneId = mesh.boneIds[boneCounter];
@ -1670,7 +1678,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
float angle = 2.0f*acosf(outRotation.w); float angle = 2.0f*acosf(outRotation.w);
float length = Vector3Length(Vector3Subtract(outScale,inScale)); float length = Vector3Length(Vector3Subtract(outScale,inScale));
if(angle==0.0 && length==0.0){ if(angle==0.0 && length==0.0){
boneCounter += 1; // boneCounter += 1;
continue; continue;
} }
@ -1696,9 +1704,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
} }
boneCounter += 1;
} }
vCounter += 3;
} }
// Upload new vertex data to GPU for model drawing // Upload new vertex data to GPU for model drawing
@ -4927,7 +4933,9 @@ static void InitGLTFBones(Model *model, const cgltf_data *data)
{ {
strcpy(model->bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name); strcpy(model->bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name);
model->bones[j].parent = (data->nodes[j].parent != NULL) ? (int)(data->nodes[j].parent - data->nodes) : -1; model->bones[j].parent = (data->nodes[j].parent != NULL) ? (int)(data->nodes[j].parent - data->nodes) : -1;
printf("Bone %3i is %s\n", j, model->bones[j].name);
} }
printf("---");
for (unsigned int i = 0; i < data->nodes_count; i++) for (unsigned int i = 0; i < data->nodes_count; i++)
{ {
@ -5052,12 +5060,10 @@ static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_dat
model->materials[model->materialCount - 1] = LoadMaterialDefault(); model->materials[model->materialCount - 1] = LoadMaterialDefault();
} }
static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex) static void BindGLTFPrimitiveToBones(Model *model, cgltf_node *node, const cgltf_data *data, int primitiveIndex)
{ {
for (unsigned int nodeId = 0; nodeId < data->nodes_count; nodeId++) int nodeId = node - data->nodes;
{ printf("\tNodeId %i\n",nodeId);
if (data->nodes[nodeId].mesh == &(data->meshes[primitiveIndex]))
{
if (model->meshes[primitiveIndex].boneIds == NULL) if (model->meshes[primitiveIndex].boneIds == NULL)
{ {
model->meshes[primitiveIndex].boneIds = RL_CALLOC(model->meshes[primitiveIndex].vertexCount*4, sizeof(int)); model->meshes[primitiveIndex].boneIds = RL_CALLOC(model->meshes[primitiveIndex].vertexCount*4, sizeof(int));
@ -5077,8 +5083,6 @@ static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int p
} }
} }
} }
}
}
} }
// LoadGLTF loads in animation data from given filename // LoadGLTF loads in animation data from given filename
@ -5158,11 +5162,13 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
output->framePoses = RL_MALLOC(output->frameCount*sizeof(Transform *)); output->framePoses = RL_MALLOC(output->frameCount*sizeof(Transform *));
// output->framerate = // TODO: Use framerate instead of const timestep // output->framerate = // TODO: Use framerate instead of const timestep
printf("LoadAnim %i %s\n",a,animation->name);
// Name and parent bones // Name and parent bones
for (int j = 0; j < output->boneCount; j++) for (int j = 0; j < output->boneCount; j++)
{ {
strcpy(output->bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name); strcpy(output->bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name);
output->bones[j].parent = (data->nodes[j].parent != NULL) ? (int)(data->nodes[j].parent - data->nodes) : -1; output->bones[j].parent = (data->nodes[j].parent != NULL) ? (int)(data->nodes[j].parent - data->nodes) : -1;
// printf("Bone %3i is %s\n",j,output->bones[j].name);
} }
// Allocate data for frames // Allocate data for frames
@ -5193,6 +5199,8 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
cgltf_animation_sampler *sampler = channel->sampler; cgltf_animation_sampler *sampler = channel->sampler;
int boneId = (int)(channel->target_node - data->nodes); int boneId = (int)(channel->target_node - data->nodes);
printf("Node Name %s\n",channel->target_node->name);
printf("Bone %i anims %s\n",boneId, channel->target_node->name);
for (int frame = 0; frame < output->frameCount; frame++) for (int frame = 0; frame < output->frameCount; frame++)
{ {
@ -5305,6 +5313,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
} }
} }
printf("---\n");
// Build frameposes // Build frameposes
for (int frame = 0; frame < output->frameCount; frame++) for (int frame = 0; frame < output->frameCount; frame++)
{ {
@ -5348,8 +5357,9 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
return animations; return animations;
} }
void LoadGLTFMesh(cgltf_data *data, cgltf_mesh *mesh, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName) void LoadGLTFMesh(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName)
{ {
cgltf_mesh *mesh = node->mesh;
for (unsigned int p = 0; p < mesh->primitives_count; p++) for (unsigned int p = 0; p < mesh->primitives_count; p++)
{ {
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++) for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
@ -5413,27 +5423,27 @@ void LoadGLTFMesh(cgltf_data *data, cgltf_mesh *mesh, Model *outModel, Matrix cu
} }
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints) else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints)
{ {
/*
This seems very inneficient to me it runs over a 100 times just to find an id ?
*/
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data; cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
unsigned int boneCount = acc->count; unsigned int boneCount = acc->count;
unsigned int totalBoneWeights = boneCount*4; unsigned int totalBoneWeights = boneCount*4;
outModel->meshes[(*primitiveIndex)].boneIds = RL_MALLOC(totalBoneWeights*sizeof(int)); outModel->meshes[(*primitiveIndex)].boneIds = RL_MALLOC(totalBoneWeights*sizeof(int));
short *bones = ReadGLTFValuesAs(acc, cgltf_component_type_r_16, false); short *bones = ReadGLTFValuesAs(acc, cgltf_component_type_r_16, false);
//find skin joint
//is this useful when only 4 bones are used ?
for (unsigned int a = 0; a < totalBoneWeights; a++) for (unsigned int a = 0; a < totalBoneWeights; a++)
{ {
outModel->meshes[(*primitiveIndex)].boneIds[a] = 0; outModel->meshes[(*primitiveIndex)].boneIds[a] = 0;
if (bones[a] < 0) continue; if (bones[a] < 0) continue;
cgltf_node* skinJoint = data->skins->joints[bones[a]]; cgltf_node* skinJoint = data->skins->joints[bones[a]];
for (unsigned int k = 0; k < data->nodes_count; k++) int skinJointId = skinJoint - data->nodes;
{ printf("%i, ",skinJointId);
if (data->nodes + k == skinJoint) outModel->meshes[(*primitiveIndex)].boneIds[a] = skinJointId;
{
outModel->meshes[(*primitiveIndex)].boneIds[a] = k;
break;
}
}
} }
printf("\n");
RL_FREE(bones); RL_FREE(bones);
} }
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights) else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights)
@ -5467,7 +5477,7 @@ void LoadGLTFMesh(cgltf_data *data, cgltf_mesh *mesh, Model *outModel, Matrix cu
} }
else outModel->meshMaterial[(*primitiveIndex)] = outModel->materialCount - 1; else outModel->meshMaterial[(*primitiveIndex)] = outModel->materialCount - 1;
BindGLTFPrimitiveToBones(outModel, data, *primitiveIndex); BindGLTFPrimitiveToBones(outModel, node, data, *primitiveIndex);
(*primitiveIndex) = (*primitiveIndex) + 1; (*primitiveIndex) = (*primitiveIndex) + 1;
} }
@ -5517,7 +5527,8 @@ void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix cu
vertexTransform = localTransform; vertexTransform = localTransform;
TRACELOG(LOG_WARNING,"MODEL: GLTF Node %s is skinned but not root node! Parent transformations will be ignored (NODE_SKINNED_MESH_NON_ROOT)",node->name); TRACELOG(LOG_WARNING,"MODEL: GLTF Node %s is skinned but not root node! Parent transformations will be ignored (NODE_SKINNED_MESH_NON_ROOT)",node->name);
} }
LoadGLTFMesh(data, node->mesh, outModel, vertexTransform, primitiveIndex, fileName); printf("Load Node: %s\n",node->name);
LoadGLTFMesh(data, node, outModel, vertexTransform, primitiveIndex, fileName);
} }
for (unsigned int i = 0; i < node->children_count; i++) LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName); for (unsigned int i = 0; i < node->children_count; i++) LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName);
} }