Issue with entity penetrating staticmesh
Issue with entity penetrating staticmesh
I'm having a bit of an issue with Box entities falling, going part way into a static mesh, and then slowly drifting back up. My blocks are 10mx10mx10m and the gravity is set to -9.81 * 10 * 2.5. If I just set it to 98.1, things fall too slow and it looks weird. I tried using the ConfigurationHelper to apply a scale of 10 and 25, and it's still doing it. PositionUpdateMode.Continuous on the boxes seems to have no effect. Same for ConfigurationHelper.ApplyHighStabilitySettings.
Turning up the scale did seem to help a bit but not as much as I would have liked. Also, when I do that, it seems to cause issues for the CharacterController. It becomes very difficult to walk around because its like there are suddenly a lot of invisible walls all over the place. Any ideas?
Video of the collision issue:
Turning up the scale did seem to help a bit but not as much as I would have liked. Also, when I do that, it seems to cause issues for the CharacterController. It becomes very difficult to walk around because its like there are suddenly a lot of invisible walls all over the place. Any ideas?
Video of the collision issue:
Last edited by Telanor on Sat Jul 21, 2012 7:18 am, edited 2 times in total.
Re: Issue with entity penetrating staticmesh
The primary difference in behavior there is caused by the CollisionResponseSettings.MaximumPenetrationCorrectionSpeed. It is modified by the ApplyScale method, but you can set it to anything you want independently. Do, however, use the ApplyScale method to modify all the other settings- if the world is 25 times larger than the interpretation expects, quality will suffer.
Objects falling a long way will pick up some speed and, because time steps are discrete, the object will penetrate the ground some. Enabling CCD prevents the object from tunnelling all the way through, but CCD does not try to stop tiny overlaps. (If it did, there would be noticeable halting artifacts on every minor collision. While this can be partially addressed by greater use of speculative contacts [which the engine already uses for some things], other artifacts can be introduced. A full solution requires a bit more trickery which hasn't yet achieved priority high enough to implement.)
Objects falling a long way will pick up some speed and, because time steps are discrete, the object will penetrate the ground some. Enabling CCD prevents the object from tunnelling all the way through, but CCD does not try to stop tiny overlaps. (If it did, there would be noticeable halting artifacts on every minor collision. While this can be partially addressed by greater use of speculative contacts [which the engine already uses for some things], other artifacts can be introduced. A full solution requires a bit more trickery which hasn't yet achieved priority high enough to implement.)
The default configuration of the character is made for something around 2 units tall. There could be some little bits of configuration here and there that could help, but I would need to know the exact configuration of the character and environment to provide any specifics. A modified BEPUphysicsDemos demo would be useful.Also, when I do that, it seems to cause issues for the CharacterController. It becomes very difficult to walk around because its like there are suddenly a lot of invisible walls all over the place. Any ideas?
Re: Issue with entity penetrating staticmesh
I made a really simple demo that shows the issue:
I played around with various settings that ApplyScale sets without any luck. Maybe I'm just being too picky and its a limitation I'll have to live with?
Code: Select all
public class FloatingUpDemo : StandardDemo
{
public FloatingUpDemo(DemosGame game): base(game)
{
Space.ForceUpdater.Gravity = new Vector3(0, -250, 0);
ConfigurationHelper.ApplyHighStabilitySettings(Space);
ConfigurationHelper.ApplyScale(10);
var toAdd = new Box(new Vector3(6, 150, 0), 10, 10, 10, 10) {PositionUpdateMode = PositionUpdateMode.Continuous};
Space.Add(toAdd);
Space.Add(new Box(new Vector3(0, 0, 0), 20f, .1f, 20));
game.Camera.Position = new Vector3(0, 0, 30);
}
public override string Name
{
get { return "Floating up"; }
}
}
Re: Issue with entity penetrating staticmesh
With regard to the demo, I was referring to the character 'invisible walls' issue.
The behavior shown in this demo is expected for the reasons described earlier. Time steps are discrete and CCD does not try to stop every tiny overlap by design. However, you can limit the duration of the overlap by increasing CollisionResponseSettings.MaximumPenetrationCorrectionSpeed and, if desired, the PenetrationRecoveryStiffness too. These modifications should be made in addition to the ApplyScale method's changes. Increasing these allows penetration recovery to work harder. This will add more energy and can make things 'bounce' a little after penetrating deeply, though.
The behavior shown in this demo is expected for the reasons described earlier. Time steps are discrete and CCD does not try to stop every tiny overlap by design. However, you can limit the duration of the overlap by increasing CollisionResponseSettings.MaximumPenetrationCorrectionSpeed and, if desired, the PenetrationRecoveryStiffness too. These modifications should be made in addition to the ApplyScale method's changes. Increasing these allows penetration recovery to work harder. This will add more energy and can make things 'bounce' a little after penetrating deeply, though.
Re: Issue with entity penetrating staticmesh
I hadn't tried PenetrationRecoveryStiffness before because I didn't see it in the ApplySettings but when I set it to 0.4, that seems to work quite nicely. The documentation for that setting seems a bit off though. It says the default is 2 when it seems more like 0.2.
As for the character controller, I've been trying to re-create the situation in a bepuphysicsdemo, but so far, the only issue it's having is that as you walk, it sometimes does this little mini-jump as if you just drove over a rock in a car.
As for the character controller, I've been trying to re-create the situation in a bepuphysicsdemo, but so far, the only issue it's having is that as you walk, it sometimes does this little mini-jump as if you just drove over a rock in a car.
Re: Issue with entity penetrating staticmesh
It is indeed 0.2 by default. The documentation does say .2, but the point is a bit difficult to discern given the intellisense font and kerning so I went ahead and tossed a zero in front of it.The documentation for that setting seems a bit off though. It says the default is 2 when it seems more like 0.2.
I assume the character is larger and is moving faster in absolute value than the default demos character. If so, going over little bumps may exceed the characterController.VerticalMotionConstraint.MaximumGlueForce. Scaling it up may help avoid the issue.As for the character controller, I've been trying to re-create the situation in a bepuphysicsdemo, but so far, the only issue it's having is that as you walk, it sometimes does this little mini-jump as if you just drove over a rock in a car.
Re: Issue with entity penetrating staticmesh
I've messed around with this for a while now and I still can't get the invisible wall issue to occur in the demo nor can I get rid of it in my game. The weird jump kind of thing seems like its related though. The area I'm running around in is just a flat plane, albeit one made up of the surface of many cubes. What I did for the demo was I saved my terrain data to a file and then read that into the demo and loaded static meshes up using that data. Is there any chance it's having some kind of issue due to the size of the triangles the mesh is made up of?
Re: Issue with entity penetrating staticmesh
There's always a chanceIs there any chance it's having some kind of issue due to the size of the triangles the mesh is made up of?

Also, make sure the version of the engine used by the game is the same one you're testing in the demos; maybe something was changed in between them.
Re: Issue with entity penetrating staticmesh
Well, after some more testing, I found that the "invisible walls" seem to go away if I comment out the line in the ApplyScale function that changes CollisionDetectionSettings.AllowedPenetration. The character still acts like a truck driving on a bumpy road though (which does happen in the demo).
Here's the demo. The terrain data file is attached. Just extract it to the same folder the demo .exe is in. If you walk around on a flat area for a minute or two, you should see the bumpiness happening.
Here's the demo. The terrain data file is attached. Just extract it to the same folder the demo .exe is in. If you walk around on a flat area for a minute or two, you should see the bumpiness happening.
Code: Select all
using System.IO;
using BEPUphysics.Collidables;
using BEPUphysics.Materials;
using BEPUphysics.Settings;
using Microsoft.Xna.Framework;
namespace BEPUphysicsDemos.Demos
{
public class BridgeDemo : StandardDemo
{
public BridgeDemo(DemosGame game): base(game)
{
ConfigurationHelper.ApplyDefaultSettings(Space);
Space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0f) * 10 * 2.5f;
ConfigurationHelper.ApplyScale(10);
CollisionResponseSettings.PenetrationRecoveryStiffness = 0.4f;
CollisionDetectionSettings.DefaultMargin = 1f;
character.CharacterController.Body.Height = 17.5f;
character.CharacterController.BodyRadius = 2.5f;
character.CharacterController.Body.Mass = 10;
character.CharacterController.HorizontalMotionConstraint.AirSpeed = 10 * 8f;
character.CharacterController.VerticalMotionConstraint.MaximumGlueForce *= 10 * 8;
character.CharacterController.JumpSpeed = 10 * 8f;
character.CharacterController.HorizontalMotionConstraint.Speed = 10 * 8f;
BinaryReader reader = new BinaryReader(File.Open("regions", FileMode.Open));
while(reader.BaseStream.Position < reader.BaseStream.Length)
{
var vertCount = reader.ReadInt32();
Vector3[] verts = new Vector3[vertCount];
for(int i = 0; i < vertCount; i++)
{
verts[i] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
}
var indexCount = reader.ReadInt32();
int[] indexes = new int[indexCount];
for(int i = 0; i < indexCount; i++)
{
indexes[i] = reader.ReadInt32();
}
var region = new StaticMesh(verts, indexes) { ImproveBoundaryBehavior = true, Material = new Material(150, 140, 0) };
Space.Add(region);
game.ModelDrawer.Add(region);
}
game.Camera.Position = new Vector3(0, 500, 0);
}
public override string Name
{
get { return "Bridge"; }
}
}
}
- Attachments
-
- regions.rar
- (105.38 KiB) Downloaded 357 times
Re: Issue with entity penetrating staticmesh
Here's a couple of things:
1) Based on the observation that the index count is always 1.5 times the vertex count, it appears that each quad has 4 vertices and 6 indices or some other organization with lots of vertices in comparison to indices. This means there's redundant vertex data and missing connectivity information. The boundary improvement system cannot help without connectivity information. From its perspective, the mesh is mostly a triangle soup right now. Triangle edges will generate collision normals with slightly non-vertical normals as the character bumps into them.
2) The CharacterController's collision margin is still 0.1. It should be scaled up. This is probably the source of most of the 'invisible walls'. Because the margin was tiny, the character was closer to the triangles allowing sideways-pointing normals to be created. This is why reducing AllowedPenetration seemed to help, too.
A trickier way to sidestep the boundary contacts problem would be to implement your own external form of "ImproveBoundaryBehavior." Without connectivity information, the triangle mesh cannot know what the normals should be, but you have more information available. You know the mesh isn't just an arbitrary triangle soup- there's lots of guarantees. If all normals from the terrain are guaranteed to be aligned along one of six axes, you can compute the nearest axis for a given normal and lock it to the closest option. This isn't a perfectly correct thing to do on edges, but it may look good enough without any special case handling. This normal correction would need to be done after the narrow phase and before the solver, just like the CharacterController's CorrectContacts method.
An even more advanced approach would be to implement your own collidable. With a custom collidable, the contacts could be created initially with all the available information rather than having to hackily correct them after the fact. The collidable probably wouldn't even be a mesh, but rather some direct representation of boxes in the world. This is usually the route taken for best behavior/performance in dynamic voxel worlds, but it does require a lot more knowledge of collision detection and the internals of BEPUphysics.
1) Based on the observation that the index count is always 1.5 times the vertex count, it appears that each quad has 4 vertices and 6 indices or some other organization with lots of vertices in comparison to indices. This means there's redundant vertex data and missing connectivity information. The boundary improvement system cannot help without connectivity information. From its perspective, the mesh is mostly a triangle soup right now. Triangle edges will generate collision normals with slightly non-vertical normals as the character bumps into them.
2) The CharacterController's collision margin is still 0.1. It should be scaled up. This is probably the source of most of the 'invisible walls'. Because the margin was tiny, the character was closer to the triangles allowing sideways-pointing normals to be created. This is why reducing AllowedPenetration seemed to help, too.
A trickier way to sidestep the boundary contacts problem would be to implement your own external form of "ImproveBoundaryBehavior." Without connectivity information, the triangle mesh cannot know what the normals should be, but you have more information available. You know the mesh isn't just an arbitrary triangle soup- there's lots of guarantees. If all normals from the terrain are guaranteed to be aligned along one of six axes, you can compute the nearest axis for a given normal and lock it to the closest option. This isn't a perfectly correct thing to do on edges, but it may look good enough without any special case handling. This normal correction would need to be done after the narrow phase and before the solver, just like the CharacterController's CorrectContacts method.
An even more advanced approach would be to implement your own collidable. With a custom collidable, the contacts could be created initially with all the available information rather than having to hackily correct them after the fact. The collidable probably wouldn't even be a mesh, but rather some direct representation of boxes in the world. This is usually the route taken for best behavior/performance in dynamic voxel worlds, but it does require a lot more knowledge of collision detection and the internals of BEPUphysics.
Re: Issue with entity penetrating staticmesh
I had completely forgotten about the redundant vertices. As a quick solution, I wrote some code to optimize out the redundant vertices before handing them to the StaticMesh. The invisible wall/bumpiness issue is completely gone now. This solution is probably more computationally expensive and generates more garbage then your suggestion of correcting the normals though. I'm not sure where to actually put code to accomplish that though. My assumption was that I would need to make my own class that inherits from StaticMesh and then override an Update method, but I didn't see anything related that I could override. Do you mind pointing me in the right direction?
Also, I can't seem to find the collision margin setting for the CharacterController. I seem to be bad at finding settings for BEPU stuff...
On a side note, my character was sliding around on the terrain like it was ice so I turned the friction on the StaticMeshes way up to 15. Is that the right way/only way to reduce the sliding around for a character, or is there another setting I'm missing?
Also, I can't seem to find the collision margin setting for the CharacterController. I seem to be bad at finding settings for BEPU stuff...
On a side note, my character was sliding around on the terrain like it was ice so I turned the friction on the StaticMeshes way up to 15. Is that the right way/only way to reduce the sliding around for a character, or is there another setting I'm missing?
Re: Issue with entity penetrating staticmesh
If you just wanted to get it to work for the CharacterController specifically, it could be put right alongside the CharacterController.CorrectContacts method. It goes through and makes modifications to contact normals for better smoothness. In a pair which involves the voxel terrain, custom correction logic could be used.My assumption was that I would need to make my own class that inherits from StaticMesh and then override an Update method, but I didn't see anything related that I could override. Do you mind pointing me in the right direction?
If you wanted to do the same thing except for all pairs as opposed to just the character-involving pairs, iterate through every pair in the voxelTerrainCollidable.Pairs list and fiddle with the contact normals stored in the Contacts collection. It needs to run between the NarrowPhase and Solver like the character for it to be useful, though. To make it run there, either create a custom IBeforeSolverUpdateable or just hook an event on NarrowPhase.Finishing or Solver.Starting.
It may be worth just creating the optimized mesh, though. While the 'snap to nearest axis' approach is easy enough, it could make edge collisions behave weirdly. A full-featured contact correction system that works all the time is nontrivial. Of course, if you test it and it looks fine for what the game needs, it doesn't really matter if it could theoretically have behavior problems

The CollisionMargin is a property of convex shapes like the CylinderShape used by the character. It can be found in the Body.CollisionInformation.Shape.CollisionMargin.Also, I can't seem to find the collision margin setting for the CharacterController.
The character actually explicitly removes all friction between it and the environment to make sliding along walls easier (and to prevent it from being slowed down by the ground). Instead, the acceleration and deceleration is defined by the HorizontalMotionConstraint's MaximumForce, MaximumSlidingForce, and MaximumAirForce properties. MaximumForce is the amount of force the character can apply while it has traction. The sliding variant is how much force it can apply without traction while still having a support. The air variant applies when the character is falling/floating. Scaling up these properties will make the character more responsive.On a side note, my character was sliding around on the terrain like it was ice so I turned the friction on the StaticMeshes way up to 15. Is that the right way/only way to reduce the sliding around for a character, or is there another setting I'm missing?
Re: Issue with entity penetrating staticmesh
Ok so I hooked into the Solver.Starting event, went through all the contacts on the terrain and.... turns out the normals aren't even close to what they should be. On a block that should have a normal of Y = 1, I get normals with X = 1 and Z = 1. It also seems like the contact points can be anywhere inside the block. I don't see an easy way to snap them to the correct value, so I think for now I'll just stick with optimizing the mesh.
Also, I changed the force properties on the character and it definitely made the character a lot more responsive.
Thanks for your help with this.
Also, I changed the force properties on the character and it definitely made the character a lot more responsive.
Thanks for your help with this.
Re: Issue with entity penetrating staticmesh
The contact points aren't rigidly required to exist on the planes of the triangles, but they should not be way off. The two fuzzy factors are penetration and persistent manifolds which keep contacts around a little while, though the latter shouldn't produce significantly penetrating positions.On a block that should have a normal of Y = 1, I get normals with X = 1 and Z = 1. It also seems like the contact points can be anywhere inside the block. I don't see an easy way to snap them to the correct value, so I think for now I'll just stick with optimizing the mesh.
Also, I wouldn't expect to see normals that are 90 degrees off unless there's severe penetration (beyond the collision margin) happening. Such bad normals would cause the 'invisible wall' effect very strongly. If there were no such strong invisible walls felt, then it's likely that the normals were actually more correct than that. Maybe the horizontal normal came from a nearby collision or something.
Even if the normals are totally random, it is still possible to correct them by using the normal of the triangle they originated from. Getting that information would be tricky and only really makes sense in the custom collidable approach, though.
All that said- optimizing the mesh is indeed probably the best quality-per-development-hour option.
