-
-
Notifications
You must be signed in to change notification settings - Fork 22.8k
Batch the adding of Jolt Physics bodies #107454
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
Conversation
@jrouwe I noticed that I'm assuming the Here's the call stack, if you're curious:
|
30d7824
to
188e600
Compare
Looking through your usages of the BodyInterface:
|
Oops. I forgot about that one.
I suppose this should never have used
Will do.
I don't know if this is all considered too niche of a use-case, but it'd be great to have documented somewhere (either in the code docs or architecture docs) which methods are unsafe for not-yet-added bodies, for future reference. |
Make sure to wake up the body as in JoltBody3D. Note that it is tricky to know when to exactly wake up the body, this is why I added it as a parameter to the BodyInterface::AddForce call. Consider an object held up by constant forces. You'd want the body to be able to go to sleep if it stopped moving, but as soon as the force changes you would want to wake the object up again.
Everything should trigger an assert before crashing. I've fixed up some of the functions where I think it makes sense to call it when the body has not been added yet and added some documentation: |
Before I forget: There is still a case where this new code can fail. If you do:
you would effectivly add single bodies, create a really inefficient broad phase and hit one of the asserts in If you do:
you would be able to make it crash. I will change the |
Yes, for sure.
I'll admit I didn't consider this when I first added the waking up in
That's a good point. I could definitely see someone procedurally building out a level in this way. Wouldn't this also be about correctness though, since you would presumably run into the exact problem that
I'm not sure I follow. Why would this cause a crash? |
I was desperate not to do any dynamic memory allocations when querying, so that's why there is this assert: once you hit it, you skip testing some nodes in the tree which causes the issue mentioned in the ticket. If I were to fall back to a dynamic allocation for this case then there wouldn't be any correctness issues. It would only be very slow (until you step the world and the tree gets rebuilt).
You would be running out of quad tree nodes just like the bug that triggered this PR. But now that I think of it, you'd actually need to ensure that the root node of the quad tree does not contain empty slots for this to trigger, so you'd need to destroy a body that was created more than 4 bodies ago (and all of this without ever stepping the world):
|
Ah, you meant replace the assert with a functioning (but slow) implementation. I misunderstood.
That sounds specific enough that I agree we can just ignore it for now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
…ce during collision queries (#1675) Previously this would trigger an assert and some collisions would not be detected. See discussion at: godotengine/godot#107454
I've merged my change. You could consider taking QuadTree.cpp to improve the robustness of this PR. |
Co-authored-by: Jorrit Rouwe <[email protected]>
I've run this through a couple of different projects now, and I can't spot any obvious regressions. I also created a tool script to do something similar to the MRP in godot-jolt/godot-jolt#833, but with an |
Thanks! |
Fixes #107366.
Supersedes #107396.
This defers the
JPH::BodyInterface::AddBody
call for as long as possible, by batching theJPH::BodyID
s for any objects that are added to a physics space, until the point where they must be added to the simulation, like when stepping it or performing physics queries against it, at which point we useJPH::BodyInterface::AddBodiesPrepare
andJPH::BodyInterface::AddBodiesFinalize
to add all pending objects as a single batchThis means that we (mostly) no longer risk certain problems with Jolt's broad phase, like running out of available nodes or getting a completely unbalanced quadtree, like we do when we add bodies one-by-one, which can cause a number of issues, like the crash seen in #107366.
This replaces the previous
JoltSpace3D::try_optimize
hack, which solved the unbalanced problem, but did so in a fairly crude way.EDIT: This now also includes a partial cherrypick of jrouwe/JoltPhysics#1675.