- Home /
Bounds.IntersectRay() inaccurate?
I am using Ray.GetPoint() in the simplest situation, and it's returning inaccurate information.
I'm intersecting a Ray with a Bounds. The Bounds is integer-aligned. The IntersectRay() method returns an exact value. But Ray.GetPoint() returns a value with error much greater than Mathf.Epsilon.
Example:
Bounds b = new Bounds(Vector3.one, Vector3.one * 2.0f);
Ray r = new Ray(new Vector3(0.5f, 0.5f, -3.7f), Vector3.forward);
float d;
b.IntersectRay(r, out d);
Vector3 p = r.GetPoint(d);
The point p should be (0.5, 0.5, 0). Instead, the Z value is off: "Ray: -3.700000E+000, Distance: 3.700000E+000, Point: -2.384186E-007"
If the Ray origin is integral, the result is as expected.
The particular ray is created by a camera which is itself at an integral point (in Z) in my test. But I want an accurate point on the surface of the bounding box, not one just outside of it.
I would like to work out the best way to adjust for the error.
One idea I have is to work out the face of the bounding box which the ray intersects. But I can't even check for the values of the point matching the min/max coordinates, because the error exceeds Epsilon.
Is there any solution besides a larger Epsilon? I can use something like 1E-006 I guess, although that's still a pretty large number, in general (although not in this case where I know I should have an integer value anyway).
UPDATE: I have done more careful analysis. The problem was not Ray.GetPoint(). It was Bounds.Raycast(). The distance value which seemed exact was actually a bit too small. I wrote a test and asserted that d == 3.7f, but instead:
Expected: 3.70000005f
But was: 3.69999981f
Great, so it sounds like your problem is resolved? Feel free to answer it yourself with your epsilon remark so that it can be closed.
Answer by bgulanowski · Dec 10, 2018 at 04:32 PM
Bounds.Raycast() is the culprit. I'm not sure what's going on. I worked around it by doing writing my own boundary raycast that uses Plane.Raycast().
Update: I was wrong. There is nothing strictly wrong with any of the methods. It's a seemingly unavoidable result of rounding errors.
If you define a bounding box (Bounds) at (1,1) with size (2,2), and a Ray at (-1, -1, -1) with direction (1, 1, 0), it should intersect at (0, 0, 1). But there is a rounding error.
If you do the math directly, it's (-1, -1, -1) + 2^(0.5) (2^(0.5)/2, 2^(0.5)/2, 0). Where "2^(0.5)" is the square root of two.
2^(0.5) 2^(0.5) / 2 should be 2, but it's just a little less: 0.999999... or -5.960464E-08 in the debugger.
The frustrating thing, ultimately, is as follows:
float d;
bounds.IntersectRay(ray, out d); // returns true
Vector3 hit = ray.GetPoint(d); // returns slightly inaccurate value, b/c d is too small
bounds.Contains(hit); // returns false <-- this is unfortunate.
That the point of intersection with a bounding box is not contained by the bounding box. This means I need some kid of workaround, because other calculations require that the "hit" point be on the bounding box. I think enlarging d by some amount might work.
I can't really figure out why the error is so large. Each calculation compounds the initial error, but it must be a bigger error that expected coming from either Mathf.Sqrt() or all the math functions.
Note that the epsilon is not necessary the smallest possible change since we deal with floating point values. Note that the error is extremely small. "-2.384186E-007" is just
"-0.0000002384186"
This can safely be considered "0".
I'm not sure what you actually want to do, nut
bounds.Contains(hit);
doesn't make any sense. The raycast should return the hit point on the surface of the bounding box. By no means would anyone assume that this point is necessarily "inside" the bounds. There is no better solution than increasing your epsilon to a reasonable value. You get different errors depending on the size of the numbers. $$anonymous$$eep in $$anonymous$$d that the accuracy of floating point numbers "float" along with the binary point. The larger the value before the point, the less accuracy you have behind it. I've posted a table of the float format over here to get a better feeling for what values with which accuracy can be represented
Your answer
Follow this Question
Related Questions
Raycast distance change object color 3 Answers
using a textured plane as a cursor, problem successfully rotating relative to RayHit.normal 1 Answer
Drawing a 3d Cone ray 2 Answers
Is it possible to make 2 raycast's collide with eachother? 1 Answer
Trouble with Projectiles, Raycasting, and 'Gravity' 0 Answers