From 971804b98eeace4aad6f1fe0bbe859bedabac918 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Nov 2014 16:14:49 -0800 Subject: [PATCH 1/5] name change shinkIfNeeded() -> shrinkIfNeeded() --- libraries/shared/src/PropertyFlags.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/PropertyFlags.h b/libraries/shared/src/PropertyFlags.h index 7614ad7b7c..de05edc076 100644 --- a/libraries/shared/src/PropertyFlags.h +++ b/libraries/shared/src/PropertyFlags.h @@ -92,7 +92,7 @@ public: PropertyFlags operator<<(Enum flag) const; // NOTE: due to the nature of the compact storage of these property flags, and the fact that the upper bound of the - // enum is not know, these operators will only perform their bitwise operations on the set of properties that have + // enum is not known, these operators will only perform their bitwise operations on the set of properties that have // been previously set PropertyFlags& operator^=(const PropertyFlags& other); PropertyFlags& operator^=(Enum flag); @@ -106,7 +106,7 @@ public: private: - void shinkIfNeeded(); + void shrinkIfNeeded(); QBitArray _flags; int _maxFlag; @@ -142,7 +142,7 @@ template inline void PropertyFlags::setHasProperty(Enum fla _flags.setBit(flag, value); if (flag == _maxFlag && !value) { - shinkIfNeeded(); + shrinkIfNeeded(); } } @@ -274,27 +274,27 @@ template inline PropertyFlags& PropertyFlags::operato template inline PropertyFlags& PropertyFlags::operator&=(const PropertyFlags& other) { _flags &= other._flags; - shinkIfNeeded(); + shrinkIfNeeded(); return *this; } template inline PropertyFlags& PropertyFlags::operator&=(Enum flag) { PropertyFlags other(flag); _flags &= other._flags; - shinkIfNeeded(); + shrinkIfNeeded(); return *this; } template inline PropertyFlags& PropertyFlags::operator^=(const PropertyFlags& other) { _flags ^= other._flags; - shinkIfNeeded(); + shrinkIfNeeded(); return *this; } template inline PropertyFlags& PropertyFlags::operator^=(Enum flag) { PropertyFlags other(flag); _flags ^= other._flags; - shinkIfNeeded(); + shrinkIfNeeded(); return *this; } @@ -422,7 +422,7 @@ template inline PropertyFlags PropertyFlags::operator return result; } -template inline void PropertyFlags::shinkIfNeeded() { +template inline void PropertyFlags::shrinkIfNeeded() { int maxFlagWas = _maxFlag; while (_maxFlag >= 0) { if (_flags.testBit(_maxFlag)) { From 114364e37a11e0a9b221a6b76db2a13842ea82a1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Nov 2014 16:39:26 -0800 Subject: [PATCH 2/5] cleanup/optimization of Octree::readElementData() --- libraries/octree/src/Octree.cpp | 40 +++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index e9cf1158fa..f13f832920 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -289,36 +289,26 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { // check the colors mask to see if we have a child to color in if (oneAtBit(colorInPacketMask, i)) { - // create the child if it doesn't exist - if (!destinationElement->getChildAtIndex(i)) { - destinationElement->addChildAtIndex(i); - if (destinationElement->isDirty()) { - _isDirty = true; - } - } + // addChildAtIndex() should actually be called getOrAddChildAtIndex(). + // When it adds the child it automatically sets the detinationElement dirty. + OctreeElement* childElementAt = destinationElement->addChildAtIndex(i); - OctreeElement* childElementAt = destinationElement->getChildAtIndex(i); - bool nodeIsDirty = false; - if (childElementAt) { + int childElementDataRead = childElementAt->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead, args); + childElementAt->setSourceUUID(args.sourceUUID); + + bytesRead += childElementDataRead; + bytesLeftToRead -= childElementDataRead; - int childElementDataRead = childElementAt->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead, args); - childElementAt->setSourceUUID(args.sourceUUID); - - bytesRead += childElementDataRead; - bytesLeftToRead -= childElementDataRead; - - // if we had a local version of the element already, it's possible that we have it already but - // with the same color data, so this won't count as a change. To address this we check the following - if (!childElementAt->isDirty() && childElementAt->getShouldRender() && !childElementAt->isRendered()) { - childElementAt->setDirtyBit(); // force dirty! - } - - nodeIsDirty = childElementAt->isDirty(); - } - if (nodeIsDirty) { + // It's possible that we already had this version of element data, in which case the unpacking of the data + // wouldn't flag childElementAt as dirty, so we manually flag it here... if the element is to be rendered. + if (childElementAt->getShouldRender() && !childElementAt->isRendered()) { + childElementAt->setDirtyBit(); // force dirty! _isDirty = true; } } + if (destinationElement->isDirty()) { + _isDirty = true; + } } unsigned char childrenInTreeMask = ALL_CHILDREN_ASSUMED_TO_EXIST; From af606f01a9418fb76975aaae890e61e8022a47c7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Nov 2014 17:35:44 -0800 Subject: [PATCH 3/5] combined SimulationStates Moving and Changing also funnel entity updates by UDP packet through a single list --- .../entities/RenderableModelEntityItem.cpp | 3 +- libraries/entities/src/BoxEntityItem.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 11 +- libraries/entities/src/EntityItem.h | 17 +- libraries/entities/src/EntityTree.cpp | 178 ++++++------------ libraries/entities/src/EntityTree.h | 17 +- libraries/entities/src/EntityTreeElement.cpp | 11 +- libraries/entities/src/ModelEntityItem.cpp | 6 +- libraries/entities/src/ModelEntityItem.h | 2 +- 9 files changed, 95 insertions(+), 152 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 8d932b121d..7b2856bb18 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -246,8 +246,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsSimulation() const { - SimulationState simulationState = getSimulationState(); - return _needsInitialSimulation || simulationState == Moving || simulationState == Changing; + return _needsInitialSimulation || getSimulationState() == EntityItem::Moving; } EntityItemProperties RenderableModelEntityItem::getProperties() const { diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index 83d6d7eff9..16204f0c16 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -94,4 +94,4 @@ void BoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); -} \ No newline at end of file +} diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d5790d88a7..d0fafa06b1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -92,6 +92,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _created = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); + _simulationState = EntityItem::Static; } EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) { @@ -104,6 +105,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _changedOnServer = 0; initFromEntityItemID(entityItemID); setProperties(properties, true); // force copy + _simulationState = EntityItem::Static; } EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const { @@ -404,7 +406,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qDebug() << " fromSameServerEdit=" << fromSameServerEdit; } - bool ignoreServerPacket = false; // assume we're use this server packet + bool ignoreServerPacket = false; // assume we'll use this server packet // If this packet is from the same server edit as the last packet we accepted from the server // we probably want to use it. @@ -715,13 +717,10 @@ void EntityItem::update(const quint64& updateTime) { } } -EntityItem::SimulationState EntityItem::getSimulationState() const { - if (hasVelocity() || (hasGravity() && !isRestingOnSurface())) { +EntityItem::SimulationState EntityItem::computeSimulationState() const { + if (hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity()) { return EntityItem::Moving; } - if (hasAngularVelocity()) { - return EntityItem::Changing; - } if (isMortal()) { return EntityItem::Mortal; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index cb153dee60..61e929d9b3 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -28,6 +28,7 @@ #include "EntityItemProperties.h" #include "EntityTypes.h" +class EntityTree; class EntityTreeElement; class EntityTreeElementExtraEncodeData; @@ -59,10 +60,10 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - /// returns true is something changed + /// returns true if something changed virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); - /// override this in your derived class if you'd like to be informed when something about the state of the entity + /// Override this in your derived class if you'd like to be informed when something about the state of the entity /// has changed. This will be called with properties change or when new data is loaded from a stream virtual void somethingChangedNotification() { } @@ -115,11 +116,13 @@ public: typedef enum SimulationState_t { Static, Mortal, - Changing, Moving } SimulationState; - virtual SimulationState getSimulationState() const; + // computes the SimulationState that the entity SHOULD be in. + // Use getSimulationState() to find the state under which it is currently categorized. + virtual SimulationState computeSimulationState() const; + virtual void debugDump() const; // similar to assignment/copy, but it handles keeping lifetime accurate @@ -262,8 +265,13 @@ public: void applyHardCollision(const CollisionInfo& collisionInfo); virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } + + SimulationState getSimulationState() const { return _simulationState; } protected: + friend EntityTree; + void setSimulationState(SimulationState state) { _simulationState = state; } + virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init virtual void recalculateCollisionShape(); @@ -305,6 +313,7 @@ protected: void setRadius(float value); AACubeShape _collisionShape; + SimulationState _simulationState; // only set by EntityTree }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 73957ad077..53d040c4a8 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -40,8 +40,8 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) { _entityToElementMap.clear(); Octree::eraseAllOctreeElements(createNewRoot); _movingEntities.clear(); - _changingEntities.clear(); _mortalEntities.clear(); + _changedEntities.clear(); } bool EntityTree::handlesEditPacketType(PacketType packetType) const { @@ -80,7 +80,7 @@ void EntityTree::addEntityItem(EntityItem* entityItem) { EntityItemID entityID = entityItem->getEntityItemID(); EntityTreeElement* containingElement = getContainingElement(entityID); if (containingElement) { - qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing entity items. entityID=" << entityID; + qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing EntityItems. entityID=" << entityID; return; } @@ -89,7 +89,7 @@ void EntityTree::addEntityItem(EntityItem* entityItem) { recurseTreeWithOperator(&theOperator); // check to see if we need to simulate this entity.. - changeEntityState(entityItem, EntityItem::Static, entityItem->getSimulationState()); + changeEntityState(entityItem); _isDirty = true; } @@ -123,15 +123,13 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp } } else { // check to see if we need to simulate this entity... - EntityItem::SimulationState oldState = existingEntity->getSimulationState(); QString entityScriptBefore = existingEntity->getScript(); UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties); recurseTreeWithOperator(&theOperator); _isDirty = true; - EntityItem::SimulationState newState = existingEntity->getSimulationState(); - changeEntityState(existingEntity, oldState, newState); + changeEntityState(existingEntity); QString entityScriptAfter = existingEntity->getScript(); if (entityScriptBefore != entityScriptAfter) { @@ -229,10 +227,6 @@ void EntityTree::removeEntityFromSimulationLists(const EntityItemID& entityID) { // make sure to remove it from any of our simulation lists EntityItem::SimulationState theState = theEntity->getSimulationState(); switch (theState) { - case EntityItem::Changing: - _changingEntities.removeAll(theEntity); - break; - case EntityItem::Moving: _movingEntities.removeAll(theEntity); break; @@ -244,6 +238,7 @@ void EntityTree::removeEntityFromSimulationLists(const EntityItemID& entityID) { default: break; } + _changedEntities.remove(theEntity); } } @@ -518,7 +513,7 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char // search for the entity by EntityItemID EntityItem* existingEntity = findEntityByEntityItemID(entityItemID); - // if the entityItem exists, then update it + // if the EntityItem exists, then update it if (existingEntity) { updateEntity(entityItemID, properties); existingEntity->markAsChangedOnServer(); @@ -580,15 +575,42 @@ void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncod extraEncodeData->clear(); } -void EntityTree::changeEntityState(EntityItem* const entity, - EntityItem::SimulationState oldState, EntityItem::SimulationState newState) { +void EntityTree::changeEntityState(EntityItem* entity) { + EntityItem::SimulationState oldState = entity->getSimulationState(); + EntityItem::SimulationState newState = entity->computeSimulationState(); + if (newState != oldState) { + switch (oldState) { + case EntityItem::Moving: + _movingEntities.removeAll(entity); + break; + + case EntityItem::Mortal: + _mortalEntities.removeAll(entity); + break; + + default: + break; + } + + switch (newState) { + case EntityItem::Moving: + _movingEntities.push_back(entity); + break; + + case EntityItem::Mortal: + _mortalEntities.push_back(entity); + break; + + default: + break; + } + entity->setSimulationState(newState); + } +} - // TODO: can we short circuit this if the state isn't changing? +void EntityTree::clearEntityState(EntityItem* entity) { + EntityItem::SimulationState oldState = entity->getSimulationState(); switch (oldState) { - case EntityItem::Changing: - _changingEntities.removeAll(entity); - break; - case EntityItem::Moving: _movingEntities.removeAll(entity); break; @@ -600,24 +622,11 @@ void EntityTree::changeEntityState(EntityItem* const entity, default: break; } + entity->setSimulationState(EntityItem::Static); +} - - switch (newState) { - case EntityItem::Changing: - _changingEntities.push_back(entity); - break; - - case EntityItem::Moving: - _movingEntities.push_back(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.push_back(entity); - break; - - default: - break; - } +void EntityTree::entityChanged(EntityItem* entity) { + _changedEntities.insert(entity); } void EntityTree::update() { @@ -633,7 +642,7 @@ void EntityTree::update() { lockForWrite(); quint64 now = usecTimestampNow(); QSet entitiesToDelete; - updateChangingEntities(now, entitiesToDelete); + updateChangedEntities(now, entitiesToDelete); updateMovingEntities(now, entitiesToDelete); updateMortalEntities(now, entitiesToDelete); @@ -643,55 +652,25 @@ void EntityTree::update() { unlock(); } -void EntityTree::updateChangingEntities(quint64 now, QSet& entitiesToDelete) { - QSet entitiesBecomingStatic; - QSet entitiesBecomingMortal; - QSet entitiesBecomingMoving; - +void EntityTree::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { // TODO: switch these to iterators so we can remove items that get deleted - for (int i = 0; i < _changingEntities.size(); i++) { - EntityItem* thisEntity = _changingEntities[i]; - thisEntity->update(now); - // always check to see if the lifetime has expired, for immortal entities this is always false + 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 entity:" << thisEntity->getEntityItemID(); + qDebug() << "Lifetime has expired for thisEntity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - entitiesBecomingStatic << thisEntity; + clearEntityState(thisEntity); } else { - // check to see if this entity is no longer moving - EntityItem::SimulationState newState = thisEntity->getSimulationState(); - - if (newState == EntityItem::Static) { - entitiesBecomingStatic << thisEntity; - } else if (newState == EntityItem::Mortal) { - entitiesBecomingMortal << thisEntity; - } else if (newState == EntityItem::Moving) { - entitiesBecomingMoving << thisEntity; - } + changeEntityState(thisEntity); } } - - // change state for any entities that were changing but are now either static, mortal, or moving - foreach(EntityItem* entity, entitiesBecomingStatic) { - changeEntityState(entity, EntityItem::Changing, EntityItem::Static); - } - foreach(EntityItem* entity, entitiesBecomingMortal) { - changeEntityState(entity, EntityItem::Changing, EntityItem::Mortal); - } - foreach(EntityItem* entity, entitiesBecomingMoving) { - changeEntityState(entity, EntityItem::Changing, EntityItem::Moving); - } + _changedEntities.clear(); } void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesToDelete) { PerformanceTimer perfTimer("updateMovingEntities"); if (_movingEntities.size() > 0) { MovingEntitiesOperator moveOperator(this); - - QSet entitiesBecomingStatic; - QSet entitiesBecomingMortal; - QSet entitiesBecomingChanging; - { PerformanceTimer perfTimer("_movingEntities"); @@ -703,7 +682,7 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT if (thisEntity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - entitiesBecomingStatic << thisEntity; + clearEntityState(thisEntity); } else { AACube oldCube = thisEntity->getMaximumAACube(); thisEntity->update(now); @@ -714,19 +693,10 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT if (!domainBounds.touches(newCube)) { qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds."; entitiesToDelete << thisEntity->getEntityItemID(); - entitiesBecomingStatic << thisEntity; + clearEntityState(thisEntity); } else { moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); - - // check to see if this entity is no longer moving - EntityItem::SimulationState newState = thisEntity->getSimulationState(); - if (newState == EntityItem::Changing) { - entitiesBecomingChanging << thisEntity; - } else if (newState == EntityItem::Mortal) { - entitiesBecomingMortal << thisEntity; - } else if (newState == EntityItem::Static) { - entitiesBecomingStatic << thisEntity; - } + changeEntityState(thisEntity); } } } @@ -735,25 +705,10 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT PerformanceTimer perfTimer("recurseTreeWithOperator"); recurseTreeWithOperator(&moveOperator); } - - // change state for any entities that were moving but are now either static, mortal, or changing - foreach(EntityItem* entity, entitiesBecomingStatic) { - changeEntityState(entity, EntityItem::Moving, EntityItem::Static); - } - foreach(EntityItem* entity, entitiesBecomingMortal) { - changeEntityState(entity, EntityItem::Moving, EntityItem::Mortal); - } - foreach(EntityItem* entity, entitiesBecomingChanging) { - changeEntityState(entity, EntityItem::Moving, EntityItem::Changing); - } } } void EntityTree::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { - QSet entitiesBecomingStatic; - QSet entitiesBecomingChanging; - QSet entitiesBecomingMoving; - // TODO: switch these to iterators so we can remove items that get deleted for (int i = 0; i < _mortalEntities.size(); i++) { EntityItem* thisEntity = _mortalEntities[i]; @@ -762,31 +717,12 @@ void EntityTree::updateMortalEntities(quint64 now, QSet& entitiesT if (thisEntity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - entitiesBecomingStatic << thisEntity; + clearEntityState(thisEntity); } else { // check to see if this entity is no longer moving - EntityItem::SimulationState newState = thisEntity->getSimulationState(); - - if (newState == EntityItem::Static) { - entitiesBecomingStatic << thisEntity; - } else if (newState == EntityItem::Changing) { - entitiesBecomingChanging << thisEntity; - } else if (newState == EntityItem::Moving) { - entitiesBecomingMoving << thisEntity; - } + changeEntityState(thisEntity); } } - - // change state for any entities that were mortal but are now either static, changing, or moving - foreach(EntityItem* entity, entitiesBecomingStatic) { - changeEntityState(entity, EntityItem::Mortal, EntityItem::Static); - } - foreach(EntityItem* entity, entitiesBecomingChanging) { - changeEntityState(entity, EntityItem::Mortal, EntityItem::Changing); - } - foreach(EntityItem* entity, entitiesBecomingMoving) { - changeEntityState(entity, EntityItem::Mortal, EntityItem::Moving); - } } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 6fe2d256c2..bf9da5a15d 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -12,6 +12,8 @@ #ifndef hifi_EntityTree_h #define hifi_EntityTree_h +#include + #include #include "EntityTreeElement.h" @@ -135,8 +137,10 @@ public: void sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); - void changeEntityState(EntityItem* const entity, - EntityItem::SimulationState oldState, EntityItem::SimulationState newState); + void changeEntityState(EntityItem* entity); + void clearEntityState(EntityItem* entity); + + void entityChanged(EntityItem* entity); void trackDeletedEntity(const EntityItemID& entityID); @@ -153,7 +157,7 @@ signals: private: - void updateChangingEntities(quint64 now, QSet& entitiesToDelete); + void updateChangedEntities(quint64 now, QSet& entitiesToDelete); void updateMovingEntities(quint64 now, QSet& entitiesToDelete); void updateMortalEntities(quint64 now, QSet& entitiesToDelete); @@ -173,9 +177,10 @@ private: QHash _entityToElementMap; - QList _movingEntities; // entities that are moving as part of update - QList _changingEntities; // entities that are changing (like animating), but not moving - QList _mortalEntities; // entities that are mortal (have lifetime), but not moving or changing + QList _movingEntities; // entities that need to be updated + QList _mortalEntities; // entities that need to be checked for expiry + + QSet _changedEntities; // entities that have changed in the last frame }; #endif // hifi_EntityTree_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 1dea2bcd85..a461df5fde 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -737,14 +737,10 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int QString entityScriptBefore = entityItem->getScript(); bool bestFitBefore = bestFitEntityBounds(entityItem); EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); - EntityItem::SimulationState oldState = entityItem->getSimulationState(); bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); - - EntityItem::SimulationState newState = entityItem->getSimulationState(); - if (oldState != newState) { - _myTree->changeEntityState(entityItem, oldState, newState); - } + // TODO: Andrew to only set changed if something has actually changed + _myTree->entityChanged(entityItem); bool bestFitAfter = bestFitEntityBounds(entityItem); if (bestFitBefore != bestFitAfter) { @@ -771,9 +767,8 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int addEntityItem(entityItem); // add this new entity to this elements entities entityItemID = entityItem->getEntityItemID(); _myTree->setContainingElement(entityItemID, this); + _myTree->changeEntityState(entityItem); _myTree->emitAddingEntity(entityItemID); // we just added an entity - EntityItem::SimulationState newState = entityItem->getSimulationState(); - _myTree->changeEntityState(entityItem, EntityItem::Static, newState); } } // Move the buffer forward to read more entities diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index f50fe7866b..31a0c57f5b 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -371,15 +371,15 @@ bool ModelEntityItem::isAnimatingSomething() const { !getAnimationURL().isEmpty(); } -EntityItem::SimulationState ModelEntityItem::getSimulationState() const { - EntityItem::SimulationState baseClassState = EntityItem::getSimulationState(); +EntityItem::SimulationState ModelEntityItem::computeSimulationState() const { + EntityItem::SimulationState baseClassState = EntityItem::computeSimulationState(); // if the base class is static, then consider our animation state, and upgrade to changing if // we are animating. If the base class has a higher simulation state than static, then // use the base class state. if (baseClassState == EntityItem::Static) { if (isAnimatingSomething()) { - return EntityItem::Changing; + return EntityItem::Moving; } } return baseClassState; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 97ffed4076..0b2508ec80 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -46,7 +46,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData); virtual void update(const quint64& now); - virtual SimulationState getSimulationState() const; + virtual SimulationState computeSimulationState() const; virtual void debugDump() const; From 47615ba9c221ea575eba6a3ee2bbff0703766963 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Nov 2014 17:38:26 -0800 Subject: [PATCH 4/5] changeEntityState() --> updateEntityState() --- libraries/entities/src/EntityTree.cpp | 12 ++++++------ libraries/entities/src/EntityTree.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 53d040c4a8..a0b2d6f9c3 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -89,7 +89,7 @@ void EntityTree::addEntityItem(EntityItem* entityItem) { recurseTreeWithOperator(&theOperator); // check to see if we need to simulate this entity.. - changeEntityState(entityItem); + updateEntityState(entityItem); _isDirty = true; } @@ -129,7 +129,7 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp recurseTreeWithOperator(&theOperator); _isDirty = true; - changeEntityState(existingEntity); + updateEntityState(existingEntity); QString entityScriptAfter = existingEntity->getScript(); if (entityScriptBefore != entityScriptAfter) { @@ -575,7 +575,7 @@ void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncod extraEncodeData->clear(); } -void EntityTree::changeEntityState(EntityItem* entity) { +void EntityTree::updateEntityState(EntityItem* entity) { EntityItem::SimulationState oldState = entity->getSimulationState(); EntityItem::SimulationState newState = entity->computeSimulationState(); if (newState != oldState) { @@ -661,7 +661,7 @@ void EntityTree::updateChangedEntities(quint64 now, QSet& entities entitiesToDelete << thisEntity->getEntityItemID(); clearEntityState(thisEntity); } else { - changeEntityState(thisEntity); + updateEntityState(thisEntity); } } _changedEntities.clear(); @@ -696,7 +696,7 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT clearEntityState(thisEntity); } else { moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); - changeEntityState(thisEntity); + updateEntityState(thisEntity); } } } @@ -720,7 +720,7 @@ void EntityTree::updateMortalEntities(quint64 now, QSet& entitiesT clearEntityState(thisEntity); } else { // check to see if this entity is no longer moving - changeEntityState(thisEntity); + updateEntityState(thisEntity); } } } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index bf9da5a15d..7370ebadc6 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -137,7 +137,7 @@ public: void sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); - void changeEntityState(EntityItem* entity); + void updateEntityState(EntityItem* entity); void clearEntityState(EntityItem* entity); void entityChanged(EntityItem* entity); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index a461df5fde..7d4d95bf94 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -767,7 +767,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int addEntityItem(entityItem); // add this new entity to this elements entities entityItemID = entityItem->getEntityItemID(); _myTree->setContainingElement(entityItemID, this); - _myTree->changeEntityState(entityItem); + _myTree->updateEntityState(entityItem); _myTree->emitAddingEntity(entityItemID); // we just added an entity } } From 27614092700e6039562afb4fd4639a413b3873bb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Nov 2014 08:55:01 -0800 Subject: [PATCH 5/5] fix build error on linux --- libraries/entities/src/EntityItem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 61e929d9b3..d57f547cc5 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -269,7 +269,7 @@ public: SimulationState getSimulationState() const { return _simulationState; } protected: - friend EntityTree; + friend class EntityTree; void setSimulationState(SimulationState state) { _simulationState = state; } virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init