Previous MR change the meaning of mPositionOffset: it is now just a log
of relative movement that were already applied to allow the physics
simulation to catch up, instead of changes that needs to be applied. As
such, after a teleport we need to reset it. Also, since mWorldPosition
is already with the offset we should not update its value in
applyPositionOffset().
Instead of registering the desired change of position and rely on
physics simulation to apply it to the world, immediately change the
position in the world without reset the simulation.
When a script calls SetPos for x,y,z in sequence on an actor, we need to make sure
that the actor will not spawn under ground at x,y coordinates.
Now that change of coordinates are cumulated and applied all at once, we
need to account for the whole offset.
To this end move the terrain height check inside of Actor class.
To make SetPos works with async physics, it was modified to register a
position offset that would be applied to the real position during the
simulation.
A common pattern to teleport NPC in scripts is a sequence of SetPos/Disable/Enable in the same frame.
Since Disable/Enable creates a new physics actor using last known
RefData::Position, the registered offset never get a chance to be applied.
Modify disable() to call moveObject with the offset applied, so that the newly created physics actor will have up-to-date position
When a position is forced, the actor position in physics subsystem is
overriden. The background physics thread is not made aware of this,
its result are simply discarded.
There is a short window where this doesn't work (in this
example, actor is at A and script moves it to B)
1) actor position is set to B. (among others, Actor::mPosition is set to B)
2) physics thread reset Actor::mPosition with stale value (around A)
3) main thread read simulation result, reset Actor::mSkipSimulation flag => actor is at B
4) physics thread fetch latest Actor::mPosition value, which is around A
5) main thread read simulation result, actor is around A
To avoid this situation, do not perform 2) until after 3) occurs. This
way, at 4) starts the simulation with up-to-date Actor::mPosition
Restore projectile caster from savegame (#5860)
See merge request OpenMW/openmw!616
(cherry picked from commit d595c7adb0fb45eafed6d3d0403ad640a91411ed)
c5426bec In the savegame, projectile caster is identified by its actor id. When
This enables accelleration of heightfield collisions.
Unfortunately, `btHeightfieldTerrainShape::processAllTriangle` does not
yet use the accellerator data, so this change does not improve
performance yet but might do so in future bullet versions.
References:
* Accellerator introduced in:
https://github.com/bulletphysics/bullet3/pull/2062
* Feature request to use the accellerator in `processAllTriangle`:
https://github.com/bulletphysics/bullet3/issues/3276
projectile collision shape.
A side effect of moving actors outside of projectile collision shape is that if both the actor and the projectile are
near a wall, the actor could get moved outside of the world.
A prerequisite to create physics objects for statics was to remove the
dependency on base node (since it doesn't yet exists) for object
position. It is still necessary for animation though.
Restore the basenode (and the associated FIXME) so that animated objects works properly.
Since actors can be active in 3x3 grid around the player, we need to
first load all statics in a 5x5 grid around the player.
Split load and unloading in 2 phases. Add an mInactiveCells set into the
scene, which contains all cells inside the aforementioned 5x5 grid.
These cells contains only heightfields and physics objects of static
class.
imprecision issue with projectile collision detection.
Simplify the mechanics: manage hits in one spot.
Give magic projectiles a collision shape similar in size to their visible
model.
Rename the 2 convex result callback to clearly state their purpose.
In this case, the actor mPreviousPosition is not updated, so the actor
position is interpolated between an old (stucked) position and the new
(unstucked) position. The new position is most likely "stucked", so the
unstuck code strikes again, making the actor "vibrates".
That's exactly what the sync code path does, and it doesn't exhibit this
behavior.
What happened is that the last handle to an Actor shared_ptr was a
promoted weak_ptr. When the shared_ptr goes out of scope, the Actor dtor
is invoked. That involves removing the Actor collision object after
exclusively locking mCollisionWorldMutex. In this case, the lock was
already held in the outter scope of the promoted weak_ptr.
Reduce the scope of the mCollisionWorldMutex to never encompass the
lifetime of a promoted weak_ptr.