diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 9ce9594d45..7f11c83c4a 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -9,8 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include +#include +#include #include "Avatar.h" #include "AvatarMotionState.h" @@ -143,7 +144,8 @@ QUuid AvatarMotionState::getSimulatorID() const { } // virtual -int16_t AvatarMotionState::computeCollisionGroup() const { - return COLLISION_GROUP_OTHER_AVATAR; +void AvatarMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const { + group = BULLET_COLLISION_GROUP_OTHER_AVATAR; + mask = PhysicsEngine::getCollisionMask(group); } diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 0465ddf50b..f02dba54bd 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -61,7 +61,7 @@ public: void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; } - virtual int16_t computeCollisionGroup() const override; + virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const; friend class AvatarManager; friend class Avatar; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 97043a635d..c04d280132 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -64,6 +64,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : _angularDamping(ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING), _visible(ENTITY_ITEM_DEFAULT_VISIBLE), _ignoreForCollisions(ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS), + _collisionMask(ENTITY_COLLISION_MASK_DEFAULT), _collisionsWillMove(ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE), _locked(ENTITY_ITEM_DEFAULT_LOCKED), _userData(ENTITY_ITEM_DEFAULT_USER_DATA), @@ -123,6 +124,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_ANGULAR_DAMPING; requestedProperties += PROP_VISIBLE; requestedProperties += PROP_IGNORE_FOR_COLLISIONS; + requestedProperties += PROP_COLLISION_MASK; requestedProperties += PROP_COLLISIONS_WILL_MOVE; requestedProperties += PROP_LOCKED; requestedProperties += PROP_USER_DATA; @@ -259,6 +261,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, getIgnoreForCollisions()); + APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, getCollisionMask()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, getCollisionsWillMove()); APPEND_ENTITY_PROPERTY(PROP_LOCKED, getLocked()); APPEND_ENTITY_PROPERTY(PROP_USER_DATA, getUserData()); @@ -678,6 +681,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions); + if (args.bitstreamVersion >= VERSION_ENTITITES_HAVE_COLLISION_MASK) { + READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, updateCollisionMask); + } READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData); @@ -1041,6 +1047,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha); COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignoreForCollisions, getIgnoreForCollisions); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionMask, getCollisionMask); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionsWillMove, getCollisionsWillMove); COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked); COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData); @@ -1096,6 +1103,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(restitution, updateRestitution); SET_ENTITY_PROPERTY_FROM_PROPERTIES(friction, updateFriction); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, updateIgnoreForCollisions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionMask, updateCollisionMask); SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove); SET_ENTITY_PROPERTY_FROM_PROPERTIES(created, updateCreated); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime); @@ -1445,6 +1453,13 @@ void EntityItem::updateIgnoreForCollisions(bool value) { } } +void EntityItem::updateCollisionMask(uint8_t value) { + if ((_collisionMask & ENTITY_COLLISION_MASK_DEFAULT) != (value & ENTITY_COLLISION_MASK_DEFAULT)) { + _collisionMask = (value & ENTITY_COLLISION_MASK_DEFAULT); + _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; + } +} + void EntityItem::updateCollisionsWillMove(bool value) { if (_collisionsWillMove != value) { _collisionsWillMove = value; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 83f2ad164e..d3b52814a3 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -21,6 +21,7 @@ #include // for EncodeBitstreamParams class #include // for OctreeElement::AppendState #include +#include #include #include #include @@ -273,6 +274,9 @@ public: bool getIgnoreForCollisions() const { return _ignoreForCollisions; } void setIgnoreForCollisions(bool value) { _ignoreForCollisions = value; } + uint8_t getCollisionMask() const { return _collisionMask; } + void setCollisionMask(uint8_t value); + bool getCollisionsWillMove() const { return _collisionsWillMove; } void setCollisionsWillMove(bool value) { _collisionsWillMove = value; } @@ -327,6 +331,7 @@ public: void updateAngularVelocity(const glm::vec3& value); void updateAngularDamping(float value); void updateIgnoreForCollisions(bool value); + void updateCollisionMask(uint8_t value); void updateCollisionsWillMove(bool value); void updateLifetime(float value); void updateCreated(uint64_t value); @@ -440,6 +445,7 @@ protected: float _angularDamping; bool _visible; bool _ignoreForCollisions; + uint8_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT }; bool _collisionsWillMove; bool _locked; QString _userData; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 214f1e5d78..d647896d1f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -203,6 +203,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ANGULAR_VELOCITY, angularVelocity); CHECK_PROPERTY_CHANGE(PROP_ANGULAR_DAMPING, angularDamping); CHECK_PROPERTY_CHANGE(PROP_IGNORE_FOR_COLLISIONS, ignoreForCollisions); + CHECK_PROPERTY_CHANGE(PROP_COLLISION_MASK, collisionMask); CHECK_PROPERTY_CHANGE(PROP_COLLISIONS_WILL_MOVE, collisionsWillMove); CHECK_PROPERTY_CHANGE(PROP_IS_SPOTLIGHT, isSpotlight); CHECK_PROPERTY_CHANGE(PROP_INTENSITY, intensity); @@ -317,6 +318,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_DAMPING, angularDamping); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE, visible); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_FOR_COLLISIONS, ignoreForCollisions); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_MASK, collisionMask); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISIONS_WILL_MOVE, collisionsWillMove); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_HREF, href); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DESCRIPTION, description); @@ -538,6 +540,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel); COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha); COPY_PROPERTY_FROM_QSCRIPTVALUE(ignoreForCollisions, bool, setIgnoreForCollisions); + COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint8_t, setCollisionMask); COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionsWillMove, bool, setCollisionsWillMove); COPY_PROPERTY_FROM_QSCRIPTVALUE(isSpotlight, bool, setIsSpotlight); COPY_PROPERTY_FROM_QSCRIPTVALUE(intensity, float, setIntensity); @@ -700,6 +703,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float); ADD_PROPERTY_TO_MAP(PROP_IGNORE_FOR_COLLISIONS, IgnoreForCollisions, ignoreForCollisions, bool); + ADD_PROPERTY_TO_MAP(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint8_t); ADD_PROPERTY_TO_MAP(PROP_COLLISIONS_WILL_MOVE, CollisionsWillMove, collisionsWillMove, bool); ADD_PROPERTY_TO_MAP(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool); ADD_PROPERTY_TO_MAP(PROP_INTENSITY, Intensity, intensity, float); @@ -946,6 +950,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, properties.getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, properties.getVisible()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, properties.getIgnoreForCollisions()); + APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, properties.getCollisionMask()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, properties.getCollisionsWillMove()); APPEND_ENTITY_PROPERTY(PROP_LOCKED, properties.getLocked()); APPEND_ENTITY_PROPERTY(PROP_USER_DATA, properties.getUserData()); @@ -1238,6 +1243,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_DAMPING, float, setAngularDamping); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_FOR_COLLISIONS, bool, setIgnoreForCollisions); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONS_WILL_MOVE, bool, setCollisionsWillMove); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); @@ -1419,6 +1425,7 @@ void EntityItemProperties::markAllChanged() { _localRenderAlphaChanged = true; _isSpotlightChanged = true; _ignoreForCollisionsChanged = true; + _collisionMaskChanged = true; _collisionsWillMoveChanged = true; _intensityChanged = true; @@ -1537,7 +1544,7 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _collisionsWillMoveChanged || _ignoreForCollisionsChanged; + _compoundShapeURLChanged || _collisionsWillMoveChanged || _ignoreForCollisionsChanged || _collisionMaskChanged; } void EntityItemProperties::clearSimulationOwner() { @@ -1653,6 +1660,9 @@ QList EntityItemProperties::listChangedProperties() { if (ignoreForCollisionsChanged()) { out += "ignoreForCollisions"; } + if (collisionMaskChanged()) { + out += "collisionMask"; + } if (collisionsWillMoveChanged()) { out += "collisionsWillMove"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 35e7bdfb78..46af6a1da9 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -128,6 +128,7 @@ public: DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING); DEFINE_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, IgnoreForCollisions, ignoreForCollisions, bool, ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS); + DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint8_t, ENTITY_COLLISION_MASK_DEFAULT); DEFINE_PROPERTY(PROP_COLLISIONS_WILL_MOVE, CollisionsWillMove, collisionsWillMove, bool, ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE); DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool, false); DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float, 1.0f); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index ad98ca7ba1..860da87705 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -191,6 +191,7 @@ inline quint16 quint16_convertFromScriptValue(const QScriptValue& v, bool& isVal inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); } inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); } inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); } +inline uint8_t uint8_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return (uint8_t)(0xff & v.toVariant().toInt(&isValid)); } inline QString QString_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toString().trimmed(); } inline QUuid QUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); } inline EntityItemID EntityItemID_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); } diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index c59ed7141b..81301cb52d 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -165,6 +165,8 @@ enum EntityPropertyList { PROP_JOINT_TRANSLATIONS_SET, PROP_JOINT_TRANSLATIONS, + PROP_COLLISION_MASK, // one byte of collision group flags + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index c1404178ff..b8637e85cb 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -164,6 +164,7 @@ const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; const PacketVersion VERSION_MODEL_ENTITIES_JOINTS_ON_WIRE = 53; const PacketVersion VERSION_ENTITITES_HAVE_QUERY_BOX = 54; +const PacketVersion VERSION_ENTITITES_HAVE_COLLISION_MASK = 55; enum class AvatarMixerPacketVersion : PacketVersion { TranslationSupport = 17, diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 86d57b7ee9..0797058f05 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -84,7 +84,7 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { // Before adding the RigidBody to the world we must save its oldGravity to the side // because adding an object to the world will overwrite it with the default gravity. btVector3 oldGravity = _rigidBody->getGravity(); - _dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR); + _dynamicsWorld->addRigidBody(_rigidBody, BULLET_COLLISION_GROUP_MY_AVATAR, BULLET_COLLISION_MASK_MY_AVATAR); _dynamicsWorld->addAction(this); // restore gravity settings _rigidBody->setGravity(oldGravity); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c1338b772c..d603fde159 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -610,19 +610,28 @@ QString EntityMotionState::getName() const { } // virtual -int16_t EntityMotionState::computeCollisionGroup() const { - if (_entity->getIgnoreForCollisions()) { - return COLLISION_GROUP_COLLISIONLESS; +void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const { + group = BULLET_COLLISION_GROUP_STATIC; + if (_entity) { + if (_entity->getIgnoreForCollisions()) { + group = BULLET_COLLISION_GROUP_COLLISIONLESS; + } + switch (computeObjectMotionType()){ + case MOTION_TYPE_STATIC: + group = BULLET_COLLISION_GROUP_STATIC; + break; + case MOTION_TYPE_KINEMATIC: + group = BULLET_COLLISION_GROUP_KINEMATIC; + break; + default: + break; + } } - switch (computeObjectMotionType()){ - case MOTION_TYPE_STATIC: - return COLLISION_GROUP_STATIC; - case MOTION_TYPE_KINEMATIC: - return COLLISION_GROUP_KINEMATIC; - default: - break; + + mask = PhysicsEngine::getCollisionMask(group); + if (_entity) { + mask &= (int16_t)(_entity->getCollisionMask()); } - return COLLISION_GROUP_DEFAULT; } void EntityMotionState::setOutgoingPriority(quint8 priority) { diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 53e7982ae1..e543ee024e 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -80,7 +80,7 @@ public: virtual QString getName() const override; - virtual int16_t computeCollisionGroup() const override; + virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const; // eternal logic can suggest a simuator priority bid for the next outgoing update void setOutgoingPriority(quint8 priority); diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index e10d58e3ed..bbdf6c408a 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -136,7 +136,7 @@ public: virtual QString getName() const { return ""; } - virtual int16_t computeCollisionGroup() const = 0; + virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const = 0; bool isActive() const { return _body ? _body->isActive() : false; } diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 9e295d5cf5..b2823746ee 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -22,20 +22,30 @@ 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; +} + PhysicsEngine::PhysicsEngine(const glm::vec3& offset) : _originOffset(offset), _myAvatarController(nullptr) { - // build table of masks with their group as the key - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEFAULT), COLLISION_MASK_DEFAULT); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_STATIC), COLLISION_MASK_STATIC); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_KINEMATIC), COLLISION_MASK_KINEMATIC); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEBRIS), COLLISION_MASK_DEBRIS); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_TRIGGER), COLLISION_MASK_TRIGGER); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_MY_AVATAR), COLLISION_MASK_MY_AVATAR); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_MY_ATTACHMENT), COLLISION_MASK_MY_ATTACHMENT); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_OTHER_AVATAR), COLLISION_MASK_OTHER_AVATAR); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_OTHER_ATTACHMENT), COLLISION_MASK_OTHER_ATTACHMENT); - _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_COLLISIONLESS), COLLISION_MASK_COLLISIONLESS); + initCollisionMaskTable(); } PhysicsEngine::~PhysicsEngine() { @@ -139,8 +149,9 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { body->setFlags(BT_DISABLE_WORLD_GRAVITY); motionState->updateBodyMaterialProperties(); - int16_t group = motionState->computeCollisionGroup(); - _dynamicsWorld->addRigidBody(body, group, getCollisionMask(group)); + int16_t group, mask; + motionState->computeCollisionGroupAndMask(group, mask); + _dynamicsWorld->addRigidBody(body, group, mask); motionState->clearIncomingDirtyFlags(); } @@ -457,11 +468,6 @@ void PhysicsEngine::setCharacterController(CharacterController* character) { } } -int16_t PhysicsEngine::getCollisionMask(int16_t group) const { - const int16_t* mask = _collisionMasks.find(btHashInt((int)group)); - return mask ? *mask : COLLISION_MASK_DEFAULT; -} - EntityActionPointer PhysicsEngine::getActionByID(const QUuid& actionID) const { if (_objectActions.contains(actionID)) { return _objectActions[actionID]; diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 0ca9b2aca8..b2a44b7a3c 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -45,6 +45,8 @@ typedef QVector CollisionEvents; class PhysicsEngine { public: + static int16_t getCollisionMask(int16_t group); + uint32_t getNumSubsteps(); PhysicsEngine(const glm::vec3& offset); @@ -88,8 +90,6 @@ public: void dumpNextStats() { _dumpNextStats = true; } - int16_t getCollisionMask(int16_t group) const; - EntityActionPointer getActionByID(const QUuid& actionID) const; void addAction(EntityActionPointer action); void removeAction(const QUuid actionID); @@ -127,7 +127,6 @@ private: QHash _objectActions; - btHashMap _collisionMasks; uint32_t _numSubsteps; }; diff --git a/libraries/shared/src/PhysicsCollisionGroups.h b/libraries/shared/src/PhysicsCollisionGroups.h index 42599a1b28..67862b7983 100644 --- a/libraries/shared/src/PhysicsCollisionGroups.h +++ b/libraries/shared/src/PhysicsCollisionGroups.h @@ -14,8 +14,8 @@ #include -/* Note: These are the Bullet collision groups defined in btBroadphaseProxy. Only - * DefaultFilter and StaticFilter are explicitly used by Bullet (when the collision +/* Note: These are the Bullet collision groups defined in btBroadphaseProxy. Only + * DefaultFilter and StaticFilter are explicitly used by Bullet (when the collision * filter of an object is not manually specified), the rest are merely suggestions. * enum CollisionFilterGroups { @@ -28,52 +28,54 @@ enum CollisionFilterGroups { AllFilter = -1 } * - * When using custom collision filters we pretty much need to do all or nothing. - * We'll be doing it all which means we define our own groups and build custom masks + * When using custom collision filters we pretty much need to do all or nothing. + * We'll be doing it all which means we define our own groups and build custom masks * for everything. * */ -const int16_t COLLISION_GROUP_DEFAULT = 1 << 0; -const int16_t COLLISION_GROUP_STATIC = 1 << 1; -const int16_t COLLISION_GROUP_KINEMATIC = 1 << 2; -const int16_t COLLISION_GROUP_DEBRIS = 1 << 3; -const int16_t COLLISION_GROUP_TRIGGER = 1 << 4; -const int16_t COLLISION_GROUP_MY_AVATAR = 1 << 5; -const int16_t COLLISION_GROUP_OTHER_AVATAR = 1 << 6; -const int16_t COLLISION_GROUP_MY_ATTACHMENT = 1 << 7; -const int16_t COLLISION_GROUP_OTHER_ATTACHMENT = 1 << 8; +const int16_t BULLET_COLLISION_GROUP_DYNAMIC = 1 << 0; +const int16_t BULLET_COLLISION_GROUP_STATIC = 1 << 1; +const int16_t BULLET_COLLISION_GROUP_KINEMATIC = 1 << 2; +const int16_t BULLET_COLLISION_GROUP_MY_AVATAR = 1 << 3; +const int16_t BULLET_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; // ... -const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 14; +const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14; -/* Note: In order for objectA to collide with objectB at the filter stage +/* Note: In order for objectA to collide with objectB at the filter stage * both (groupA & maskB) and (groupB & maskA) must be non-zero. */ -// DEFAULT collides with everything except COLLISIONLESS -const int16_t COLLISION_MASK_DEFAULT = ~ COLLISION_GROUP_COLLISIONLESS; +// the default collision mask is: collides with everything except collisionless +const int16_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS; -// STATIC also doesn't collide with other STATIC -const int16_t COLLISION_MASK_STATIC = ~ (COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_STATIC); +const int16_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT; -const int16_t COLLISION_MASK_KINEMATIC = COLLISION_MASK_DEFAULT; +// STATIC is special: it collides with everything exept COLLISIONLESS and other STATIC +const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_STATIC); -// DEBRIS also doesn't collide with other DEBRIS, or TRIGGER -const int16_t COLLISION_MASK_DEBRIS = ~ (COLLISION_GROUP_COLLISIONLESS - | COLLISION_GROUP_DEBRIS - | COLLISION_GROUP_TRIGGER); - -// TRIGGER also doesn't collide with DEBRIS, TRIGGER, or STATIC (TRIGGER only detects moveable things that matter) -const int16_t COLLISION_MASK_TRIGGER = COLLISION_MASK_DEBRIS & ~(COLLISION_GROUP_STATIC); - -// AVATAR also doesn't collide with corresponding ATTACHMENTs -const int16_t COLLISION_MASK_MY_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_ATTACHMENT); -const int16_t COLLISION_MASK_MY_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_AVATAR); -const int16_t COLLISION_MASK_OTHER_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_ATTACHMENT); -const int16_t COLLISION_MASK_OTHER_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_AVATAR); +const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_DEFAULT; +const int16_t BULLET_COLLISION_MASK_MY_AVATAR = BULLET_COLLISION_MASK_DEFAULT; +const int16_t BULLET_COLLISION_MASK_OTHER_AVATAR = BULLET_COLLISION_MASK_DEFAULT; // COLLISIONLESS gets an empty mask. -const int16_t COLLISION_MASK_COLLISIONLESS = 0; +const int16_t BULLET_COLLISION_MASK_COLLISIONLESS = 0; + + +// The USER collision groups are exposed to script and can be used to generate per-object collision masks. +const uint8_t USER_COLLISION_GROUP_DYNAMIC = 1 << 0; +const uint8_t USER_COLLISION_GROUP_STATIC = 1 << 1; +const uint8_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2; +const uint8_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3; +const uint8_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; + +const uint8_t ENTITY_COLLISION_MASK_DEFAULT = + USER_COLLISION_GROUP_DYNAMIC | + USER_COLLISION_GROUP_STATIC | + USER_COLLISION_GROUP_KINEMATIC | + USER_COLLISION_GROUP_MY_AVATAR | + USER_COLLISION_GROUP_OTHER_AVATAR; + #endif // hifi_PhysicsCollisionGroups_h