使用 OpenGLES 2 在 android(java) 中渲染 3D 对象时缺少某些部分

Some parts are missing when render 3D object in android(java) using OpenGLES 2

我是 OpenGL 的新手,我正在尝试将 .obj 文件加载到我的 Android 应用程序中并使用 OpenGLES 2 显示它。对象已呈现。但是里面有一些空格,如下图所示。我该如何解决这个问题?

这是实物。

这是我的代码(补充:我在 MaxST Instant 跟踪器中使用它)

objLoader = new ObjLoader(context, "andy.obj");

    numFaces = objLoader.numFaces;


    positions = ByteBuffer.allocateDirect(objLoader.positions.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    positions.put(objLoader.positions).position(0);

    normals = ByteBuffer.allocateDirect(objLoader.normals.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    normals.put(objLoader.normals).position(0);

    textureCoordinates = ByteBuffer.allocateDirect(objLoader.textureCoordinates.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    textureCoordinates.put(objLoader.textureCoordinates).position(0);

    ByteBuffer bb = ByteBuffer.allocateDirect(objLoader.positions.length * Float.SIZE / 8);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(positions);
    vertexBuffer.position(0);

    bb = ByteBuffer.allocateDirect(objLoader.textureCoordinates.length * Float.SIZE / 8);
    bb.order(ByteOrder.nativeOrder());
    textureCoordBuff = bb.asFloatBuffer();
    textureCoordBuff.put(textureCoordinates);
    textureCoordBuff.position(0);


    shaderProgramId = ShaderUtil.createProgram(VERTEX_SHADER_SRC, FRAGMENT_SHADER_SRC);

    positionHandle = GLES20.glGetAttribLocation(shaderProgramId, "a_position");
    textureCoordHandle = GLES20.glGetAttribLocation(shaderProgramId, "a_texCoord");
    mvpMatrixHandle = GLES20.glGetUniformLocation(shaderProgramId, "u_mvpMatrix");
    textureHandle = GLES20.glGetUniformLocation(shaderProgramId, "u_texture");

    textureNames = new int[1];

    GLES20.glGenTextures(1, textureNames, 0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureNames[0]);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

(ObjLoader class 来自

这是我的绘制方法

@Override
public void draw() {
    GLES20.glUseProgram(shaderProgramId);

    GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false,
            0, vertexBuffer);
    GLES20.glEnableVertexAttribArray(positionHandle);
    GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false,
            0, textureCoordBuff);
    GLES20.glEnableVertexAttribArray(textureCoordHandle);

    Matrix.setIdentityM(modelMatrix, 0);
    Matrix.multiplyMM(modelMatrix, 0, translation, 0, rotation, 0);
    Matrix.multiplyMM(modelMatrix, 0, modelMatrix, 0, scale, 0);
    Matrix.multiplyMM(modelMatrix, 0, transform, 0, modelMatrix, 0);

    Matrix.multiplyMM(localMvpMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
    GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, localMvpMatrix, 0);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glUniform1i(textureHandle, 0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureNames[0]);

    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, objLoader.positions.length / 3);

    GLES20.glDisableVertexAttribArray(positionHandle);
    GLES20.glDisableVertexAttribArray(textureCoordHandle);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}

模型文件似乎由四边形组成。如果面是四边形,则必须为每个面生成 2 个三角形。

调整对象加载器。例如:

class ObjLoader {
    // [...]

    public ObjLoader(Context context, String file) {
        // [...]

               switch (parts[0]) {
                   // [...]

                    case "f":
                        // faces: vertex/texture/normal
                        if (parts.length == 5) {
                            // triangle 1
                            faces.add(parts[1]);
                            faces.add(parts[2]);
                            faces.add(parts[3]);
                            // triangle 2
                            faces.add(parts[1]);
                            faces.add(parts[3]);
                            faces.add(parts[4]);
                        }
                        else {
                            faces.add(parts[1]);
                            faces.add(parts[2]);
                            faces.add(parts[3]);
                        }
                        break;
                }
        // [...]
    }
}