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> meshes = new HashMap>();

 /** 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 attributes = new ArrayList();
  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 attributes = new ArrayList();
  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 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);

你可能感兴趣的:(android,开发系列教程)