package com.nilunder.bdx.gl; import com.badlogic.gdx.graphics.g3d.Model; import com.badlogic.gdx.graphics.g3d.ModelInstance; import com.badlogic.gdx.graphics.g3d.model.MeshPart; import com.badlogic.gdx.graphics.g3d.model.NodePart; import com.badlogic.gdx.math.Matrix3; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.JsonReader; import com.nilunder.bdx.Bdx; import com.nilunder.bdx.Scene; import com.nilunder.bdx.utils.ArrayListNamed; import com.nilunder.bdx.utils.Color; import com.nilunder.bdx.utils.Named; import javax.vecmath.Matrix3f; import javax.vecmath.Matrix4f; import javax.vecmath.Vector2f; import javax.vecmath.Vector3f; import java.util.ArrayList; import java.util.HashMap; public class Mesh implements Named { public Model model; public String name; public Scene scene; public ArrayListMaterials materials; public ArrayList<ModelInstance> instances; public class ArrayListMaterials extends ArrayListNamed<Material> { public Material set(int index, Material material) { model.nodes.get(0).parts.get(index).material = material; for (ModelInstance m : instances) m.nodes.get(0).parts.get(index).material = material; return super.set(index, material); } public Material set(int index, String matName) { return set(index, scene.materials.get(matName)); } public void set(Material material){ for (int i = 0; i < size(); i++) { set(i, material); } } public void set(String matName){ set(scene.materials.get(matName)); } public void color(Color color){ for (Material mat : this) mat.color(color); } public void tint(Color color){ for (Material mat : this) mat.tint(color); } public void blendMode(int src, int dest){ for (Material mat : this) mat.blendMode(src, dest); } public void shadeless(boolean shadelessness){ for (Material mat : this) mat.shadeless(shadelessness); } } public Mesh(Model model, Scene scene, String name){ this.model = model; this.name = name; this.scene = scene; materials = new ArrayListMaterials(); for (NodePart part : model.nodes.get(0).parts) materials.add((Material) part.material); instances = new ArrayList<ModelInstance>(); } public Mesh(Model model, Scene scene){ this(model, scene, model.meshParts.first().id); } protected void finalize() throws Throwable { model.dispose(); } public int getVertexCount(int materialSlot){ return model.nodes.first().parts.get(materialSlot).meshPart.size; } public int getVertexCount(){ int count = 0; for (int i = 0; i < model.nodes.get(0).parts.size; i++) count += getVertexCount(i); return count; } public void vertPos(int materialSlot, int index, float x, float y, float z){ com.badlogic.gdx.graphics.Mesh mesh = model.meshes.first(); float[] verts = new float[getVertexCount() * Bdx.VERT_STRIDE]; mesh.getVertices(verts); int i = (model.meshParts.get(materialSlot).offset * Bdx.VERT_STRIDE) + (index * Bdx.VERT_STRIDE); verts[i] = x; verts[i+1] = y; verts[i+2] = z; mesh.setVertices(verts); } public void vertPos(int materialSlot, int index, Vector3f pos){ vertPos(materialSlot, index, pos.x, pos.y, pos.z); } public Vector3f vertPos(int materialSlot, int index){ com.badlogic.gdx.graphics.Mesh mesh = model.meshes.first(); float[] verts = new float[3]; mesh.getVertices((model.meshParts.get(materialSlot).offset * Bdx.VERT_STRIDE) + (index * Bdx.VERT_STRIDE), 3, verts); return new Vector3f(verts[0], verts[1], verts[2]); } public void vertNor(int materialSlot, int index, float x, float y, float z){ com.badlogic.gdx.graphics.Mesh mesh = model.meshes.first(); float[] verts = new float[getVertexCount() * Bdx.VERT_STRIDE]; mesh.getVertices(verts); int i = (model.meshParts.get(materialSlot).offset * Bdx.VERT_STRIDE) + (index * Bdx.VERT_STRIDE); verts[i+3] = x; verts[i+4] = y; verts[i+5] = z; mesh.setVertices(verts); } public void vertNor(int materialSlot, int index, Vector3f pos){ vertNor(materialSlot, index, pos.x, pos.y, pos.z); } public Vector3f vertNor(int materialSlot, int index){ com.badlogic.gdx.graphics.Mesh mesh = model.meshes.first(); float[] verts = new float[3]; mesh.getVertices((model.meshParts.get(materialSlot).offset * Bdx.VERT_STRIDE) + (index * Bdx.VERT_STRIDE) + 3, 3, verts); return new Vector3f(verts[0], verts[1], verts[2]); } public void vertUV(int materialSlot, int index, float u, float v){ com.badlogic.gdx.graphics.Mesh mesh = model.meshes.first(); float[] verts = new float[getVertexCount() * Bdx.VERT_STRIDE]; mesh.getVertices(verts); int i = (model.meshParts.get(materialSlot).offset * Bdx.VERT_STRIDE) + (index * Bdx.VERT_STRIDE); verts[i+6] = u; verts[i+7] = v; mesh.setVertices(verts); } public void vertUV(int materialSlot, int index, Vector2f uv){ vertUV(materialSlot, index, uv.x, uv.y); } public Vector2f vertUV(int materialSlot, int index){ com.badlogic.gdx.graphics.Mesh mesh = model.meshes.first(); float[] verts = new float[3]; mesh.getVertices((model.meshParts.get(materialSlot).offset * Bdx.VERT_STRIDE) + (index * Bdx.VERT_STRIDE) + 6, 2, verts); return new Vector2f(verts[0], verts[1]); } public void vertTransform(int materialSlot, Matrix4f matrix){ Matrix4f m = matrix; float[] vals = {m.m00, m.m10, m.m20, m.m30, m.m01, m.m11, m.m21, m.m31, m.m02, m.m12, m.m22, m.m32, m.m03, m.m13, m.m23, m.m33}; model.meshes.first().transform(new Matrix4(vals), model.meshParts.get(materialSlot).offset, model.meshParts.get(materialSlot).size); } public void vertTransformUV(int materialSlot, Matrix3f matrix){ Matrix3f m = matrix; float[] vals = {m.m00, m.m10, m.m20, m.m01, m.m11, m.m21, m.m02, m.m12, m.m22}; float[] verts = new float[getVertexCount() * Bdx.VERT_STRIDE]; model.meshes.first().getVertices(verts); MeshPart mp = model.meshParts.get(materialSlot); com.badlogic.gdx.graphics.Mesh.transformUV(new Matrix3(vals), verts, Bdx.VERT_STRIDE, 6, mp.offset, mp.size); model.meshes.first().setVertices(verts); } public String serialized() { HashMap<String, Float[]> out = new HashMap<String, Float[]>(); Float[] d; for (int i = 0; i < materials.size(); i++) { d = new Float[getVertexCount(i) * Bdx.VERT_STRIDE]; for (int v = 0; v < getVertexCount(i); v++) { int vi = v * 8; Vector3f p = vertPos(i, v); d[vi] = p.x; d[vi + 1] = p.y; d[vi + 2] = p.z; p = vertNor(i, v); d[vi + 3] = p.x; d[vi + 4] = p.y; d[vi + 5] = p.z; Vector2f u = vertUV(i, v); d[vi + 6] = u.x; d[vi + 7] = u.y; } out.put(materials.get(i).name(), d); } return new Json().toJson(out); } public String name(){ return name; } public Mesh copy(String newName){ Model uniqueModel = scene.createModel(new JsonReader().parse(serialized())); Mesh newMesh = new Mesh(uniqueModel, scene, newName); newMesh.materials.clear(); for (NodePart part : uniqueModel.nodes.get(0).parts) { Material newMat = new Material( (Material) part.material ); // Don't forget to cast to Material for it to be a true copy (see shader copying) newMesh.materials.add(newMat); part.material = newMat; } return newMesh; } public Mesh copy(){ return copy(name); } public ModelInstance getInstance(){ ModelInstance m = new ModelInstance(model); for (int i = 0; i < m.nodes.get(0).parts.size; i++) m.nodes.get(0).parts.get(i).material = materials.get(i); instances.add(m); return m; } public String toString(){ return name + " <" + getClass().getName() + "> @" + Integer.toHexString(hashCode()); } // Also UV, Normal, and Transforms (and possibly "do this to all" versions that don't use transforms?) }