Weird performance problem

Topics: User Forum
May 15, 2011 at 4:43 PM
Edited May 15, 2011 at 5:38 PM

Hello,

I am currently building a physics-based Xbox XNA game using Farseer Physics. So far, the engine is working flawlessly (thanks to devs for that!). However, I have now run into a performance issue.

My levels consist of several large static polygon bodies. The only actor so far is a sphere controlled by the player. I have now tried to add kinematic level objects. Thus, I have added a kinematic object. As long as the object is sleeping, the performance is perfect, with world.step taking around 1ms. However, as soon as I active the object by setting its AngularVelocity, the time for world.step goes up to around 16ms. If I remove the other level objects, the performance impact is far less pronounced. Shouldn't the performance of kinematic objects be independent of the number of static objects? Enabling and disabling CCD has little influence on the performance.

The added object looks like this: http://www.abload.de/img/shape0t9s.png  It consists of 196 triangles. The EAR Decomposer creates 96 convex fixtures for it. Could the high number of fixtures be a problem? Is there anything I'm overlooking that could lead to this massive performance decrease?

Thank you very much in advance for any suggestions as to overcome this issue.

Best regards,
Bartl

Edit: I did some snooping around with SlimTune and it appears that a lot of time is spent in Body.SynchronizeFixtures. So I guess the problem is indeed the large number of Fixtures per Body. Is there a good way to circumvent this?

May 23, 2011 at 7:14 PM

Bump.

I've had some time to looker deeper into the issue and I've had some success. I have tried using a LoopShape to avoid the large number of fixtures, only to find that that also creates a fixture for each edge of the polygon. I am pretty sure now that problem lies with the broadphase tree. The engine spends a lot of time each frame updating the tree, but hardly anything ever collides with the shapes.

To prove my point, I made a subclass of LoopShape, that only reports a single child shape and returns the AABB of the entire polygon. Then, I modified Contact.cs and added the following code:

case ContactType.LoopAndCircle:
	LoopShape loop = (LoopShape)FixtureA.Shape;
	if (FixtureA.Shape is StaticLoopShape)
	{
		manifold.PointCount = 0;

		StaticLoopShape sloop = (StaticLoopShape)loop;
		for (int i = 0; i < sloop.Vertices.Count; i++)
		{
			loop.GetChildEdge(ref _edge, i);
			Manifold m=new Manifold();
			Collision.Collision.CollideEdgeAndCircle(ref m, _edge, ref transformA,
													 (CircleShape)FixtureB.Shape, ref transformB);
			if (m.PointCount > 0)			
				manifold = m;			
		}
	}
	else
	...

So instead of relying on the broad phase, the individual edges are now checked in the narrow phase. As I will never have more than four dynamic objects, this is vastly faster than updating the tree 200 times each frame. However, this code obviously doesn't work properly either: Only one contact manifold is returned and thus by CircleShape passes through the polygon when there should be more than one contact.

I'm really at the end of wits as to how to solve this conundrum. I really don't want to switch engines, because yours is really nice, but I don't want to restructure the entire engine either. I would really appreciate it, if you would share some ideas or at least tell me that I'm wasting my time.

Thank you very much in advance and best regards,
Bartl