Problems with picking (need help)

Hello everyone,

I have a scene and want to highlight some objects when the mouse is over them. So I took the simple “picking demo” from the xith.org page and modified it in that way, that I changed the mousePressed() method to a mouseMoved() method. But running that demo and moving the mouse over the window made the complete application hang after a short time. There is no exeption or anything else that could help me to determine where the failure comes from.

So I need some help. Please try my code and to tell me weather the application hangs too on your machine or not. I am thankful for any suggestions that could help me to solve that problem.

Thanks a lot

Marc


import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.BitSet;

import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import com.xith3d.picking.PickRenderResult;
import com.xith3d.render.CanvasPeer;
import com.xith3d.render.RenderPeer;
import com.xith3d.render.jogl.RenderPeerImpl;
import com.xith3d.scenegraph.Appearance;
import com.xith3d.scenegraph.BranchGroup;
import com.xith3d.scenegraph.Canvas3D;
import com.xith3d.scenegraph.Geometry;
import com.xith3d.scenegraph.GeometryArray;
import com.xith3d.scenegraph.Locale;
import com.xith3d.scenegraph.Node;
import com.xith3d.scenegraph.QuadArray;
import com.xith3d.scenegraph.Shape3D;
import com.xith3d.scenegraph.Switch;
import com.xith3d.scenegraph.View;
import com.xith3d.scenegraph.VirtualUniverse;

public class Picking
{
private boolean mouseClicked;
private int xPos;
private int yPos;

private int counter = 0;

private Switch sw;
private BitSet displayedPlanes = new BitSet(3);

public Integer pickParamsMutex = new Integer(0);


public static void main(String[] args)
{
    new Picking();
}

public Picking()
{
    VirtualUniverse universe = new VirtualUniverse();

    View view = new View();
    universe.addView(view);

    Locale locale = new Locale();
    universe.addLocale(locale);

    BranchGroup scene = new BranchGroup();
    locale.addBranchGraph(scene);
    scene.setPickable(true);

    displayedPlanes.set(0, 3);
    sw = new Switch(Switch.CHILD_MASK, displayedPlanes);        
    sw.setPickable(true);
    scene.addChild(sw);

    Geometry geo1 = createColouredPlane(-.5f, 0, .2f, .5f, .5f, 0, 1, 0);
    Shape3D sh1 = new Shape3D(geo1, new Appearance());
    sh1.setPickable(true);
    sh1.setName("left plane");
    sw.addChild(sh1);

    Geometry geo2 = createColouredPlane(0, 0, 0, 1, 1, 1, 0, 0);
    Shape3D sh2 = new Shape3D(geo2, new Appearance());
    sh2.setPickable(true);
    sh2.setName("middle plane");
    sw.addChild(sh2);

    Geometry geo3 = createColouredPlane(.5f, 0, .2f, .5f, .5f, 0, 0, 1);
    Shape3D sh3 = new Shape3D(geo3, new Appearance());
    sh3.setPickable(true);
    sh3.setName("right plane");
    sw.addChild(sh3);

    RenderPeer rp = new RenderPeerImpl();
    CanvasPeer cp = rp.makeCanvas(null, 640, 480, 32, false);
    Canvas3D canvas = new Canvas3D();
    canvas.set3DPeer(cp);

    cp.getComponent().addMouseMotionListener(new MouseMotionAdapter()
    {
        public void mouseMoved(MouseEvent e)
        {
            synchronized (pickParamsMutex)
            {
                xPos = e.getX();
                yPos = e.getY();
                mouseClicked = true;
                counter++;
                System.out.println(counter);
            }
        }
    });

    view.addCanvas3D(canvas);
    view.getTransform().lookAt(new Vector3f( 0, 0, 1.5f),   // location of eye
                               new Vector3f( 0, 0, 0),   // center of view
                               new Vector3f( 0, 1, 0));  // vector pointing up

    while(true)
    {
        view.renderOnce();
        synchronized (pickParamsMutex)
        {
            if(mouseClicked)
            {
                PickRenderResult[] results = view.pick(canvas, xPos, yPos, 1, 1);
                if(results != null)
                {
                    displayedPlanes.set(0, 3);
                    for(int i=0; i<results.length; i++)
                    {
                        Node node = results[i].getNodes()[0];
                        String nodeName = node.getName();

                        if(nodeName.equals("left plane"))
                            displayedPlanes.clear(0);
                        else if(nodeName.equals("middle plane"))
                            displayedPlanes.clear(1);
                        else if(nodeName.equals("right plane"))
                            displayedPlanes.clear(2);
                    }
                }
                mouseClicked = false;
            }
        }
    }
}
private Geometry createColouredPlane(float xPos,
                                     float yPos,
                                     float zPos,
                                     float xSize,
                                     float ySize,
                                     float redValue,
                                     float greenValue,
                                     float blueValue)
{
    float xHalf = xSize/2f;
    float yHalf = ySize/2f;

    Point3f[] coords = new Point3f[]
    {
        new Point3f(xPos+xHalf, yPos-yHalf, zPos),
        new Point3f(xPos+xHalf, yPos+yHalf, zPos),
        new Point3f(xPos-xHalf, yPos+yHalf, zPos),
        new Point3f(xPos-xHalf, yPos-yHalf, zPos),
    };

    Color3f[] colors = new Color3f[]
    {
        new Color3f(redValue, greenValue, blueValue),
        new Color3f(redValue, greenValue, blueValue),
        new Color3f(redValue, greenValue, blueValue),
        new Color3f(redValue, greenValue, blueValue)
    };

    QuadArray g = new QuadArray(coords.length, GeometryArray.COORDINATES
                                             | GeometryArray.COLOR_3);
    g.setCoordinates(0,coords);
    g.setColors(0,colors);

    return g;
}

}

The problem is this: It creates loads of garbage, so after some time the memory is full and the garbage collector has to be run. This will result in a very low frame rate, or it will even hang (if there is a memory leak). To solve the problem use my code (it should be around here somewhere (do a search)) you’ll probably also have to modify it to fit your needs more (I believe there’s only the version out there that creates much garbage) To reduce garbage, you can simply use global private variables, so you don’t have to recreate them every time you perform a pick. My code should work (with the appropriate modification) without creating any garbage !! :slight_smile:

Arne

Hi arne,

I really thank you. Your picking code

http://192.18.37.44/forums/index.php?topic=5549.msg75762#msg75762

really helped me solving my problems.

I added some lines so the code can now handle IndexedTriangleArrays too (that was what I needed).


if (geomArr instanceof IndexedTriangleArray) {
    //System.out.println("indexedTriangleArray");
    IndexedTriangleArray geomArr1 = (IndexedTriangleArray) geomArr;
    int[] indizes = geomArr1.getIndex();
    for (int j = 0; j < indizes.length; j += 3) {
        geomArr.getVertex(indizes[j], pos1);
        geomArr.getVertex(indizes[j + 1], pos2);
        geomArr.getVertex(indizes[j + 2], pos3);
        t.set(pos1, pos2, pos3);
        float f = t.test(transOrigin, transDirection,closestIntersect);
        if (f != -1) { // there is a collision
             f = f / transDirection.length();
             if (f < closestIntersect) {
                   closestIntersect = f;
                   r.setDistance(f);
                   nearest = r;
              }//if
         }//if
    }//for
}//if

glad I could help you :slight_smile: