Просмотр исходного кода

Particle Emitter :
- fixed setNumParticle method to correctly update the mesh buffers
- added a getMaxNumParticle that returns the max number of particles of the emitter
- changed testMovingParticles and testPointSprite to change the numParticle when hitting the space bar

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7939 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

rem..om 14 лет назад
Родитель
Сommit
8f59984d00

+ 34 - 27
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 EmitterShape DEFAULT_SHAPE = new EmitterPointShape(Vector3f.ZERO);
     private static final ParticleInfluencer DEFAULT_INFLUENCER = new DefaultParticleInfluencer();
     private static final ParticleInfluencer DEFAULT_INFLUENCER = new DefaultParticleInfluencer();
-    
     private ParticleEmitterControl control;
     private ParticleEmitterControl control;
     private EmitterShape shape = DEFAULT_SHAPE;
     private EmitterShape shape = DEFAULT_SHAPE;
     private ParticleMesh particleMesh;
     private ParticleMesh particleMesh;
@@ -110,19 +109,19 @@ public class ParticleEmitter extends Geometry {
     public static class ParticleEmitterControl implements Control {
     public static class ParticleEmitterControl implements Control {
 
 
         ParticleEmitter parentEmitter;
         ParticleEmitter parentEmitter;
-        
-        public ParticleEmitterControl(){
+
+        public ParticleEmitterControl() {
         }
         }
-        
-        public ParticleEmitterControl(ParticleEmitter parentEmitter){
+
+        public ParticleEmitterControl(ParticleEmitter parentEmitter) {
             this.parentEmitter = parentEmitter;
             this.parentEmitter = parentEmitter;
         }
         }
-        
+
         public Control cloneForSpatial(Spatial spatial) {
         public Control cloneForSpatial(Spatial spatial) {
             return this; // WARNING: Sets wrong control on spatial. Will be
             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) {
         public void setSpatial(Spatial spatial) {
         }
         }
 
 
@@ -153,21 +152,21 @@ public class ParticleEmitter extends Geometry {
     public ParticleEmitter clone() {
     public ParticleEmitter clone() {
         ParticleEmitter clone = (ParticleEmitter) super.clone();
         ParticleEmitter clone = (ParticleEmitter) super.clone();
         clone.shape = shape.deepClone();
         clone.shape = shape.deepClone();
-        
+
         // Reinitialize particle list
         // Reinitialize particle list
         clone.setNumParticles(particles.length);
         clone.setNumParticles(particles.length);
-        
+
         clone.faceNormal = faceNormal.clone();
         clone.faceNormal = faceNormal.clone();
         clone.startColor = startColor.clone();
         clone.startColor = startColor.clone();
         clone.endColor = endColor.clone();
         clone.endColor = endColor.clone();
         clone.particleInfluencer = particleInfluencer.clone();
         clone.particleInfluencer = particleInfluencer.clone();
-        
+
         // remove wrong control
         // remove wrong control
         clone.controls.remove(control);
         clone.controls.remove(control);
-        
+
         // put correct control
         // put correct control
         clone.controls.add(new ParticleEmitterControl(clone));
         clone.controls.add(new ParticleEmitterControl(clone));
-        
+
         // Reinitialize particle mesh
         // Reinitialize particle mesh
         switch (meshType) {
         switch (meshType) {
             case Point:
             case Point:
@@ -183,7 +182,7 @@ public class ParticleEmitter extends Geometry {
         }
         }
         clone.particleMesh.initParticleData(clone, clone.particles.length);
         clone.particleMesh.initParticleData(clone, clone.particles.length);
         clone.particleMesh.setImagesXY(clone.imagesX, clone.imagesY);
         clone.particleMesh.setImagesXY(clone.imagesX, clone.imagesY);
-        
+
         return clone;
         return clone;
     }
     }
 
 
@@ -201,8 +200,8 @@ public class ParticleEmitter extends Geometry {
 
 
         meshType = type;
         meshType = type;
 
 
-        this.setNumParticles(numParticles);
-        
+
+
         // Must create clone of shape/influencer so that a reference to a static is 
         // Must create clone of shape/influencer so that a reference to a static is 
         // not maintained
         // not maintained
         shape = shape.deepClone();
         shape = shape.deepClone();
@@ -223,7 +222,8 @@ public class ParticleEmitter extends Geometry {
             default:
             default:
                 throw new IllegalStateException("Unrecognized particle type: " + meshType);
                 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++) {
         for (int i = 0; i < numParticles; i++) {
             particles[i] = new Particle();
             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;
         firstUnUsed = 0;
         lastUsed = -1;
         lastUsed = -1;
     }
     }
 
 
+    public int getMaxNumParticles() {
+        return particles.length;
+    }
+
     /**
     /**
      * Returns a list of all particles (shouldn't be used in most cases).
      * 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);
         super.read(im);
         InputCapsule ic = im.getCapsule(this);
         InputCapsule ic = im.getCapsule(this);
         shape = (EmitterShape) ic.readSavable("shape", DEFAULT_SHAPE);
         shape = (EmitterShape) ic.readSavable("shape", DEFAULT_SHAPE);
-        
-        if (shape == DEFAULT_SHAPE){
+
+        if (shape == DEFAULT_SHAPE) {
             // Prevent reference to static
             // Prevent reference to static
             shape = shape.deepClone();
             shape = shape.deepClone();
         }
         }
-        
+
         meshType = ic.readEnum("meshType", ParticleMesh.Type.class, ParticleMesh.Type.Triangle);
         meshType = ic.readEnum("meshType", ParticleMesh.Type.class, ParticleMesh.Type.Triangle);
         int numParticles = ic.readInt("numParticles", 0);
         int numParticles = ic.readInt("numParticles", 0);
         this.setNumParticles(numParticles);
         this.setNumParticles(numParticles);
@@ -1161,17 +1168,17 @@ public class ParticleEmitter extends Geometry {
         particleMesh.setImagesXY(imagesX, imagesY);
         particleMesh.setImagesXY(imagesX, imagesY);
 
 
         particleInfluencer = (ParticleInfluencer) ic.readSavable("influencer", DEFAULT_INFLUENCER);
         particleInfluencer = (ParticleInfluencer) ic.readSavable("influencer", DEFAULT_INFLUENCER);
-        if (particleInfluencer == DEFAULT_INFLUENCER){
+        if (particleInfluencer == DEFAULT_INFLUENCER) {
             particleInfluencer = particleInfluencer.clone();
             particleInfluencer = particleInfluencer.clone();
         }
         }
-  
-        if (im.getFormatVersion() == 0){
+
+        if (im.getFormatVersion() == 0) {
             // compatibility before the control inside particle emitter
             // compatibility before the control inside particle emitter
             // was changed:
             // was changed:
             // find it in the controls and take it out, then add the proper one in
             // 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);
                 Object obj = controls.get(i);
-                if (obj instanceof ParticleEmitter){
+                if (obj instanceof ParticleEmitter) {
                     controls.remove(i);
                     controls.remove(i);
                     // now add the proper one in
                     // now add the proper one in
                     controls.add(new ParticleEmitterControl(this));
                     controls.add(new ParticleEmitterControl(this));
@@ -1180,11 +1187,11 @@ public class ParticleEmitter extends Geometry {
             }
             }
 
 
             // compatability before gravity was not a vector but a float
             // compatability before gravity was not a vector but a float
-            if (gravity == null){
+            if (gravity == null) {
                 gravity = new Vector3f();
                 gravity = new Vector3f();
                 gravity.y = ic.readFloat("gravity", 0);
                 gravity.y = ic.readFloat("gravity", 0);
             }
             }
-        }else{
+        } else {
             // since the parentEmitter is not loaded, it must be 
             // since the parentEmitter is not loaded, it must be 
             // loaded separately
             // loaded separately
             control = getControl(ParticleEmitterControl.class);
             control = getControl(ParticleEmitterControl.class);

+ 29 - 4
engine/src/core/com/jme3/effect/ParticlePointMesh.java

@@ -64,26 +64,51 @@ public class ParticlePointMesh extends ParticleMesh {
         FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles);
         FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles);
         VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position);
         VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position);
         pvb.setupData(Usage.Stream, 3, Format.Float, pb);
         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
         // set colors
         ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4);
         ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4);
         VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color);
         VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color);
         cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb);
         cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb);
         cvb.setNormalized(true);
         cvb.setNormalized(true);
-        setBuffer(cvb);
+        
+        buf = getBuffer(VertexBuffer.Type.Color);
+        if (buf != null) {
+            buf.updateData(cb);
+        } else {
+            setBuffer(cvb);
+        }
 
 
         // set sizes
         // set sizes
         FloatBuffer sb = BufferUtils.createFloatBuffer(numParticles);
         FloatBuffer sb = BufferUtils.createFloatBuffer(numParticles);
         VertexBuffer svb = new VertexBuffer(VertexBuffer.Type.Size);
         VertexBuffer svb = new VertexBuffer(VertexBuffer.Type.Size);
         svb.setupData(Usage.Stream, 1, Format.Float, sb);
         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
         // set UV-scale
         FloatBuffer tb = BufferUtils.createFloatBuffer(numParticles*4);
         FloatBuffer tb = BufferUtils.createFloatBuffer(numParticles*4);
         VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord);
         VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord);
         tvb.setupData(Usage.Stream, 4, Format.Float, tb);
         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
     @Override

+ 31 - 6
engine/src/core/com/jme3/effect/ParticleTriMesh.java

@@ -66,14 +66,27 @@ public class ParticleTriMesh extends ParticleMesh {
         FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles * 4);
         FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles * 4);
         VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position);
         VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position);
         pvb.setupData(Usage.Stream, 3, Format.Float, pb);
         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
         // set colors
         ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4 * 4);
         ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4 * 4);
         VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color);
         VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color);
         cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb);
         cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb);
         cvb.setNormalized(true);
         cvb.setNormalized(true);
-        setBuffer(cvb);
+        
+        buf = getBuffer(VertexBuffer.Type.Color);
+        if (buf != null) {
+            buf.updateData(cb);
+        } else {
+            setBuffer(cvb);
+        }
 
 
         // set texcoords
         // set texcoords
         VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord);
         VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord);
@@ -89,7 +102,12 @@ public class ParticleTriMesh extends ParticleMesh {
         tb.flip();
         tb.flip();
         tvb.setupData(Usage.Static, 2, Format.Float, tb);
         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
         // set indices
         ShortBuffer ib = BufferUtils.createShortBuffer(numParticles * 6);
         ShortBuffer ib = BufferUtils.createShortBuffer(numParticles * 6);
@@ -110,9 +128,16 @@ public class ParticleTriMesh extends ParticleMesh {
         
         
         VertexBuffer ivb = new VertexBuffer(VertexBuffer.Type.Index);
         VertexBuffer ivb = new VertexBuffer(VertexBuffer.Type.Index);
         ivb.setupData(Usage.Static, 3, Format.UnsignedShort, ib);
         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
     @Override
     public void setImagesXY(int imagesX, int imagesY) {
     public void setImagesXY(int imagesX, int imagesY) {
         this.imagesX = imagesX;
         this.imagesX = imagesX;

+ 24 - 11
engine/src/test/jme3test/effect/TestMovingParticle.java

@@ -29,13 +29,16 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
-
 package jme3test.effect;
 package jme3test.effect;
 
 
 import com.jme3.app.SimpleApplication;
 import com.jme3.app.SimpleApplication;
 import com.jme3.effect.ParticleEmitter;
 import com.jme3.effect.ParticleEmitter;
 import com.jme3.effect.ParticleMesh.Type;
 import com.jme3.effect.ParticleMesh.Type;
 import com.jme3.effect.shapes.EmitterSphereShape;
 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.material.Material;
 import com.jme3.math.FastMath;
 import com.jme3.math.FastMath;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
@@ -45,19 +48,19 @@ import com.jme3.math.Vector3f;
  *
  *
  * @author Kirill Vainer
  * @author Kirill Vainer
  */
  */
-public class TestMovingParticle  extends SimpleApplication {
-
+public class TestMovingParticle extends SimpleApplication {
+    
     private ParticleEmitter emit;
     private ParticleEmitter emit;
     private float angle = 0;
     private float angle = 0;
-
-    public static void main(String[] args){
+    
+    public static void main(String[] args) {
         TestMovingParticle app = new TestMovingParticle();
         TestMovingParticle app = new TestMovingParticle();
         app.start();
         app.start();
     }
     }
-
+    
     @Override
     @Override
     public void simpleInitApp() {
     public void simpleInitApp() {
-        emit = new ParticleEmitter("Emitter", Type.Triangle, 200);
+        emit = new ParticleEmitter("Emitter", Type.Triangle, 300);
         emit.setGravity(0, 0, 0);
         emit.setGravity(0, 0, 0);
         emit.setVelocityVariation(1);
         emit.setVelocityVariation(1);
         emit.setLowLife(1);
         emit.setLowLife(1);
@@ -67,17 +70,27 @@ public class TestMovingParticle  extends SimpleApplication {
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
         mat.setTexture("Texture", assetManager.loadTexture("Effects/Smoke/Smoke.png"));
         mat.setTexture("Texture", assetManager.loadTexture("Effects/Smoke/Smoke.png"));
         emit.setMaterial(mat);
         emit.setMaterial(mat);
-
+        
         rootNode.attachChild(emit);
         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
     @Override
-    public void simpleUpdate(float tpf){
+    public void simpleUpdate(float tpf) {
         angle += tpf;
         angle += tpf;
         angle %= FastMath.TWO_PI;
         angle %= FastMath.TWO_PI;
         float x = FastMath.cos(angle) * 2;
         float x = FastMath.cos(angle) * 2;
         float y = FastMath.sin(angle) * 2;
         float y = FastMath.sin(angle) * 2;
         emit.setLocalTranslation(x, 0, y);
         emit.setLocalTranslation(x, 0, y);
     }
     }
-
 }
 }

+ 16 - 2
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.ParticleEmitter;
 import com.jme3.effect.ParticleMesh.Type;
 import com.jme3.effect.ParticleMesh.Type;
 import com.jme3.effect.shapes.EmitterBoxShape;
 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.material.Material;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
@@ -49,13 +52,13 @@ public class TestPointSprite extends SimpleApplication {
 
 
     @Override
     @Override
     public void simpleInitApp() {
     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),
         emit.setShape(new EmitterBoxShape(new Vector3f(-1.8f, -1.8f, -1.8f),
                                           new Vector3f(1.8f, 1.8f, 1.8f)));
                                           new Vector3f(1.8f, 1.8f, 1.8f)));
         emit.setGravity(0, 0, 0);
         emit.setGravity(0, 0, 0);
         emit.setLowLife(60);
         emit.setLowLife(60);
         emit.setHighLife(60);
         emit.setHighLife(60);
-        emit.setInitialVelocity(new Vector3f(0, 0, 0));
+        emit.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 0, 0));
         emit.setImagesX(15);
         emit.setImagesX(15);
         emit.setStartSize(0.05f);
         emit.setStartSize(0.05f);
         emit.setEndSize(0.05f);
         emit.setEndSize(0.05f);
@@ -70,6 +73,17 @@ public class TestPointSprite extends SimpleApplication {
         emit.setMaterial(mat);
         emit.setMaterial(mat);
 
 
         rootNode.attachChild(emit);
         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));
         
         
     }
     }