【问题标题】:opengl es 2.0 populating the Vertex and index Bufferopengl es 2.0 填充顶点和索引缓冲区
【发布时间】:2014-04-10 19:27:14
【问题描述】:

这似乎是一个愚蠢的问题,但我觉得我需要问一下,这样我才能了解 openGl 缓冲区的工作原理。

我有两个缓冲区,顶点缓冲区和索引缓冲区。为了填充这些缓冲区,我正在解析一个 obj 文件。

解析数据后,我用我认为正确的数据和数据顺序填充缓冲区。

但是,当我调试代码时,我在缓冲区中看到了一些奇怪的东西。

首先是顶点缓冲区。我放入 Vbuffer 的前 3 个值是 0.99,-0.99,-0.7741 但是,当我通过逐步检查缓冲区时,这些值是 -92,112,125 这是因为这是一个 FloatBuffer 但作为一个字节缓冲区?

    this.vertexBuffer = ByteBuffer.allocateDirect(VertexList.length *   mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();                             
    this.vertexBuffer.put(VertexList);
    this.vertexBuffer.position(0);

我放入的索引缓冲区不同 4,1,2 当我检查它时,我似乎在每个值之间得到了一个额外的 0 4,0,1,0,2

    this.IndexBuffer = ByteBuffer.allocateDirect(IndexList.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
    this.IndexBuffer.put(IndexList);
    this.IndexBuffer.position(0);

在这个缓冲区中,我可以将数据作为 ShortBuffer 读取,即使它是一个字节缓冲区。 还有为什么其他值都是 0?

任何理解这一点的帮助将不胜感激。

更新!

这是我从 obj 文件中解析数据并填充缓冲区的完整代码。放入缓冲区的数据似乎是正确的。

public class RBLoadModelFromFile 
{
/** How many bytes per float. */
private final int mBytesPerFloat = 4;   

private Context context;
public FloatBuffer vertexBuffer;
public ShortBuffer IndexBuffer;
public float[] vertices;
public float[] normals;
public float[] uVs;
public short[] Ind;
private ArrayList<Short> indicies;
public int NumVertices;
public int NumIndicies;

public RBLoadModelFromFile(Context c) 
{
    context = c;
}


public void loadModel(String filename) 
{

    ArrayList<RBVector3> tempVertices = new ArrayList<RBVector3>();        
    ArrayList<RBVector3> tempNormals = new ArrayList<RBVector3>();
    ArrayList<RBVector3> tempUVs = new ArrayList<RBVector3>();

    ArrayList<Short> vertexIndices = new ArrayList<Short>();
    ArrayList<Short> normalIndices = new ArrayList<Short>();
    ArrayList<Short> textureIndices = new ArrayList<Short>();
    indicies = new ArrayList<Short>();

    try {
        AssetManager manager = context.getAssets();
        BufferedReader reader = new BufferedReader(new InputStreamReader(manager.open(filename)));
        String line;
        while ((line = reader.readLine()) != null) 
        {
            if (line.startsWith("v  ")) 
            {    
                RBVector3 tempVert = new RBVector3(0f,0f,0f);
                tempVert.add(Float.valueOf(line.split(" ")[2]),Float.valueOf(line.split(" ")[3]),Float.valueOf(line.split(" ")[4]));
                tempVertices.add(tempVert); 
            }
            else if (line.startsWith("vn")) 
            {
                RBVector3 tempNorm = new RBVector3(0f,0f,0f);
                tempNorm.add(Float.valueOf(line.split(" ")[1]),Float.valueOf(line.split(" ")[2]),Float.valueOf(line.split(" ")[3]));
                tempNormals.add(tempNorm);                              
            }
            else if (line.startsWith("vt")) 
            {
                RBVector3 tempUV = new RBVector3(0f,0f,0f);
                tempUV.add(Float.valueOf(line.split(" ")[1]),Float.valueOf(line.split(" ")[2]), 0f);
                tempUVs.add(tempUV);                            
            }
            else if (line.startsWith("f"))
            {                
                String tmp[] = line.split(" ");     
                vertexIndices.add(Short.valueOf(tmp[1].split("/")[0]));
                textureIndices.add(Short.valueOf(tmp[1].split("/")[1]));
                normalIndices.add(Short.valueOf(tmp[1].split("/")[2]));

                vertexIndices.add(Short.valueOf(tmp[2].split("/")[0]));
                textureIndices.add(Short.valueOf(tmp[2].split("/")[1]));
                normalIndices.add(Short.valueOf(tmp[2].split("/")[2]));

                vertexIndices.add(Short.valueOf(tmp[3].split("/")[0]));
                textureIndices.add(Short.valueOf(tmp[3].split("/")[1]));
                normalIndices.add(Short.valueOf(tmp[3].split("/")[2]));
            }
        }
        Ind = new short[vertexIndices.size() + normalIndices.size() + textureIndices.size()];
        vertices = new float[(vertexIndices.size() * 3) + (normalIndices.size() * 3) + (textureIndices.size() * 2)];
        ArrayList<Float> vertInfo = new ArrayList<Float>();
        for (int i = 0; i < vertexIndices.size(); i++) 
        {            
            Short v = vertexIndices.get(i);
            vertInfo.add(tempVertices.get(v-1).x);
            vertInfo.add(tempVertices.get(v-1).y);
            vertInfo.add(tempVertices.get(v-1).z);
            indicies.add((short) (v-1));
            Short n = normalIndices.get(i);
            vertInfo.add(tempNormals.get(n-1).x);
            vertInfo.add(tempNormals.get(n-1).y);
            vertInfo.add(tempNormals.get(n-1).z);
            indicies.add((short) (n-1));
            Short t = textureIndices.get(i);
            vertInfo.add(tempUVs.get(t-1).x);
            vertInfo.add(tempUVs.get(t-1).y);
            indicies.add((short) (t-1));
        }
        for(int i = 0; i < indicies.size(); i++)
        {
            Ind[i] = indicies.get(i);
        }
        for (int i = 0; i < vertInfo.size(); i++) 
        { 
            vertices[i] = vertInfo.get(i);
        }
        createIndexBuffer(Ind);
        createVertexBuffer(vertices);
        NumIndicies = Ind.length;
        NumVertices = vertices.length;
    }
    catch (Exception e)
    {
        Log.d("DEBUG", "Error.", e);
    }
}
private void createVertexBuffer(float[] VertexList)
{
    this.vertexBuffer = ByteBuffer.allocateDirect(VertexList.length * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();                               
    this.vertexBuffer.put(VertexList);
    this.vertexBuffer.position(0);
}
private void createIndexBuffer(short[] IndexList)
{
    this.IndexBuffer = ByteBuffer.allocateDirect(IndexList.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
    this.IndexBuffer.put(IndexList);
    this.IndexBuffer.position(0);
}
}

这是一个我正在尝试解析的简单立方体 obj 文件

v  -0.500000 -0.500000 0.500000
v  0.500000 -0.500000 0.500000
v  -0.500000 0.500000 0.500000
v  0.500000 0.500000 0.500000
v  -0.500000 0.500000 -0.500000
v  0.500000 0.500000 -0.500000
v  -0.500000 -0.500000 -0.500000
v  0.500000 -0.500000 -0.500000

vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000

vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000

f 1/1/1 2/2/1 3/3/1
f 3/3/1 2/2/1 4/4/1
f 3/1/2 4/2/2 5/3/2
f 5/3/2 4/2/2 6/4/2
f 5/4/3 6/3/3 7/2/3
f 7/2/3 6/3/3 8/1/3
f 7/1/4 8/2/4 1/3/4
f 1/3/4 8/2/4 2/4/4
f 2/1/5 8/2/5 4/3/5
f 4/3/5 8/2/5 6/4/5
f 7/1/6 1/2/6 5/3/6
f 5/3/6 1/2/6 3/4/6

我现在正在绘制一些东西,但顶点似乎离我们很远。

这是我现在的绘图方法

public void DrawModel(float[] mProjectionMatrix, float[] mViewMatrix, float[] mMVPMatrix, int mProgramHandle, int mMVPMatrixHandle, int mMVMatrixHandle, int mLightPosHandle, float[] mLightPosInEyeSpace)
{

    mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
    mNormalHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Normal");
    mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
    mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

    // Bind the texture to this unit.
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle); 
    // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
    GLES20.glUniform1i(mTextureUniformHandle, 0);

    // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
    // (which currently contains model * view).
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

    // Pass in the modelview matrix.
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);

    // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
    // (which now contains model * view * projection).
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

    // Pass in the combined matrix.
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

    // Pass in the light position in eye space.
    GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);        

    // the vertex coordinates
    VertexBuffer.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false,
            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, VertexBuffer);
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    // the normal info
    VertexBuffer.position(TRIANGLE_VERTICES_DATA_NOR_OFFSET);
    GLES20.glVertexAttribPointer(mNormalHandle, 3, GLES20.GL_FLOAT, false,
            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, VertexBuffer);
    GLES20.glEnableVertexAttribArray(mNormalHandle);

// texture coordinates
    VertexBuffer.position(TRIANGLE_VERTICES_DATA_TEX_OFFSET);
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false,
            TRIANGLE_VERTICES_DATA_STRIDE_BYTES, VertexBuffer);
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);//GLES20.glEnableVertexAttribArray(shader.maTextureHandle);

    // Draw with indices
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, NumIndicies , GLES20.GL_UNSIGNED_SHORT, IndexBuffer);
    //checkGlError("glDrawElements");
}

【问题讨论】:

    标签: java android memory buffer opengl-es-2.0


    【解决方案1】:

    没有完整的代码很难判断问题出在哪里。

    在我看来,您正在混合数据类型。

    浮点数相当棘手,如果不将它们作为浮点数处理,则无法轻松“读取”浮点内存单元的内容。

    浮点数,根据标准是基于3个不同的组件,位符号(最有意义的),指数和尾数。

    通常浮动,在当今最常见的平台上用 32 位(4 字节)表示,其中:

    1 代表标志 8 位为指数 尾数为 23 位(通常是打包的,但这将是一个很长的讨论)

    如果您不将浮点数“读取”或“写入”为浮点数(有一些方法可以将浮点数作为整数处理,但知道它们的属性,但这会离题太多)您可能会以不可预测的方式解释它们。

    我的建议是将这些值读/写为浮点数,不要按字节/整数进行读/写操作。

    【讨论】:

    • 朋友你好,我已经更改了一些内容并上传了所有代码,包括上面的解析器。我现在画了一些东西,但顶点似乎混淆了你能检查一下上面的内容,看看你认为问题是什么。谢谢
    【解决方案2】:

    好的,我终于设法解决了我的渲染问题。快速感谢@MaurizioBenedetti,因为他评论并回答了我的一些问题,这些问题帮助我到达了现在的位置。

    首先,我放入缓冲区的内容在某种程度上是正确的。我的问题来了,因为我创建了一个交错的顶点缓冲区 - 这意味着数据已经处于正确的顺序 VVVNNNTT 中。然后我创建了包含实际索引数据的索引缓冲区,这是非交错缓冲区的索引

    例如,如果面包含 2/4/6 4/7/9 2/1/3 那么我的索引缓冲区包含这些确切的值,但由于我的顶点缓冲区是交错的,它应该包含一个有序列表指标。

    所以这意味着如果上面的面是唯一的索引,那么索引缓冲区应该包含 0,1,2,3,4,5,6,7,8

    在我填充顶点信息时总结上面的代码

    我应该说这样的话

    indicies.add(index++);
    

    而不是分配每个索引值

    我希望任何被困在这类事情上的人都清楚这一点,并希望能有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 2011-11-14
      • 1970-01-01
      • 2014-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多