Jump to content
  • Advertisement
Sign in to follow this  
masterbubu

Ray Picking - need help

This topic is 2341 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm trying to implement ray picking algorithm, but it looks like it doesn't work as it should.
If I get it right, the ray should starts from the near view, go straight to the mouse cursor, and then ends at the far view.


const Matrix4& inverseVP = (pCamera->mProjection * pCamera->mView()).inverse();
float NewX = (2.0f * MouseX/ pCamera->fWidth) - 1.0f;
float NewY = 1.0f - (2.0f * MouseY/pCamera->fHeight);
vec3 nearPoint(NewX, NewY, -1.f );
vec3 midPoint (NewX, NewY, 0.0f);
vec3 rayOrigin, rayTarget;

m_WorldPosition = inverseVP * (nearPoint);
rayTarget = inverseVP * (midPoint);
m_Direction = rayTarget - rayOrigin;
m_Direction.normal();
m_WorldPosition = rayOrigin;


Draw the ray: ( with GL_LINES )

vec3 p0 = m_WorldPosition;
vec3 p1 = m_WorldPosition + pCamera->fZFar*m_Direction;


I have tried other algorithms which uses tan(FOV/PI/360) but got the same results.

Any help would be great.

tnx

Share this post


Link to post
Share on other sites
Advertisement
If I get it right, the ray should starts from the near view, go straight to the mouse cursor, and then ends at the far view.
You should see nothing except possibly a 1 pixel dot under some circumstances.


const Matrix4& inverseVP = (pCamera->mProjection * pCamera->mView()).inverse();
float NewX = (2.0f * MouseX/ pCamera->fWidth) - 1.0f;
float NewY = 1.0f - (2.0f * MouseY/pCamera->fHeight);
vec3 nearPoint(NewX, NewY, -1.f );
vec3 midPoint (NewX, NewY, 0.0f);
vec3 rayOrigin, rayTarget;

m_WorldPosition = inverseVP * (nearPoint);
rayTarget = inverseVP * (midPoint);
m_Direction = rayTarget - rayOrigin;
m_Direction.normal();
m_WorldPosition = rayOrigin;
It looks like you're converting the mouse positions to normalized device coordinates, then transforming by the inverse view projection matrix. Did you take into account the perspective divide between clip coordinates and normalized device coordinates?

I usually prefer getting the world space camera position and basis vectors, and then using those to figure out world space positions. I find it makes the math more straightforward.

This line is suspect: "m_WorldPosition = inverseVP * (nearPoint);"
It looks like it should be: "rayOrigin = inverseVP * (nearPoint);"
Otherwise many lines in your code deal with an uninitialzed variable.

[quote name='masterbubu']Anyone?[/quote]blink.png Impatient, are we? Edited by scniton

Share this post


Link to post
Share on other sites
Hi,


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]Did you take into account the perspective divide between clip coordinates and normalized device coordinates[/background]

[/font]
[/quote]
Doesn't the projection multiplication do that?
Do u mean that I need to divide by Z coord?

About the uninitialized variable, I noticed after posting, so tnx for that :)


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]blink.png[/background]

[/font][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)] Impatient, are we? [/background]

[/font]
[/quote]
Sorry, I have short deadline for that.

Share this post


Link to post
Share on other sites


[background=rgb(250, 251, 252)]Did you take into account the perspective divide between clip coordinates and normalized device coordinates[/background]



Doesn't the projection multiplication do that?
Do u mean that I need to divide by Z coord?
[/quote]
Usually, it doesn't. A matrix multiplication is basically a sum of a few dot products, which means, it can't divide something. If your * operator internally lifts a vec3 to vec4 and eventually projects it back, then your lucky. If it only use the upper-left 3x3 part of your matrix, well - then you're not. smile.png
Just to be safe, I'd do it myself:

const Matrix4& inverseVP = (pCamera->mProjection * pCamera->mView()).inverse();
float NewX = (2.0f * MouseX/ pCamera->fWidth) - 1.0f;
float NewY = 1.0f - (2.0f * MouseY/pCamera->fHeight);
vec4 nearPoint(NewX, NewY, -1.f, 1); // lift from cartesian to homogeneous coodinates.
vec4 midPoint (NewX, NewY, 0.0f, 1); // lift from cartesian to homogeneous coodinates.
vec4 rayOrigin, rayTarget;

rayOrigin = inverseVP * (nearPoint);
rayTarget = inverseVP * (midPoint);
rayOrigin /= rayOrigin.w; // project from homogeneous coordinates to cartesian.
rayOrigin /= rayOrigin.w; // project from homogeneous coordinates to cartesian.
m_Direction = rayTarget.xyz() - rayOrigin.xyz(); // only use the xyz components
m_Direction.normal(); // does this method modify m_Direction or should it perhaps be: m_Direction = m_Direction.normal();
m_WorldPosition = rayOrigin;


Best regards!

Share this post


Link to post
Share on other sites
Hi,

tnx for the help.
I have tried you suggestion.
In order to draw the ray, I draw a line from the m_WorldPostion to m_WorldPostion + t* m_Direction. Where t = Z far of the camera.
The ray appears good on the 3D scene, however, it does not seems to cross the scene, so the collisions does not works.

Share this post


Link to post
Share on other sites
So the ray is placed in the scene just fine but no intersection is detected?
It appears to me that we are on a good way. The first part seems to work. smile.png

Which intersection test do you use? Here is some very nice overview of intersection algorithms. I usually use the test of Möller and Trumbore for ray tests with triangles and try to cull objects by their bounding volumes. For picking this used to be fast enough for me. (If you need more speed you could keep some acceleration data structure to get faster ray traversals, e.g. bounding volume hierarchies, Kd trees etc.)

A frequent bug is to have the ray and the geometry in different spaces, e.g. the ray is in world or view space and the geometry is in object space. It's the easiest to transform the ray into the space of the model and then do the test there. This can be done by transforming the ray's position (w=1) and the ray's direction (w=0) with the inverse world matrix (or inverse worldview matrix respectively).

Best regards! Edited by Tsus

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!