Hello.
I'm developing an Android application with OpenGL ES 2.0.
I want to load an export made with Blender 2.49b in Wavefront OBJ format. I have identified verxtex position, normal and texture.
I want to use glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) to draw my mesh but I don't know how I can obtain the last parameter, indices, from a Wavefront OBJ file.
Are faces the 'indices' that I'm looking for?
I've found this on a forum:
faces = indices starting with 1!
What is the meaning of 'starting with 1!'?
Thanks.
OpenGL ES 2.0. How to obtain indices from a Wavefront OBJ file?
The indices are the f parameters.
They look something like this (depending on what data you exported):
x being an arbitrary number.
The indices in OBJ files are 1-based array indices, meaning that x=1 is the first vertex/texcoord/normal.
The indices in most programming languages are 0-based array indices, meaning that x=0 is the first element.
This simply means that when you load the indices into your application, subtract 1 from them and you'll be fine on that front.
Another issue is that it exports shared data.
This means that a triangle consisting of 3 vertices, texcoords and normals might look like this:
Where every triple is v/t/n (vertex/texcoord/normal) if I remember correctly.
This doesn't work with OpenGL since it expects data to be seperated, as in
This problem is harder to solve - you'll need to search for vertices with different normals/texcoords and duplicate them accordingly, since they are actually different vertices.
This is why it's much easier to draw OBJ files with glBegin/End, and I can only assume OBJ files look like this because glBegin/End and the DX equivalent was the only thing back then.
As a last thought - OBJ files are a big piece of crap that I have no idea how someone was stupid enough to make up.
It's easier both for the computer and for humans to write linear data, and it would load a magnitude times faster...
If you can make a simple script for Blender, you can export something like this:
And if you can make that in binary, loading this file would take 3 memcpy's, instead of the hell of OBJ file retard-ness.
Another solution is to make an OBJ -> your format converter in case you don't know how to write a script for Blender.
Now seriously...what were they thinking about when making such an idiotic format?
They look something like this (depending on what data you exported):
f x/x/x x/x/x x/x/x
x being an arbitrary number.
The indices in OBJ files are 1-based array indices, meaning that x=1 is the first vertex/texcoord/normal.
The indices in most programming languages are 0-based array indices, meaning that x=0 is the first element.
This simply means that when you load the indices into your application, subtract 1 from them and you'll be fine on that front.
Another issue is that it exports shared data.
This means that a triangle consisting of 3 vertices, texcoords and normals might look like this:
f 1/2/4 2/10/1 3/2/4
Where every triple is v/t/n (vertex/texcoord/normal) if I remember correctly.
This doesn't work with OpenGL since it expects data to be seperated, as in
1/1/1 3/3/3 8/8/8
This problem is harder to solve - you'll need to search for vertices with different normals/texcoords and duplicate them accordingly, since they are actually different vertices.
This is why it's much easier to draw OBJ files with glBegin/End, and I can only assume OBJ files look like this because glBegin/End and the DX equivalent was the only thing back then.
As a last thought - OBJ files are a big piece of crap that I have no idea how someone was stupid enough to make up.
It's easier both for the computer and for humans to write linear data, and it would load a magnitude times faster...
If you can make a simple script for Blender, you can export something like this:
4 // number of elements-1 1 0 // vertex 0 ...-1 -1 01 -1 01 1 00 0 // texcoord 0...0 11 11 00 0 1 // normal 0...0 0 10 0 10 0 1
And if you can make that in binary, loading this file would take 3 memcpy's, instead of the hell of OBJ file retard-ness.
Another solution is to make an OBJ -> your format converter in case you don't know how to write a script for Blender.
Now seriously...what were they thinking about when making such an idiotic format?
Thanks for your answer. But...
I've found this on a forum:
faces = indices starting with 1!
What is the meaning of 'starting with 1!'? Should I subtract one to all values?
I've found this on a forum:
faces = indices starting with 1!
What is the meaning of 'starting with 1!'? Should I subtract one to all values?
check out this page:
http://en.wikipedia.org/wiki/Obj
I assume that for every vertex the position, texcoord and the normal is stored in your obj file. your data will look something like this:
# faces
f 6/4/1 3/5/3 7/6/5
f 8/3/7 4/7/0 6/9/2
f 4/5/3 6/6/1 4/6/1
...
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
so basicly you have 3 indices for every vertex in order to use this data for rendering you need to unpack it.
Array<Vector3> vertices;
Array<Vector3> texcoords;
Array<Vector3> normals;
// read obj
- read all vertices from obj and stored in vertices
- read all texcoords from obj and store in texcoords
- read all normals from obj and sotre in normals
// Now read the # faces section and get the correct v, vt, vn according to the indices. for every face you read add the data to a new list
Array<Vector3> verticesUnpacked;
Array<Vector3> texcoordsUnpacked;
Array<Vector3> normalsUnpacked;
Array<int> indicesUnpacked;
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
// Vertices for this face
Vector3 vertex1 = vertices[v1];
verticesUnpacked.Add(vertex1);
Vector3 vertex2 = vertices[v2];
verticesUnpacked.Add(vertex2);
Vector3 vertex3 = vertices[v3];
verticesUnpacked.Add(vertex3);
// Texcoords for this face
Vector3 tex1 = texcoords[vt1];
texcoordsUnpacked.Add(tex1);
Vector3 tex2 = texcoords[vt2];
texcoordsUnpacked.Add(tex2);
Vector3 tex3 = texcoords[vt3];
texcoordsUnpacked.Add(tex3);
// Normalsfor this face
Vector3 normal1 = texcoords[vn1];
normalsUnpacked.Add(normal1 );
Vector3 normal2 = texcoords[vn2];
normalsUnpacked.Add(normal2 );'
Vector3 normal3 = texcoords[vn3];
normalsUnpacked.Add(normal3 );
// Create new indices (this will automaticly build the new indices because the faces are now unpacked and in order.
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
Now your indexbuffer corresponds with the vertexbuffer, texcoordbuffer and normalbuffer.
the index start with 1 meaning that you need to -1 the index to get the correct vertex/texcoord/normal in your array (C/C++ arrays start with 0)
http://en.wikipedia.org/wiki/Obj
I assume that for every vertex the position, texcoord and the normal is stored in your obj file. your data will look something like this:
# faces
f 6/4/1 3/5/3 7/6/5
f 8/3/7 4/7/0 6/9/2
f 4/5/3 6/6/1 4/6/1
...
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
so basicly you have 3 indices for every vertex in order to use this data for rendering you need to unpack it.
Array<Vector3> vertices;
Array<Vector3> texcoords;
Array<Vector3> normals;
// read obj
- read all vertices from obj and stored in vertices
- read all texcoords from obj and store in texcoords
- read all normals from obj and sotre in normals
// Now read the # faces section and get the correct v, vt, vn according to the indices. for every face you read add the data to a new list
Array<Vector3> verticesUnpacked;
Array<Vector3> texcoordsUnpacked;
Array<Vector3> normalsUnpacked;
Array<int> indicesUnpacked;
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
// Vertices for this face
Vector3 vertex1 = vertices[v1];
verticesUnpacked.Add(vertex1);
Vector3 vertex2 = vertices[v2];
verticesUnpacked.Add(vertex2);
Vector3 vertex3 = vertices[v3];
verticesUnpacked.Add(vertex3);
// Texcoords for this face
Vector3 tex1 = texcoords[vt1];
texcoordsUnpacked.Add(tex1);
Vector3 tex2 = texcoords[vt2];
texcoordsUnpacked.Add(tex2);
Vector3 tex3 = texcoords[vt3];
texcoordsUnpacked.Add(tex3);
// Normalsfor this face
Vector3 normal1 = texcoords[vn1];
normalsUnpacked.Add(normal1 );
Vector3 normal2 = texcoords[vn2];
normalsUnpacked.Add(normal2 );'
Vector3 normal3 = texcoords[vn3];
normalsUnpacked.Add(normal3 );
// Create new indices (this will automaticly build the new indices because the faces are now unpacked and in order.
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
Now your indexbuffer corresponds with the vertexbuffer, texcoordbuffer and normalbuffer.
the index start with 1 meaning that you need to -1 the index to get the correct vertex/texcoord/normal in your array (C/C++ arrays start with 0)
Is there a mistake here?
// Create new indices (this will automaticly build the new indices because the faces are now unpacked and in order.
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
Now your indexbuffer corresponds with the vertexbuffer, texcoordbuffer and normalbuffer.
What are you trying to do with these?
What indices(vertex, texcoord or normal indices) must I use on glDrawElements?
Thanks.
// Create new indices (this will automaticly build the new indices because the faces are now unpacked and in order.
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
indicesUnpacked.Add(indicesUnpacked.size());
Now your indexbuffer corresponds with the vertexbuffer, texcoordbuffer and normalbuffer.
What are you trying to do with these?
What indices(vertex, texcoord or normal indices) must I use on glDrawElements?
Thanks.
When you are unpacking, the vertices are placed in order into the new array.
the 1st triangle has vertex indices 0, 1, 2 the 2nd triangle 3, 4, 5, the 3rd triangle 6, 7, 8 etc.
when you do this in a loop the code below will create the correct indexbuffer for the new unpacked buffer.
// unpacking #faces section
// added v1, v2, v3
// added vt1, vt2, vt3
// added vn1, vn2, vn3
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 0
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 1
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 2
// next loop/face
// added v1, v2, v3
// added vt1, vt2, vt3
// added vn1, vn2, vn3
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 3
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 4
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 5
etc
or you can use:
int size = indicesUnpacked.size();
indicesUnpacked.Add(size); // the size here is 0
indicesUnpacked.Add(size+1); // the size here is 1
indicesUnpacked.Add(size+2); // the size here is 2
the 1st triangle has vertex indices 0, 1, 2 the 2nd triangle 3, 4, 5, the 3rd triangle 6, 7, 8 etc.
when you do this in a loop the code below will create the correct indexbuffer for the new unpacked buffer.
// unpacking #faces section
// added v1, v2, v3
// added vt1, vt2, vt3
// added vn1, vn2, vn3
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 0
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 1
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 2
// next loop/face
// added v1, v2, v3
// added vt1, vt2, vt3
// added vn1, vn2, vn3
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 3
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 4
indicesUnpacked.Add(indicesUnpacked.size()); // the size of indicesUnpacked here is 5
etc
or you can use:
int size = indicesUnpacked.size();
indicesUnpacked.Add(size); // the size here is 0
indicesUnpacked.Add(size+1); // the size here is 1
indicesUnpacked.Add(size+2); // the size here is 2
I've tried this method and it doesn't work for me.
I'm trying to draw a cube and I'm getting a flat square.
These are my vertex and fragment shader:
[Edited by - VansFannel on December 10, 2010 5:03:12 AM]
I'm trying to draw a cube and I'm getting a flat square.
These are my vertex and fragment shader:
static const char* vertexShader = " attribute vec4 vertexPosition; uniform mat4 modelViewProjectionMatrix; void main() { gl_Position = modelViewProjectionMatrix * vertexPosition; } ";static const char* fragmentShader = " precision mediump float; void main() { gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); } ";
[Edited by - VansFannel on December 10, 2010 5:03:12 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement