crash on heightmap collision

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

crash on heightmap collision

Postby JoeJ » Mon Aug 15, 2022 4:38 am

heighmap crash.PNG
heighmap crash.PNG (196.13 KiB) Viewed 7477 times

Well, maybe i do have some memory corruption issues, but posting anyway...

I made a heightfield to compare performance with my meshes.
I have just the heightmap in the scene, plus the car in the middle.
I can drive for a second, then the crash happens every time.

The height field is pretty flat, just some smooth high frequency noise. But it's high resolution, 20 cm edge length.

Code: Select all
static ndBodyKinematic* BuildHeightFieldTerrain (ndWorld& world, const ndMatrix& xform)
   {
      constexpr ndInt32 D_TERRAIN_WIDTH = 256;
      constexpr ndInt32 D_TERRAIN_HEIGHT = 256;
      constexpr ndFloat32 D_TERRAIN_GRID_SIZE = 0.2f;
      constexpr ndFloat32 D_TERRAIN_ELEVATION_SCALE = 1.f;

      ndArray<ndFloat32> heightfield(D_TERRAIN_WIDTH * D_TERRAIN_HEIGHT);
      heightfield.SetCount(D_TERRAIN_WIDTH * D_TERRAIN_HEIGHT);
   
      ndFloat32 minHeight = ndFloat32(1.0e10f);
      ndFloat32 maxHight = ndFloat32(-1.0e10f);
      for (ndInt32 y = 0; y < D_TERRAIN_HEIGHT; y++)
      {
         for (ndInt32 x = 0; x < D_TERRAIN_WIDTH; x++)
         {
            ndVector p (x * D_TERRAIN_GRID_SIZE, 0.f, y * D_TERRAIN_GRID_SIZE, 0.f);
            ndFloat32 noiseVal = PROCEDURAL::C33::ValueNoise3D((float*)&p);
            heightfield[y * D_TERRAIN_WIDTH + x] = noiseVal;
            minHeight = ndMin(minHeight, noiseVal);
            maxHight = ndMax(maxHight, noiseVal);
         }
      }

      ndFloat32 highScale = D_TERRAIN_ELEVATION_SCALE;
      ndFloat32 scale = ndFloat32(2.0f) / (maxHight - minHeight);
      for (ndInt32 i = 0; i < heightfield.GetCapacity(); ++i)
      {
         ndFloat32 y = heightfield[i];
         y = scale * (y - minHeight) - ndFloat32(1.0f);
         heightfield[i] *= highScale;
      }


      // create the height field collision and rigid body
      ndShapeInstance heighfieldInstance(
         new ndShapeHeightfield(D_TERRAIN_WIDTH, D_TERRAIN_WIDTH,
         ndShapeHeightfield::m_invertedDiagonals,
         D_TERRAIN_GRID_SIZE, D_TERRAIN_GRID_SIZE));

      ndShapeHeightfield* const shape = heighfieldInstance.GetShape()->GetAsShapeHeightfield();
      ndArray<ndReal>& hightMap = shape->GetElevationMap();
      dAssert(hightMap.GetCount() == heightfield.GetCount());
      for (int i = 0; i < heightfield.GetCount(); ++i)
      {
         ndFloat32 high = heightfield[i];
         hightMap[i] = ndReal(high);
      }
      shape->UpdateElevationMapAabb();

      ndBodyDynamic* const body = new ndBodyDynamic();
      body->SetNotifyCallback(new BodyNotify);
      body->SetMatrix(xform);
      body->SetCollisionShape(heighfieldInstance);

      world.AddBody(body);
      return body;
   }


Edit:
Tried to change elevation scale to 0(flat) and 10. But still the same crash.
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: crash on heightmap collision

Postby JoeJ » Mon Aug 15, 2022 5:11 am

I can reproduce in Sandbox :)

Change settings:
Code: Select all
#define D_TERRAIN_GRID_SIZE      0.2f//4.0f
#define D_TERRAIN_TILE_SIZE      128
#define D_TERRAIN_ELEVATION_SCALE   0.f//64.0f


Change basic vehicle demo:
Code: Select all
void ndBasicVehicle (ndDemoEntityManager* const scene)
{
   ndMatrix sceneLocation(dGetIdentityMatrix());

   //BuildFloorBox(scene, sceneLocation);
   //BuildFlatPlane(scene, true);
   //BuildGridPlane(scene, 120, 4.0f, 0.0f);
   //BuildStaticMesh(scene, "track.fbx", true);
   //BuildCompoundScene(scene, dGetIdentityMatrix());
   //BuildStaticMesh(scene, "playerarena.fbx", true);
   //BuildSplineTrack(scene, "playerarena.fbx", true);
   sceneLocation.m_posit.m_x = -200.0f;
   sceneLocation.m_posit.m_z = -200.0f;
   BuildHeightFieldTerrain(scene, sceneLocation);


The car starts close to the edge, but is still fully on ground.
When i try to drive backwards, the same crash happens.
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: crash on heightmap collision

Postby Julio Jerez » Mon Aug 15, 2022 10:11 am

ok, fixed.

notice that by making the terrain such heigh resolution, you are forcing the collision to work really hard. the max capacity of the query is 512 faces.

#define D_MAX_COLLIDING_FACES 512
#define D_MAX_COLLIDING_INDICES (D_MAX_COLLIDING_FACES * (4 * 2 + 3))

the index buffer is 9 indices per triangles time the max triangles = 4608
this fix nice on the stack,

the fix I made is that it will bail out of the loop if it reaches that number.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: crash on heightmap collision

Postby Julio Jerez » Mon Aug 15, 2022 10:35 am

The fix preven the crash, but it is not correct.
You should sync, so that it does not crash.
I will try to do the proper fix tonight.

The code is almost verbatim from 3.13 and use indices to get the information.
I will do some refactoring so that it is easier to read.
I got all lost reading it now.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: crash on heightmap collision

Postby JoeJ » Wed Aug 17, 2022 5:18 am

notice that by making the terrain such heigh resolution, you are forcing the collision to work really hard.

Yeah, i have noticed :)
It's the same resolution i use for the static meshes. And so far i have a simple streaming system, activating meshes near the player.
It's not bad. I can driver over the terrain and do not notice the loading and bvh building, which i currently do on the main thread after the physics update is done.
With the car, the physics time is 2-3 ms (single threaded, 4 substeps). But i need to use a small simulation radius of 10-20m. With a larger amount of meshes around, performance becomes too bad.

The effect of having detailed world geometry is interesting. The car reacts properly to small scale bumps, etc. The simulation quality is again surprisingly high. E.g. i did drive into a narrowing cave until the car got stuck in detailed geometry. I'd expect some jitter, but no - it just works.

But currently i would say it's not worth the cost.
So i'll surely work on mesh reduction. Having so many triangles for flat surfaces is obviously a waste.

the max capacity of the query is 512 faces.

What makes those queries?
Actually i don't know much about how physics engines collision detection works.
If it was like classical raytracing, mesh reduction would not help too much.
But i guess you do something different, e.g. making bounding box of a short ray (or a whole body?), get a list of all triangles and process all of them?
If you make queries from the bound of a whole body, large bodies would be a problem no matter what, so i'd like to know this in more detail. Looking at ndAabbPolygonSoup i see both ray tracing and range queries implemented, but i don't know what's mostly used.


Another thing i might try is using a regular grid to find my meshes quickly, replacing you mechanism for a top level acceleration structure. I'll keep my mesh segments divided by a regular grid, because this minimizes the overlap of adjacent segments bounding boxes, so that's a low fruit to take.
This way i should eventually get a larger simulation region for free, as long as nothing happens in those regions.

But all this has to wait until my editor is more complete. For now my approach works well enough to stick at it for some time.
I realize i know little about how current games make their physics geometry, what resolutions they use, and how much of the work is automated. I'll try to look up some related resources.
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: crash on heightmap collision

Postby Julio Jerez » Sat Sep 03, 2022 11:56 am

Oh, I forgot to mention.
I actually did the correct fix for the crash.

The 512 face buffer, is just an arbitrary size buffer.

The way the Collison work, is that it only knows about shortest distance between two convex shapes.
This has shown to be almost optimal for contact point calculation.

A polygonal mesh is not convex, so in order for the convex - convex collision tto work, some preprocess of the face has to be done first. But the engine can propose the entire mesh on each contact query, so what it does is that it collect the number of faces that intersect the bounding box of the colliding shape.

The collection is the 512 faces, that is set arbitrarily.

Once is collect thos faces, them it can preprocess them by using the share edge information.

What that does is that it strudel the face in the direction of the adjacent face to and edge, if the edge is convex, if tge edge is not convex the theoretically the sound be not contact, so the edge can be extended as if it was two flat faces.

This work quite well as long as the penetraion is not too bad, so for that this can be dealt be continue collision, or by more substeps.

Now this will can potentially generate lot of contacts, with many duplicated, so after that a contact reduction optimization is run.

As you can see it is a lot of calculation, so it is in the best interest for peormace, if the face buffer is as Samuel as it can be.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 4 guests