mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 20:34:07 +02:00
Merge pull request #6796 from AndrewMeadows/collision-groups
entity collision masks can be set via script
This commit is contained in:
commit
6f85ee135f
20 changed files with 261 additions and 106 deletions
|
@ -106,7 +106,7 @@ var GRABBABLE_PROPERTIES = [
|
|||
"position",
|
||||
"rotation",
|
||||
"gravity",
|
||||
"ignoreForCollisions",
|
||||
"collisionMask",
|
||||
"collisionsWillMove",
|
||||
"locked",
|
||||
"name"
|
||||
|
@ -117,7 +117,6 @@ var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js
|
|||
|
||||
var DEFAULT_GRABBABLE_DATA = {
|
||||
grabbable: true,
|
||||
invertSolidWhileHeld: false
|
||||
};
|
||||
|
||||
|
||||
|
@ -164,6 +163,11 @@ var POINT_HAND_STATES = [STATE_NEAR_TRIGGER, STATE_CONTINUE_NEAR_TRIGGER, STATE_
|
|||
var FAR_GRASP_HAND_STATES = [STATE_DISTANCE_HOLDING, STATE_CONTINUE_DISTANCE_HOLDING];
|
||||
// otherwise grasp
|
||||
|
||||
// collision masks are specified by comma-separated list of group names
|
||||
// the possible list of names is: static, dynamic, kinematic, myAvatar, otherAvatar
|
||||
var COLLISION_MASK_WHILE_GRABBED = "dynamic,otherAvatar";
|
||||
|
||||
|
||||
function stateToName(state) {
|
||||
switch (state) {
|
||||
case STATE_OFF:
|
||||
|
@ -1823,7 +1827,6 @@ function MyController(hand) {
|
|||
|
||||
this.activateEntity = function(entityID, grabbedProperties) {
|
||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA);
|
||||
var invertSolidWhileHeld = grabbableData["invertSolidWhileHeld"];
|
||||
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
|
||||
data["activated"] = true;
|
||||
data["avatarId"] = MyAvatar.sessionUUID;
|
||||
|
@ -1831,18 +1834,16 @@ function MyController(hand) {
|
|||
// zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done
|
||||
if (data["refCount"] == 1) {
|
||||
data["gravity"] = grabbedProperties.gravity;
|
||||
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
|
||||
data["collisionMask"] = grabbedProperties.collisionMask;
|
||||
data["collisionsWillMove"] = grabbedProperties.collisionsWillMove;
|
||||
var whileHeldProperties = {
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}
|
||||
},
|
||||
"collisionMask": COLLISION_MASK_WHILE_GRABBED
|
||||
};
|
||||
if (invertSolidWhileHeld) {
|
||||
whileHeldProperties["ignoreForCollisions"] = !grabbedProperties.ignoreForCollisions;
|
||||
}
|
||||
Entities.editEntity(entityID, whileHeldProperties);
|
||||
}
|
||||
|
||||
|
@ -1857,7 +1858,7 @@ function MyController(hand) {
|
|||
if (data["refCount"] < 1) {
|
||||
Entities.editEntity(entityID, {
|
||||
gravity: data["gravity"],
|
||||
ignoreForCollisions: data["ignoreForCollisions"],
|
||||
collisionMask: data["collisionMask"],
|
||||
collisionsWillMove: data["collisionsWillMove"]
|
||||
});
|
||||
data = null;
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <PhysicsHelpers.h>
|
||||
#include <PhysicsCollisionGroups.h>
|
||||
#include <PhysicsEngine.h>
|
||||
#include <PhysicsHelpers.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,7 @@ 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);
|
||||
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 +1045,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 +1101,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 +1451,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;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <Octree.h> // for EncodeBitstreamParams class
|
||||
#include <OctreeElement.h> // for OctreeElement::AppendState
|
||||
#include <OctreePacketData.h>
|
||||
#include <PhysicsCollisionGroups.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <Transform.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
|
@ -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) { _collisionMask = 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;
|
||||
|
|
|
@ -116,6 +116,59 @@ void buildStringToShapeTypeLookup() {
|
|||
addShapeType(SHAPE_TYPE_CYLINDER_Z);
|
||||
}
|
||||
|
||||
QString getCollisionGroupAsString(uint8_t group) {
|
||||
switch (group) {
|
||||
case USER_COLLISION_GROUP_DYNAMIC:
|
||||
return "dynamic";
|
||||
case USER_COLLISION_GROUP_STATIC:
|
||||
return "static";
|
||||
case USER_COLLISION_GROUP_KINEMATIC:
|
||||
return "kinematic";
|
||||
case USER_COLLISION_GROUP_MY_AVATAR:
|
||||
return "myAvatar";
|
||||
case USER_COLLISION_GROUP_OTHER_AVATAR:
|
||||
return "otherAvatar";
|
||||
};
|
||||
return "";
|
||||
}
|
||||
|
||||
uint8_t getCollisionGroupAsBitMask(const QStringRef& name) {
|
||||
if (0 == name.compare("dynamic")) {
|
||||
return USER_COLLISION_GROUP_DYNAMIC;
|
||||
} else if (0 == name.compare("static")) {
|
||||
return USER_COLLISION_GROUP_STATIC;
|
||||
} else if (0 == name.compare("kinematic")) {
|
||||
return USER_COLLISION_GROUP_KINEMATIC;
|
||||
} else if (0 == name.compare("myAvatar")) {
|
||||
return USER_COLLISION_GROUP_MY_AVATAR;
|
||||
} else if (0 == name.compare("otherAvatar")) {
|
||||
return USER_COLLISION_GROUP_OTHER_AVATAR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString EntityItemProperties::getCollisionMaskAsString() const {
|
||||
QString maskString("");
|
||||
for (int i = 0; i < NUM_USER_COLLISION_GROUPS; ++i) {
|
||||
uint8_t group = 0x01 << i;
|
||||
if (group & _collisionMask) {
|
||||
maskString.append(getCollisionGroupAsString(group));
|
||||
maskString.append(',');
|
||||
}
|
||||
}
|
||||
return maskString;
|
||||
}
|
||||
|
||||
void EntityItemProperties::setCollisionMaskFromString(const QString& maskString) {
|
||||
QVector<QStringRef> groups = maskString.splitRef(',');
|
||||
uint8_t mask = 0x00;
|
||||
for (auto group : groups) {
|
||||
mask |= getCollisionGroupAsBitMask(group);
|
||||
}
|
||||
_collisionMask = mask;
|
||||
_collisionMaskChanged = true;
|
||||
}
|
||||
|
||||
QString EntityItemProperties::getShapeTypeAsString() const {
|
||||
if (_shapeType < sizeof(shapeTypeNames) / sizeof(char *))
|
||||
return QString(shapeTypeNames[_shapeType]);
|
||||
|
@ -203,6 +256,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 +371,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_GETTER(PROP_COLLISION_MASK, collisionMask, getCollisionMaskAsString());
|
||||
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 +593,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_QSCRITPTVALUE_ENUM(collisionMask, CollisionMask);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionsWillMove, bool, setCollisionsWillMove);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isSpotlight, bool, setIsSpotlight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(intensity, float, setIntensity);
|
||||
|
@ -700,6 +756,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 +1003,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 +1296,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 +1478,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_localRenderAlphaChanged = true;
|
||||
_isSpotlightChanged = true;
|
||||
_ignoreForCollisionsChanged = true;
|
||||
_collisionMaskChanged = true;
|
||||
_collisionsWillMoveChanged = true;
|
||||
|
||||
_intensityChanged = true;
|
||||
|
@ -1537,7 +1597,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 +1713,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (ignoreForCollisionsChanged()) {
|
||||
out += "ignoreForCollisions";
|
||||
}
|
||||
if (collisionMaskChanged()) {
|
||||
out += "collisionMask";
|
||||
}
|
||||
if (collisionsWillMoveChanged()) {
|
||||
out += "collisionsWillMove";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -273,6 +274,10 @@ public:
|
|||
void setJointRotationsDirty() { _jointRotationsSetChanged = true; _jointRotationsChanged = true; }
|
||||
void setJointTranslationsDirty() { _jointTranslationsSetChanged = true; _jointTranslationsChanged = true; }
|
||||
|
||||
protected:
|
||||
QString getCollisionMaskAsString() const;
|
||||
void setCollisionMaskFromString(const QString& maskString);
|
||||
|
||||
private:
|
||||
QUuid _id;
|
||||
bool _idSet;
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITITES_HAVE_QUERY_BOX;
|
||||
return VERSION_ENTITITES_HAVE_COLLISION_MASK;
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SoftAttachmentSupport);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -27,6 +27,9 @@ class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
|
|||
public:
|
||||
ClosestNotMe(btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0f, 0.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f)) {
|
||||
_me = me;
|
||||
// the RayResultCallback's group and mask must match MY_AVATAR
|
||||
m_collisionFilterGroup = BULLET_COLLISION_GROUP_MY_AVATAR;
|
||||
m_collisionFilterMask = BULLET_COLLISION_MASK_MY_AVATAR;
|
||||
}
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) {
|
||||
if (rayResult.m_collisionObject == _me) {
|
||||
|
@ -84,7 +87,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);
|
||||
|
|
|
@ -80,9 +80,9 @@ EntityMotionState::~EntityMotionState() {
|
|||
_entity = nullptr;
|
||||
}
|
||||
|
||||
void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) {
|
||||
void EntityMotionState::updateServerPhysicsVariables() {
|
||||
assert(entityTreeIsLocked());
|
||||
if (_entity->getSimulatorID() == sessionID) {
|
||||
if (_entity->getSimulatorID() == PhysicsEngine::getSessionID()) {
|
||||
// don't slam these values if we are the simulation owner
|
||||
return;
|
||||
}
|
||||
|
@ -96,10 +96,10 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) {
|
|||
}
|
||||
|
||||
// virtual
|
||||
bool EntityMotionState::handleEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
bool EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
assert(entityTreeIsLocked());
|
||||
updateServerPhysicsVariables(engine->getSessionID());
|
||||
ObjectMotionState::handleEasyChanges(flags, engine);
|
||||
updateServerPhysicsVariables();
|
||||
ObjectMotionState::handleEasyChanges(flags);
|
||||
|
||||
if (flags & Simulation::DIRTY_SIMULATOR_ID) {
|
||||
_loopsWithoutOwner = 0;
|
||||
|
@ -113,7 +113,7 @@ bool EntityMotionState::handleEasyChanges(uint32_t& flags, PhysicsEngine* engine
|
|||
_outgoingPriority = NO_PRORITY;
|
||||
} else {
|
||||
_nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) {
|
||||
if (PhysicsEngine::getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) {
|
||||
// we own the simulation or our priority looses to (or ties with) remote
|
||||
_outgoingPriority = NO_PRORITY;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ bool EntityMotionState::handleEasyChanges(uint32_t& flags, PhysicsEngine* engine
|
|||
|
||||
// virtual
|
||||
bool EntityMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
updateServerPhysicsVariables(engine->getSessionID());
|
||||
updateServerPhysicsVariables();
|
||||
return ObjectMotionState::handleHardAndEasyChanges(flags, engine);
|
||||
}
|
||||
|
||||
|
@ -523,6 +523,17 @@ uint32_t EntityMotionState::getIncomingDirtyFlags() {
|
|||
uint32_t dirtyFlags = 0;
|
||||
if (_body && _entity) {
|
||||
dirtyFlags = _entity->getDirtyFlags();
|
||||
|
||||
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();
|
||||
if ((bool)(entityCollisionMask & USER_COLLISION_GROUP_MY_AVATAR) !=
|
||||
(bool)(entityCollisionMask & USER_COLLISION_GROUP_OTHER_AVATAR)) {
|
||||
// bits are asymmetric --> flag for reinsertion in physics simulation
|
||||
dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP;
|
||||
}
|
||||
}
|
||||
// we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings
|
||||
int bodyFlags = _body->getCollisionFlags();
|
||||
bool isMoving = _entity->isMoving();
|
||||
|
@ -610,19 +621,40 @@ 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_DYNAMIC:
|
||||
group = BULLET_COLLISION_GROUP_DYNAMIC;
|
||||
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) {
|
||||
uint8_t entityCollisionMask = _entity->getCollisionMask();
|
||||
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);
|
||||
}
|
||||
return COLLISION_GROUP_DEFAULT;
|
||||
}
|
||||
|
||||
void EntityMotionState::setOutgoingPriority(quint8 priority) {
|
||||
|
|
|
@ -28,8 +28,8 @@ public:
|
|||
EntityMotionState(btCollisionShape* shape, EntityItemPointer item);
|
||||
virtual ~EntityMotionState();
|
||||
|
||||
void updateServerPhysicsVariables(const QUuid& sessionID);
|
||||
virtual bool handleEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
||||
void updateServerPhysicsVariables();
|
||||
virtual bool handleEasyChanges(uint32_t& flags);
|
||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
||||
|
||||
/// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem
|
||||
|
@ -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);
|
||||
|
|
|
@ -62,9 +62,10 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
|||
float offsetLength = offset.length();
|
||||
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (offsetLength > 0) {
|
||||
float speed = (offsetLength > FLT_EPSILON) ? glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED) : 0.0f;
|
||||
float speed = (offsetLength > FLT_EPSILON) ? glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED) : 0.0f;
|
||||
if (speed > rigidBody->getLinearSleepingThreshold()) {
|
||||
targetVelocity = (-speed / offsetLength) * offset;
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
// this action is aggresively critically damped and defeats the current velocity
|
||||
|
@ -90,10 +91,10 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
|||
//
|
||||
// dQ = Q1 * Q0^
|
||||
btQuaternion deltaQ = target * bodyRotation.inverse();
|
||||
float angle = deltaQ.getAngle();
|
||||
const float MIN_ANGLE = 1.0e-4f;
|
||||
if (angle > MIN_ANGLE) {
|
||||
targetVelocity = (angle / _angularTimeScale) * deltaQ.getAxis();
|
||||
float speed = deltaQ.getAngle() / _angularTimeScale;
|
||||
if (speed > rigidBody->getAngularSleepingThreshold()) {
|
||||
targetVelocity = speed * deltaQ.getAxis();
|
||||
rigidBody->activate();
|
||||
}
|
||||
}
|
||||
// this action is aggresively critically damped and defeats the current velocity
|
||||
|
|
|
@ -164,7 +164,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ObjectMotionState::handleEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
if (flags & Simulation::DIRTY_POSITION) {
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
btVector3 newPosition = glmToBullet(getObjectPosition());
|
||||
|
@ -251,7 +251,7 @@ bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine*
|
|||
if ((flags & HARD_DIRTY_PHYSICS_FLAGS) == 0) {
|
||||
// no HARD flags remain, so do any EASY changes
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags, engine);
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine*
|
|||
}
|
||||
}
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags, engine);
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
// it is possible there are no HARD flags at this point (if DIRTY_SHAPE was removed)
|
||||
// so we check again before we reinsert:
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
ObjectMotionState(btCollisionShape* shape);
|
||||
~ObjectMotionState();
|
||||
|
||||
virtual bool handleEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
||||
virtual bool handleEasyChanges(uint32_t& flags);
|
||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
||||
|
||||
void updateBodyMaterialProperties();
|
||||
|
@ -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; }
|
||||
|
||||
|
|
|
@ -22,20 +22,43 @@ uint32_t PhysicsEngine::getNumSubsteps() {
|
|||
return _numSubsteps;
|
||||
}
|
||||
|
||||
btHashMap<btHashInt, int16_t> _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),
|
||||
_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 +162,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();
|
||||
}
|
||||
|
@ -198,7 +222,7 @@ VectorOfMotionStates PhysicsEngine::changeObjects(const VectorOfMotionStates& ob
|
|||
stillNeedChange.push_back(object);
|
||||
}
|
||||
} else if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
if (object->handleEasyChanges(flags, this)) {
|
||||
if (object->handleEasyChanges(flags)) {
|
||||
object->clearIncomingDirtyFlags();
|
||||
} else {
|
||||
stillNeedChange.push_back(object);
|
||||
|
@ -457,11 +481,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];
|
||||
|
|
|
@ -45,14 +45,16 @@ typedef QVector<Collision> CollisionEvents;
|
|||
|
||||
class PhysicsEngine {
|
||||
public:
|
||||
static int16_t getCollisionMask(int16_t group);
|
||||
|
||||
uint32_t getNumSubsteps();
|
||||
|
||||
PhysicsEngine(const glm::vec3& offset);
|
||||
~PhysicsEngine();
|
||||
void init();
|
||||
|
||||
void setSessionUUID(const QUuid& sessionID) { _sessionID = sessionID; }
|
||||
const QUuid& getSessionID() const { return _sessionID; }
|
||||
static void setSessionUUID(const QUuid& sessionID);
|
||||
static const QUuid& getSessionID();
|
||||
|
||||
void removeObjects(const VectorOfMotionStates& objects);
|
||||
void removeObjects(const SetOfMotionStates& objects); // only called during teardown
|
||||
|
@ -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);
|
||||
|
@ -122,12 +122,10 @@ private:
|
|||
bool _dumpNextStats = false;
|
||||
bool _hasOutgoingChanges = false;
|
||||
|
||||
QUuid _sessionID;
|
||||
CollisionEvents _collisionEvents;
|
||||
|
||||
QHash<QUuid, EntityActionPointer> _objectActions;
|
||||
|
||||
btHashMap<btHashInt, int16_t> _collisionMasks;
|
||||
|
||||
uint32_t _numSubsteps;
|
||||
};
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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,60 @@ 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_STATIC = 1 << 0;
|
||||
const int16_t BULLET_COLLISION_GROUP_DYNAMIC = 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);
|
||||
// STATIC does not collide with itself (as optimization of physics simulation)
|
||||
const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_STATIC);
|
||||
|
||||
const int16_t COLLISION_MASK_KINEMATIC = COLLISION_MASK_DEFAULT;
|
||||
const int16_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT;
|
||||
const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_DEFAULT;
|
||||
|
||||
// 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);
|
||||
// MY_AVATAR does not collide with itself
|
||||
const int16_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR);
|
||||
|
||||
// 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_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.
|
||||
// They are not necessarily the same as the BULLET_COLLISION_GROUPS, but we start them off with matching numbers.
|
||||
const uint8_t USER_COLLISION_GROUP_STATIC = 1 << 0;
|
||||
const uint8_t USER_COLLISION_GROUP_DYNAMIC = 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_STATIC |
|
||||
USER_COLLISION_GROUP_DYNAMIC |
|
||||
USER_COLLISION_GROUP_KINEMATIC |
|
||||
USER_COLLISION_GROUP_MY_AVATAR |
|
||||
USER_COLLISION_GROUP_OTHER_AVATAR;
|
||||
|
||||
const uint8_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR;
|
||||
|
||||
const int NUM_USER_COLLISION_GROUPS = 5;
|
||||
|
||||
#endif // hifi_PhysicsCollisionGroups_h
|
||||
|
|
Loading…
Reference in a new issue