I have the repro and I can see the issue.
I can see there is a real bug in that teleporting is not waking up the other bodies that it touches at the destination.
It is an intermittent problem that happens when the body it touches is covered by the same aabb of the scene tree.
Essentially that function should wakeup the body unconditionally. So that's a real bug that needs fixing.
For the effect, I’ll try to fix it, though it may be tricky in the sense that, that kind of teleporting may not be the best way to move a body
I explain it bellow.
For version 4, I made the decision to fully embrace first- and second-order Newtonian mechanics.
This means a body’s state is determined strictly by its velocity and net acceleration.
For example, in this function:
bool ndScene::ValidateContactCache(ndContact* const contact, const ndVector& timestep) const
The code doesn’t check for changes in position. Instead, it checks if the set of contacts has zero velocity and acceleration once transformed into the collision’s local space.
I worked around this by calling invalidate cache instead of just resetting the contact distance, but this introduces a few shortcomings:
Since the update happens during the model update phase, the contacts are already calculated. If a body is teleported, it will still collide with contacts that don’t reflect its new position, because they are generated before teleport.
This may breaks the dynamics, leading to unpredictable behavior.
The body ends up moving based on penetration values from the previous frame.
Large teleport steps are especially problematic, for example,
if a body is moved far away and collides with something at its new position,
it won’t register a collision that frame.
But since the cache was invalidated, new contacts will be calculated in the next frame, which could result in deep penetrations.
to see this behavior, run the demo, and move the camera so that you can see the body sideway.
you will see that when you move the box, it goes into deep penetration, and this is the only thing that makes it recovers. but that is just luck. Other situations may be very undesirable.
are you moving your bodies by teleporting? if so, may I suggest using
void ndBodyDynamic::ApplyImpulsePair(const ndVector& linearImpulseIn, const ndVector& angularImpulseIn, ndFloat32 timestep)
basically, you calculate an impulse by dividing the delta position by the time step and multiply by the body mass and you call that function.
that function accumulate that impulse in the body, without moving it.
then, the solver calculate the correct velocity to realize movement.
it will not work for large teleports, but if you are using teleport to animate background objects, then that's a good way.
the moral is that you should use the right function for the right effect.
if you are doing runtime object placement, that is, moving a body to a position and let is settle.
them SetMatrixUpdateScene is the function to use.
It will move the body and calculate new contacts that will position the bodies and neighbor, base on resolving inter penetration.
if you are doing runtime body animations based of some velocity, that means some continue motion,
For that, ApplyImpulsePair is a better function.
check out demo: ..\ndSandbox\demos\ndBagroundLowLodVehicle.cpp
Sync to get the work around fix.