Hi, monkeys!
I want to create a particle system that emits particles from a model’s shape. I thought I found the solution with the EmitterMeshFaceShape
class, but it won’t work if I change the scale of the model since it uses the original Mesh
object as a base for the particles. Is there any other way to achieve what I want? Or is there a way to change the Mesh
's size with the Geometry
s?
Here is a sample code so you can see what I am trying to do:
package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.effect.shapes.EmitterMeshFaceShape;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author fba
*/
public class ParticlesOnMesh extends SimpleApplication {
public static void main(String... args) {
ParticlesOnMesh app = new ParticlesOnMesh();
app.start();
}
@Override
public void simpleInitApp() {
DirectionalLight sun = new DirectionalLight();
sun.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalizeLocal());
sun.setColor(ColorRGBA.White);
rootNode.addLight(sun);
AmbientLight ambient = new AmbientLight();
ambient.setColor(ColorRGBA.White.mult(.3f));
rootNode.addLight(ambient);
Spatial model = assetManager.loadModel("Models/Boat/boat.j3o");
model.setName("Model");
rootNode.attachChild(model);
rootNode.attachChild(createParticles());
// Uncomment the following line to see what happens when the scale is changed:
// model.scale(.5f);
// Uncomment the following line to see the particles only:
// rootNode.detachChild(model);
}
private ParticleEmitter createParticles() {
ParticleEmitter emitter = new ParticleEmitter("Particles", ParticleMesh.Type.Triangle, 10000);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
emitter.setMaterial(mat);
emitter.setStartColor(new ColorRGBA(1, .9725f, 0, 1));
emitter.setEndColor(new ColorRGBA(1, .1255f, 0, 1));
emitter.setStartSize(.1f);
emitter.setEndSize(.1f);
emitter.setLowLife(2);
emitter.setHighLife(5);
emitter.setImagesX(2);
emitter.setImagesY(2);
emitter.setParticlesPerSec(3000);
emitter.setGravity(Vector3f.ZERO);
List<Mesh> meshes = new ArrayList<>();
addMeshesToList(rootNode.getChild("Model"), meshes);
emitter.setShape(new EmitterMeshFaceShape(meshes)); // <-- Here the magic happens
return emitter;
}
private void addMeshesToList(Spatial spatial, List<Mesh> meshes) {
if (spatial instanceof Node) {
for (Spatial s : ((Node) spatial).getChildren()) {
if (s instanceof Node) {
addMeshesToList(s, meshes);
} else {
meshes.add(((Geometry) s).getMesh());
}
}
} else {
meshes.add(((Geometry) spatial).getMesh());
}
}
}