summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/models.c105
1 files changed, 82 insertions, 23 deletions
diff --git a/src/models.c b/src/models.c
index 5c54902a..b9222855 100644
--- a/src/models.c
+++ b/src/models.c
@@ -3719,11 +3719,11 @@ static Model LoadGLTF(const char *fileName)
model.boneCount = (int)data->nodes_count;
model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo));
model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform));
-
+
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 = (int)((j != 0 && data->nodes[j].parent != NULL) ? data->nodes[j].parent - data->nodes : 0);
+ model.bones[j].parent = (data->nodes[j].parent != NULL) ? data->nodes[j].parent - data->nodes : -1;
}
for (unsigned int i = 0; i < data->nodes_count; i++)
@@ -3739,22 +3739,41 @@ static Model LoadGLTF(const char *fileName)
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;
- int root = currentBone->parent;
- if (root >= model.boneCount) root = 0;
- Transform *parentTransform = model.bindPose + root;
-
- 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);
+ bool* completedBones = RL_CALLOC(model.boneCount, sizeof(bool));
+ int numberCompletedBones = 0;
+
+ while (numberCompletedBones < model.boneCount) {
+ for (int i = 0; i < model.boneCount; i++)
+ {
+ if (completedBones[i]) continue;
+
+ if (model.bones[i].parent < 0) {
+ completedBones[i] = true;
+ numberCompletedBones++;
+ continue;
+ }
+
+ if (!completedBones[model.bones[i].parent]) continue;
+
+ Transform* currentTransform = &model.bindPose[i];
+ BoneInfo* currentBone = &model.bones[i];
+ int root = currentBone->parent;
+ if (root >= model.boneCount)
+ root = 0;
+ Transform* parentTransform = &model.bindPose[root];
+
+ 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);
+ completedBones[i] = true;
+ numberCompletedBones++;
+ }
}
+
+ RL_FREE(completedBones);
}
for (int i = 0; i < model.materialCount - 1; i++)
@@ -3879,7 +3898,28 @@ static Model LoadGLTF(const char *fileName)
short* bones = RL_MALLOC(sizeof(short) * acc->count * 4);
LOAD_ACCESSOR(short, 4, acc, bones);
- for (unsigned int a = 0; a < acc->count * 4; a ++)
+ for (unsigned int a = 0; a < acc->count * 4; a++)
+ {
+ cgltf_node* skinJoint = data->skins->joints[bones[a]];
+
+ for (unsigned int k = 0; k < data->nodes_count; k++)
+ {
+ if (&(data->nodes[k]) == skinJoint)
+ {
+ model.meshes[primitiveIndex].boneIds[a] = k;
+ break;
+ }
+ }
+ }
+ RL_FREE(bones);
+ }
+ else if (acc->component_type == cgltf_component_type_r_8u)
+ {
+ model.meshes[primitiveIndex].boneIds = RL_MALLOC(sizeof(int) * acc->count * 4);
+ unsigned char* bones = RL_MALLOC(sizeof(unsigned char) * acc->count * 4);
+
+ LOAD_ACCESSOR(unsigned char, 4, acc, bones);
+ for (unsigned int a = 0; a < acc->count * 4; a++)
{
cgltf_node* skinJoint = data->skins->joints[bones[a]];
@@ -4009,6 +4049,9 @@ static ModelAnimation* LoadGLTFModelAnimations(const char *fileName, int *animCo
{
TRACELOG(LOG_INFO, "MODEL: [%s] glTF animations (%s) count: %i", fileName, (data->file_type == 2)? "glb" :
"gltf", data->animations_count);
+
+ result = cgltf_load_buffers(&options, data, fileName);
+ if (result != cgltf_result_success) TRACELOG(LOG_WARNING, "MODEL: [%s] unable to load glTF animations data", fileName);
animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
@@ -4054,7 +4097,7 @@ static ModelAnimation* LoadGLTFModelAnimations(const char *fileName, int *animCo
for (unsigned int j = 0; j < data->nodes_count; j++)
{
strcpy(output->bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name);
- output->bones[j].parent = j != 0 ? (int)(data->nodes[j].parent - data->nodes) : 0;
+ output->bones[j].parent = (data->nodes[j].parent != NULL) ? (int)(data->nodes[j].parent - data->nodes) : -1;
}
// Allocate data for frames
@@ -4099,11 +4142,11 @@ static ModelAnimation* LoadGLTFModelAnimations(const char *fileName, int *animCo
if (frameTime < inputFrameTime)
{
shouldSkipFurtherTransformation = false;
- outputMin = j - 1;
+ outputMin = (j == 0) ? 0 : j - 1;
outputMax = j;
float previousInputTime = 0.0f;
- if (GltfReadFloat(sampler->input, j - 1, (float*)&previousInputTime, 1))
+ if (GltfReadFloat(sampler->input, outputMin, (float*)&previousInputTime, 1))
{
lerpPercent = (frameTime - previousInputTime) / (inputFrameTime - previousInputTime);
}
@@ -4163,16 +4206,32 @@ static ModelAnimation* LoadGLTFModelAnimations(const char *fileName, int *animCo
// Build frameposes
for (int frame = 0; frame < output->frameCount; frame++)
{
- for (int i = 0; i < output->boneCount; i++)
- {
- if (output->bones[i].parent >= 0)
+ bool* completedBones = RL_CALLOC(output->boneCount, sizeof(bool));
+ int numberCompletedBones = 0;
+
+ while (numberCompletedBones < output->boneCount) {
+ for (int i = 0; i < output->boneCount; i++)
{
+ if (completedBones[i]) continue;
+
+ if (output->bones[i].parent < 0) {
+ completedBones[i] = true;
+ numberCompletedBones++;
+ continue;
+ }
+
+ if (!completedBones[output->bones[i].parent]) continue;
+
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);
output->framePoses[frame][i].scale = Vector3Multiply(output->framePoses[frame][i].scale, output->framePoses[frame][output->bones[i].parent].scale);
+ completedBones[i] = true;
+ numberCompletedBones++;
}
}
+
+ RL_FREE(completedBones);
}
}