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".

Reply via email to