|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 5
// Initialize the engine at the start of the program.
ps = new PS (display);
// In some other method ...
// Reset the engine in case some other simulation has ended before
// all particles have died.
ps.reset ();
// Generate a single white particle in the lower-right quadrant of
// the window. This particle will move towards the upper-left
// quadrant.
// At least one particle must be created before the animation loop
// because isFinished() will return true if no alive particles are
// present, and there are no alive particles following a reset()
// method call.
ps.generateParticle (PS.PARTICLE_TYPE_CONSTANT,
PS.PARTICLE_COLOR_TYPE_WHITE,
300,
0,
75.0,
-75.0,
-1.0,
1.0);
// Establish the animation.
Runnable r = new Runnable ()
{
public void run ()
{
Thread thdCurrent = Thread.currentThread ();
while (thdCurrent == thd && !ps.isFinished ())
{
// Erase the contents of the background
// buffer to remove the particle from its
// previous position.
display.clear ();
// Transition the particle system to a new
// state. This might involve the death of
// the particle.
ps.update ();
// Display's plot() method, which ps.update()
// calls, renders the particle in the
// background buffer in its new position. A
// repaint() call is needed to display the
// buffer on the surface of the Display
// component.
display.repaint ();
// Every animation needs to sleep for a length
// of time before moving on to the next frame.
try
{
Thread.sleep (DELAY);
}
catch (InterruptedException e)
{
}
}
}
};
// Prepare new simulation thread and begin the simulation.
thd = new Thread (r);
thd.start ();
My particle system software lets you simulate a wide variety of fuzzy phenomena. To give you some idea of what is possible,
I've created a PSDemo applet that demonstrates explosion rings, fireworks explosions, and vapor trails.
The movies Star Trek VI: The Undiscovered Country and Star Wars: A New Hope feature a ring of energy/matter moving away from an exploded moon, planet, and deathstar. I like this explosion ring effect and have created a particle system that simulates explosion rings. Because of 2D graphics limitations, however, you don't see the effect in all of its glory. Instead, you observe the effect as if you were looking down on it (or looking up at it). The result, shown in Figure 4, looks more like rings of plasma ejected from a star going nova.

Figure 4. The outer explosion ring accelerates away from the inner explosion ring
To simplify the explosion ring simulation, I wrote a startExplosionRing() method that generates a specific number of particles. Each particle is given the same starting location, a random departure
angle (to achieve a circular ring effect), and a velocity constrained to a bounded range of randomly-generated velocities.
An acceleration factor is applied to the velocity so that the outer explosion ring pulls away from the inner explosion ring
(which I think looks cool). This method, excerpted from PSDemo, appears below:
void startExplosionRing (int type, int color_type, int lifetime, int age,
double x, double y, double xv, double yv,
double accel, int num_particles)
{
while (--num_particles >= 0)
{
// Calculate particle's departure angle in terms of degrees.
int ang = PS.rnd (0, 359);
// All particles must leave the explosion's center within a limited
// range of velocities.
double vel = 1.5+rnd (0.0, 0.5);
// Accelerate or decelerate the explosion ring if accel is not 1.0.
vel *= accel;
// Generate the particle so that it leaves the explosion ring in the
// appropriate direction.
ps.generateParticle (type, color_type, lifetime, age, x, y,
xv+Math.cos (Math.toRadians (ang))*vel,
yv+Math.sin (Math.toRadians (ang))*vel);
}
}
The explosion ring simulation resets the engine, calls startExplosionRing() to start an explosion ring, and creates/starts a thread to handle the animation. The animation thread loop iteration clears
the display, updates the particle system, paints the display on the component surface, increments the counter, and then sleeps.
When the counter reaches 8, another explosion ring starts. These tasks are carried out by PSDemo's explosionRing() method:
void explosionRing ()
{
btnFireworksExplosion.setEnabled (false);
btnVaporTrail.setEnabled (false);
btnExplosionRing.setEnabled (false);
// Reset the particle system.
ps.reset ();
// Generate 1000 particles that are positioned at the center of the
// outer explosion ring and share the same range of velocities. Give the
// outer explosion ring a higher acceleration than the inner explosion
// ring so that the outer explosion ring pulls away from the inner
// explosion ring.
final double x;
final double y;
startExplosionRing (PS.PARTICLE_TYPE_FLICKERFADE,
PS.PARTICLE_COLOR_TYPE_GREEN,
300,
0,
x = rnd (-75.0, 75.0),
y = rnd (-75.0, 75.0),
0,
0,
1.6,
1000);
Runnable r = new Runnable ()
{
public void run ()
{
int counter = 0;
Thread thdCurrent = Thread.currentThread ();
while (thdCurrent == thd && !ps.isFinished ())
{
display.clear ();
ps.update ();
display.repaint ();
try
{
Thread.sleep (DELAY_EXPLOSION_RING);
}
catch (InterruptedException e)
{
}
// After a small delay, generate a secondary
// explosion ring consisting of 500 particles.
// These particles are positioned at the center
// of the explosion ring and share the same range
// of velocities.
if (++counter == 8)
startExplosionRing (PS.PARTICLE_TYPE_FADE,
PS.PARTICLE_COLOR_TYPE_YELLOW,
300,
0,
x,
y,
0,
0,
1.0,
500);
}
btnFireworksExplosion.setEnabled (true);
btnVaporTrail.setEnabled (true);
btnExplosionRing.setEnabled (true);
}
};
thd = new Thread (r);
thd.start ();
}
I love watching fireworks displays, especially the exploding balls of energy/matter. I've created a particle system to simulate this effect. As Figure 5 reveals, the particle system uses multiple colors to enhance the explosion.

Figure 5. A fireworks explosion is circular
To simplify the fireworks explosion simulation, I wrote a startFireworksExplosion() method that generates a specific number of particles. Each particle is given the same starting location, a random departure
angle (to achieve a circular effect), and a unique velocity. This method, excerpted from PSDemo, appears below:
void startFireworksExplosion (int type, int color_type, int lifetime,
int age, double x, double y, double xv,
double yv, int num_particles)
{
// Each particle must be given a unique velocity for the fireworks
// explosion to look realistic. This is accomplished first by calculating
// a velocity increment based on the number of particles, and then by
// specifying num_particles velocities, where each velocity is a unique
// multiple of the increment.
double incr = 1.0/num_particles;
double vel = 0.0;
while (--num_particles >= 0)
{
// Calculate particle's departure angle in terms of degrees.
int ang = PS.rnd (0, 359);
// Establish appropriate departure velocity.
vel += incr;
// Generate the particle so that it leaves the fireworks explosion's
// center in the appropriate direction and at the appropriate
// velocity.
ps.generateParticle (type, color_type, lifetime, age, x, y,
xv+Math.cos (Math.toRadians (ang))*vel,
yv+Math.sin (Math.toRadians (ang))*vel);
}
}
The fireworks explosion simulation resets the engine, calls startFireworksExplosion() three times to start three fireworks explosions (each with a different color for its particles; all three beginning at the
same window location), establishes some gravity to pull the particles toward the bottom of the window, and creates/starts
a thread to take care of the animation. The animation thread loop iteration clears the display, updates the particle system,
paints the display on the component surface, and then sleeps. These tasks are carried out by PSDemo's fireworksExplosion() method:
void fireworksExplosion ()
{
btnVaporTrail.setEnabled (false);
btnExplosionRing.setEnabled (false);
btnFireworksExplosion.setEnabled (false);
ps.reset ();
// Generate 4000 particles that are positioned at the center of the
// fireworks explosion and have unique velocities.
double x;
double y;
startFireworksExplosion (PS.PARTICLE_TYPE_FLICKERFADE,
PS.PARTICLE_COLOR_TYPE_YELLOW,
800,
PS.rnd (50, 100),
x = rnd (-75.0, 75.0),
y = rnd (-75.0, 75.0),
0,
0,
4000);
// Generate 500 particles of a different color that are positioned at
// the center of the fireworks explosion and have unique velocities among
// themselves. This adds a more colorful effect to the explosion.
startFireworksExplosion (PS.PARTICLE_TYPE_FADE,
PS.PARTICLE_COLOR_TYPE_RED,
800,
PS.rnd (50, 100),
x,
y,
0,
0,
500);
// Generate 250 particles of a different color that are positioned at
// the center of the fireworks explosion and have unique velocities among
// themselves. This adds an even more colorful effect to the explosion.
startFireworksExplosion (PS.PARTICLE_TYPE_FADE,
PS.PARTICLE_COLOR_TYPE_WHITE,
800,
PS.rnd (50, 100),
x,
y,
0,
0,
250);
// Because the fireworks explosion happens in the atmosphere of a planet,
// particles will be pulled toward the ground via the planet's
// gravitational force. Because of the window transform, a negative
// value must be used to pull particles toward the bottom of the window.
ps.setGravity (-0.01);
Runnable r = new Runnable ()
{
public void run ()
{
Thread thdCurrent = Thread.currentThread ();
while (thdCurrent == thd && !ps.isFinished ())
{
display.clear ();
ps.update ();
display.repaint ();
try
{
Thread.sleep (DELAY_FIREWORKS_EXPLOSION);
}
catch (InterruptedException e)
{
}
}
btnVaporTrail.setEnabled (true);
btnExplosionRing.setEnabled (true);
btnFireworksExplosion.setEnabled (true);
}
};
thd = new Thread (r);
thd.start ();
}
The final effect that I've simulated with a particle system is the vapor trail—a streak of condensed water vapor created in the atmosphere by an airplane or a rocket at a high altitude. I've fudged this definition somewhat by assuming that a vapor trail can alternatively consist of plasma fired from a rocket engine in space. Figure 6 reveals this assumption by showing one frame of an animation where an arrow-shaped rocket travels through space and ejects plasma from its engine nozzle—an emitter of particles.

Figure 6. A vapor trail spreads out as it moves away from the emitter
The vapor trail simulation resets the engine and creates/starts a thread to handle the animation. The animation thread establishes
an emitter location, generates an initial particle to ensure at least one live particle exists before entering the animation
loop, and enters the loop. Each loop iteration generates a random number of particles with random velocities constrained to
a specific range of directions, clears the display, updates the particle system, draws an arrow shape signifying a rocket
and its direction, calls repaint(), sleeps, and moves the emitter in an upper-left direction so that the trail flows in a lower-right direction. These tasks
are carried out by PSDemo's vaporTrail() method:
void vaporTrail ()
{
btnExplosionRing.setEnabled (false);
btnFireworksExplosion.setEnabled (false);
btnVaporTrail.setEnabled (false);
ps.reset ();
Runnable r;
r = new Runnable ()
{
public void run ()
{
// Vapor trail particles emerge from an emitter -- the nozzle
// of a rocket ship, for example. Establish the emitter's
// initial location in the lower-right quadrant of the window.
double emit_x = 75.0;
double emit_y = -75.0;
// Generate an initial particle. At least one particle must
// exist. Otherwise, ps.isFinished() returns false (because
// there are no alive particles) and the while loop is never
// entered.
ps.generateParticle (PS.PARTICLE_TYPE_FADE,
PS.PARTICLE_COLOR_TYPE_WHITE,
300,
PS.rnd (90, 150),
emit_x,
emit_y,
1.0,
-1.0);
Thread thdCurrent = Thread.currentThread ();
while (thdCurrent == thd && !ps.isFinished ())
{
// Create a group of particles that blast forth in various
// directions from the emitter. Directions are constrained
// so that the vapor trail moves in the opposite direction
// to the emitter.
int limit = PS.rnd (30, 130);
for (int i = 0; i < limit; i++)
{
double xv = rnd (1.0, 7.0);
double yv = rnd (-1.0, -7.0);
ps.generateParticle (PS.PARTICLE_TYPE_FADE,
PS.PARTICLE_COLOR_TYPE_WHITE,
300,
PS.rnd (90, 150),
emit_x,
emit_y,
xv,
yv);
}
display.clear ();
ps.update ();
// Draw a rocket. (As an exercise, make the rocket look
// more realistic than its current arrow shape.)
display.drawLine (emit_x-8, emit_y+8, emit_x-8, emit_y-2,
Color.magenta);
display.drawLine (emit_x-8, emit_y+8, emit_x+2, emit_y+8,
Color.magenta);
display.drawLine (emit_x-8, emit_y+8, emit_x+2, emit_y-2,
Color.magenta);
display.repaint ();
try
{
Thread.sleep (DELAY_VAPOR_TRAIL);
}
catch (InterruptedException e)
{
}
// Move the emitter (and rocket) in a diagonal direction
// towards the upper-left corner of the window.
emit_x -= 1.0;
emit_y += 1.0;
}
btnExplosionRing.setEnabled (true);
btnFireworksExplosion.setEnabled (true);
btnVaporTrail.setEnabled (true);
}
};
thd = new Thread (r);
thd.start ();
}
Within each of the startExplosionRing(), startFireworksExplosion(), and startVaporTrail() methods, I disable GUI buttons to prevent another simulation from being selected while a simulation is running. I re-enable
those buttons when the simulation finishes. You might be wondering why I change the button order from method to method when
disabling buttons. I do this because the focus shifts to the last disabled button and I don't want the focus to shift away
from the currently focused button.
It's fun to simulate different kinds of fuzzy phenomena with particle systems. After playing with the applet's explosion ring, fireworks explosion, and vapor trail simulations, you might consider improving the existing simulations and introducing your own simulations. I have some ideas that can help get you started:
PSDemo's GUI to include configuration items. Perhaps you might want to introduce a java.awt.Choice component for modifying the color of the vapor trail, or for determining if a particle type should be constant, fade, or
flicker-fade.
PS's update() method decrement the current color every other time (rather than every time) this method is called. Modify PSDemo to use these new constants.
Although this article's 2D-based particle system software lets you create interesting particle systems, you'll probably want to build 3D-based particle system software to achieve more impressive particle systems. To learn how to build this software, I recommend reading Mike Jacobs's "Star Trek Technology for Java3D" (Java Developers Journal, July 2005).
Read more about Core Java in JavaWorld's Core Java section.
Archived Discussions (Read only)