diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3a242a28e0..7e02a29813 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2156,7 +2156,7 @@ void Application::init() { _physicsEngine.init(); EntityTree* tree = _entities.getTree(); - _entitySimulation.init(tree, &_physicsEngine, &_shapeManager, &_entityEditSender); + _entitySimulation.init(tree, &_physicsEngine, &_entityEditSender); tree->setSimulation(&_entitySimulation); auto entityScriptingInterface = DependencyManager::get(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 8a627c019c..f5af137710 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -38,6 +38,7 @@ #include "Application.h" #include "Avatar.h" #include "AvatarManager.h" +#include "AvatarMotionState.h" #include "Hand.h" #include "Head.h" #include "Menu.h" @@ -972,6 +973,9 @@ int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) { const float MOVE_DISTANCE_THRESHOLD = 0.001f; _moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD; + if (_moving && _motionState) { + _motionState->addDirtyFlags(EntityItem::DIRTY_POSITION); + } return bytesRead; } @@ -1087,20 +1091,15 @@ void Avatar::setShowDisplayName(bool showDisplayName) { } -// virtual -void Avatar::rebuildSkeletonBody() { - /* TODO: implement this and remove override from MyAvatar (when we have AvatarMotionStates working) - if (_motionState) { - // compute localAABox - const CapsuleShape& capsule = _skeletonModel.getBoundingShape(); - float radius = capsule.getRadius(); - float height = 2.0f * (capsule.getHalfHeight() + radius); - glm::vec3 corner(-radius, -0.5f * height, -radius); - corner += _skeletonModel.getBoundingShapeOffset(); - glm::vec3 scale(2.0f * radius, height, 2.0f * radius); - //_characterController.setLocalBoundingBox(corner, scale); - _motionState->setBoundingBox(corner, scale); - } - */ +// virtual +void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { + const CapsuleShape& capsule = _skeletonModel.getBoundingShape(); + shapeInfo.setCapsuleY(capsule.getRadius(), capsule.getHalfHeight()); + shapeInfo.setOffset(_skeletonModel.getBoundingShapeOffset()); +} + +// virtual +void Avatar::rebuildSkeletonBody() { + DependencyManager::get()->updateAvatarPhysicsShape(getSessionUUID()); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 6dca1f4a7f..0cdaf36099 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -18,11 +18,11 @@ #include #include +#include #include "Hand.h" #include "Head.h" #include "InterfaceConfig.h" -#include "Recorder.h" #include "SkeletonModel.h" #include "world.h" @@ -55,6 +55,7 @@ enum ScreenTintLayer { NUM_SCREEN_TINT_LAYERS }; +class AvatarMotionState; class Texture; class Avatar : public AvatarData { @@ -164,6 +165,10 @@ public: virtual void rebuildSkeletonBody(); + virtual void computeShapeInfo(ShapeInfo& shapeInfo); + + friend class AvatarManager; + signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); @@ -231,7 +236,7 @@ private: int _voiceSphereID; - //AvatarMotionState* _motionState = nullptr; + AvatarMotionState* _motionState = nullptr; }; #endif // hifi_Avatar_h diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7b91d2cf91..0de9f06742 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -174,7 +174,6 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() { // virtual AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { AvatarSharedPointer avatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer); - // TODO: create MotionState for avatar and add to internal lists return avatar; } @@ -184,6 +183,16 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) { if (avatarIterator != _avatarHash.end()) { Avatar* avatar = reinterpret_cast(avatarIterator.value().data()); if (avatar != _myAvatar && avatar->isInitialized()) { + AvatarMotionState* motionState= avatar->_motionState; + if (motionState) { + // clean up physics stuff + motionState->clearObjectBackPointer(); + avatar->_motionState = nullptr; + _avatarMotionStates.remove(motionState); + _motionStatesToAdd.remove(motionState); + _motionStatesToDelete.push_back(motionState); + } + _avatarFades.push_back(avatarIterator.value()); _avatarHash.erase(avatarIterator); } @@ -225,14 +234,28 @@ QVector AvatarManager::getLocalLights() const { } VectorOfMotionStates& AvatarManager::getObjectsToDelete() { + _tempMotionStates.clear(); + _tempMotionStates.swap(_motionStatesToDelete); return _tempMotionStates; } VectorOfMotionStates& AvatarManager::getObjectsToAdd() { + _tempMotionStates.clear(); + + for (auto motionState : _motionStatesToAdd) { + _tempMotionStates.push_back(motionState); + } + _motionStatesToAdd.clear(); return _tempMotionStates; } VectorOfMotionStates& AvatarManager::getObjectsToChange() { + _tempMotionStates.clear(); + for (auto state : _avatarMotionStates) { + if (state->_dirtyFlags > 0) { + _tempMotionStates.push_back(state); + } + } return _tempMotionStates; } @@ -242,3 +265,23 @@ void AvatarManager::handleOutgoingChanges(VectorOfMotionStates& motionStates) { void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) { } +void AvatarManager::updateAvatarPhysicsShape(const QUuid& id) { + AvatarHash::iterator avatarItr = _avatarHash.find(id); + if (avatarItr != _avatarHash.end()) { + Avatar* avatar = static_cast(avatarItr.value().data()); + AvatarMotionState* motionState = avatar->_motionState; + if (motionState) { + motionState->addDirtyFlags(EntityItem::DIRTY_SHAPE); + } else { + ShapeInfo shapeInfo; + avatar->computeShapeInfo(shapeInfo); + btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); + if (shape) { + AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); + avatar->_motionState = motionState; + _motionStatesToAdd.insert(motionState); + _avatarMotionStates.insert(motionState); + } + } + } +} diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index f30b47c066..5f22d5c194 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -59,6 +59,8 @@ public: VectorOfMotionStates& getObjectsToChange(); void handleOutgoingChanges(VectorOfMotionStates& motionStates); void handleCollisionEvents(CollisionEvents& collisionEvents); + + void updateAvatarPhysicsShape(const QUuid& id); public slots: void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; } @@ -83,7 +85,9 @@ private: bool _shouldShowReceiveStats = false; - VectorOfAvatarMotionStates _avatarMotionStates; + SetOfAvatarMotionStates _avatarMotionStates; + SetOfMotionStates _motionStatesToAdd; + VectorOfMotionStates _motionStatesToDelete; VectorOfMotionStates _tempMotionStates; }; diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index cc693ecb66..592bc7685a 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -28,25 +28,27 @@ void AvatarMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* } // virtual -void AvatarMotionState::updateBodyMaterialProperties() { +uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() { + uint32_t dirtyFlags = 0; + if (_body && _avatar) { + dirtyFlags = _dirtyFlags; + _dirtyFlags = 0; + } + return dirtyFlags; } -// virtual -void AvatarMotionState::updateBodyVelocities() { -} - -// virtual -uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() const { - return 0; -} - -// virtual MotionType AvatarMotionState::computeObjectMotionType() const { return _motionType; } // virtual -void AvatarMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) { +btCollisionShape* AvatarMotionState::computeNewShape() { + if (_avatar) { + ShapeInfo shapeInfo; + _avatar->computeShapeInfo(shapeInfo); + return getShapeManager()->getShape(shapeInfo); + } + return nullptr; } // virtual @@ -54,6 +56,16 @@ bool AvatarMotionState::isMoving() const { return false; } +// virtual +void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const { + // TODO: implement this +} + +// virtual +void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) { + // TODO: implement this +} + // These pure virtual methods must be implemented for each MotionState type // and make it possible to implement more complicated methods in this base class. @@ -61,14 +73,17 @@ bool AvatarMotionState::isMoving() const { float AvatarMotionState::getObjectRestitution() const { return 0.5f; } + // virtual float AvatarMotionState::getObjectFriction() const { return 0.5f; } + // virtual float AvatarMotionState::getObjectLinearDamping() const { return 0.5f; } + // virtual float AvatarMotionState::getObjectAngularDamping() const { return 0.5f; @@ -78,10 +93,12 @@ float AvatarMotionState::getObjectAngularDamping() const { glm::vec3 AvatarMotionState::getObjectPosition() const { return glm::vec3(0.0f); } + // virtual glm::quat AvatarMotionState::getObjectRotation() const { return _avatar->getOrientation(); } + // virtual const glm::vec3& AvatarMotionState::getObjectLinearVelocity() const { return _avatar->getVelocity(); @@ -111,6 +128,10 @@ QUuid AvatarMotionState::getSimulatorID() const { void AvatarMotionState::bump() { } -// protected, virtual -void AvatarMotionState::setMotionType(MotionType motionType) { +// virtual +void AvatarMotionState::clearObjectBackPointer() { + ObjectMotionState::clearObjectBackPointer(); + _avatar = nullptr; } + + diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index ea5dc9ae63..04318c6e88 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -12,7 +12,7 @@ #ifndef hifi_AvatarMotionState_h #define hifi_AvatarMotionState_h -#include +#include #include @@ -26,42 +26,53 @@ public: virtual void handleEasyChanges(uint32_t flags); virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); - virtual void updateBodyMaterialProperties(); - virtual void updateBodyVelocities(); - virtual MotionType getMotionType() const { return _motionType; } - virtual uint32_t getAndClearIncomingDirtyFlags() const = 0; + virtual uint32_t getAndClearIncomingDirtyFlags(); - virtual MotionType computeObjectMotionType() const = 0; - virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo) = 0; + virtual MotionType computeObjectMotionType() const; + virtual btCollisionShape* computeNewShape(); + + virtual bool isMoving() const; + + // this relays incoming position/rotation to the RigidBody + virtual void getWorldTransform(btTransform& worldTrans) const; + + // this relays outgoing position/rotation to the EntityItem + virtual void setWorldTransform(const btTransform& worldTrans); - virtual bool isMoving() const = 0; // These pure virtual methods must be implemented for each MotionState type // and make it possible to implement more complicated methods in this base class. - virtual float getObjectRestitution() const = 0; - virtual float getObjectFriction() const = 0; - virtual float getObjectLinearDamping() const = 0; - virtual float getObjectAngularDamping() const = 0; + virtual float getObjectRestitution() const; + virtual float getObjectFriction() const; + virtual float getObjectLinearDamping() const; + virtual float getObjectAngularDamping() const; - virtual glm::vec3 getObjectPosition() const = 0; - virtual glm::quat getObjectRotation() const = 0; - virtual const glm::vec3& getObjectLinearVelocity() const = 0; - virtual const glm::vec3& getObjectAngularVelocity() const = 0; - virtual const glm::vec3& getObjectGravity() const = 0; + virtual glm::vec3 getObjectPosition() const; + virtual glm::quat getObjectRotation() const; + virtual const glm::vec3& getObjectLinearVelocity() const; + virtual const glm::vec3& getObjectAngularVelocity() const; + virtual const glm::vec3& getObjectGravity() const; - virtual const QUuid& getObjectID() const = 0; + virtual const QUuid& getObjectID() const; - virtual QUuid getSimulatorID() const = 0; - virtual void bump() = 0; + virtual QUuid getSimulatorID() const; + virtual void bump(); + + void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal); + + void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; } + + friend class AvatarManager; protected: - virtual void setMotionType(MotionType motionType); + virtual void clearObjectBackPointer(); Avatar* _avatar; + uint32_t _dirtyFlags; }; -typedef QVector VectorOfAvatarMotionStates; +typedef QSet SetOfAvatarMotionStates; #endif // hifi_AvatarMotionState_h diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 3986762f6f..7ce6bdf682 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -39,7 +39,7 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity _loopsSinceOwnershipBid(0), _loopsWithoutOwner(0) { - _type = MOTION_STATE_TYPE_ENTITY; + _type = MOTIONSTATE_TYPE_ENTITY; assert(entity != nullptr); } @@ -98,10 +98,9 @@ void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* ObjectMotionState::handleHardAndEasyChanges(flags, engine); } -void EntityMotionState::clearEntity() { +void EntityMotionState::clearObjectBackPointer() { + ObjectMotionState::clearObjectBackPointer(); _entity = nullptr; - // set the type to INVALID so that external logic that pivots on the type won't try to access _entity - _type = MOTION_STATE_TYPE_INVALID; } MotionType EntityMotionState::computeObjectMotionType() const { @@ -178,10 +177,13 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { #endif } -void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) { +btCollisionShape* EntityMotionState::computeNewShape() { if (_entity) { + ShapeInfo shapeInfo; _entity->computeShapeInfo(shapeInfo); + return getShapeManager()->getShape(shapeInfo); } + return nullptr; } // RELIABLE_SEND_HACK: until we have truly reliable resends of non-moving updates @@ -445,7 +447,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q _lastStep = step; } -uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() const { +uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() { uint32_t dirtyFlags = 0; if (_body && _entity) { dirtyFlags = _entity->getDirtyFlags(); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 6df3965623..fe2223630f 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -43,14 +43,14 @@ public: // this relays outgoing position/rotation to the EntityItem virtual void setWorldTransform(const btTransform& worldTrans); - virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo); + virtual btCollisionShape* computeNewShape(); bool isCandidateForOwnership(const QUuid& sessionID) const; bool remoteSimulationOutOfSync(uint32_t simulationStep); bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID); void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step); - virtual uint32_t getAndClearIncomingDirtyFlags() const; + virtual uint32_t getAndClearIncomingDirtyFlags(); void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; } void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; } @@ -82,8 +82,7 @@ public: friend class PhysicalEntitySimulation; protected: - void clearEntity(); - + virtual void clearObjectBackPointer(); virtual void setMotionType(MotionType motionType); EntityItem* _entity; diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index c5288cfa76..b421df7812 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -140,20 +140,14 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags) { } if (flags & EntityItem::DIRTY_MASS) { - float mass = getMass(); - btVector3 inertia(0.0f, 0.0f, 0.0f); - _body->getCollisionShape()->calculateLocalInertia(mass, inertia); - _body->setMassProps(mass, inertia); - _body->updateInertiaTensor(); + updateBodyMassProperties(); } } void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) { if (flags & EntityItem::DIRTY_SHAPE) { // make sure the new shape is valid - ShapeInfo shapeInfo; - computeObjectShapeInfo(shapeInfo); - btCollisionShape* newShape = getShapeManager()->getShape(shapeInfo); + btCollisionShape* newShape = computeNewShape(); if (!newShape) { qCDebug(physics) << "Warning: failed to generate new shape!"; // failed to generate new shape! --> keep old shape and remove shape-change flag @@ -168,17 +162,21 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* } } getShapeManager()->releaseShape(_shape); - _shape = newShape; - _body->setCollisionShape(_shape); - if (flags & EASY_DIRTY_PHYSICS_FLAGS) { - handleEasyChanges(flags); - } - } else { - if (flags & EASY_DIRTY_PHYSICS_FLAGS) { - handleEasyChanges(flags); + if (_shape != newShape) { + // huh... the shape didn't actually change, so we remove the DIRTY_SHAPE flag + _shape = newShape; + _body->setCollisionShape(_shape); + flags &= ~EntityItem::DIRTY_SHAPE; } } - engine->reinsertObject(this); + if (flags & EASY_DIRTY_PHYSICS_FLAGS) { + handleEasyChanges(flags); + } + // it is possible that there are no HARD flags at this point (if DIRTY_SHAPE was removed) + // so we check again befoe we reinsert: + if (flags & HARD_DIRTY_PHYSICS_FLAGS) { + engine->reinsertObject(this); + } } void ObjectMotionState::updateBodyMaterialProperties() { @@ -193,3 +191,11 @@ void ObjectMotionState::updateBodyVelocities() { setBodyGravity(getObjectGravity()); _body->setActivationState(ACTIVE_TAG); } + +void ObjectMotionState::updateBodyMassProperties() { + float mass = getMass(); + btVector3 inertia(0.0f, 0.0f, 0.0f); + _body->getCollisionShape()->calculateLocalInertia(mass, inertia); + _body->setMassProps(mass, inertia); + _body->updateInertiaTensor(); +} diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 0af051221d..8813a39379 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -30,9 +30,9 @@ enum MotionType { }; enum MotionStateType { - MOTION_STATE_TYPE_INVALID, - MOTION_STATE_TYPE_ENTITY, - MOTION_STATE_TYPE_AVATAR + MOTIONSTATE_TYPE_INVALID, + MOTIONSTATE_TYPE_ENTITY, + MOTIONSTATE_TYPE_AVATAR }; // The update flags trigger two varieties of updates: "hard" which require the body to be pulled @@ -74,8 +74,9 @@ public: virtual void handleEasyChanges(uint32_t flags); virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); - virtual void updateBodyMaterialProperties(); - virtual void updateBodyVelocities(); + void updateBodyMaterialProperties(); + void updateBodyVelocities(); + virtual void updateBodyMassProperties(); MotionStateType getType() const { return _type; } virtual MotionType getMotionType() const { return _motionType; } @@ -90,11 +91,10 @@ public: glm::vec3 getBodyLinearVelocity() const; glm::vec3 getBodyAngularVelocity() const; - virtual uint32_t getAndClearIncomingDirtyFlags() const = 0; + virtual uint32_t getAndClearIncomingDirtyFlags() = 0; virtual MotionType computeObjectMotionType() const = 0; - virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo) = 0; - + virtual btCollisionShape* computeNewShape() = 0; btCollisionShape* getShape() const { return _shape; } btRigidBody* getRigidBody() const { return _body; } @@ -127,10 +127,14 @@ public: friend class PhysicsEngine; protected: - virtual void setMotionType(MotionType motionType); + void setMotionType(MotionType motionType); + + // clearObjectBackPointer() overrrides should call the base method, then actually clear the object back pointer. + virtual void clearObjectBackPointer() { _type = MOTIONSTATE_TYPE_INVALID; } + void setRigidBody(btRigidBody* body); - MotionStateType _type = MOTION_STATE_TYPE_INVALID; // type of MotionState + MotionStateType _type = MOTIONSTATE_TYPE_INVALID; // type of MotionState MotionType _motionType; // type of motion: KINEMATIC, DYNAMIC, or STATIC btCollisionShape* _shape; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 4d4be27df9..94321e3c77 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -24,7 +24,6 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() { void PhysicalEntitySimulation::init( EntityTree* tree, PhysicsEngine* physicsEngine, - ShapeManager* shapeManager, EntityEditPacketSender* packetSender) { assert(tree); setEntityTree(tree); @@ -32,9 +31,6 @@ void PhysicalEntitySimulation::init( assert(physicsEngine); _physicsEngine = physicsEngine; - assert(shapeManager); - _shapeManager = shapeManager; - assert(packetSender); _entityPacketSender = packetSender; } @@ -59,7 +55,7 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) { void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (motionState) { - motionState->clearEntity(); + motionState->clearObjectBackPointer(); entity->setPhysicsInfo(nullptr); _pendingRemoves.insert(motionState); _outgoingChanges.remove(motionState); @@ -108,7 +104,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { if (entity) { entity->setPhysicsInfo(nullptr); } - motionState->clearEntity(); + motionState->clearObjectBackPointer(); } // then delete the objects (aka MotionStates) @@ -134,7 +130,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToDelete() { if (entity) { _pendingAdds.remove(entity); entity->setPhysicsInfo(nullptr); - motionState->clearEntity(); + motionState->clearObjectBackPointer(); } _tempVector.push_back(motionState); } @@ -157,7 +153,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() { } else if (entity->isReadyToComputeShape()) { ShapeInfo shapeInfo; entity->computeShapeInfo(shapeInfo); - btCollisionShape* shape = _shapeManager->getShape(shapeInfo); + btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); if (shape) { EntityMotionState* motionState = new EntityMotionState(shape, entity); entity->setPhysicsInfo(static_cast(motionState)); @@ -191,7 +187,7 @@ void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motio // walk the motionStates looking for those that correspond to entities for (auto stateItr : motionStates) { ObjectMotionState* state = &(*stateItr); - if (state && state->getType() == MOTION_STATE_TYPE_ENTITY) { + if (state && state->getType() == MOTIONSTATE_TYPE_ENTITY) { EntityMotionState* entityState = static_cast(state); EntityItem* entity = entityState->getEntity(); if (entity) { diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 083f8f4212..510b99ebcc 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -23,8 +23,6 @@ #include "PhysicsEngine.h" #include "EntityMotionState.h" -class ShapeManager; - typedef QSet SetOfEntityMotionStates; class PhysicalEntitySimulation :public EntitySimulation { @@ -32,7 +30,7 @@ public: PhysicalEntitySimulation(); ~PhysicalEntitySimulation(); - void init(EntityTree* tree, PhysicsEngine* engine, ShapeManager* shapeManager, EntityEditPacketSender* packetSender); + void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender); protected: // only called by EntitySimulation // overrides for EntitySimulation @@ -62,7 +60,6 @@ private: SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine VectorOfMotionStates _tempVector; // temporary array reference, valid immediately after getObjectsToRemove() (and friends) - ShapeManager* _shapeManager = nullptr; PhysicsEngine* _physicsEngine = nullptr; EntityEditPacketSender* _entityPacketSender = nullptr; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index bfd0b6cb28..b622a37136 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -318,16 +318,16 @@ CollisionEvents& PhysicsEngine::getCollisionEvents() { ObjectMotionState* A = static_cast(contactItr->first._a); ObjectMotionState* B = static_cast(contactItr->first._b); - if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) { + if (A && A->getType() == MOTIONSTATE_TYPE_ENTITY) { QUuid idA = A->getObjectID(); QUuid idB; - if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) { + if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) { idB = B->getObjectID(); } glm::vec3 position = bulletToGLM(contact.getPositionWorldOnB()) + _originOffset; glm::vec3 penetration = bulletToGLM(contact.distance * contact.normalWorldOnB); _collisionEvents.push_back(Collision(type, idA, idB, position, penetration)); - } else if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) { + } else if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) { QUuid idB = B->getObjectID(); glm::vec3 position = bulletToGLM(contact.getPositionWorldOnA()) + _originOffset; // NOTE: we're flipping the order of A and B (so that the first objectID is never NULL) diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index ca812532fa..676cd8c253 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -17,7 +17,7 @@ void ShapeInfo::clear() { _type = SHAPE_TYPE_NONE; - _halfExtents = glm::vec3(0.0f); + _halfExtents = _offset = glm::vec3(0.0f); _doubleHashKey.clear(); } @@ -45,6 +45,7 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString _halfExtents = halfExtents; break; } + _doubleHashKey.clear(); } void ShapeInfo::setBox(const glm::vec3& halfExtents) { @@ -85,6 +86,11 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) { _doubleHashKey.clear(); } +void ShapeInfo::setOffset(const glm::vec3& offset) { + _offset = offset; + _doubleHashKey.clear(); +} + uint32_t ShapeInfo::getNumSubShapes() const { if (_type == SHAPE_TYPE_NONE) { return 0; @@ -190,9 +196,12 @@ const DoubleHashKey& ShapeInfo::getHash() const { for (int j = 0; j < 3; ++j) { // NOTE: 0.49f is used to bump the float up almost half a millimeter // so the cast to int produces a round() effect rather than a floor() - uint32_t floatHash = - DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++); - hash ^= floatHash; + hash ^= DoubleHashKey::hashFunction( + (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), + primeIndex++); + hash ^= DoubleHashKey::hashFunction( + (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f), + primeIndex++); } key.setHash(hash); @@ -201,8 +210,10 @@ const DoubleHashKey& ShapeInfo::getHash() const { for (int j = 0; j < 3; ++j) { // NOTE: 0.49f is used to bump the float up almost half a millimeter // so the cast to int produces a round() effect rather than a floor() - uint32_t floatHash = - DoubleHashKey::hashFunction2((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f)); + uint32_t floatHash = DoubleHashKey::hashFunction2( + (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f)); + floatHash ^= DoubleHashKey::hashFunction2( + (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f)); hash += ~(floatHash << 17); hash ^= (floatHash >> 11); hash += (floatHash << 4); diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index e10cf1a149..62047745bf 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -46,10 +46,12 @@ public: void setEllipsoid(const glm::vec3& halfExtents); void setConvexHulls(const QVector>& points); void setCapsuleY(float radius, float halfHeight); + void setOffset(const glm::vec3& offset); int getType() const { return _type; } const glm::vec3& getHalfExtents() const { return _halfExtents; } + const glm::vec3& getOffset() const { return _offset; } const QVector>& getPoints() const { return _points; } uint32_t getNumSubShapes() const; @@ -68,6 +70,7 @@ public: protected: ShapeType _type = SHAPE_TYPE_NONE; glm::vec3 _halfExtents = glm::vec3(0.0f); + glm::vec3 _offset = glm::vec3(0.0f); DoubleHashKey _doubleHashKey; QVector> _points; // points for convex collision hulls QUrl _url; // url for model of convex collision hulls