1
0
Fork 0
2018-soft-3d-renderer/src/loader.cpp

136 lines
3.0 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.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.faces.push_back(f);
}
token = GetLine(buffer, sizeof(buffer), fp);
}
ComputeNormals(mesh);
printf("OBJ: %s\n", filename);
printf("Verts: %lu\n", mesh.verts.size());
printf("Faces: %lu\n", mesh.faces.size());
mesh.renderData.vertsTransformed.resize(mesh.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.verts.size()), sizeof(int));
for (size_t f = 0; f < mesh.faces.size(); ++f)
{
unsigned int v0 = mesh.faces[f].vertIndex[0];
unsigned int v1 = mesh.faces[f].vertIndex[1];
unsigned int v2 = mesh.faces[f].vertIndex[2];
Vector v01 = mesh.verts[v1].point - mesh.verts[v0].point;
Vector v02 = mesh.verts[v2].point - mesh.verts[v0].point;
Vector normal = Vector::Cross(v01, v02);
// Add each vertex's normal to the sum for future averaging
mesh.verts[v0].normal += normal;
mesh.verts[v1].normal += normal;
mesh.verts[v2].normal += normal;
++vertexNormalCount[v0];
++vertexNormalCount[v1];
++vertexNormalCount[v2];
}
for (size_t v = 0; v < mesh.verts.size(); ++v)
{
if (vertexNormalCount[v] > 0)
{
// Compute the average normal for this vertex
mesh.verts[v].normal /= vertexNormalCount[v];
mesh.verts[v].normal.Normalize();
}
}
}