diff --git a/engine/src/core/com/jme3/effect/ParticleEmitter.java b/engine/src/core/com/jme3/effect/ParticleEmitter.java index a71159f32..e3f1f57a2 100644 --- a/engine/src/core/com/jme3/effect/ParticleEmitter.java +++ b/engine/src/core/com/jme3/effect/ParticleEmitter.java @@ -75,7 +75,6 @@ public class ParticleEmitter extends Geometry { private static final EmitterShape DEFAULT_SHAPE = new EmitterPointShape(Vector3f.ZERO); private static final ParticleInfluencer DEFAULT_INFLUENCER = new DefaultParticleInfluencer(); - private ParticleEmitterControl control; private EmitterShape shape = DEFAULT_SHAPE; private ParticleMesh particleMesh; @@ -110,19 +109,19 @@ public class ParticleEmitter extends Geometry { public static class ParticleEmitterControl implements Control { ParticleEmitter parentEmitter; - - public ParticleEmitterControl(){ + + public ParticleEmitterControl() { } - - public ParticleEmitterControl(ParticleEmitter parentEmitter){ + + public ParticleEmitterControl(ParticleEmitter parentEmitter) { this.parentEmitter = parentEmitter; } - + public Control cloneForSpatial(Spatial spatial) { return this; // WARNING: Sets wrong control on spatial. Will be - // fixed automatically by ParticleEmitter.clone() method. + // fixed automatically by ParticleEmitter.clone() method. } - + public void setSpatial(Spatial spatial) { } @@ -153,21 +152,21 @@ public class ParticleEmitter extends Geometry { public ParticleEmitter clone() { ParticleEmitter clone = (ParticleEmitter) super.clone(); clone.shape = shape.deepClone(); - + // Reinitialize particle list clone.setNumParticles(particles.length); - + clone.faceNormal = faceNormal.clone(); clone.startColor = startColor.clone(); clone.endColor = endColor.clone(); clone.particleInfluencer = particleInfluencer.clone(); - + // remove wrong control clone.controls.remove(control); - + // put correct control clone.controls.add(new ParticleEmitterControl(clone)); - + // Reinitialize particle mesh switch (meshType) { case Point: @@ -183,7 +182,7 @@ public class ParticleEmitter extends Geometry { } clone.particleMesh.initParticleData(clone, clone.particles.length); clone.particleMesh.setImagesXY(clone.imagesX, clone.imagesY); - + return clone; } @@ -201,8 +200,8 @@ public class ParticleEmitter extends Geometry { meshType = type; - this.setNumParticles(numParticles); - + + // Must create clone of shape/influencer so that a reference to a static is // not maintained shape = shape.deepClone(); @@ -223,7 +222,8 @@ public class ParticleEmitter extends Geometry { default: throw new IllegalStateException("Unrecognized particle type: " + meshType); } - particleMesh.initParticleData(this, particles.length); + this.setNumParticles(numParticles); +// particleMesh.initParticleData(this, particles.length); } /** @@ -330,10 +330,17 @@ public class ParticleEmitter extends Geometry { for (int i = 0; i < numParticles; i++) { particles[i] = new Particle(); } + //We have to reinit the mesh's buffers with the new size + particleMesh.initParticleData(this, particles.length); + particleMesh.setImagesXY(this.imagesX, this.imagesY); firstUnUsed = 0; lastUsed = -1; } + public int getMaxNumParticles() { + return particles.length; + } + /** * Returns a list of all particles (shouldn't be used in most cases). * @@ -1117,12 +1124,12 @@ public class ParticleEmitter extends Geometry { super.read(im); InputCapsule ic = im.getCapsule(this); shape = (EmitterShape) ic.readSavable("shape", DEFAULT_SHAPE); - - if (shape == DEFAULT_SHAPE){ + + if (shape == DEFAULT_SHAPE) { // Prevent reference to static shape = shape.deepClone(); } - + meshType = ic.readEnum("meshType", ParticleMesh.Type.class, ParticleMesh.Type.Triangle); int numParticles = ic.readInt("numParticles", 0); this.setNumParticles(numParticles); @@ -1161,17 +1168,17 @@ public class ParticleEmitter extends Geometry { particleMesh.setImagesXY(imagesX, imagesY); particleInfluencer = (ParticleInfluencer) ic.readSavable("influencer", DEFAULT_INFLUENCER); - if (particleInfluencer == DEFAULT_INFLUENCER){ + if (particleInfluencer == DEFAULT_INFLUENCER) { particleInfluencer = particleInfluencer.clone(); } - - if (im.getFormatVersion() == 0){ + + if (im.getFormatVersion() == 0) { // compatibility before the control inside particle emitter // was changed: // find it in the controls and take it out, then add the proper one in - for (int i = 0; i < controls.size(); i++){ + for (int i = 0; i < controls.size(); i++) { Object obj = controls.get(i); - if (obj instanceof ParticleEmitter){ + if (obj instanceof ParticleEmitter) { controls.remove(i); // now add the proper one in controls.add(new ParticleEmitterControl(this)); @@ -1180,11 +1187,11 @@ public class ParticleEmitter extends Geometry { } // compatability before gravity was not a vector but a float - if (gravity == null){ + if (gravity == null) { gravity = new Vector3f(); gravity.y = ic.readFloat("gravity", 0); } - }else{ + } else { // since the parentEmitter is not loaded, it must be // loaded separately control = getControl(ParticleEmitterControl.class); diff --git a/engine/src/core/com/jme3/effect/ParticlePointMesh.java b/engine/src/core/com/jme3/effect/ParticlePointMesh.java index 6a66fe809..28db3e6dd 100644 --- a/engine/src/core/com/jme3/effect/ParticlePointMesh.java +++ b/engine/src/core/com/jme3/effect/ParticlePointMesh.java @@ -64,26 +64,51 @@ public class ParticlePointMesh extends ParticleMesh { FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles); VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position); pvb.setupData(Usage.Stream, 3, Format.Float, pb); - setBuffer(pvb); + + //if the buffer is already set only update the data + VertexBuffer buf = getBuffer(VertexBuffer.Type.Position); + if (buf != null) { + buf.updateData(pb); + } else { + setBuffer(pvb); + } // set colors ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4); VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color); cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb); cvb.setNormalized(true); - setBuffer(cvb); + + buf = getBuffer(VertexBuffer.Type.Color); + if (buf != null) { + buf.updateData(cb); + } else { + setBuffer(cvb); + } // set sizes FloatBuffer sb = BufferUtils.createFloatBuffer(numParticles); VertexBuffer svb = new VertexBuffer(VertexBuffer.Type.Size); svb.setupData(Usage.Stream, 1, Format.Float, sb); - setBuffer(svb); + + buf = getBuffer(VertexBuffer.Type.Size); + if (buf != null) { + buf.updateData(sb); + } else { + setBuffer(svb); + } // set UV-scale FloatBuffer tb = BufferUtils.createFloatBuffer(numParticles*4); VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord); tvb.setupData(Usage.Stream, 4, Format.Float, tb); - setBuffer(tvb); + + buf = getBuffer(VertexBuffer.Type.TexCoord); + if (buf != null) { + buf.updateData(tb); + } else { + setBuffer(tvb); + } } @Override diff --git a/engine/src/core/com/jme3/effect/ParticleTriMesh.java b/engine/src/core/com/jme3/effect/ParticleTriMesh.java index 55bd936cc..8d27838da 100644 --- a/engine/src/core/com/jme3/effect/ParticleTriMesh.java +++ b/engine/src/core/com/jme3/effect/ParticleTriMesh.java @@ -66,14 +66,27 @@ public class ParticleTriMesh extends ParticleMesh { FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles * 4); VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position); pvb.setupData(Usage.Stream, 3, Format.Float, pb); - setBuffer(pvb); - + + //if the buffer is already set only update the data + VertexBuffer buf = getBuffer(VertexBuffer.Type.Position); + if (buf != null) { + buf.updateData(pb); + } else { + setBuffer(pvb); + } + // set colors ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4 * 4); VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color); cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb); cvb.setNormalized(true); - setBuffer(cvb); + + buf = getBuffer(VertexBuffer.Type.Color); + if (buf != null) { + buf.updateData(cb); + } else { + setBuffer(cvb); + } // set texcoords VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord); @@ -89,7 +102,12 @@ public class ParticleTriMesh extends ParticleMesh { tb.flip(); tvb.setupData(Usage.Static, 2, Format.Float, tb); - setBuffer(tvb); + buf = getBuffer(VertexBuffer.Type.TexCoord); + if (buf != null) { + buf.updateData(tb); + } else { + setBuffer(tvb); + } // set indices ShortBuffer ib = BufferUtils.createShortBuffer(numParticles * 6); @@ -110,9 +128,16 @@ public class ParticleTriMesh extends ParticleMesh { VertexBuffer ivb = new VertexBuffer(VertexBuffer.Type.Index); ivb.setupData(Usage.Static, 3, Format.UnsignedShort, ib); - setBuffer(ivb); + + buf = getBuffer(VertexBuffer.Type.Index); + if (buf != null) { + buf.updateData(ib); + } else { + setBuffer(ivb); + } + } - + @Override public void setImagesXY(int imagesX, int imagesY) { this.imagesX = imagesX; diff --git a/engine/src/test/jme3test/effect/TestMovingParticle.java b/engine/src/test/jme3test/effect/TestMovingParticle.java index dba56e086..2e98a29a9 100644 --- a/engine/src/test/jme3test/effect/TestMovingParticle.java +++ b/engine/src/test/jme3test/effect/TestMovingParticle.java @@ -29,13 +29,16 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package jme3test.effect; import com.jme3.app.SimpleApplication; import com.jme3.effect.ParticleEmitter; import com.jme3.effect.ParticleMesh.Type; import com.jme3.effect.shapes.EmitterSphereShape; +import com.jme3.input.KeyInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.InputListener; +import com.jme3.input.controls.KeyTrigger; import com.jme3.material.Material; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; @@ -45,19 +48,19 @@ import com.jme3.math.Vector3f; * * @author Kirill Vainer */ -public class TestMovingParticle extends SimpleApplication { - +public class TestMovingParticle extends SimpleApplication { + private ParticleEmitter emit; private float angle = 0; - - public static void main(String[] args){ + + public static void main(String[] args) { TestMovingParticle app = new TestMovingParticle(); app.start(); } - + @Override public void simpleInitApp() { - emit = new ParticleEmitter("Emitter", Type.Triangle, 200); + emit = new ParticleEmitter("Emitter", Type.Triangle, 300); emit.setGravity(0, 0, 0); emit.setVelocityVariation(1); emit.setLowLife(1); @@ -67,17 +70,27 @@ public class TestMovingParticle extends SimpleApplication { Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); mat.setTexture("Texture", assetManager.loadTexture("Effects/Smoke/Smoke.png")); emit.setMaterial(mat); - + rootNode.attachChild(emit); + + inputManager.addListener(new ActionListener() { + + public void onAction(String name, boolean isPressed, float tpf) { + if ("setNum".equals(name) && isPressed) { + emit.setNumParticles(1000); + } + } + }, "setNum"); + + inputManager.addMapping("setNum", new KeyTrigger(KeyInput.KEY_SPACE)); } - + @Override - public void simpleUpdate(float tpf){ + public void simpleUpdate(float tpf) { angle += tpf; angle %= FastMath.TWO_PI; float x = FastMath.cos(angle) * 2; float y = FastMath.sin(angle) * 2; emit.setLocalTranslation(x, 0, y); } - } diff --git a/engine/src/test/jme3test/effect/TestPointSprite.java b/engine/src/test/jme3test/effect/TestPointSprite.java index 5d6f4ab33..77064d20b 100644 --- a/engine/src/test/jme3test/effect/TestPointSprite.java +++ b/engine/src/test/jme3test/effect/TestPointSprite.java @@ -36,6 +36,9 @@ import com.jme3.app.SimpleApplication; import com.jme3.effect.ParticleEmitter; import com.jme3.effect.ParticleMesh.Type; import com.jme3.effect.shapes.EmitterBoxShape; +import com.jme3.input.KeyInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.KeyTrigger; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; @@ -49,13 +52,13 @@ public class TestPointSprite extends SimpleApplication { @Override public void simpleInitApp() { - ParticleEmitter emit = new ParticleEmitter("Emitter", Type.Point, 10000); + final ParticleEmitter emit = new ParticleEmitter("Emitter", Type.Point, 10000); emit.setShape(new EmitterBoxShape(new Vector3f(-1.8f, -1.8f, -1.8f), new Vector3f(1.8f, 1.8f, 1.8f))); emit.setGravity(0, 0, 0); emit.setLowLife(60); emit.setHighLife(60); - emit.setInitialVelocity(new Vector3f(0, 0, 0)); + emit.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 0, 0)); emit.setImagesX(15); emit.setStartSize(0.05f); emit.setEndSize(0.05f); @@ -70,6 +73,17 @@ public class TestPointSprite extends SimpleApplication { emit.setMaterial(mat); rootNode.attachChild(emit); + inputManager.addListener(new ActionListener() { + + public void onAction(String name, boolean isPressed, float tpf) { + if ("setNum".equals(name) && isPressed) { + emit.setNumParticles(5000); + emit.emitAllParticles(); + } + } + }, "setNum"); + + inputManager.addMapping("setNum", new KeyTrigger(KeyInput.KEY_SPACE)); }