Hey, so I want to get a basic understanding of how to click on things in a 3D space, in my case cubes. From what I am reading, Ray Picking is what I am looking for. I can't find a tutorial on it at all. So if anyone can point me to one, or teach me themselves, that would be wonderful.

I assume something like that would just be simple, calculating when I am hitting that cube.

I would personally use a vector from the camera to the mouse (with a 1 delta in z) with this when I click I would check what was the first object on the vector path and do the function onto that object.

well in simplistic terms basically the vector path increments (x+ y+ z+) are just the difference between the mouse and player then just adding these on each time is fairly simple. However the mouse position would have to be 1 / mousex 1/mousey and rotxyz(1);

// now decide what kind of resolution you want:// a longer test distance will allow you to pick blocks// further away, while the test iteration distance will// improve the accuracy of the picking algorithm.// Balance this how you see fit, but the iteration distance// should really be around 1/3 of your block's actual sizefloatmaxDist = 50;floatiterationDist = 0.5f;

// now work out how many iterations along the camera vector// we'll be testing withintiterations = (int)Math.floor(maxDist / iterationDist);

// now we'll loop through and get each test point in 3D space// along the test vectorfor (inti = 0; i < iterations; i++) {// how far in front of the camera will this iteration take us?floatcurrentDist = iterationDist * i;

// get the current delta point in space for this iterationfloatf = (float)Math.cos(Math.toRadians(camPitch));

// let's assume you have an array of objects in your world that you're pickingfor (Blockblock : blockList) {// create a method like 'isPointInside' on your Block object that// just tests whether or not a Vector3f coordinate is 'inside' the// block's boundsif (block.isPointInside(pointInWorld)) {// we've found our block!returnblock; } } }

// we couldn't find anything in this testreturnnull;}

This code isn't perfect, but should give you the general idea.

Note that the 'blockList' array should be a list of logical blocks that are likely to be within the viewer's camera frustum - so you'd obviously not be looping through the entire world's block list, but rather your optimised list of blocks within the viewing cone.

Picking blocks using the mouse cursor (rather than with the camera's line of sight, a-la Minecraft) can be accomplished using a technique known as unprojecting, but this is more complex and I'd recommend getting to grips with this method first.

Create two 4D vectors by using the mouse position as the XY part the projected near and far clipping plane values (-1, 1) as Z and 1 as W. Then multiply them with the inverse, get the difference for the direction and either the camera position or the near-vector as the start.

Also don't use iterations to select what you picked. Calculate the ray intersection point for every entity you are interested in and then select the one which intersection point is the most near to the origin(eye/camera).

Well I just had an idea and I want to share it before I look at any code given to me. I will have 2 vector3fs calculated with the fov angle of the camera, then I will iterate over every point in between them and see if that point happens to fall into an object.

Danny, I'm glad that you've pointed out that line iteration is not perhaps the best way to do this type of object picking - but could you elaborate more on the concept you're discussing as the right way to do this?

I think that both I and the OP (along with anybody else interested in this particular topic) would benefit from some insight into the correct methodology to achieving this. I'd like to improve my own attempts at this.

I took the time to write up some code to illustrate one possible method of tackling this problem, and while I'm not suggesting that you need to do the same, I'd be interested to see a more explained version of your concept, as I had some difficulty understanding it.

So you know where your near clipping plane is (based off of your camera's current position). You can therefore map the user's XY mouse position to its relative 3D world coordinates (the red dot).

Then, using information known about your far clipping plane (the end of your camera's view frustum) you can accurately map a point in the relative position on that far clipping plane (the blue dot).

The vector between these two points would effectively become the current picking ray (the dotted, red line) - and either using iterations OR line-intersection you could work out what this ray hits first in the scene, and pick that.

If none of this is right, I would appreciate some input so that the theory behind this is correct. I'm basing this off of my own interpretation of line picking that correctly observes the camera's FOV.

Pixelprime's picture shows quite well the idea behind mouse picking in a 3D world. One can define that the mouse cursor is lying on the near clipping plane of the view frustum and defines a ray in addition to the camera origin.

This ray/line is unlimited in each direction. So to only "pick" stuff we can actually can see (stuff in the view frustum) we restrict our further search to the line-segment of this ray which lies in the frustum. You see this line segment in the illustration in the post above.

Create two 4D vectors by using the mouse position as the XY part, the projected near and far clipping plane values (-1, 1) as Z and 1 as W. Then multiply them with the inverse view-projection matrix, get the difference for the direction and either the camera position or the near-vector as the start.

Now a more indepth explanation, but first some minor stuff about vector matrix multiplication:

A 4x4 matrix can be seen as another coordinate-system or space. You probably already heard about object-, world-, eye-space in OpenGL.

To multiply a vector with a matrix can be seen as to project that vector to the space the matrix is representing

To undo such a projection one can use the inverse of the previously used matrix

Two calculate the two points we need (blue/red dots in the picture) we will use the OpenGL projection-space(we get there with the Projection-Matrix, glOrtho ...) to our advantage. The projection space is defined, so that every point in the view-frustum is in the range [-1, 1] for all dimensions.

i.e. a point with XY == (-1, -1) will be rendered to the left bottom pixel of the canvas, (0,0) to the center ...

Perhaps now it is already clear for some how we can easily calculate the positions of the red and blue points. Both points share the same X,Y coordinates in the projection space, because both are covered by the mouse cursor. To calculate these coordinates we can simply divide the mouse position by the canvas size and do a little multiply and add:

1 2

floatrelativeX = mouseX / width;floatprojectedX = relativeX * 2 - 1;

The Z coordinate is even more simple to derive. We just take -1 for the red and 1 for the blue point, see projection-space definition.

Now as a final step, we will need the inverse of the view-projection matrix. This is because we have the coordinates for both points in the projection-space, but need them in world-coordinates for our actual picking calculations.

The view-projection matrix projects points from world to projection space, so multiplying our calculated two points by the inverse gives us our solution of this chapter.

Doing the line intersection testAs said in the introduction we want to do some picking with the line-segment defined by the red and blue points. The first thing to do is to define what we actually try to achieve. What we want to do is to find all objects which intersect with the line-segment and then select the object which intersection point is the most near to the camera origin.

How to do these two steps can vary greatly for each application. It totally depends on the organisation of the objects you want to pick, but let us take a quick look at the most common case with just a simple list of objects to test.

Say you have some game entities, like units in a RTS, you want to pick. The first thing you need to do is to define the physical boundaries of the entity somehow. You can do this by using some simple shapes like a sphere, AABB, OOBB or a capsule. Further more you can use some hierarchy of such shapes(like hitboxes for a character in a FPS. sphere for the head and boxes for the limbs) or just test against a polygon mesh. Depending on what you use, you will need some function which can calculate intersection point(s) between a line/ray and such shapes. Just use google("line AABB intersection") or ask/search in this forum.

The only difference between a line intersection test and one for a line-segment is that you have to check if the calculated intersection point lies between the two points of the segment.

As a little bonus a little thinking incentive for all the block-world lovers: Like you can calculate the pixels of a line you draw on a 2D canvas very easily, you can do the same with a 3D line in a 3D picture like a voxel-block-world is.

A very thorough and detailed explanation, thank you for taking the time to draft it out. This should answer the OP's question nicely, and will allow me to correct the method I'm using to do this to something more appropriate.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org