well while I am spamming I might as well continue. I have spheres in space how do I catch mouse over and mouse click?
There is two methods:
-
Cast a ray from the center of the camera threw the pixel of the mouse cursor hotspot, and find which sphere it intersects. Ray - sphere intersection is easy and fast, so this might be the best solution.
-
Set up the view frustum so that it only covers the one pixel of the mouse cursor hotspot. Then render each object using an unique color. Then read back the rendered pixel. Its color will give you what object were intersected. This is a more general solution.
[quote]2. Set up the view frustum so that it only covers the one pixel of the mouse cursor hotspot. Then render each object using an unique color. Then read back the rendered pixel. Its color will give you what object were intersected. This is a more general solution.
[/quote]
And will be slow as hell because you’ve got to transfer that information back the wrong way across the AGP. You’ll end up needing proper geometry intersection testing like ray-sphere anyway so you might as well code it right in the first place.
So the GL_SELECTION in the red book is method 2?
Looking in the red book I see that there are 3 methods 
Method 2 is the one described under “Object Selection Using the Back Buffer”.
Opengl also has it’s own selection mechanism. It has it’s own chapter in the red book. You render your objects in a special selection mode. You give the object a name by calling glPushName(int name) or glLoadName(int name). At the end opengl returns the picked names. You limit the rendered area using a special pick matrix.
Seems like GL_SELECTION is the easiste.
Even though I will need ray intersection… any good toutorials for that?
well I managed to set up a ray and make it intersect witha sphere… BUT I have run into another problem.
Translating mouse coords(screen coords) into world coords so I can set the origin of the ray.
What about the direction… uuhm
/me head hurts
You can use gluUnProject with two different depth values to convert a mouse click into a couple of world coordinates, then you can construct your ray from them.
Middy,
Do you mind releasing your code as an example. I wish to do same but am just started to do simple 3d programming. Abstracts and terms used in several answers usually give me zero information 
its distributed in a great deal of classes. So it easier if U ask for specific stuff
actually speaking of code I could use an example on calling gluUnproject
especially the GL_PROJECTION_MATRIX and GL_MODELVIEW
I’ve looked at the Xith3D sourcecode implemented. It uses gl.glRenderMode(GL.GL_SELECT); mode if picking is enabled. (code can be see in CanvasPeerImpl.java.renderStart method). It’s not really “cast a ray…” method suggested previously.
[quote]Cast a ray from the center of the camera threw the pixel of the mouse cursor hotspot, and find which sphere it intersects. Ray - sphere intersection is easy and fast, so this might be the best solution.
[/quote]
If anyone had a very simple example code to do “cast a ray” picking method I appreciate a lot.
I tried implementing it… Its not that easy…
First U must translate your mousecoord to world coord to get a origin(use gluUnport). A ray is a origon coord and a vector. Then U can cast the ray and test on all objects and see if it intersects. I gave up on it since I actually managed to crash the VM.
So… I am desperatly trying to make my selection work(using GL.SELECT)… I dont think I get the concept, I only get data in buffer when I click weird places
Translation code (do not work)
DoubleBuffer glProjection = ByteBuffer.allocateDirect(8*4).order(ByteOrder.nativeOrder()).asDoubleBuffer();
DoubleBuffer glModel = ByteBuffer.allocateDirect(8*4).order(ByteOrder.nativeOrder()).asDoubleBuffer();
IntBuffer viewPort = ByteBuffer.allocateDirect(4*4).order(ByteOrder.nativeOrder()).asIntBuffer();
DoubleBuffer result = ByteBuffer.allocateDirect(8*4).order(ByteOrder.nativeOrder()).asDoubleBuffer();
GL.glGetDouble(GL.GL_PROJECTION_MATRIX, glProjection);
GL.glGetDouble(GL.GL_MODELVIEW_MATRIX, glProjection);
GL.glGetInteger(GL.GL_VIEWPORT,viewPort);
GLU.gluUnProject(0,0,0,glModel,glProjection,viewPort,result);
Intersect code for a sphere:
public boolean intersect(Ray ray) {
float dx = _center.getX() - ray.get_origin().getX();
float dy = _center.getY() - ray.get_origin().getY();
float dz = _center.getZ() - ray.get_origin().getZ();
float v = ray.get_direction().dot(dx, dy, dz);
// Do the following quick check to see if there is even a chance
// that an intersection here might be closer than a previous one
if (v -_radius > ray.getT())
return false;
// Test if the ray actually intersects the sphere
float t = this._radSqr + v*v - dx*dx - dy*dy - dz*dz;
if (t < 0)
return false;
// Test if the intersection is in the positive
// ray direction and it is the closest so far
t = v - ((float) Math.sqrt(t));
if ((t > ray.getT()) || (t < 0))
return false;
ray.setT(t);
ray._asterHit= this;
return true;
}
where do I find that example?.. I only seen NeHes
New 3D engine and is about to start using JOGL as renderer.
http://www.mind2machine.com
They had a sample for picking objects: openmind.samples.pickingDemo
I looked at it, but the actual picking code is somewhere behind the OM engine. I did not browse that codebase.
Xith3D example had more pure gl implementation without the engine support.
I see a couple of problems with your translation code:
-
glProjection and glModel represents double matrices which has 16 elements, not 4. This is why the vm crashes. LWJGL does not handle buffers with wrong size cracefully

-
You store the model view matrix in glProjection instead of glModel. I usume this is a typo

Here is my go at it:
/**
* Creates a ray that goes from the origin of the camera and threw the mouse
* cursor. The result is in the current model view space.
* @param mousex, mousey position of the mouse in screen space
* @param eyeOut where the un projected position of the origin of the camera is stored
* @param dirOut where the direction of the resulting ray is stored.
*/
private void unProject(int mousex, int mousey, Vector3f eyeOut, Vector3f dirOut) {
DoubleBuffer projection = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer();
DoubleBuffer model = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer();
IntBuffer viewPort = ByteBuffer.allocateDirect(4*4).order(ByteOrder.nativeOrder()).asIntBuffer();
DoubleBuffer result = ByteBuffer.allocateDirect(3*8).order(ByteOrder.nativeOrder()).asDoubleBuffer();
GL.glGetDouble(GL.GL_PROJECTION_MATRIX, projection);
GL.glGetDouble(GL.GL_MODELVIEW_MATRIX, model);
GL.glGetInteger(GL.GL_VIEWPORT, viewPort);
GLU.gluUnProject(mousex, mousey, 1, model, projection, viewPort, result);
Vector3f target = new Vector3f((float)result.get(), (float)result.get(), (float)result.get());
// reuse buffers
projection.rewind();
model.rewind();
viewPort.rewind();
result.rewind();
GLU.gluUnProject(mousex, mousey, 0, model, projection, viewPort, result);
Vector3f eye = new Vector3f((float)result.get(), (float)result.get(), (float)result.get());
dirOut.sub(target, eye);
dirOut.normalize();
System.out.println("eye="+eyeOut.x+" "+eyeOut.y+" "+eyeOut.z);
System.out.println("dir="+dirOut.x+" "+dirOut.y+" "+dirOut.z);
}
Vector3f is a 3d vector class from java3d.
The resulting ray is defined in the current modelview matrix. So if you call unProject right after gluLookAt, you will get the ray in world coordinates. If you call it right before you render your sphere, you get the ray in object space. In object space you can check intersection between ray, and the sphere at location (0, 0, 0).
Hope this makes sense.
…and here is a descent opengl tutorial: http://isgwww.cs.uni-magdeburg.de/graphik/lehre/cg1/dokumente/gltutorial.pdf
I had a few general questions about the ray casting technique here.
-
What exactly is the ray given by dirOut in your example code. Is this the ray which goes from the camera through the point clicked on by the mouse?
-
Does each object in your scene have its own model view matrix?
-
If each object has its own model view matrix then which one do you use when you want to get the ray of the mouse pick?
THanks for your help!
Hi shochu
-
yes, dirOut is the ray which goes from the camera through the point clicked on by the mouse.
-
I haven’t actually used the code. I only made it to help. But Each object has it’s own modelview matrix. It is the matrix that is on top of the opengl modelview stack when the object is drawn.
-
If you want to get the ray in object space, you use the modelview matrix that is used to draw the object.