diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7400261858..07843b8c33 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -613,7 +613,7 @@ void MyAvatar::simulate(float deltaTime) { MovingEntitiesOperator moveOperator(entityTree); forEachDescendant([&](SpatiallyNestablePointer object) { // if the queryBox has changed, tell the entity-server - if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) { + if (object->getNestableType() == NestableType::Entity && object->checkAndMaybeUpdateQueryAACube()) { EntityItemPointer entity = std::static_pointer_cast(object); bool success; AACube newCube = entity->getQueryAACube(success); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 378f344d26..422488f86f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1355,8 +1355,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy); AACube saveQueryAACube = _queryAACube; - checkAndAdjustQueryAACube(); - if (saveQueryAACube != _queryAACube) { + if (checkAndMaybeUpdateQueryAACube() && saveQueryAACube != _queryAACube) { somethingChanged = true; } @@ -1424,26 +1423,20 @@ void EntityItem::setDimensions(const glm::vec3& value) { /// AACube EntityItem::getMaximumAACube(bool& success) const { if (_recalcMaxAACube) { - // * we know that the position is the center of rotation glm::vec3 centerOfRotation = getPosition(success); // also where _registration point is if (success) { _recalcMaxAACube = false; - // * we know that the registration point is the center of rotation - // * we can calculate the length of the furthest extent from the registration point - // as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint) - glm::vec3 dimensions = getDimensions(); - glm::vec3 registrationPoint = (dimensions * _registrationPoint); - glm::vec3 registrationRemainder = (dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint)); - glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder); + // we want to compute the furthestExtent that an entity can extend out from its "position" + // to do this we compute the max of these two vec3s: registration and 1-registration + // and then scale by dimensions + glm::vec3 maxExtents = getDimensions() * glm::max(_registrationPoint, glm::vec3(1.0f) - _registrationPoint); - // * we know that if you rotate in any direction you would create a sphere - // that has a radius of the length of furthest extent from registration point - float radius = glm::length(furthestExtentFromRegistration); + // there exists a sphere that contains maxExtents for all rotations + float radius = glm::length(maxExtents); - // * we know that the minimum bounding cube of this maximum possible sphere is - // (center - radius) to (center + radius) + // put a cube around the sphere + // TODO? replace _maxAACube with _boundingSphereRadius glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); - _maxAACube = AACube(minimumCorner, radius * 2.0f); } } else { @@ -1635,6 +1628,8 @@ void EntityItem::updateDimensions(const glm::vec3& value) { if (getDimensions() != value) { setDimensions(value); markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); + _queryAACubeSet = false; + dimensionsChanged(); } } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index a207902789..20b541f563 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2157,12 +2157,17 @@ QList EntityItemProperties::listChangedProperties() { return out; } -bool EntityItemProperties::parentDependentPropertyChanged() const { - return localPositionChanged() || positionChanged() || - localRotationChanged() || rotationChanged() || - localVelocityChanged() || localAngularVelocityChanged(); +bool EntityItemProperties::transformChanged() const { + return positionChanged() || rotationChanged() || + localPositionChanged() || localRotationChanged(); } bool EntityItemProperties::parentRelatedPropertyChanged() const { - return parentDependentPropertyChanged() || parentIDChanged() || parentJointIndexChanged(); + return positionChanged() || rotationChanged() || + localPositionChanged() || localRotationChanged() || + parentIDChanged() || parentJointIndexChanged(); +} + +bool EntityItemProperties::queryAACubeRelatedPropertyChanged() const { + return parentRelatedPropertyChanged() || dimensionsChanged(); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index b526ac663c..90afd39fbf 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -86,8 +86,9 @@ public: EntityPropertyFlags getChangedProperties() const; - bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret? - bool parentRelatedPropertyChanged() const; // parentDependentPropertyChanged or parentID or parentJointIndex + bool transformChanged() const; + bool parentRelatedPropertyChanged() const; + bool queryAACubeRelatedPropertyChanged() const; AABox getAABox() const; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 9d2cb30c6e..e21c9581e1 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -221,7 +221,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties _entityTree->withWriteLock([&] { EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); if (entity) { - if (propertiesWithSimID.parentRelatedPropertyChanged()) { + if (propertiesWithSimID.queryAACubeRelatedPropertyChanged()) { // due to parenting, the server may not know where something is in world-space, so include the bounding cube. bool success; AACube queryAACube = entity->getQueryAACube(success); @@ -435,7 +435,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& entity->rememberHasSimulationOwnershipBid(); } } - if (properties.parentRelatedPropertyChanged() && entity->computePuffedQueryAACube()) { + if (properties.queryAACubeRelatedPropertyChanged()) { properties.setQueryAACube(entity->getQueryAACube()); } entity->setLastBroadcast(usecTimestampNow()); @@ -445,7 +445,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& // if they've changed. entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { if (descendant->getNestableType() == NestableType::Entity) { - if (descendant->computePuffedQueryAACube()) { + if (descendant->checkAndMaybeUpdateQueryAACube()) { EntityItemPointer entityDescendant = std::static_pointer_cast(descendant); EntityItemProperties newQueryCubeProperties; newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5e58736477..f17b991b69 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1675,6 +1675,7 @@ QVector EntityTree::sendEntities(EntityEditPacketSender* packetSen addToNeedsParentFixupList(entity); } entity->forceQueryAACubeUpdate(); + entity->checkAndMaybeUpdateQueryAACube(); moveOperator.addEntityToMoveList(entity, entity->getQueryAACube()); i++; } else { @@ -1693,7 +1694,7 @@ QVector EntityTree::sendEntities(EntityEditPacketSender* packetSen EntityItemPointer entity = localTree->findEntityByEntityItemID(newID); if (entity) { // queue the packet to send to the server - entity->computePuffedQueryAACube(); + entity->updateQueryAACube(); EntityItemProperties properties = entity->getProperties(); properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity packetSender->queueEditEntityMessage(PacketType::EntityAdd, localTree, newID, properties); diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index e406926141..d41b22137e 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -136,7 +136,7 @@ void SimpleEntitySimulation::sortEntitiesThatMoved() { SetOfEntities::iterator itemItr = _entitiesToSort.begin(); while (itemItr != _entitiesToSort.end()) { EntityItemPointer entity = *itemItr; - entity->computePuffedQueryAACube(); + entity->checkAndMaybeUpdateQueryAACube(); ++itemItr; } EntitySimulation::sortEntitiesThatMoved(); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index ecfb2b55e4..f02dcee8f6 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -484,11 +484,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { return false; } - if (_entity->dynamicDataNeedsTransmit()) { - return true; - } - - if (_entity->queryAABoxNeedsUpdate()) { + if (_entity->dynamicDataNeedsTransmit() || _entity->queryAACubeNeedsUpdate()) { return true; } @@ -577,9 +573,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setActionData(_serverActionData); } - if (properties.parentRelatedPropertyChanged() && _entity->computePuffedQueryAACube()) { - // due to parenting, the server may not know where something is in world-space, so include the bounding cube. - properties.setQueryAACube(_entity->getQueryAACube()); + if (properties.transformChanged()) { + if (_entity->checkAndMaybeUpdateQueryAACube()) { + // due to parenting, the server may not know where something is in world-space, so include the bounding cube. + properties.setQueryAACube(_entity->getQueryAACube()); + } } // set the LastEdited of the properties but NOT the entity itself @@ -643,7 +641,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { if (descendant->getNestableType() == NestableType::Entity) { EntityItemPointer entityDescendant = std::static_pointer_cast(descendant); - if (descendant->computePuffedQueryAACube()) { + if (descendant->checkAndMaybeUpdateQueryAACube()) { EntityItemProperties newQueryCubeProperties; newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); newQueryCubeProperties.setLastEdited(properties.getLastEdited()); diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 4fe9cda825..fc189c5e3e 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -946,11 +946,35 @@ AACube SpatiallyNestable::getMaximumAACube(bool& success) const { return AACube(getPosition(success) - glm::vec3(defaultAACubeSize / 2.0f), defaultAACubeSize); } -bool SpatiallyNestable::checkAndAdjustQueryAACube() { - bool success; +const float PARENTED_EXPANSION_FACTOR = 3.0f; + +bool SpatiallyNestable::checkAndMaybeUpdateQueryAACube() { + bool success = false; AACube maxAACube = getMaximumAACube(success); - if (success && (!_queryAACubeSet || !_queryAACube.contains(maxAACube))) { - setQueryAACube(maxAACube); + if (success) { + // maybe update _queryAACube + if (!_queryAACubeSet || (_parentID.isNull() && _children.size() == 0) || !_queryAACube.contains(maxAACube)) { + if (_parentJointIndex != INVALID_JOINT_INDEX || _children.size() > 0 ) { + // make an expanded AACube centered on the object + float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale(); + _queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale); + } else { + _queryAACube = maxAACube; + } + + getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) { + bool childSuccess; + AACube descendantAACube = descendant->getQueryAACube(childSuccess); + if (childSuccess) { + if (_queryAACube.contains(descendantAACube)) { + return; + } + _queryAACube += descendantAACube.getMinimumPoint(); + _queryAACube += descendantAACube.getMaximumPoint(); + } + }); + _queryAACubeSet = true; + } } return success; } @@ -961,46 +985,34 @@ void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) { return; } _queryAACube = queryAACube; - if (queryAACube.getScale() > 0.0f) { - _queryAACubeSet = true; - } + _queryAACubeSet = true; } -bool SpatiallyNestable::queryAABoxNeedsUpdate() const { - bool success; - AACube currentAACube = getMaximumAACube(success); - if (!success) { - qCDebug(shared) << "can't getMaximumAACube for" << getID(); - return false; +bool SpatiallyNestable::queryAACubeNeedsUpdate() const { + if (!_queryAACubeSet) { + return true; } // make sure children are still in their boxes, also. bool childNeedsUpdate = false; getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) { - if (!childNeedsUpdate && descendant->queryAABoxNeedsUpdate()) { + if (!childNeedsUpdate && descendant->queryAACubeNeedsUpdate()) { childNeedsUpdate = true; } }); - if (childNeedsUpdate) { - return true; - } - - if (_queryAACubeSet && _queryAACube.contains(currentAACube)) { - return false; - } - - return true; + return childNeedsUpdate; } -bool SpatiallyNestable::computePuffedQueryAACube() { - if (!queryAABoxNeedsUpdate()) { - return false; - } +void SpatiallyNestable::updateQueryAACube() { bool success; - AACube currentAACube = getMaximumAACube(success); - // make an AACube with edges thrice as long and centered on the object - _queryAACube = AACube(currentAACube.getCorner() - glm::vec3(currentAACube.getScale()), currentAACube.getScale() * 3.0f); - _queryAACubeSet = true; + AACube maxAACube = getMaximumAACube(success); + if (_parentJointIndex != INVALID_JOINT_INDEX || _children.size() > 0 ) { + // make an expanded AACube centered on the object + float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale(); + _queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale); + } else { + _queryAACube = maxAACube; + } getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) { bool success; @@ -1013,8 +1025,7 @@ bool SpatiallyNestable::computePuffedQueryAACube() { _queryAACube += descendantAACube.getMaximumPoint(); } }); - - return true; + _queryAACubeSet = true; } AACube SpatiallyNestable::getQueryAACube(bool& success) const { diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index b98ab4c358..78a014d7c1 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -102,11 +102,11 @@ public: virtual glm::vec3 getParentAngularVelocity(bool& success) const; virtual AACube getMaximumAACube(bool& success) const; - virtual bool checkAndAdjustQueryAACube(); - virtual bool computePuffedQueryAACube(); + bool checkAndMaybeUpdateQueryAACube(); + void updateQueryAACube(); virtual void setQueryAACube(const AACube& queryAACube); - virtual bool queryAABoxNeedsUpdate() const; + virtual bool queryAACubeNeedsUpdate() const; void forceQueryAACubeUpdate() { _queryAACubeSet = false; } virtual AACube getQueryAACube(bool& success) const; virtual AACube getQueryAACube() const; @@ -197,7 +197,7 @@ protected: mutable QHash _children; virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed - virtual void dimensionsChanged() { } // called when a this object's dimensions have changed + virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed virtual void parentDeleted() { } // called on children of a deleted parent // _queryAACube is used to decide where something lives in the octree