// // EntityMotionState.h // libraries/entities/src // // Created by Andrew Meadows on 2014.11.06 // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #ifndef hifi_EntityMotionState_h #define hifi_EntityMotionState_h #include #include #include #include "ObjectMotionState.h" // From the MotionState's perspective: // Inside = physics simulation // Outside = external agents (scripts, user interaction, other simulations) class EntityMotionState : public ObjectMotionState { public: enum class OwnershipState { NotLocallyOwned = 0, PendingBid, LocallyOwned, Unownable }; EntityMotionState() = delete; EntityMotionState(btCollisionShape* shape, EntityItemPointer item); virtual ~EntityMotionState(); void handleDeactivation(); virtual void handleEasyChanges(uint32_t& flags) override; virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override; /// \return PhysicsMotionType based on params set in EntityItem virtual PhysicsMotionType computePhysicsMotionType() const override; virtual bool isMoving() const override; // this relays incoming position/rotation to the RigidBody virtual void getWorldTransform(btTransform& worldTrans) const override; // this relays outgoing position/rotation to the EntityItem virtual void setWorldTransform(const btTransform& worldTrans) override; bool shouldSendUpdate(uint32_t simulationStep); void sendBid(OctreeEditPacketSender* packetSender, uint32_t step); void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step); virtual uint32_t getIncomingDirtyFlags() override; virtual void clearIncomingDirtyFlags() override; virtual float getObjectRestitution() const override { return _entity->getRestitution(); } virtual float getObjectFriction() const override { return _entity->getFriction(); } virtual float getObjectLinearDamping() const override { return _entity->getDamping(); } virtual float getObjectAngularDamping() const override { return _entity->getAngularDamping(); } virtual glm::vec3 getObjectPosition() const override { return _entity->getWorldPosition() - ObjectMotionState::getWorldOffset(); } virtual glm::quat getObjectRotation() const override { return _entity->getWorldOrientation(); } virtual glm::vec3 getObjectLinearVelocity() const override { return _entity->getWorldVelocity(); } virtual glm::vec3 getObjectAngularVelocity() const override { return _entity->getWorldAngularVelocity(); } virtual glm::vec3 getObjectGravity() const override { return _entity->getGravity(); } virtual glm::vec3 getObjectLinearVelocityChange() const override; virtual const QUuid getObjectID() const override { return _entity->getID(); } virtual uint8_t getSimulationPriority() const override; virtual QUuid getSimulatorID() const override; virtual void bump(uint8_t priority) override; // getEntity() returns a smart-pointer by reference because it is only ever used // to insert into lists of smart pointers, and the lists will make their own copies const EntityItemPointer& getEntity() const { return _entity; } void resetMeasuredBodyAcceleration(); void measureBodyAcceleration(); virtual QString getName() const override; virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override; bool shouldSendBid() const; bool isLocallyOwned() const override; bool isLocallyOwnedOrShouldBe() const override; // aka shouldEmitCollisionEvents() friend class PhysicalEntitySimulation; OwnershipState getOwnershipState() const { return _ownershipState; } void setRegion(uint8_t region); void saveKinematicState(btScalar timeStep) override; protected: uint8_t computeFinalBidPriority() const; void updateSendVelocities(); uint64_t getNextBidExpiry() const { return _nextBidExpiry; } void initForBid(); void initForOwned(); void clearOwnershipState() { _ownershipState = OwnershipState::NotLocallyOwned; } void updateServerPhysicsVariables(); bool remoteSimulationOutOfSync(uint32_t simulationStep); void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity void clearObjectVelocities() const; #ifdef WANT_DEBUG_ENTITY_TREE_LOCKS bool entityTreeIsLocked() const; #endif bool isReadyToComputeShape() const override; const btCollisionShape* computeNewShape() override; void setMotionType(PhysicsMotionType motionType) override; // EntityMotionState keeps a SharedPointer to its EntityItem which is only set in the CTOR // and is only cleared in the DTOR EntityItemPointer _entity; // These "_serverFoo" variables represent what we think the server knows. // They are used in two different modes: // // (1) For remotely owned simulation: we store the last values recieved from the server. // When the body comes to rest and goes inactive we slam its final transforms to agree with the last server // update. This to reduce state synchronization errors when the local simulation deviated from remote. // // (2) For locally owned simulation: we store the last values sent to the server, integrated forward over time // according to how we think the server doing it. We calculate the error between the true local transform // and the remote to decide whether to send another update or not. // glm::vec3 _serverPosition; // in simulation-frame (not world-frame) glm::quat _serverRotation; glm::vec3 _serverVelocity; glm::vec3 _serverAngularVelocity; // radians per second glm::vec3 _serverGravity; glm::vec3 _serverAcceleration; QByteArray _serverActionData; glm::vec3 _lastVelocity; glm::vec3 _measuredAcceleration; quint64 _nextBidExpiry { 0 }; float _measuredDeltaTime; uint32_t _lastMeasureStep; uint32_t _lastStep; // last step of server extrapolation OwnershipState _ownershipState { OwnershipState::NotLocallyOwned }; uint8_t _loopsWithoutOwner; mutable uint8_t _accelerationNearlyGravityCount; uint8_t _numInactiveUpdates { 1 }; uint8_t _bumpedPriority { 0 }; // the target simulation priority according to collision history uint8_t _region { workload::Region::INVALID }; bool isServerlessMode(); }; #endif // hifi_EntityMotionState_h