Android和OpenGL“如何显示面孔”

时间:2011-08-26 16:24:22

标签: android opengl-es

我想显示例如* .obj文件。 正常,在OpenGL中我使用指令:

glBegin(Traing..);
glVertex3f(Face[i].VertexIndex);
glTexcoords2f(Face[i].TexcoordIndex);
glNormal(Face[i].NormalIndex);
glEnd();

但是在Android OpenGL中我没有这个功能...... 我有一个DrawElements(...); 但是当我想绘制面34/54/3(数组的顶点/ texcord /普通索引) 它是绘制线性34/34/34 ......

那我怎么画一个* .obj文件?


我在网上搜索,我找到了这个主题: http://www.anddev.org/android-2d-3d-graphics-opengl-problems-f55/obj-import-to-opengl-trouble-t48883.html所以......我在C#中为我的游戏编写了一个模型编辑器,并为测试写了类似的东西:

   public void display2()
    {
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.EnableClientState(ArrayCap.TextureCoordArray);
        GL.EnableClientState(ArrayCap.NormalArray);


        double[] vertexBuff = new double[faces.Count * 3 * 3];
        double[] normalBuff = new double[faces.Count * 3 * 3];
        double[] texcorBuff = new double[faces.Count * 3 * 2];


        foreach (face f in faces)
        {
            for (int i = 0; i < f.vector.Length; i++)
            {
                vertexBuff[i_3] = mesh[f.vector[i]].X;
                vertexBuff[i_3 + 1] = mesh[f.vector[i]].Y;
                vertexBuff[i_3 + 2] = mesh[f.vector[i]].Z;

                normalBuff[i_3] = normal[f.normal[i]].X;
                normalBuff[i_3 + 1] = normal[f.normal[i]].Y;
                normalBuff[i_3 + 2] = normal[f.normal[i]].Z;


                texcorBuff[i_2] = texture[f.texCord[i]].X;
                texcorBuff[i_2 + 1] = texture[f.texCord[i]].Y;
                i_3 += 3;
                i_2 += 2;
            }

        }
        GL.VertexPointer<double>(3, VertexPointerType.Double, 0, vertexBuff);
        GL.TexCoordPointer<double>(2, TexCoordPointerType.Double, 0, texcorBuff);
        GL.NormalPointer<double>(NormalPointerType.Double, 0, normalBuff);


        GL.DrawArrays(BeginMode.Triangles, 0, faces.Count * 3);

        GL.DisableClientState(ArrayCap.VertexArray);
        GL.DisableClientState(ArrayCap.TextureCoordArray);
        GL.DisableClientState(ArrayCap.NormalArray);
    }

它正在工作..但我认为这可以更优化?... 我不想将我的模型数据更改为arraysbuffer, 因为它在内存中占用了太多空间..任何建议?

2 个答案:

答案 0 :(得分:3)

我不是Android程序员,但我认为它使用的是OpenGL-ES,其中不推荐使用这些函数(以及缺少的方式)。

解释这个好解决方案的教程是在众多其他人之间绘制的,这些教程展示了如何使用glVertex3f函数绘制三角形(因为它提供了简单快速的结果但完全没有意义)。我发现它很悲惨,因为NOBODY应该使用这些东西。

glBegin / glEnd,glVertex3f,glTexcoords2f以及这些函数现在因性能而被弃用(它们“慢”,因为我们必须限制对图形库的调用次数)。我不会对此进行太多扩展,因为如果有兴趣你可以搜索它。 相反,请使用Vertex和Indices缓冲区。对不起因为我没有推荐的“完美”链接,但你应该很容易在谷歌上得到你需要的东西:)


然而,我挖出一些来自古老的C#项目:

  • 注意:OpenTK绑定更改函数名称但它们仍然非常接近OGL,例如glVertex3f变为GL.Vertex3。

顶点定义

用于存储自定义顶点信息的简单结构(位置,法线(如果需要),颜色......)

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
public struct Vertex
{
  public Core.Math.Vector3 Position;
  public Core.Math.Vector3 Normal;
  public Core.Math.Vector2 UV;
  public uint Coloring;


  public Vertex(float x, float y, float z)
  {
    this.Position = new Core.Math.Vector3(x, y, z);
    this.Normal = new Core.Math.Vector3(0, 0, 0);
    this.UV = new Core.Math.Vector2(0, 0);

    System.Drawing.Color color = System.Drawing.Color.Gray;
    this.Coloring = (uint)color.A << 24 | (uint)color.B << 16 | (uint)color.G << 8 | (uint)color.R;
  }

}

Vertex Buffer类

这是一个围绕OpenGL缓冲区对象的包装类来处理我们的顶点格式。

public class VertexBuffer
{
  public uint Id;
  public int Stride;
  public int Count;

  public VertexBuffer(Graphics.Objects.Vertex[] vertices)
  {
    int size;

    // We create an OpenGL buffer object
    GL.GenBuffers(1, out this.Id); //note: out is like passing an object by reference in C#
    this.Stride = OpenTK.BlittableValueType.StrideOf(vertices); //size in bytes of the VertexType (Vector3 size*2 + Vector2 size + uint size)
    this.Count = vertices.Length;

    // Fill the buffer with our vertices data
    GL.BindBuffer(BufferTarget.ArrayBuffer, this.Id);
    GL.BufferData(BufferTarget.ArrayBuffer, (System.IntPtr)(vertices.Length * this.Stride), vertices, BufferUsageHint.StaticDraw);
    GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out size);

    if (vertices.Length * this.Stride != size)
      throw new System.ApplicationException("Vertex data not uploaded correctly");

  }

}

指数缓冲类

与顶点缓冲区非常相似,它存储模型每个面的顶点索引。

public class IndexBuffer
{
  public uint Id;
  public int Count;


  public IndexBuffer(uint[] indices)
  {
    int size;
    this.Count = indices.Length;

    GL.GenBuffers(1, out this.Id);
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.Id);
    GL.BufferData(BufferTarget.ElementArrayBuffer, (System.IntPtr)(indices.Length * sizeof(uint)), indices,
                  BufferUsageHint.StaticDraw);
    GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out size);

    if (indices.Length * sizeof(uint) != size)
        throw new System.ApplicationException("Indices data not uploaded correctly");
  }

}

绘图缓冲区

然后,要渲染三角形,您必须创建一个顶点缓冲区来存储顶点的位置。一个Indice缓冲区包含顶点[0,1,2]的索引(注意逆时针规则,但与glVertex3f方法相同) 完成后,只需使用指定的缓冲区调用此函数。请注意,您可以使用多组索引,每次只有一个顶点缓冲区只渲染一些面。

void DrawBuffer(VertexBuffer vBuffer, IndexBuffer iBuffer)
{
  // 1) Ensure that the VertexArray client state is enabled.
  GL.EnableClientState(ArrayCap.VertexArray);
  GL.EnableClientState(ArrayCap.NormalArray);
  GL.EnableClientState(ArrayCap.TextureCoordArray);

  // 2) Bind the vertex and element (=indices) buffer handles.
  GL.BindBuffer(BufferTarget.ArrayBuffer, vBuffer.Id);
  GL.BindBuffer(BufferTarget.ElementArrayBuffer, iBuffer.Id);

  // 3) Set up the data pointers (vertex, normal, color) according to your vertex format.
  GL.VertexPointer(3, VertexPointerType.Float, vBuffer.Stride, new System.IntPtr(0));
  GL.NormalPointer(NormalPointerType.Float, vBuffer.Stride, new System.IntPtr(Vector3.SizeInBytes));
  GL.TexCoordPointer(2, TexCoordPointerType.Float, vBuffer.Stride, new System.IntPtr(Vector3.SizeInBytes * 2));
  GL.ColorPointer(4, ColorPointerType.UnsignedByte, vBuffer.Stride, new System.IntPtr(Vector3.SizeInBytes * 3 + Vector2.SizeInBytes));

  // 4) Call DrawElements. (Note: the last parameter is an offset into the element buffer and will usually be IntPtr.Zero).
  GL.DrawElements(BeginMode.Triangles, iBuffer.Count, DrawElementsType.UnsignedInt, System.IntPtr.Zero);

  //Disable client state
  GL.DisableClientState(ArrayCap.VertexArray);
  GL.DisableClientState(ArrayCap.NormalArray);
  GL.DisableClientState(ArrayCap.TextureCoordArray);
}

我希望这可以提供帮助;)

答案 1 :(得分:1)

请参阅glVertex arrays

上的本教程