Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PersistentManifolds and Raycast callbacks cripple performance #8

Open
Kuraperunat opened this issue Jul 12, 2015 · 4 comments
Open

Comments

@Kuraperunat
Copy link

I compiled the latest BulletSharpPInvoke for .NET3.5 by changing few function names to their .NET3.5 variants and I'm using it in Unity5 game engine. Everything is working great, except for few performance bottlenecks.

Using raycasts like e.g.

bt.ClosestRayResultCallback callback = new bt.ClosestRayResultCallback(ref from, ref to);

simWorld.RayTest(from, to, callback);

if (callback.HasHit) {
    //something
}

is causing a large cpu overhead and GC allocation for the callback creation, which seems to take around 5-100x the time used for the actual raycast. This same happens when creating persistent manifold objects and manifold points when e.g. looping through all collisions.

Here's an image from the profiler.
r2742

As far as I know it's not possible to reuse these callback/manifold objects on application level so caching is not a solution. Is there a better way to go around this?

@AndresTraks
Copy link
Owner

Are you sure they can't be reused? Did you try reinitializing all the fields in ClosestRayResultCallback and RayResultCallback similarly to the constructors?

@AndresTraks
Copy link
Owner

I think it's enough to set callback.ClosestHitFraction = 1 (and rewrite RayFromWorld/RayToWorld if necessary).

@Kuraperunat
Copy link
Author

Ok, I managed to reuse the ClosestRayResultCallback with your instructions. callback.hasHit was set to read only so I had assumed there was no way to reuse them. Rewriting rayfrom/rayto and comparing the value of callback.ClosestHitFraction != 1 for determining if there was a hit seems to work as well. Thanks a lot.

What about determining collisions? For example the C# variant of the code for looping through all collision points at http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers has the same problem. e.g.

for (int i = 0; i < simWorld.Dispatcher.NumManifolds; i++) {
    bt.PersistentManifold contactManifold = simWorld.Dispatcher.GetManifoldByIndexInternal(i); // Slow!

    for (int j = 0; j < contactManifold.NumContacts; j++) {
        bt.ManifoldPoint pt = contactManifold.GetContactPoint(j); // Slow!

        // Something
    }
}

is causing same sort of slowdown. I don't think it's possible to reuse these, and using a btGhostObject would also still require calling GetContactPoint. Is there a better way to do this?

@AndresTraks
Copy link
Owner

RayResultCallback.HasHit is defined as "m_collisionObject != 0", so it should become false if you set callback.CollisionObject = null. I just fixed a bug where setting CollisionObject to null crashed, but checking ClosestHitFraction works too.

The documentation says iterating over manifolds is the best way to determine collisions, but I guess that doesn't really hold in C#. I've made a C# version of that page, you can try some of the other methods desribed there:
https://github.com/AndresTraks/BulletSharp/wiki/Collision-Callbacks-and-Triggers
I'll probably do some testing at some point to see what the best method is.

One thing you can do for a small speedup is to cache the NumManifolds/NumContacts values, otherwise the properties are accessed at each iteration and it's a managed-to-unmanaged call, which is slow-ish. It probably has less effect than GetManifoldByIndexInternal/GetContactPoint, but you can see if it helps:

int numManifolds = simWorld.Dispatcher.NumManifolds;
for (int i = 0; i < numManifolds; i++) {
    bt.PersistentManifold contactManifold = simWorld.Dispatcher.GetManifoldByIndexInternal(i); // Slow!

    int numContacts = contactManifold.NumContacts;
    for (int j = 0; j < numContacts; j++) {
        bt.ManifoldPoint pt = contactManifold.GetContactPoint(j); // Slow!

    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants