libgdx中的mesh

mesh就是網格,在d3d中有嚴格的定義, 也有專門的工具來寫.x提供給d3d生成mesh,

什麼是mesh?

簡單的說就是那些點座標,顏色,紋理,材質,光照等等的一個集合

 

libgdx定義的mesh

public class Mesh implements Disposable {
 public enum VertexDataType {
  VertexArray, VertexBufferObject, VertexBufferObjectSubData,
 }

 /** list of all meshes **/
 static final Map<Application, List<Mesh>> meshes = new HashMap<Application, List<Mesh>>();

 /** used for benchmarking **/
 public static boolean forceVBO = false;

 final VertexData vertices;
 final IndexData indices;
 boolean autoBind = true;
 final boolean isVertexArray;
 int refCount = 0;

 /** Creates a new Mesh with the given attributes.
  *
  * @param isStatic whether this mesh is static or not. Allows for internal optimizations.
  * @param maxVertices the maximum number of vertices this mesh can hold
  * @param maxIndices the maximum number of indices this mesh can hold
  * @param attributes the {@link VertexAttribute}s. Each vertex attribute defines one property of a vertex such as position,
  *           normal or texture coordinate */

public Mesh (boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes) {
  if (Gdx.gl20 != null || Gdx.gl11 != null || Mesh.forceVBO) {
   vertices = new VertexBufferObject(isStatic, maxVertices, attributes);
   indices = new IndexBufferObject(isStatic, maxIndices);
   isVertexArray = false;
  } else {
   vertices = new VertexArray(maxVertices, attributes);
   indices = new IndexBufferObject(maxIndices);
   isVertexArray = true;
  }

  addManagedMesh(Gdx.app, this);
 }

 

...  ...

 

保存了頂點和索引

當然頂點是有不同定義方式的,d3d就是這麼做的,這裏libgdx有了一個VertexAttribute的概念

VertexAttribute

 /** Constructs a new VertexAttribute.
  *
  * @param usage the usage, used for the fixed function pipeline. Generic attributes are not supported in the fixed function
  *           pipeline.
  * @param numComponents the number of components of this attribute, must be between 1 and 4.
  * @param alias the alias used in a shader for this attribute. Can be changed after construction. */
 public VertexAttribute (int usage, int numComponents, String alias) {
  this.usage = usage;//屬性的作用
  this.numComponents = numComponents;  //這個屬性佔3個數字
  this.alias = alias;
 }

 

構造這個mesh通常是從文件裏面來,例子裏面就是這麼做的

public Renderer (Application app) {
  try {
   spriteBatch = new SpriteBatch();

   InputStream in = Gdx.files.internal("data/ship.obj").read();
   shipMesh = ModelLoaderOld.loadObj(in);
   in.close();

   in = Gdx.files.internal("data/invader.obj").read();
   invaderMesh = ModelLoaderOld.loadObj(in);
   in.close();

   in = Gdx.files.internal("data/block.obj").read();
   blockMesh = ModelLoaderOld.loadObj(in);
   in.close();

   in = Gdx.files.internal("data/shot.obj").read();
   shotMesh = ModelLoaderOld.loadObj(in);
   in.close();

這段是 invader的Renderer,它就是這麼做的

invaderMesh = ModelLoaderOld.loadObj(in);

public class ModelLoaderOld {
 /** Loads a Wavefront OBJ file from the given InputStream. The OBJ file must only contain triangulated meshes. Materials are
  * ignored.
  *
  * @param in the InputStream
  * @return a Mesh holding the OBJ data or null in case something went wrong. */
 public static Mesh loadObj (InputStream in) {
  return ObjLoader.loadObj(in);
 }
}

ObjLoader就是這個加載器

public static Mesh loadObjFromString (String obj, boolean flipV) {
  String[] lines = obj.split("\n");
  float[] vertices = new float[lines.length * 3];
  float[] normals = new float[lines.length * 3];
  float[] uv = new float[lines.length * 3];

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

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

  for (int i = 0; i < lines.length; i++) {
   String line = lines[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] = flipV ? 1 - Float.parseFloat(tokens[2]) : 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 (numNormals > 0) {
    int normalIdx = facesNormals[i] * 3;
    verts[vi++] = normals[normalIdx];
    verts[vi++] = normals[normalIdx + 1];
    verts[vi++] = normals[normalIdx + 2];
   }
   if (numUV > 0) {
    int uvIdx = facesUV[i] * 2;
    verts[vi++] = uv[uvIdx];
    verts[vi++] = uv[uvIdx + 1];
   }
  }

  Mesh mesh = null;

  ArrayList<VertexAttribute> attributes = new ArrayList<VertexAttribute>();
  attributes.add(new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE));
  if (numNormals > 0) attributes.add(new VertexAttribute(Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE));
  if (numUV > 0) attributes.add(new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"));

  mesh = new Mesh(true, numFaces * 3, 0, attributes.toArray(new VertexAttribute[attributes.size()]));
  mesh.setVertices(verts);
  return mesh;
 }

前面一段都是在讀數據,重點看後面一段

 ArrayList<VertexAttribute> attributes = new ArrayList<VertexAttribute>();
  attributes.add(new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE));
  if (numNormals > 0) attributes.add(new VertexAttribute(Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE));
  if (numUV > 0) attributes.add(new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"));

有3種屬性 位置,法線,紋理

new Mesh(true, numFaces * 3, 0, attributes.toArray(new VertexAttribute[attributes.size()]));

isStatic

頂點數:numFaces * 3

索引:0

 

上面的數據讀取是格式化的讀取,這個model的位置,法線,紋理等數據

 

 private void renderInvaders (GL10 gl, ArrayList<Invader> invaders) {
  invaderTexture.bind();
  for (int i = 0; i < invaders.size(); i++) {
   Invader invader = invaders.get(i);
   gl.glPushMatrix();
   gl.glTranslatef(invader.position.x, invader.position.y, invader.position.z);
   gl.glRotatef(invaderAngle, 0, 1, 0);
   invaderMesh.render(GL10.GL_TRIANGLES);
   gl.glPopMatrix();
  }
 }

這是例子中通過mesh繪圖的代碼

invaderMesh.render(GL10.GL_TRIANGLES);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章