1

I am having a problem adapting and or I guess understanding the vertices/indices/faces in an OBJ file. I want to eventually parse a OBJ file programmatically but first I need to understand how to do it manually. I am using an adaptation of the example from GLWallpaperService(provided by a dev on the web) to do this.

The problem I am having is it seems to work fine with the code he provided to produce a generic cube with different colored faces which he had to implement and draw individually. My adjusted code below trying to draw just a basic cube from the coords I exported from blender and plugged in values.

public class GLCube {
private final int _nrOfVertices = 8;

private FloatBuffer _vertexBuffer;
private FloatBuffer _normalBuffer;
private ShortBuffer _indiceBuffer;

public GLCube() {
    this.init();
}

private void init() {
    // 3 is the number of coordinates to each vertex.
    _vertexBuffer = BufferFactory.createFloatBuffer(_nrOfVertices * 3);
    _normalBuffer = BufferFactory.createFloatBuffer(18);
    _indiceBuffer = BufferFactory.createShortBuffer(72);

    // Coordinates for the vertexes of the cube.
    float[] vertexCoords = {
            /*
            1f,  1f,  0f,
            0f,  1f,  0f, 
            0f,  0f,  0f, 
            1f,  0f,  0f, 
            1f,  0f, -1f, 
            1f,  1f, -1f, 
            0f,  1f, -1f, 
            0f,  0f, -1f,
            */
            2.195671f, -0.176713f, -1.292541f,
            2.195671f, -0.176713f,  0.707459f,
            0.195671f, -0.176713f,  0.707459f,
            0.195672f, -0.176713f, -1.292542f,
            2.195672f,  1.823287f, -1.292541f,
            2.195671f,  1.823287f,  0.707460f,
            0.195671f,  1.823287f,  0.707459f,
            0.195671f,  1.823287f, -1.292541f
    };

    short[] indicesArray = {/*
            0, 1, 2,   0, 2, 3,
            3, 4, 0,   4, 5, 0,
            7, 2, 6,   6, 2, 1,
            4, 7, 5,   7, 6, 5,
            1, 0, 6,   6, 0, 5,
            2, 7, 3,   7, 4, 3
            */
            1,1,2, 1,3,1,
            1,1,3, 1,4,1,
            5,2,8, 2,7,2,
            5,2,7, 2,6,2,
            1,3,5, 3,6,3,
            1,3,6, 3,2,3,
            2,4,6, 4,7,4,
            2,4,7, 4,3,4,
            3,5,7, 5,8,5,
            3,5,8, 5,4,5,
            5,6,1, 6,4,6,
            5,6,4, 6,8,6
            };

    //Coordinates for Normal Vector. Used for Lighting calculations
    float[] normalCoords = {/*
             0f, 0f, 1f,   0f, 0f, 1f,   
             0f, 0f, 1f,   0f, 0f, 1f,   
             0f, 0f, 1f,   0f, 0f, 1f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
            -1f, 0f, 0f,  -1f, 0f, 0f,  
            -1f, 0f, 0f,  -1f, 0f, 0f,  
            -1f, 0f, 0f,  -1f, 0f, 0f,  
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 1f, 0f,   0f, 1f, 0f,   
             0f, 1f, 0f,   0f, 1f, 0f,   
             0f, 1f, 0f,   0f, 1f, 0f,  
             0f,-1f, 0f,   0f,-1f, 0f,   
             0f,-1f, 0f,   0f,-1f, 0f,   
             0f,-1f, 0f,   0f,-1f, 0f   
             */
             0f, -1f,  0f,
             0f,  1f,  0f,
             1f, -0f,  0f,
            -0f, -0f,  1f,
            -1f, -0f, -0f,
             0f,  0f, -1f
    };

    _vertexBuffer.put(vertexCoords);
    _normalBuffer.put(normalCoords);
    _indiceBuffer.put(indicesArray);

    _indiceBuffer.position(0);
    _vertexBuffer.position(0);
    _normalBuffer.position(0);

}

public void draw(GL10 gl) {
    // 3 coordinates in each vertex
    // 0 is the space between each vertex. They are densely packed in the array, so the value is 0
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

    // 0 is the space between each vertex. They are densely packed in the array, so the value is 0
    gl.glNormalPointer(GL10.GL_FLOAT, 0, _normalBuffer);

    gl.glColor4f(1.0f, 0f, 0f, 1f);     //Red
    gl.glDrawElements(GL10.GL_TRIANGLES, 72, GL10.GL_UNSIGNED_SHORT, _indiceBuffer);
}
}

This is the Obj file and maybe I'm just not putting the values in the correct arrays but I have been trying to figure this out for awhile and honestly just don't have any background working with OpenGL so this is my first project trying to work with it.

# Blender v2.58 (sub 1) OBJ File: ''
# www.blender.org
v 2.195671 -0.176713 -1.292541
v 2.195671 -0.176713 0.707459
v 0.195671 -0.176713 0.707459
v 0.195672 -0.176713 -1.292542
v 2.195672 1.823287 -1.292541
v 2.195671 1.823287 0.707460
v 0.195671 1.823287 0.707459
v 0.195671 1.823287 -1.292541
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 -0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl (null)
s off
f 1//1 2//1 3//1
f 1//1 3//1 4//1
f 5//2 8//2 7//2
f 5//2 7//2 6//2
f 1//3 5//3 6//3
f 1//3 6//3 2//3
f 2//4 6//4 7//4
f 2//4 7//4 3//4
f 3//5 7//5 8//5
f 3//5 8//5 4//5
f 5//6 1//6 4//6
f 5//6 4//6 8//6

Any help with this would be so greatly appreciated. I left his values commented in so you could see what works. The image I see on my screen is a completely distorted set of triangles and it appears its trying to make my cube but is just not quite getting there.

An answer containing what to change would be awesome. -=)

genpfault
  • 51,148
  • 11
  • 85
  • 139
Joey
  • 142
  • 2
  • 14

1 Answers1

6

I think you're interpreting the .obj format in the wrong way. Have a look at this document.

Basically the indices for your faces into the vertexCoords should be the first ints. Each face is defined by indices in a format like this:

f v1/t1/n1 v2/t2/n2 v3/t3/n3

Where the v's are vertex indices, the t's are texture coordinate indices and the n's are normal indices.

So for this line (which defines a single face/triangle)

f 1//1 2//1 3//1

the vertex indices would be 1,2,3and the normal indices 1,1,1. You have no texture coordinates, so no indices there and hence the double slash.

Keep in mind that the indices for the vertices that make up a face and the indices of the associated normals are different. So you will have to create two sets of indices. (See my edit below about glDrawElements though)

Another minor detail is to keep in mind that .obj files start counting with indices at 1, although that might be (an probably is) the 0th value in your array. So you'll have to account for that (i.e. subtract 1 from all index values).

Edit: Looking at your code I see you're using glDrawElements. From what I know (but correct me if I'm wrong) this doesn't allow you to have multiple (different) sets of indices for vertices, texcoords and normals. So you will have to change your normal data to match the same indices as you have for your vertices.

Bart
  • 19,692
  • 7
  • 68
  • 77
  • ok I have researched the link and from what you have said I think I kinda get it but Im still not converting properly lol... anyway you could modify my code in reply with the data I have provided to show me what you mean? If you fix my code I guarentee an "Answered" -=) – Joey Aug 01 '11 at 22:57
  • Forget normals for the moment. Just the vertices you have provided. Given the .obj the indices array should then look like this: http://pastebin.com/Sj4sigPq I don't have the means to compile/run/check your code, but at least this is what the indices should look like. Is that what you tried? – Bart Aug 01 '11 at 23:06
  • ok that makes sense! I wasn't subtracting the 1 from each of the indices. that gives me a little more understanding of the conversions. Answer accepted. Any more explanation would be great but you have more than exceeded my expectations -=D – Joey Aug 01 '11 at 23:42
  • actually the example I'm using from the GLWallpaperService had multiple glDrawElements with seperate sides for each one. Is there a better way to do this without having to have a seperate set of indices for each shape? – Joey Aug 02 '11 at 02:23
  • Ah, I see now. He is drawing a cube with 6 solidly colored sides. In this particular case duplication of vertices is necessary, since all attributes are specified on a per vertex level. Of course, if you have a mesh with a single color/material or texture mapping, you don't need to do this. – Bart Aug 05 '11 at 09:30