I hope I find all the help I need here... This is the problem I have.
I am trying to create a .obj model loader (from .obj files). Searching the internet, I found the specification, and I started programming based on that. here is what I have done so far:
ObjLoaders.h
ObjLoaders.cpp
the code to draw:
Although something is drawn to the screen, I only see garbage! The file is parsed correctly, and all classes end up in having the correct variables stored in them. So it must be a logic error, and not a programming one (and logic errors are hard to spot!). For simplicity reasons I haven't implemented texture or material support, and I am trying to load a file that only contains vertex and vertex normals data.
I am attaching the file, in case you want to run the code yourself.
NOTE: What happened to my identation? Why is the code being displayed so badly? I strongly recommend you paste it into an editor...
The result should be a lightcycle (remember the movie "Tron"?) or at least something that looks like it. But instead I see garbage... Can anyone help me?
I am trying to create a .obj model loader (from .obj files). Searching the internet, I found the specification, and I started programming based on that. here is what I have done so far:
ObjLoaders.h
Code:
#ifndef OBJLOADERS_H
#define OBJLOADERS_H
#include <iostream>
#include <vector>
#include <string>
#include <OpenGL/OpenGL.h>
#include <OpenGL/glu.h>
using namespace std;
typedef float vector3f[3];
class OBJFileInfo{
public:
unsigned numVertices;
unsigned numTriangles;
unsigned numVertexNormals;
unsigned numTextureVertex;
OBJFileInfo(){
numVertices = 0;
numTriangles = 0;
numVertexNormals = 0;
numTextureVertex = 0;
}
};
class Triangle{
public:
unsigned TriangleEdges[3];
unsigned TriangleTextureCoords[3];
unsigned TriangleNormals[3];
Triangle(const Triangle& otherTriangle){
for (int i=0; i<3; i++) {
TriangleEdges[i] = otherTriangle.TriangleEdges[i];
TriangleTextureCoords[i] = otherTriangle.TriangleTextureCoords[i];
TriangleNormals[i] = otherTriangle.TriangleNormals[i];
}
}
Triangle(){
reset();
}
void reset(){
for (int i=0; i<3; i++) {
TriangleEdges[i] = 0;
TriangleTextureCoords[i] = 0;
TriangleNormals[i] = 0;
}
}
};
class OBJModel{
OBJFileInfo fileinfo;
public:
vector3f* vertices;
vector3f* vertexNormals;
vector3f* textureVertices;
//Triangle* triangles;
vector<Triangle> triangles;
OBJModel(OBJFileInfo info){
fileinfo = info;
vertices = new vector3f[info.numVertices];
vertexNormals = new vector3f[info.numVertexNormals];
textureVertices = new vector3f[info.numTextureVertex];
//triangles = new Triangle[info.numTriangles];
}
void vertexAtIndex(unsigned index, vector3f resultBuffer){
resultBuffer[0] = vertices[index][0];
resultBuffer[1] = vertices[index][1];
resultBuffer[1] = vertices[index][1];
}
void drawVertexAtIndex(unsigned index){
vector3f vertexToDraw;
vertexToDraw[0] = vertices[index][0];
vertexToDraw[1] = vertices[index][1];
vertexToDraw[1] = vertices[index][1];
glVertex3f(vertexToDraw[0], vertexToDraw[1], vertexToDraw[2]);
}
//TO BE COMPLETED!!!
void drawFaceAtIndex(unsigned index){
unsigned triangleVertexPositions[3];
triangleVertexPositions[0] = triangles[index].TriangleEdges[0];
triangleVertexPositions[1] = triangles[index].TriangleEdges[1];
triangleVertexPositions[2] = triangles[index].TriangleEdges[2];
//cout << triangles[index].TriangleEdges[0] << " " << triangles[index].TriangleEdges[0] << " " << triangles[index].TriangleEdges[0] << '\n';
vector3f v1, v2, v3;
v1[0] = vertices[triangleVertexPositions[0]][0];
v1[1] = vertices[triangleVertexPositions[0]][1];
v1[2] = vertices[triangleVertexPositions[0]][2];
v2[0] = vertices[triangleVertexPositions[1]][0];
v2[1] = vertices[triangleVertexPositions[1]][1];
v2[2] = vertices[triangleVertexPositions[1]][2];
v3[0] = vertices[triangleVertexPositions[2]][0];
v3[1] = vertices[triangleVertexPositions[2]][1];
v3[2] = vertices[triangleVertexPositions[2]][2];
cout << v1[0] << " " << v1[1] << " " << v1[2] << '\n';
cout << v2[0] << " " << v2[1] << " " << v2[2] << '\n';
cout << v3[0] << " " << v3[1] << " " << v3[2] << '\n';
glBegin(GL_TRIANGLES);
glVertex3f(v1[0], v1[1], v1[2]);
glVertex3f(v2[0], v2[1], v2[2]);
glVertex3f(v3[0], v3[1], v3[2]);
glEnd();
}
~OBJModel()
{
delete [] vertices;
delete [] vertexNormals;
delete [] textureVertices;
//delete [] triangles;
}
unsigned numVertices(){return fileinfo.numVertices;}
unsigned numTriangles(){return fileinfo.numTriangles;}
unsigned numVertexNormals(){return fileinfo.numVertexNormals;}
unsigned numTextureVertex(){return fileinfo.numTextureVertex;}
};
void firstPass(char *filename, OBJFileInfo& info);
void secondPass(char *filename, OBJModel *model);
#endif
ObjLoaders.cpp
Code:
#include "ObjLoaders.h"
void firstPass(char *filename, OBJFileInfo& info)
{
char buf[128];
FILE *filePointer = fopen(filename, "r");
while ( fscanf(filePointer, "%s", buf) != EOF){
switch (buf[0]) {
case 'v':
switch (buf[1]) {
case 't':
fgets(buf, sizeof(buf), filePointer);
info.numTextureVertex++;
break;
case '\0':
fgets(buf, sizeof(buf), filePointer);
info.numVertices++;
break;
case 'n':
fgets(buf, sizeof(buf), filePointer);
info.numVertexNormals++;
break;
default:
break;
}
break;
case '#':
fgets(buf, sizeof(buf), filePointer);
break;
case 'f':
info.numTriangles++;
//NSLog(@"not implemented yet! %i", info.numTriangles);
break;
default:
fgets(buf, sizeof(buf), filePointer);
break;
}
}
fclose(filePointer);
info.numTriangles--;
}
void secondPass(char *filename, OBJModel *model){
char buf[128];
FILE *filePointer = fopen(filename, "r");
unsigned currentVertexIndex = 0;
unsigned currentvertexNormalIndex = 0;
unsigned currentTextureVertexIndex = 0;
unsigned currentTriangleIndex = 0;
while ( fscanf(filePointer, "%s", buf) != EOF ) {
switch (buf[0]) {
case 'v':{
switch (buf[1]) {
case '\0':{
float a,b,c;
fscanf(filePointer, "%f %f %f", &a, &b, &c);
model->vertices[currentVertexIndex][0] = a;
model->vertices[currentVertexIndex][1] = b;
model->vertices[currentVertexIndex][2] = c;
//cout << a << " " << b << " " << c << '\n';
currentVertexIndex++;
}
break;
case 'n':{
float a,b,c;
fscanf(filePointer, "%f %f %f", &a, &b, &c);
//cout << a << ' ' << b << ' ' << c << '\n';
model->vertexNormals[currentvertexNormalIndex][0] = a;
model->vertexNormals[currentvertexNormalIndex][1] = b;
model->vertexNormals[currentvertexNormalIndex][2] = c;
currentvertexNormalIndex++;
}
break;
case 't':{
float a,b,c;
fscanf(filePointer, "%f %f %f", &a, &b, &c);
model->textureVertices[currentTextureVertexIndex][0] = a;
model->textureVertices[currentTextureVertexIndex][1] = b;
model->textureVertices[currentTextureVertexIndex][2] = c;
currentTextureVertexIndex++;
}
break;
default:
break;
}
}
break;
case 'f':{
Triangle currentTriangle;
int v,t,n = 0;
fscanf(filePointer, "%s", buf);
if ( strstr(buf, "//") ) {
sscanf(buf, "%d//%d", &v, &n);
currentTriangle.TriangleEdges[0] = v;
currentTriangle.TriangleNormals[0] = n;
fscanf(filePointer, "%d//%d", &v, &n);
currentTriangle.TriangleEdges[1] = v;
currentTriangle.TriangleNormals[1] = n;
fscanf(filePointer, "%d//%d", &v, &n);
currentTriangle.TriangleEdges[2] = v;
currentTriangle.TriangleNormals[2] = n;
}
else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3){
currentTriangle.TriangleEdges[0] = v;
currentTriangle.TriangleTextureCoords[0] = t;
currentTriangle.TriangleNormals[0] = n;
fscanf(filePointer, "%d/%d%d", ¤tTriangle.TriangleEdges[1], ¤tTriangle.TriangleTextureCoords[1], ¤tTriangle.TriangleTextureCoords[1]);
fscanf(filePointer, "%d/%d%d", ¤tTriangle.TriangleEdges[1], ¤tTriangle.TriangleTextureCoords[1], ¤tTriangle.TriangleNormals[1]);
}
else if (sscanf(buf, "%d/%d", &v, &t) == 2){
currentTriangle.TriangleTextureCoords[0] = t;
currentTriangle.TriangleEdges[0] = v;
fscanf(filePointer, "%d/%d", ¤tTriangle.TriangleEdges[1], ¤tTriangle.TriangleTextureCoords[1]);
fscanf(filePointer, "%d/%d", ¤tTriangle.TriangleEdges[2], ¤tTriangle.TriangleTextureCoords[2]);
}
else {
sscanf(buf, "%d", &v);
currentTriangle.TriangleEdges[0] = v;
fscanf(filePointer, "%d", currentTriangle.TriangleEdges[1]);
fscanf(filePointer, "%d", currentTriangle.TriangleEdges[2]);
}
//cout << currentTriangleIndex << ": ";
//cout << "f " << currentTriangle.TriangleEdges[0] << "/" << currentTriangle.TriangleTextureCoords[0] << "/" << currentTriangle.TriangleNormals[0];
//cout << currentTriangle.TriangleEdges[1] << "/" << currentTriangle.TriangleTextureCoords[1] << "/" << currentTriangle.TriangleNormals[0];
//cout << currentTriangle.TriangleEdges[2] << "/" << currentTriangle.TriangleTextureCoords[2] << "/" << currentTriangle.TriangleNormals[2] << '\n';
//cout << "f " << currentTriangle.TriangleEdges[0] << "//" << currentTriangle.TriangleNormals[0] << " ";
//cout << currentTriangle.TriangleEdges[1] << "//" << currentTriangle.TriangleNormals[1] << " ";
//cout << currentTriangle.TriangleEdges[2] << "//" << currentTriangle.TriangleNormals[2] << "\n";
model->triangles.push_back(currentTriangle);
currentTriangleIndex++;
}
break;
default:
fgets(buf, sizeof(buf), filePointer);
break;
}
}
}
the code to draw:
Code:
OBJFileInfo objFile;
firstPass(FILENAME2, objFile);
OBJModel model(objFile);
secondPass(FILENAME2, &model);
model.drawFaceAtIndex(1);
Although something is drawn to the screen, I only see garbage! The file is parsed correctly, and all classes end up in having the correct variables stored in them. So it must be a logic error, and not a programming one (and logic errors are hard to spot!). For simplicity reasons I haven't implemented texture or material support, and I am trying to load a file that only contains vertex and vertex normals data.
I am attaching the file, in case you want to run the code yourself.
NOTE: What happened to my identation? Why is the code being displayed so badly? I strongly recommend you paste it into an editor...
The result should be a lightcycle (remember the movie "Tron"?) or at least something that looks like it. But instead I see garbage... Can anyone help me?