m_hitNormalWorld meaning (in convex sweep test result)

Post Reply
mechkg
Posts: 1
Joined: Mon Apr 13, 2009 1:50 am

m_hitNormalWorld meaning (in convex sweep test result)

Post by mechkg »

Hello,

I am trying to implement a character controller using Bullet for collision detection. I use a kinematic ghost object, and my approach in general is very much similar to the approach used in btKinematicCharacterController, however with some additional features.

In my test program the static world is a single triangle mesh. I use a capsule collision shape for the character. In order to perform a step, every frame I do a convex sweep test, raising the capsule stepHeight higher than its original position and sweeping to the target position (the target position determined from user input is also raised accordingly). If it hits something, I stop a small distance before that collision takes place, otherwise, I do the full step. Then, I do another sweep downwards to find where the ground is. There is also some logic to slide along surfaces, but I don't think it is relevant to the problem that I have.

When I hit a surface during the ground test phase, I would like to see what is the slope of the surface at the point of collision, and if the slope is too steep, the character should slide down. I assumed that m_hitNormalWorld in the sweep test callback was what I needed (i.e. the normal of the colliding surface), but apparently it is not, or not always. Everything worked fine until I tried to test a stairway. The character started to exhibit some weird behaviour around the step edges. It was occasionally sliding back down, despite the fact that the sides of the steps were vertical and it should have been "stepping over" them (I realise that there is rarely such thing as an absolutely vertical triangle in floating point computations, so I added a threshold to the step size so that it doesn't get too small even if the FPS is very high, that didn't help).

After some debugging, I realised that the normals that were coming from the convex sweep test were not actually normals of the surface that the character ended up standing on. They look like this:

Image

I wonder what is the physical meaning of those normals? In the case of a capsule collision shape (that is round), I suppose they can be visualised this way:

Image

But then I tried to replace the capsule with a box, and this is what I've got:

Image

The strange normals are still there, but now they don't make any sense to me, since they are not perpendicular neither to the triangles of the mesh, nor to the sides of the collision box. Trying to visualise where these could come from, I came up with something like this:

Image

So I have these questions:

1) What is the actual meaning of the m_hitNormalWorld in the convex sweep test callback object? Why is there such a case where this normal is not actually a normal of any of the involved surfaces?
2) Is there a way to reliably determine the normal of the surface that the convex sweep test ran into? Or maybe determine the particular triangle in case it is a mesh?


Thank you very much in advance,
Ivan.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: m_hitNormalWorld meaning (in convex sweep test result)

Post by Erwin Coumans »

Thanks for the beautiful and clear diagrams.
mechkg wrote: 1) What is the actual meaning of the m_hitNormalWorld in the convex sweep test callback object? Why is there such a case where this normal is not actually a normal of any of the involved surfaces?
The m_hitNormalWorld is a separating normal, at the time of impact. The separating normal is calculated using an algorithm that uses a 'getSupportingVertex' on both collision shapes. The normal could be different from the triangle/box faces because:
  • the collision margin makes a box a bit rounded
  • it is the vector, connecting the two closest points, one on each object. Those two points are generated through a combination of several 'getSupportingVertex' calls, that can return an actual vertex of the original object, but also an implicit function (for spheres, capsules, cylinder, cone)
mechkg wrote: 2) Is there a way to reliably determine the normal of the surface that the convex sweep test ran into? Or maybe determine the particular triangle in case it is a mesh?
In case the convex sweep test runs into a triangle mesh, the triangle/part index (that determines the hit normal) could be exposed (need to look further into this).

Hope this helps,
Erwin
shybovycha
Posts: 3
Joined: Thu Aug 13, 2009 8:46 pm
Contact:

Re: m_hitNormalWorld meaning (in convex sweep test result)

Post by shybovycha »

mechkg, can you show me sources of your character controller implementation? 'cause i've really get stuck with it...
TomSpilman
Posts: 2
Joined: Tue Dec 15, 2009 11:30 am

Re: m_hitNormalWorld meaning (in convex sweep test result)

Post by TomSpilman »

I'm running into this same issue in version 2.75.

I've tried doing the following raycast to get the right normal...

Code: Select all

         btTransform rayStart( btTransform::getIdentity() );
         rayStart.setOrigin( sweepHit.m_hitPointWorld + sweepHit.m_hitNormalWorld );
         btTransform rayEnd( btTransform::getIdentity() );
         rayEnd.setOrigin( sweepHit.m_hitPointWorld - sweepHit.m_hitNormalWorld );

         btCollisionWorld::ClosestRayResultCallback rayHit( rayStart.getOrigin(), rayEnd.getOrigin() ); 
         getDynamicsWorld()->rayTestSingle(   rayStart, 
                                                      rayEnd, 
                                                      sweepHit.m_hitCollisionObject, 
                                                      sweepHit.m_hitCollisionObject->getCollisionShape(),
                                                      sweepHit.m_hitCollisionObject->getWorldTransform(),
                                                      rayHit );        
... but the resulting rayHit.m_hitNormalWorld is nearly identical to the sweepHit.m_hitNormalWorld and doesn't equal the normal of the hit surface.

Its hard to believe its not possible to get the real normal of the hit surface for sweeps and ray casts. I must be doing something wrong... right?
kwhatmough
Posts: 1
Joined: Thu Jul 05, 2012 2:20 pm

Re: m_hitNormalWorld meaning (in convex sweep test result)

Post by kwhatmough »

This seems like a very common problem. Does anyone have a solution (i.e., a good way to get the hit surface normal instead of the so-called separating normal)?
br3ton
Posts: 2
Joined: Thu Aug 30, 2018 10:40 am

Re: m_hitNormalWorld meaning (in convex sweep test result)

Post by br3ton »

Sorry to necro this old post but I think I'm having a similar issue that I can't find a solution for.

When convex sweeping against a corner I get inconsistent normals returned when I just want the normal of either of the two joining surfaces.

Image
Post Reply