13-05-2024, 08:07 AM
(This post was last modified: 13-05-2024, 08:27 AM by josemendez.)
(12-05-2024, 09:06 PM)btduser Wrote: As you can see, I am not directly referencing the collider handle - just passing `targetObiCollider` to the API.
That's ok, ObiCollider already contains a reference to its handle. I just mentioned that the handle to that collider is stored by the batch when you call AddConstraint, not that you had to explicitly pass a handle yourself.
(12-05-2024, 09:06 PM)btduser Wrote: Regardless, I noticed that `ObiPinConstraintsBatch.AddConstraint` is doing two things: 1) it tracks the collider handle in pinBodies 2) it caches the current handle index in `colliderIndices`.
Correct, this is what I was talking about in my previous post:
josemendez Wrote:When you create a pin constraint using batch.AddConstraint(), the handle to this collider is stored in the batch. Any subsequent calls to
rope.SetConstraintsDirty(Oni.ConstraintType.Pin); will force the constraints to use whatever collider index is currently stored in the handle
(12-05-2024, 09:06 PM)btduser Wrote: I had originally assumed that `rope.SetConstraintsDirty(Oni.ConstraintType.Pin);` would cause the collision system to update the index value in `colliderIndices`, because it is already keeping track of the handle, but this doesn't actually seem to be happening.
That's exactly what SetConstraintsDirty does: it triggers an update of the collider index (and other data) for all pin constraints.
SetConstraintsDirty activates a "dirty" flag for that specific type of constraint. Next time the solver is updated, the constraint's Merge() method is called for any constraint types that were flagged as dirty. This method takes whatever constraint data is stored in all actors, reorders/batches it together in as few batches as possible for efficient parallelization, and copies their data over to the solver. In case of PinConstraints, this is implemented by ObiPinConstraintsBatch.Merge() which copies whatever collider indices are currently stored in the handles to the solver's constraint arrays.
Note that since SetConstraintsDirty just sets them "dirty" but doesn't actually update them, the change is not immediate and only takes place right before the next physics update.
Also note this means you shouldn't destroy colliders/constraints/particles during the physics update, since this would basically pull the rug from under the solver's feet. Maybe this is what's happening in your case?
A quick summary of what happens under the hood:
- A collider is deleted -> collision system swaps it with the last active collider and reduces the number of active colliders by one -> the collider index for both collider handles is updated.
- Any call to SetConstraintsDirty() tells the solver to update affected constraints at the start of next update.
- As a response to SetConstraintsDirty, constraints.Merge is called which takes the collider index in the handle and copies it over to the solver's constraint arrays.
(12-05-2024, 09:06 PM)btduser Wrote: If the only possible solution is to duplicate the logic in `ObiParticleAttachment.UpdateAttachment`, that's fine. It seems pretty heavy-handed to require every single pin I create to then have to continuously poll for changes instead of having the collision system resolve this internally, which is what I was hoping for.
Attachments only pool for changes to avoid calling rope.SetConstraintsDirty every frame regardless of whether there's been a change - something you could also do. Note there isn't any need to cache the current index and check whether it has changed or not, we do this just to avoid some extra overhead since use cases with thousand of attachments (only case where the cost of polling would show up in profiling) aren't common at all. Either way, the collision system does resolve this internally.
let me know if you need further help.