View Full Version : Help with OBJ Loader

11-27-2002, 07:25 AM
Well I'm once again trying to write an obj loader but it keeps on crashing on me. Through debugging I have narrowed the crash down to one line. My obj loader is currently two passes, the first pass counts how much of each type there is, then it allocates memory accordingly, then it goes through again and assigns the memory. The problem I'm running into is with sscanf and I'm not worried about actually filling up the memory right now, just getting it to recongnize vertices, texture cords, and normals as needed. Does anybody see the problem with sscanf? Thanks

void readstr(FILE *f,char *string) // Reads A String From File (f)
do // Do This
fgets(string, 255, f); // Gets A String Of 255 Chars Max From f (File)
} while ((string[0] == '/') | | (string[0] == '\n')); // Until End Of Line Is Reached
return; // Return

int loadOBJ(const char *filename) {
char strLine[255] = { 0 };
// Check to make sure the extension is obj
int length;

// Vertice memory
float *vertx;
float *verty;
float *vertz;

// Texture Coordinate memory
float *texcordx;
float *texcordy;

// Lighting normal memory
float *lightingx;
float *lightingy;
float *lightingz;

int verts = 0; // how many vertices
int cords = 0; // how many texture coordinates
int normals = 0; // how many normals
int groups = 0; // how many groups
char c; // a simple buffer
char b; // another buffer
char d; // yet another buffer

char type[10]; // What type is the current line
float values[3]; // The values being read in
int counter[3] = { 0, 0, 0 }; // A counter for which line we are on
char charbuffer[255];
int percentRight = 0; // The percentage of values successfully matched

length = strlen(filename);
if( length < 5) {
cout << "Filename given to loadOBJ is too short to be complete. Aborting" << endl;
if(FILE *inputfile = fopen(filename, "r")) {
// Our first task will be to allocate all of the appropriate space for the vertices, texture cords, and lighting normals
while(feof(inputfile)==0) {
c = fgetc(inputfile);
if(c=='v') {
b = fgetc(inputfile);
if(b==' ') { // Its a vertex
//while(fgetc(inputfile) != '\n' &amp;#0124; &amp;#0124; '\r') { }
else if(b=='t') { // Its a texture cordinate
//while(fgetc(inputfile) != '\n' &amp;#0124; &amp;#0124; '\r') { }
else if(b=='n'){ // If its niether then its a lighting normal
//while(fgetc(inputfile) != '\n' &amp;#0124; &amp;#0124; '\r') { }
if(c=='g') {
//while(fgetc(inputfile) != '\n' &amp;#0124; &amp;#0124; '\r') { }
// Now establish memory for storing all of them

vertx = new float [verts];
verty = new float [verts];
vertz = new float [verts];

texcordx = new float [cords];
texcordy = new float [cords];

lightingx = new float [normals];
lightingy = new float [normals];
lightingz = new float [normals];
// Now read in all of the values to the memory after going back to the beginning
fseek(inputfile,0,SEEK_SET); // Reset to the beginning of the file
while(feof(inputfile)==0) {
readstr(inputfile, charbuffer);
sscanf(charbuffer, "%s %f %f %f", type, values[0], values[1], values[2]);
// Its a vertex or a normal
if(strcmp(type, "v")==0) {
cout << "vertex" << endl;
else if(strcmp(type, "vn")==0) {
cout << "lighting normal" << endl;

else if(strcmp(type, "vt")==0) {
cout << "Texture coordinate" << endl;

else {
cout << "skipped line" << endl;

cout << verts << " " << cords << " " << normals << " " << groups << endl;
return true;
else {
return false;

11-27-2002, 02:17 PM
no help for a struggling learner? http://www.opengl.org/discussion_boards/ubb/frown.gif

11-27-2002, 02:36 PM
Try this:
sscanf(charbuffer, "%s %f %f %f", &type, &values[0], &values[1], &values[2]);

Hope it works. Claude

11-27-2002, 03:14 PM
woot that worked thanks a ton dude! I can't believe I didn't try that...

11-27-2002, 05:04 PM
Ok I've started trying to parse the f lines but I'm running into some problems. Mainly I made a structure for the polygon faces that looks like this:

typedef struct {
int vertices[4];
int texCords[4];
int uvNormals[4];

int status; // 0 means everything is there, 1 means vertices and texCords, 2 means vertices and normals
} polyface;

and I need to have an array of this structure that is dynamically decided upon by how many f lines there are. So in my function I have a pointer that looks like this:

struct *faces;

and then after I know how many f lines there are I do:

faces = new polyface [facesn];

However it doesn't seem to like that last line (facesn is the number of f lines). It says Cannot convert polyface* to struct LoadOBJ::blehblehbleh

Also, how is the best way to go about deciding if the f line is leaving out uv cords, tex cords, or not? It would be easy if I could move the file pointer from the beginning of the line and back again. I tried looking at some tutorial but I looked all the way through their code and I don't even see how it works for them! Any help would be greatly appreciated. Thank you

11-28-2002, 05:14 AM
The code that you posted, does what you want to do.
The only thing left is to transfer the value
to the right array.

It goes through the file calculate the # of vertex, uvcoords and normal,
allocate memory for the arrays,
go back to the beginning of the file
and read the data.

Hope it helps Claude

11-28-2002, 05:42 AM
It won't compile though?? Also how do I reset the file reading point to the beginning of the line? I need to know this to determine if it is leaving out uv or text cords.

11-28-2002, 10:51 AM
I was making reference to your first post.
The code in that post seemed to be doing the job.Why change?

To make the correction compile,try this:
polyface *faces;

int vertices[4]; int texCords[4]
int uvNormals[4];
They are not integer.Check if you need 4 of
each.Use an array for each so that you dont
allocate memory if they dont exist.

Dont understand your last question.

Bye Claude

11-28-2002, 09:06 PM
You can take a look at topic "Problems with DrawElements", I've posted code there. I think it should be clearer. And maybe you'll spot the problem there http://www.opengl.org/discussion_boards/ubb/frown.gif