Raycast problem on small distances

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
User avatar
Piranha
Posts: 8
Joined: Fri Jun 01, 2012 12:20 am

Raycast problem on small distances

Post by Piranha »

Hi,

after fixing the StaticMeshes generated from my planet-chunks (Some of the vertices were 'NaN'. I don't even know how you handled this on mesh creation without throwing an exception xD) they are pretty fast :)

Now I'm stuck with another problem:
My RayCasts are very inaccurate. I don't know why, but when pointing (=selecting) towards the planet, I get sometimes the correct chunk selected and sometimes I get the chunk from the other side.

For a better explanation I made a video:
http://youtu.be/tFXsXPNUNfc

The big box around the whole planet has a side length of 2 and is centered at zero, indicating the 'high precision area' (-1 to 1).

As you can see, I just slightly changing my crosshair and I select the chunk behind on the other side. In addition I made a collision box I shoot towards the planet. Sometimes it collides with the planet, sometimes it went's through it.
When moving closer (producing smaller chunks [quadtree]. The greater parent chunk is removed from space) the collision with box/ray totally fails.

Here is my ray cast code:

Code: Select all

                                                                                    //This is OpenTK's equivalent to XNA's Matrix.Forward
if (planet.PlanetSpace.RayCast(new Ray(camera.Position, -camera.CameraMatrix.Row2.Xyz), out raycastResult))
{
    if (raycastResult.HitObject as BEPUphysics.Collidables.StaticMesh  != null) //Check if result is a chunk
    {
        var entityCollision = raycastResult.HitObject as BEPUphysics.Collidables.StaticMesh; //Get the StaticMesh
        var box = entityCollision.BoundingBox; // Get the Boundingbox from StaticMesh
        selectionBox = new WireBox(this, box.GetCorners()); // Create a visible wirebox from the BoundingBox for drawing
        Console.WriteLine("HIT: " + raycastResult.HitData.Location); // Write HitData
    }
}
It can't be float rounding problems because everything is running on on double precision. (Even on float it shouldn't be that inaccurate)

Any ideas?
When I create the shooting box larger than 0.09 (i.e. 0.1) in side length, the box is colliding correct every time (but I even want a 0.0000001 sized box colliding correctly :D).-
Is 0.1 maybe the smallest that BEPUphysics can handle ?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Raycast problem on small distances

Post by Norbo »

There are predefined values in the engine which make it prefer certain ranges. The defaults for these were tuned based on the assumption of single precision floating point and a common range of values.

For example, if the individual triangles being raycasted are extremely small, they are likely running afoul of the FindRayTriangleIntersection's epsilon comparison.

You could shrink the epsilons involved arbitrarily if you'd like (Toolbox.Epsilon and Toolbox.BigEpsilon), but this will have side effects across the whole engine. Generally speaking, pushing the epsilons smaller will make things more expensive since algorithms have to work harder to reach their goal. Smaller epsilons would also generally just fail with single precision floating point numbers.

Or, if the triangles are large enough, it may be that the triangle winding is inconsistent and the StaticMesh sidedness isn't double sided. That would allow some rays (and collisions) to pass through. If Counterclockwise or Clockwise StaticMesh.TriangleSidedness fails and DoubleSided sidedness doesn't, this is likely a contributing issue.
When I create the shooting box larger than 0.09 (i.e. 0.1) in side length, the box is colliding correct every time (but I even want a 0.0000001 sized box colliding correctly ).-
Is 0.1 maybe the smallest that BEPUphysics can handle ?
There are other tuning factors as well. Check out the BEPUphysicsDemos ConfigurationHelper.ApplyScale method and ScaleDemo for a sampling of the big ones related to collision stability. The 'scale interpretation' that the default values were built for is around 0.5 to 10 units per object, sometimes for reasons other than numerical concerns. Calling ApplyScale(2) will make the engine handle sizes twice as large more effectively. Calling ApplyScale(.001) will make the engine handle sizes a a thousand times smaller better. However, watch out- tuning the engine for a particular range can make it behave worse in significantly different ranges. Tune for the range where you care most about collision detail.

If the simulation is very tiny, it may be easier to scale it up to match the default expectation of sizes instead of retuning everything. Thanks to the precision of doubles (15-16 digits worth), you could have more than a thousand discrete values between integers out to over a trillion units away. Taking a unit to be a meter, this scale would work for a range larger than the distance from the Sun to Jupiter. (That's over 8 octillion cubic kilometers of play volume :))
User avatar
Piranha
Posts: 8
Joined: Fri Jun 01, 2012 12:20 am

Re: Raycast problem on small distances

Post by Piranha »

Norbo wrote: Or, if the triangles are large enough, it may be that the triangle winding is inconsistent and the StaticMesh sidedness isn't double sided. That would allow some rays (and collisions) to pass through. If Counterclockwise or Clockwise StaticMesh.TriangleSidedness fails and DoubleSided sidedness doesn't, this is likely a contributing issue.
Omg, I'm such a dumb-ass. I forgot to set the sidedness at all. Now the "select wrong face"-bug is gone. :oops:
Norbo wrote: There are other tuning factors as well. Check out the BEPUphysicsDemos ConfigurationHelper.ApplyScale method and ScaleDemo for a sampling of the big ones related to collision stability. The 'scale interpretation' that the default values were built for is around 0.5 to 10 units per object, sometimes for reasons other than numerical concerns. Calling ApplyScale(2) will make the engine handle sizes twice as large more effectively. Calling ApplyScale(.001) will make the engine handle sizes a a thousand times smaller better. However, watch out- tuning the engine for a particular range can make it behave worse in significantly different ranges. Tune for the range where you care most about collision detail.
I played around with the scale in the Scale-Demo, that was exactly what I needed! When I scaled everything down except for the ApplyScale (set to '1') the tiny objects have the exact inaccurate behavior as my planet. Giving the ApplyScale the same scale as everything else, the tiny boxes were behaving correct.

But when I use ConfigurationHelper.ApplyScale (copy cat style) in my own project, the behavior doesn't change at all. No matter what values I put into ApplyScale 10, 0.1 , 1000, 0.001, 10000000000 ......
(except for '-1' that made crash BEPU). Is there something more to do than ApplyScale ? The changes to the engine are applied correctly and aren't changed somewhere.
I know ApplyScale is the solution for my accuracy problem, but it just doesn't do anything in my project :(
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Raycast problem on small distances

Post by Norbo »

There's nothing special about how they need to be applied, so it should just work the same way it does in the demos. A value of 10000000000 should make the simulation obviously and completely unstable. If it does nothing, something isn't working- unfortunately, I do not have any helpful specific theories.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Raycast problem on small distances

Post by Norbo »

Here's a possibility: the CollisionDetectionSettings.DefaultMargin must be set before any convex objects are created since changing the default does not change existing objects. I would still expect the remainder of the settings to be noticeable even in the absence of modified margin, though.
Post Reply