Height Field Collision Issue

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

Re: Height Field Collision Issue

Postby Julio Jerez » Fri Feb 04, 2022 2:20 pm

ok, here is a solution.
It took me time because I had to make modification so that the material graph is functional, the way is was, could work, but was no generic enough.

you do no need to use ndModel, if you do not what to.
as I said you car is essentially and raycast but you drag the actual body shape over the ground.
I am actually surpriced that is work as well as if does, but that's a different story.

her is how it works.
-I made the change to the app martial graph, that's files ../applications\ndSandbox\ndContactCallback
-2 you take the and add to your applicatiopn. you cna remove the thing you do no need and what what you need, (ex I have a sound there)
3- in the material graph, you set the enum fo rteh kind of materil; you application will deal with
4- these could be concret, grass, metal .....

5-then when you make the collision shapes, you asign the type of material that shape will be.
for example
Code: Select all
   ndShapeInstance heighfieldInstance(new ndShapeHeightfield(D_HEIGHTFIELD_WIDTH, D_HEIGHTFIELD_HEIGHT,
      ndShapeHeightfield::m_invertedDiagonals,
      1.0f / 100.0f, D_HEIGHTFIELD_GRID_SIZE, D_HEIGHTFIELD_GRID_SIZE));

   ndShapeMaterial material (heighfieldInstance.GetMaterial());
   material.m_userId = ndApplicationMaterial::m_aiTerrain;
   heighfieldInstance.SetMaterial(material);


same for the body parts.


6- you make your material class that will handle the car/terrain contact and register with teh contact notify graph, something like

Code: Select all
class CAIMaterial : public ndApplicationMaterial
{
   public:
   CAIMaterial()
      :ndApplicationMaterial()
   {
   }

   CAIMaterial(const CAIMaterial& src)
      :ndApplicationMaterial(src)
   {
   }

   ndApplicationMaterial* Clone(const ndApplicationMaterial& src) const
   {
      return new CAIMaterial((CAIMaterial&)src);
   }

   virtual void OnContactCallback(const ndContact* const joint, ndFloat32) const
   {
      //dAssert(joint->IsActive());

      const ndContactPointList& contactPoints = joint->GetContactPoints();
      for (ndContactPointList::ndNode* contactPointsNode = contactPoints.GetFirst(); contactPointsNode; contactPointsNode = contactPointsNode->GetNext())
      {
         ndContactPoint& contactPoint = contactPointsNode->GetInfo();
         // quick hack to show the solution.
         contactPoint.m_normal = ndVector(0.0f, 1.0f, 0.0f, 0.0f);
      }
   }
};


and the registration is like

Code: Select all
   CAIMaterial material;
   ndContactCallback* const callback = (ndContactCallback*)scene->GetWorld()->GetContactNotify();
   callback->RegisterMaterial(material, ndApplicationMaterial::m_aiCar, ndApplicationMaterial::m_aiTerrain);


7- now each time new contacts are generated, you can iterate ovr the contact point and fix the contact normals.

as a test so that you can see it is action I simple overide the normal to be a vector point up.
but I will use this to determine when the bug happen,

if you think this could be a solution, please check it out, before I add the part that take the contact and cast and small sphere, to get a general enough contact point.
The rectified contacts, will not have the edge contact problem because they will be the translation distance that will move the sphere up, the vehicle move horizontal.

anyway I hope this is clear,

If you sync, it is all in the sandbox, and I test it, the vehicle moves like silk, not a single bump.

of course, we need a better fix, as I said but I leave like that, until you see it, and also to see if I can detect where the edge bug is actually happening, I's like to know why, and maybe I can fix it.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Height Field Collision Issue

Postby Julio Jerez » Fri Feb 04, 2022 2:40 pm

and the good know is that the code exposed the bug right way.
now I have a repro that will let me debug this.
this little check exposes it at frame 4035.
Code: Select all
      for (ndContactPointList::ndNode* contactPointsNode = contactPoints.GetFirst(); contactPointsNode; contactPointsNode = contactPointsNode->GetNext())
      {
         ndContactPoint& contactPoint = contactPointsNode->GetInfo();
         // quick hack to show the solution.
         //contactPoint.m_normal = ndVector(0.0f, 1.0f, 0.0f, 0.0f);
         if (contactPoint.m_normal.m_y < 0.999)
         {
            dTrace(("frame %d: this is when the bug happens\n", xxxx));
         }


but fixing this is just optional, even if it is fixed, you should see the material graph,
because it will save you from future recurrence of the same bug.

also the material graph is useful for many things in app.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Height Field Collision Issue

Postby Julio Jerez » Fri Feb 04, 2022 4:32 pm

ahhh, I found the bug.
is was a side effect fix that we made for the immediate collision.

this is what happens,
when two shapes collides. the collision routine do not find all the contacts, is just find the contact that if you translated along the normal, it will resolve the interpenetration.
for most shapes one contact is not enough,
example is one object being a box resting on a plane, it needs three or more contacts.
there are few heuristics that can be used to get all the contacts.
a popular one is to make a cache, where it keep track of the ladt few contacts from previous frames until it gets a stable set, but I do not like that method.
My method is to do a geometric intersection of the two plane that intersect the two shapes.
this method provides all contact in the same frame but is full of degenerated cases and numerical rounding errors.

to solve this numerical error, the trick that I use, is to add numerical perturbations, this is if the first intersection fails, move the plane in one direction and try again, it does this a few times and if they all fail, them it means not collisions.

if all test fail. the fall back is the cache, basically the two shapes intersect so we know that at least one contact is valid, so it returns that contact.

this is what caused the bug for enlarge polygon shapes, if for polygons we calculate the contacts naively, we get many bad edge contacts.
so to fix this there is a preprocess of the faces that encode which edges are concave or convex.

concave edge is not problem because a convex shape cannot collide with a concave corner.
convex edge can cause the problem you see. so, the code build an enlarge skirt around the polygon and use that to get the intersections point.

what this does is that is, edge collisions happens, outside the polygon and will be rejected. the bug, is that the code that add the perturbation was not awared that this was an enlarged polygon, so it reports contacts outside the perimeter as valid.

I know is a long windy explanation, but the fix is just skipping polygonal shapes whe the perturbation fal all tests.

Code: Select all
            count = CalculateContacts(m_closestPoint0, m_closestPoint1, m_separatingVector * ndVector::m_negOne);
            //if (!count) //skip polygonal shapes.
            if (!(count || m_instance1.GetShape()->GetAsShapeAsConvexPolygon()))
            {
               // poly line failed probably because of rounding error
               // but we know the shapes are colliding
               // just return the closest points as contacts
               m_buffer[0] = ndVector::m_half * (m_closestPoint0 + m_closestPoint1);
               count = 1;
            }



if you sync, the bug should not be there anymore.

however, like I said before, please see the Material Graphs, this can save you from future cases where for example say two meshes share a concave edge, but because of some numerical errors, they can't be welded. and when you have millions of faces those things can happens.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Height Field Collision Issue

Postby Esharc » Mon Feb 07, 2022 5:24 am

Thank you, the bug is not there anymore. The AI vehicle moves around very smoothly now.

We already use the materials for custom collision detection between object. But never thought about using it in this instance. That is a very good tip thanks. I think an example of how to use it for a case like this is handy.

Again, thank you very much for all the assistance so far.
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Height Field Collision Issue

Postby Julio Jerez » Mon Feb 07, 2022 11:37 am

Yes that was a resilient one. Glad is fix now.
Ironically, I always test with shape that can never generate the bug, capsules, sphere and camphered cylinder, which all by definition can only produce one contact.
So, it really surprised my why was falling.
But I am glad is over now.

On the material graph. There is a demo that show how to use it, but you are right it is not very clear.

I will clean it so that it only registers one material pair, and the override the different friction values in the call back from the input data.
This will probably show how flexible and versatile the system is for game play.

I also separated the two demos. It is cool to have a very low lod AI car, and this is by far one of the cheapest I have ever seen. The only one that could possibly in the same ballpark is one that I made for the Game Battle zone two long, long time ago when computers where less than one tenth of what they are today. https://www.youtube.com/watch?v=kwGnzS4eTfE
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Previous

Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 18 guests