.obj Loader Problem

Member
Posts: 227
Joined: 2008.08
Post: #1
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;
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #2
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.
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #3
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.
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #4
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.
Quote this message in a reply
Member
Posts: 269
Joined: 2005.04
Post: #5
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.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #6
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
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #7
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]
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #8
You don't have an OpenGL context?
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #9
OpenGL is allowed to crash your app if you give it bad pointers.
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #10
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...
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #11
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.
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #12
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
Quote this message in a reply
Post Reply