diff --git a/interface/resources/qml/+android_interface/Stats.qml b/interface/resources/qml/+android_interface/Stats.qml index 1f07af786f..b44b95c5ca 100644 --- a/interface/resources/qml/+android_interface/Stats.qml +++ b/interface/resources/qml/+android_interface/Stats.qml @@ -386,6 +386,10 @@ Item { visible: root.expanded text: "LOD: " + root.lodStatus; } + StatText { + visible: root.expanded + text: "Entity Updates: " + root.numEntityUpdates + " / " + root.numNeededEntityUpdates; + } } } } diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 23aa256cdc..9e4fdffaee 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -437,6 +437,10 @@ Item { visible: root.expanded text: "LOD: " + root.lodStatus; } + StatText { + visible: root.expanded + text: "Entity Updates: " + root.numEntityUpdates + " / " + root.numNeededEntityUpdates; + } } } } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 8b9b9743f0..a9e2e4d8e3 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -456,6 +456,8 @@ void Stats::updateStats(bool force) { STAT_UPDATE(localLeaves, (int)OctreeElement::getLeafNodeCount()); // LOD Details STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get()->getLODFeedbackText()); + STAT_UPDATE(numEntityUpdates, DependencyManager::get()->getPrevNumEntityUpdates()); + STAT_UPDATE(numNeededEntityUpdates, DependencyManager::get()->getPrevTotalNeededEntityUpdates()); } diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index b87e3a3dbc..96f0ea725a 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -112,6 +112,8 @@ private: \ * @property {number} lodAngle - Read-only. * @property {number} lodTargetFramerate - Read-only. * @property {string} lodStatus - Read-only. + * @property {string} numEntityUpdates - Read-only. + * @property {string} numNeededEntityUpdates - Read-only. * @property {string} timingStats - Read-only. * @property {string} gameUpdateStats - Read-only. * @property {number} serverElements - Read-only. @@ -277,6 +279,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, lodAngle, 0) STATS_PROPERTY(int, lodTargetFramerate, 0) STATS_PROPERTY(QString, lodStatus, QString()) + STATS_PROPERTY(int, numEntityUpdates, 0) + STATS_PROPERTY(int, numNeededEntityUpdates, 0) STATS_PROPERTY(QString, timingStats, QString()) STATS_PROPERTY(QString, gameUpdateStats, QString()) STATS_PROPERTY(int, serverElements, 0) @@ -883,6 +887,20 @@ signals: */ void lodStatusChanged(); + /**jsdoc + * Triggered when the value of the numEntityUpdates property changes. + * @function Stats.numEntityUpdatesChanged + * @returns {Signal} + */ + void numEntityUpdatesChanged(); + + /**jsdoc + * Triggered when the value of the numNeededEntityUpdates property changes. + * @function Stats.numNeededEntityUpdatesChanged + * @returns {Signal} + */ + void numNeededEntityUpdatesChanged(); + /**jsdoc * Triggered when the value of the serverElements property changes. * @function Stats.serverElementsChanged diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ab3f4c5243..5e05ebf5c9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -426,6 +426,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene } float expectedUpdateCost = _avgRenderableUpdateCost * _renderablesToUpdate.size(); + _prevTotalNeededEntityUpdates = _renderablesToUpdate.size(); if (expectedUpdateCost < MAX_UPDATE_RENDERABLES_TIME_BUDGET) { // we expect to update all renderables within available time budget PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); @@ -434,7 +435,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene assert(renderable); // only valid renderables are added to _renderablesToUpdate renderable->updateInScene(scene, transaction); } - size_t numRenderables = _renderablesToUpdate.size() + 1; // add one to avoid divide by zero + _prevNumEntityUpdates = _renderablesToUpdate.size(); + size_t numRenderables = _prevNumEntityUpdates + 1; // add one to avoid divide by zero _renderablesToUpdate.clear(); // compute average per-renderable update cost @@ -495,7 +497,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene } // compute average per-renderable update cost - size_t numUpdated = sortedRenderables.size() - _renderablesToUpdate.size() + 1; // add one to avoid divide by zero + _prevNumEntityUpdates = sortedRenderables.size() - _renderablesToUpdate.size(); + size_t numUpdated = _prevNumEntityUpdates + 1; // add one to avoid divide by zero float cost = (float)(usecTimestampNow() - updateStart) / (float)(numUpdated); const float BLEND = 0.1f; _avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 6dbaedc123..36ec94c464 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -135,6 +135,9 @@ public: static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName); static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName); + int getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; } + int getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; } + signals: void enterEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID); @@ -248,6 +251,8 @@ private: ReadWriteLockable _changedEntitiesGuard; std::unordered_set _changedEntities; + int _prevNumEntityUpdates { 0 }; + int _prevTotalNeededEntityUpdates { 0 }; std::unordered_set _renderablesToUpdate; std::unordered_map _entitiesInScene; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index ae56a8fc47..79ee861c95 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -201,13 +201,6 @@ void EntityRenderer::render(RenderArgs* args) { return; } - if (!_renderUpdateQueued && needsRenderUpdate()) { - // FIXME find a way to spread out the calls to needsRenderUpdate so that only a given subset of the - // items checks every frame, like 1/N of the tree ever N frames - _renderUpdateQueued = true; - emit requestRenderUpdate(); - } - if (_visible && (args->_renderMode != RenderArgs::RenderMode::DEFAULT_RENDER_MODE || !_cauterized)) { doRender(args); } @@ -326,11 +319,6 @@ void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& trans } _updateTime = usecTimestampNow(); - // FIXME is this excessive? - if (!needsRenderUpdate()) { - return; - } - doRenderUpdateSynchronous(scene, transaction, _entity); transaction.updateItem(_renderItemID, [this](PayloadProxyInterface& self) { if (!isValidRenderItem()) { @@ -338,7 +326,6 @@ void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& trans } // Happens on the render thread. Classes should use doRenderUpdateAsynchronous(_entity); - _renderUpdateQueued = false; }); } @@ -431,7 +418,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa } void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { - QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] { + QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] { auto renderer = DependencyManager::get(); if (renderer) { renderer->onEntityChanged(_entity->getID()); @@ -440,7 +427,10 @@ void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { _changeHandlerId = entity->registerChangeHandler([](const EntityItemID& changedEntity) { auto renderer = DependencyManager::get(); if (renderer) { - renderer->onEntityChanged(changedEntity); + auto renderable = renderer->renderableForEntityId(changedEntity); + if (renderable && renderable->needsRenderUpdate()) { + renderer->onEntityChanged(changedEntity); + } } }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 227eb6a018..d52ccf4a99 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -145,8 +145,6 @@ protected: PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; bool _cauterized { false }; bool _moving { false }; - // Only touched on the rendering thread - bool _renderUpdateQueued{ false }; Transform _renderTransform; std::unordered_map _materials; @@ -187,10 +185,7 @@ protected: using Parent::needsRenderUpdateFromEntity; // Returns true if the item in question needs to have updateInScene called because of changes in the entity virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const override final { - if (Parent::needsRenderUpdateFromEntity(entity)) { - return true; - } - return needsRenderUpdateFromTypedEntity(_typedEntity); + return Parent::needsRenderUpdateFromEntity(entity) || needsRenderUpdateFromTypedEntity(_typedEntity); } virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) override final { diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 9081d0727f..7a36ae2707 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -39,6 +39,16 @@ bool GizmoEntityRenderer::isTransparent() const { return Parent::isTransparent() || ringTransparent; } +void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { + void* key = (void*)this; + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { + withWriteLock([&] { + _renderTransform = getModelTransform(); + _renderTransform.postScale(entity->getScaledDimensions()); + }); + }); +} + void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { bool dirty = false; RingGizmoPropertyGroup ringProperties = entity->getRingProperties(); @@ -186,15 +196,6 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint } } } - - void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() { - withWriteLock([&] { - updateModelTransformAndBound(); - _renderTransform = getModelTransform(); - _renderTransform.postScale(entity->getScaledDimensions()); - }); - }); } Item::Bound GizmoEntityRenderer::getBound() { diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h index c072f482cd..e3d84a0201 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h @@ -29,6 +29,7 @@ protected: bool isTransparent() const override; private: + virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity); virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 0b074f7a81..52900d0798 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -41,10 +41,9 @@ void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen }); void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { _dimensions = entity->getScaledDimensions(); - updateModelTransformAndBound(); _renderTransform = getModelTransform(); }); }); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index acdf5a35de..4d19a83ae6 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -30,11 +30,9 @@ bool ImageEntityRenderer::isTransparent() const { } bool ImageEntityRenderer::needsRenderUpdate() const { - bool textureLoadedChanged = resultWithReadLock([&] { - return (!_textureIsLoaded && _texture && _texture->isLoaded()); - }); - - if (textureLoadedChanged) { + if (resultWithReadLock([&] { + return !_textureIsLoaded; + })) { return true; } @@ -63,15 +61,15 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _pulseProperties = entity->getPulseProperties(); _billboardMode = entity->getBillboardMode(); - if (!_textureIsLoaded && _texture && _texture->isLoaded()) { - _textureIsLoaded = true; + if (!_textureIsLoaded) { + emit requestRenderUpdate(); } + _textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed()); }); void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { - updateModelTransformAndBound(); _renderTransform = getModelTransform(); _renderTransform.postScale(entity->getScaledDimensions()); }); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f34eb85230..5ffb395302 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -64,6 +64,16 @@ ParticleEffectEntityRenderer::ParticleEffectEntityRenderer(const EntityItemPoint }); } +bool ParticleEffectEntityRenderer::needsRenderUpdate() const { + if (resultWithReadLock([&] { + return !_textureLoaded; + })) { + return true; + } + + return Parent::needsRenderUpdate(); +} + void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { auto newParticleProperties = entity->getParticleProperties(); if (!newParticleProperties.valid()) { @@ -102,6 +112,7 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi } withWriteLock([&] { + _textureLoaded = true; entity->setVisuallyReady(true); }); } else { @@ -111,20 +122,29 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi if (textureNeedsUpdate) { withWriteLock([&] { _networkTexture = DependencyManager::get()->getTexture(_particleProperties.textures); + _textureLoaded = false; + entity->setVisuallyReady(false); }); } - if (_networkTexture) { + if (!_textureLoaded) { + emit requestRenderUpdate(); + } + + bool textureLoaded = resultWithReadLock([&] { + return _networkTexture && (_networkTexture->isLoaded() || _networkTexture->isFailed()); + }); + if (textureLoaded) { withWriteLock([&] { - entity->setVisuallyReady(_networkTexture->isFailed() || _networkTexture->isLoaded()); + entity->setVisuallyReady(true); + _textureLoaded = true; }); } } void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] { withWriteLock([&] { - updateModelTransformAndBound(); _renderTransform = getModelTransform(); }); }); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index cc907f2b1d..a89ab804fc 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -25,6 +25,7 @@ public: ParticleEffectEntityRenderer(const EntityItemPointer& entity); protected: + virtual bool needsRenderUpdate() const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; @@ -111,6 +112,7 @@ private: GeometryResource::Pointer _geometryResource; NetworkTexturePointer _networkTexture; + bool _textureLoaded { false }; ScenePointer _scene; }; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index e75f8593d6..a843083831 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -204,9 +204,8 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& bool geometryChanged = uvModeStretchChanged || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged || faceCameraChanged; void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, geometryChanged] () { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, geometryChanged] { withWriteLock([&] { - updateModelTransformAndBound(); _renderTransform = getModelTransform(); if (geometryChanged) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index d5a0e22199..222b833be2 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -70,20 +70,18 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce }); void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { - auto entity = getEntity(); _position = entity->getWorldPosition(); _dimensions = entity->getUnscaledDimensions(); // get unscaled to avoid scaling twice _orientation = entity->getWorldOrientation(); - updateModelTransformAndBound(); _renderTransform = getModelTransform(); // contains parent scale, if this entity scales with its parent if (_shape == entity::Sphere) { _renderTransform.postScale(SPHERE_ENTITY_SCALE); } _renderTransform.postScale(_dimensions); - });; + }); }); } @@ -125,6 +123,7 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint auto materials = _materials.find("0"); if (materials != _materials.end()) { materials->second.setNeedsUpdate(true); + emit requestRenderUpdate(); } } }); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index fbd10e2f5b..a5baad4841 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -102,10 +102,9 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { _dimensions = entity->getScaledDimensions(); - updateModelTransformAndBound(); _renderTransform = getModelTransform(); _renderTransform.postScale(_dimensions); }); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 1da4999bad..c818eaf237 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -236,11 +236,10 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene } void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() { + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { glm::vec2 windowSize = getWindowSize(entity); _webSurface->resize(QSize(windowSize.x, windowSize.y)); - updateModelTransformAndBound(); _renderTransform = getModelTransform(); _renderTransform.setScale(1.0f); _renderTransform.postScale(entity->getScaledDimensions()); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index bbb8c67ad1..d6c675e88c 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -255,14 +255,6 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen entity->setVisuallyReady(visuallyReady); } -void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - if (entity->getShapeType() == SHAPE_TYPE_SPHERE) { - _renderTransform = getModelTransform(); - _renderTransform.postScale(SPHERE_ENTITY_SCALE); - } -} - - ItemKey ZoneEntityRenderer::getKey() { return ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).build(); } @@ -299,8 +291,6 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } - // FIXME: do we need to trigger an update when shapeType changes? see doRenderUpdateAsynchronousTyped - return false; } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 5fd9b87408..d4e3d16408 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -39,7 +39,6 @@ protected: virtual void doRender(RenderArgs* args) override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; - virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; private: void updateKeyZoneItemFromEntity(const TypedEntityPointer& entity); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 856468f2ec..a48b7377df 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -615,10 +615,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef _lastEdited = lastEditedFromBufferAdjusted; _lastEditedFromRemote = now; _lastEditedFromRemoteInRemoteTime = lastEditedFromBuffer; - - // TODO: only send this notification if something ACTUALLY changed (hint, we haven't yet parsed - // the properties out of the bitstream (see below)) - somethingChangedNotification(); // notify derived classes that something has changed } // last updated is stored as ByteCountCoded delta from lastEdited @@ -1569,7 +1565,6 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); #endif setLastEdited(now); - somethingChangedNotification(); // notify derived classes that something has changed if (getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES)) { // anything that sets the transform or velocity must update _lastSimulated which is used // for kinematic extrapolation (e.g. we want to extrapolate forward from this moment @@ -1827,6 +1822,7 @@ void EntityItem::setPosition(const glm::vec3& value) { void EntityItem::setParentID(const QUuid& value) { QUuid oldParentID = getParentID(); if (oldParentID != value) { + _needsRenderUpdate = true; EntityTreePointer tree = getTree(); if (tree && !oldParentID.isNull()) { tree->removeFromChildrenOfAvatars(getThisPointer()); @@ -2993,10 +2989,15 @@ bool EntityItem::getCauterized() const { } void EntityItem::setCauterized(bool value) { + bool needsRenderUpdate = false; withWriteLock([&] { - _needsRenderUpdate |= _cauterized != value; + needsRenderUpdate = _cauterized != value; + _needsRenderUpdate |= needsRenderUpdate; _cauterized = value; }); + if (needsRenderUpdate) { + somethingChangedNotification(); + } } bool EntityItem::getIgnorePickIntersection() const { @@ -3031,10 +3032,15 @@ bool EntityItem::getCullWithParent() const { } void EntityItem::setCullWithParent(bool value) { + bool needsRenderUpdate = false; withWriteLock([&] { - _needsRenderUpdate |= _cullWithParent != value; + needsRenderUpdate = _cullWithParent != value; + _needsRenderUpdate |= needsRenderUpdate; _cullWithParent = value; }); + if (needsRenderUpdate) { + somethingChangedNotification(); + } } bool EntityItem::isChildOfMyAvatar() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 14b8b259cc..5b0f1ad44c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -574,8 +574,8 @@ public: bool stillHasMyGrab() const; - bool needsRenderUpdate() const { return resultWithReadLock([&] { return _needsRenderUpdate; }); } - void setNeedsRenderUpdate(bool needsRenderUpdate) { withWriteLock([&] { _needsRenderUpdate = needsRenderUpdate; }); } + bool needsRenderUpdate() const { return _needsRenderUpdate; } + void setNeedsRenderUpdate(bool needsRenderUpdate) { _needsRenderUpdate = needsRenderUpdate; } signals: void spaceUpdate(std::pair data); diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index a2fc691387..9d79e06534 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -58,6 +58,7 @@ bool GizmoEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index e45ab89b69..a1147b21df 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -70,6 +70,7 @@ bool GridEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 2d942cc25d..c538ce619d 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -71,6 +71,7 @@ bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 2df2136639..11864f59da 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -55,21 +55,6 @@ void LightEntityItem::setUnscaledDimensions(const glm::vec3& value) { } } -void LightEntityItem::locationChanged(bool tellPhysics, bool tellChildren) { - EntityItem::locationChanged(tellPhysics, tellChildren); - withWriteLock([&] { - _needsRenderUpdate = true; - }); -} - -void LightEntityItem::dimensionsChanged() { - EntityItem::dimensionsChanged(); - withWriteLock([&] { - _needsRenderUpdate = true; - }); -} - - EntityItemProperties LightEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class @@ -145,6 +130,7 @@ bool LightEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 8194ff8308..533d2994d6 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -73,9 +73,6 @@ public: static bool getLightsArePickable() { return _lightsArePickable; } static void setLightsArePickable(bool value) { _lightsArePickable = value; } - - virtual void locationChanged(bool tellPhysics, bool tellChildren) override; - virtual void dimensionsChanged() override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 1cd09c1a0c..45cdf980a1 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -61,6 +61,7 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 73bebfc403..11745c29ce 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -60,6 +60,7 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 0b6e62e89e..aa0c7304a7 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -111,6 +111,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index c20ae87276..082c4efb17 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -759,6 +759,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index fe14ba6925..fcd4b6d89d 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -77,6 +77,7 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index b424ba137f..c31d0b81b3 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -130,6 +130,7 @@ bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 882ab26901..5b9c3e6881 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -186,6 +186,7 @@ bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); + somethingChangedNotification(); } return somethingChanged; } diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index bcc2c0efed..9c53196247 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -109,6 +109,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index a62f599e4c..d8b2c8fc3d 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -92,6 +92,7 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 0771d9ad54..dc18c05ef3 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -88,6 +88,7 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) { "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties._lastEdited); + somethingChangedNotification(); } return somethingChanged; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d8172112ff..d3f2a04d24 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -282,11 +282,6 @@ void Model::setRenderItemsNeedUpdate() { emit requestRenderUpdate(); } -void Model::setPrimitiveMode(PrimitiveMode primitiveMode) { - _primitiveMode = primitiveMode; - setRenderItemsNeedUpdate(); -} - void Model::reset() { if (isLoaded()) { const HFMModel& hfmModel = getHFMModel(); @@ -888,6 +883,13 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) { scene->enqueueTransaction(transaction); } +void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) { + if (_primitiveMode != primitiveMode) { + _primitiveMode = primitiveMode; + updateRenderItemsKey(scene); + } +} + void Model::setVisibleInScene(bool visible, const render::ScenePointer& scene) { if (Model::isVisible() != visible) { auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index b677861e9f..85aaa33bcb 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -129,6 +129,9 @@ public: bool isCauterized() const { return _cauterized; } void setCauterized(bool value, const render::ScenePointer& scene); + void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr); + PrimitiveMode getPrimitiveMode() const { return _primitiveMode; } + void setCullWithParent(bool value); // Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model. @@ -168,9 +171,6 @@ public: bool isLoaded() const { return (bool)_renderGeometry && _renderGeometry->isHFMModelLoaded(); } bool isAddedToScene() const { return _addedToScene; } - void setPrimitiveMode(PrimitiveMode primitiveMode); - PrimitiveMode getPrimitiveMode() const { return _primitiveMode; } - void reset(); void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint);