[quote]The server VM may give you a significant speed boost, as it has some array bounds checking removal.
[/quote]
Yes, I’ve been using -server ever since I found that out last week. The performance boost is SHUPAR!!! I want to emphasize:
ALWAYS USE SERVER VM IF YOU CAN!!!
Okay, 2D metaballs here :
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.Random;
import java.util.*;
/*
* 2D METABALLS, by Ben Yeoh, 7/05/04
*
* A humble reference for those wanting to write their own metaballs code
*
* Please share if you've got a simpler/quicker algorithm than what I have here.
*
*/
public class MetaballTest extends JFrame implements Runnable
{
static final boolean BUFFER_STRATEGY = true;
final byte CLEAR = 0;
static final int BITMASK_BLITS_PER_FRAME = 1;
static final int WINDOW_WIDTH = 800, WINDOW_HEIGHT = 600;
static final int METABALLS_SCREEN_WIDTH = 400, METABALLS_SCREEN_HEIGHT = 400;
Image bb;
BufferedImage blobby;
DataBufferByte db;
byte[] pixel;
Metaball[] balls;
boolean movingToCenter;
final int DISPERSION_DELAY = 30;
final int CHARGE_STRENGTH = 900;
final int ISO_RADIUS = 50; // pixels
final int INVISIBLE_THRESHOLD = 0;
final int ISO_DIAMETER = (ISO_RADIUS*2) + 1;
byte[] textureMap;
int[] x,y;
float[] movingWithAccel;
float[] movingWithDecel;
float[] movingWithAccelAndDecel;
float[] dispersionX;
float[] dispersionY;
final int NO_OF_BALLS = 32;
final int NO_OF_STEPS = 800;
final int NO_OF_DIRECTIONS = 60; // in 360 degrees
final int BUFFER_FROM_BORDER_WIDTH = 0; // pixels
final int BUFFER_FROM_BORDER_HEIGHT = 0; // pixels
final int NO_OF_POINTS = 4;
final int NO_OF_BALLS_PER_POINT = NO_OF_BALLS/NO_OF_POINTS;
int delayToDisperse;
int indexToDisperse;
Random rand;
ArrayList choiceList;
private ChoiceNumber[] choices;
int counter;
public static void main(String[] args)
{
Thread t = new Thread(new MetaballTest());
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
public MetaballTest()
{
setIgnoreRepaint(true);
getContentPane().setLayout(null);
setBounds(new Rectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT));
setVisible(true);
/*
* Declare and create our speed tables and direction vector tables based on sin and cos
*/
movingWithAccel = new float[NO_OF_STEPS];
movingWithDecel = new float[NO_OF_STEPS];
movingWithAccelAndDecel = new float[NO_OF_STEPS];
double UNIT = (Math.PI/2) / NO_OF_STEPS;
for(int i=1; i <= movingWithAccel.length; i++)
movingWithAccel[i-1] = (float) (Math.cos(Math.PI + i*UNIT) + 1);
for(int i=1; i <= movingWithDecel.length; i++)
movingWithDecel[i-1] = (float) Math.sin(i*UNIT);
UNIT = (Math.PI)/NO_OF_STEPS;
for(int i=1; i <= movingWithAccelAndDecel.length; i++)
movingWithAccelAndDecel[i-1] = (float) ((Math.cos(Math.PI + i*UNIT) + 1)/2);
dispersionX = new float[NO_OF_DIRECTIONS]; // Normalized direction vector arrays
dispersionY = new float[NO_OF_DIRECTIONS];
float radius = 1.0f;
for(int i=0; i < dispersionX.length; i++)
{
dispersionX[i] = (float) (radius * Math.cos(Math.toRadians(i*(360/NO_OF_DIRECTIONS))));
dispersionY[i] = (float) (radius * Math.sin(Math.toRadians(i*(360/NO_OF_DIRECTIONS))));
}
/*
* Declare our color pallette arrays
*/
byte[] red = new byte[256];
byte[] blue = new byte[256];
byte[] green = new byte[256];
byte[] alpha = new byte[256];
int index = 0; // this is used as a pointer to the array values
// BLACK TO DARK BLUE
for(int i=0; i < 64; i++, index++)
{
red[index] = (byte) 0;
green[index] = (byte) 0;
blue[index] = (byte)(i * 2.5f);
alpha[index] = (byte)255; //( (i * 4f) - ((INVISIBLE_THRESHOLD) * 4f) );
}
int blueOffset = blue[index-1] & 0xFF;
float blueFactor = (256f - blueOffset)/96f;
int alphaOffset = alpha[index-1] & 0xFF;
float alphaFactor = (256f - alphaOffset)/(96f/2);
//DARK BLUE to BRIGHT BLUE
for(int i=1; i <= 96; i++, index++)
{
red[index] = (byte) (i * 1.0f);
green[index] = (byte) (i * 2f);
blue[index] = (byte)( (((i * blueFactor) + blueOffset) > 255)? 255: ((i * blueFactor) + blueOffset) ) ;
alpha[index] = (byte) 255; // ( (((i * alphaFactor) + alphaOffset) > 255)? 255: ((i * alphaFactor) + alphaOffset) ) ;
}
int redOffset = red[index-1] & 0xFF;
float redFactor = (256f - redOffset)/96f;
int greenOffset = green[index-1] & 0xFF;
float greenFactor = (256f - greenOffset)/96f;
//BRIGHT BLUE to WHITE
for(int i=1; i <= 96; i++, index++)
{
red[index] = (byte) ( (((i * redFactor) + redOffset) > 255)? 255: ((i * redFactor) + redOffset) ) ;
green[index] = (byte) ( (((i * greenFactor) + greenOffset) > 255)? 255: ((i * greenFactor) + greenOffset) ) ;
blue[index] = (byte) ( 255 );
alpha[index] = (byte) ( 255 );
}
//MAKE INVISIBLE
for(int i=0; i < INVISIBLE_THRESHOLD; i++)
{
red[i] = (byte) 0;
green[i] = (byte) 0;
blue[i] = (byte) 0;
alpha[i] = (byte) 0;
}
/*
* Create our customized image and grab the pixel array
*/
IndexColorModel cm = new IndexColorModel(8, 256, red, green, blue, alpha);
blobby = new BufferedImage(METABALLS_SCREEN_WIDTH, METABALLS_SCREEN_HEIGHT, BufferedImage.TYPE_BYTE_INDEXED, cm);
pixel = ((DataBufferByte) (blobby.getRaster().getDataBuffer())).getData();
initTextureMap(); // initialize the texel colors for each metaball
/*
* Create and place our metaballs
*/
balls = new Metaball[NO_OF_BALLS];
int startX = METABALLS_SCREEN_WIDTH/2;
int startY = METABALLS_SCREEN_HEIGHT/2;
for(int i=0; i < NO_OF_BALLS; i++)
balls[i] = new Metaball(startX, startY);
/*
* Create our list to randomly assign metaballs to predetermined points
*/
choices = new ChoiceNumber[NO_OF_POINTS];
choiceList = new ArrayList(NO_OF_POINTS); // the list of choices for indexes of positions to assign
for(int i=0; i < NO_OF_POINTS; i++)
{
ChoiceNumber num = new ChoiceNumber();
num.number = i;
num.occurrences = NO_OF_BALLS_PER_POINT;
choices[i] = num;
choiceList.add(num);
}
/*
* Misc
*/
rand = new Random(); // random number gen
x = new int[NO_OF_POINTS]; // predetermined points to form the shapes
y = new int[NO_OF_POINTS];
indexToDisperse = 0; // pointer to the ball in the array to disperse this frame
delayToDisperse = 0; // delay before another ball gets dispersed
counter = 0;
changeToZ();
if(BUFFER_STRATEGY)
{
createBufferStrategy(2);
}
else
{
bb = getGraphicsConfiguration().createCompatibleVolatileImage(WINDOW_WIDTH, WINDOW_HEIGHT);
}
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void changeToCube()
{
x[0] = METABALLS_SCREEN_WIDTH/4;
y[0] = METABALLS_SCREEN_HEIGHT/4;
x[1] = x[0] + 50;
y[1] = y[0];
x[2] = x[0] + 50;
y[2] = y[0] + 50;
x[3] = x[0];
y[3] = y[0] + 50;
// Reset choiceLists
choiceList.clear();
for(int i=0; i < choices.length; i++)
{
choices[i].occurrences = NO_OF_BALLS_PER_POINT;
choiceList.add(choices[i]);
}
// Reset ball states
for(int i=0; i < balls.length; i++)
{
balls[i].dispersed = true;
}
// Reset dispersion index
indexToDisperse = 0;
delayToDisperse = 0;
}
cont…