159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.effect.shapes; 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule; 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter; 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule; 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath; 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList; 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.HashMap; 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List; 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Map; 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Map.Entry; 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This emiter shape emits the particles from the given shape's vertices 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski (Kaelthas) 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class EmitterMeshVertexShape implements EmitterShape { 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected List<List<Vector3f>> vertices; 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected List<List<Vector3f>> normals; 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Empty constructor. Sets nothing. 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public EmitterMeshVertexShape() { 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Constructor. It stores a copy of vertex list of all meshes. 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param meshes 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a list of meshes that will form the emitter's shape 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public EmitterMeshVertexShape(List<Mesh> meshes) { 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.setMeshes(meshes); 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method sets the meshes that will form the emiter's shape. 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param meshes 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a list of meshes that will form the emitter's shape 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setMeshes(List<Mesh> meshes) { 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Map<Vector3f, Vector3f> vertToNormalMap = new HashMap<Vector3f, Vector3f>(); 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.normals = new ArrayList<List<Vector3f>>(meshes.size()); 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Mesh mesh : meshes) { 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // fetching the data 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[] vertexTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Position)); 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[] normalTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Normal)); 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // unifying normals 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < vertexTable.length; i += 3) {// the tables should have the same size and be dividable by 3 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vert = new Vector3f(vertexTable[i], vertexTable[i + 1], vertexTable[i + 2]); 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f norm = vertToNormalMap.get(vert); 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (norm == null) { 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta norm = new Vector3f(normalTable[i], normalTable[i + 1], normalTable[i + 2]); 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertToNormalMap.put(vert, norm); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta norm.addLocal(normalTable[i], normalTable[i + 1], normalTable[i + 2]); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // adding data to vertices and normals 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector3f> vertices = new ArrayList<Vector3f>(vertToNormalMap.size()); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector3f> normals = new ArrayList<Vector3f>(vertToNormalMap.size()); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Entry<Vector3f, Vector3f> entry : vertToNormalMap.entrySet()) { 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertices.add(entry.getKey()); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normals.add(entry.getValue().normalizeLocal()); 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.vertices.add(vertices); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.normals.add(normals); 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method fills the point with coordinates of randomly selected mesh vertex. 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param store 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the variable to store with coordinates of randomly selected mesh vertex 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void getRandomPoint(Vector3f store) { 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() - 1); 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta store.set(vertices.get(meshIndex).get(vertIndex)); 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method fills the point with coordinates of randomly selected mesh vertex. 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The normal param is filled with selected vertex's normal. 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param store 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the variable to store with coordinates of randomly selected mesh vertex 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param normal 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * filled with selected vertex's normal 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() - 1); 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta store.set(vertices.get(meshIndex).get(vertIndex)); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normal.set(normals.get(meshIndex).get(vertIndex)); 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public EmitterShape deepClone() { 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EmitterMeshVertexShape clone = (EmitterMeshVertexShape) super.clone(); 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.vertices != null) { 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.vertices = new ArrayList<List<Vector3f>>(vertices.size()); 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (List<Vector3f> list : vertices) { 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector3f> vectorList = new ArrayList<Vector3f>(list.size()); 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Vector3f vector : list) { 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vectorList.add(vector.clone()); 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.vertices.add(vectorList); 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.normals != null) { 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.normals = new ArrayList<List<Vector3f>>(normals.size()); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (List<Vector3f> list : normals) { 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector3f> vectorList = new ArrayList<Vector3f>(list.size()); 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Vector3f vector : list) { 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vectorList.add(vector.clone()); 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.normals.add(vectorList); 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return clone; 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (CloneNotSupportedException e) { 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new AssertionError(); 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter ex) throws IOException { 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule oc = ex.getCapsule(this); 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.writeSavableArrayList((ArrayList<List<Vector3f>>) vertices, "vertices", null); 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.writeSavableArrayList((ArrayList<List<Vector3f>>) normals, "normals", null); 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @SuppressWarnings("unchecked") 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter im) throws IOException { 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule ic = im.getCapsule(this); 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.vertices = ic.readSavableArrayList("vertices", null); 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<List<Vector3f>> tmpNormals = ic.readSavableArrayList("normals", null); 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tmpNormals != null){ 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.normals = tmpNormals; 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 159