Skip to content

Instantly share code, notes, and snippets.

@joshbodily
Created January 29, 2025 17:42
Show Gist options
  • Save joshbodily/5cfb89169e413260893b0d28482621f0 to your computer and use it in GitHub Desktop.
Save joshbodily/5cfb89169e413260893b0d28482621f0 to your computer and use it in GitHub Desktop.
Parse .OBJ file for OpenGL
MyVertex* parseObjFile(const char* file, int* faces, int* lines) {
FILE* fp = NULL;
errno_t ferr = fopen_s(&fp, file, "r");
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* buffer = (char*)malloc(size + 1);
fread(buffer, 1, size, fp);
buffer[size] = '\0';
int numVertices = 0;
int numFaces = 0;
int numLines = 0;
char* start = buffer;
for (int i = 0; i < size;) {
// Search for the end
int lineLength = 0;
while (start[lineLength++] != '\n');
float vx, vy, vz;
int f1, f2, f3, t1, t2, t3;
if (sscanf_s(start, "v %f %f %f", &vx, &vy, &vz) == 3) {
numVertices++;
} else if (sscanf_s(start, "f %d/%d %d/%d %d/%d", &f1, &t1, &f2, &t2, &f3, &t3) == 6) {
numFaces++;
}
else if (sscanf_s(start, "l %d %d", &f1, &f2) == 2) {
numLines++;
}
assert(lineLength >= 0);
start += lineLength;
i += lineLength;
}
// Temporary for holding vertex definitions
MyVertex* verticesList = (MyVertex*)malloc(sizeof(MyVertex) * numVertices);
// "Actual" vertices
int numActualVertices = numFaces * 3 + numLines * 2;
MyVertex* vertices = (MyVertex*)malloc(sizeof(MyVertex) * numActualVertices);
start = buffer;
int vertex = 0;
for (int i = 0; i < size;) {
// Search for the end
int lineLength = 0;
while (start[lineLength++] != '\n');
float vx, vy, vz;
int f1, f2, f3, t1, t2, t3;
if (sscanf_s(start, "v %f %f %f", &vx, &vy, &vz) == 3) {
verticesList[vertex].x = vx;
verticesList[vertex].y = vy;
verticesList[vertex++].z = vz;
}
start += lineLength;
i += lineLength;
}
int currentMaterial = 0;
start = buffer;
vertex = 0;
for (int i = 0; i < size;) {
// Search for the end
int lineLength = 0;
while (start[lineLength++] != '\n');
float vx, vy, vz;
int f1, f2, f3, t1, t2, t3;
if (sscanf_s(start, "f %d/%d %d/%d %d/%d", &f1, &t1, &f2, &t2, &f3, &t3) == 6) {
vertices[vertex] = verticesList[f1 - 1];
setMaterial(&vertices[vertex++], currentMaterial, t1 - 1);
vertices[vertex] = verticesList[f2 - 1];
setMaterial(&vertices[vertex++], currentMaterial, t2 - 1);
vertices[vertex] = verticesList[f3 - 1];
setMaterial(&vertices[vertex++], currentMaterial, t3 - 1);
assert(vertex <= numActualVertices);
}
else if (sscanf_s(start, "l %d %d", &f1, &f2) == 2) {
vertices[vertex] = verticesList[f1 - 1];
setMaterial(&vertices[vertex++], currentMaterial, 0);
vertices[vertex] = verticesList[f2 - 1];
setMaterial(&vertices[vertex++], currentMaterial, 0);
assert(vertex <= numActualVertices);
}
else if (sscanf_s(start, "usemtl mtl_%X", &currentMaterial) == 1) {
// TODO: Make sure currentMaterial doesn't change if no match
}
start += lineLength;
i += lineLength;
}
free(verticesList);
free(buffer);
*faces = numFaces;
*lines = numLines;
return vertices;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment