136 lines
3.1 KiB
C++
136 lines
3.1 KiB
C++
#include "loader.h"
|
|
#include <cctype>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
|
|
// STATIC PROTOTYPES
|
|
static char *GetLine(char *buffer, int maxLength, FILE *fp);
|
|
static void ComputeNormals(Mesh &mesh);
|
|
|
|
|
|
// PUBLIC FUNCTIONS
|
|
int LoadMesh(char *filename, Mesh &mesh)
|
|
{
|
|
FILE *fp;
|
|
char buffer[256];
|
|
char *token;
|
|
|
|
char garbage[5];
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
if (fp == NULL)
|
|
{
|
|
fprintf(stderr, "Error loading file: %s\n", filename);
|
|
return -1;
|
|
}
|
|
|
|
token = GetLine(buffer, sizeof(buffer), fp);
|
|
|
|
while (token != NULL)
|
|
{
|
|
if (token[0] == 'v')
|
|
{
|
|
Vertex v;
|
|
|
|
sscanf(
|
|
token, "%s %f %f %f",
|
|
garbage,
|
|
&v.point.x,
|
|
&v.point.y,
|
|
&v.point.z);
|
|
|
|
mesh.local.verts.push_back(v);
|
|
}
|
|
else if (token[0] == 'f')
|
|
{
|
|
Face f;
|
|
|
|
sscanf(token, "%s %d %d %d",
|
|
garbage,
|
|
&f.vertIndex[0],
|
|
&f.vertIndex[1],
|
|
&f.vertIndex[2]);
|
|
|
|
// Convert to 0-indexed
|
|
f.vertIndex[0] -= 1;
|
|
f.vertIndex[1] -= 1;
|
|
f.vertIndex[2] -= 1;
|
|
|
|
mesh.local.faces.push_back(f);
|
|
}
|
|
|
|
token = GetLine(buffer, sizeof(buffer), fp);
|
|
}
|
|
|
|
ComputeNormals(mesh);
|
|
|
|
printf("OBJ: %s\n", filename);
|
|
printf("Verts: %lu\n", mesh.local.verts.size());
|
|
printf("Faces: %lu\n", mesh.local.faces.size());
|
|
|
|
mesh.transformed.verts.resize(mesh.local.verts.size());
|
|
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static char *GetLine(char *buffer, int maxLength, FILE *fp)
|
|
{
|
|
while(true)
|
|
{
|
|
if (!fgets(buffer, maxLength, fp))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// for (length = strlen(buffer), index = 0; isspace(buffer[index]); ++index);
|
|
|
|
if (buffer[0] != 'v' && buffer[0] != 'f')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
}
|
|
|
|
|
|
static void ComputeNormals(Mesh &mesh)
|
|
{
|
|
int *vertexNormalCount = (int*)calloc((size_t)(mesh.local.verts.size()), sizeof(int));
|
|
|
|
for (size_t f = 0; f < mesh.local.faces.size(); ++f)
|
|
{
|
|
unsigned int v0 = mesh.local.faces[f].vertIndex[0];
|
|
unsigned int v1 = mesh.local.faces[f].vertIndex[1];
|
|
unsigned int v2 = mesh.local.faces[f].vertIndex[2];
|
|
|
|
Vector v01 = mesh.local.verts[v1].point - mesh.local.verts[v0].point;
|
|
Vector v02 = mesh.local.verts[v2].point - mesh.local.verts[v0].point;
|
|
|
|
Vector normal = Vector::Cross(v01, v02);
|
|
|
|
// Add each vertex's normal to the sum for future averaging
|
|
mesh.local.verts[v0].normal += normal;
|
|
mesh.local.verts[v1].normal += normal;
|
|
mesh.local.verts[v2].normal += normal;
|
|
|
|
++vertexNormalCount[v0];
|
|
++vertexNormalCount[v1];
|
|
++vertexNormalCount[v2];
|
|
}
|
|
|
|
for (size_t v = 0; v < mesh.local.verts.size(); ++v)
|
|
{
|
|
if (vertexNormalCount[v] > 0)
|
|
{
|
|
// Compute the average normal for this vertex
|
|
mesh.local.verts[v].normal /= vertexNormalCount[v];
|
|
mesh.local.verts[v].normal.Normalize();
|
|
}
|
|
}
|
|
}
|