问题
I have been having problems rendering a model in opengl. I have made my own obj parser and a render function using glDrawElements but I can't see the problem. This is my parser function:
void load_obj(char *nom)
{
FILE *file = fopen(nom, "r");
int iv = 0, in = 0, it = 0, ifa = 0;
if(file != NULL)
{
while(1)
{
char lineHeader[128];
int res = fscanf(file, "%s", lineHeader);
if(res == EOF)
break;
if(strcmp(lineHeader, "v") == 0)
{
float vertex[3] = {0,0,0};
fscanf(file, "%f %f %f\n",
&vertex[0], &vertex[1], &vertex[2]);
vertices[iv] = vertex[0];
vertices[iv+1] = vertex[1];
vertices[iv+2] = vertex[2];
iv += 3;
}
else if(strcmp(lineHeader, "vt") == 0)
{
float tex_vert[2] = {0,0};
fscanf(file, "%f %f\n",
&tex_vert[0], &tex_vert[1]);
texturas[it] = tex_vert[0];
texturas[it+1] = tex_vert[1];
it += 2;
}
else if(strcmp(lineHeader, "vn") == 0)
{
float normal[3] = {0,0,0};
fscanf(file, "%f %f %f\n",
&normal[0], &normal[1], &normal[2]);
normales[in] = normal[0];
normales[in+1] = normal[1];
normales[in+2] = normal[2];
in += 3;
}
else if(strcmp(lineHeader, "f") == 0)
{
unsigned int vertexIndex[9] = {0,0,0,0,0,0,0,0,0};
fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
&vertexIndex[3], &vertexIndex[4], &vertexIndex[5],
&vertexIndex[6], &vertexIndex[7], &vertexIndex[8]);
vertTriangulos[ifa] = vertexIndex[0];
vertTriangulos[ifa+1] = vertexIndex[1];
vertTriangulos[ifa+2] = vertexIndex[2];
vertTriangulos[ifa+3] = vertexIndex[3];
vertTriangulos[ifa+4] = vertexIndex[4];
vertTriangulos[ifa+5] = vertexIndex[5];
vertTriangulos[ifa+6] = vertexIndex[6];
vertTriangulos[ifa+7] = vertexIndex[7];
vertTriangulos[ifa+8] = vertexIndex[8];
ifa += 9;
nTriangulos++;
}
}
}
And this is my draw function:
void draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texturas);
glNormalPointer(GL_FLOAT, 0, normales);
glDrawElements(GL_TRIANGLES, nTriangulos*9, GL_UNSIGNED_INT, vertTriangulos);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
Being the variables:
long nTriangulos;
float *vertices, *normales, *texturas;
unsigned int *vertTriangulos;
The obj file I'm using is a simple cube, but the mesh I'm rendering is a complete disaster.
EDIT: I have changed my code and now the parser looks like this:
if(strcmp(lineHeader, "f") == 0)
{
unsigned int vertexIndex[9] = {0,0,0,0,0,0,0,0,0};
fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
&vertexIndex[3], &vertexIndex[4], &vertexIndex[5],
&vertexIndex[6], &vertexIndex[7], &vertexIndex[8]);
for(int i = 0; i < 9; i += 3)
{
bool cierto = true;
int pos = 0;
if(indexbuff.size() > 0)
{
for(int i = 0; i < registro.size(); i++)
{
if(vertexIndex[0] == registro[i].in1
&& vertexIndex[1] == registro[i].in2
&& vertexIndex[2] == registro[i].in3)
{
cierto = false;
pos = i;
}
}
}
if(cierto)
{
verticebuff.push_back(vertices[vertexIndex[i]]);
verticebuff.push_back(vertices[vertexIndex[i]+1]);
verticebuff.push_back(vertices[vertexIndex[i]+2]);
textbuff.push_back(texturas[vertexIndex[i+1]]);
textbuff.push_back(texturas[vertexIndex[i+1]+1]);
normalbuff.push_back(normales[vertexIndex[i+2]]);
normalbuff.push_back(normales[vertexIndex[i+2]+1]);
normalbuff.push_back(normales[vertexIndex[i+2]+2]);
indexbuff.push_back(verticebuff.size()/3);
index3 indice;
indice.in1 = vertexIndex[i];
indice.in2 = vertexIndex[i+1];
indice.in3 = vertexIndex[i+2];
registro.push_back(indice);
}
else
{
indexbuff.push_back(i);
}
}
}
But it doesn't seem to work properly.
回答1:
Classic obj to opengl buffer mistake, the element buffer index points to all attributes. In other words if opengl sees a 0
index it takes the first element out of all the enabled buffers and move on to the next index. There is no way to use the obj structure directly without duplication of the data as you are reading
you face code should be
if(/*vertexIndex[0..2] triplet has not been seen yet*/){
verticebuff.pushback(vertices[vertexIndex[0]]);
verticebuff.pushback(vertices[vertexIndex[0]+1]);
verticebuff.pushback(vertices[vertexIndex[0]+2]);
textbuff.pushback(texturas[vertexIndex[1]]);
textbuff.pushback(texturas[vertexIndex[1]+1]);
normalbuff.pushback(normales[vertexIndex[2]]);
normalbuff.pushback(normales[vertexIndex[2]+1]);
indexbuff.pushback(verticebuff.size()/3);
} else {
indexbuff.pushback(/*index of the seen triplet*/);
}
//repeat 3 times
then you can paint them with draw elements.
来源:https://stackoverflow.com/questions/22185654/rendering-obj-files-with-opengl