Skip to content

Commit 9913e20

Browse files
committed
extern: Implement support for line input in fast_obj
When the .OBJ file specifies polylines via `l` command, we now preserve them as is. Because faces and lines can interleave, and the lines are a comparatively rare feature, we encode these as a per-face attribute and let the caller figure it out. When face_lines[f] is 1, instead of treating the face as a polygon, applications should treat it as a line strip, with each vertex being connected to the previous one. To avoid the overhead during parsing, we lazily allocate the array when encountering the first line, and keep them synchronized afterwards.
1 parent 756c652 commit 9913e20

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

extern/fast_obj.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ typedef struct
137137
unsigned int face_count;
138138
unsigned int* face_vertices;
139139
unsigned int* face_materials;
140+
unsigned char* face_lines;
140141

141142
/* Index data: one element for each face vertex */
142143
unsigned int index_count;
@@ -734,7 +735,7 @@ const char* parse_normal(fastObjData* data, const char* ptr)
734735

735736

736737
static
737-
const char* parse_face(fastObjData* data, const char* ptr)
738+
const char* parse_face(fastObjData* data, const char* ptr, unsigned char line)
738739
{
739740
unsigned int count;
740741
fastObjIndex vn;
@@ -796,6 +797,16 @@ const char* parse_face(fastObjData* data, const char* ptr)
796797
array_push(data->mesh->face_vertices, count);
797798
array_push(data->mesh->face_materials, data->material);
798799

800+
if (line || data->mesh->face_lines)
801+
{
802+
/* when line info exists, ensure it uses aligned indexing with other face data */
803+
size_t skipped = array_size(data->mesh->face_vertices) - array_size(data->mesh->face_lines);
804+
while (--skipped > 0)
805+
array_push(data->mesh->face_lines, 0);
806+
807+
array_push(data->mesh->face_lines, line);
808+
}
809+
799810
data->group.face_count++;
800811
data->object.face_count++;
801812

@@ -1295,7 +1306,22 @@ void parse_buffer(fastObjData* data, const char* ptr, const char* end, const fas
12951306
{
12961307
case ' ':
12971308
case '\t':
1298-
p = parse_face(data, p);
1309+
p = parse_face(data, p, 0);
1310+
break;
1311+
1312+
default:
1313+
p--; /* roll p++ back in case *p was a newline */
1314+
}
1315+
break;
1316+
1317+
case 'l':
1318+
p++;
1319+
1320+
switch (*p++)
1321+
{
1322+
case ' ':
1323+
case '\t':
1324+
p = parse_face(data, p, 1);
12991325
break;
13001326

13011327
default:
@@ -1398,6 +1424,7 @@ void fast_obj_destroy(fastObjMesh* m)
13981424
array_clean(m->colors);
13991425
array_clean(m->face_vertices);
14001426
array_clean(m->face_materials);
1427+
array_clean(m->face_lines);
14011428
array_clean(m->indices);
14021429
array_clean(m->objects);
14031430
array_clean(m->groups);
@@ -1454,6 +1481,7 @@ fastObjMesh* fast_obj_read_with_callbacks(const char* path, const fastObjCallbac
14541481
m->colors = 0;
14551482
m->face_vertices = 0;
14561483
m->face_materials = 0;
1484+
m->face_lines = 0;
14571485
m->indices = 0;
14581486
m->materials = 0;
14591487
m->textures = 0;

0 commit comments

Comments
 (0)