TriangleShape RayTest method with compound bodies.

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

TriangleShape RayTest method with compound bodies.

Post by Spankenstein »

I'm performing a ray test against every triangle in a compound body in order to ignore those that are intersected but are facing away from the camera (i.e. culled)

Code: Select all

                                // Test ray against all triangles that make up the hollow object
                                var compoundBody = hollowObject.Entity as CompoundBody;

                                int numTriangles = compoundBody.Shapes.Count;

                                var ray = new Microsoft.Xna.Framework.Ray(cursorRay.Origin, cursorRay.Direction);

                                for (int t = 0; t < numTriangles; ++t)
                                {
                                    RigidTransform rigidTransform = compoundBody.Shapes[t].LocalTransform;
                                    TriangleShape tri = compoundBody.Shapes[t].Shape as TriangleShape;
                                    RayHit triangleResults = new RayHit();

                                    // Test ray for triangle intersection
                                    if (tri.RayTest(ref ray, ref rigidTransform, 1000f, out triangleResults))
                                    {
                                        Vector3 normal = Vector3.Normalize(triangleResults.Normal);

                                        if (Vector3.Dot(normal, game.ActiveCamera.Forward) < 0f)
                                        {
                                            continue;
                                        }
                                        else if (result != null && results[i].HitData.T < tMin)
                                        {
                                            // Find the closest IGrabbableObject
                                            index = i;
                                            o = result;
                                            tMin = results[i].HitData.T;
                                        }
                                    }
                                }
The ray doesn't return true for triangle intersection even though the object is intersected.

Does the ray need to be transformed from world space or is the compound shape's LocalTransform not what I should be passing into the ray casting method?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: TriangleShape RayTest method with compound bodies.

Post by Norbo »

The ray and transform need to be consistent. So, if the ray is in world space, the transform should be the full world transform (for a child, this would be the local transform multiplied by the parent world transform). If the ray is in the local space of the compound, then the transform should be the local transform of the shape.

However, this sort of sidedness calculation is automatic if you use a MobileMesh and pick Clockwise or Counterclockwise for the sidedness. It may be more convenient to either use a MobileMesh instead of a Compound or, if the compound has other non-triangle stuff in it, include a mobile mesh as a child of the compound.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: TriangleShape RayTest method with compound bodies.

Post by Spankenstein »

Norbo wrote: However, this sort of sidedness calculation is automatic if you use a MobileMesh and pick Clockwise or Counterclockwise for the sidedness.
I would like to calculate the contact normal to do a dot product with the camera forward (same as camera culling). I don't think the sidedness can help with this and it will be relative to the camera and the ray cast?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: TriangleShape RayTest method with compound bodies.

Post by Norbo »

Making triangles in a mesh one sided with Clockwise or Counterclockwise effectively 'culls' collisions and ray casts from the backside of the triangle. It is based on winding, just like graphical backface culling. When Clockwise sidedness is used, ray impacts and collisions can occur on the side where the vertices appear to be in a clockwise order. On the other side, they pass straight through.

Try flipping the sidedness on one of the meshes in the BEPUphysicsDemos to see how it works.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: TriangleShape RayTest method with compound bodies.

Post by Spankenstein »

The problem is that the triangles have to be DoubleSided as they belong to a hollow mesh that should constrain objects inside and react to objects outside. The ray cast route is probably the only viable option then?

I apologise I should have mentioned this before.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: TriangleShape RayTest method with compound bodies.

Post by Norbo »

In that case, custom logic is indeed required. You can still cut down on the amount of manual sidedness testing needed by using the Toolbox.FindRayTriangleIntersection(ref ray, maximumLength, sidedness, ref vA, ref vB, ref vC, out hit) method though. It may be slightly more intuitive than the shape's ray cast (which performs transformations internally and then uses this method) since it's a direct test.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: TriangleShape RayTest method with compound bodies.

Post by Spankenstein »

Excellent stuff, the ToolBox method is a great idea.

Code: Select all

                                for (int t = 0; t < numTriangles; ++t)
                                {
                                    TriangleShape tri = compoundBody.Shapes[t].Shape as TriangleShape;
                                    Matrix m = compoundBody.Shapes[t].LocalTransform.Matrix * compoundBody.WorldTransform;

                                    Vector3 a = Vector3.Transform(tri.VertexA, m);
                                    Vector3 b = Vector3.Transform(tri.VertexB, m);
                                    Vector3 c = Vector3.Transform(tri.VertexC, m);

                                    // Test ray for triangle intersection
                                    if (Toolbox.FindRayTriangleIntersection(ref ray, 1000f, TriangleSidedness.DoubleSided, ref a, ref b, ref c, out triangleResult)) 
Thanks for your help Norbo :)
Post Reply