diff --git a/model.c b/model.c index c93c80c..0709c12 100644 --- a/model.c +++ b/model.c @@ -6,9 +6,9 @@ model_t model_init(size_t vertex_count, size_t index_count) { model_t model = { - .indices = calloc(index_count, sizeof(index_t)), + .indices = malloc(index_count * sizeof(index_t)), .index_count = index_count, - .vertices = calloc(vertex_count, sizeof(vertex_t)), + .vertices = malloc(vertex_count * sizeof(vertex_t)), .vertex_count = vertex_count, }; return model; @@ -34,5 +34,19 @@ void model_cleanup(model_t *m) free(m->inverse_bind_matrices); m->inverse_bind_matrices = nullptr; } - m->vertex_count = m->index_count = m->bone_count = 0; + if (m->animation.times != nullptr) { + free(m->animation.times); + m->animation.times = nullptr; + } + if (m->animation.bones != nullptr) { + for (unsigned i = 0; i < m->bone_count; ++i) { + free(m->animation.bones[i].translations); + free(m->animation.bones[i].rotations); + free(m->animation.bones[i].scales); + } + free(m->animation.bones); + m->animation.bones = nullptr; + } + m->vertex_count = m->index_count = m->bone_count + = m->animation.keyframe_count = 0; } diff --git a/model.h b/model.h index 7f67951..0f88965 100644 --- a/model.h +++ b/model.h @@ -22,11 +22,24 @@ typedef struct { vec3_t scale; } bone_t; +typedef struct { + vec3_t *translations; + vec4_t *rotations; + vec3_t *scales; +} animation_bone_t; + +typedef struct { + float *times; + size_t keyframe_count; + animation_bone_t *bones; +} animation_t; + typedef struct { vertex_t *vertices; index_t *indices; bone_t *bones; mat4_t *inverse_bind_matrices; + animation_t animation; size_t vertex_count; size_t index_count; size_t bone_count; diff --git a/model_format_glb.c b/model_format_glb.c index 88690ce..52c14b7 100644 --- a/model_format_glb.c +++ b/model_format_glb.c @@ -1146,13 +1146,67 @@ model_t model_format_glb_read(const char *path) (const u16_vec4_t *)(bin_data + info.bone_indices.offset), (const vec4_t *)(bin_data + info.weights.offset), info.vertex_count); memcpy(model.indices, bin_data + info.indices.offset, info.indices.len); - model.inverse_bind_matrices = calloc(info.bone_count, sizeof(mat4_t)); + model.inverse_bind_matrices = malloc(info.bone_count * sizeof(mat4_t)); assert(model.inverse_bind_matrices != nullptr); memcpy( model.inverse_bind_matrices, bin_data + info.inverse_bind_matrices.offset, info.inverse_bind_matrices.len); + // Load animation data + model.animation.keyframe_count = info.animation.keyframe_count; + const size_t times_size = model.animation.keyframe_count * sizeof(float); + model.animation.times = malloc(times_size); + assert(model.animation.times != nullptr); + memcpy( + model.animation.times, bin_data + info.animation.times[0].offset, + times_size); + model.animation.length_us = (size_t)roundf( + 1'000'000 + * model.animation.times[model.animation.keyframe_count - 1]); + for (unsigned i = 1; i < info.bone_count; ++i) { + // Verify that all time series data matches + if (info.animation.times[i].offset + != info.animation.times[0].offset) { + assert( + memcmp( + model.animation.times, + bin_data + info.animation.times[i].offset, times_size) + == 0); + } + } + model.animation.bones + = malloc(model.bone_count * sizeof(animation_bone_t)); + assert(model.animation.bones != nullptr); + for (unsigned i = 0; i < info.bone_count; ++i) { + // Load translations + model.animation.bones[i].translations + = malloc(model.animation.keyframe_count * sizeof(vec3_t)); + assert(model.animation.bones[i].translations != nullptr); + memcpy( + model.animation.bones[i].translations, + bin_data + info.animation.translations[i].offset, + model.animation.keyframe_count * sizeof(vec3_t)); + + // Load rotations + model.animation.bones[i].rotations + = malloc(model.animation.keyframe_count * sizeof(vec4_t)); + assert(model.animation.bones[i].rotations != nullptr); + memcpy( + model.animation.bones[i].rotations, + bin_data + info.animation.rotations[i].offset, + model.animation.keyframe_count * sizeof(vec4_t)); + + // Load scales + model.animation.bones[i].scales + = malloc(model.animation.keyframe_count * sizeof(vec3_t)); + assert(model.animation.bones[i].scales != nullptr); + memcpy( + model.animation.bones[i].scales, + bin_data + info.animation.scales[i].offset, + model.animation.keyframe_count * sizeof(vec3_t)); + } + munmap(file, len); return model; }