From a183248f3856a03861958a137af3f23c2c6c82e8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Nov 2014 14:12:26 -0800 Subject: [PATCH 1/3] add updateFoo() methods that accumulate flags about properties that have changed --- libraries/entities/src/EntityItem.cpp | 107 ++++++++++++++++++++++++-- libraries/entities/src/EntityItem.h | 38 ++++++++- 2 files changed, 137 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d0fafa06b1..1ede0b0fa2 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -90,6 +90,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _lastEditedFromRemoteInRemoteTime = 0; _lastUpdated = 0; _created = 0; + _updateFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); _simulationState = EntityItem::Static; @@ -102,6 +103,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _lastEditedFromRemoteInRemoteTime = 0; _lastUpdated = 0; _created = properties.getCreated(); + _updateFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); setProperties(properties, true); // force copy @@ -731,11 +733,6 @@ bool EntityItem::lifetimeHasExpired() const { return isMortal() && (getAge() > getLifetime()); } - -void EntityItem::copyChangedProperties(const EntityItem& other) { - *this = other; -} - EntityItemProperties EntityItem::getProperties() const { EntityItemProperties properties; properties._id = getID(); @@ -947,4 +944,104 @@ void EntityItem::recalculateCollisionShape() { _collisionShape.setScale(entityAACube.getScale()); } +void EntityItem::updatePosition(const glm::vec3& value) { + if (_position != value) { + _position = value; + recalculateCollisionShape(); + _updateFlags |= UPDATE_POSITION; + } +} + +void EntityItem::updatePositionInMeters(const glm::vec3& value) { + glm::vec3 position = glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f); + if (_position != position) { + _position = position; + recalculateCollisionShape(); + _updateFlags |= UPDATE_POSITION; + } +} + +void EntityItem::updateDimensions(const glm::vec3& value) { + if (_dimensions != value) { + _dimensions = value; + recalculateCollisionShape(); + _updateFlags |= UPDATE_SHAPE; + } +} + +void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { + glm::vec3 dimensions = value / (float) TREE_SCALE; + if (_dimensions != dimensions) { + _dimensions = dimensions; + recalculateCollisionShape(); + _updateFlags |= UPDATE_SHAPE; + } +} + +void EntityItem::updateRotation(const glm::quat& rotation) { + if (_rotation != rotation) { + _rotation = rotation; + recalculateCollisionShape(); + _updateFlags |= UPDATE_POSITION; + } +} + +void EntityItem::updateMass(float value) { + if (_mass != value) { + _mass = value; + _updateFlags |= UPDATE_MASS; + } +} + +void EntityItem::updateVelocity(const glm::vec3& value) { + if (_velocity != value) { + _velocity = value; + _updateFlags |= UPDATE_VELOCITY; + } +} + +void EntityItem::updateVelocityInMeters(const glm::vec3& value) { + glm::vec3 velocity = value / (float) TREE_SCALE; + if (_velocity != velocity) { + _velocity = velocity; + _updateFlags |= UPDATE_VELOCITY; + } +} + +void EntityItem::updateGravity(const glm::vec3& value) { + if (_gravity != value) { + _gravity = value; + _updateFlags |= UPDATE_VELOCITY; + } +} + +void EntityItem::updateGravityInMeters(const glm::vec3& value) { + glm::vec3 gravity = value / (float) TREE_SCALE; + if (_gravity != gravity) { + _gravity = gravity; + _updateFlags |= UPDATE_VELOCITY; + } +} + +void EntityItem::updateAngularVelocity(const glm::vec3& value) { + if (_angularVelocity != value) { + _angularVelocity = value; + _updateFlags |= UPDATE_VELOCITY; + } +} + +void EntityItem::updateIgnoreForCollisions(bool value) { + if (_ignoreForCollisions != value) { + _ignoreForCollisions = value; + _updateFlags |= UPDATE_COLLISION; + } +} + +void EntityItem::updateCollisionsWillMove(bool value) { + if (_collisionsWillMove != value) { + _collisionsWillMove = value; + _updateFlags |= UPDATE_COLLISION; + } +} + diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index d57f547cc5..2a818217be 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -35,6 +35,14 @@ class EntityTreeElementExtraEncodeData; #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; #define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { }; +enum EntityUpdateFlags { + UPDATE_POSITION = 0x0001, + UPDATE_VELOCITY = 0x0002, + UPDATE_MASS = 0x0004, + UPDATE_COLLISION = 0x0008, + UPDATE_SHAPE = 0x0010, + //UPDATE_APPEARANCE = 0x8000, +}; /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate @@ -125,9 +133,6 @@ public: virtual void debugDump() const; - // similar to assignment/copy, but it handles keeping lifetime accurate - void copyChangedProperties(const EntityItem& other); - // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0) @@ -266,6 +271,29 @@ public: virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } + // updateFoo() methods to be used when changes need to be accumulated in the _updateFlags + void updatePosition(const glm::vec3& value); + void updatePositionInMeters(const glm::vec3& value); + void updateDimensions(const glm::vec3& value); + void updateDimensionsInMeters(const glm::vec3& value); + void updateRotation(const glm::quat& rotation); + void updateMass(float value); + void updateVelocity(const glm::vec3& value); + void updateVelocityInMeters(const glm::vec3& value); + void updateGravity(const glm::vec3& value); + void updateGravityInMeters(const glm::vec3& value); + void updateAngularVelocity(const glm::vec3& value); + void updateIgnoreForCollisions(bool value); + void updateCollisionsWillMove(bool value); + + void setUpdateFlags(uint32_t mask) { _updateFlags |= mask; } + void clearUpdateFlags(uint32_t mask) { _updateFlags &= ~mask; } + +#ifdef USE_BULLET_PHYSICS + EntityMotionState* getMotionState() const { return _motionState; } + virtual EntityMotionState* createMotionState() { return NULL; } + void destroyMotionState(); +#endif // USE_BULLET_PHYSICS SimulationState getSimulationState() const { return _simulationState; } protected: @@ -314,6 +342,10 @@ protected: AACubeShape _collisionShape; SimulationState _simulationState; // only set by EntityTree + + // UpdateFlags are set whenever a property changes that requires the change to be communicated to other + // data structures. It is the responsibility of the EntityTree to relay changes entity and clear flags. + uint32_t _updateFlags; }; From 97d1dc4200f7fa638999b9a7608129142198ab0d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Nov 2014 15:12:22 -0800 Subject: [PATCH 2/3] use updateFoo() where entity properties need relay clear EntityItem updateFlags when processed --- libraries/entities/src/EntityItem.cpp | 27 ++++++++++++------- libraries/entities/src/EntityItem.h | 6 +++-- .../entities/src/EntityItemPropertiesMacros.h | 11 ++++++++ libraries/entities/src/EntityTree.cpp | 3 ++- libraries/entities/src/EntityTreeElement.cpp | 5 ++-- 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1ede0b0fa2..8c7ef72138 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -467,7 +467,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += propertyFlags.getEncodedLength(); bytesRead += propertyFlags.getEncodedLength(); - READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, _position); + READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePosition); // Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) { @@ -486,7 +486,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } } else { - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, _dimensions); + READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensions); if (wantDebug) { qDebug() << " readEntityDataFromBuffer() NEW FORMAT... look for PROP_DIMENSIONS"; } @@ -496,19 +496,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qDebug() << " readEntityDataFromBuffer() _dimensions:" << getDimensionsInMeters() << " in meters"; } - READ_ENTITY_PROPERTY_QUAT(PROP_ROTATION, _rotation); - READ_ENTITY_PROPERTY(PROP_MASS, float, _mass); - READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, _velocity); - READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, _gravity); + READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation); + READ_ENTITY_PROPERTY_SETTER(PROP_MASS, float, updateMass); + READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity); + READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity); READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping); - READ_ENTITY_PROPERTY(PROP_LIFETIME, float, _lifetime); + READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT,setScript); READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, _registrationPoint); - READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, _angularVelocity); + READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, _angularDamping); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, _visible); - READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions); - READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove); + READ_ENTITY_PROPERTY_SETTER(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions); + READ_ENTITY_PROPERTY_SETTER(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked); READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData); @@ -1044,4 +1044,11 @@ void EntityItem::updateCollisionsWillMove(bool value) { } } +void EntityItem::updateLifetime(float value) { + if (_lifetime != value) { + _lifetime = value; + _updateFlags |= UPDATE_LIFETIME; + } +} + diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2a818217be..5929ab73c6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -41,6 +41,7 @@ enum EntityUpdateFlags { UPDATE_MASS = 0x0004, UPDATE_COLLISION = 0x0008, UPDATE_SHAPE = 0x0010, + UPDATE_LIFETIME = 0x0020 //UPDATE_APPEARANCE = 0x8000, }; @@ -285,9 +286,10 @@ public: void updateAngularVelocity(const glm::vec3& value); void updateIgnoreForCollisions(bool value); void updateCollisionsWillMove(bool value); + void updateLifetime(float value); - void setUpdateFlags(uint32_t mask) { _updateFlags |= mask; } - void clearUpdateFlags(uint32_t mask) { _updateFlags &= ~mask; } + uint32_t getUpdateFlags() const { return _updateFlags; } + void clearUpdateFlags() { _updateFlags = 0; } #ifdef USE_BULLET_PHYSICS EntityMotionState* getMotionState() const { return _motionState; } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 8ad444a975..3288e56a3d 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -63,6 +63,17 @@ } \ } +#define READ_ENTITY_PROPERTY_QUAT_SETTER(P,M) \ + if (propertyFlags.getHasProperty(P)) { \ + glm::quat fromBuffer; \ + int bytes = unpackOrientationQuatFromBytes(dataAt, fromBuffer); \ + dataAt += bytes; \ + bytesRead += bytes; \ + if (overwriteLocalData) { \ + M(fromBuffer); \ + } \ + } + #define READ_ENTITY_PROPERTY_STRING(P,O) \ if (propertyFlags.getHasProperty(P)) { \ uint16_t length; \ diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a0b2d6f9c3..b25b153f44 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -657,12 +657,13 @@ void EntityTree::updateChangedEntities(quint64 now, QSet& entities foreach (EntityItem* thisEntity, _changedEntities) { // check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for thisEntity:" << thisEntity->getEntityItemID(); + qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); clearEntityState(thisEntity); } else { updateEntityState(thisEntity); } + thisEntity->clearUpdateFlags(); } _changedEntities.clear(); } diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 7d4d95bf94..2c189846eb 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -739,8 +739,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); - // TODO: Andrew to only set changed if something has actually changed - _myTree->entityChanged(entityItem); + if (entityItem->getUpdateFlags()) { + _myTree->entityChanged(entityItem); + } bool bestFitAfter = bestFitEntityBounds(entityItem); if (bestFitBefore != bestFitAfter) { From 11e7339e9e07093b971bf5d8235ef851067382c0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Nov 2014 15:52:57 -0800 Subject: [PATCH 3/3] add UPDATE_COLLISION_GROUP and UPDATE_MOTION_TYPE --- libraries/entities/src/EntityItem.cpp | 28 +++++++++++++-------------- libraries/entities/src/EntityItem.h | 21 ++++++++++---------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8c7ef72138..98dda6f33f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -948,7 +948,7 @@ void EntityItem::updatePosition(const glm::vec3& value) { if (_position != value) { _position = value; recalculateCollisionShape(); - _updateFlags |= UPDATE_POSITION; + _updateFlags |= EntityItem::UPDATE_POSITION; } } @@ -957,7 +957,7 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) { if (_position != position) { _position = position; recalculateCollisionShape(); - _updateFlags |= UPDATE_POSITION; + _updateFlags |= EntityItem::UPDATE_POSITION; } } @@ -965,7 +965,7 @@ void EntityItem::updateDimensions(const glm::vec3& value) { if (_dimensions != value) { _dimensions = value; recalculateCollisionShape(); - _updateFlags |= UPDATE_SHAPE; + _updateFlags |= EntityItem::UPDATE_SHAPE; } } @@ -974,7 +974,7 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { if (_dimensions != dimensions) { _dimensions = dimensions; recalculateCollisionShape(); - _updateFlags |= UPDATE_SHAPE; + _updateFlags |= EntityItem::UPDATE_SHAPE; } } @@ -982,21 +982,21 @@ void EntityItem::updateRotation(const glm::quat& rotation) { if (_rotation != rotation) { _rotation = rotation; recalculateCollisionShape(); - _updateFlags |= UPDATE_POSITION; + _updateFlags |= EntityItem::UPDATE_POSITION; } } void EntityItem::updateMass(float value) { if (_mass != value) { _mass = value; - _updateFlags |= UPDATE_MASS; + _updateFlags |= EntityItem::UPDATE_MASS; } } void EntityItem::updateVelocity(const glm::vec3& value) { if (_velocity != value) { _velocity = value; - _updateFlags |= UPDATE_VELOCITY; + _updateFlags |= EntityItem::UPDATE_VELOCITY; } } @@ -1004,14 +1004,14 @@ void EntityItem::updateVelocityInMeters(const glm::vec3& value) { glm::vec3 velocity = value / (float) TREE_SCALE; if (_velocity != velocity) { _velocity = velocity; - _updateFlags |= UPDATE_VELOCITY; + _updateFlags |= EntityItem::UPDATE_VELOCITY; } } void EntityItem::updateGravity(const glm::vec3& value) { if (_gravity != value) { _gravity = value; - _updateFlags |= UPDATE_VELOCITY; + _updateFlags |= EntityItem::UPDATE_VELOCITY; } } @@ -1019,35 +1019,35 @@ void EntityItem::updateGravityInMeters(const glm::vec3& value) { glm::vec3 gravity = value / (float) TREE_SCALE; if (_gravity != gravity) { _gravity = gravity; - _updateFlags |= UPDATE_VELOCITY; + _updateFlags |= EntityItem::UPDATE_VELOCITY; } } void EntityItem::updateAngularVelocity(const glm::vec3& value) { if (_angularVelocity != value) { _angularVelocity = value; - _updateFlags |= UPDATE_VELOCITY; + _updateFlags |= EntityItem::UPDATE_VELOCITY; } } void EntityItem::updateIgnoreForCollisions(bool value) { if (_ignoreForCollisions != value) { _ignoreForCollisions = value; - _updateFlags |= UPDATE_COLLISION; + _updateFlags |= EntityItem::UPDATE_COLLISION_GROUP; } } void EntityItem::updateCollisionsWillMove(bool value) { if (_collisionsWillMove != value) { _collisionsWillMove = value; - _updateFlags |= UPDATE_COLLISION; + _updateFlags |= EntityItem::UPDATE_MOTION_TYPE; } } void EntityItem::updateLifetime(float value) { if (_lifetime != value) { _lifetime = value; - _updateFlags |= UPDATE_LIFETIME; + _updateFlags |= EntityItem::UPDATE_LIFETIME; } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5929ab73c6..3f63c96c4e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -35,22 +35,23 @@ class EntityTreeElementExtraEncodeData; #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; #define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { }; -enum EntityUpdateFlags { - UPDATE_POSITION = 0x0001, - UPDATE_VELOCITY = 0x0002, - UPDATE_MASS = 0x0004, - UPDATE_COLLISION = 0x0008, - UPDATE_SHAPE = 0x0010, - UPDATE_LIFETIME = 0x0020 - //UPDATE_APPEARANCE = 0x8000, -}; - /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate /// one directly, instead you must only construct one of it's derived classes with additional features. class EntityItem { public: + enum EntityUpdateFlags { + UPDATE_POSITION = 0x0001, + UPDATE_VELOCITY = 0x0002, + UPDATE_MASS = 0x0004, + UPDATE_COLLISION_GROUP = 0x0008, + UPDATE_MOTION_TYPE = 0x0010, + UPDATE_SHAPE = 0x0020, + UPDATE_LIFETIME = 0x0040 + //UPDATE_APPEARANCE = 0x8000, + }; + DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly EntityItem(const EntityItemID& entityItemID);