OSDN Git Service

* Proper aging for particles emitted in a frame
authorshadowislord <shadowislord@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Sun, 31 Jul 2011 20:51:05 +0000 (20:51 +0000)
committershadowislord <shadowislord@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Sun, 31 Jul 2011 20:51:05 +0000 (20:51 +0000)
git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@7958 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/core/com/jme3/effect/ParticleEmitter.java

index 9e71525..53bb463 100644 (file)
@@ -90,7 +90,7 @@ public class ParticleEmitter extends Geometry {
     private boolean selectRandomImage;
     private boolean facingVelocity;
     private float particlesPerSec = 20;
-    private float emitCarry;
+    private float timeDifference = 0;
     private float lowLife = 3f;
     private float highLife = 7f;
     private Vector3f gravity = new Vector3f(0.0f, 0.1f, 0.0f);
@@ -206,8 +206,6 @@ public class ParticleEmitter extends Geometry {
 
         meshType = type;
 
-
-
         // Must create clone of shape/influencer so that a reference to a static is 
         // not maintained
         shape = shape.deepClone();
@@ -859,13 +857,13 @@ public class ParticleEmitter extends Geometry {
 //        assert !unusedIndices.contains(index);
 //        unusedIndices.add(index);
 //    }
-    private boolean emitParticle(Vector3f min, Vector3f max) {
+    private Particle emitParticle(Vector3f min, Vector3f max) {
 //        int idx = newIndex();
 //        if (idx == -1)
 //            return false;
         int idx = lastUsed + 1;
         if (idx >= particles.length) {
-            return false;
+            return null;
         }
 
         Particle p = particles[idx];
@@ -896,7 +894,7 @@ public class ParticleEmitter extends Geometry {
 
         ++lastUsed;
         firstUnUsed = idx + 1;
-        return true;
+        return p;
     }
 
     /**
@@ -924,7 +922,7 @@ public class ParticleEmitter extends Geometry {
             max.set(Vector3f.NEGATIVE_INFINITY);
         }
 
-        while (emitParticle(min, max));
+        while (emitParticle(min, max) != null);
 
         bbox.setMinMax(min, max);
         this.setBoundRefresh();
@@ -971,13 +969,37 @@ public class ParticleEmitter extends Geometry {
         particles[idx2] = p1;
     }
 
+    private void updateParticle(Particle p, float tpf, Vector3f min, Vector3f max){
+        // applying gravity
+        p.velocity.x -= gravity.x * tpf;
+        p.velocity.y -= gravity.y * tpf;
+        p.velocity.z -= gravity.z * tpf;
+        temp.set(p.velocity).multLocal(tpf);
+        p.position.addLocal(temp);
+
+        // affecting color, size and angle
+        float b = (p.startlife - p.life) / p.startlife;
+        p.color.interpolate(startColor, endColor, b);
+        p.size = FastMath.interpolateLinear(b, startSize, endSize);
+        p.angle += p.rotateSpeed * tpf;
+
+        // Computing bounding volume
+        temp.set(p.position).addLocal(p.size, p.size, p.size);
+        max.maxLocal(temp);
+        temp.set(p.position).subtractLocal(p.size, p.size, p.size);
+        min.minLocal(temp);
+
+        if (!selectRandomImage) {
+            p.imageIndex = (int) (b * imagesX * imagesY);
+        }
+    }
+    
     private void updateParticleState(float tpf) {
         // Force world transform to update
         this.getWorldTransform();
 
         TempVars vars = TempVars.get();
 
-
         Vector3f min = vars.vect1.set(Vector3f.POSITIVE_INFINITY);
         Vector3f max = vars.vect2.set(Vector3f.NEGATIVE_INFINITY);
 
@@ -994,31 +1016,7 @@ public class ParticleEmitter extends Geometry {
                 continue;
             }
 
-            // position += velocity * tpf
-            //p.distToCam = -1;
-
-            // applying gravity
-            p.velocity.x -= gravity.x * tpf;
-            p.velocity.y -= gravity.y * tpf;
-            p.velocity.z -= gravity.z * tpf;
-            temp.set(p.velocity).multLocal(tpf);
-            p.position.addLocal(temp);
-
-            // affecting color, size and angle
-            float b = (p.startlife - p.life) / p.startlife;
-            p.color.interpolate(startColor, endColor, b);
-            p.size = FastMath.interpolateLinear(b, startSize, endSize);
-            p.angle += p.rotateSpeed * tpf;
-
-            // Computing bounding volume
-            temp.set(p.position).addLocal(p.size, p.size, p.size);
-            max.maxLocal(temp);
-            temp.set(p.position).subtractLocal(p.size, p.size, p.size);
-            min.minLocal(temp);
-
-            if (!selectRandomImage) {
-                p.imageIndex = (int) (b * imagesX * imagesY);
-            }
+            updateParticle(p, tpf, min, max);
 
             if (firstUnUsed < i) {
                 this.swap(firstUnUsed, i);
@@ -1028,19 +1026,23 @@ public class ParticleEmitter extends Geometry {
                 firstUnUsed++;
             }
         }
-
-        float particlesToEmitF = particlesPerSec * tpf;
-        int particlesToEmit = (int) particlesToEmitF;
-        emitCarry += particlesToEmitF - particlesToEmit;
-
-        while (emitCarry > 1f) {
-            ++particlesToEmit;
-            emitCarry -= 1f;
-        }
-
-        for (int i = 0; i < particlesToEmit; ++i) {
-            this.emitParticle(min, max);
+        
+        // Spawns particles within the tpf timeslot with proper age
+        float interval = 1f / particlesPerSec;
+        tpf += timeDifference;
+        while (tpf > interval){
+            tpf -= interval;
+            Particle p = emitParticle(min, max);
+            if (p != null){
+                p.life -= tpf;
+                if (p.life <= 0){
+                    freeParticle(lastUsed);
+                }else{
+                    updateParticle(p, tpf, min, max);
+                }
+            }
         }
+        timeDifference = tpf;
 
         BoundingBox bbox = (BoundingBox) this.getMesh().getBound();
         bbox.setMinMax(min, max);