Collidable geoclipmapping terrain

Discuss any questions about BEPUphysics or problems encountered.
sergiusz308
Posts: 49
Joined: Mon Oct 08, 2012 4:57 pm

Collidable geoclipmapping terrain

Post by sergiusz308 »

Hello, I'm evaluating BepuPhysics right now for indie FPS game and this piece of software is just amazing!

I have question regarding terrain. Internally, terrain in my engine is managed thru kind of geoclipmapping implementation: various resolution grid patches, displaced by GPU. I want to have collisions terrain vs player and terrain vs dynamic objects (i.e. debris, vehicles, NPCs, etc.)

Which entity should be best to handle terrain-collisions here? I thought about terrain class, but geoclipmapping involves dynamic allocations of patches of heightfield data, depending on distance to camera and patch resolution. Will terrain class be suitable for this?

Thanks,
S.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

Out of all the options, Terrain is probably the best fit. Terrains do not have to construct or reconstruct an acceleration structure when they're created or changed because the acceleration structure is implicit.

However, making modifications to any static object will result in issues if there are objects resting on that static object. In the worst case, if the geometry moves upward a significant amount, the resting object could be then under the ground. Unless the Terrain.Thickness is nonzero, the object would then fall into the void. Even if that doesn't happen, though, changing a static object is not a proper 'dynamic' action, so collision response will have to rely entirely on penetration correction impulses. The object will 'squish' out.

All of that said, a common approach is to not bother updating physics to match the graphics. This takes two main forms:
1) Don't simulate anything beyond the full resolution terrain; the game just simulates the immediately visible area. Objects are put into the simulation and taken out of the simulation as the character moves around.
2) Simulate the entire world at full resolution. Objects interacting with the terrain beyond the full resolution graphics area will not match, but if it's far enough to apply LOD, chances are the character won't notice. Fading out small objects and only keeping really big objects visible at further distances will lessen the apparent effect.

Ignoring view-dependent geometry is also important for networking. Different clients can't synchronize the position of a physics object if everyone simulates the physics geometry differently.
sergiusz308
Posts: 49
Joined: Mon Oct 08, 2012 4:57 pm

Re: Collidable geoclipmapping terrain

Post by sergiusz308 »

Norbo, thanks for elaborated answer.

As I understand this - changing height data in terrain class is OK and by design there should be no penalties in performance. Another thing are issues resulting from sudden change of heights and its impact on simulation.

BTW, static objects can generate collisions, but don't move. Dynamic objects generate collisions and can be in motion - am I right?

Are there any methods to persist simulation i.e. by serialization?

Thanks,
S.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

changing height data in terrain class is OK and by design there should be no penalties in performance.
The only cost is updating the bounding box. It's pretty quick- a lot faster than rebuilding a hierarchy for a StaticMesh. If you had some additional information about the bounding box externally, you could go in and modify the Terrain to avoid doing redundant calculation.
BTW, static objects can generate collisions, but don't move. Dynamic objects generate collisions and can be in motion - am I right?
I would separate collidable things into three categories:
1) Dynamic entities. These are Entity objects created with a mass or given a mass post-creation. They can move and respond to forces.
2) Kinematic entities. These are Entity objects created without a specified mass, or forced into a kinematic state after the fact. They can move if you manually assign a velocity, but no simulation forces will change their velocity. They have effectively infinite mass, so kinematic entities cannot respond to collisions. The engine will not try to handle collisions between two kinematic entities. (You can force collision detection to run between kinematics by modifying collision rules, but collision response cannot run.)
3) Static objects. These include the StaticMesh, InstancedMesh, Terrain, and StaticGroup. They are incapable of velocity or force based movement. They do not respond to collisions. Contacts will be generated between a dynamic entity and the static object; the dynamic entity will respond to those contacts. (You can force collision detection to run between static objects and kinematic entities by modifying collision rules, but collision response cannot occur.)
Are there any methods to persist simulation i.e. by serialization?
Nope. Given the tedious, code-infecting complexity of a highly general serialization system, I generally just recommend skimming the bare minimum of externally visible data from the engine for game-specialized serialization. Using entities as an example, this usually amounts to storing out shape instances, an entity's used shape instance index, its mass/inertia tensor/volume, and its MotionState.
sergiusz308
Posts: 49
Joined: Mon Oct 08, 2012 4:57 pm

Re: Collidable geoclipmapping terrain

Post by sergiusz308 »

OK, thanks for explanation.

Regarding static objects - I thinking on how to approach destruction, walls for example, and reading thru your response on similar question earlier this comes to my mind:

1) static object with orginial mesh is in the space and acting as a wall
2) contact with this object was generated and triggered destruction
3) static object mesh is replaced with a cracked one, debris as dynamic objects (or kinectic objects, because we don't realy need collisions) are simulated to give visual feedback

Is it feasible scenario with bepu?

Based on what you said previously, about kinetic entities, in the scenario above if I would use them for debris I'd have to handle their movement myself? I.e. they wont be affected by gravity setting?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

Is it feasible scenario with bepu?
Yup.
Based on what you said previously, about kinetic entities, in the scenario above if I would use them for debris I'd have to handle their movement myself? I.e. they wont be affected by gravity setting?
Kinematic entities do not respond to any forces. Gravity doesn't affect them, explosions don't affect them, collisions don't affect them. So yes, you would have to control their movement by repeatedly setting the velocities to the desired values.

That isn't a really good place to use kinematic entities, though. The defining characteristic of kinematic entities is that they have can move, but have effectively infinite mass. Kinematic entities still collide with dynamic objects- the dynamic object just gets out of the way at all costs. Presumably, you wouldn't want small bits of debris to unstoppably crush everything in their path.

Debris is a perfect application for dynamic entities. If you do not want debris to interact with certain parts of the environment (or each other) for performance or design reasons, you can modify the collision rules for those objects. Check out the collision rules documentation and CollisionFilteringDemo in the BEPUphysicsDemos for more information.
diabloqfdb
Posts: 38
Joined: Mon Aug 20, 2012 10:33 am

Re: Collidable geoclipmapping terrain

Post by diabloqfdb »

Norbo wrote:Out of all the options, Terrain is probably the best fit. Terrains do not have to construct or reconstruct an acceleration structure when they're created or changed because the acceleration structure is implicit.

However, making modifications to any static object will result in issues if there are objects resting on that static object. In the worst case, if the geometry moves upward a significant amount, the resting object could be then under the ground. Unless the Terrain.Thickness is nonzero, the object would then fall into the void. Even if that doesn't happen, though, changing a static object is not a proper 'dynamic' action, so collision response will have to rely entirely on penetration correction impulses. The object will 'squish' out.
Hi!

Sorry for highjacking the discussion, but I am also interested about this subject. I am currently using a StaticMesh for terrain and might switch to Terrain. I have a grid of chunks for efficient rendering and each chunk has its own physics object. As I understand, maybe I should create one big physics object for the entire terrain, but keep chunks for rendering. But will this work will terrain in sizes of several kilometers?

The terrain is deformable and I do want object to react to changes in height. Lowering the height causes the object to remain afloat. I could solve this by detecting the bounding box of the terrain height transformation, intersect that box with the space, and for each dynamic object, drop a light weight small entity, just to give it a nudge. There is probably a more elegant solution to this. But what to do on height increase so that the deformation and object reaction looks natural? Sometimes object react, but generally they will get buried.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

will this work will terrain in sizes of several kilometers?
A single terrain can handle immense numbers of triangles because the acceleration structure is implicit. Evaluating which triangles are nearby is a constant time operation.

The trickier part would be updating the bounding box when you change the terrain. Computing a tight bounding box visits every single vertex once. For a terrain with many many millions of vertices, that's not going to be particularly fast.

So, you can either keep using a chunk-based approach to limit the number of vertices touched when you call UpdateBoundingBox on the terrain after making a height modification, or you could hack it a little bit:
Set the Terrain's BoundingBox directly to a value you know (based on game design or whatever else) totally contains the terrain without having to test every single vertex within it. Doing this instead of calling Terrain.UpdateBoundingBox would save a lot of recomputation time at the cost of a looser bounding box. I assume most of your simulation is near the terrain most of the time anyway, so having a looser fit probably won't matter from a performance perspective.
The terrain is deformable and I do want object to react to changes in height. Lowering the height causes the object to remain afloat. I could solve this by detecting the bounding box of the terrain height transformation, intersect that box with the space, and for each dynamic object, drop a light weight small entity, just to give it a nudge. There is probably a more elegant solution to this.
The floating objects occur because they are asleep (modifying static objects is not a physically recognized operation). Instead of dropping an entity on them to wake them up, just call entity.ActivityInformation.Activate().
But what to do on height increase so that the deformation and object reaction looks natural? Sometimes object react, but generally they will get buried.
There's no correct solution here since the operation isn't particularly physical. How would an object react to the ground beneath it instantly jumping up and swallowing it whole in real life? :)

So, just choose something that feels right.

One option would be to increase the Terrain.Thickness. That way, objects beneath the terrain are pulled up and out of the terrain. The object will vanish for a while before popping back up above the ground, but at least it's not falling into the void.

Another option is to compute the new height of the terrain at the object's horizontal location with a ray cast and then teleport the object up, just as the ground was teleported.
diabloqfdb
Posts: 38
Joined: Mon Aug 20, 2012 10:33 am

Re: Collidable geoclipmapping terrain

Post by diabloqfdb »

Norbo wrote: A single terrain can handle immense numbers of triangles because the acceleration structure is implicit. Evaluating which triangles are nearby is a constant time operation.

The trickier part would be updating the bounding box when you change the terrain. Computing a tight bounding box visits every single vertex once. For a terrain with many many millions of vertices, that's not going to be particularly fast.
There is also the problem of memory. There is the big height map that is used to keep track of the terrain that is not in a format the Terrain class expects. So there is an additional step to prepare the data. Then the actual vertex information must be created. Then it must be passed to VertexBuffers. I am currently trying to eliminate some of the steps.

And StaticMesh eats a lot of memory.
The floating objects occur because they are asleep (modifying static objects is not a physically recognized operation). Instead of dropping an entity on them to wake them up, just call entity.ActivityInformation.Activate().
Thanks! Activate was just what I needed.

Come tot think of it, I could use a Deactivate too. Both placing objects and implementing level load could benefit from placing the object approximately firmly on a surface and marking it as inactive, so the first few seconds of the game the entire world is not trying to settle down. Then if something will brush by the object, it will both try to land on the surface, but generate very little movement and settling action and react to the force of the object that touched it.

I have a feeling that getting a robust quicksave/quickload system will be quite the challenge.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

There is also the problem of memory. There is the big height map that is used to keep track of the terrain that is not in a format the Terrain class expects. So there is an additional step to prepare the data. Then the actual vertex information must be created. Then it must be passed to VertexBuffers. I am currently trying to eliminate some of the steps.
If it comes down to it, you could make a custom version of the Terrain which operates on your data format directly. The changes would be relatively small. (You may want to modify the existing Terrain as opposed to making a new copied type; otherwise, you'll have to copy all the collidable pair handlers and set up all the narrow phase helper pair factories. It's doable but tedious.)
Come tot think of it, I could use a Deactivate too. Both placing objects and implementing level load could benefit from placing the object approximately firmly on a surface and marking it as inactive, so the first few seconds of the game the entire world is not trying to settle down. Then if something will brush by the object, it will both try to land on the surface, but generate very little movement and settling action and react to the force of the object that touched it.
To deactivate an entity's current simulation island, set the entity.ActivityInformation.SimulationIsland.IsActive = false. (Force-deactivating a single entity without deactivating its simulation island isn't possible since the entity's activity state is defined entirely by the simulation island's activity state.)
diabloqfdb
Posts: 38
Joined: Mon Aug 20, 2012 10:33 am

Re: Collidable geoclipmapping terrain

Post by diabloqfdb »

Well the transition over to Terrain from StaticMesh is still problematic for me. Terrain only takes a array of heights and an AffineTransform as parameters. My terrain data is chunked, with each chunk containing absolute coordinates, so you don't need to use a world transform to get it into the right position and height in absolute coordinates. How can I map this to a simple array of heights? How do you represent the spacing between two points in the heighmap and their actual position?

I'm sorry, I was not familiar with AffineTransform, but I think I figured it out. I used what I have a good grasp on, matrices. Here is the code if someone is curious, with the commented part being the static mesh generation and the uncommented one using terrain:

Code: Select all

      public void GenerateMesh(ISpace space, HeightMap heightMap) {
            /*Vector3[] ver = new Vector3[vertices.Length];
            int[] ind = new int[indices16Bit.Length];
            for (int i = 0; i < vertices.Length; i++)
                ver[i] = vertices[i].Position;

            for (int i = 0; i < indices16Bit.Length; i++)
                ind[i] = (int)indices16Bit[i];

            mesh = new StaticMesh(ver, ind);
            space.Add(mesh);*/
            AffineTransform f = new AffineTransform();
            f.Matrix = Matrix.CreateScale(heightMap.GridSpacing, 1, heightMap.GridSpacing) * Matrix.CreateTranslation(sx * heightMap.GridSpacing, 0, sz * heightMap.GridSpacing);
            
            float[,] h = new float[size, size];
            for (int z = sz; z < sz + size; ++z) {
                for (int x = sx; x < sx + size; ++x) {
                    h[x - sx, z - sz] = heightMap.HeightAtPixel(x, z);
                }
            }

            mesh2 = new BEPUphysics.Collidables.Terrain(h, f);
            mesh2.Thickness = 20f;
            space.Add(mesh2);      
        }
Memory consumption is down from 580 MiBs to 318 MiBs, and creation time is down from 9.11 seconds to 0.11 seconds, so using Terrain is a good idea. I'll continue testing. And I still need to reduce memory consumption a lot.

I have two more questions.
1. I think there is a drawer similar to BEPUphysicsDrawer.Lines.BoundingBoxDrawer, that drawns the actual collision data, but I can't find it. Something to at least draw the physics primitives, like box and cylinder.
2. Is there a way to serialize static objects like Terrain so I can stream them asynchronously from disk?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

1. I think there is a drawer similar to BEPUphysicsDrawer.Lines.BoundingBoxDrawer, that drawns the actual collision data, but I can't find it. Something to at least draw the physics primitives, like box and cylinder.
The ModelDrawer- or more specifically, its subclass the InstancedModelDrawer- will do it. Watch out, though; it's designed for Reach and will have trouble drawing Terrains beyond a certain primitive count.
2. Is there a way to serialize static objects like Terrain so I can stream them asynchronously from disk?
There is no built-in serialization.
diabloqfdb
Posts: 38
Joined: Mon Aug 20, 2012 10:33 am

Re: Collidable geoclipmapping terrain

Post by diabloqfdb »

Wow, I rewrote parts of the core of the terrain engine to generate smaller heightmap chunks in a format the BEPU expects instead of one big heightmap and now the creation of terrain collision information only takes up time, no longer eating memory.

That is some very impressive implementation of terrain, not consuming any extra memory except for the float[,] heighmap! Fantastic!
diabloqfdb
Posts: 38
Joined: Mon Aug 20, 2012 10:33 am

Re: Collidable geoclipmapping terrain

Post by diabloqfdb »

Norbo wrote: The ModelDrawer- or more specifically, its subclass the InstancedModelDrawer- will do it. Watch out, though; it's designed for Reach and will have trouble drawing Terrains beyond a certain primitive count.
I was not able to use InstancedModelDrawer. I have no problems with my models matching the collision entity nor any problems with BoundingBoxDrawer nor reason to suspect that anything else is wrong.

Still, I would like to have some visual info when turning on physics debug info. For entities I have the bounding boxes, but for all my StaticMesh instances it does not draw anything. How do you use InstancedModelDrawer? I called Add with the static meshes as parameters and called Draw in the Draw method, next to the BoundingBoxDrawer.Draw statement. And nothing shows up.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collidable geoclipmapping terrain

Post by Norbo »

Be sure to call the drawer's Update method too.
Post Reply