如何在 OpenGL ES 1.1 中处理索引缓冲区 [英] How to handle index buffer in OpenGL ES 1.1

查看:20
本文介绍了如何在 OpenGL ES 1.1 中处理索引缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 OPENGL ES 1.1 for Android 渲染从 .obj 文件加载的模型.我有顶点、顶点法线和面.当我使用 GL10.GL_POINTS 渲染模型时,模型看起来很好:

I want to render a model loaded from an .obj file using OPENGL ES 1.1 for Android. I have vertices, vertice normals and faces. When I render the model using GL10.GL_POINTS the model looks fine:

当我使用 GL10.GL_TRIANGLES 时,我得到一堆这样的形状:

When I use GL10.GL_TRIANGLES I get a mess of shapes like this:

这是我的绘图方法.我尝试了 glDrawArrays 和 glDrawElements 但得到了相同的结果.

Here's my drawing method. I tried both glDrawArrays and glDrawElements but got the same results.

public void draw(GL10 gl){
    gl.glEnable(GL10.GL_CULL_FACE);
    gl.glFrontFace(GL10.GL_CCW);
    gl.glCullFace(GL10.GL_BACK);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, BYTES_PER_VERTEX, m_vertexBuffer);

    gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
    gl.glNormalPointer(COORDS_PER_VERTEX, BYTES_PER_VERTEX, m_normalBuffer);

    gl.glColor4f(m_color[0], m_color[1], m_color[2], m_color[3]);
    gl.glScalef(0.1f, 0.1f, 0.1f);

    // gl.glDrawArrays(GL10.GL_TRIANGLES, 0, m_numNormals);
    gl.glDrawElements(GL10.GL_TRIANGLES, m_numIndices, GL10.GL_UNSIGNED_SHORT, m_indexBuffer);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
    gl.glDisable(GL10.GL_CULL_FACE);
}

以下是 .obj 文件中的示例行:

Here are sample lines from the .obj file:

v 1.012781 -1.591947 1.752353
...
vn 0.495193 0.342204 0.798517
...
# same indices within pairs
f 14978//14978 14977//14977 22659//22659
...
# different indices
f 34422//34418 34375//34371 34374//34370

面部线条的有趣之处在于,有时 v//vn 对包含相同的索引,有时则不包含.此外,总共有 4 条法线少于顶点.我怀疑这是导致问题的原因.但我将如何处理呢?当我使用 glDrawElements 时,我应该传递哪些索引?

What's interesting about the face lines is that sometimes the pairs of v//vn consist of the same indices and sometimes they don't. Also in total there are 4 normals less than vertices. I suspect this is what's causing the problems. But how would I deal with that? When I use glDrawElements, which indices should I pass?

这就是我初始化缓冲区的方式:

This is how I initialize my Buffers:

public void setVertices(float[] coordinates, int size){
    final ByteBuffer bb = ByteBuffer.allocateDirect(size * 4);
    bb.order(ByteOrder.nativeOrder());
    m_vertexBuffer = bb.asFloatBuffer();
    m_vertexBuffer.put(coordinates, 0, size);
    m_vertexBuffer.position(0);
    m_numVertices = size / COORDS_PER_VERTEX;
}

public void setNormals(float[] coordinates, int size){
    final ByteBuffer bb = ByteBuffer.allocateDirect(size * 4);
    bb.order(ByteOrder.nativeOrder());
    m_normalBuffer = bb.asFloatBuffer();
    m_normalBuffer.put(coordinates, 0, size);
    m_normalBuffer.position(0);
    m_numNormals = size / COORDS_PER_VERTEX;
}

// array contains vertices and normals in the order read from the .obj file
// ie every even index is a vertex, every odd index is a normal
public void setIndices(int[] array, int size){
    m_numIndices = size / 2;
    final ByteBuffer bb = ByteBuffer.allocateDirect(m_numIndices * 4);
    bb.order(ByteOrder.nativeOrder());
    m_indexBuffer = bb.asIntBuffer();
    for(int i = 0; i < size; i+=2)
        m_indexBuffer.put(array[i]);
    m_indexBuffer.position(0);
}

能否给我一个提示如何初始化和使用索引缓冲区?

Can you maybe give me a hint how to initialize and use the index buffer?

这是模型:bunny.obj

推荐答案

也许这会对你有所帮助到您的项目,它与所有这些其他类相关联,例如 GLGame 和 GLGraphics 的实例用于文件输入并获取 GL10 的实例,祝你好运,希望这会有所帮助

maybe this will help you i used it to import an .obj file and it worked with a texture and everything, you will have to pick it apart to whats relevant to your project its tied into all these other classes, like the instance of GLGame and GLGraphics are used for file input and getting an instance of GL10, good luck, hope this helps

对象加载器

public class ObjLoader {
    public static Vertices3 load(GLGame game, String file) {
        InputStream in = null;
        try {
            in = game.getFileIO().readAsset(file);
            List<String> lines = readLines(in);

            float[] vertices = new float[lines.size() * 3];
            float[] normals = new float[lines.size() * 3];
            float[] uv = new float[lines.size() * 2];

            int numVertices = 0;
            int numNormals = 0;
            int numUV = 0;
            int numFaces = 0;

            int[] facesVerts = new int[lines.size() * 3];
            int[] facesNormals = new int[lines.size() * 3];
            int[] facesUV = new int[lines.size() * 3];
            int vertexIndex = 0;
            int normalIndex = 0;
            int uvIndex = 0;
            int faceIndex = 0;

            for (int i = 0; i < lines.size(); i++) {
                String line = lines.get(i);
                if (line.startsWith("v ")) {
                    String[] tokens = line.split("[ ]+");
                    vertices[vertexIndex] = Float.parseFloat(tokens[1]);
                    vertices[vertexIndex + 1] = Float.parseFloat(tokens[2]);
                    vertices[vertexIndex + 2] = Float.parseFloat(tokens[3]);
                    vertexIndex += 3;
                    numVertices++;
                    continue;
                }

                if (line.startsWith("vn ")) {
                    String[] tokens = line.split("[ ]+");
                    normals[normalIndex] = Float.parseFloat(tokens[1]);
                    normals[normalIndex + 1] = Float.parseFloat(tokens[2]);
                    normals[normalIndex + 2] = Float.parseFloat(tokens[3]);
                    normalIndex += 3;
                    numNormals++;
                    continue;
                }

                if (line.startsWith("vt")) {
                    String[] tokens = line.split("[ ]+");
                    uv[uvIndex] = Float.parseFloat(tokens[1]);
                    uv[uvIndex + 1] = Float.parseFloat(tokens[2]);
                    uvIndex += 2;
                    numUV++;
                    continue;
                }

                if (line.startsWith("f ")) {
                    String[] tokens = line.split("[ ]+");

                    String[] parts = tokens[1].split("/");
                    facesVerts[faceIndex] = getIndex(parts[0], numVertices);
                    if (parts.length > 2)
                        facesNormals[faceIndex] = getIndex(parts[2], numNormals);
                    if (parts.length > 1)
                        facesUV[faceIndex] = getIndex(parts[1], numUV);
                    faceIndex++;

                    parts = tokens[2].split("/");
                    facesVerts[faceIndex] = getIndex(parts[0], numVertices);
                    if (parts.length > 2)
                        facesNormals[faceIndex] = getIndex(parts[2], numNormals);
                    if (parts.length > 1)
                        facesUV[faceIndex] = getIndex(parts[1], numUV);
                    faceIndex++;

                    parts = tokens[3].split("/");
                    facesVerts[faceIndex] = getIndex(parts[0], numVertices);
                    if (parts.length > 2)
                        facesNormals[faceIndex] = getIndex(parts[2], numNormals);
                    if (parts.length > 1)
                        facesUV[faceIndex] = getIndex(parts[1], numUV);
                    faceIndex++;
                    numFaces++;
                    continue;
                }
            }

            float[] verts = new float[(numFaces * 3)
                    * (3 + (numNormals > 0 ? 3 : 0) + (numUV > 0 ? 2 : 0))];

            for (int i = 0, vi = 0; i < numFaces * 3; i++) {
                int vertexIdx = facesVerts[i] * 3;
                verts[vi++] = vertices[vertexIdx];
                verts[vi++] = vertices[vertexIdx + 1];
                verts[vi++] = vertices[vertexIdx + 2];

                if (numUV > 0) {
                    int uvIdx = facesUV[i] * 2;
                    verts[vi++] = uv[uvIdx];
                    verts[vi++] = 1 - uv[uvIdx + 1];
                }

                if (numNormals > 0) {
                    int normalIdx = facesNormals[i] * 3;
                    verts[vi++] = normals[normalIdx];
                    verts[vi++] = normals[normalIdx + 1];
                    verts[vi++] = normals[normalIdx + 2];
                }
            }

            Vertices3 model = new Vertices3(game.getGLGraphics(), numFaces * 3,
                    0, false, numUV > 0, numNormals > 0);
            model.setVertices(verts, 0, verts.length);
            return model;
        } catch (Exception ex) {
            throw new RuntimeException("couldn't load '" + file + "'", ex);
        } finally {
            if (in != null)
                try {
                    in.close();
                } catch (Exception ex) {

                }
        }
    }

    static int getIndex(String index, int size) {
        int idx = Integer.parseInt(index);
        if (idx < 0)
            return size + idx;
        else
            return idx - 1;
    }

    static List<String> readLines(InputStream in) throws IOException {
        List<String> lines = new ArrayList<String>();

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = null;
        while ((line = reader.readLine()) != null)
            lines.add(line);
        return lines;
    }
}

顶点3

public class Vertices3 {
    final GLGraphics glGraphics;
    final boolean hasColor;
    final boolean hasTexCoords;
    final boolean hasNormals;
    final int vertexSize;
    final IntBuffer vertices;
    final int[] tmpBuffer;
    final ShortBuffer indices;

    public Vertices3(GLGraphics glGraphics, int maxVertices, int maxIndices,
            boolean hasColor, boolean hasTexCoords, boolean hasNormals) {
        this.glGraphics = glGraphics;
        this.hasColor = hasColor;
        this.hasTexCoords = hasTexCoords;
        this.hasNormals = hasNormals;
        this.vertexSize = (3 + (hasColor ? 4 : 0) + (hasTexCoords ? 2 : 0) + (hasNormals ? 3
                : 0)) * 4;
        this.tmpBuffer = new int[maxVertices * vertexSize / 4];

        ByteBuffer buffer = ByteBuffer.allocateDirect(maxVertices * vertexSize);
        buffer.order(ByteOrder.nativeOrder());
        vertices = buffer.asIntBuffer();

        if (maxIndices > 0) {
            buffer = ByteBuffer.allocateDirect(maxIndices * Short.SIZE / 8);
            buffer.order(ByteOrder.nativeOrder());
            indices = buffer.asShortBuffer();
        } else {
            indices = null;
        }
    }

    public void setVertices(float[] vertices, int offset, int length) {
        this.vertices.clear();
        int len = offset + length;
        for (int i = offset, j = 0; i < len; i++, j++)
            tmpBuffer[j] = Float.floatToRawIntBits(vertices[i]);
        this.vertices.put(tmpBuffer, 0, length);
        this.vertices.flip();
    }

    public void setIndices(short[] indices, int offset, int length) {
        this.indices.clear();
        this.indices.put(indices, offset, length);
        this.indices.flip();
    }

    public void bind() {
        GL10 gl = glGraphics.getGL();

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        vertices.position(0);
        gl.glVertexPointer(3, GL10.GL_FLOAT, vertexSize, vertices);

        if (hasColor) {
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
            vertices.position(3);
            gl.glColorPointer(4, GL10.GL_FLOAT, vertexSize, vertices);
        }

        if (hasTexCoords) {
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            vertices.position(hasColor ? 7 : 3);
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, vertexSize, vertices);
        }

        if (hasNormals) {
            gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
            int offset = 3;
            if (hasColor)
                offset += 4;
            if (hasTexCoords)
                offset += 2;
            vertices.position(offset);
            gl.glNormalPointer(GL10.GL_FLOAT, vertexSize, vertices);
        }
    }

    public void draw(int primitiveType, int offset, int numVertices) {
        GL10 gl = glGraphics.getGL();

        if (indices != null) {
            indices.position(offset);
            gl.glDrawElements(primitiveType, numVertices,
                    GL10.GL_UNSIGNED_SHORT, indices);
        } else {
            gl.glDrawArrays(primitiveType, offset, numVertices);
        }
    }

    public void unbind() {
        GL10 gl = glGraphics.getGL();
        if (hasTexCoords)
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        if (hasColor)
            gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

        if (hasNormals)
            gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
    }

    public int getNumIndices() {
        return indices.limit();
    }

    public int getNumVertices() {
        return vertices.limit() / (vertexSize / 4);
    }
}

这篇关于如何在 OpenGL ES 1.1 中处理索引缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆