Hi All
I intend to draw a bunch grass in java3d. I divided the x-z plane to
several blocks and in each block I choose some points randomly as the
start point of the grasses and draw a projectile path with random
initial velocity and angle. My problem is when I increase the number
of grass in each block (for example to 15 grass per block), the
program exits by java.lang.OutOfMemoryError. Does anybody have any
idea to improve the performance? Actually, I even don't know why this
error occurs! Does it really need much memory?!
BTW, I create a BranchGroup for each grass and add it to the main BranchGroup.
Yours,
Siamak
This is the code:
//////////////////////////////////////////////////////////////////////
package j3dtest.ui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Random;
import javax.vecmath.Point3d;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import javax.vecmath.Color3f;
import java.awt.Color;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.swing.JToolBar;
import javax.swing.JLabel;
import javax.swing.JColorChooser;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.media.j3d.LineStripArray;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.Shape3D;
import javax.media.j3d.BoundingSphere;
import javax.swing.BorderFactory;
public class MainFrame extends JFrame implements ActionListener, MouseListener {
private BorderLayout borderLayout1 = new BorderLayout();
private BranchGroup scene = null;
private Canvas3D canvas3d = null;
private final int n = 10;
private SimpleUniverse universe = null;
private Transform3D transform3d = new Transform3D();
private Random rand = new Random();
private double pX = 0;
private double pY = 0;
private double pZ = 0;
double oX = 0;
double oZ = 0;
double step = 0;
double grassHeight = 0;
double px = 0;
double py = 0;
private final double limit = 0.05;
private JToolBar toolbar = new JToolBar();
private JLabel lblGrassNum = new JLabel("Grass Count: ");
private JLabel lblGrassHeight = new JLabel("Grass Height: ");
private JLabel lblFColor = new JLabel("Far Color: ");
private JLabel lblCColor = new JLabel("Close Color: ");
private JSpinner spnGrassNum = new JSpinner();
private JSpinner spnGrassHeight = new JSpinner();
private JColorChooser ccColor = new JColorChooser();
private JPanel pnlFColor = new JPanel();
private JPanel pnlCColor = new JPanel();
private JButton btnApply = new JButton("Apply");
private JButton btnReset = new JButton("Reset");
private JButton btnExit = new JButton("Exit");
public MainFrame(String title) {
super(title);
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if ("exit".equals(cmd)) {
System.exit(0);
} else if ("apply".equals(cmd)) {
redrawGrass();
} else if ("reset".equals(cmd)) {
spnGrassHeight.setValue(new Float(0.05));
spnGrassNum.setValue(new Integer(8));
pnlFColor.setBackground(new Color(60, 106, 38));
pnlCColor.setBackground(new Color(69, 171, 19));
redrawGrass();
}
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.getSource() instanceof JPanel) {
JPanel panel = (JPanel) e.getSource();
String title = (panel == pnlFColor ? "Select Far Color" :
"Select Close Color");
Color dc = (panel == pnlFColor ? pnlFColor.getBackground() :
pnlCColor.getBackground());
Color c = ccColor.showDialog(this, title, dc);
if (c != null) {
if (panel == pnlFColor) {
pnlFColor.setBackground(c);
} else {
pnlCColor.setBackground(c);
}
/** @todo Update Canvas3D */
}
}
}
}
public void mouseReleased(MouseEvent e) {
}
private void drawGrass() {
btnApply.setEnabled(false);
btnReset.setEnabled(false);
transform3d.rotX(Math.PI / 10);
Point3d p = new Point3d(0, 0, 0);
double baseX = -0.7;
double baseZ = -0.7;
int iLimit = (int) ((Math.abs(baseZ) * 2) / limit);
int jLimit = (int) ((Math.abs(baseX) * 2) / limit);
Color fc = pnlFColor.getBackground();
float rStart = fc.getRed() / 256.0f;
float gStart = fc.getGreen() / 256.0f;
float bStart = fc.getBlue() / 256.0f;
Color cc = pnlCColor.getBackground();
float rEnd = cc.getRed() / 256.0f;
float gEnd = cc.getGreen() / 256.0f;
float bEnd = cc.getBlue() / 256.0f;
Color3f c = new Color3f(rStart, gStart, bStart);
float rStep = (rEnd - rStart) / iLimit;
float gStep = (gEnd - gStart) / iLimit;
float bStep = (bEnd - bStart) / iLimit;
double grassNumber =
Double.parseDouble(spnGrassNum.getValue().toString());
double bX = 0;
double bZ = 0;
double r = 0;
double angle = 0;
double v0 = 0;
Point3d base = new Point3d(0, 0, 0);
for (int i = 0; i < iLimit; i++) {
c.set(rStart + i * rStep, gStart + i * gStep, bStart + i * bStep);
for (int j = 0; j < jLimit; j++) {
bX = baseX + (j + 1.0 / 2) * limit;
bZ = baseZ + (i + 1.0 / 2) * limit;
base.x = bX;
base.y = 0;
base.z = bZ;
for (int k = 0; k < grassNumber; k++) {
r = rand.nextDouble();
angle = Math.PI / (r + 2.1);
v0 = 2.1 - r;
addGrass(rand.nextBoolean(),
base,
limit,
angle,
v0,
c,
(rand.nextDouble() * 2 - 1) * 1);
}
}
}
btnApply.setEnabled(true);
btnReset.setEnabled(true);
}
private void redrawGrass() {
scene.detach();
setupScene();
universe.addBranchGraph(scene);
drawGrass();
}
private void addGrass(boolean dir,
Point3d origin,
double limit,
double angle,
double v0,
Color3f color,
double zFactor) {
LineStripArray lsa = new LineStripArray(n,
GeometryArray.COORDINATES |
GeometryArray.COLOR_3,
new int[] {n});
oX = origin.x + (rand.nextDouble() - 0.5) * limit;
oZ = origin.z + (rand.nextDouble() - 0.5) * limit;
step = limit / (2 * n);
pX = 0;
pY = 0;
pZ = 0;
grassHeight = Double.parseDouble(spnGrassHeight.getValue().toString());
px = 0;
py = 0;
for (int i = 0; i < n; i++) {
lsa.setCoordinate(i, new Point3d(dir ? oX + pX : oX - pX,
pY,
oZ + pZ));
lsa.setColor(i, color);
px = pX + step;
py = getProjectileY(angle, v0, pX);
if ((grassHeight > 0) && (py <= grassHeight)) {
pY = py;
pX = px;
pZ = pX * zFactor;
} else if ((grassHeight <= 0) && (py <= limit)) {
pY = py;
pX = px;
pZ = pX * zFactor;
}
}
BranchGroup bg = new BranchGroup();
TransformGroup tg1 = new TransformGroup(transform3d);
tg1.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
tg1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Shape3D sh3d = new Shape3D(lsa);
tg1.addChild(sh3d);
bg.addChild(tg1);
MouseZoom zoom = new MouseZoom(tg1);
zoom.setSchedulingBounds(new BoundingSphere());
bg.addChild(zoom);
bg.compile();
scene.addChild(bg);
}
private double getProjectileY(double angle, double v0, double x) {
return x * Math.tan(angle) -
(9.8 * x * x) / (2 * Math.pow(v0 * Math.cos(angle), 2));
}
private void jbInit() throws Exception {
getContentPane().setLayout(borderLayout1);
canvas3d = new Canvas3D(null);
canvas3d.setDoubleBufferEnable(true);
getContentPane().add(canvas3d, BorderLayout.CENTER);
// Init Components
Dimension sep = new Dimension(15, 22);
Dimension txtDim = new Dimension(45, 22);
Dimension btnDim = new Dimension(80, 22);
getContentPane().add(toolbar, BorderLayout.NORTH);
spnGrassNum.setPreferredSize(txtDim);
spnGrassNum.setMaximumSize(txtDim);
spnGrassNum.setModel(new SpinnerNumberModel(8, 1, 50, 1));
toolbar.add(lblGrassNum);
toolbar.add(spnGrassNum);
toolbar.addSeparator();
spnGrassHeight.setPreferredSize(txtDim);
spnGrassHeight.setMaximumSize(txtDim);
spnGrassHeight.setModel(new SpinnerNumberModel(0.05, 0.01, 1.00, 0.01));
toolbar.add(lblGrassHeight);
toolbar.add(spnGrassHeight);
toolbar.addSeparator();
Dimension pnlDim = new Dimension(15, 15);
pnlFColor.setMinimumSize(pnlDim);
pnlFColor.setMaximumSize(pnlDim);
pnlFColor.setPreferredSize(pnlDim);
pnlFColor.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
pnlFColor.addMouseListener(this);
pnlFColor.setBackground(new Color(60, 106, 38));
toolbar.add(lblFColor);
toolbar.add(pnlFColor);
toolbar.addSeparator();
pnlCColor.setMinimumSize(pnlDim);
pnlCColor.setMaximumSize(pnlDim);
pnlCColor.setPreferredSize(pnlDim);
pnlCColor.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
pnlCColor.addMouseListener(this);
pnlCColor.setBackground(new Color(69, 171, 19));
toolbar.add(lblCColor);
toolbar.add(pnlCColor);
btnApply.setPreferredSize(btnDim);
btnApply.setMaximumSize(btnDim);
btnReset.setPreferredSize(btnDim);
btnReset.setMaximumSize(btnDim);
btnExit.setPreferredSize(btnDim);
btnExit.setMaximumSize(btnDim);
toolbar.addSeparator();
btnApply.setActionCommand("apply");
btnApply.addActionListener(this);
btnReset.setActionCommand("reset");
btnReset.addActionListener(this);
btnExit.setActionCommand("exit");
btnExit.addActionListener(this);
toolbar.add(btnApply);
toolbar.add(btnReset);
toolbar.add(btnExit);
setupScene();
universe = new SimpleUniverse(canvas3d);
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(scene);
drawGrass();
}
private void setupScene() {
scene = new BranchGroup();
scene.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
scene.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
scene.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
scene.setCapability(BranchGroup.ALLOW_DETACH);
scene.setCapability(BranchGroup.ALLOW_LOCAL_TO_VWORLD_READ);
scene.compile();
}
public static void main(String[] args) {
// try {
// UIManager.setLookAndFeel(UIManager.
// getSystemLookAndFeelClassName());
// } catch (UnsupportedLookAndFeelException ex) {
// } catch (IllegalAccessException ex) {
// } catch (InstantiationException ex) {
// } catch (ClassNotFoundException ex) {
// }
MainFrame frame = new MainFrame("Grass");
frame.setSize(new Dimension(700, 600));
frame.setResizable(false);
frame.setLocation(100, 100);
frame.show();
}
}
////////////////////////////////////////////////////////////////
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA3D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".