diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index 2a8aaf7..ff078f0 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -430,7 +430,7 @@ struct pol_triangle { uint32_t uv_index[3]; uint32_t light_uv_index[3]; vec3 normals[3]; - uint32_t material; // index in the material group + uint32_t material_group_index; }; struct pol_bone { diff --git a/src/3d/model.c b/src/3d/model.c index 0396fcd..3936284 100644 --- a/src/3d/model.c +++ b/src/3d/model.c @@ -214,7 +214,7 @@ static void *buf_alloc(uint8_t **ptr, int size) return p; } -static void add_mesh(struct model *model, struct pol_mesh *m, int material_index, int material) +static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_group_index, int material) { bool has_light_map = m->light_uvs && model->materials[material].light_map; bool has_normal_map = model->materials[material].normal_map != 0; @@ -234,7 +234,7 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index int nr_vertices = 0; for (uint32_t i = 0; i < m->nr_triangles; i++) { struct pol_triangle *t = &m->triangles[i]; - if (material_index >= 0 && t->material != (uint32_t)material_index) + if (t->material_group_index != material_group_index) continue; vec4 tangent[3]; if (has_normal_map) @@ -465,7 +465,7 @@ struct model *model_load(struct archive *aar, const char *path) struct pol_material_group *mg = &pol->materials[pol->meshes[i]->material]; int m_off = material_offsets[pol->meshes[i]->material]; if (mg->nr_children == 0) { - add_mesh(model, pol->meshes[i], -1, m_off); + add_mesh(model, pol->meshes[i], 0, m_off); continue; } for (uint32_t j = 0; j < mg->nr_children; j++) { diff --git a/src/3d/parser.c b/src/3d/parser.c index c71e78d..228853f 100644 --- a/src/3d/parser.c +++ b/src/3d/parser.c @@ -134,7 +134,7 @@ static void destroy_vertex(struct pol_vertex *v) free(v->weights); } -static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle_index, int unknowns_length) +static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle_index, int unknowns_length, const struct pol_material_group *mg) { struct pol_triangle *t = &mesh->triangles[triangle_index]; t->vert_index[0] = buffer_read_int32(r); @@ -154,7 +154,9 @@ static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle read_direction(r, t->normals[0]); read_direction(r, t->normals[1]); read_direction(r, t->normals[2]); - t->material = buffer_read_int32(r); + t->material_group_index = buffer_read_int32(r); + if (t->material_group_index >= mg->nr_children) + t->material_group_index = 0; } static uint32_t parse_mesh_attributes(const char *name) @@ -173,7 +175,7 @@ static uint32_t parse_mesh_attributes(const char *name) return flags; } -static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version) +static struct pol_mesh *parse_mesh(struct buffer *r, const struct pol *pol) { int type = buffer_read_int32(r); if (type != 0) { @@ -185,11 +187,15 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version) mesh->name = read_cstring(r); mesh->flags = parse_mesh_attributes(mesh->name); mesh->material = buffer_read_int32(r); + if (mesh->material >= pol->nr_materials) { + WARNING("material index out of range (%d >= %d)", mesh->material, pol->nr_materials); + mesh->material = 0; + } mesh->nr_vertices = buffer_read_int32(r); mesh->vertices = xcalloc(mesh->nr_vertices, sizeof(struct pol_vertex)); for (uint32_t i = 0; i < mesh->nr_vertices; i++) { - parse_vertex(r, pol_version, &mesh->vertices[i]); + parse_vertex(r, pol->version, &mesh->vertices[i]); } mesh->nr_uvs = buffer_read_int32(r); @@ -209,7 +215,7 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version) } int triangle_unknowns_length = 12; - if (pol_version == 1) { + if (pol->version == 1) { int nr_unknown_vecs = buffer_read_int32(r); buffer_skip(r, nr_unknown_vecs * 12); } else { @@ -225,10 +231,10 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version) mesh->nr_triangles = buffer_read_int32(r); mesh->triangles = xcalloc(mesh->nr_triangles, sizeof(struct pol_triangle)); for (uint32_t i = 0; i < mesh->nr_triangles; i++) { - parse_triangle(r, mesh, i, triangle_unknowns_length); + parse_triangle(r, mesh, i, triangle_unknowns_length, &pol->materials[mesh->material]); } - if (pol_version == 1) { + if (pol->version == 1) { if (buffer_read_int32(r) != 1) WARNING("unexpected mesh footer"); if (buffer_read_int32(r) != 0) @@ -290,7 +296,7 @@ struct pol *pol_parse(uint8_t *data, size_t size) pol->nr_meshes = buffer_read_int32(&r); pol->meshes = xcalloc(pol->nr_meshes, sizeof(struct pol_mesh *)); for (uint32_t i = 0; i < pol->nr_meshes; i++) { - pol->meshes[i] = parse_mesh(&r, pol->version); + pol->meshes[i] = parse_mesh(&r, pol); } pol->nr_bones = buffer_read_int32(&r);