From 8af1beca8dd72288c27b63c1b7a8ec535b1a4615 Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Mon, 4 Jun 2018 12:07:57 -0700
Subject: [PATCH] add isGroupCulled for model overlays

---
 interface/src/ui/overlays/Base3DOverlay.cpp   | 20 +++++++++++++
 interface/src/ui/overlays/Base3DOverlay.h     |  1 +
 interface/src/ui/overlays/ModelOverlay.cpp    | 22 ++++++++++++++
 interface/src/ui/overlays/ModelOverlay.h      |  4 +++
 interface/src/ui/overlays/Overlay.cpp         | 17 +++++++++++
 interface/src/ui/overlays/Overlay.h           |  1 +
 interface/src/ui/overlays/OverlaysPayload.cpp | 29 +------------------
 libraries/render/src/render/Item.h            |  1 +
 scripts/system/libraries/WebTablet.js         |  3 +-
 9 files changed, 69 insertions(+), 29 deletions(-)

diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp
index f4efd1301d..f59b513bd5 100644
--- a/interface/src/ui/overlays/Base3DOverlay.cpp
+++ b/interface/src/ui/overlays/Base3DOverlay.cpp
@@ -349,3 +349,23 @@ void Base3DOverlay::setVisible(bool visible) {
     Parent::setVisible(visible);
     notifyRenderVariableChange();
 }
+
+render::ItemKey Base3DOverlay::getKey() {
+    auto builder = render::ItemKey::Builder(Overlay::getKey());
+
+    if (getDrawInFront()) {
+        builder.withLayer(render::hifi::LAYER_3D_FRONT);
+    } else if (getDrawHUDLayer()) {
+        builder.withLayer(render::hifi::LAYER_3D_HUD);
+    } else {
+        builder.withoutLayer();
+    }
+
+    builder.withoutViewSpace();
+
+    if (isTransparent()) {
+        builder.withTransparent();
+    }
+
+    return builder.build();
+}
\ No newline at end of file
diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h
index ab83a64273..2a63a6cb67 100644
--- a/interface/src/ui/overlays/Base3DOverlay.h
+++ b/interface/src/ui/overlays/Base3DOverlay.h
@@ -35,6 +35,7 @@ public:
     // getters
     virtual bool is3D() const override { return true; }
 
+    virtual render::ItemKey getKey() override;
     virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); }
     virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
 
diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp
index a541b3365f..4ed7072f23 100644
--- a/interface/src/ui/overlays/ModelOverlay.cpp
+++ b/interface/src/ui/overlays/ModelOverlay.cpp
@@ -115,6 +115,10 @@ void ModelOverlay::update(float deltatime) {
         _drawInHUDDirty = false;
         _model->setLayeredInHUD(getDrawHUDLayer(), scene);
     }
+    if (_groupCulledDirty) {
+        _groupCulledDirty = false;
+        _model->setGroupCulled(_isGroupCulled);
+    }
     scene->enqueueTransaction(transaction);
 
     if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) {
@@ -158,6 +162,11 @@ void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) {
     _drawInHUDDirty = true;
 }
 
+void ModelOverlay::setGroupCulled(bool groupCulled) {
+    _isGroupCulled = groupCulled;
+    _groupCulledDirty = true;
+}
+
 void ModelOverlay::setProperties(const QVariantMap& properties) {
     auto origPosition = getWorldPosition();
     auto origRotation = getWorldOrientation();
@@ -210,6 +219,11 @@ void ModelOverlay::setProperties(const QVariantMap& properties) {
                                   Q_ARG(const QVariantMap&, textureMap));
     }
 
+    auto groupCulledValue = properties["isGroupCulled"];
+    if (groupCulledValue.isValid() && groupCulledValue.canConvert(QVariant::Bool)) {
+        setGroupCulled(groupCulledValue.toBool());
+    }
+
     // jointNames is read-only.
     // jointPositions is read-only.
     // jointOrientations is read-only.
@@ -711,3 +725,11 @@ scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() {
     }
     return result;
 }
+
+render::ItemKey ModelOverlay::getKey() {
+    auto builder = render::ItemKey::Builder(Base3DOverlay::getKey());
+    if (_isGroupCulled) {
+        builder.withMetaCullGroup();
+    }
+    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 3ef3f23fec..334c9c06f1 100644
--- a/interface/src/ui/overlays/ModelOverlay.h
+++ b/interface/src/ui/overlays/ModelOverlay.h
@@ -33,6 +33,7 @@ public:
 
     virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override;
 
+    render::ItemKey getKey() override;
     void clearSubRenderItemIDs();
     void setSubRenderItemIDs(const render::ItemIDs& ids);
 
@@ -63,6 +64,7 @@ public:
     void setVisible(bool visible) override;
     void setDrawInFront(bool drawInFront) override;
     void setDrawHUDLayer(bool drawHUDLayer) override;
+    void setGroupCulled(bool groupCulled);
 
     void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override;
     void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override;
@@ -121,6 +123,8 @@ private:
     bool _visibleDirty { true };
     bool _drawInFrontDirty { false };
     bool _drawInHUDDirty { false };
+    bool _isGroupCulled { false };
+    bool _groupCulledDirty { false };
 
     void processMaterials();
 
diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp
index 2c0c7c71b6..faa15ee2b4 100644
--- a/interface/src/ui/overlays/Overlay.cpp
+++ b/interface/src/ui/overlays/Overlay.cpp
@@ -244,4 +244,21 @@ void Overlay::addMaterial(graphics::MaterialLayer material, const std::string& p
 void Overlay::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
     std::lock_guard<std::mutex> lock(_materialsLock);
     _materials[parentMaterialName].remove(material);
+}
+
+render::ItemKey Overlay::getKey() {
+    auto builder = render::ItemKey::Builder().withTypeShape();
+
+    builder.withViewSpace();
+    builder.withLayer(render::hifi::LAYER_2D);
+
+    if (!getVisible()) {
+        builder.withInvisible();
+    }
+
+    // always visible in primary view.  if isVisibleInSecondaryCamera, also draw in secondary view
+    render::hifi::Tag viewTagBits = getIsVisibleInSecondaryCamera() ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW;
+    builder.withTagBits(viewTagBits);
+
+    return builder.build();
 }
\ No newline at end of file
diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h
index 890d5178e5..45fc77a452 100644
--- a/interface/src/ui/overlays/Overlay.h
+++ b/interface/src/ui/overlays/Overlay.h
@@ -40,6 +40,7 @@ public:
     virtual void update(float deltatime) {}
     virtual void render(RenderArgs* args) = 0;
 
+    virtual render::ItemKey getKey();
     virtual AABox getBounds() const = 0;
     virtual bool supportsGetProperty() const { return true; }
 
diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp
index 6b55b2b701..37fadef0b4 100644
--- a/interface/src/ui/overlays/OverlaysPayload.cpp
+++ b/interface/src/ui/overlays/OverlaysPayload.cpp
@@ -32,34 +32,7 @@
 
 namespace render {
     template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
-        auto builder = ItemKey::Builder().withTypeShape();
-        if (overlay->is3D()) {
-            auto overlay3D = std::static_pointer_cast<Base3DOverlay>(overlay);
-            if (overlay3D->getDrawInFront()) {
-                builder.withLayer(render::hifi::LAYER_3D_FRONT);
-            } else if (overlay3D->getDrawHUDLayer()) {
-                builder.withLayer(render::hifi::LAYER_3D_HUD);
-            }
-
-            if (overlay->isTransparent()) {
-                builder.withTransparent();
-            }
-        } else {
-            builder.withViewSpace();
-            builder.withLayer(render::hifi::LAYER_2D);
-        }
-
-        if (!overlay->getVisible()) {
-            builder.withInvisible();
-        }
-
-        // always visible in primary view.  if isVisibleInSecondaryCamera, also draw in secondary view
-        uint32_t viewTagBits = render::hifi::TAG_MAIN_VIEW |
-            (overlay->getIsVisibleInSecondaryCamera() ? render::hifi::TAG_SECONDARY_VIEW : render::hifi::TAG_NONE);
-
-        builder.withTagBits(viewTagBits);
-
-        return builder.build();
+        return overlay->getKey();
     }
     template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
         return overlay->getBounds();
diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h
index 1dfef73686..28994d82b6 100644
--- a/libraries/render/src/render/Item.h
+++ b/libraries/render/src/render/Item.h
@@ -149,6 +149,7 @@ public:
         Builder& withTypeMeta() { _flags.set(TYPE_META); return (*this); }
         Builder& withTransparent() { _flags.set(TRANSLUCENT); return (*this); }
         Builder& withViewSpace() { _flags.set(VIEW_SPACE); return (*this); }
+        Builder& withoutViewSpace() { _flags.reset(VIEW_SPACE); return (*this); }
         Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); }
         Builder& withDeformed() { _flags.set(DEFORMED); return (*this); }
         Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); }
diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js
index 783b91f5f0..fade6f6b26 100644
--- a/scripts/system/libraries/WebTablet.js
+++ b/scripts/system/libraries/WebTablet.js
@@ -115,7 +115,8 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
         }),
         dimensions: { x: tabletWidth, y: tabletHeight, z: tabletDepth },
         parentID: MyAvatar.SELF_ID,
-        visible: visible
+        visible: visible,
+        isGroupCulled: true
     };
 
     // compute position, rotation & parentJointIndex of the tablet