From ec29f44db067702d98861c486ed087f5acf532fe Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Wed, 1 Oct 2025 14:18:38 +0100 Subject: [PATCH] Load inverse bind matrices into model --- model.c | 6 +++++- model.h | 1 + model_format_glb.c | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/model.c b/model.c index 45b64e7..c93c80c 100644 --- a/model.c +++ b/model.c @@ -29,6 +29,10 @@ void model_cleanup(model_t *m) if (m->bones != nullptr) { free(m->bones); m->bones = nullptr; - m->bone_count = 0; } + if (m->inverse_bind_matrices != nullptr) { + free(m->inverse_bind_matrices); + m->inverse_bind_matrices = nullptr; + } + m->vertex_count = m->index_count = m->bone_count = 0; } diff --git a/model.h b/model.h index 50ba14b..7f67951 100644 --- a/model.h +++ b/model.h @@ -26,6 +26,7 @@ typedef struct { vertex_t *vertices; index_t *indices; bone_t *bones; + mat4_t *inverse_bind_matrices; 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 cd80d15..fed6cb6 100644 --- a/model_format_glb.c +++ b/model_format_glb.c @@ -98,6 +98,7 @@ typedef struct { accessor_t bone_indices; accessor_t weights; accessor_t indices; + accessor_t inverse_bind_matrices; } accessors_t; typedef struct { @@ -112,6 +113,7 @@ typedef struct { view_t bone_indices; view_t weights; view_t indices; + view_t inverse_bind_matrices; } views_t; typedef struct { @@ -126,6 +128,7 @@ typedef struct { gltf_info_member_t bone_indices; gltf_info_member_t weights; gltf_info_member_t indices; + gltf_info_member_t inverse_bind_matrices; size_t vertex_count, index_count, bone_count; } gltf_info_t; @@ -580,7 +583,7 @@ static accessor_t read_accessor(const uint8_t **p) return accessor; } -static accessors_t read_accessors(const uint8_t *p, mesh_t mesh) +static accessors_t read_accessors(const uint8_t *p, mesh_t mesh, skin_t skin) { accessors_t accessors = {}; assert(*p == '['); @@ -596,11 +599,20 @@ static accessors_t read_accessors(const uint8_t *p, mesh_t mesh) accessors.weights = read_accessor(&p); else if (i == mesh.indices) accessors.indices = read_accessor(&p); + else if (i == skin.inverse_bind_matrices) + accessors.inverse_bind_matrices = read_accessor(&p); else skip_value(&p); if (*p == ',') ++p; } + + assert(accessors.normals.count != 0); + assert(accessors.positions.count != 0); + assert(accessors.bone_indices.count != 0); + assert(accessors.weights.count != 0); + assert(accessors.indices.count != 0); + assert(accessors.inverse_bind_matrices.count != 0); return accessors; } @@ -652,6 +664,8 @@ static views_t read_views(const uint8_t *p, accessors_t accessors) views.weights = read_view(&p); else if (i == accessors.indices.view) views.indices = read_view(&p); + else if (i == accessors.inverse_bind_matrices.view) + views.inverse_bind_matrices = read_view(&p); else skip_value(&p); @@ -667,6 +681,7 @@ static views_t read_views(const uint8_t *p, accessors_t accessors) assert(views.bone_indices.len != 0); assert(views.weights.len != 0); assert(views.indices.len != 0); + assert(views.inverse_bind_matrices.len != 0); return views; } @@ -728,7 +743,7 @@ static gltf_info_t read_json(const uint8_t *json) assert(bones != nullptr); read_joints(nodes_json, skin, bones); - const accessors_t accessors = read_accessors(accessors_json, mesh); + const accessors_t accessors = read_accessors(accessors_json, mesh, skin); const views_t views = read_views(views_json, accessors); // Verify data types @@ -747,6 +762,9 @@ static gltf_info_t read_json(const uint8_t *json) assert( accessors.indices.component == COMPONENT_TYPE_U16 && accessors.indices.type == ACCESSOR_TYPE_SCALAR); + assert( + accessors.inverse_bind_matrices.component == COMPONENT_TYPE_F32 + && accessors.inverse_bind_matrices.type == ACCESSOR_TYPE_MAT4); // Ensure the vertex count is consistent assert( @@ -754,6 +772,9 @@ static gltf_info_t read_json(const uint8_t *json) && accessors.positions.count == accessors.bone_indices.count && accessors.positions.count == accessors.weights.count); + // Ensure the joint count is consistent + assert(accessors.inverse_bind_matrices.count == skin.joint_count); + return (gltf_info_t) { .bones = bones, .positions = info_member(accessors.positions, views.positions), @@ -764,6 +785,8 @@ static gltf_info_t read_json(const uint8_t *json) .indices = info_member(accessors.indices, views.indices), .vertex_count = accessors.positions.count, .index_count = accessors.indices.count, + .inverse_bind_matrices = info_member( + accessors.inverse_bind_matrices, views.inverse_bind_matrices), .bone_count = skin.joint_count, }; } @@ -817,6 +840,12 @@ 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)); + assert(model.inverse_bind_matrices != nullptr); + memcpy( + model.inverse_bind_matrices, + bin_data + info.inverse_bind_matrices.offset, + info.inverse_bind_matrices.len); munmap(file, len); return model;