* Proper aging for particles emitted in a frame

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7958 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
sha..rd 14 years ago
parent 6dcf5f2d50
commit 2767600fe3
  1. 90
      engine/src/core/com/jme3/effect/ParticleEmitter.java

@ -90,7 +90,7 @@ public class ParticleEmitter extends Geometry {
private boolean selectRandomImage; private boolean selectRandomImage;
private boolean facingVelocity; private boolean facingVelocity;
private float particlesPerSec = 20; private float particlesPerSec = 20;
private float emitCarry; private float timeDifference = 0;
private float lowLife = 3f; private float lowLife = 3f;
private float highLife = 7f; private float highLife = 7f;
private Vector3f gravity = new Vector3f(0.0f, 0.1f, 0.0f); private Vector3f gravity = new Vector3f(0.0f, 0.1f, 0.0f);
@ -206,8 +206,6 @@ public class ParticleEmitter extends Geometry {
meshType = type; meshType = type;
// 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();
@ -859,13 +857,13 @@ public class ParticleEmitter extends Geometry {
// assert !unusedIndices.contains(index); // assert !unusedIndices.contains(index);
// unusedIndices.add(index); // unusedIndices.add(index);
// } // }
private boolean emitParticle(Vector3f min, Vector3f max) { private Particle emitParticle(Vector3f min, Vector3f max) {
// int idx = newIndex(); // int idx = newIndex();
// if (idx == -1) // if (idx == -1)
// return false; // return false;
int idx = lastUsed + 1; int idx = lastUsed + 1;
if (idx >= particles.length) { if (idx >= particles.length) {
return false; return null;
} }
Particle p = particles[idx]; Particle p = particles[idx];
@ -896,7 +894,7 @@ public class ParticleEmitter extends Geometry {
++lastUsed; ++lastUsed;
firstUnUsed = idx + 1; firstUnUsed = idx + 1;
return true; return p;
} }
/** /**
@ -924,7 +922,7 @@ public class ParticleEmitter extends Geometry {
max.set(Vector3f.NEGATIVE_INFINITY); max.set(Vector3f.NEGATIVE_INFINITY);
} }
while (emitParticle(min, max)); while (emitParticle(min, max) != null);
bbox.setMinMax(min, max); bbox.setMinMax(min, max);
this.setBoundRefresh(); this.setBoundRefresh();
@ -971,13 +969,37 @@ public class ParticleEmitter extends Geometry {
particles[idx2] = p1; 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) { private void updateParticleState(float tpf) {
// Force world transform to update // Force world transform to update
this.getWorldTransform(); this.getWorldTransform();
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
Vector3f min = vars.vect1.set(Vector3f.POSITIVE_INFINITY); Vector3f min = vars.vect1.set(Vector3f.POSITIVE_INFINITY);
Vector3f max = vars.vect2.set(Vector3f.NEGATIVE_INFINITY); Vector3f max = vars.vect2.set(Vector3f.NEGATIVE_INFINITY);
@ -994,31 +1016,7 @@ public class ParticleEmitter extends Geometry {
continue; continue;
} }
// position += velocity * tpf updateParticle(p, tpf, min, max);
//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);
}
if (firstUnUsed < i) { if (firstUnUsed < i) {
this.swap(firstUnUsed, i); this.swap(firstUnUsed, i);
@ -1029,18 +1027,22 @@ public class ParticleEmitter extends Geometry {
} }
} }
float particlesToEmitF = particlesPerSec * tpf; // Spawns particles within the tpf timeslot with proper age
int particlesToEmit = (int) particlesToEmitF; float interval = 1f / particlesPerSec;
emitCarry += particlesToEmitF - particlesToEmit; tpf += timeDifference;
while (tpf > interval){
while (emitCarry > 1f) { tpf -= interval;
++particlesToEmit; Particle p = emitParticle(min, max);
emitCarry -= 1f; if (p != null){
} p.life -= tpf;
if (p.life <= 0){
for (int i = 0; i < particlesToEmit; ++i) { freeParticle(lastUsed);
this.emitParticle(min, max); }else{
updateParticle(p, tpf, min, max);
}
}
} }
timeDifference = tpf;
BoundingBox bbox = (BoundingBox) this.getMesh().getBound(); BoundingBox bbox = (BoundingBox) this.getMesh().getBound();
bbox.setMinMax(min, max); bbox.setMinMax(min, max);

Loading…
Cancel
Save