编写Wavefront OBJ解析器,用于OpenGL索引顶点缓冲区对象

时间:2014-02-18 06:07:23

标签: android opengl-es-2.0 vbo vertex-shader wavefront

我正在尝试为我的Android OpenGL ES 2.0程序编写基本的Wavefront OBJ加载程序。现在,除了顶点,法线和面外,我忽略了OBJ文件中的所有内容。这是我到目前为止所写的内容:

InputStream inputStream = context.getResources().openRawResource(resourceID);

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

String line;

while((line = reader.readLine()) != null)
{
    if(line.startsWith("v "))
    {
        Float x = Float.valueOf(line.split(" ")[1]);
        Float y = Float.valueOf(line.split(" ")[2]);
        Float z = Float.valueOf(line.split(" ")[3]);
        verticesArrayList.add(x);
        verticesArrayList.add(y);
        verticesArrayList.add(z);
    }
    else if(line.startsWith("vn "))
    {
        Float x = Float.valueOf(line.split(" ")[1]);
        Float y = Float.valueOf(line.split(" ")[2]);
        Float z = Float.valueOf(line.split(" ")[3]);
        normalsArrayList.add(x);
        normalsArrayList.add(y);
        normalsArrayList.add(z);
    }
    else if(line.startsWith("f "))
    {
        // Loop 3 times for the 3 vertices/textures/normals associated with each face
        for(int i = 1; i <= 3; i++)
        {
            Short vertex = (short) (Short.valueOf(line.split(" ")[i].split("/")[0]) - 1);
            indicesArrayList.add(vertex);

            // Make a copy of my normals array list
            if(normalsArrayList2.size() == 0)
                normalsArrayList2 = new ArrayList<Float>(normalsArrayList);

            // Attempt to re-arrange the normals to match the order of the vertices
            int normal = Integer.valueOf(line.split(" ")[i].split("/")[2]) - 1;
            normalsArrayList2.add(vertex * 3, normalsArrayList.get(normal * 3));
            normalsArrayList2.add((vertex * 3) + 1, normalsArrayList.get((normal * 3) + 1));
            normalsArrayList2.add((vertex * 3) + 2, normalsArrayList.get((normal * 3) + 2));
        }
    }
}
reader.close();

但是,我不确定我是否正确设置了法线。你在我的代码底部看到我在做什么?我正在尝试重新排列法线,使它们匹配顶点的顺序。我这样做是因为我正在使用GLES20.glDrawElements()方法:

// Get handle to vertex shader's aPosition member, enable the handle, and prepare the vertex data
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDINATES_PER_VERTEX, GLES20.GL_FLOAT, false, VERTEX_STRIDE, verticesBuffer);

// Get handle to vertex shader's aNormal member, enable the handle, and prepare the vertex data
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal");
GLES20.glEnableVertexAttribArray(mNormalHandle);
GLES20.glVertexAttribPointer(mNormalHandle, COORDINATES_PER_VERTEX, GLES20.GL_FLOAT, false, VERTEX_STRIDE, normalsBuffer);

// Draw the cube
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numberOfIndices, GLES20.GL_UNSIGNED_SHORT, indicesBuffer);

在谷歌用无数个小时搜索这个主题后,我从这个site得到了重新安排的想法。

然而,有些事情是不对的。我的着色器中的灯光适用于我使用OpenGL手动创建的所有形状,而不是我使用OBJ解析器读取的模型,因此我认为我的灯光计算不是问题,只是如何计算法线我的OBJ解析器。此外,我用Maya打开了我的测试OBJ文件,并使用“顶点法线编辑工具”直观地验证所有法线都指向正确的方向。您的任何代码都可以看到任何明显的问题吗?

1 个答案:

答案 0 :(得分:1)

使用ArrayList的set()方法而不是add()