Closest Plane in Ray Pick

So, in my program, I just have a simple Ray Casting method:

float[] matModelView = new float[16], matProjView = new float[16];
        int[] view = new int[16];
        Vector3f start = new Vector3f();
        Vector3f end = new Vector3f();

        FloatBuffer modelBuffer = compileBuffer(matModelView);
        FloatBuffer projBuffer = compileBuffer(matProjView);
        FloatBuffer startBuffer = compileBuffer(new float[]{start.x, start.y, start.z, 1});
        FloatBuffer endBuffer = compileBuffer(new float[]{end.x, end.y, end.z, 1});
        IntBuffer viewBuffer = compileBuffer(view);

        glGetFloat(GL_MODELVIEW_MATRIX, modelBuffer);
        glGetFloat(GL_PROJECTION_MATRIX, projBuffer);
        glGetInteger(GL_VIEWPORT, viewBuffer);

        gluUnProject(mouseX, mouseY, 0.0f, modelBuffer, projBuffer, viewBuffer, startBuffer);
        gluUnProject(mouseX, mouseY, 1f, modelBuffer, projBuffer, viewBuffer, endBuffer);
        
        this.start = new Vector3f(startBuffer.get(0), startBuffer.get(1), startBuffer.get(2));
        this.end = new Vector3f(endBuffer.get(0), endBuffer.get(1), endBuffer.get(2));

And I handle all intersections perfectly. The only problem is getting the closest intersection, I am able to get the closest intersection when I am in an open area, but if an intersect able plane is behind me, and closer that the one in front of me, I have a simple method to determine the closest plane:

float distance = (float) Math.abs(intersection.z - ray.getStart().z);

I assume the problem is with the absolute value, but this is the simplest way I can deal with distance, since you can rotate, if I didn’t call the absolute value method, it would glitch even more.

You have to unproject only into view space not world space. If you do this you can throw away all intersection points with a positive Z value, because they are behind you.

How do I do that? I have not read anything specific on view space vs world space

EDIT: what if I am projecting into the positive Z direction?

Is anyone going to try and help? I don’t think Danny could have been more vague. I assume

GL_VIEWPORT

uses the view and not the world.

World space is the coordinates of your objects.
View space is their coordinates ‘on screen’ (in the range -1 to 1), before being projected into 2D space (actually on the screen).

Projection is when you use the matrices to multiply from one coordinate space to the next.
Unprojection is when you multiply by the inverse of the matrix to get the previous coordinate space.

What you’re currently doing is unprojecting all the way back to world space, when you only need to unproject back to view space.

I’m not that familiar with un/projection, but I think that’s the general idea.

Well, I am doing that, considering my method works, its just that if I am back against a plane, and the plane behind me is closer to me than the plane I want to click on, the smallest length to the intersection is the one behind me.

The sign of your into-screen (probably Z) coordinate of the intersection point tells you the answer…assuming your working in camera space. So if negative Z is into screen, then if the coordinate’s Z is positive, then it’s behind you.

As I mention in that other thread…this probably far from the ideal way to address your problem.

this code should work for you


Ray ray = ...;
Vec3 intersection = ...;

Vec3 rayDir = ray.end() - ray.start();
Vec3 toIntersec = intersection - ray.start();

if(rayDir dot toIntersec > 0)
{
  //is infront of the camera
}


As an aside: Danny02’s snippet and my suggestion are answering the same question: What’s the sign of the signed (scaled) distance? Use the projection operator (dot product) for arbitrary configurations.

What is ‘dot’? Like multiplication?
And also, you cant add and subtract Vector3fs like that.
Or multiply them like that… Or compare them to 0 like that. Vec3 is not a valid object in java, and ‘dot’ is not a valid function. So no, that code won’t work for me, or anyone. Sorry mate.

You know that’s pseudocode, right? Obviously you can’t copy + paste that code in. It’s a layout of what the actual code should end up doing.

Dot product is basically this:
Assume U and V are two vectors.
U.V = U.x * V.x + U.y * V.y

I know its pseudo code, I was just stressing the inaccuracy in the statement “This code should work for you”. But thanks for explaining the dot product.
EDIT: In the snippet, danny is comparing a vector to 0, does that mean I should compare all of the coords in the vector to 0, or add the coords up and compare?

EDIT AGAIN: It appears to be working. I will test further.

the dot product between to vectors is a number not a vector.

Some attributes of the dot product:

  • Zero if the vectors are orthogonal to each other.
  • Positive if facing in the same direction (angle lower than 90°),
    negative otherwise.

If both vectors are normalized:
One if the same, -1 if direct opposite direction. => the dot product is the cosines of the angle between the two vectors.

I see, I did not read thoroughly enough. My bad.

Though, that method does not take into consideration the way I am facing. If I am facing towards the back (positive Z) I cannot click on anything. However:

toI.x * rayDir.x > 0 && toI.y * rayDir.y > 0 && toI.z * rayDir.z > 0

Seems to work.

Saying the same thing: For dot product (A.B) is the parallel projection of A into B, which is the same as the parallel projection of B into A since A.B=B.A. If this case the dot product is a signed scaled distance and hints how lines and planes are related.

The dot product doesn’t care about facings or orientations.