From a92c512c1704814d04d201b6a016b8a6d7671f0d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Jan 2016 19:49:34 -0800 Subject: [PATCH] move collision group/mask calculus into EntityItem --- interface/src/Application.cpp | 6 ++- interface/src/avatar/AvatarMotionState.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 27 ++++++++++++ libraries/entities/src/EntityItem.h | 7 +-- .../entities/src/EntityItemProperties.cpp | 4 +- libraries/physics/src/EntityMotionState.cpp | 41 +++--------------- libraries/physics/src/PhysicsEngine.cpp | 43 +++---------------- libraries/physics/src/PhysicsEngine.h | 27 +++++------- libraries/shared/src/PhysicsHelpers.cpp | 41 ++++++++++++++++-- libraries/shared/src/PhysicsHelpers.h | 11 +++++ 10 files changed, 108 insertions(+), 101 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fa730c5d40..cfe6b1f6aa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -92,6 +92,7 @@ #include #include #include +#include #include #include #include @@ -3135,7 +3136,7 @@ void Application::update(float deltaTime) { PerformanceTimer perfTimer("havestChanges"); if (_physicsEngine->hasOutgoingChanges()) { getEntities()->getTree()->withWriteLock([&] { - _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID()); + _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), Physics::getSessionUUID()); avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges()); }); @@ -4296,6 +4297,9 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) { } void Application::setSessionUUID(const QUuid& sessionUUID) { + // HACK: until we swap the library dependency order between physics and entities + // we cache the sessionID in two distinct places for physics. + Physics::setSessionUUID(sessionUUID); // TODO: remove this one _physicsEngine->setSessionUUID(sessionUUID); } diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 84f276529a..b361ea5e26 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -146,6 +146,6 @@ QUuid AvatarMotionState::getSimulatorID() const { // virtual void AvatarMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const { group = BULLET_COLLISION_GROUP_OTHER_AVATAR; - mask = PhysicsEngine::getCollisionMask(group); + mask = Physics::getDefaultCollisionMask(group); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 093ad33dcb..24314e807d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1507,6 +1507,33 @@ void EntityItem::updateCreated(uint64_t value) { } } +void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const { + // TODO: detect attachment status and adopt group of wearer + if (_collisionless) { + group = BULLET_COLLISION_GROUP_COLLISIONLESS; + mask = 0; + } else { + if (_dynamic) { + group = BULLET_COLLISION_GROUP_DYNAMIC; + } else if (isMoving() || hasActions()) { + group = BULLET_COLLISION_GROUP_KINEMATIC; + } else { + group = BULLET_COLLISION_GROUP_STATIC; + } + + uint8_t userMask = getCollisionMask(); + if ((bool)(userMask & USER_COLLISION_GROUP_MY_AVATAR) != + (bool)(userMask & USER_COLLISION_GROUP_OTHER_AVATAR)) { + // asymmetric avatar collision mask bits + if (!getSimulatorID().isNull() && (!getSimulatorID().isNull()) && getSimulatorID() != Physics::getSessionUUID()) { + // someone else owns the simulation, so we toggle the avatar bits (swap interpretation) + userMask ^= USER_COLLISION_MASK_AVATARS | ~userMask; + } + } + mask = Physics::getDefaultCollisionMask(group) & (int16_t)(userMask); + } +} + void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) { if (wantTerseEditLogging() && (id != _simulationOwner.getID() || priority != _simulationOwner.getPriority())) { qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 9be018183a..67af53615d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -275,9 +275,10 @@ public: void setCollisionless(bool value) { _collisionless = value; } uint8_t getCollisionMask() const { return _collisionMask; } - uint8_t getFinalCollisionMask() const { return _collisionless ? 0 : _collisionMask; } void setCollisionMask(uint8_t value) { _collisionMask = value; } + void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const; + bool getDynamic() const { return _dynamic; } void setDynamic(bool value) { _dynamic = value; } @@ -370,8 +371,8 @@ public: bool clearActions(EntitySimulation* simulation); void setActionData(QByteArray actionData); const QByteArray getActionData() const; - bool hasActions() { return !_objectActions.empty(); } - QList getActionIDs() { return _objectActions.keys(); } + bool hasActions() const { return !_objectActions.empty(); } + QList getActionIDs() const { return _objectActions.keys(); } QVariantMap getActionArguments(const QUuid& actionID) const; void deserializeActions(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0535621c85..a8f476554b 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -162,8 +162,8 @@ QString EntityItemProperties::getCollisionMaskAsString() const { void EntityItemProperties::setCollisionMaskFromString(const QString& maskString) { QVector groups = maskString.splitRef(','); uint8_t mask = 0x00; - for (auto group : groups) { - mask |= getCollisionGroupAsBitMask(group); + for (auto groupName : groups) { + mask |= getCollisionGroupAsBitMask(groupName); } _collisionMask = mask; _collisionMaskChanged = true; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 4e5f942265..5cffd031d0 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -82,7 +82,7 @@ EntityMotionState::~EntityMotionState() { void EntityMotionState::updateServerPhysicsVariables() { assert(entityTreeIsLocked()); - if (_entity->getSimulatorID() == PhysicsEngine::getSessionID()) { + if (_entity->getSimulatorID() == Physics::getSessionUUID()) { // don't slam these values if we are the simulation owner return; } @@ -113,7 +113,7 @@ bool EntityMotionState::handleEasyChanges(uint32_t& flags) { _outgoingPriority = NO_PRORITY; } else { _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; - if (PhysicsEngine::getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) { + if (Physics::getSessionUUID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) { // we own the simulation or our priority looses to (or ties with) remote _outgoingPriority = NO_PRORITY; } @@ -527,7 +527,7 @@ uint32_t EntityMotionState::getIncomingDirtyFlags() { if (dirtyFlags | Simulation::DIRTY_SIMULATOR_ID) { // when SIMULATOR_ID changes we must check for reinterpretation of asymmetric collision mask // bits for the avatar groups (e.g. MY_AVATAR vs OTHER_AVATAR) - uint8_t entityCollisionMask = _entity->getCollisionMask(); + uint8_t entityCollisionMask = _entity->getCollisionless() ? 0 : _entity->getCollisionMask(); if ((bool)(entityCollisionMask & USER_COLLISION_GROUP_MY_AVATAR) != (bool)(entityCollisionMask & USER_COLLISION_GROUP_OTHER_AVATAR)) { // bits are asymmetric --> flag for reinsertion in physics simulation @@ -622,39 +622,8 @@ QString EntityMotionState::getName() const { // virtual void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const { - group = BULLET_COLLISION_GROUP_STATIC; - if (_entity) { - if (_entity->getCollisionless()) { - group = BULLET_COLLISION_GROUP_COLLISIONLESS; - } - switch (computePhysicsMotionType()){ - case MOTION_TYPE_STATIC: - group = BULLET_COLLISION_GROUP_STATIC; - break; - case MOTION_TYPE_DYNAMIC: - group = BULLET_COLLISION_GROUP_DYNAMIC; - break; - case MOTION_TYPE_KINEMATIC: - group = BULLET_COLLISION_GROUP_KINEMATIC; - break; - default: - break; - } - } - - mask = PhysicsEngine::getCollisionMask(group); - if (_entity) { - uint8_t entityCollisionMask = _entity->getFinalCollisionMask(); - if ((bool)(entityCollisionMask & USER_COLLISION_GROUP_MY_AVATAR) != - (bool)(entityCollisionMask & USER_COLLISION_GROUP_OTHER_AVATAR)) { - // asymmetric avatar collision mask bits - if (!_entity->getSimulatorID().isNull() && _entity->getSimulatorID() != PhysicsEngine::getSessionID()) { - // someone else owns the simulation, so we swap the interpretation of the bits - entityCollisionMask ^= USER_COLLISION_MASK_AVATARS | ~entityCollisionMask; - } - } - mask &= (int16_t)(entityCollisionMask); - } + assert(_entity); + _entity->computeCollisionGroupAndFinalMask(group, mask); } void EntityMotionState::setOutgoingPriority(quint8 priority) { diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 691f2b89c5..0a7ef606ba 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -18,47 +18,10 @@ #include "ThreadSafeDynamicsWorld.h" #include "PhysicsLogging.h" -uint32_t PhysicsEngine::getNumSubsteps() { - return _numSubsteps; -} - -btHashMap _collisionMasks; - -void initCollisionMaskTable() { - if (_collisionMasks.size() == 0) { - // build table of masks with their group as the key - _collisionMasks.insert(btHashInt((int)BULLET_COLLISION_GROUP_DYNAMIC), BULLET_COLLISION_MASK_DYNAMIC); - _collisionMasks.insert(btHashInt((int)BULLET_COLLISION_GROUP_STATIC), BULLET_COLLISION_MASK_STATIC); - _collisionMasks.insert(btHashInt((int)BULLET_COLLISION_GROUP_KINEMATIC), BULLET_COLLISION_MASK_KINEMATIC); - _collisionMasks.insert(btHashInt((int)BULLET_COLLISION_GROUP_MY_AVATAR), BULLET_COLLISION_MASK_MY_AVATAR); - _collisionMasks.insert(btHashInt((int)BULLET_COLLISION_GROUP_OTHER_AVATAR), BULLET_COLLISION_MASK_OTHER_AVATAR); - _collisionMasks.insert(btHashInt((int)BULLET_COLLISION_GROUP_COLLISIONLESS), BULLET_COLLISION_MASK_COLLISIONLESS); - } -} - -// static -int16_t PhysicsEngine::getCollisionMask(int16_t group) { - const int16_t* mask = _collisionMasks.find(btHashInt((int)group)); - return mask ? *mask : BULLET_COLLISION_MASK_DEFAULT; -} - -QUuid _sessionID; - -// static -void PhysicsEngine::setSessionUUID(const QUuid& sessionID) { - _sessionID = sessionID; -} - -// static -const QUuid& PhysicsEngine::getSessionID() { - return _sessionID; -} - - PhysicsEngine::PhysicsEngine(const glm::vec3& offset) : _originOffset(offset), + _sessionID(), _myAvatarController(nullptr) { - initCollisionMaskTable(); } PhysicsEngine::~PhysicsEngine() { @@ -90,6 +53,10 @@ void PhysicsEngine::init() { } } +uint32_t PhysicsEngine::getNumSubsteps() { + return _numSubsteps; +} + // private void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { assert(motionState); diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index c42fe2f66e..16c8456e55 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -45,16 +45,11 @@ typedef QVector CollisionEvents; class PhysicsEngine { public: - static int16_t getCollisionMask(int16_t group); - - uint32_t getNumSubsteps(); - PhysicsEngine(const glm::vec3& offset); ~PhysicsEngine(); void init(); - static void setSessionUUID(const QUuid& sessionID); - static const QUuid& getSessionID(); + uint32_t getNumSubsteps(); void removeObjects(const VectorOfMotionStates& objects); void removeObjects(const SetOfMotionStates& objects); // only called during teardown @@ -95,6 +90,8 @@ public: void removeAction(const QUuid actionID); void forEachAction(std::function actor); + void setSessionUUID(const QUuid& sessionID) { _sessionID = sessionID; } + private: void addObjectToDynamicsWorld(ObjectMotionState* motionState); void removeObjectFromDynamicsWorld(ObjectMotionState* motionState); @@ -111,23 +108,21 @@ private: ThreadSafeDynamicsWorld* _dynamicsWorld = NULL; btGhostPairCallback* _ghostPairCallback = NULL; - glm::vec3 _originOffset; - ContactMap _contactMap; - uint32_t _numContactFrames = 0; + CollisionEvents _collisionEvents; + QHash _objectActions; + + glm::vec3 _originOffset; + QUuid _sessionID; - /// character collisions CharacterController* _myAvatarController; + uint32_t _numContactFrames = 0; + uint32_t _numSubsteps; + bool _dumpNextStats = false; bool _hasOutgoingChanges = false; - CollisionEvents _collisionEvents; - - QHash _objectActions; - - - uint32_t _numSubsteps; }; typedef std::shared_ptr PhysicsEnginePointer; diff --git a/libraries/shared/src/PhysicsHelpers.cpp b/libraries/shared/src/PhysicsHelpers.cpp index 578c85683b..18accfd799 100644 --- a/libraries/shared/src/PhysicsHelpers.cpp +++ b/libraries/shared/src/PhysicsHelpers.cpp @@ -11,6 +11,9 @@ #include "PhysicsHelpers.h" #include "NumericalConstants.h" +#include + +#include "PhysicsCollisionGroups.h" // This chunk of code was copied from Bullet-2.82, so we include the Bullet license here: /* @@ -19,12 +22,12 @@ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it freely, + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it freely, * subject to the following restrictions: * - * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. - * If you use this software in a product, an acknowledgment in the product documentation would be appreciated but + * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment in the product documentation would be appreciated but * is not required. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. @@ -56,3 +59,33 @@ glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float time } return glm::quat(cosf(0.5f * speed * timeStep), axis.x, axis.y, axis.z); } +/* end Bullet code derivation*/ + +int16_t Physics::getDefaultCollisionMask(int16_t group) { + switch(group) { + case BULLET_COLLISION_GROUP_STATIC: + return BULLET_COLLISION_MASK_STATIC; + case BULLET_COLLISION_GROUP_DYNAMIC: + return BULLET_COLLISION_MASK_DYNAMIC; + case BULLET_COLLISION_GROUP_KINEMATIC: + return BULLET_COLLISION_MASK_KINEMATIC; + case BULLET_COLLISION_GROUP_MY_AVATAR: + return BULLET_COLLISION_MASK_MY_AVATAR; + case BULLET_COLLISION_GROUP_OTHER_AVATAR: + return BULLET_COLLISION_MASK_OTHER_AVATAR; + default: + break; + }; + return BULLET_COLLISION_MASK_COLLISIONLESS; +} + +QUuid _sessionID; + +void Physics::setSessionUUID(const QUuid& sessionID) { + _sessionID = sessionID; +} + +const QUuid& Physics::getSessionUUID() { + return _sessionID; +} + diff --git a/libraries/shared/src/PhysicsHelpers.h b/libraries/shared/src/PhysicsHelpers.h index 3b6fccdc99..28ded661f0 100644 --- a/libraries/shared/src/PhysicsHelpers.h +++ b/libraries/shared/src/PhysicsHelpers.h @@ -14,6 +14,10 @@ #include #include +#include + +// TODO: move everything in here to the physics library after the physics/entities library +// dependency order is swapped. const int PHYSICS_ENGINE_MAX_NUM_SUBSTEPS = 6; // Bullet will start to "lose time" at 10 FPS. const float PHYSICS_ENGINE_FIXED_SUBSTEP = 1.0f / 90.0f; @@ -21,4 +25,11 @@ const float PHYSICS_ENGINE_FIXED_SUBSTEP = 1.0f / 90.0f; // return incremental rotation (Bullet-style) caused by angularVelocity over timeStep glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float timeStep); +namespace Physics { + int16_t getDefaultCollisionMask(int16_t group); + + void setSessionUUID(const QUuid& sessionID); + const QUuid& getSessionUUID(); +}; + #endif // hifi_PhysicsHelpers_h