computer-grafik-1/u07/wavefrontobj.c

167 lines
3.6 KiB
C

#include <GL/glew.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wavefrontobj.h"
#define OBJ_LINE_BUFFER_SIZE 256
/**
*
* ADJUSTMENT NEEDED FOR
* - Textures
* - Face Definitions other than vertex/texture/normal
* - Vertex positions including w
* - Any faces using vertices yet to be defined
* (File is read top to bottom. A face using a vertex
* defined underneath it in the file will not work)
*
*/
ParsedObjFile readObjFile(char* path) {
ParsedObjFile parsedFile;
FILE* fp = fopen(path, "r");
if (fp == NULL) {
fprintf(stderr, "File could not be opened: %s", path);
parsedFile.faces = NULL;
parsedFile.length = 0;
}
uint numVertices = 0;
uint numVertexNormals = 0;
uint numFaces = 0;
uint numTextureCoords = 0;
char buf[OBJ_LINE_BUFFER_SIZE];
while (fgets(buf, OBJ_LINE_BUFFER_SIZE, fp)) {
if (buf[0] == 'v') {
if (buf[1] == ' ') {
numVertices++;
} else if (buf[1] == 't') {
numTextureCoords++;
} else if (buf[1] == 'n') {
numVertexNormals++;
}
}
if (buf[0] == 'f') {
int numSpaces = 0;
for (int i = 0; i < strlen(buf); i++) {
if (buf[i] == ' ') {
numSpaces++;
}
}
numFaces += numSpaces - 2;
}
}
// printf("Vertices: %d\nFaces: %d\nNormals:%d\nTextures:%d\n", numVertices, numFaces, numVertexNormals, numTextureCoords);
vec3* vertices = (vec3*) malloc(sizeof(vec3) * numVertices);
vec3* normals = (vec3*) malloc(sizeof(vec3) * numVertexNormals);
face* faces = (face*) malloc(sizeof(face) * numFaces);
parsedFile.faces = faces;
parsedFile.length = numFaces;
rewind(fp);
uint curVertex = 0;
uint curNormal = 0;
uint curFace = 0;
while (fgets(buf, OBJ_LINE_BUFFER_SIZE, fp)) {
if (buf[0] == 'v') {
if (buf[1] == ' ') {
sscanf(buf,
"v %f %f %f",
&vertices[curVertex].x,
&vertices[curVertex].y,
&vertices[curVertex].z
);
curVertex++;
} else if (buf[1] == 't') {
continue;
} else if (buf[1] == 'n') {
sscanf(buf,
"vn %f %f %f",
&normals[curNormal].x,
&normals[curNormal].y,
&normals[curNormal].z
);
curNormal++;
}
}
if (buf[0] == 'f') {
int v1, v2, v3;
int vt1, vt2, vt3;
int vn1, vn2, vn3;
sscanf(buf,
"f %d/%d/%d %d/%d/%d %d/%d/%d",
&v1, &vt1, &vn1,
&v2, &vt2, &vn2,
&v3, &vt3, &vn3
);
memcpy(&faces[curFace].v1.position, &vertices[v1 - 1], sizeof(vec3));
memcpy(&faces[curFace].v2.position, &vertices[v2 - 1], sizeof(vec3));
memcpy(&faces[curFace].v3.position, &vertices[v3 - 1], sizeof(vec3));
memcpy(&faces[curFace].v1.normal, &normals[vn1 - 1], sizeof(vec3));
memcpy(&faces[curFace].v2.normal, &normals[vn2 - 1], sizeof(vec3));
memcpy(&faces[curFace].v3.normal, &normals[vn3 - 1], sizeof(vec3));
curFace++;
int numSpaces = 0;
for (int i = 0; i < strlen(buf); i++) {
if (buf[i] == ' ') {
numSpaces++;
}
}
if (numSpaces == 4) {
sscanf(buf,
"f %d/%d/%d %*d/%*d/%*d %d/%d/%d %d/%d/%d",
&v1, &vt1, &vn1,
&v2, &vt2, &vn2,
&v3, &vt3, &vn3
);
memcpy(&faces[curFace].v1.position, &vertices[v1 - 1], sizeof(vec3));
memcpy(&faces[curFace].v2.position, &vertices[v2 - 1], sizeof(vec3));
memcpy(&faces[curFace].v3.position, &vertices[v3 - 1], sizeof(vec3));
memcpy(&faces[curFace].v1.normal, &normals[vn1 - 1], sizeof(vec3));
memcpy(&faces[curFace].v2.normal, &normals[vn2 - 1], sizeof(vec3));
memcpy(&faces[curFace].v3.normal, &normals[vn3 - 1], sizeof(vec3));
curFace++;
}
// TODO: textures
}
}
free(vertices);
free(normals);
fclose(fp);
return parsedFile;
}
void clearParsedFile(ParsedObjFile file) {
free(file.faces);
}