Android и OpenGL "как отображать лица" - PullRequest
1 голос
/ 26 августа 2011

Я хочу отобразить, например, файл * .obj. и нормально, в OpenGL я использую инструкцию:

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

Но в Android OpenGL у меня нет этой функции ... у меня есть DrawElements (...); но когда я хочу нарисовать лицо 34/54/3 (вершина / текскорд / нормальный индекс массивов) это рисунок линейный 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);
    }

и это работает .. но я думаю, что это может быть более оптимизировано? ... Я не хочу менять свои данные модели на массив буферов, потому что это занимает слишком много места в памяти .. любое предложение?

Ответы [ 2 ]

3 голосов
/ 26 августа 2011

Я не программист Android, но я предполагаю, что он использует OpenGL-ES, в котором эти функции устарели (и, кстати, отсутствуют).

Учебники, объясняющие хорошее решение, нарисованы среди множества другихкоторые показывают, как рисовать треугольники с функциями glVertex3f (потому что это дает простые и быстрые результаты, но совершенно бессмысленно).Я нахожу это трагичным, поскольку НИКТО не должен использовать эти вещи.

glBegin / glEnd, glVertex3f, glTexcoords2f, и такие функции в настоящее время устарели из-за производительности (они "медленные", потому что мы должны ограничить количество вызововграфическая библиотека).Я не буду подробно останавливаться на этом, так как вы можете найти его, если интересно.Вместо этого используйте буферы Vertex и Indices.Я извиняюсь, потому что у меня нет "идеальной" ссылки, чтобы рекомендовать, но вы легко можете получить то, что вам нужно на google:)


Тем не менее, я выкопал некоторые из древнего проекта 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;
  }

}

Класс буфера вершин

Это класс-оболочка для 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 голос
/ 26 августа 2011

См. Это руководство по массивам glVertex

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...