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