Spheres and StaticMesh plane movement issue

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
empitness
Posts: 3
Joined: Sat Sep 24, 2011 5:50 pm

Spheres and StaticMesh plane movement issue

Post by empitness »

Hi guys, I'm implementing a pool game using BEPUphysics and I came across a problem I don't know how to solve.

I have a 3D *.obj model for the pool table which I'm loading manually since I'm targeting Silverlight 5 and not XNA (unfortunately Silvelight's subset of XNA functionality is missing the content pipeline support).
Apart from geometry the model also consists of considerably simpler collision meshes for various parts of the table, such as pockets, rails or the flat surface the balls roll on. And it's the surface collision mesh I'm having problems with - no matter how I triangulate it, there's always a lot of weird ball movement going on.
Just to illustrate it better I simplified the surface as a plane made of 8 triangles: http://img17.imageshack.us/img17/7367/b ... icsbug.png.
The vertices are marked red and next to them are their indices.

I create a StaticMesh:

Code: Select all

StaticMesh mesh = new StaticMesh( Vertices.ToArray(), Indices.ToArray() );
where Vertices contains:

Code: Select all

[0]	{X:-2.1382 Y:1.7576 Z:0.0174}	
[1]	{X:-2.1382 Y:1.7576 Z:3.7969}	
[2]	{X:0.0326 Y:1.7576 Z:0.0174}	
[3]	{X:0.0326 Y:1.7576 Z:3.7969}	
[4]	{X:2.2033 Y:1.7576 Z:0.0174}	
[5]	{X:2.2033 Y:1.7576 Z:3.7969}	
[6]	{X:-2.1382 Y:1.7576 Z:-3.762}	
[7]	{X:0.0326 Y:1.7576 Z:-3.762}	
[8]	{X:2.2033 Y:1.7576 Z:-3.762}	
and Indices contains:

Code: Select all

[0]	0	
[1]	1	
[2]	2	
[3]	3	
[4]	2	
[5]	1	
[6]	2	
[7]	3	
[8]	4	
[9]	5	
[10] 4	
[11] 3	
[12] 6	
[13] 0	
[14] 7	
[15] 2	
[16] 7	
[17] 0	
[18] 7	
[19] 2	
[20] 8	
[21] 4	
[22] 8	
[23] 2	
The problem is that the balls (Sphere prefabs) behave unexpectedly on the boundaries of the triangles.
When I set:

Code: Select all

mesh.ImproveBoundaryBehavior = true;
then the balls accelerate in a completely different direction when rolling over a triangle-triangle boundary and often pass through the triangles.
When I set:

Code: Select all

mesh.ImproveBoundaryBehavior = false;
then nothing bad happens as the balls pass triangle boundaries and their movement seems generally better. But when a ball passes over a vertex shared by multiple triangles (e.g. the one in the center of the surface) then it's slightly changes it's move direction.
Both the issues seem to happen only when balls are moving slowly, e.g. when coming to stop, but on the other hand when they move faster it may be just harder to notice the same behavior.

Here are some videos that show the issues I'm talking about:
mesh.ImproveBoundaryBehavior = true
mesh.ImproveBoundaryBehavior = false
Using the mouse I apply a linear impulse when button is pressed to shoot a ball in a straight line towards the cursor.

Any help would be appreciated :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Spheres and StaticMesh plane movement issue

Post by Norbo »

My first guess would be scale issues. How small is the ball itself? If it's below a certain threshold defined by various tuning factors designed to operate on the 0.5 to 10 units scale, collision won't work so well. Specifically, in this case, it looks like you're hitting a combination of contact distance thresholds (avoid creating contacts that are too close together) and boundary handling (ignore certain collisions to avoid 'bumping' at triangle intersections). Sphere-mesh is a special case in collision detection, so going way above 10 shouldn't pose a problem (though it's still a good idea to stay in that range anyway), but going significantly below 0.5 units in size probably will.

Could you reproduce the problem in the BEPUphysicsDemos? If I could copy-paste some simple code and debug it, it would be easier to diagnose thoroughly.
empitness
Posts: 3
Joined: Sat Sep 24, 2011 5:50 pm

Re: Spheres and StaticMesh plane movement issue

Post by empitness »

You're completely right Norbo about the scale being of the issues. I used a scale of: 1 unit = 1.0m, which in turn caused the ball to be only 0.07 units in radius. After changing the scale by a factor of 10x the problem of balls passing through the surface seems to be solved.

But the other issue (spheres wandering around a plane made of triangles on low velocities) hasn't been resolved yet, unfortunately. I start to think it's perhaps somehow connected with the gravity force having relatively high value of (0, -300, 0). Initially the gravity was set to (0, -30, 0) but I had to adjust it after changing the scale. When I set the magnitude of the gravity to 9.81 the wandering didn't seem to occur, but I'm definitely not satisfied with the quality of the simulation with such small gravity values. Any solutions allowing me to keep the gravity at values around -300 would be greatly appreciated.

I was able to reproduce the issues by modifying the StaticMesh demo resulting with this code:

Code: Select all

using BEPUphysics.Collidables;
using BEPUphysics.DataStructures;
using BEPUphysics.Entities;
using BEPUphysics.Entities.Prefabs;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using BEPUphysics.MathExtensions;
using BEPUphysics.CollisionShapes.ConvexShapes;
using System.Diagnostics;
using BEPUphysics.Settings;
using BEPUphysics.Materials;
using BEPUphysics.Constraints.SingleEntity;
using System;
using BEPUphysics.PositionUpdating;

namespace BEPUphysicsDemos.Demos
{
    /// <summary>
    /// A nice driveble landscape.
    /// </summary>
    public class StaticMeshDemo : StandardDemo
    {
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public StaticMeshDemo(DemosGame game)
            : base(game)
        {
            //Load in mesh data and create the group.
            Vector3[] staticTriangleVertices;
            int[] staticTriangleIndices;

            var playgroundModel = game.Content.Load<Model>("plane");
            //This load method wraps the TriangleMesh.GetVerticesAndIndicesFromModel method 
            //to output vertices of type StaticTriangleGroupVertex instead of TriangleMeshVertex or simply Vector3.
            TriangleMesh.GetVerticesAndIndicesFromModel(playgroundModel, out staticTriangleVertices, out staticTriangleIndices);
            var staticMesh = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(Matrix3X3.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi), new Vector3(0, -10, 0)));
            staticMesh.Sidedness = TriangleSidedness.Counterclockwise;

            Space.Add(staticMesh);
            game.ModelDrawer.Add(staticMesh);

				Space.ForceUpdater.Gravity = new Vector3( 0, -300, 0f ); 
				//kapow = new Sphere( new Vector3( 11000, 0, 0 ), .6f, 3 );
				kapow.Mass = 3.0f;

				((Sphere)kapow).PositionUpdateMode = PositionUpdateMode.Continuous;

            game.Camera.Position = new Vector3(0, 1, 20);

				kapow.Position = new Vector3( 0, 1, 0 );
				kapow.ApplyImpulse( kapow.Position, new Vector3( 10, 0, 14 ) );


        }

        /// <summary>
        /// Gets the name of the simulation.
        /// </summary>
        public override string Name
        {
            get { return "Static Mesh"; }
        }

		  public override void Update(float dt)
		  {
			  base.Update( dt );

			  Vector3 vel = kapow.LinearVelocity;
			  vel.Normalize();
			  float dir = MathHelper.ToDegrees( (float)Math.Atan2( vel.Z, vel.X ) );
			  Debug.WriteLine( dir );
		  }

    }
}
The plane.fbx model required for this test can be downloaded here.
After you run this test in debug mode you'll notice the direction (in degrees) of the ball's linear velocity being printed out in the debugger's Output window. The direction keeps at ~54 degrees for a couple of seconds and changes suddenly to ~134 degrees when reaching really low velocity values.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Spheres and StaticMesh plane movement issue

Post by Norbo »

Assuming the velocity change you're referring to happened at a triangle border, it does appear to be a bug.

This replaces the special case sphere-mesh with the general convex-mesh method which doesn't have the issue:

Code: Select all

            NarrowPhaseHelper.CollisionManagers.Remove(new TypePair(typeof(ConvexCollidable<SphereShape>), typeof(StaticMesh)));
            NarrowPhaseHelper.CollisionManagers.Add(new TypePair(typeof(ConvexCollidable<SphereShape>), typeof(StaticMesh)), NarrowPhaseHelper.Factories.StaticMeshConvex);
I'm surprised that issue evaded detection for so long, given how simple the sphere-mesh system is.

Other than dealing with that issue, you may also find that it's useful to increase the update rate of the space. For example, changing the Space.TimeStepSettings.TimeStepDuration from 1/60f to something like 1/300f and updating the Space 5 times instead of once will make the simulation quite a bit more robust in the presence of relatively extreme gravity. You could also set the time step duration and then just pass in the elapsed time each frame to the Space.Update method and the engine will take however many time steps are necessary. The asynchronous update demo has more information (that applies even if not updating asynchronously): http://bepuphysics.codeplex.com/wikipag ... umentation

You may also find that, for something the size of a pool simulation, multithreading doesn't really help. With so few objects being simulated, the cost of managing multiple threads each frame probably makes it slower than just running it on a single thread.

I'll fix whatever's causing the sphere-mesh issue in a few minutes and put it on the development fork (and possibly the main/other forks shortly thereafter).
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Spheres and StaticMesh plane movement issue

Post by Norbo »

Upon further investigation, the 'bug' doesn't appear to be much of a bug. I'm a bit surprised it was visible, but it would explain why you don't see it at low gravity.

Basically, the sphere-triangle test detects normals a bit off vertical. This might seem a bit odd for spheres rolling around on a flat plane, but the mesh is actually treated as a bunch of isolated triangles for the first pass and the sphere is ever so slightly interpenetrating the plane. If you turn off the mesh's ImproveBoundaryBehavior, you can see this more clearly. With extremely high gravity, these off-vertical normals introduce a significant horizontal acceleration as if the sphere were on a slope.

With ImproveBoundaryBehavior on, as it is by default, the normals are force-corrected to align with the triangle normal or the contact is removed entirely (depending on the pair tester's state). Correction can lessen the effect, but doesn't always get rid of it- the normal correction isn't foolproof at these extremes; even a slight numerical error will introduce horizontal acceleration.

Removal of the contact, however, eliminates any chance for a 'bad' normal to contribute. In the general convex-mesh case, correction is only used during deep contact. The rest of the time, the contact is just ignored. This is why replacing the collision pair handler fixes the issue. In the sphere-mesh case, it always attempts to correct the contact, so you suffer from the apparent numerical issues. You can fix this easily by changing the TriangleSpherePairTester's ShouldCorrectContactNormal to return false instead of true, though this requires a source edit.

I'm still considering whether I should change the public version. Further tests of the sphere-mesh case will be necessary (since the ShouldCorrectContactNormal was set to true for a reason, though there may be a better choice now). Given its rarity and the ease of the workaround, I may wait a while to batch up some more changes before releasing a bugfix version.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Spheres and StaticMesh plane movement issue

Post by Norbo »

The development version now includes the ShouldCorrectContactNormal test change: http://bepuphysics.codeplex.com/SourceC ... evelopment
empitness
Posts: 3
Joined: Sat Sep 24, 2011 5:50 pm

Re: Spheres and StaticMesh plane movement issue

Post by empitness »

Thanks a lot Norbo for your help! After following your instructions the simulation is running great now. Thanks for the thorough explanation too, it's always good to know how an engine works under the hood.
Now that I have nice and smooth simulation I can concentrate on the gameplay. I would seek for support if any problems arise. Thanks again! :)
Post Reply