iDevGames Forums
.obj Loader Problem - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: .obj Loader Problem (/thread-2057.html)



.obj Loader Problem - Oddity007 - Dec 9, 2008 05:37 PM

I keep getting errors with my .obj loader attempts, many many many many errors. Segmentation faults, unfound files, double free(), reallocing un-allocated data, Segmentation violation, -108058793 pointer value (0x1111111111111111111111111111111111111111111111111111111111111)
and many more. What in the world is going on? My bet is pointer problems.
Here is my code.
Code:
oeMesh* oeLoadObjFileNamed(char* filename){
    //printf("Trying to open %s.....",filename);
    FILE* file=fopen(filename,"r");
    //printf("Ok!\n");
    if(file==NULL){
        printf("Invallid file name %s\n",filename);
        exit(2);
    }
    oeMesh* m=calloc(1,sizeof(oeMesh));
    oeVec3*n; oeVec2* t;
    oeuint vcount,fcount,tcount,ncount,lineNumber;
    char buffer[1000],*line;
    int tID,nID;
    float x,y,z,u,v;
    int v1,v2,v3,t1,t2,t3,n1,n2,n3;
    m->v=calloc(1,sizeof(oeVertex));
    m->v=calloc(1,sizeof(oeFace));
    t=calloc(1,sizeof(oeVec2));
    n=calloc(1,sizeof(oeVec3));
    
    //printf("Allocated memory!\n");
    while(!feof(file)){
    //printf("Line %i\n",lineNumber);
        line=fgets(buffer,1000,file);
        lineNumber++;
        //printf("Line %s\n",line);
        if(sscanf(buffer,"v %f %f %f",&x,&y,&z)==3){
            vcount++;
            m->v=realloc(m->v,vcount*sizeof(oeVertex));
            m->v[vcount-1].x=x;m->v[vcount-1].y=y;m->v[vcount-1].z=z;
        }
        else if(sscanf(buffer,"vt %f %f",&x,&y)==2){
            tcount++;
            t=realloc(t,tcount*sizeof(oeVec2));
            t[tcount-1].x=x;t[tcount-1].y=y;
        }
        else if(sscanf(buffer,"vn %f %f %f",&x,&y,&z)==3){
            ncount++;
            n=realloc(n,ncount*sizeof(oeVec3));
            n[ncount-1].x=x;n[ncount-1].y=y;n[ncount-1].z=z;
        }
        else if(sscanf(buffer,"f %i/%i/%i %i/%i/%i %i/%i/%i",&v1,&t1,&n1,&v2,&t2,&n2,&v3,&t3,&n3)==9){
            fcount++;
            m->f=realloc(m->f,fcount*sizeof(oeFace));
            m->f[fcount-1].v[0]=v1-1;m->f[fcount-1].v[1]=v2-1;m->f[fcount-1].v[2]=v3-1;
            
            m->f[fcount-1].t[0][0]=t[t1-1].x;
            m->f[fcount-1].t[0][1]=t[t1-1].y;
            
            m->f[fcount-1].t[1][0]=t[t2-1].x;
            m->f[fcount-1].t[1][1]=t[t2-1].y;
            
            m->f[fcount-1].t[2][0]=t[t3-1].x;
            m->f[fcount-1].t[2][1]=t[t3-1].y;
            
            m->v[m->f[fcount-1].v[0]].normal.x=n[n1-1].x;
            m->v[m->f[fcount-1].v[0]].normal.y=n[n1-1].y;
            m->v[m->f[fcount-1].v[0]].normal.z=n[n1-1].z;
            
            m->v[m->f[fcount-1].v[1]].normal.x=n[n2-1].x;
            m->v[m->f[fcount-1].v[1]].normal.y=n[n2-1].y;
            m->v[m->f[fcount-1].v[1]].normal.z=n[n2-1].z;
            
            m->v[m->f[fcount-1].v[2]].normal.x=n[n3-1].x;
            m->v[m->f[fcount-1].v[2]].normal.y=n[n3-1].y;
            m->v[m->f[fcount-1].v[2]].normal.z=n[n3-1].z;
        }
        else if(sscanf(buffer,"f %i//%i %i//%i %i//%i",&v1,&n1,&v2,&n2,&v3,&n3)==6){
            fcount++;
            m->f=realloc(m->f,fcount*sizeof(oeFace));
            m->f[fcount-1].v[0]=v1;m->f[fcount-1].v[1]=v2;m->f[fcount-1].v[2]=v3;
            
            m->v[m->f[fcount-1].v[0]].normal.x=n[n1].x;
            m->v[m->f[fcount-1].v[0]].normal.y=n[n1].y;
            m->v[m->f[fcount-1].v[0]].normal.z=n[n1].z;
            
            m->v[m->f[fcount-1].v[1]].normal.x=n[n2].x;
            m->v[m->f[fcount-1].v[1]].normal.y=n[n2].y;
            m->v[m->f[fcount-1].v[1]].normal.z=n[n2].z;
            
            m->v[m->f[fcount-1].v[2]].normal.x=n[n3].x;
            m->v[m->f[fcount-1].v[2]].normal.y=n[n3].y;
            m->v[m->f[fcount-1].v[2]].normal.z=n[n3].z;
        }
        else if(sscanf(buffer,"f %i %i %i",&v1,&v2,&v3)==3){
            fcount++;
            m->f=realloc(m->f,fcount*sizeof(oeFace));
            m->f[fcount-1].v[0]=v1;m->f[fcount-1].v[1]=v2;m->f[fcount-1].v[2]=v3;
        }
        
    }
    //assignments go here
    m->count.v=vcount;
    m->count.f=fcount;
    
    fclose(file);
    free(t);
    free(n);
    return m;
}
And these are my structures:
Code:
typedef struct{
    float x,y,z;
    oeVec3 normal;
}oeVertex;
typedef struct{
    oeuint v[3];// 3 vertices
    float t[3][2];// 3 arrays of 2 texture uv
}oeFace;
typedef struct{
    struct{oeuint v,f;}count;
    oeVertex* v;
    oeFace* f;
}oeMesh;



.obj Loader Problem - longjumper - Dec 9, 2008 05:45 PM

Your tcount, vcount, etc., are not initialized to zero, and you start adding to them when they could be anything, then allocating a region that is 1 + whatever was currently at that spot in memory. Which could be just about anything.

You will gain more by just having static arrays than having to reallocate space over and over again, possibly thousands of times.


.obj Loader Problem - Oddity007 - Dec 9, 2008 06:08 PM

I did try this:
Code:
oeuint vcount,fcount,tcount,ncount,lineNumber;
vcount=tcount=fcount=ncount=0;
edit:
Sorry, my error is coming from this:
Code:
inline void oeMeshDraw(oeMesh* m){
    oeVertex* cv;oeFace* cf;oeVec3* cn;
    //printf("Drawing model...\n");
    glBegin(GL_TRIANGLES);
        for (int f = 0; f < m->count.f; f++) {
            cf=&m->f[f];
            for (int i = 0; i < m->count.v; i++) {
                cv=&m->v[cf->v[i]];
                cn=&cv->normal;
                glTexCoord2fv(&cf->t[i][0]);
                glNormal3f(cn->x,cn->y,cn->z);
                glVertex3f(cv->x,cv->y,cv->z);
                
                
            }
        }
    glEnd();
}

The line:
Code:
glNormal3f(cn->x,cn->y,cn->z);
is where I get a EXC_BAD_ACCESS.


.obj Loader Problem - Oddity007 - Dec 12, 2008 05:23 PM

Ive changed a few things, even tried making a buggy 3ds loader using lib3ds, now I wrote a new obj loader and still got errors.

Using this code:
Code:
inline void oeMeshDraw(oeMesh* m){
    oeVertex* cv;oeFace* cf;oeVec3* cn;
    //printf("Drawing model...\n");
    glBegin(GL_TRIANGLES);
        for (int f = 0; f < m->count.f; f++) {
            cf=&m->f[f];
            for (int i = 0; i <3; i++) {
                cv=&m->v[cf->v[i]];
                cn=&cv->normal;
                glNormal3f(cn->x,cn->y,cn->z);
                glTexCoord2f(cv->tex[0],cv->tex[1]);
                glVertex3f(cv->x,cv->y,cv->z);
            }
        }
    glEnd();
}

oeMesh* oeLoadObjFile(char* filename){
    oeMesh* m;
    int fcount,vcount;
    int cv,cf,ct,cn,v1,v2,v3;
    char buffer[256];
    float x,y,z;
    
    cv=cf=ct=cn=fcount=vcount=0;
    
    FILE* file=fopen(filename,"r");
        if(file==NULL){
                printf("File named %s doesn't open\n",filename);
                return NULL;
        }
    while(!feof(file)){
        fgets(buffer,255,file);
        if((buffer[0]=='v')&&(buffer[1]==' ')){
            vcount++;
            
        }
        else if((buffer[0]=='f')&&(buffer[1]==' ')){
            fcount++;
            
        }

    }
    rewind(file);
    printf("vcount:%i\n",vcount);
    printf("fcount:%i\n",fcount);
    m=calloc(1,sizeof(oeMesh));
    m->v=calloc(vcount,sizeof(oeVertex));
    m->f=calloc(fcount,sizeof(oeFace));
    
    if(m->f==NULL){
        printf("Couldn't allocate %i faces for file named %s\n",fcount,filename);
        return NULL;
    }

    if(m->v==NULL){
        printf("Couldn't allocate %i vertices for file named %s\n",vcount,filename);
        return NULL;
    }

    m->count.f=fcount;
    m->count.v=vcount;
    
    while(!feof(file)){
        fgets(buffer,255,file);
        if(3==sscanf(buffer,"v %f %f %f",&x,&y,&z)){
            cv++;
            m->v[cv].x=x;
            m->v[cv].y=y;
            m->v[cv].z=z;
        }
        else if(2==sscanf(buffer,"vt %f %f",&x,&y)){
            ct++;
            m->v[ct].tex[0]=x;
            m->v[ct].tex[1]=y;
        }
        else if(3==sscanf(buffer,"vn %f %f %f",&x,&y,&z)){
            cn++;
            m->v[cn].normal.x=x;
            m->v[cn].normal.y=y;
            m->v[cn].normal.z=z;
        }
        else if(9==sscanf(buffer,"f %i/%*i/%*i %i/%*i/%*i %i/%*i/%*i",&v1,&v2,&v3)){
            cf++;
            m->f[cf].v[0]=v1-1;
            m->f[cf].v[1]=v2-1;
            m->f[cf].v[2]=v3-1;
        }
        else if(6==sscanf(buffer,"f %i//%*i %i//%*i %i//%*i",&v1,&v2,&v3)){
            cf++;
            printf("f%i %i %i\n",v1-1,v2-1,v3-1);
            m->f[cf].v[0]=v1-1;
            m->f[cf].v[1]=v2-1;
            m->f[cf].v[2]=v3-1;
        }
        else if(3==sscanf(buffer,"f %i %i %i",&v1,&v2,&v3)){
            cf++;
            printf("f%i %i %i\n",v1-1,v2-1,v3-1);
            m->f[cf].v[0]=v1-1;
            m->f[cf].v[1]=v2-1;
            m->f[cf].v[2]=v3-1;
        }


    }
    fclose(file);
    return m;
}
I assumed that no exporter would bother optimizing and so vn 5 is the normal of v 5.


.obj Loader Problem - Bachus - Dec 12, 2008 09:55 PM

Oddity007 Wrote:I assumed that no exporter would bother optimizing and so vn 5 is the normal of v 5.

That's a dangerous assumption to make. Vertices get split depending on texture coordinates and normals. Multiple faces may use the same vertex over and over, but with different tex coords and normals. You're likely to have wildly wrong textures and lighting like that.


.obj Loader Problem - DoG - Dec 13, 2008 05:46 AM

No matter what file format you load, you will most likely have to swizzle things to get homogenous arrays that OpenGL can display efficiently. It's not even very difficult to do so, but best left as an exercise to the reader Smile


.obj Loader Problem - Oddity007 - Dec 13, 2008 05:57 PM

Dog Wrote:No matter what file format you load, you will most likely have to swizzle things to get homogeneous arrays that OpenGL can display efficiently. It's not even very difficult to do so, but best left as an exercise to the reader Smile

Huh? I haven't heard of this one.
Back on the original subject:
It appears to get the error from the drawing code.
My guess is an opengl problem as the gdb error comes from its functions.
Here it is:
[Image: picture1dr3.png]


.obj Loader Problem - DoG - Dec 13, 2008 07:48 PM

You don't have an OpenGL context?


.obj Loader Problem - arekkusu - Dec 13, 2008 08:24 PM

OpenGL is allowed to crash your app if you give it bad pointers.


.obj Loader Problem - Oddity007 - Dec 14, 2008 01:41 PM

I have a valid opengl context.
@ arekkusu: Opengl isn't crashing my app, Its getting stuck in a loop and endlessly trying to fix itself.
Opengl is failing to make a display list but not giving an error...


.obj Loader Problem - arekkusu - Dec 14, 2008 02:37 PM

Your screenshot says EXC_BAD_ACCESS. That's a crash. What makes you think it's a loop?

Right before that, it's warning you that you've freed a buffer you didn't allocate, so it seems likely that you're passing a bad pointer to OpenGL.

To debug this, try:
* turn off display lists. Long term, you shouldn't use display lists anyway.
* null out your pointers everywhere you free memory.
* add asserts in your functions where you're dereferencing your model pointers like m-> and cf->. Those can't be null.
* instrument all of your alloc and frees, so you can see the pattern.
* read the libgmalloc manpage, then use it to catch accesses outside of your allocations early.


.obj Loader Problem - Oddity007 - Dec 14, 2008 02:54 PM

Sorry, I fixed this problem a few minutes ago. I was In the process of editing my post when the power went out. It works, I had accidentally forgot to return my DL id in the loader function. I was absent minded. Smile