diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index a5203b5afd..5fc5f7688b 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -17,20 +17,6 @@ #endif // USE_BULLET_PHYSICS #include "EntityMotionState.h" -// TODO: store _worldOffset in a more central location -- VoxelTree and others also need to know about it -// origin of physics simulation in world frame -glm::vec3 _worldOffset(0.0f); - -// static -void EntityMotionState::setWorldOffset(const glm::vec3& offset) { - _worldOffset = offset; -} - -// static -const glm::vec3& getWorldOffset() { - return _worldOffset; -} - EntityMotionState::EntityMotionState(EntityItem* entity) : _entity(entity), _outgoingPhysicsDirtyFlags(0) { @@ -55,14 +41,12 @@ MotionType EntityMotionState::computeMotionType() const { // it is an opportunity for outside code to update the object's simulation position void EntityMotionState::getWorldTransform (btTransform &worldTrans) const { btVector3 pos; - glmToBullet(_entity->getPositionInMeters() - _worldOffset, pos); + glmToBullet(_entity->getPositionInMeters() - ObjectMotionState::getWorldOffset(), pos); worldTrans.setOrigin(pos); btQuaternion rot; glmToBullet(_entity->getRotation(), rot); worldTrans.setRotation(rot); - - applyVelocities(); } // This callback is invoked by the physics simulation at the end of each simulation frame... @@ -72,7 +56,7 @@ void EntityMotionState::setWorldTransform (const btTransform &worldTrans) { if (! (dirytFlags & EntityItem::DIRTY_POSITION)) { glm::vec3 pos; bulletToGLM(worldTrans.getOrigin(), pos); - _entity->setPositionInMeters(pos + _worldOffset); + _entity->setPositionInMeters(pos + ObjectMotionState::getWorldOffset()); glm::quat rot; bulletToGLM(worldTrans.getRotation(), rot); @@ -122,7 +106,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender) { btTransform worldTrans = _body->getWorldTransform(); bulletToGLM(worldTrans.getOrigin(), _sentPosition); - properties.setPosition(_sentPosition); + properties.setPosition(_sentPosition + ObjectMotionState::getWorldOffset()); bulletToGLM(worldTrans.getRotation(), _sentRotation); properties.setRotation(_sentRotation); @@ -144,7 +128,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender) { if (_outgoingPhysicsDirtyFlags & EntityItem::DIRTY_POSITION) { btTransform worldTrans = _body->getWorldTransform(); bulletToGLM(worldTrans.getOrigin(), _sentPosition); - properties.setPosition(_sentPosition); + properties.setPosition(_sentPosition + ObjectMotionState::getWorldOffset()); bulletToGLM(worldTrans.getRotation(), _sentRotation); properties.setRotation(_sentRotation); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index d2151d2da5..562efde87e 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -32,14 +32,6 @@ class EntityItem; class EntityMotionState : public ObjectMotionState { public: - // The WorldOffset is used to keep the positions of objects in the simulation near the origin, to - // reduce numerical error when computing vector differences. In other words: The EntityMotionState - // class translates between the simulation-frame and the world-frame as known by the render pipeline, - // various object trees, etc. The EntityMotionState class uses a static "worldOffset" to help in - // the translations. - static void setWorldOffset(const glm::vec3& offset); - static const glm::vec3& getWorldOffset(); - EntityMotionState(EntityItem* item); virtual ~EntityMotionState(); @@ -62,6 +54,10 @@ public: void sendUpdate(OctreeEditPacketSender* packetSender); + uint32_t getIncomingDirtyFlags() const { return _entity->getDirtyFlags(); } + void clearIncomingDirtyFlags(uint32_t flags) { _entity->clearDirtyFlags(flags); } + void clearConflictingDirtyFlags() { _outgoingDirtyFlags &= ~_entity->getDirtyFlags(); } + protected: EntityItem* _entity; uint32_t _outgoingPhysicsDirtyFlags; diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index bfa1149bc6..b80a996d0c 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -29,6 +29,19 @@ const float MAX_FRICTION = 10.0f; const float DEFAULT_RESTITUTION = 0.0f; +// origin of physics simulation in world frame +glm::vec3 _worldOffset(0.0f); + +// static +void ObjectMotionState::setWorldOffset(const glm::vec3& offset) { + _worldOffset = offset; +} + +// static +const glm::vec3& ObjectMotionState::getWorldOffset() { + return _worldOffset; +} + ObjectMotionState::ObjectMotionState() : _density(DEFAULT_DENSITY), _volume(DEFAULT_VOLUME), @@ -108,6 +121,9 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame, float subStep return true; } + // NOTE: math in done the simulation-frame, which is NOT necessarily the same + // as the world-frame due to _worldOffset + // compute position error glm::vec3 expectedPosition = _sentPosition + dt * (_sentVelocity + (0.5f * dt) * _sentAcceleration); diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index c387bb1dad..1341cb6168 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -43,6 +43,14 @@ class OctreeEditPacketSender; class ObjectMotionState : public btMotionState { public: + // The WorldOffset is used to keep the positions of objects in the simulation near the origin, to + // reduce numerical error when computing vector differences. In other words: The EntityMotionState + // class translates between the simulation-frame and the world-frame as known by the render pipeline, + // various object trees, etc. The EntityMotionState class uses a static "worldOffset" to help in + // the translations. + static void setWorldOffset(const glm::vec3& offset); + static const glm::vec3& getWorldOffset(); + ObjectMotionState(); ~ObjectMotionState(); @@ -71,7 +79,11 @@ public: void getVelocity(glm::vec3& velocityOut) const; void getAngularVelocity(glm::vec3& angularVelocityOut) const; + virtual uint32_t getIncomingDirtyFlags() const = 0; + virtual void clearIncomingDirtyFlags(uint32_t flags) = 0; void clearOutgoingDirtyFlags(uint32_t flags) { _outgoingDirtyFlags &= ~flags; } + virtual void clearConflictingDirtyFlags() = 0; + bool isAtRest() const { return !(_body->isActive()) && _weKnowRecipientHasReceivedNotMoving; } virtual bool shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder) const; virtual void sendUpdate(OctreeEditPacketSender* packetSender) = 0;