Drawing an OBJ from structs

Member
Posts: 281
Joined: 2009.04
Post: #1
OK, I've been working on an .OBJ Loader for a while now for my game in C. I ended up using Kamran Paaji's code as a template. I can't see why It's not working.

weapon.c
Code:
int i;

    glTranslatef(0.0f,0.0f,-1.0f);
    glBegin(GL_TRIANGLES);

    for (i = 0 ; i < LCTcount ; i++)
    {
        glVertex3f(v[t[i].vert1-1].x, v[t[i].vert1-1].y, v[t[i].vert1-1].z);
        glVertex3f(v[t[i].vert2-1].x, v[t[i].vert2-1].y, v[t[i].vert2-1].z);
        glVertex3f(v[t[i].vert3-1].x, v[t[i].vert3-1].y, v[t[i].vert3-1].z);
    }
    glEnd();

func-declarations.h
Code:
extern struct LCtris {
    int vert1;
    int vert2;
    int vert3;
};

extern struct LCverts {
    float x;
    float y;
    float z;
}  ;

struct LCverts v[50000];
struct LCtris t[50000];

int LCVcount ;
int LCTcount ;


main.c

Code:
    struct LCverts v[50000];
struct    LCtris t[50000];

    int LCVcount = 0;
    int LCTcount = 0;
        
    char line[100];
    
    FILE * fp = fopen("cube.obj" , "r");
    
    
    if ( fp != NULL)
    {
        while ( fgets(line , 75 , fp) != NULL )
        {
            
            if (line[0] == 'v')
            {
                sscanf(line, " %*c %f %f %f ",    &v[LCVcount].x    , &v[LCVcount].y        , &v[LCVcount].z    );                  
                LCVcount++;
            }
            else if (line[0] == 'f')
            {
                sscanf(line, " %*c %d %d %d "    , &t[LCTcount].vert1        , &t[LCTcount].vert2        , &t[LCTcount].vert3        );
                LCTcount++;
            }       
        }
    }
    fclose(fp);

There is no errors according to GDB or Xcode's debugger. Nothing is drawn.

Huh

~ Bring a Pen ~
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #2
How is it not working? Is it not loading, not drawing, etc. Printing out the data structures after loading and other info can help point to the problem. Do that and share the info you get. This will allow us to understand what is happening, and help you in turn.

I remember that I used that example. I found that:
Code:
if(3==sscanf(line,"v %f %f %f",...//yada yada
Worked better.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #3
You should not write:
Code:
glVertex3f(v[t[i].vert1-1].x, v[t[i].vert1-1].y, v[t[i].vert1-1].z);

Instead lets define:
Code:
void vertex(LCverts xyz) { glVertex3f(xyz.x, xyz.y, xyz.z); }

and then we may write:
Code:
vertex(v[t[i].vert1-1]);


EDIT: I would also suggest that you may rather set the values vert1, vert2 and vert3 to be one less than read in, that lets you have:
Code:
vertex(v[t[i].vert1]);

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #4
Hello unknown and Oditty007.

If I change the code to:

Code:
            
            if (line[0] == 'v')
            {
                if ( sscanf(line , "%*c %f %f %f " , &v[LCVcount].x    , &v[LCVcount].y        , &v[LCVcount].z ) == 0 )
                    printf("line is 0");
                
                sscanf(line, " %*c %f %f %f ",    &v[LCVcount].x    , &v[LCVcount].y        , &v[LCVcount].z    );                  
                LCVcount++;
            }
            else if (line[0] == 'f')
            {
                
                sscanf(line, " %*c %d %d %d "    , &t[LCTcount].vert1        , &t[LCTcount].vert2        , &t[LCTcount].vert3        );
                LCTcount++;
            }

It prints line is 0 ten times. This is strange. cube.obj goes like this:


Code:
# Only 8 v's.
# 4 vt's
# 6 vn's
# 6 f's

#  ( â‰* 10 )

v -0.500000 -0.500000 0.500000  
v -0.500000 0.500000 0.500000  
v 0.500000 0.500000 0.500000    
v 0.500000 -0.500000 0.500000  
v 0.500000 -0.500000 -0.500000  
v 0.500000 0.500000 -0.500000  
v -0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000

vt 0.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 0.000000

vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 -1.000000
vn -1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 -1.000000 0.000000


f 4/4/1 3/3/1 2/2/1 1/1/1
f 8/4/2 7/3/2 6/2/2 5/1/2
f 1/4/3 2/3/3 7/2/3 8/1/3
f 5/4/4 6/3/4 3/2/4 4/1/4
f 3/4/5 6/3/5 7/2/5 2/1/5
f 5/4/6 4/3/6 1/2/6 8/1/6

So where does the ten come from? I think my problem is in loading the OBJ, but my code checks if it is NULL, so it's loaded something.

~ Bring a Pen ~
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #5
Its printing out "line is 0" because you have printf("line is 0");
It wont increment on itself!

As to the problem, your loader was made for triangulated obj's. Your cube is in quads.
Even if it did load, it wont draw correctly.

And, 'v' is the first char of "vt" "v" and "vn" all totaling 10 times. Then it gets to the sscanf, and after ignoring the first char it gets to the second, and exits with 0, not copying anything and acting as if it did, messing up the v counts, drawing blank. Thats why I said to use:

Code:
if(3==sscanf(line,"v %f %f %f",...//yada yada
This guarrantees it to be only matching "v"

Then f %i %i %i is what your code is looking for, f %i/%*i/%*i %i/%*i/%*i %i/%*i/%*i is what you need, but make a way to find all 3 variations.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #6
C (or at least scanf) is the wrong approach for this problem.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #7
Quote:C (or at least scanf) is the wrong approach for this problem.

Better ideas? While you're thinkin' Ill crack on.

~ Bring a Pen ~
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #8
Anybody? Please?

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,571
Joined: 2003.06
Post: #9
C and scanf work fine for this. Oddity007 has some great input.

mikey, I deliberately posted that obj cube a while back with quad sides since that would help encourage you to think about how the faces are constructed, since you'll want to at least support quads (in addition to triangles). So in this case you'll have to split each quad into two triangles. Do note that with obj's you might also encounter faces with more than four sides. You can either attempt to detect those and return an error, or ignore them I suppose, but just keep in mind that obj files are notoriously inconsistent in terms of sides and other random issues.

You're getting closer to being able to load obj files (especially now that you can load textures too), so keep at it! Again, be sure to carefully read this page, since it pretty much has all the info you'll need right now, and it's short. Try to draw out the cube obj file on graph paper if you have to to understand how the obj file is structured.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #10
AnotherJake Wrote:You can either attempt to detect those and return an error, or ignore them I suppose

Or automatically triangulate them at load time.
Quote this message in a reply
Moderator
Posts: 3,571
Joined: 2003.06
Post: #11
ThemsAllTook Wrote:Or automatically triangulate them at load time.

Oh ya, sure, except that I don't want to allude to the next chapter where we explain how to use glutess Wink
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #12
OK, I've taken Oddity007 (Thanks, BTW) advice and constructed this:

main.c

Code:
FILE * fp = fopen("Laser Carbine.obj" , "r");
    
    
    if ( fp != NULL)
    {
        while ( fgets(line , 75 , fp) != NULL )
        {
            
            if (3 == sscanf(line, "v %*f %*f %*f")  )
            {
                sscanf(line, " %*c %f %f %f ",    &v[LCVcount].x    , &v[LCVcount].y        , &v[LCVcount].z    );                  
                LCVcount++;
            }
            else if (3 == sscanf(line, "f %*i %*i %*i")  )
            {
                sscanf(line, " %*c %d %d %d "    , &t[LCTcount].vert1        , &t[LCTcount].vert2        , &t[LCTcount].vert3        );
                LCTcount++;
            }       
        }
    }
    fclose(fp);

weaponry.c

Code:
int i;
    
    glTranslatef(0.0f,0.0f,-1.0f);
    glBegin(GL_TRIANGLES);
    
    for (i = 0 ; i < LCTcount ; i++)
    {
        vertex(v[t[i].vert1-1]);
        
        
    }
    glEnd();

Yet still nothing is drawn.
"Laser Carbine" is an OBJ I had kicking around (It's all in triangles) but it's 3,000 lines plus, is this a problem?

My main 3D modeller (Art of Illusion) exports it's OBJ's as triangles, so do I have to include support for other polygons?

PS. It doesn't print line is 0 anymore.

~ Bring a Pen ~
Quote this message in a reply
Member
Posts: 351
Joined: 2002.04
Post: #13
I haven't had a good look through your code but you're only checking if fp != NULL, but not giving yourself a warning if it is NULL. So it could be that you file is not loading properly in the first place.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #14
I don't think it's NULL. In my if (fp != NULL) block, i added an else statement, which does not print Error. Thanks anyway though.

~ Bring a Pen ~
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #15
why have 75? maybe that's too small

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Weird behaviour with structs and the = operand Jones 2 2,576 Oct 12, 2006 07:11 PM
Last Post: Jones
  Free Structs Justin Brimm 4 3,362 May 30, 2006 06:20 AM
Last Post: Jones