diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9d07c17b34..bcd07106ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -622,8 +622,6 @@ public: switch (type) { case NestableType::Entity: return getEntityModelProvider(static_cast(uuid)); - case NestableType::Overlay: - return nullptr; case NestableType::Avatar: return getAvatarModelProvider(uuid); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 7d0fc3409a..395fc3b7b4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -64,7 +64,11 @@ namespace render { return keyBuilder.build(); } template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) { - return static_pointer_cast(avatar)->getRenderBounds(); + auto avatarPtr = static_pointer_cast(avatar); + if (avatarPtr) { + return avatarPtr->getRenderBounds(); + } + return Item::Bound(); } template <> void payloadRender(const AvatarSharedPointer& avatar, RenderArgs* args) { auto avatarPtr = static_pointer_cast(avatar); @@ -75,10 +79,15 @@ namespace render { } template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems) { auto avatarPtr = static_pointer_cast(avatar); - if (avatarPtr->getSkeletonModel()) { - auto& metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs(); - subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); - return (uint32_t) metaSubItems.size(); + if (avatarPtr) { + uint32_t total = 0; + if (avatarPtr->getSkeletonModel()) { + auto& metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs(); + subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); + total += (uint32_t)metaSubItems.size(); + } + total += avatarPtr->appendSubMetaItems(subItems); + return total; } return 0; } @@ -626,12 +635,18 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc _skeletonModel->setVisibleInScene(_isMeshVisible, scene); processMaterials(); + bool attachmentRenderingNeedsUpdate = false; for (auto& attachmentModel : _attachmentModels) { attachmentModel->addToScene(scene, transaction); attachmentModel->setTagMask(render::hifi::TAG_ALL_VIEWS); - attachmentModel->setGroupCulled(false); + attachmentModel->setGroupCulled(true); attachmentModel->setCanCastShadow(true); attachmentModel->setVisibleInScene(_isMeshVisible, scene); + attachmentRenderingNeedsUpdate = true; + } + + if (attachmentRenderingNeedsUpdate) { + updateAttachmentRenderIDs(); } _mustFadeIn = true; @@ -855,15 +870,17 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { canTryFade = true; _isAnimatingScale = true; } + bool attachmentRenderingNeedsUpdate = false; for (auto attachmentModel : _attachmentModels) { if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) { attachmentModel->removeFromScene(scene, transaction); attachmentModel->addToScene(scene, transaction); attachmentModel->setTagMask(render::hifi::TAG_ALL_VIEWS); - attachmentModel->setGroupCulled(false); + attachmentModel->setGroupCulled(true); attachmentModel->setCanCastShadow(true); attachmentModel->setVisibleInScene(_isMeshVisible, scene); + attachmentRenderingNeedsUpdate = true; } } @@ -886,9 +903,15 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { for (auto attachmentModelToRemove : _attachmentsToRemove) { attachmentModelToRemove->removeFromScene(scene, transaction); + attachmentRenderingNeedsUpdate = true; } _attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end()); _attachmentsToRemove.clear(); + + if (attachmentRenderingNeedsUpdate) { + updateAttachmentRenderIDs(); + } + scene->enqueueTransaction(transaction); } @@ -931,6 +954,11 @@ void Avatar::simulateAttachments(float deltaTime) { } } } + + if (_ancestorChainRenderableVersion != _lastAncestorChainRenderableVersion) { + _lastAncestorChainRenderableVersion = _ancestorChainRenderableVersion; + updateDescendantRenderIDs(); + } } float Avatar::getBoundingRadius() const { @@ -1608,7 +1636,6 @@ void Avatar::setAttachmentData(const QVector& attachmentData) { } } - int Avatar::parseDataFromBuffer(const QByteArray& buffer) { PerformanceTimer perfTimer("unpack"); if (!_initialized) { @@ -2084,3 +2111,60 @@ void Avatar::clearAvatarGrabData(const QUuid& id) { } }); } + +uint32_t Avatar::appendSubMetaItems(render::ItemIDs& subItems) { + return _subItemLock.resultWithReadLock([&] { + uint32_t total = 0; + + if (_attachmentRenderIDs.size() > 0) { + subItems.insert(subItems.end(), _attachmentRenderIDs.begin(), _attachmentRenderIDs.end()); + total += (uint32_t)_attachmentRenderIDs.size(); + } + + if (_descendantRenderIDs.size() > 0) { + subItems.insert(subItems.end(), _descendantRenderIDs.begin(), _descendantRenderIDs.end()); + total += (uint32_t)_descendantRenderIDs.size(); + } + + return total; + }); +} + +void Avatar::updateAttachmentRenderIDs() { + _subItemLock.withWriteLock([&] { + _attachmentRenderIDs.clear(); + for (auto& attachmentModel : _attachmentModels) { + if (attachmentModel && attachmentModel->isRenderable()) { + auto& metaSubItems = attachmentModel->fetchRenderItemIDs(); + _attachmentRenderIDs.insert(_attachmentRenderIDs.end(), metaSubItems.begin(), metaSubItems.end()); + } + } + }); +} + +void Avatar::updateDescendantRenderIDs() { + _subItemLock.withWriteLock([&] { + _descendantRenderIDs.clear(); + auto entityTreeRenderer = DependencyManager::get(); + EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; + if (entityTree) { + entityTree->withReadLock([&] { + forEachDescendant([&](SpatiallyNestablePointer object) { + if (object && object->getNestableType() == NestableType::Entity) { + EntityItemPointer entity = std::static_pointer_cast(object); + if (entity->isVisible()) { + auto renderer = entityTreeRenderer->renderableForEntityId(object->getID()); + if (renderer) { + render::ItemIDs renderableSubItems; + uint32_t numRenderableSubItems = renderer->metaFetchMetaSubItems(renderableSubItems); + if (numRenderableSubItems > 0) { + _descendantRenderIDs.insert(_descendantRenderIDs.end(), renderableSubItems.begin(), renderableSubItems.end()); + } + } + } + } + }); + }); + } + }); +} diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 06942a13d8..1e6893a410 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -498,6 +498,8 @@ public: const std::vector& getMultiSphereShapes() const { return _multiSphereShapes; } void tearDownGrabs(); + uint32_t appendSubMetaItems(render::ItemIDs& subItems); + signals: void targetScaleChanged(float targetScale); @@ -638,8 +640,6 @@ protected: RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; - -protected: class AvatarEntityDataHash { public: AvatarEntityDataHash(uint32_t h) : hash(h) {}; @@ -699,6 +699,13 @@ protected: MapOfGrabs _avatarGrabs; SetOfIDs _grabsToChange; // updated grab IDs -- changes needed to entities or physics VectorOfIDs _grabsToDelete; // deleted grab IDs -- changes needed to entities or physics + + ReadWriteLockable _subItemLock; + void updateAttachmentRenderIDs(); + render::ItemIDs _attachmentRenderIDs; + void updateDescendantRenderIDs(); + render::ItemIDs _descendantRenderIDs; + uint32_t _lastAncestorChainRenderableVersion { 0 }; }; #endif // hifi_Avatar_h diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 5c73b9576d..a6826da91b 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -320,6 +320,7 @@ bool EntityRenderer::addToScene(const ScenePointer& scene, Transaction& transact transaction.resetItem(_renderItemID, renderPayload); onAddToScene(_entity); updateInScene(scene, transaction); + _entity->bumpAncestorChainRenderableVersion(); return true; } @@ -327,6 +328,7 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra onRemoveFromScene(_entity); transaction.removeItem(_renderItemID); Item::clearID(_renderItemID); + _entity->bumpAncestorChainRenderableVersion(); } void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) { @@ -352,14 +354,6 @@ void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& trans }); } -void EntityRenderer::clearSubRenderItemIDs() { - _subRenderItemIDs.clear(); -} - -void EntityRenderer::setSubRenderItemIDs(const render::ItemIDs& ids) { - _subRenderItemIDs = ids; -} - // // Internal methods // diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index d5e236a76a..e9a6035e3d 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -52,9 +52,6 @@ public: virtual bool addToScene(const ScenePointer& scene, Transaction& transaction) final; virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction); - void clearSubRenderItemIDs(); - void setSubRenderItemIDs(const render::ItemIDs& ids); - const uint64_t& getUpdateTime() const { return _updateTime; } virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); @@ -64,6 +61,9 @@ public: static glm::vec4 calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start); + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; + virtual Item::Bound getBound() override; + protected: virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } virtual void onAddToScene(const EntityItemPointer& entity); @@ -75,9 +75,7 @@ protected: // Implementing the PayloadProxyInterface methods virtual ItemKey getKey() override; virtual ShapeKey getShapeKey() override; - virtual Item::Bound getBound() override; virtual void render(RenderArgs* args) override final; - virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; virtual render::hifi::Tag getTagMask() const; virtual render::hifi::Layer getHifiRenderLayer() const; @@ -133,7 +131,6 @@ protected: SharedSoundPointer _collisionSound; QUuid _changeHandlerId; ItemID _renderItemID{ Item::INVALID_ITEM_ID }; - ItemIDs _subRenderItemIDs; uint64_t _fadeStartTime{ usecTimestampNow() }; uint64_t _updateTime{ usecTimestampNow() }; // used when sorting/throttling render updates bool _isFading { EntityTreeRenderer::getEntitiesShouldFadeFunction()() }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ae9fdf572a..e842d98714 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1079,7 +1079,7 @@ render::hifi::Tag ModelEntityRenderer::getTagMask() const { uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) { if (_model) { - auto metaSubItems = _subRenderItemIDs; + auto metaSubItems = _model->fetchRenderItemIDs(); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); return (uint32_t)metaSubItems.size(); } @@ -1321,11 +1321,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (!_hasModel) { if (model) { model->removeFromScene(scene, transaction); + entity->bumpAncestorChainRenderableVersion(); withWriteLock([&] { _model.reset(); }); - transaction.updateItem(getRenderItemID(), [](PayloadProxyInterface& data) { - auto entityRenderer = static_cast(&data); - entityRenderer->clearSubRenderItemIDs(); - }); emit DependencyManager::get()-> modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, _model); } @@ -1442,12 +1439,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce render::Item::Status::Getters statusGetters; makeStatusGetters(entity, statusGetters); model->addToScene(scene, transaction, statusGetters); - - auto newRenderItemIDs{ model->fetchRenderItemIDs() }; - transaction.updateItem(getRenderItemID(), [newRenderItemIDs](PayloadProxyInterface& data) { - auto entityRenderer = static_cast(&data); - entityRenderer->setSubRenderItemIDs(newRenderItemIDs); - }); + entity->bumpAncestorChainRenderableVersion(); processMaterials(); } } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index c0b12c4d1f..9f11b3c018 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2935,6 +2935,7 @@ void EntityItem::setVisible(bool value) { }); if (changed) { + bumpAncestorChainRenderableVersion(); emit requestRenderUpdate(); } } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 150aa6b0cf..22cd26eac6 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -941,7 +941,7 @@ QUuid EntityScriptingInterface::editEntity(const QUuid& id, const EntityItemProp auto nestable = nestableWP.lock(); if (nestable) { NestableType nestableType = nestable->getNestableType(); - if (nestableType == NestableType::Overlay || nestableType == NestableType::Avatar) { + if (nestableType == NestableType::Avatar) { qCWarning(entities) << "attempted edit on non-entity: " << id << nestable->getName(); return QUuid(); // null script value to indicate failure } diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index d3ed79faf4..19fafdccf4 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -67,6 +67,7 @@ const QUuid SpatiallyNestable::getParentID() const { } void SpatiallyNestable::setParentID(const QUuid& parentID) { + bumpAncestorChainRenderableVersion(); _idLock.withWriteLock([&] { if (_parentID != parentID) { _parentID = parentID; @@ -78,6 +79,7 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) { bool success = false; auto parent = getParentPointer(success); if (success && parent) { + bumpAncestorChainRenderableVersion(); parent->updateQueryAACube(); } } @@ -1337,8 +1339,6 @@ QString SpatiallyNestable::nestableTypeToString(NestableType nestableType) { return "entity"; case NestableType::Avatar: return "avatar"; - case NestableType::Overlay: - return "overlay"; default: return "unknown"; } @@ -1419,3 +1419,12 @@ QUuid SpatiallyNestable::getEditSenderID() { }); return editSenderID; } + +void SpatiallyNestable::bumpAncestorChainRenderableVersion() const { + _ancestorChainRenderableVersion++; + bool success = false; + auto parent = getParentPointer(success); + if (success && parent) { + parent->bumpAncestorChainRenderableVersion(); + } +} \ No newline at end of file diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index e7a449f73f..495c941c07 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -30,8 +30,7 @@ static const uint16_t INVALID_JOINT_INDEX = -1; enum class NestableType { Entity, - Avatar, - Overlay + Avatar }; class SpatiallyNestable : public std::enable_shared_from_this { @@ -222,6 +221,8 @@ public: bool hasGrabs(); virtual QUuid getEditSenderID(); + void bumpAncestorChainRenderableVersion() const; + protected: QUuid _id; mutable SpatiallyNestableWeakPointer _parent; @@ -244,6 +245,8 @@ protected: mutable ReadWriteLockable _grabsLock; QSet _grabs; // upon this thing + mutable std::atomic _ancestorChainRenderableVersion { 0 }; + private: SpatiallyNestable() = delete; const NestableType _nestableType; // EntityItem or an AvatarData