iDevGames Forums
Drawing an OBJ from structs - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Drawing an OBJ from structs (/thread-1059.html)

Pages: 1 2 3 4


Drawing an OBJ from structs - mikey - Jul 4, 2009 06:07 AM

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


Drawing an OBJ from structs - Oddity007 - Jul 4, 2009 09:22 AM

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.


Drawing an OBJ from structs - unknown - Jul 4, 2009 11:03 AM

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]);



Drawing an OBJ from structs - mikey - Jul 5, 2009 04:02 AM

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.


Drawing an OBJ from structs - Oddity007 - Jul 5, 2009 05:24 AM

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.


Drawing an OBJ from structs - unknown - Jul 5, 2009 11:56 AM

C (or at least scanf) is the wrong approach for this problem.


Drawing an OBJ from structs - mikey - Jul 5, 2009 12:35 PM

Quote:C (or at least scanf) is the wrong approach for this problem.

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


Drawing an OBJ from structs - mikey - Jul 6, 2009 12:58 PM

Anybody? Please?


Drawing an OBJ from structs - AnotherJake - Jul 6, 2009 06:46 PM

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.


Drawing an OBJ from structs - ThemsAllTook - Jul 6, 2009 08:41 PM

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.


Drawing an OBJ from structs - AnotherJake - Jul 6, 2009 11:30 PM

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


Drawing an OBJ from structs - mikey - Jul 7, 2009 03:24 AM

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.


Drawing an OBJ from structs - monteboyd - Jul 7, 2009 04:42 AM

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.


Drawing an OBJ from structs - mikey - Jul 7, 2009 05:00 AM

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.


Drawing an OBJ from structs - unknown - Jul 7, 2009 08:15 AM

why have 75? maybe that's too small