Getting contact points upon collision

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Getting contact points upon collision

Postby GravitateGames » Tue Aug 26, 2025 11:39 pm

Hello,

Within my "ndContactNotify" callback class, I'm trying to get the contact points from within this function;

Code: Select all
void PhysicsContactCallback::OnContactCallback(const ndContact* contact, ndFloat32 timestep) const {
      auto body0 = contact->GetBody0();
      auto body1 = contact->GetBody1();

      //auto map = body0->GetContactMap();//inaccessible, won't compile
      auto points = contact->GetContactPoints();//crashes when called


However GetContactMap() is inaccessible and won't compile and GetContactPoints() crashes here in "ndList.h"

Code: Select all
template<class T, class allocator>
ndList<T, allocator>::ndList(const ndList& src)
   :ndClassAlloc()
   ,m_first(src.m_first)
   ,m_last(src.m_last)
   ,m_count(src.m_count)
{
   //steal the members.
   //yes I know this is wrong, I have to add the move semantic,
   //but since my code predate move semantic, I will do my own steal
   //this will work as long as src is empty
   ndAssert(src.m_count == 0);
   ndAssert(src.m_first == nullptr);
   ndAssert(src.m_last == nullptr);
}


I see why the program is crashing here based on the Asserts, but should it be? Is there a better way to find out the contact positions?

Thankyou!
GravitateGames
 
Posts: 3
Joined: Thu Aug 21, 2025 5:55 pm

Re: Getting contact points upon collision

Postby Julio Jerez » Wed Aug 27, 2025 9:46 am

the call is:
    const ndContactPointList& contactPoints = contact->GetContactPoints();
there is not accert, it is just this:
Code: Select all
const ndContactPointList& ndContact::GetContactPoints() const
{
   return m_contacPointsList;
}


if you want to get it from a body, you can try a function like this
Code: Select all
const ndContact* GetContact (ndBodyKinematic* const body) const
{
   const ndBodyKinematic::ndContactMap& contacts = body->GetContactMap();
   ndBodyKinematic::ndContactMap::Iterator it(contacts);
   for (it.Begin(); it; it++)
   {
      ndContact* const contact = *it;
      if (contact->IsActive())
      {
         return contact;
      }
   }
   return nullptr;
};


them if the function returns the contact joint, you can get the contact points.

Code: Select all
   ... from anywhere of the updates.
   ndBodyKinematic* const someBody;
   const ndContact* contact = GetContact (someBody);
   if (contact)
   {
        ndContactPointList& contactPoints = contact->GetContactPoints();
   }


you can look at the demos for examples
...\ndSandbox\demos\ndBasicFrictionRamp.cpp


there is a function that show how to iterates over all contacts in the scene.
from file: ....\ndSandbox\toolbox\ndDebugDisplay.cpp

Code: Select all
void ndDebugDisplay::ndNormalForces::UpdateBuffers(ndDemoEntityManager* const scene)
{
   ndScopeSpinLock lock(m_lock);
   
   m_points.SetCount(0);
   
   ndWorld* const world = scene->GetWorld();
   const ndContactArray& contactList = world->GetContactList();
   ndScopeSpinLock contactLock(contactList.GetLock());

   for (ndInt32 i = 0; i < contactList.GetCount(); ++i)
   {
      const ndContact* const contact = contactList[i];
      if (contact->IsActive())
      {
         glVector3 color(GLfloat(1.0f), GLfloat(1.0f), GLfloat(0.0f));
         const ndContactPointList& contactPoints = contact->GetContactPoints();
         for (ndContactPointList::ndNode* contactPointsNode = contactPoints.GetFirst(); contactPointsNode; contactPointsNode = contactPointsNode->GetNext())
         {
            const ndContactMaterial& contactPoint = contactPointsNode->GetInfo();
            const ndVector origin(contactPoint.m_point);
            const ndVector normal(contactPoint.m_normal);
            const ndVector dest(origin + normal.Scale(contactPoint.m_normal_Force.m_force * m_scale));
   
            ndColorPoint colorPoint;
            colorPoint.m_point = origin;
            colorPoint.m_color = color;
            m_points.PushBack(colorPoint);
   
            colorPoint.m_point = dest;
            colorPoint.m_color = color;
            m_points.PushBack(colorPoint);
         }
      }
   }
   m_frameTick1++;
}


Pay attention to the contact behind valid.
Contact are created when two bodies shared the same parent aabb. But they aren't valid until the distance between the two bodies is small.
They get destroyed when the bodies do not shared the same aabb, that makes it a lazy system, and may appear that contact are always part of the body.
This means you should not hold to a contact pointer. You should always get them from the body contact map.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Getting contact points upon collision

Postby GravitateGames » Wed Aug 27, 2025 9:11 pm

Thankyou, got it working.

It was the auto keyword that it didn't like.

I've looked at the ndContactMaterial struct while debugging, but I can find any way of getting the impact speed?
GravitateGames
 
Posts: 3
Joined: Thu Aug 21, 2025 5:55 pm

Re: Getting contact points upon collision

Postby Julio Jerez » Thu Aug 28, 2025 12:04 am

The joint doesn't report the impact speed directly,
instead it produces the impulse and the reaction forces.
when objects collide, the force is almost zero, but the impulse is high. but when they are at rest, it is the opposite.
if you want to get a velocity, you can just multiply the impulse by the larger of the inverse mass of the two colliding bodies. that's usually a good approximation for games.

the info is just a public member of class ndContactMaterial: public ndContactPoint

after you get the contact joint, you can iterate over each contact point.
each contact will have the force and collision impulse impact in members

    ndVector m_dir0;
    ndVector m_dir1;
    ndForceImpactPair m_normal_Force;
    ndForceImpactPair m_dir0_Force;
    ndForceImpactPair m_dir1_Force;

you probably want member: ndForceImpactPair m_normal_Force;

you can look up ndForceImpactPair and you will get impulse and force of the last sim step.
The value is collected after each RK4 substep.
so it is does not represent the average of to the frame step but it is good enough for game play stuff.

they are scalar quantities. To get direction, you can scale the contact normal by the impulse scalar value.
and that gives you an impulse vector.
Then scaling by the larger invMass of the two bodies, you get the an impact velocity.

remember that's not a permanent value. So do hold pointers
You need to get it in an update callback.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Getting contact points upon collision

Postby GravitateGames » Thu Aug 28, 2025 1:32 am

That's great, thanks for your help! :D
GravitateGames
 
Posts: 3
Joined: Thu Aug 21, 2025 5:55 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 2 guests