Hello everybody,
I have dealed with OpenGL 3.3 by the help of my old experiences in former versions of it for a few days and with long breaks.
I have wrote an OBJ loader function in C++ with SDL for things like window management, event handling and binding OpenGL context.
I used glDrawElements to reach my aim of loading an .obj model from any filepatch and drawing it in correct way as values the program got from the file are correct and match with buffer values.
The snippet I typed is:
GLuint LoadOBJ(char *filepath,GLuint *mdl_vb,GLuint *mdl_tb,GLuint *mdl_nb,GLuint *mdl_vidb,GLuint *mdl_tidb,GLuint *mdl_nidb)
{
char a,b,c;
char number[20]="";
GLuint vertex_id=0,
texture_id =0,
normal_id =0,
face_id =0,
*idptr;
GLfloat *vertexes=new float[30000],
*textures=new float[30000],
*normals =new float[30000],
*ptr;
GLuint faces[100000];
ifstream file;
file.open(filepath,ios::in);
if(file.is_open())
{
while(!file.eof())
{
a=file.get();
switch(a)
{
case '#':
while((a=file.get())!='
' && ! file.eof());
break;
case 'v':
b=file.get();
switch(b)
{
case ' ':
ptr=vertexes;
idptr=&vertex_id;
break;
case 't':
ptr=textures;
idptr=&texture_id;
break;
case 'n':
ptr=normals;
idptr=&normal_id;
break;
}
c=file.get();
while(c!='
' && !file.eof())
{
while(c==' ') c=file.get();
number[0]=c;
int i=1;
for( ;(c=file.get())>='-' && c<='9'; i++)
{
number[i]=c;
}
number[i]='\0';
*(ptr+(*idptr))=strtofloat(number);
(*idptr)++;
}
break;
case 'f':
c=file.get();
while(c!='
' && !file.eof())
{
while(c==' ' || c=='/') c=file.get();
number[0]=c;
int i=1;
for( ;(c=file.get())>='0' && c<='9'; i++)
{
number[i]=c;
}
number[i]='\0';
*(faces+face_id)=(GLuint)strtoint(number);
face_id++;
}
break;
case '
':
break;
default:
while((a=file.get())!='
' && ! file.eof());
break;
}
}
}
file.close();
GLuint model_vb,model_tb,model_nb,model_vidb,model_tidb,model_nidb;
glGenBuffers(1,&model_vb);
glBindBuffer(GL_ARRAY_BUFFER,model_vb);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(vertex_id),vertexes,GL_STATIC_DRAW);
glGenBuffers(1,&model_tb);
glBindBuffer(GL_ARRAY_BUFFER,model_tb);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(texture_id),textures,GL_STATIC_DRAW);
glGenBuffers(1,&model_nb);
glBindBuffer(GL_ARRAY_BUFFER,model_nb);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(normal_id),normals,GL_STATIC_DRAW);
delete[]vertexes;
delete[]textures;
delete[]normals;
GLuint *vertex_ids =new GLuint[50000],
*texture_ids=new GLuint[50000],
*normal_ids =new GLuint[50000];
int size_v,size_t,size_n;
int i=0;
for( ; i<face_id/3; i++)
{
vertex_ids[i]=faces[i*3 ]-1;
texture_ids[i]=faces[i*3+1]-1;
normal_ids[i]=faces[i*3+2]-1;
}
glGenBuffers(1,&model_vidb);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,model_vidb);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLuint)*i,vertex_ids,GL_STATIC_DRAW);
glGenBuffers(1,&model_tidb);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,model_tidb);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLuint)*i,texture_ids,GL_STATIC_DRAW);
glGenBuffers(1,&model_nidb);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,model_nidb);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLuint)*i,normal_ids,GL_STATIC_DRAW);
delete []vertex_ids;
delete []texture_ids;
delete []normal_ids;
*mdl_vb =model_vb;
*mdl_tb =model_tb;
*mdl_nb =model_nb;
*mdl_vidb=model_vidb;
*mdl_tidb=model_tidb;
*mdl_nidb=model_nidb;
return (face_id)/3;
}
void DrawOBJ(GLuint mdl_vb,GLuint mdl_tb,GLuint mdl_nb,GLuint mdl_vidb,GLuint mdl_tidb,GLuint mdl_nidb,GLuint used_vertex_number)
{
glBindBuffer(GL_ARRAY_BUFFER,mdl_vb);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mdl_vidb);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glBindBuffer(GL_ARRAY_BUFFER,mdl_tb);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mdl_tidb);
glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,0,(void*)0);
glBindBuffer(GL_ARRAY_BUFFER,mdl_nb);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mdl_nidb);
glVertexAttribPointer(3,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glDrawElements(GL_TRIANGLES,used_vertex_number,GL_UNSIGNED_INT,0);
}
Now, the result I got from this is not always as I expect. Sometimes it can accidently give correct shapes with lack of proper texture mapping.
It seems that the reason is not wrong values been taken from the file to buffers or incompatibility from 1-indexed to 0. The problem is that glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,xxx) doesn’t exist for glVertexAttribPointer unlike other GL_ARRAY_BUFFER. Since binding a buffer is only one current buffer related to which buffer we are talking about, last draw function consider only lastest bound buffer before its own. Hence, the last glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mdl_nidb) will be operated and this index array will be used for vertex,texture,normal buffers. And when I examined my object model file again, I figured out that all indexing of vertex and of normals were same so that the model is drown in correct way as shape but I can’t say same thing for texture indexing which wasn’t binded as last bound buffer and is cause of the disordered mapping.
If I am not wrong, the function of glDrawElements is as I mentioned above. Then what do you suggest to overcome multi-indexing without considering I am right or not?
Excuse for my bad English.
Thanks in advance.