Merge all face/index arrays together

Instead of each group storing a separate face/index array, we now store
one large face/index array and each group stores offsets inside it.

This makes it easier to parse .obj files when group information is
unimportant since one can just skip it - group information is often
inessential as it doesn't affect rendering behavior.

This makes parsing large files slightly faster (rungholt.obj parses in
~500ms instead of ~530ms after this change).
This commit is contained in:
Arseny Kapoulkine 2019-06-11 07:35:30 -07:00
parent c4c468f9db
commit 9aaef40e36
2 changed files with 38 additions and 27 deletions

View file

@ -88,14 +88,11 @@ typedef struct
/* Number of faces */ /* Number of faces */
unsigned int face_count; unsigned int face_count;
/* Material index for each face */ /* First face in fastObjMesh face_* arrays */
unsigned int* materials; unsigned int face_offset;
/* Vertex count for each face */ /* First index in fastObjMesh indices array */
unsigned int* vertices; unsigned int index_offset;
/* Array of indices */
fastObjIndex* indices;
} fastObjGroup; } fastObjGroup;
@ -112,6 +109,14 @@ typedef struct
unsigned int normal_count; unsigned int normal_count;
float* normals; float* normals;
/* Face data: one element for each face */
unsigned int face_count;
unsigned int* face_vertices;
unsigned int* face_materials;
/* Index data: one element for each face vertex */
fastObjIndex* indices;
/* Materials */ /* Materials */
unsigned int material_count; unsigned int material_count;
fastObjMaterial* materials; fastObjMaterial* materials;
@ -437,11 +442,10 @@ fastObjGroup group_default(void)
{ {
fastObjGroup group; fastObjGroup group;
group.name = 0; group.name = 0;
group.face_count = 0; group.face_count = 0;
group.materials = 0; group.face_offset = 0;
group.vertices = 0; group.index_offset = 0;
group.indices = 0;
return group; return group;
} }
@ -451,10 +455,6 @@ static
void group_clean(fastObjGroup* group) void group_clean(fastObjGroup* group)
{ {
memory_dealloc(group->name); memory_dealloc(group->name);
array_clean(group->materials);
array_clean(group->vertices);
array_clean(group->indices);
} }
@ -469,6 +469,8 @@ void flush_output(fastObjData* data)
/* Reset for more data */ /* Reset for more data */
data->group = group_default(); data->group = group_default();
data->group.face_offset = array_size(data->mesh->face_vertices);
data->group.index_offset = array_size(data->mesh->indices);
} }
@ -685,14 +687,14 @@ const char* parse_face(fastObjData* data, const char* ptr)
else else
vn.n = 0; vn.n = 0;
array_push(data->group.indices, vn); array_push(data->mesh->indices, vn);
count++; count++;
ptr = skip_whitespace(ptr); ptr = skip_whitespace(ptr);
} }
array_push(data->group.vertices, count); array_push(data->mesh->face_vertices, count);
array_push(data->group.materials, data->material); array_push(data->mesh->face_materials, data->material);
data->group.face_count++; data->group.face_count++;
@ -1245,6 +1247,9 @@ void fast_obj_destroy(fastObjMesh* m)
array_clean(m->positions); array_clean(m->positions);
array_clean(m->texcoords); array_clean(m->texcoords);
array_clean(m->normals); array_clean(m->normals);
array_clean(m->face_vertices);
array_clean(m->face_materials);
array_clean(m->indices);
array_clean(m->groups); array_clean(m->groups);
array_clean(m->materials); array_clean(m->materials);
@ -1277,11 +1282,14 @@ fastObjMesh* fast_obj_read(const char* path)
if (!m) if (!m)
return 0; return 0;
m->positions = 0; m->positions = 0;
m->texcoords = 0; m->texcoords = 0;
m->normals = 0; m->normals = 0;
m->materials = 0; m->face_vertices = 0;
m->groups = 0; m->face_materials = 0;
m->indices = 0;
m->materials = 0;
m->groups = 0;
/* Add dummy position/texcoord/normal */ /* Add dummy position/texcoord/normal */
@ -1371,6 +1379,7 @@ fastObjMesh* fast_obj_read(const char* path)
m->position_count = array_size(m->positions) / 3; m->position_count = array_size(m->positions) / 3;
m->texcoord_count = array_size(m->texcoords) / 2; m->texcoord_count = array_size(m->texcoords) / 2;
m->normal_count = array_size(m->normals) / 3; m->normal_count = array_size(m->normals) / 3;
m->face_count = array_size(m->face_vertices);
m->material_count = array_size(m->materials); m->material_count = array_size(m->materials);
m->group_count = array_size(m->groups); m->group_count = array_size(m->groups);

View file

@ -83,12 +83,14 @@ void compare_mesh(fastObjMesh* m, tinyObj* o)
int idx = 0; int idx = 0;
for (unsigned int jj = 0; jj < grp.face_count; jj++) for (unsigned int jj = 0; jj < grp.face_count; jj++)
{ {
CHECK(shp.mesh.num_face_vertices[jj] == grp.vertices[jj]); unsigned int fv = m->face_vertices[grp.face_offset + jj];
for (unsigned int kk = 0; kk < grp.vertices[jj]; kk++) CHECK(shp.mesh.num_face_vertices[jj] == fv);
for (unsigned int kk = 0; kk < fv; kk++)
{ {
index_t oi = shp.mesh.indices[idx]; index_t oi = shp.mesh.indices[idx];
fastObjIndex mi = grp.indices[idx]; fastObjIndex mi = m->indices[grp.index_offset + idx];
CHECK(oi.vertex_index + 1 == mi.p); CHECK(oi.vertex_index + 1 == mi.p);
CHECK(oi.texcoord_index + 1 == mi.t); CHECK(oi.texcoord_index + 1 == mi.t);