diff --git a/libraries/shared/src/Ragdoll.cpp b/libraries/shared/src/Ragdoll.cpp index 7eeaf0b609..70ea63930b 100644 --- a/libraries/shared/src/Ragdoll.cpp +++ b/libraries/shared/src/Ragdoll.cpp @@ -19,7 +19,8 @@ #include "PhysicsSimulation.h" #include "SharedUtil.h" // for EPSILON -Ragdoll::Ragdoll() : _massScale(1.0f), _translation(0.0f), _translationInSimulationFrame(0.0f), _simulation(NULL) { +Ragdoll::Ragdoll() : _massScale(1.0f), _translation(0.0f), _translationInSimulationFrame(0.0f), + _accumulatedMovement(0.0f), _simulation(NULL) { } Ragdoll::~Ragdoll() { @@ -116,3 +117,27 @@ void Ragdoll::setMassScale(float scale) { _massScale = scale; } } + +void Ragdoll::removeRootOffset(bool accumulateMovement) { + const int numPoints = _points.size(); + if (numPoints > 0) { + // shift all points so that the root aligns with the the ragdoll's position in the simulation + glm::vec3 offset = _translationInSimulationFrame - _points[0]._position; + float offsetLength = glm::length(offset); + if (offsetLength > EPSILON) { + for (int i = 0; i < numPoints; ++i) { + _points[i].shift(offset); + } + const float MIN_ROOT_OFFSET = 0.02f; + if (accumulateMovement && offsetLength > MIN_ROOT_OFFSET) { + _accumulatedMovement -= (1.0f - MIN_ROOT_OFFSET / offsetLength) * offset; + } + } + } +} + +glm::vec3 Ragdoll::getAndClearAccumulatedMovement() { + glm::vec3 movement = _accumulatedMovement; + _accumulatedMovement = glm::vec3(0.0f); + return movement; +} diff --git a/libraries/shared/src/Ragdoll.h b/libraries/shared/src/Ragdoll.h index c82295d9a5..1ffbdb29ab 100644 --- a/libraries/shared/src/Ragdoll.h +++ b/libraries/shared/src/Ragdoll.h @@ -56,6 +56,10 @@ public: virtual void initPoints() = 0; virtual void buildConstraints() = 0; + void removeRootOffset(bool accumulateMovement); + + glm::vec3 getAndClearAccumulatedMovement(); + protected: float _massScale; glm::vec3 _translation; // world-frame @@ -66,6 +70,12 @@ protected: QVector _points; QVector _boneConstraints; QVector _fixedConstraints; + + // The collisions are typically done in a simulation frame that is slaved to the center of one of the Ragdolls. + // To allow the Ragdoll to provide feedback of its own displacement we store it in _accumulatedMovement. + // The owner of the Ragdoll can harvest this displacement to update the rest of the object positions in the simulation. + glm::vec3 _accumulatedMovement; + private: void updateSimulationTransforms(const glm::vec3& translation, const glm::quat& rotation);