242 lines
5.2 KiB
C
242 lines
5.2 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
|
|
* - 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)
|
|
*
|
|
*/
|
|
|
|
void storeFace(
|
|
face* f,
|
|
vec3* v1, vec2* vt1, vec3* vn1,
|
|
vec3* v2, vec2* vt2, vec3* vn2,
|
|
vec3* v3, vec2* vt3, vec3* vn3
|
|
) {
|
|
|
|
memcpy(&f->v1.position, v1, sizeof(vec3));
|
|
memcpy(&f->v2.position, v2, sizeof(vec3));
|
|
memcpy(&f->v3.position, v3, sizeof(vec3));
|
|
|
|
memcpy(&f->v1.normal, vn1, sizeof(vec3));
|
|
memcpy(&f->v2.normal, vn2, sizeof(vec3));
|
|
memcpy(&f->v3.normal, vn3, sizeof(vec3));
|
|
|
|
memcpy(&f->v1.texture, vt1, sizeof(vec2));
|
|
memcpy(&f->v2.texture, vt2, sizeof(vec2));
|
|
memcpy(&f->v3.texture, vt3, sizeof(vec2));
|
|
}
|
|
|
|
void storeTB(face* f,
|
|
vec3* v1, vec2* vt1,
|
|
vec3* v2, vec2* vt2,
|
|
vec3* v3, vec2* vt3
|
|
) {
|
|
// https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-13-normal-mapping/
|
|
vec3 deltaPos1;
|
|
vec3 deltaPos2;
|
|
|
|
vec3Subtract(&deltaPos1, v2, v1);
|
|
vec3Subtract(&deltaPos1, v3, v1);
|
|
|
|
vec2 deltaTex1;
|
|
vec2 deltaTex2;
|
|
|
|
vec2Subtract(&deltaTex1, vt2, vt1);
|
|
vec2Subtract(&deltaTex2, vt3, vt1);
|
|
|
|
GLfloat r = 1.0f / (deltaTex1.x * deltaTex2.y - deltaTex1.y * deltaTex2.x);
|
|
|
|
vec3Multiply(&deltaPos1, &deltaPos1, deltaTex2.y);
|
|
vec3Multiply(&deltaPos2, &deltaPos2, deltaTex1.y);
|
|
|
|
vec3 tangent;
|
|
vec3Subtract(&tangent, &deltaPos1, &deltaPos2);
|
|
vec3Multiply(&tangent, &tangent, r);
|
|
|
|
memcpy(&f->v1.tangent, &tangent, sizeof(vec3));
|
|
memcpy(&f->v2.tangent, &tangent, sizeof(vec3));
|
|
memcpy(&f->v3.tangent, &tangent, sizeof(vec3));
|
|
}
|
|
|
|
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);
|
|
|
|
vec2* textures = (vec2*) malloc(sizeof(vec2) * numTextureCoords);
|
|
|
|
face* faces = (face*) malloc(sizeof(face) * numFaces);
|
|
|
|
parsedFile.faces = faces;
|
|
parsedFile.length = numFaces;
|
|
|
|
rewind(fp);
|
|
|
|
uint curVertex = 0;
|
|
uint curNormal = 0;
|
|
uint curFace = 0;
|
|
uint curTexture = 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') {
|
|
|
|
int readValues = sscanf(buf,
|
|
"vt %f %f",
|
|
&textures[curTexture].x,
|
|
&textures[curTexture].y
|
|
);
|
|
|
|
if (readValues != 2) {
|
|
textures[curTexture].y = 0;
|
|
}
|
|
|
|
curTexture++;
|
|
|
|
|
|
} 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
|
|
);
|
|
|
|
storeFace(&faces[curFace],
|
|
&vertices[v1 - 1], &textures[vt1 - 1], &normals[vn1 - 1],
|
|
&vertices[v2 - 1], &textures[vt2 - 1], &normals[vn2 - 1],
|
|
&vertices[v3 - 1], &textures[vt3 - 1], &normals[vn3 - 1]
|
|
);
|
|
|
|
storeTB(&faces[curFace],
|
|
&vertices[v1 - 1], &textures[vt1 - 1],
|
|
&vertices[v2 - 1], &textures[vt2 - 1],
|
|
&vertices[v3 - 1], &textures[vt3 - 1]
|
|
);
|
|
|
|
curFace++;
|
|
|
|
int numSpaces = 0;
|
|
for (int i = 0; i < strlen(buf); i++) {
|
|
if (buf[i] == ' ') {
|
|
numSpaces++;
|
|
}
|
|
}
|
|
|
|
if (numSpaces == 4) {
|
|
storeTB(&faces[curFace],
|
|
&vertices[v1 - 1], &textures[vt1 - 1],
|
|
&vertices[v2 - 1], &textures[vt2 - 1],
|
|
&vertices[v3 - 1], &textures[vt3 - 1]
|
|
);
|
|
|
|
sscanf(buf,
|
|
"f %d/%d/%d %*d/%*d/%*d %d/%d/%d %d/%d/%d",
|
|
&v1, &vt1, &vn1,
|
|
&v2, &vt2, &vn2,
|
|
&v3, &vt3, &vn3
|
|
);
|
|
|
|
storeFace(&faces[curFace],
|
|
&vertices[v1 - 1], &textures[vt1 - 1], &normals[vn1 - 1],
|
|
&vertices[v2 - 1], &textures[vt2 - 1], &normals[vn2 - 1],
|
|
&vertices[v3 - 1], &textures[vt3 - 1], &normals[vn3 - 1]
|
|
);
|
|
|
|
curFace++;
|
|
}
|
|
|
|
|
|
// TODO: textures
|
|
}
|
|
|
|
}
|
|
|
|
free(vertices);
|
|
free(normals);
|
|
fclose(fp);
|
|
|
|
return parsedFile;
|
|
}
|
|
|
|
void clearParsedFile(ParsedObjFile file) {
|
|
free(file.faces);
|
|
} |