Picking not working right in Java3D

I have picking set up, and finds things, but it doesn’t find them where I think it should find them. It’s as if the PickCanvas thinks the camera is somewhere other than where I see it. However it still responds to my changes in angle when I rotate the camera. Initially in my scene I see the objects I’m working with in the center of the view. However I can’t pick anything. If I rotate the camera a whole lot, all of a sudden I can pick one of the objects on like half of the entire screen even though it’s not very thick. This makes me think that the camera view it THINKS it has is very up close on the objects, maybe initially facing away from them.

Here’s the code that creates my scene.


GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
canvas = new Canvas3D(config);

BranchGroup branchGroup = new BranchGroup();
branchGroup.setCapability(javax.media.j3d.Group.ALLOW_CHILDREN_EXTEND);

root = new TransformGroup();
root.setCapability(javax.media.j3d.Group.ALLOW_CHILDREN_EXTEND);
root.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
root.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
branchGroup.addChild(root);

camera = new org.opensourcephysics.display3d.java3d.Camera(this);
camera.setTransformGroup(root);

universe = new SimpleUniverse(canvas);
universe.getViewingPlatform().setNominalViewingTransform();
universe.getViewer().getView().setLocalEyeLightingEnable(true);
universe.getViewer().getView().setCompatibilityModeEnable(true);
Transform3D t = new Transform3D();
t.perspective(Math.PI/4, getScreenRatio(), .1, maxObjectDistance);
universe.getViewer().getView().setLeftProjection(t);
universe.getViewer().getView().setRightProjection(t);

pickCanvas = new PickCanvas(canvas, branchGroup);
universe.addBranchGraph(branchGroup);

I use this code to pick the target when I want to:


pickCanvas.setShapeLocation(lastMotionEvent.getX(), lastMotionEvent.getY());
PickResult pr = pickCanvas.pickClosest();

where lastMotionEvent is the last MouseEvent that was processed on the screen.

Here is the code that handles the mouse rotation on the screen:


Transform3D currXform = new Transform3D();
Vector3d position = getPerspectivePosition();
		
currXform.lookAt(
		new Point3d(position.x, position.y, position.z),
		new Point3d(focusX, focusY, focusZ),
		new Vector3d(0, 0, 1)); //so that our coordinate system is in the
				//same direction as the simple3d one usually 0, 1, 0 is used

root.setTransform(currXform);

Any ideas on why my PickCanvas isn’t picking from the same perspective as the one shown on my screen? Thanks!

EDIT: Oh I just remembered I had another question. All of this perspective setup is identical to what I’ve done in JOGL. I’m basically trying to create two scenes that are identical in JOGL and Java3D. However even though I’m passing the same perspective matrix and the same camera transformation, I don’t get exactly the same perspective. Maybe this is related to how the PickCanvas sees something different also?

EDIT 2: I found that if I remove the line:
universe.getViewingPlatform().setNominalViewingTransform();
Then my perspective looks as it should, but the picking problem still remains.

I wrote my own class for picking to avoid the problems of obscurity you are encountering. I do something like this to adjust for the projection distortion:

// mouse click to imageplate coordinates
c3D.getPixelLocationInImagePlate(pickXY.x, pickXY.y, p3d);
// imageplate to world transformation
c3D.getImagePlateToVworld(t3D);
t3D.transform(p3d);
// find vector eye -> target
v3d.sub(p3d, eyeIs);
// set the pickRay
pickRay.set(eyeIs, v3d);
// do the picking
PickInfo pi = sceneBranch.pickClosest(PickInfo.PICK_GEOMETRY, PickInfo.NODE, pickRay);

I think this is as safe as it gets.

Thank you for the response! It sounds like it will help and I think I understand how that works except I’m not sure what “eyeIs” is. I figured from the comments that it’s the location of my “camera” so I tried giving it that, but I get:


Exception in thread "AWT-EventQueue-0" javax.vecmath.SingularMatrixException: cannot invert matrix
	at javax.media.j3d.Transform3D.invertAffine(Transform3D.java:2853)
	at javax.media.j3d.Transform3D.invert(Transform3D.java:2707)
	at javax.media.j3d.Shape3DRetained.intersect(Shape3DRetained.java:630)
	at javax.media.j3d.PickInfo.pick(PickInfo.java:869)
	at javax.media.j3d.BranchGroupRetained.pickAllSorted(BranchGroupRetained.java:284)
	at javax.media.j3d.BranchGroupRetained.pickClosest(BranchGroupRetained.java:317)
	at javax.media.j3d.BranchGroup.pickClosest(BranchGroup.java:442)

Am I not understanding what that variable should be?

yes, it’s the position vector of your camera / eye.

you can easily find out where your camera is by reading it’s transformgroup’s transform3D, then doing transform3D.get( eyeIs );

It seems to work for you up until the point where you do the actual picking, I dont know why it says it encountered a Singular matrix. I can only guess you provided the pickray with a ZERO vector? check the values.

OK, that’s what I was using. It starts out as 0,0,4, and then I turn it and get something like .1,.1,3.8333 but it doesn’t seem to like either.

what do you mean you turn it? you shouldn’t be transforming the eye->target vector anymore, it’s only used for the current picking. and btw, the chances you got a straight 0,0,4 ray vector from picking are very slim, are you sure you are doing what I suggested?

Oh! I was referring to the camera position vector, and turning the camera about it’s focus, so the camera position is in a new place.

v3d: 0.42465753424657504 4.784246575342467 -2.414213562373095
eyeIs: 2.4492935982947064E-16 -4.0 0.0

I start out with something like that, and I get no errors thrown, however picking doesn’t seem to be working at all because it doesn’t find anything.

If I turn my camera in any way, and start the picking method again, i get something like:
eyeIs: 0.11998050103809739 -3.998150157598382 0.019999916666770833
v3d: 0.07864963594820366 4.056369335680574 -2.4342134790398657

Then I get the exception thrown. I can’t find a place I can turn the camera that doesn’t throw the exception.

I just realized another big problem. Some of my other examples stopped working, and it was because I removed this code:


universe.getViewer().getView().setCompatibilityModeEnable(true);
Transform3D t = new Transform3D();
t.perspective(Math.PI/4, getScreenRatio(), .1, maxObjectDistance);
universe.getViewer().getView().setLeftProjection(t);
universe.getViewer().getView().setRightProjection(t);

Putting it back in makes my examples work again. I guess otherwise it doesn’t support me changing the camera position/angles otherwise. However the sad part is this means I need compatibility mode on, which means picking won’t work. What do I do now if I need this? I still need picking too but I also need to change the perspective and camera position/angle.

OK I think I’ve solved my problems. The problem I was having with changing the perspective with compatibility mode on seems to have been unrelated… as direct as it seemed to be when I was testing for this bug. However it’s simply “gone away” as a result of all the other work I’ve been doing :slight_smile: As for the initial wierdness with it not quite being on target, I changed the mode to PickTool.GEOMETRY and now it’s much better. I suppose before it was just using bounds, but it was doing a very bad job even with bounds. Like if you were to cut my sphere into 4 quadrants like the cartesian coordinate system, I could pick in quadrants 2, 3 and 4 but not 1. Very strange. However it seems to be working now.

As for the affine matrix exception being thrown… I tried just catching it and telling my program I didn’t find anything works ok. I make it change cursors if I find something, which has led me to be able to find that it often has problem picking if I put my mouse directly on an edge or vertex. I have no idea why there would be this problem, OpenGL never had a problem like this, but whatever. So I can’t pick on a few pixels, I think that’s ok for now :slight_smile: I’ll chalk it up to Java3D’s flustered state and let it slide.

and from here what do i do with the PickInfo? sorry if it’s a noob question…