LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Daslee on January 02, 2013, 18:45:08

Title: Ray Picking
Post by: Daslee on January 02, 2013, 18:45:08
Hello. Does someone have ray picking code for lwjgl, with which I can select objects in 3d scene? I was searching 2 days in google, but which I was found didn't worked. Sometimes z position always stay in -2 and sometimes z position changes only between 0.9 and 1.0. All codes which I was found in google were not working.  :-[
Title: Re: Ray Picking
Post by: quew8 on January 03, 2013, 14:10:54
Are you talking about choosing an object you click on with the mouse? If so then what you want is opengls selection feature in which you: give each object to be rendered a unique name, assign a buffer for results to be written to, create a clip such that only the area around the mouse will be drawn to, switch to selection rendering mode, draw the scene and read back the result with the smallest depth value.
If this isn't what your talking about then it's just a matter of testing each object in the scene for intersection with the ray of which there are a huge number of methods like minkowski difference or defining faces algebraically and testing them that way. You could even use the selection mode and create a modelview matrix that "looks along" the ray. You have an infinite number of options.
If you would like to post the code you have which isn't working I'm sure we could also help you get that working.
Title: Re: Ray Picking
Post by: Daslee on January 03, 2013, 15:20:44
Quote from: quew8 on January 03, 2013, 14:10:54
Are you talking about choosing an object you click on with the mouse? If so then what you want is opengls selection feature in which you: give each object to be rendered a unique name, assign a buffer for results to be written to, create a clip such that only the area around the mouse will be drawn to, switch to selection rendering mode, draw the scene and read back the result with the smallest depth value.

Yes, that is what I want to do, but can't because I'm newbie to LWJGL and I do not know many things such as buffers float buffers and etc, what they are and what they are doing... I would like to read LWJGL book, but don't have so much time. Mostly when I copy some code I'm playing around two days with it to get know which line what doing and then understanding, but when I watched java basics I didn't seen tutorials about things which is need now.

Code which I was using last time:
FloatBuffer mousePos = getOGLPos(Mouse.getX(), Mouse.getY());
selectObject(mousePos.get(0), mousePos.get(1), mousePos.get(2));


And getOGLPos method:
private FloatBuffer getOGLPos(int mouseX, int mouseY){
IntBuffer viewport = BufferUtils.createIntBuffer(16);
FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
FloatBuffer projection = BufferUtils.createFloatBuffer(16);
FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
float winX, winY;
FloatBuffer position = BufferUtils.createFloatBuffer(3);
glGetFloat(GL_MODELVIEW_MATRIX, modelview);
glGetFloat(GL_PROJECTION_MATRIX, projection);
glGetInteger(GL_VIEWPORT, viewport);
winX = (float)mouseX;
winY = (float)viewport.get(3) - (float)mouseY;
glReadPixels(mouseX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, winZ);
gluUnProject(winX, winY, winZ.get(), modelview, projection, viewport, position);
return position;
}


And selectCube method:
public void selectObject(float mouseX, float mouseY, float mouseZ){
for(Object obj : world.visibleCollidingObjects){
if(mouseX > obj.x && mouseX < obj.x + obj.width){
if(mouseY > obj.y && mouseY < obj.y + obj.height){
if(mouseZ > obj.z && mouseZ < obj.z + obj.depth){
obj.selected = true;
}else{
obj.selected = false;
}
}else{
obj.selected = false;
}
}else{
obj.selected = false;
}
}
}


But maybe here I need to cast ray from player position to FloatBuffer mousePos?

Can't upload my video example to youtube, because upload speed slow.
Title: Re: Ray Picking
Post by: quew8 on January 03, 2013, 19:56:15
First of all, buffers are very simple. Think of them as just a container of an array of values that we use to communicate with openGL. The method you have posted is not one I'm familiar with and after a quick look through I can't see any errors in the code however I cannot see how it would be very efficient and would advise you try out openGls selection mode for which I will write you some sample code. Be warned It is a long time since I have done this and there might be an error in my code.


public int getIndexOfSelectedObject(int mouseX, int mouseY) {
     int bufferSize = 128; //This number is the size of the buffer for openGl to write your results to. I chose 128 because I'm not sure how
                                 //many objects your likely to be drawing. If the maximum number of objects potentially under the mouse is n then
                                 //the size should be n * (3 + sizeOfNameStack). In this example there will be 1 name per object therefore the
                                 //name stack size is 1 and the size should be n * 4.
     IntBuffer resultBuffer = BufferUtils.createIntBuffer(bufferSize);
     glSelectBuffer(resultBuffer); //Tells openGl to write results to this buffer.
     glRenderMode(GL_SELECT);
     
     glInitNames();  //Initialize openGLs name stack into which we will put the name of each object (i will use its index in your array)
     glPushName(0);  //Adds 1 to the size of the name stack (it starts off as 0).
     
     IntBuffer currentViewport = BufferUtils.createIntBuffer(4);
     glGetInteger(GL_VIEWPORT, currentViewport); //If you are storing the values you use for glViewport then you can put them in instead

     //You must have setup the correct projection matrix before you do the next line.
     FloatBuffer currentProjectionMatrix = BufferUtils.createFloatBuffer(16);
     glGetFloat(GL_PROJECTION_MATRIX, currentProjectionMatrix);

     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPickMatrix(mouseX, mouseY, 1, 1, currentViewport);
     glMultMatrix(currentProjectionMatrix);
     
     for(int i = 0; i < world.visibleCollidingObjects.length; i++) { // I'm presuming visibleCollidingObjects is an array and not one of the         
                                                                                    // collections
          glLoadName(i) //Replaces the name on the top of the name stack with the argument.
          world.visibleCollidingObjects[i].drawForSelection(); //You should write a new method that only gives position data, no normals,
                                                                              // colours, textures etc.
     }
     
     int numberOfHitRecords = glRenderMode(GL_RENDER); //Switches back to regular mode and returns the number of hit records written.
                                                                             //If this returns a negative number you need to supply a larger selection buffer.
     //Each hit record contains: the number of names on the stack at the time (always 1 for us), the minimum z value of the object, the
     //maximum z value of the object, a list of the names on the stack (just the objects name for us).

     int minimumZValue = Integer.MAX_VALUE;
     int nameOfClosest = -1;
     for(int i = 0; i < numberOfHitRecords; i++) {
          int stackSize = resultBuffer.get(); //Unused by us. If not 1, somethings gone wrong.
          int thisMinimumZValue = resultBuffer.get();
          int maxZValue = resultBuffer.get(); //Unused by us.
          int name = resultBuffer.get();
          if(thisMinimumZValue < minimumZValue) { //This means this result is closer to the viewer that the previous and is therefore         
                                                                  // preferable.
               minimumZValue = thisMinimumZValue;
               nameOfClosest = name;
          }
          glMatrixMode(GL_PROJECTION); //These lines just return the projection matrix to what it was before. Not necessary but neater.
          glLoadMatrix(currentProjectionMatrix);
          return nameOfClosest ; //Which is the index of the selected object.
     }
}


I checked through this a few times, but as I say it's been a while since I last used this and I apologize in advance if I got something wrong.
Title: Re: Ray Picking
Post by: Daslee on January 03, 2013, 22:32:06
It works, but no so accurately. I'm not sure about this line: int bufferSize = 128;, for now I typed here my objects size in world. And got error here: IntBuffer currentViewport = BufferUtils.createIntBuffer(4);, but when I changed size to 16 then it's working.

Where could be the problem? Maybe you have skype? There we could chat better.
Title: Re: Ray Picking
Post by: quew8 on January 04, 2013, 00:20:28
My apologies for the error, I had forgotten that LWJGL requires a buffer size of at least 16 for that method. About "bufferSize," it is the size of the buffer that openGL will write it's results into (4 numbers per result), it isn't all that important as long as it is large enough. Essentially this method just records any and all objects drawn at the point specified whether they are at the front of the scene or the back. Therefore the number of results is the number of objects drawn there even if they have been "drawn over." I can't really find the words to explain, if 128 is working (as in the second glRenderMode isn't returning a negative value) I would just leave it as that, else you can make it larger.
About the inaccuracy: I forgot to comment in the code about the gluPickMatrix(). The third and fourth are respectively width and height of the area to check in. If it is not picking objects when clicking on their edge, you could enlarge these (they are measured in window coordinates).
Title: Re: Ray Picking
Post by: Daslee on January 04, 2013, 00:55:45
It picks objects, but when I rotate camera pitch then it picks wrong. And when I am looking at object center, it picks object next one from that object (only if I'm looking far). I do not know how to actually explain all that thing what is wrong with picking, maybe I'll upload video to youtube when I can and show you here, or you can try to look at my game through teamviewer.
Title: Re: Ray Picking
Post by: abcdef on January 04, 2013, 11:44:17
Its normally recommended not to use the method above, ray picking is the way most people do it. I'm in the process of implementing this in what I am doing so I will post something later today to show how I get the ray vector. Once you have that its just a matter of checking against each object you render.
Title: Re: Ray Picking
Post by: Daslee on January 04, 2013, 12:03:13
Ok I'll be waiting. And why it's not recommended to use that method above?

quew8, I just noticed that when my camera yaw is rotated between 90-180 it works perfect, but when yaw is rotated greater than 180 or lesser than 90, it gets inaccurately.
Title: Re: Ray Picking
Post by: quew8 on January 04, 2013, 14:59:36
Really sorry. I have just been doing some reading after seeing abcdef's post. It turns out selection and feedback are deprecated in opengl 3.0 and removed thereafter. It would seem that it is actually done on the CPU rather than the GPU with no hardware acceleration whatsoever.
Really sorry to have led you on this wild goose chase. And thank you abcdef for the correction.
Title: Re: Ray Picking
Post by: Daslee on January 04, 2013, 15:02:21
quew8, So your method is deprecated now?  :-\
Title: Re: Ray Picking
Post by: quew8 on January 04, 2013, 15:21:51
In opengl 3.0 it is deprecated and in all versions above 3.1, it is removed from the core profile.
Title: Re: Ray Picking
Post by: Daslee on January 04, 2013, 16:40:01
So what can be another way to pick objects? Maybe you have another code?
Title: Re: Ray Picking
Post by: abcdef on January 04, 2013, 21:30:42
I did the following, it gets you a picking ray (vector) which you then need to check against your render objects and then work out whats the closest to you

I haven't fully implemented mine yet but I wanted to show you the way I was approaching it


   public Vector3 getPickingRay(float cursorX,float cursorY)
   {    
       IntBuffer viewport = ByteBuffer.allocateDirect((Integer.SIZE/8)*16).order(ByteOrder.nativeOrder()).asIntBuffer();
       FloatBuffer modelview = ByteBuffer.allocateDirect((Float.SIZE/8)*16).order(ByteOrder.nativeOrder()).asFloatBuffer();
       FloatBuffer projection = ByteBuffer.allocateDirect((Float.SIZE/8)*16).order(ByteOrder.nativeOrder()).asFloatBuffer();
       FloatBuffer pickingRayBuffer = ByteBuffer.allocateDirect((Float.SIZE/8)*3).order(ByteOrder.nativeOrder()).asFloatBuffer();
       FloatBuffer zBuffer = ByteBuffer.allocateDirect((Float.SIZE/8)*1).order(ByteOrder.nativeOrder()).asFloatBuffer();
       glGetFloat(GL_MODELVIEW_MATRIX, modelview);
       glGetFloat(GL_PROJECTION_MATRIX, projection);
       glGetInteger(GL_VIEWPORT, viewport);
       float winX = (float) cursorX;
       // convert window coordinates to opengl coordinates (top left to bottom left for (0,0)
       float winY = (float) viewport.get(3) - (float) cursorY;
       
       // now unproject this to get the  vector in to the screen
       // take the frustrm and unproject in to the screen
       // frustrum has a near plane and a far plane
       
       // first the near vector
       gluUnProject(winX, winY,  0, modelview, projection, viewport, pickingRayBuffer);        
       Vector3 nearVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));
       
       pickingRayBuffer.rewind();
       
       // now the far vector
       gluUnProject(winX, winY,  1, modelview, projection, viewport, pickingRayBuffer);
       Vector3 farVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));
       
       //save the results in a vector, far-near
       return farVector.subtractVector(nearVector).normalise();
   }


if you are wondering why you use unproject with win z having values 0 and 1 then have a look at

http://www.opengl.org/wiki/GluProject_and_gluUnProject_code

It shows you the code for the unproject function and should help tell you why (0 maps to normalised z of -1 and 1 maps to a normalised value of 0)
Title: Re: Ray Picking
Post by: Daslee on January 04, 2013, 22:58:25
Quote from: abcdef on January 04, 2013, 21:30:42
I did the following, it gets you a picking ray (vector) which you then need to check against your render objects and then work out whats the closest to you

I haven't fully implemented mine yet but I wanted to show you the way I was approaching it


   public Vector3 getPickingRay(float cursorX,float cursorY)
   {    
       IntBuffer viewport = ByteBuffer.allocateDirect((Integer.SIZE/8)*16).order(ByteOrder.nativeOrder()).asIntBuffer();
       FloatBuffer modelview = ByteBuffer.allocateDirect((Float.SIZE/8)*16).order(ByteOrder.nativeOrder()).asFloatBuffer();
       FloatBuffer projection = ByteBuffer.allocateDirect((Float.SIZE/8)*16).order(ByteOrder.nativeOrder()).asFloatBuffer();
       FloatBuffer pickingRayBuffer = ByteBuffer.allocateDirect((Float.SIZE/8)*3).order(ByteOrder.nativeOrder()).asFloatBuffer();
       FloatBuffer zBuffer = ByteBuffer.allocateDirect((Float.SIZE/8)*1).order(ByteOrder.nativeOrder()).asFloatBuffer();
       glGetFloat(GL_MODELVIEW_MATRIX, modelview);
       glGetFloat(GL_PROJECTION_MATRIX, projection);
       glGetInteger(GL_VIEWPORT, viewport);
       float winX = (float) cursorX;
       // convert window coordinates to opengl coordinates (top left to bottom left for (0,0)
       float winY = (float) viewport.get(3) - (float) cursorY;
       
       // now unproject this to get the  vector in to the screen
       // take the frustrm and unproject in to the screen
       // frustrum has a near plane and a far plane
       
       // first the near vector
       gluUnProject(winX, winY,  0, modelview, projection, viewport, pickingRayBuffer);        
       Vector3 nearVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));
       
       pickingRayBuffer.rewind();
       
       // now the far vector
       gluUnProject(winX, winY,  1, modelview, projection, viewport, pickingRayBuffer);
       Vector3 farVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));
       
       //save the results in a vector, far-near
       return farVector.subtractVector(nearVector).normalise();
   }


if you are wondering why you use unproject with win z having values 0 and 1 then have a look at

http://www.opengl.org/wiki/GluProject_and_gluUnProject_code

It shows you the code for the unproject function and should help tell you why (0 maps to normalised z of -1 and 1 maps to a normalised value of 0)

So with your code here I need to cast ray from camera position to return farVector.subtractVector(nearVector).normalise(); ? Or? Because now what I know from your code, so I got some coordinates and do not know what to do. If I need to cast ray, so ok I'll try to do something.
Title: Re: Ray Picking
Post by: abcdef on January 05, 2013, 08:24:27
You are correct

return farVector.subtractVector(nearVector).normalise();

returns a vector (x,y,z). This is essentially describes a line with the line going through (0,0,0) and (x,y,z)

With each object you render you need to do a line intersection test with the line being the one above. Your object may have a simple boundary shape (Cube or Sphere) in which case it's just an intersection test with that.

Some example intersection logic for a sphere can be found

http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection

And for triangles

http://geomalgorithms.com/a06-_intersect-2.html

There are lots of pages on the web to help you here, just find what best suits what you are doing
Title: Re: Ray Picking
Post by: Daslee on January 05, 2013, 10:56:50
This also not working correctly. Maybe my line - box intersection code wrong, or your code giving bad positions. getPickingRay gives this coordinates:
0.004095578758544765, -0.7583613829642083, -0.6518214779088259
0.004164626369625344, -0.7487740152381042, -0.6628122886544945


They will never be more than 1, just X sometimes going to 9. And I'm using this code for intersection: http://www.3dkingdoms.com/weekly/weekly.php?a=3
And also tried this one: http://www.3dkingdoms.com/weekly/weekly.php?a=21 Both picks same objects.

Also maybe I converted intersection code wrong, but I think that problem is in getPickingRay, because coordinates will never be more than 1 or never equals to 1.
Title: Re: Ray Picking
Post by: abcdef on January 05, 2013, 14:25:29
They are never more that one because they are normalised, your "ray" is t*(vector) where t can be anything. The vector is just a point on the line and as the line passes through (0,0,0) any multiple of the vector is also on the line.
Title: Re: Ray Picking
Post by: Daslee on January 05, 2013, 15:16:29
If it will never be more than 1, so it picks objects which x, y, z is around 1. So how to do that it can pick all objects?
Title: Re: Ray Picking
Post by: abcdef on January 06, 2013, 19:22:21
Read this article

http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/

the article you linked isn't really what you need
Title: Re: Ray Picking
Post by: Daslee on January 09, 2013, 12:01:37
So okay, I readed that article and tried to translate code to Java. This is what I got:
public boolean rayIntersection(Ray r, Object obj){
float tmin = (obj.min.x - r.begin.x()) / r.dest.x();
    float tmax = (obj.max.x - r.begin.x()) / r.dest.x();
    if(tmin > tmax){
    float temp = tmin;
    tmin = tmax;
    tmax = temp;
    }
    float tymin = (obj.min.y - r.begin.y()) / r.dest.y();
    float tymax = (obj.max.y - r.begin.y()) / r.dest.y();
    if(tymin > tymax){
    float temp = tymin;
    tymin = tymax;
    tymax = temp;
    }
    if((tmin > tymax) || (tymin > tmax))
    return false;
    if(tymin > tmin)
    tmin = tymin;
    if(tymax < tmax)
        tmax = tymax;
    float tzmin = (obj.min.z - r.begin.z()) / r.dest.z();
    float tzmax = (obj.max.z - r.begin.z()) / r.dest.z();
    if(tzmin > tzmax){
    float temp = tzmin;
    tzmin = tzmax;
    tzmax = temp;
    }
    if((tmin > tzmax) || (tzmin > tmax))
    return false;
    if(tzmin > tmin)
    tmin = tzmin;
    if(tzmax < tmax)
    tmax = tzmax;
   
    if((tmin > r.tmax) || (tmax < r.tmin)) return false;
    if(r.tmin < tmin) r.tmin = tmin;
    if(r.tmax > tmax) r.tmax = tmax;
    return true;
}


And how I'm using it:
for(Object obj : world.objects) obj.selected = false;
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);
for(Object obj : world.objects){
if(rayIntersection(rayPick, obj)){
obj.selected = true;
break;
}
}


Now it picks objects, but again inaccuracy.  :-\

Also I didn't know how to actually calculate box min and max values, so this is how I'm calculating:
float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, minz = Float.MAX_VALUE;
if(x + width < minx) minx = x + width;
if(x < minx) minx = x;
if(y + height < miny) miny = y + height;
if(y < miny) miny = y;
if(z + depth < minz) minz = z + depth;
if(z < minz) minz = z;

float maxx = 0, maxy = 0, maxz = 0;
if(x > maxx) maxx = x;
if(x + width > maxx) maxx = x + width;
if(y > maxy) maxy = y;
if(y + height > maxy) maxy = y + depth;
if(z > maxz) maxz = z;
if(z + depth > maxz) maxz = z + depth;

min = new Vector3f(minx, miny, minz);
max = new Vector3f(maxx, maxy, maxz);


Maybe this is wrong?
Title: Re: Ray Picking
Post by: abcdef on January 09, 2013, 13:38:06
Don't really know whay its not working

But in

Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);

shouldn't you use 0,0,0 as the origin?

Also the article is for simple boxes that align with axes, you need to make sure that occurs
Title: Re: Ray Picking
Post by: Daslee on January 09, 2013, 13:44:08
No, if I set origin to 0, 0, 0 then it doesn't works because it's from where ray must be casted, so from camera x,y,z to mouse x,y,z. And in my game mouse is always grabbed (Mouse.setGrabbed(true);), so instead of getting mouse x,y,z I'm using to get x,y,z from crosshair (screen center).

EDIT: Again checked at rotation of yaw at > 90 and < 270, so it works almost good, there is just inaccurate per 1 cube. If many getPickingRay methods give almost same results, so maybe problem in my camera class or somewhere other?
Title: Re: Ray Picking
Post by: Daslee on January 14, 2013, 20:33:09
No more ideas how to fix this problem?  :-[
Title: Re: Ray Picking
Post by: abcdef on January 21, 2013, 11:10:25
I have verified the ray creation method by implementing it in a different way (not using any opengl calls), your problem is probably in your ray intersection method. You also need to work out if you are only checking positive distance items from camera as negative distances will be behind you
Title: Re: Ray Picking
Post by: Daslee on January 21, 2013, 11:27:57
Quote from: abcdef on January 21, 2013, 11:10:25
I have verified the ray creation method by implementing it in a different way (not using any opengl calls), your problem is probably in your ray intersection method. You also need to work out if you are only checking positive distance items from camera as negative distances will be behind you

Ray picking is a bit hard to me as for beginner. So now I'm using color picking, it's way easier.  :)
Title: Re: Ray Picking
Post by: Daslee on January 27, 2013, 20:25:44
Damn.. I think I'll get back to ray picking, because color picking has too low fps.

abcdef,
Now as you said:
QuoteYou also need to work out if you are only checking positive distance items from camera as negative distances will be behind you

I noticed that when I looking to objects which x/z position are negative, then ray picking goes wrong. But with yaw rotation picking is good, only rotating pitch it goes wrong. Maybe in making picking ray I must multiply some vectors with pitch rotation or something like that?

EDIT: I was playing with ray picking in morning and as I said it works good at 90-180 of yaw rotation, so now found way how to fix between 270-360 yaw rotation, just when it gets picking ray subtract begin vector's Y axis by 8 and works good. But now problem in yaw rotation between 0-90 and 180-270

Here is code how I'm doing now:
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);
if(control.yaw >= 270 && control.yaw <= 360) rayPick.begin.xyz[1] -= 8; //This is what about I'm talking.


Maybe this is not effective way to fix it, but I can't found any other solutions. :D
Title: Re: Ray Picking
Post by: abcdef on January 28, 2013, 09:47:37
One thing you should note, if you move your camera (+x,0,0) in the x directions, your actual position in the real world is (-x,0,0) in the x direction as moving all the objects forward is the same as moving yourself backwards. This is the same for the y and z direction too.

Also when you rotate your camera 75 degrees around the x axis your actual rotation is -75 degrees around the xaxis as rotating objects around the x direction is the same as roatating the camera in the opposite direction.

This is important when keeping a log of your current position for which the ray starts.

Something you should try and do is to draw a line from your current position in the ray direction, this ay you can test your ray is correct

Assuming its correct and you aren't getting a successful hit on your ray object collision testing, then there is some thing wrong with your collission testing.

You should check out the lighthouse3d tutorial on ray picking as it gives you sample tests for different shapes.

You having issues with it working on some angles and not others tells me your ray is not 100% correct
Title: Re: Ray Picking
Post by: Daslee on January 28, 2013, 10:54:34
Quote from: abcdef on January 28, 2013, 09:47:37
Something you should try and do is to draw a line from your current position in the ray direction, this ay you can test your ray is correct

I tried this, but it's hard to see where line starts, where line ends.. Here is image how it looks: http://img651.imageshack.us/img651/548/screenshot20130128.png (http://img651.imageshack.us/img651/548/screenshot20130128.png)

And code how I drawing:
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINES);
glColor3f(1f, 1f, 1f);
glVertex3f(rayPick.begin.x(), rayPick.begin.y(), rayPick.begin.z());
glColor3f(.3f, .3f, .3f);
glVertex3f(rayPick.dest.x(), rayPick.dest.y(), rayPick.dest.z());
glEnd();
glEnable(GL_TEXTURE_2D);
Title: Re: Ray Picking
Post by: abcdef on January 28, 2013, 11:01:27
I can't see your picture at the moment as that site is blocked at work.

Quick question though, how do you work out your destination?

The definition of a line can be thought of as

p + t * d

p = vector of start point
d = direction vector of ray
t = scalar

if you choose a value for t, say 10,000 then you can draw a line from p to p+(10000*d). That will represent your ray.
Title: Re: Ray Picking
Post by: Daslee on January 28, 2013, 13:25:24
Okay, this is what I've got:

Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Vector3 p = new Vector3(control.position.x, control.position.y, control.position.y);
Vector3 d = destination;
float t = 10000;
//As you said p+(10000*d)
//So now I will multiply 10000 with d
d.mul(t); //Multiply d vector by t, as you said: (10000*d)
//And now p + d
d.add(p);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINES);
glColor3f(1f, 1f, 1f);
glVertex3f(p.x(), p.y(), p.z());
glColor3f(0f, 0f, 0f);
glVertex3f(d.x(), d.y(), d.z());
glEnd();
glEnable(GL_TEXTURE_2D);


As you can see I colored line as gradient. White end of line moves as I move player, but black always stays almost in center of game x,y,z is around 0,0,0. Also when I move mouse, no one end of line moves. It's really hard to see if it intersects with any box, because that line looks weird, like 2d..
Title: Re: Ray Picking
Post by: OverBlob on January 29, 2013, 13:09:43
Hello, I found this link while I was looking for some ray picking stuff, but I didn't take the time to read it carefully yet, so I don't know if it will be very usefull for you.
However I hope it could help you :)

http://schabby.de/picking-opengl-ray-tracing/

Title: Re: Ray Picking
Post by: abcdef on January 29, 2013, 16:54:33
Daslee

Its hard to pin point your error, there are plenty of comments giving you lots of advice on what to do. I can't really help you any further at the moment.

Good luck in your debugging though, I suggest you break everything down to simple tests and test everything seperately.
Title: Re: Ray Picking
Post by: Daslee on January 29, 2013, 17:31:22
Quote from: OverBlob on January 29, 2013, 13:09:43
Hello, I found this link while I was looking for some ray picking stuff, but I didn't take the time to read it carefully yet, so I don't know if it will be very usefull for you.
However I hope it could help you :)

http://schabby.de/picking-opengl-ray-tracing/



Thanks for helping, but now I can't understand here:
// look direction
        view.subAndAssign(lookAt, position).normalize();

        // screenX
        screenHoritzontally.crossAndAssign(view, up).normalize();

        // screenY
        screenVertically.crossAndAssign(screenHoritzontally, view).normalize();

        final float radians = (float) (viewAngle*Math.PI / 180f);
        float halfHeight = (float) (Math.tan(radians/2)*nearClippingPlaneDistance);
        float halfScaledAspectRatio = halfHeight*getViewportAspectRatio();

        screenVertically.scale(halfHeight);
        screenHoritzontally.scale(halfScaledAspectRatio);


How does author gets lookAt vector? And what means that up vector, what position must be in it?
Title: Re: Ray Picking
Post by: quew8 on January 29, 2013, 19:03:56
QuoteHow does author gets lookAt vector? And what means that up vector, what position must be in it?
Firstly a vector is a direction, a vertex is a position.

Any viewing matrix can be defined by three vectors:
look at / forward, which is the direction you look in.
up, which is the upward direction of your view.
left, which is the sideways direction of your view.
All three must be at right angles to one another and normalized.
I find the best way to think of it is as a coordinate system, where lookAt is the z axis, up the y axis and left the x axis. 

In fact if you aren't already constructing your viewing matrix from these vectors (with a call to gluLookAt) the vectors can be directly extracted from the matrix (it must be solely the VIEWING matrix, not modelview). They are the first three elements of the first three rows (or columns depending on the handiness of your matrices) of your viewing matrix.
Title: Re: Ray Picking
Post by: Daslee on January 29, 2013, 19:55:41
So instead of lookAt I can write camera.position.z and instead of up camera.position.y? And one more question about view Vector. I actually do not know what to do with view vector, so I wrote it like this:

Vector3f view = new Vector3f(control.pitch, control.yaw, 0);

Is that's right?
Title: Re: Ray Picking
Post by: quew8 on January 30, 2013, 22:59:45
That's not right. Please read this article: http://3dgep.com/?p=1700 (http://3dgep.com/?p=1700), it will explain it far better than I could here. Also I would like to apologize, instead of the "left" vector it would be more correct to say the "right" vector. I'm not quite sure what you meant by the view vector. Do you mean the forward/lookAt vector? It is better to get this from the viewing matrix. Presumably you make the viewing matrix with glRotate(yaw, 0, 1, 0) and glRotate(pitch, 1, 0, 0)? If so then the article will explain how the viewing matrix relates to these vectors.
Title: Re: Ray Picking
Post by: Daslee on March 08, 2013, 21:42:05
Im back  ;D
So I think I found the problem. I think that problem is with ray-box intersection or maybe in for loop where checking for intersection, because when it checks for intersection and it found intersection then it continues searching for another (goes through intersected object). Here is short video about it: http://www.youtube.com/watch?v=8gsWnA6uRE4

And image with short explanation: http://img707.imageshack.us/img707/3368/60398683.png

Now as you can see in image for example yellow line (where I'm looking at) intersects with first cube, but also if it continue searching for intersection it will intersects with second cube and second cube will be set as selected. And black line, it intersects with first, second, third and fourth cube, but fourth cube is last intersected, so this one will be selected. But I can't understand why this problem doesn't appears when yaw rotation is between 90 and 180.

So there is the problem, I think, but as in code:
for(Object obj : world.visibleCollidingObjects) obj.selected = false;
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);

//if(control.yaw >= 270 && control.yaw <= 360) rayPick.begin.xyz[1] -= 8;
//if(control.yaw >= 0 && control.yaw <= 90) rayPick.begin.xyz[1] -= 8;
for(Object obj : world.visibleCollidingObjects){
if(rayIntersection(rayPick, obj)){
obj.selected = true;
selectedObjectIndex = world.objects.indexOf(obj);
break;
}
}


It will set all objects selected = false, and then searches for intersection with ray, and as you can see if it found intersection it stops for loop with break;, but as I explained it'll searches for intersection with ray-cube till ray end. And what would be solution for this problem?  ;D
Title: Re: Ray Picking
Post by: quew8 on March 09, 2013, 11:24:45
You need to check the screen z-coordinate of each cube that intersects and if it less than all the previous intersections then record it and the index of the cube it corresponds to. At the end of the loop, whichever index remains is the closest cube being selected:


for(Object obj : world.visibleCollidingObjects) obj.selected = false;
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);

int index = -1;
                                float minDepth = Float.MAX_VALUE;
for(int i = 0; i < world.visibleCollidingObjects.length; i++) {
                                        //Change this method to return the depth (z value) of the intersection or Float.MAX_VALUE if there is no
                                        //intersection.
                                        float depth = getDepthOfRayIntersection(rayPick, world.visibleCollidingObjects[i])
                                        if(depth < minDepth ) {
                                                minDepth = depth;
                                                index = i;
                                        }
}
                                world.visibleCollidingObjects[index].selected = true;
                                selectedObjectIndex = index;
Title: Re: Ray Picking
Post by: Daslee on March 09, 2013, 14:00:55
So now I got this code:
int index = -1;
float tmin = Float.MAX_VALUE;
t=tmin;
float minDepth = Float.MAX_VALUE;
for(int i=0; i<world.visibleCollidingObjects.size(); i++){
float depth = 0;
if(rayIntersection(rayPick, world.visibleCollidingObjects.get(i))){
t = (world.visibleCollidingObjects.get(i).min.z() - rayPick.begin.z()) / rayPick.dest.z();
if(t < tmin){
tmin = t;
}
depth = rayPick.begin.add(rayPick.dest.mul(tmin)).z();
}else{
depth = Float.MAX_VALUE;
}
if(depth < minDepth){
minDepth = depth;
index = i;
break;
}
}
if(index != -1) world.visibleCollidingObjects.get(index).selected = true;
selectedObjectIndex = index;


Where you commented:
Quote//Change this method to return the depth (z value) of the intersection or Float.MAX_VALUE if there is no
                                        //intersection.

Here I wrote code to get ray intersection point and then get z coordinate, so now if there is intersection with ray and cube, then depth is set as ray intersection point, Z coordinate:
depth = rayPick.begin.add(rayPick.dest.mul(tmin)).z();

But anyway, it's same as before. I even tried to use rayPick.tmin as intersection point which is set in rayIntersection method, but everything's same as before...

EDIT: I done simple test with new lwjgl project, added one line of cubes and tried picking by mouse position. So picking worked good with objects which x position was > 0 and picking worked bad (checked for intersection through objects) with objects which x position was < 0. So maybe this could be another problem, that picking works bad, when looking to objects which positions going to negative numbers?
Title: Re: Ray Picking
Post by: quew8 on March 09, 2013, 18:46:57
Quotet = (world.visibleCollidingObjects.get(i).min.z() - rayPick.begin.z()) / rayPick.dest.z();

In the Ray class, is dest the position vector of the end of the ray or is it the direction the ray goes in from the start point?
ie, with a ray AB, is dest B or AB?

If it is the destination as the name would suggest, you shouldn't be dividing by it. You should be dividing by the direction (dest - begin)

Another thing, surely you need to test every single cube now to make sure there isn't one closer, so you shouldn't have the break statement.

Also your code is rather messy; you seem to do more conditional clauses than you need to.
With the correction and a little optimization:


int index = -1;
float tmin = Float.MAX_VALUE;
t = tmin; //You don't actually need to work out the depth as it is proportional to t. If t is smaller then the depth would be too
for(int i = 0; i < world.visibleCollidingObjects.size(); i++) {
if(rayIntersection(rayPick, world.visibleCollidingObjects.get(i))) {
t = (world.visibleCollidingObjects.get(i).min.z() - rayPick.begin.z()) / (rayPick.dest.z() - rayPick.begin.z());
if(t < tmin) {
tmin = t;
                                        index = i; //No break statement
}
}
}
if(index != -1) world.visibleCollidingObjects.get(index).selected = true; //Sorry I didn't include this if in my original. Slipped my
                                                                                                               //mind
selectedObjectIndex = index;
Title: Re: Ray Picking
Post by: Daslee on March 09, 2013, 21:17:47
Yes, in Ray class dest is defined as direction. But whatever I try to do, nothing changes. Maybe problem in ray-box intersection method?

EDIT: No, ray-box intersection is good. I tried with another codes from google, so I got same results.
Title: Re: Ray Picking
Post by: quew8 on March 10, 2013, 11:27:13
You have got rid of the break statement though? Have you tried testing with just 2 or 3 objects and printing out the intermediate results such as t, tmin and the result of the conditionals. The only other thing I can think of is your rayIntersection() method is slightly wrong. Maybe we could see that.
Title: Re: Ray Picking
Post by: Daslee on March 10, 2013, 11:56:23
Yes, I removed break; in for loop, but still nothing. Tried to print results, so they looks good. And here is two rayIntersection methods, which give same results:

public boolean rayIntersect(Ray r, Object obj){
float tx1 = (obj.min.x() - r.begin.x()) * r.n_inv.x();
float tx2 = (obj.max.x() - r.begin.x()) * r.n_inv.x();

float tmin = Math.min(tx1, tx2);
float tmax = Math.max(tx1, tx2);

float ty1 = (obj.min.y() - r.begin.y())*r.n_inv.y();
float ty2 = (obj.max.y() - r.begin.y())*r.n_inv.y();

tmin = Math.max(tmin, Math.min(ty1, ty2));
tmax = Math.min(tmax, Math.max(ty1, ty2));

float tz1 = (obj.min.z() - r.begin.z()) * r.n_inv.z();
float tz2 = (obj.max.z() - r.begin.z()) * r.n_inv.z();
tmin = Math.max(tmin, Math.min(tz1, tz2));
tmax = Math.min(tmax, Math.max(tz1, tz2));

return tmax >= tmin;
}

public boolean rayIntersection(Ray r, Object obj){
float tmin = (obj.min.x() - r.begin.x()) / r.dest.x();
float tmax = (obj.max.x() - r.begin.x()) / r.dest.x();
if(tmin > tmax){
float temp = tmin;
tmin = tmax;
tmax = temp;
}
float tymin = (obj.min.y() - r.begin.y()) / r.dest.y();
float tymax = (obj.max.y() - r.begin.y()) / r.dest.y();
if(tymin > tymax){
float temp = tymin;
tymin = tymax;
tymax = temp;
}
if((tmin > tymax) || (tymin > tmax))
return false;
if(tymin > tmin)
tmin = tymin;
if(tymax < tmax)
tmax = tymax;
float tzmin = (obj.min.z() - r.begin.z()) / r.dest.z();
float tzmax = (obj.max.z() - r.begin.z()) / r.dest.z();
if(tzmin > tzmax){
float temp = tzmin;
tzmin = tzmax;
tzmax = temp;
}
if((tmin > tzmax) || (tzmin > tmax))
return false;
if(tzmin > tmin)
tmin = tzmin;
if(tzmax < tmax)
tmax = tzmax;

if((tmin > r.tmax) || (tmax < r.tmin)) return false;
if(r.tmin < tmin) r.tmin = tmin;
if(r.tmax > tmax) r.tmax = tmax;
return true;
}


Ray class:
package utility;

public class Ray {
public Vector3 begin; //origin
public Vector3 dest; //direction
public Vector3 n_inv;

public float tmin, tmax;

public Ray(Vector3 p, Vector3 dest){
this.begin = p;
this.dest = dest;

Vector3 temp = dest;
temp.inverse();
this.n_inv = temp;

tmin = 0;
tmax = Float.MAX_VALUE;
}
}


UPDATE: I found one more bad thing with ray casting. There is a little space between ray and mouse position, here is image example (sorry for bad cursor, lwjgl taking screenshot couldn't save cursor, so I downloaded random from google): http://img189.imageshack.us/img189/5562/screenshot20130312.png

So... As you can see I casted ray from sphere center, to mouse position, but there is little space between mouse and ray. And I think that this is the problem why it picks objects inaccurate, not like I want. For example with mouse I'm on second cube, but by this image, ray would be on first cube, soo... Just need to find solution how to fix it. I could add some float values to ray direction x and y position, but I think that would not be efficient way to fix this problem.
Title: Re: Ray Picking
Post by: quew8 on March 14, 2013, 18:50:11
I'm not sure what you mean by
Quoteadd some float values to ray direction
. But this is most likely a problem with the way you create the ray. Could I see that code?
Title: Re: Ray Picking
Post by: Daslee on March 14, 2013, 18:55:31
Quote from: quew8 on March 14, 2013, 18:50:11
I'm not sure what you mean by
Quoteadd some float values to ray direction
. But this is most likely a problem with the way you create the ray. Could I see that code?

I add 0.75f to ray direction x and y values and then ray is almost correct, but only then when camera is not moving. And here is my code to get picking ray:

public Vector3 getPickingRay(float cursorX, float cursorY){
IntBuffer viewport = ByteBuffer.allocateDirect((Integer.SIZE/8)*16).order(ByteOrder.nativeOrder()).asIntBuffer();
FloatBuffer modelview = ByteBuffer.allocateDirect((Float.SIZE/8)*16).order(ByteOrder.nativeOrder()).asFloatBuffer();
FloatBuffer projection = ByteBuffer.allocateDirect((Float.SIZE/8)*16).order(ByteOrder.nativeOrder()).asFloatBuffer();
FloatBuffer pickingRayBuffer = ByteBuffer.allocateDirect((Float.SIZE/8)*3).order(ByteOrder.nativeOrder()).asFloatBuffer();
FloatBuffer zBuffer = ByteBuffer.allocateDirect((Float.SIZE/8)*1).order(ByteOrder.nativeOrder()).asFloatBuffer();
glGetFloat(GL_MODELVIEW_MATRIX, modelview);
glGetFloat(GL_PROJECTION_MATRIX, projection);
glGetInteger(GL_VIEWPORT, viewport);
float winX = (float) cursorX;
// convert window coordinates to opengl coordinates (top left to bottom left for (0,0)
float winY = (float) viewport.get(3) - (float) cursorY;

// now unproject this to get the  vector in to the screen
// take the frustrm and unproject in to the screen
// frustrum has a near plane and a far plane

// first the near vector
gluUnProject(winX, winY,  0, modelview, projection, viewport, pickingRayBuffer);
Vector3 nearVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));

pickingRayBuffer.rewind();

// now the far vector
gluUnProject(winX, winY,  1, modelview, projection, viewport, pickingRayBuffer);
Vector3 farVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));

//save the results in a vector, far-near
return farVector.sub(nearVector).normalize();
}


abcdef gave me this code. And here how I use it:
for(Object obj : world.visibleCollidingObjects) obj.selected = false;
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);

int index = -1;
float tmin = Float.MAX_VALUE;
t=tmin;
float minDepth = Float.MAX_VALUE;
for(int i=0; i<world.visibleCollidingObjects.size(); i++){
float depth = 0;
if(rayIntersection(rayPick, world.visibleCollidingObjects.get(i))){
depth = world.visibleCollidingObjects.get(i).z;
}else{
depth = Float.MAX_VALUE;
}
if(depth < minDepth){
minDepth = depth;
index = i;
}
}
if(index != -1) world.visibleCollidingObjects.get(index).selected = true;
selectedObjectIndex = index;
Title: Re: Ray Picking
Post by: quew8 on March 15, 2013, 16:40:21
The only things I can think of right now are:
1) You are applying transforms to your drawn objects in rendering but not in picking.
2) You don't have the correct projection / modelview / viewport matrices setup when calling getPickingRay. Essentially are you calling it after calling glInitMatrix but before all the glFrustum, glTranslate and glRotate.

These seem unlikely and I'm probably missing something. I'll do something else for a few hours then take another look, maybe I'll see something. On a side note, in your second code extract, you call getPickingRay inside the loop, despite it being the same each time. I don't know for sure but I don't see it as being a very computationally "fast" function.
Title: Re: Ray Picking
Post by: Daslee on March 24, 2013, 18:42:17
Look what I found. On this line:
Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);

As ray begin I'm using camera position and picking works good at yaw > 90 and yaw < 180. But if I set ray begin Y position to player Y position, not camera:

Ray rayPick = new Ray(new Vector3(control.position.x, this.y-1f, control.position.z), destination);

Then picking works good at yaw > 270 and yaw < 360. So maybe something's bad with ray begin position?
Title: Re: Ray Picking
Post by: quew8 on March 24, 2013, 23:20:11
This is an FPS game. What is the difference between player position and camera position?
Title: Re: Ray Picking
Post by: Daslee on March 25, 2013, 08:06:29
In my game there is difference, because I would only use camera position, but I have player position for collision detection. Player has its own cube, but it's not rendering. http://img831.imageshack.us/img831/4193/53435298.png

But actually that couldn't be the problem, because in other game where I'm testing ray picking, I'm sure that camera position always stays in 0, 0, 0 and when creating picking ray I'm also using 0, 0, 0 as begin position. Now thinking about that, what you said:
Quote1) You are applying transforms to your drawn objects in rendering but not in picking.

So I'm applying transforms in rendering, but not elsewhere. If that could be the problem, so where I should apply transforms elsewhere?
Title: Re: Ray Picking
Post by: quew8 on March 25, 2013, 09:36:57
You need to apply the transforms to your cubes before you test them for picking. Are these transforms the viewing transforms (as in translating to camera position then rotating by camera's pitch and yaw)? If they are then it would probably be better to transform the camera position by the opposite of these. But that's up to you. Probably best to get it working before worrying too much about performance. 
Title: Re: Ray Picking
Post by: Daslee on March 25, 2013, 09:59:57
For first person camera control I'm using this code: http://www.lloydgoodall.com/tutorials/first-person-camera-control-with-lwjgl/ So you can look at it's source code how it works. And in my game I never using glRotatef except for camera. Cubes are only translated to their x,y,z position (when rendering) and then calling display list for cube.
Title: Re: Ray Picking
Post by: quew8 on March 25, 2013, 11:42:48
Couldn't look at the code, your link is broken. Googling lloyd goodall didn't give anything programmesque either. So going only from your description:
To start with you're going to need to need a different picking ray for each cube you test.
rayStart = cameraPosition + cubePosition .
rayEnd = farVector + cubePosition.

farVector by the way is the variable from your getPickingRay method you posted earlier:
Quote
gluUnProject(winX, winY,  1, modelview, projection, viewport, pickingRayBuffer);
Vector3 farVector = new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));

You must make sure however that when you call getPickingRay(), the only transformations you have given OpenGl are the viewing transformations and projection transformations.
Title: Re: Ray Picking
Post by: Daslee on March 25, 2013, 13:00:39
So in getPickingRay method I changed return to this:
gluUnProject(winX, winY,  1, modelview, projection, viewport, pickingRayBuffer)
return new Vector3(pickingRayBuffer.get(0),pickingRayBuffer.get(1),pickingRayBuffer.get(2));


And now checking for picking:
Vector3 farVec = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);
Ray rayPick = null;
Vector3 cubePos = null;

int index = -1;
float minDepth = Float.MAX_VALUE;
for(int i = 0; i < world.objects.size(); i++) {
cubePos = new Vector3(world.objects.get(i).x, world.objects.get(i).y, world.objects.get(i).z);
rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z).add(cubePos), farVec.add(cubePos));
float depth = 0;
if(rayIntersection(rayPick, world.objects.get(i))){
depth = world.objects.get(i).z;
}else{
depth = Float.MAX_VALUE;
}
if(depth < minDepth){
minDepth = depth;
index = i;
}
}
if(index != -1) world.objects.get(index).selected = true;
selectedObjectIndex = index;


But rayIntersection method wants ray direction vector to be as normalized or..? Because now rayPick direction values sometimes can be ~1000, and it doesn't works.
Title: Re: Ray Picking
Post by: quew8 on March 25, 2013, 19:38:00
It shouldn't matter that the ray isn't normalized, in fact I don't think it was before. Is it not working at all now?
And could you post the code that calls this method. Essentially anywhere where you do any matrix stuff.
Title: Re: Ray Picking
Post by: Daslee on March 26, 2013, 07:35:48
Look at my old getPickingRay method. return was:
farVector.sub(nearVector).normalize();
And it worked, but now it doesn't, just if I would stay in center of world and then just sensitive, when I move mouse just per 1 pixels, so it picks through 20 cubes far.

And I'm doing matrix only before ray picking check when rendering world objects.
world.render(); //Here
for(int i=0; i<world.objects.size(); i++) world.objects.get(i).selected = false;


if(world.rayPicking){
Vector3 destination = getPickingRay(Display.getWidth() / 2, Display.getHeight() / 2);

Ray rayPick = new Ray(new Vector3(control.position.x, control.position.y, control.position.z), destination);
int index = -1;
float minDepth = Float.MAX_VALUE;
for(int i = 0; i < world.objects.size(); i++) {
float depth = 0;
if(rayIntersection(rayPick, world.objects.get(i))){
depth = world.objects.get(i).z;
}else{
depth = Float.MAX_VALUE;
}
if(depth < minDepth){
minDepth = depth;
index = i;
}
}
if(index != -1) world.objects.get(index).selected = true;
selectedObjectIndex = index;
}


And after this code is doing matrix with player camera "lookThrough" method.
public void lookThrough(){
glRotatef(pitch, 1.0f, 0.0f, 0.0f);
        glRotatef(yaw, 0.0f, 1.0f, 0.0f);
        glTranslatef(-position.x, -position.y, -position.z);
}