How do I pick the correct ring when ray casting?

Started by
22 comments, last by Spa8nky 12 years, 9 months ago
Would it be correct to first test the sphere for intersection then take the intersection point and calculate its distance from each plane?
Advertisement
That is what you are doing right now with the projections; the projections ARE the distances to each plane.

to rdragon1; that is not the same as finding the distance from each circle to the mouse, and would fail terribly when trying to select a circle nearly perpendicular to the viewing plane
Note also that computing the distance between a ray and a circle requires solving a quartic equation; which is best done numerically since precise accuracy wouldn't be needed.
I see, point to plane but D is 0:


Vector3.Dot(Normal, point) - D;


The intersection with the sphere will determine whether your test should be performed.

I have the unprojected mouse coordinates. I then need to find the distance between those coordinates and the rings projected to screen coordinates, correct?
I can project the mouse ray's origin onto each circle in 3D:



// Get the normal of the circle
normal = Vector3.UnitX;

// Project the ray's origin onto the circle plane
q = ClosestPtPointPlane(ray.Origin, normal, Vector3.Dot(boundingSphere.Position, normal));

// Find the closest point on the circle to the ray's origin
closestPoint = boundingSphere.Position + radius * Vector3.Normalize(q - boundingSphere.Position);


but I'm unsure how I would project each circle to 2D?

I usually use the transpose of the camera's view matrix:



Matrix view = game.ActiveCamera.ViewMatrix;
Matrix.Transpose(ref view, out view);


but would this affect the radius for both the X and Y axis making the circle an ellipse?

Therefore would I need to do a test for closest point to ellipse instead?

EDIT:



Matrix view = game.ActiveCamera.ViewMatrix;
Matrix.Transpose(ref view, out view);

// Get the normal of the circle
normal = Vector3.UnitX;

// Ellipse extents
Vector3 e = new Vector3();
e.X = Vector3.Dot(normal, view.Right) * radius;
e.Y = Vector3.Dot(normal, view.Up) * radius;
e.Z = 0f;

// Calculate the distance
float p0 = DistancePointEllipse(e, ray.Origin);
You 'either' compute the ellipse of each circle in the 2d projection, and find distance to 2d mouse coordinate.

OR

you find distance from the unprojected mouse ray with each circle in 3D.

Computing the ellipse of each circle wouldn't really be entirely trivial, your 'ellipse' extents are almost NEVER going to be the points corresponding to the ellipse extents in 2D. Infact i'm not even entirely sure a circle is 'always' projected to an ellipse though that would seem intuitive.

It is also the case (like with line-circle in 3D distance) that the distance between a point an ellipse is also not entirely trivial to find.

I would suggest then that you should stick to 3D in which we already have a well defined problem without the trouble of trying to determine the orientatino of an ellipse from a projected circle.

Using: http://www.geometrictools.com/Documentation/DistanceLine3Circle3.pdf (Circle, not Disk)

And some google searches for solving quartic equations (Note: i would not suggest implementing the analytical solution, as it is not generally numerically stable; a numerical solution is generally much better)

You should be able to get the distance to each of the 3 circles from your unprojected mouse ray.
Hi,

I assume that you want to use the rings for rotating the object? Is it totally out of the option to place few (let's say 4) grip point on each of the circles? The grip points could be screen aligned and the angle of the ring wouldn't matter.

Best regards!

you find distance from the unprojected mouse ray with each circle in 3D.


I tried this before attempting the ellipse method but it doesn't work as intended either:


[color="#1c2837"]
Vector3 closestPoint;
Vector3 normal;
Vector3 q;

//Vector3 p = new Vector3(game.HID.MousePosition, 0f); // Unprojected screen coordinates
Vector3 p = ray.Origin; // Projected to near plane

// [X Axis]

// Get the normal of the circle
normal = Vector3.UnitX;

// Project the ray's origin onto the circle plane
q = ClosestPtPointPlane(p, normal, Vector3.Dot(boundingSphere.Position, normal));

// Find the closest point on the circle to the ray's origin
closestPoint = boundingSphere.Position + radius * Vector3.Normalize(q - boundingSphere.Position);

// Calculate the distance from point 'p' to 'closestPoint'
float p0 = Vector3.DistanceSquared(p, closestPoint);

pV0 = closestPoint;

normal = Vector3.UnitY;
q = ClosestPtPointPlane(p, normal, Vector3.Dot(boundingSphere.Position, normal));
closestPoint = boundingSphere.Position + radius * Vector3.Normalize(q - boundingSphere.Position);
float p1 = Vector3.DistanceSquared(p, closestPoint);

pV1 = closestPoint;

normal = Vector3.UnitZ;
q = ClosestPtPointPlane(p, normal, Vector3.Dot(boundingSphere.Position, normal));
closestPoint = boundingSphere.Position + radius * Vector3.Normalize(q - boundingSphere.Position);
float p2 = Vector3.DistanceSquared(p, closestPoint);

pV2 = closestPoint;


If I draw pv0, pv1 and pv2:

Mouse Unprojected Screen Coordinates:

ScreenCoordinatesRings.png


Mouse Projected Onto Near Plane:

ProjectedMouseCoordinatesRings.png

[color=#1C2837][size=2]

[color=#1C2837][size=2]In both cases the correct ring is not selected.
That's because your calculation of the distance between the ray and the circle is COMPLETE utter rubbish :P I don't know how you came up with that but it makes absolutely no sense at all.

I gave you a link to an article describing how to calculate the distance between a ray and a circle in 3D; it involves solving a quartic equation which you can do easily with a numerical solution you can find online.
Example: http://www.flipcode....ot-Finder.shtml

Using that you would have something like:


unproject mouse coordinate to ray.
for each circle:
vector<double> quartic = gen_quartic(ray, circle); //as in article
vector<double> roots = find_roots(quartic); //from flipcode
for each root:
find distance for this root; //as in article
take minimum distance as distance between ray and circle
take circle with minimum distance

This topic is closed to new replies.

Advertisement