(was) How to call terrain UpdateGeometry? (now) Running out of memory updating geometry 50x

What is the proper way to trigger an UpdateGeometry on terrain? Every code path seems locked down as strictly private. I have deformable terrain working… but to trigger UpdateGeometry I have to kludge set data to nil and then set it again to the terrain data. This works… but also seems to cause running out of memory really quickly. I am tempted to just expose the functionality which is so important… but figure there must be a correct way that doesn’t involve changing library code.

Hmm. Calling updategeometry about 50 times runs out of heap. Do I need to do something to insure the garbage is taken out?

I figured out how to get the change to trigger UpdateGeometry by calling DoChange from within the terrain data class. However I can still only do about 50 changes before it runs out of memory. It is as if it isn’t disposing the old triangle sets.

I did some testing, and it doesn’t seem like UpdateGeometry leaks memory. After calling it more than 300 times, the application memory usage remains similar.

My test:

  • I added
  // Changing Smoothness (see TCastleTerrainNoise.SetSmoothness implementation)
  // calls TCastleTerrain.UpdateGeometry each time.
  TerrainNoise1.Smoothness := TerrainNoise1.Smoothness + SecondsPassed * 0.1;
  Inc(ChangeCount);
  WritelnLog('Smoothness change: %f (change num %d)', [
    TerrainNoise1.Smoothness,
    ChangeCount
    ]);

to the TViewMain.Update implementation in examples/terrain/code/gameviewmain.pas in CGE. So in each update, I change TerrainNoise1.Smoothness which causes UpdateGeometry (I see the terrain actually getting smoother, so I know it works).

Here’s the screenshot after a while:

So, I cannot reproduce the problem on my own. Can you post a testcase to reproduce the issue? Maybe there’s something specific in how you use it to cause the memory leak?

I am back to working on my projects after a couple months off. I have updated to the latest cge. I still have this problem. I can modify the terrain with a mouseclick. I have a grid of singles 100x100 for each tile (I have multiple tiles). A click adds or removes a little at the clicked point. This then calls DoChange on the TCastleTerrainData that wraps my grid of singles. This triggers the UpdateGeometry from the tile. If I click as fast as I can, it runs out of heap after 113 clicks. But if I click really slowly, I can can go way beyond 113, maybe indefinitely. So it seems to me like the garbage collection is falling behind? It is not easy to give you a simple testcase. I could give you access to the whole repository. It is based off of wyrd-forest.

I have a body and collider on the terrain. If I don’t add these, it doesn’t eat memory when I rebuild the terrain after deforming.

     (*
     Body := TCastleRigidBody.Create(Self);
     TerrainTile.AddBehavior(Body);
     Collider := TCastleMeshCollider.Create(Self);
     Collider.Mesh := TerrainTile;
     Collider.Restitution := 0.3;
     TerrainTile.AddBehavior(Collider);*)

Thank you! Thanks to this info, I was able to reproduce and fix the problem :slight_smile:

At each mesh change, TCastleMeshCollider was internally leaking memory.

The fix is committed and pushed ( Fix memory leak due to leaving TKraftMesh instances · castle-engine/castle-engine@12d0f04 · GitHub ). As usual. give Jenkins a few hours to rebuild the engine, and the version with the fix will be available on Download | Castle Game Engine . You can observe the page Comparing snapshot...master · castle-engine/castle-engine · GitHub to know when exactly it will be available: if that page will no longer show the commit “Fix memory leak due to leaving TKraftMesh instances” → then the fix is included in the build.

Note that you speculated in older posts about garbage collector and freeing with delay being an issue: To be clear, there is no such thing in our X3D nodes. We do reference-counting for X3D nodes, but when the count drops to zero → the node is freed immediately, without any delay. (At least for now – I don’t preclude more complicated schemes for freeing / reuse in the future.)

1 Like

Thankyou Thankyou Thankyou! This was a roadblock.