From 5fbf10c2f390918f126ea287c52302df8038add3 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 8 Oct 2018 23:48:12 -0700 Subject: [PATCH] INtroducing the LODEnabled flag on the render item in order prevent LOD to hide important objects regardless of the LOD level. --- interface/src/ui/overlays/ModelOverlay.cpp | 22 ++++++++++++++++++++++ interface/src/ui/overlays/ModelOverlay.h | 3 +++ libraries/render-utils/src/Model.cpp | 11 +++++++++++ libraries/render-utils/src/Model.h | 3 +++ libraries/render/src/render/CullTask.cpp | 6 +++--- libraries/render/src/render/Item.h | 9 +++++++++ scripts/system/libraries/WebTablet.js | 3 ++- 7 files changed, 53 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index eee8222051..2379685252 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -127,6 +127,11 @@ void ModelOverlay::update(float deltatime) { _model->setGroupCulled(_isGroupCulled, scene); metaDirty = true; } + if (_lodEnabledDirty) { + _lodEnabledDirty = false; + _model->setLODEnabled(_isLODEnabled, scene); + metaDirty = true; + } if (metaDirty) { transaction.updateItem(getRenderItemID(), [](Overlay& data) {}); } @@ -191,6 +196,14 @@ void ModelOverlay::setGroupCulled(bool groupCulled) { } } +void ModelOverlay::setLODEnabled(bool lodEnabled) { + if (lodEnabled != _isLODEnabled) { + _isLODEnabled = lodEnabled; + _lodEnabledDirty = true; + } +} + + void ModelOverlay::setProperties(const QVariantMap& properties) { auto origPosition = getWorldPosition(); auto origRotation = getWorldOrientation(); @@ -248,6 +261,12 @@ void ModelOverlay::setProperties(const QVariantMap& properties) { setGroupCulled(groupCulledValue.toBool()); } + auto lodEnabledValue = properties["isLODEnabled"]; + if (lodEnabledValue.isValid() && lodEnabledValue.canConvert(QVariant::Bool)) { + setLODEnabled(lodEnabledValue.toBool()); + } + + // jointNames is read-only. // jointPositions is read-only. // jointOrientations is read-only. @@ -765,5 +784,8 @@ render::ItemKey ModelOverlay::getKey() { if (_isGroupCulled) { builder.withMetaCullGroup(); } + if (!_isLODEnabled) { + builder.withLODDisabled(); + } return builder.build(); } \ No newline at end of file diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index bd922e258a..dc127afe48 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -69,6 +69,7 @@ public: void setDrawInFront(bool drawInFront) override; void setDrawHUDLayer(bool drawHUDLayer) override; void setGroupCulled(bool groupCulled); + void setLODEnabled(bool lodEnabled); void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override; void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override; @@ -130,6 +131,8 @@ private: bool _drawInHUDDirty { false }; bool _isGroupCulled { false }; bool _groupCulledDirty { false }; + bool _isLODEnabled{ true }; + bool _lodEnabledDirty{ true }; void processMaterials(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index a700c200f8..8b50f2e420 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -973,6 +973,17 @@ bool Model::isGroupCulled() const { return _renderItemKeyGlobalFlags.isSubMetaCulled(); } +void Model::setLODEnabled(bool isLODEnabled, const render::ScenePointer& scene) { + if (Model::isLODEnabled() != isLODEnabled) { + auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags); + _renderItemKeyGlobalFlags = (isLODEnabled ? keyBuilder.withLODEnabled() : keyBuilder.withLODDisabled()); + updateRenderItemsKey(scene); + } +} +bool Model::isLODEnabled() const { + return _renderItemKeyGlobalFlags.isLODEnabled(); +} + const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { return _renderItemKeyGlobalFlags; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e42da4ecb1..954cc57e0b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -119,6 +119,9 @@ public: bool isGroupCulled() const; void setGroupCulled(bool isGroupCulled, const render::ScenePointer& scene = nullptr); + bool isLODEnabled() const; + void setLODEnabled(bool isLODEnabled, const render::ScenePointer& scene = nullptr); + bool canCastShadow() const; void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene = nullptr); diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index b2930032a3..ad9f6b7076 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -205,7 +205,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (!srcFilter.selectsNothing()) { auto filter = render::ItemFilter::Builder(srcFilter).withoutSubMetaCulled().build(); - // Now get the bound, and + // Now get the bound, and // filter individually against the _filter // visibility cull if partially selected ( octree cell contianing it was partial) // distance cull if was a subcell item ( octree cell is way bigger than the item bound itself, so now need to test per item) @@ -294,7 +294,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, auto& item = scene->getItem(id); if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); - if (test.solidAngleTest(itemBound.bound)) { + if (item.getKey().isLODDisabled() || test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { item.fetchMetaSubItemBounds(outItems, (*scene)); @@ -329,7 +329,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); if (test.frustumTest(itemBound.bound)) { - if (test.solidAngleTest(itemBound.bound)) { + if (item.getKey().isLODDisabled() || test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { item.fetchMetaSubItemBounds(outItems, (*scene)); diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 88e85c604a..a30067cb5c 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -101,6 +101,7 @@ public: SHADOW_CASTER, // Item cast shadows META_CULL_GROUP, // As a meta item, the culling of my sub items is based solely on my bounding box and my visibility in the view SUB_META_CULLED, // As a sub item of a meta render item set as cull group, need to be set to my culling to the meta render it + LOD_DISABLED, // Item LOD behavior is disabled, it won't be LODed because of lod behavior in the view FIRST_TAG_BIT, // 8 Tags available to organize the items and filter them against LAST_TAG_BIT = FIRST_TAG_BIT + NUM_TAGS, @@ -160,6 +161,8 @@ public: Builder& withoutMetaCullGroup() { _flags.reset(META_CULL_GROUP); return (*this); } Builder& withSubMetaCulled() { _flags.set(SUB_META_CULLED); return (*this); } Builder& withoutSubMetaCulled() { _flags.reset(SUB_META_CULLED); return (*this); } + Builder& withLODDisabled() { _flags.set(LOD_DISABLED); return (*this); } + Builder& withLODEnabled() { _flags.reset(LOD_DISABLED); return (*this); } Builder& withTag(Tag tag) { _flags.set(FIRST_TAG_BIT + tag); return (*this); } // Set ALL the tags in one call using the Tag bits @@ -203,6 +206,9 @@ public: bool isSubMetaCulled() const { return _flags[SUB_META_CULLED]; } void setSubMetaCulled(bool metaCulled) { (metaCulled ? _flags.set(SUB_META_CULLED) : _flags.reset(SUB_META_CULLED)); } + bool isLODEnabled() const { return !_flags[LOD_DISABLED]; } + bool isLODDisabled() const { return _flags[LOD_DISABLED]; } + bool isTag(Tag tag) const { return _flags[FIRST_TAG_BIT + tag]; } uint8_t getTagBits() const { return ((_flags.to_ulong() & KEY_TAG_BITS_MASK) >> FIRST_TAG_BIT); } @@ -274,6 +280,9 @@ public: Builder& withoutSubMetaCulled() { _value.reset(ItemKey::SUB_META_CULLED); _mask.set(ItemKey::SUB_META_CULLED); return (*this); } Builder& withSubMetaCulled() { _value.set(ItemKey::SUB_META_CULLED); _mask.set(ItemKey::SUB_META_CULLED); return (*this); } + Builder& withLODEnabled() { _value.reset(ItemKey::LOD_DISABLED); _mask.set(ItemKey::LOD_DISABLED); return (*this); } + Builder& withLODDisabled() { _value.set(ItemKey::LOD_DISABLED); _mask.set(ItemKey::LOD_DISABLED); return (*this); } + Builder& withoutTag(ItemKey::Tag tagIndex) { _value.reset(ItemKey::FIRST_TAG_BIT + tagIndex); _mask.set(ItemKey::FIRST_TAG_BIT + tagIndex); return (*this); } Builder& withTag(ItemKey::Tag tagIndex) { _value.set(ItemKey::FIRST_TAG_BIT + tagIndex); _mask.set(ItemKey::FIRST_TAG_BIT + tagIndex); return (*this); } // Set ALL the tags in one call using the Tag bits and the Tag bits touched diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index c201a251d0..0d13874e4c 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -135,7 +135,8 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { dimensions: { x: tabletWidth, y: tabletHeight, z: tabletDepth }, parentID: MyAvatar.SELF_ID, visible: visible, - isGroupCulled: true + isGroupCulled: true, + isLODEnabled: false }; // compute position, rotation & parentJointIndex of the tablet