// ! Initializes a particle protected void initParticle(Particle particle) { // timeToLive // no negative life. prevent division by 0 particle.timeToLive = mLife + mLifeVar * randomMinus1To1(); particle.timeToLive = Math.max(0, particle.timeToLive); // position particle.pos.x = mSourcePosition.x + mPosVar.x * randomMinus1To1(); particle.pos.y = mSourcePosition.y + mPosVar.y * randomMinus1To1(); // Color int start; int r = Misc.clamp( Color.red(mStartColor) + (int) (Color.red(mStartColorVar) * randomMinus1To1()), 0, 255); int g = Misc.clamp( Color.green(mStartColor) + (int) (Color.green(mStartColorVar) * randomMinus1To1()), 0, 255); int b = Misc.clamp( Color.blue(mStartColor) + (int) (Color.blue(mStartColorVar) * randomMinus1To1()), 0, 255); int a = Misc.clamp( Color.alpha(mStartColor) + (int) (Color.alpha(mStartColorVar) * randomMinus1To1()), 0, 255); start = Color.argb(a, r, g, b); int end; r = Misc.clamp( Color.red(mEndColor) + (int) (Color.red(mEndColorVar) * randomMinus1To1()), 0, 255); g = Misc.clamp( Color.green(mEndColor) + (int) (Color.green(mEndColorVar) * randomMinus1To1()), 0, 255); b = Misc.clamp( Color.blue(mEndColor) + (int) (Color.blue(mEndColorVar) * randomMinus1To1()), 0, 255); a = Misc.clamp( Color.alpha(mEndColor) + (int) (Color.alpha(mEndColorVar) * randomMinus1To1()), 0, 255); end = Color.argb(a, r, g, b); particle.color = start; r = (int) ((Color.red(end) - Color.red(start)) / particle.timeToLive); g = (int) ((Color.green(end) - Color.green(start)) / particle.timeToLive); b = (int) ((Color.blue(end) - Color.blue(start)) / particle.timeToLive); a = (int) ((Color.alpha(end) - Color.alpha(start)) / particle.timeToLive); particle.deltaColor = new Colour(a, r, g, b); // size float startS = mStartSize + mStartSizeVar * randomMinus1To1(); startS = Math.max(0, startS); // No negative value particle.size = startS; if (mEndSize < 0) { particle.deltaSize = 0; } else { float endS = mEndSize + mEndSizeVar * randomMinus1To1(); endS = Math.max(0, endS); // No negative values particle.deltaSize = (endS - startS) / particle.timeToLive; } // rotation float startA = mStartSpin + mStartSpinVar * randomMinus1To1(); float endA = mEndSpin + mEndSpinVar * randomMinus1To1(); particle.rotation = startA; particle.deltaRotation = (endA - startA) / particle.timeToLive; if (mPositionType == PositionType.POSITION_GROUP) { particle.startPos = new Point(); } else { particle.startPos = new Point(mPosition); } // direction double radians = Math.toRadians(mAngle + mAngleVar * randomMinus1To1()); // Mode Gravity: A if (mEmitterMode == EmitterMode.MODE_GRAVITY) { Point v = new Point((float) Math.cos(radians), (float) Math.sin(radians)); float s = modeA.speed + modeA.speedVar * randomMinus1To1(); // direction particle.modeA.dir = Point.mult(v, s); // radial accel particle.modeA.radialAccel = modeA.radialAccel + modeA.radialAccelVar * randomMinus1To1(); // tangential accel particle.modeA.tangentialAccel = modeA.tangentialAccel + modeA.tangentialAccelVar * randomMinus1To1(); } else { // Mode Radius: B // Set the default diameter of the particle from the source position float startRadius = modeB.startRadius + modeB.startRadiusVar * randomMinus1To1(); float endRadius = modeB.endRadius + modeB.endRadiusVar * randomMinus1To1(); particle.modeB.radius = startRadius; if (modeB.endRadius < 0) { particle.modeB.deltaRadius = 0; } else { particle.modeB.deltaRadius = (endRadius - startRadius) / particle.timeToLive; } particle.modeB.angle = a; particle.modeB.degreesPerSecond = (float) Math.toRadians(modeB.rotatePerSecond + modeB.rotatePerSecondVar * randomMinus1To1()); } }
public void update(float dt) { if (mIsActive && mEmissionRate > 0) { float rate = 1.0f / mEmissionRate; // issue #1201, prevent bursts of particles, due to too high emitCounter if (mParticleCount < mTotalParticles) { mEmitCounter += dt; } while (mParticleCount < mTotalParticles && mEmitCounter > rate) { this.addParticle(); mEmitCounter -= rate; } mElapsed += dt; if (mDuration != -1 && mDuration < mElapsed) { this.stopEmitting(); } } mParticleIdx = 0; if (mIsVisible) { boolean needInvalidate = mParticleIdx < mParticleCount; while (mParticleIdx < mParticleCount) { Particle p = mParticles[mParticleIdx]; // life p.timeToLive -= dt; if (p.timeToLive > 0) { // Mode A: gravity, direction, tangential accel & radial accel if (mEmitterMode == EmitterMode.MODE_GRAVITY) { Point tmp, radial, tangential; // radial acceleration if (p.pos.x != 0 || p.pos.y != 0) { radial = Point.Normalize(p.pos); } else { radial = new Point(); } tangential = radial; radial = Point.mult(radial, p.modeA.radialAccel); // tangential acceleration float newY = tangential.x; tangential.x = -tangential.y; tangential.y = newY; tangential.multBy(p.modeA.tangentialAccel); // (gravity + radial + tangential) * dt // tmp = Point.add(Point.add(radial, tangential), modeA.gravity); tmp = tangential; tmp.addBy(radial); tmp.addBy(modeA.gravity); tmp.multBy(dt); p.modeA.dir.addBy(tmp); p.pos.addBy(Point.mult(p.modeA.dir, dt)); } else { // Mode B: radius movement // Update the angle and radius of the particle. p.modeB.angle += p.modeB.degreesPerSecond * dt; p.modeB.radius += p.modeB.deltaRadius * dt; p.pos.x = (float) (-Math.cos(p.modeB.angle) * p.modeB.radius); p.pos.y = (float) (-Math.sin(p.modeB.angle) * p.modeB.radius); } // color int r = Color.red(p.color) + (int) (p.deltaColor.r * dt); int g = Color.green(p.color) + (int) (p.deltaColor.g * dt); int b = Color.blue(p.color) + (int) (p.deltaColor.b * dt); int a = Color.alpha(p.color) + (int) (p.deltaColor.a * dt); p.color = Color.argb(a, r, g, b); // size p.size += (p.deltaSize * dt); p.size = Math.max(0, p.size); // angle p.rotation += (p.deltaRotation * dt); // update particle counter ++mParticleIdx; } else { // life < 0 if (mParticleIdx != mParticleCount - 1) { mParticles[mParticleIdx].copy(mParticles[mParticleCount - 1]); } --mParticleCount; } } // while if (needInvalidate && null != mCallbackRef) { UpdateCallback callback = mCallbackRef.get(); if (null != callback) { callback.needInvalidate(); } } } postStep(); }
public void update(int anim, int time) { float dt = (float) viewer.getDelta() * 0.001F; float grav = AnimatedFloat.getValue(gravity, anim, time); float deaccel = AnimatedFloat.getValue(gravity2, anim, time); if (emitterType == 1 || emitterType == 2) { float rate = AnimatedFloat.getValue(emissionRate, anim, time); float life = AnimatedFloat.getValue(lifespan, anim, time); float toSpawn = 0.0F; if (life != 0.0F) toSpawn = (dt * rate) / life + spawnRemainder; else toSpawn = spawnRemainder; if (toSpawn < 1.0F) { spawnRemainder = toSpawn; if (spawnRemainder < 0.0F) spawnRemainder = 0.0F; } else { int spawnCount = (int) toSpawn; if (spawnCount + particles.size() > 1000) spawnCount = 1000 - particles.size(); spawnRemainder = toSpawn - (float) spawnCount; float w = AnimatedFloat.getValue(areaWidth, anim, time) * 0.5F; float l = AnimatedFloat.getValue(areaLength, anim, time) * 0.5F; float speed = AnimatedFloat.getValue(emissionSpeed, anim, time); float var = AnimatedFloat.getValue(speedVariation, anim, time); float spread = AnimatedFloat.getValue(verticalRange, anim, time); float spread2 = AnimatedFloat.getValue(horizontalRange, anim, time); boolean en = true; int thisAnim = anim; if (thisAnim >= enabled.length) thisAnim = 0; if (enabled.length > 0 && enabled[thisAnim].used) en = enabled[thisAnim].getValue(time) != 0; if (en) { for (int i = 0; i < spawnCount; i++) { Particle p; if (emitterType == 1) p = PlaneEmitter.newParticle(this, anim, time, w, l, speed, var, spread, spread2); else p = SphereEmitter.newParticle(this, anim, time, w, l, speed, var, spread, spread2); particles.add(p); } } } } float speed = 1.0F; Vec3 t1 = new Vec3(); Vec3 t2 = new Vec3(); Vec3 t3 = new Vec3(); Point4f d = new Point4f(); Point4f c[] = new Point4f[3]; for (int i = 0; i < 3; i++) c[i] = new Point4f(); for (int i = 0; i < particles.size(); ) { Particle p = (Particle) particles.get(i); p.speed.add( Vec3.sub(Vec3.scale(p.down, grav * dt, t1), Vec3.scale(p.dir, deaccel * dt, t2), t3)); if (slowdown > 0.0F) speed = (float) Math.exp(-1F * slowdown * p.life); p.pos.add(Vec3.scale(p.speed, speed * dt, t1)); p.life += dt; float lifePos = p.life / p.maxLife; float s1 = size.data[0].x; float s2 = 0.0F; float s3 = 0.0F; if (size.data.length > 1) s2 = size.data[1].x; else s2 = s1; if (size.data.length > 2) s3 = size.data[2].x; else s3 = s2; p.size = lifeInterp(lifePos, 0.5F, s1 * scale.x, s2 * scale.y, s3 * scale.z); int limit = Math.min(3, color.data.length); for (int j = 0; j < limit; j++) { Point3f t = color.data[j]; c[j].set(t.x / 255F, t.y / 255F, t.z / 255F, (float) transparency.data[j] / 32767F); } if (limit < 3) { Point3f t = color.data[limit - 1]; for (int j = limit - 1; j < 3; j++) c[j].set(t.x / 255F, t.y / 255F, t.z / 255F, (float) transparency.data[j] / 32767F); } lifeInterp(lifePos, 0.5F, c[0], c[1], c[2], d); p.color.set(d); if (lifePos >= 1.0F) particles.remove(i); else i++; } }