diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h index 114777ba0f..4d53652c0e 100644 --- a/interface/src/graphics/WorldBox.h +++ b/interface/src/graphics/WorldBox.h @@ -19,8 +19,6 @@ #include #include "Menu.h" - - class WorldBoxRenderData { public: typedef render::Payload Payload; @@ -29,8 +27,6 @@ public: int _val = 0; static render::ItemID _item; // unique WorldBoxRenderData - - static void renderWorldBox(RenderArgs* args, gpu::Batch& batch); }; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index ae56a8fc47..dcf90cd966 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -128,7 +128,7 @@ std::shared_ptr make_renderer(const EntityItemPointer& entity) { return std::shared_ptr(new T(entity), [](T* ptr) { ptr->deleteLater(); }); } -EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity) {} +EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity), _entityID(entity->getID()) {} EntityRenderer::~EntityRenderer() {} @@ -196,6 +196,23 @@ uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { return 0; } +bool EntityRenderer::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + auto renderWithZones = resultWithReadLock>([&] { + return _renderWithZones; + }); + if (!renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } + } + return false; + } + return true; +} + void EntityRenderer::render(RenderArgs* args) { if (!isValidRenderItem()) { return; @@ -385,6 +402,10 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity return true; } + if (entity->needsZoneOcclusionUpdate()) { + return true; + } + return false; } @@ -426,6 +447,10 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _canCastShadow = entity->getCanCastShadow(); setCullWithParent(entity->getCullWithParent()); _cauterized = entity->getCauterized(); + if (entity->needsZoneOcclusionUpdate()) { + entity->resetNeedsZoneOcclusionUpdate(); + setRenderWithZones(entity->getRenderWithZones()); + } entity->setNeedsRenderUpdate(false); }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 227eb6a018..9c787d82c2 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -65,6 +65,7 @@ public: virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; virtual Item::Bound getBound() override; + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override; protected: virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } @@ -109,6 +110,7 @@ protected: virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; } virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; } virtual void setCullWithParent(bool value) { _cullWithParent = value; } + virtual void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } template T withReadLockResult(const std::function& f) { @@ -143,6 +145,7 @@ protected: bool _cullWithParent { false }; RenderLayer _renderLayer { RenderLayer::WORLD }; PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; + QVector _renderWithZones; bool _cauterized { false }; bool _moving { false }; // Only touched on the rendering thread @@ -153,6 +156,7 @@ protected: std::mutex _materialsLock; quint64 _created; + QUuid _entityID; // The base class relies on comparing the model transform to the entity transform in order // to trigger an update, so the member must not be visible to derived classes as a modifiable diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5fbbdfa0b8..107890cd21 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1324,6 +1324,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce setKey(didVisualGeometryRequestSucceed); _model->setTagMask(getTagMask()); _model->setHifiRenderLayer(getHifiRenderLayer()); + _model->setPrimitiveMode(_primitiveMode); + _model->setCullWithParent(_cullWithParent); + _model->setRenderWithZones(_renderWithZones); emit requestRenderUpdate(); if(didVisualGeometryRequestSucceed) { emit DependencyManager::get()-> @@ -1507,6 +1510,13 @@ void ModelEntityRenderer::setCullWithParent(bool value) { } } +void ModelEntityRenderer::setRenderWithZones(const QVector& renderWithZones) { + Parent::setRenderWithZones(renderWithZones); + if (_model) { + _model->setRenderWithZones(renderWithZones); + } +} + // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 0119c7bc26..84384532d0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -165,6 +165,7 @@ protected: void setRenderLayer(RenderLayer value) override; void setPrimitiveMode(PrimitiveMode value) override; void setCullWithParent(bool value) override; + void setRenderWithZones(const QVector& renderWithZones) override; private: void animate(const TypedEntityPointer& entity); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index fbd10e2f5b..2ba1acea11 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -289,6 +289,17 @@ ShapeKey entities::TextPayload::getShapeKey() const { return ShapeKey::Builder::invalid(); } +bool entities::TextPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + auto entityTreeRenderer = DependencyManager::get(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + return std::static_pointer_cast(renderable)->passesZoneOcclusionTest(containingZones); + } + } + return false; +} + void entities::TextPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("TextPayload::render"); Q_ASSERT(args->_batch); @@ -388,4 +399,12 @@ template <> const ShapeKey shapeGetShapeKey(const TextPayload::Pointer& payload) template <> void payloadRender(const TextPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} + } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 63cf3e6e9e..87102daa32 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -94,6 +94,7 @@ public: Item::Bound getBound() const; ShapeKey getShapeKey() const; void render(RenderArgs* args); + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; protected: QUuid _entityID; @@ -109,6 +110,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones); } #endif // hifi_RenderableTextEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index bbb8c67ad1..948c6ca762 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -71,6 +71,11 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity } void ZoneEntityRenderer::doRender(RenderArgs* args) { + // This is necessary so that zones can themselves be zone culled + if (!passesZoneOcclusionTest(CullTest::_prevContainingZones)) { + return; + } + if (!_stage) { _stage = args->_scene->getStage(); assert(_stage); @@ -180,6 +185,8 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { _bloomStage->_currentFrame.pushBloom(_bloomIndex); } } + + CullTest::_containingZones.insert(_entityID); } void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index cc215d3528..0fffe2de35 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -105,6 +105,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_RENDER_LAYER; requestedProperties += PROP_PRIMITIVE_MODE; requestedProperties += PROP_IGNORE_PICK_INTERSECTION; + requestedProperties += PROP_RENDER_WITH_ZONES; requestedProperties += _grabProperties.getEntityProperties(params); // Physics @@ -300,6 +301,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)getRenderLayer()); APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, getIgnorePickIntersection()); + APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, getRenderWithZones()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -875,6 +877,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); READ_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); + READ_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1354,6 +1357,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderLayer, getRenderLayer); COPY_ENTITY_PROPERTY_TO_PROPERTIES(primitiveMode, getPrimitiveMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignorePickIntersection, getIgnorePickIntersection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderWithZones, getRenderWithZones); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1503,6 +1507,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderLayer, setRenderLayer); SET_ENTITY_PROPERTY_FROM_PROPERTIES(primitiveMode, setPrimitiveMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignorePickIntersection, setIgnorePickIntersection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderWithZones, setRenderWithZones); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -3520,3 +3525,18 @@ void EntityItem::disableGrab(GrabPointer grab) { } } } + +void EntityItem::setRenderWithZones(const QVector& renderWithZones) { + withWriteLock([&] { + if (_renderWithZones != renderWithZones) { + _needsZoneOcclusionUpdate = true; + _renderWithZones = renderWithZones; + } + }); +} + +QVector EntityItem::getRenderWithZones() const { + return resultWithReadLock>([&] { + return _renderWithZones; + }); +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 14b8b259cc..2d2d158ebd 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -577,6 +577,11 @@ public: bool needsRenderUpdate() const { return resultWithReadLock([&] { return _needsRenderUpdate; }); } void setNeedsRenderUpdate(bool needsRenderUpdate) { withWriteLock([&] { _needsRenderUpdate = needsRenderUpdate; }); } + void setRenderWithZones(const QVector& renderWithZones); + QVector getRenderWithZones() const; + bool needsZoneOcclusionUpdate() const { return _needsZoneOcclusionUpdate; } + void resetNeedsZoneOcclusionUpdate() { withWriteLock([&] { _needsZoneOcclusionUpdate = false; }); } + signals: void spaceUpdate(std::pair data); @@ -765,6 +770,9 @@ protected: QHash _grabActions; + QVector _renderWithZones; + mutable bool _needsZoneOcclusionUpdate { false }; + bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 2b8f2b4c14..54f84beee1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -421,6 +421,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RENDER_LAYER, renderLayer); CHECK_PROPERTY_CHANGE(PROP_PRIMITIVE_MODE, primitiveMode); CHECK_PROPERTY_CHANGE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); + CHECK_PROPERTY_CHANGE(PROP_RENDER_WITH_ZONES, renderWithZones); changedProperties += _grab.getChangedProperties(); // Physics @@ -793,6 +794,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * avatar entities, false if they won't be. * @property {Uuid} cloneOriginID - The ID of the entity that this entity was cloned from. * + * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. + * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within + * one of the zones in this list. + * * @property {Entities.Grab} grab - The entity's grab-related properties. * * @property {string} itemName="" - Certifiable name of the Marketplace item. @@ -1583,6 +1588,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_RENDER_LAYER, renderLayer, getRenderLayerAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PRIMITIVE_MODE, primitiveMode, getPrimitiveModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -2000,6 +2006,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(renderLayer, RenderLayer); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(primitiveMode, PrimitiveMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(ignorePickIntersection, bool, setIgnorePickIntersection); + COPY_PROPERTY_FROM_QSCRIPTVALUE(renderWithZones, qVectorQUuid, setRenderWithZones); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -2293,6 +2300,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(renderLayer); COPY_PROPERTY_IF_CHANGED(primitiveMode); COPY_PROPERTY_IF_CHANGED(ignorePickIntersection); + COPY_PROPERTY_IF_CHANGED(renderWithZones); _grab.merge(other._grab); // Physics @@ -2585,6 +2593,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer); ADD_PROPERTY_TO_MAP(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode); ADD_PROPERTY_TO_MAP(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool); + ADD_PROPERTY_TO_MAP(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector); { // Grab ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable); ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic); @@ -3073,6 +3082,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)properties.getRenderLayer()); APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)properties.getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, properties.getIgnorePickIntersection()); + APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, properties.getRenderWithZones()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3562,6 +3572,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3979,6 +3990,7 @@ void EntityItemProperties::markAllChanged() { _renderLayerChanged = true; _primitiveModeChanged = true; _ignorePickIntersectionChanged = true; + _renderWithZonesChanged = true; _grab.markAllChanged(); // Physics @@ -4381,6 +4393,9 @@ QList EntityItemProperties::listChangedProperties() { if (ignorePickIntersectionChanged()) { out += "ignorePickIntersection"; } + if (renderWithZonesChanged()) { + out += "renderWithZones"; + } getGrab().listChangedProperties(out); // Physics diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 63d8183899..69c25cecdd 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -192,6 +192,7 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer, RenderLayer::WORLD); DEFINE_PROPERTY_REF_ENUM(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode, PrimitiveMode::SOLID); DEFINE_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool, false); + DEFINE_PROPERTY_REF(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector, QVector()); DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup); // Physics diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 4c989ef74e..c25eb21e6c 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -119,6 +119,7 @@ inline QScriptValue qVectorVec3Color_convertScriptValue(QScriptEngine* e, const inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorQuatToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorBoolToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorFloatToScriptValue(e, v); } +inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorQUuidToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QRect& v) { return qRectToScriptValue(e, v); } @@ -216,6 +217,7 @@ typedef QVector qVectorVec3; typedef QVector qVectorQuat; typedef QVector qVectorBool; typedef QVector qVectorFloat; +typedef QVector qVectorQUuid; inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); } inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); } inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isValid) { @@ -293,6 +295,11 @@ inline qVectorBool qVectorBool_convertFromScriptValue(const QScriptValue& v, boo return qVectorBoolFromScriptValue(v); } +inline qVectorQUuid qVectorQUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = true; + return qVectorQUuidFromScriptValue(v); +} + inline glm::quat quat_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = false; /// assume it can't be converted QScriptValue x = v.property("x"); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index d5af337a7d..c186b2b87f 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -43,6 +43,7 @@ enum EntityPropertyList { PROP_RENDER_LAYER, PROP_PRIMITIVE_MODE, PROP_IGNORE_PICK_INTERSECTION, + PROP_RENDER_WITH_ZONES, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fbf575065e..1bfeff5e7f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -275,6 +275,7 @@ enum class EntityVersion : PacketVersion { ShadowBiasAndDistance, TextEntityFonts, ScriptServerKinematicMotion, + ZoneOcclusion, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 8ab502e951..5e6825c886 100755 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -482,6 +482,19 @@ bool OctreePacketData::appendValue(const QVector& value) { return success; } +bool OctreePacketData::appendValue(const QVector& value) { + uint16_t qVecSize = value.size(); + bool success = appendValue(qVecSize); + if (success) { + success = append((const unsigned char*)value.constData(), qVecSize * sizeof(QUuid)); + if (success) { + _bytesOfValues += qVecSize * sizeof(QUuid); + _totalBytesOfValues += qVecSize * sizeof(QUuid); + } + } + return success; +} + bool OctreePacketData::appendValue(const glm::quat& value) { const size_t VALUES_PER_QUAT = 4; const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT; @@ -774,6 +787,15 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto return (dataBytes - start) + (int)sizeof(uint16_t); } +int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { + uint16_t length; + memcpy(&length, dataBytes, sizeof(uint16_t)); + dataBytes += sizeof(length); + result.resize(length); + memcpy(result.data(), dataBytes, length * sizeof(QUuid)); + return sizeof(uint16_t) + length * sizeof(QUuid); +} + int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) { uint16_t length; memcpy(&length, dataBytes, sizeof(length)); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 46e5de9bda..2050dd1487 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -186,6 +186,9 @@ public: /// appends a QVector of bools to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QVector& value); + /// appends a QVector of QUuids to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const QVector& value); + /// appends a packed quat to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::quat& value); @@ -284,6 +287,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); + static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result); static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QRect& result); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index e82af5395f..88ba24cbc2 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -55,6 +55,13 @@ template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payl template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} } MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : @@ -167,10 +174,23 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputStream(0, _drawMesh->getVertexStream()); } - void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { batch.setModelTransform(_drawTransform); } +bool MeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + if (!_renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : _renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } + } + return false; + } + return true; +} void MeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("MeshPartPayload::render"); @@ -242,6 +262,12 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren return payload->render(args); } +template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} } ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index ee205bd778..db3e1fca4d 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -75,11 +75,15 @@ public: void setCullWithParent(bool value) { _cullWithParent = value; } + void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; + static bool enableMaterialProceduralShaders; protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; bool _cullWithParent { false }; + QVector _renderWithZones; uint64_t _created; }; @@ -88,6 +92,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload); template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); } class ModelMeshPartPayload : public MeshPartPayload { @@ -154,6 +159,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); } #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d8172112ff..db4fc46e36 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -976,6 +976,16 @@ void Model::setCullWithParent(bool cullWithParent) { } } +void Model::setRenderWithZones(const QVector& renderWithZones) { + render::Transaction transaction; + for(auto item : _modelMeshRenderItemIDs) { + transaction.updateItem(item, [renderWithZones](ModelMeshPartPayload& data) { + data.setRenderWithZones(renderWithZones); + }); + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + 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 b677861e9f..ec68db4b27 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -131,6 +131,8 @@ public: void setCullWithParent(bool value); + void setRenderWithZones(const QVector& renderWithZones); + // Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model. const render::ItemKey getRenderItemKeyGlobalFlags() const; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a75192bad7..5fee00b370 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -13,15 +13,16 @@ #include #include #include +#include #include #include #include +#include #include #include "Forward.h" - class AABox; namespace render { @@ -142,13 +143,6 @@ namespace render { bool _takingSnapshot { false }; StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE }; std::function _stencilMaskOperator; - - float _visionSqueezeX { 0.0f }; - float _visionSqueezeY { 0.0f }; - float _visionSqueezeTransition { 0.15f }; - int _visionSqueezePerEye { 0 }; - float _visionSqueezeGroundPlaneY { 0.0f }; - float _visionSqueezeSpotlightSize { 0.02f }; }; } diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 068d6f9851..f309d5a3bf 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -19,6 +19,9 @@ using namespace render; +std::unordered_set CullTest::_containingZones = std::unordered_set(); +std::unordered_set CullTest::_prevContainingZones = std::unordered_set(); + CullTest::CullTest(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails, ViewFrustumPointer antiFrustum) : _functor(functor), _args(pargs), @@ -64,46 +67,8 @@ bool CullTest::solidAngleTest(const AABox& bound) { return true; } -void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, - const ItemBounds& inItems, ItemBounds& outItems) { - assert(renderContext->args); - assert(renderContext->args->hasViewFrustum()); - - RenderArgs* args = renderContext->args; - const ViewFrustum& frustum = args->getViewFrustum(); - - details._considered += (int)inItems.size(); - - // Culling / LOD - for (auto item : inItems) { - if (item.bound.isNull()) { - outItems.emplace_back(item); // One more Item to render - continue; - } - - // TODO: some entity types (like lights) might want to be rendered even - // when they are outside of the view frustum... - bool inView; - { - PerformanceTimer perfTimer("boxIntersectsFrustum"); - inView = frustum.boxIntersectsFrustum(item.bound); - } - if (inView) { - bool bigEnoughToRender; - { - PerformanceTimer perfTimer("shouldRender"); - bigEnoughToRender = cullFunctor(args, item.bound); - } - if (bigEnoughToRender) { - outItems.emplace_back(item); // One more Item to render - } else { - details._tooSmall++; - } - } else { - details._outOfView++; - } - } - details._rendered += (int)outItems.size(); +bool CullTest::zoneOcclusionTest(const render::Item& item) { + return item.passesZoneOcclusionTest(_containingZones); } void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemBounds& outItems) { @@ -117,7 +82,7 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const outItems.reserve(items.size()); for (auto& id : items) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && item.passesZoneOcclusionTest(CullTest::_containingZones)) { outItems.emplace_back(ItemBound(id, item.getBound())); } } @@ -126,7 +91,6 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const void FetchSpatialTree::configure(const Config& config) { _justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum); _freezeFrustum = config.freezeFrustum; - _lodAngle = config.lodAngle; } void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemSpatialTree::ItemSelection& outSelection) { @@ -215,7 +179,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideFitItems"); for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -230,7 +194,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideSmallItems"); for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -245,7 +209,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialFitItems"); for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -260,7 +224,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialSmallItems"); for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -277,7 +241,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideFitItems"); for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -292,7 +256,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideSmallItems"); for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); @@ -309,7 +273,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialFitItems"); for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); @@ -326,14 +290,12 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialSmallItems"); for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); - if (test.frustumTest(itemBound.bound)) { - if (test.solidAngleTest(itemBound.bound)) { - outItems.emplace_back(itemBound); - if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); - } + if (test.frustumTest(itemBound.bound) && test.solidAngleTest(itemBound.bound)) { + outItems.emplace_back(itemBound); + if (item.getKey().isMetaCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); } } } @@ -444,3 +406,13 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext args->popViewFrustum(); } } + +void ClearContainingZones::run(const RenderContextPointer& renderContext) { + // This is a bit of a hack. We want to do zone culling as early as possible, so we do it + // during the RenderFetchCullSortTask (in CullSpatialSelection and FetchNonspatialItems), + // but the zones aren't collected until after (in SetupZones). To get around this, + // we actually use the zones from the previous frame to render, and then clear at the beginning + // of the next frame + CullTest::_prevContainingZones = CullTest::_containingZones; + CullTest::_containingZones.clear(); +} \ No newline at end of file diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index e67edd6666..9a7466223d 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -19,9 +19,6 @@ namespace render { using CullFunctor = std::function; - void cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, - const ItemBounds& inItems, ItemBounds& outItems); - // Culling Frustum / solidAngle test helper class struct CullTest { CullFunctor _functor; @@ -36,6 +33,10 @@ namespace render { bool frustumTest(const AABox& bound); bool antiFrustumTest(const AABox& bound); bool solidAngleTest(const AABox& bound); + bool zoneOcclusionTest(const render::Item& item); + + static std::unordered_set _containingZones; + static std::unordered_set _prevContainingZones; }; class FetchNonspatialItems { @@ -48,7 +49,6 @@ namespace render { Q_OBJECT Q_PROPERTY(int numItems READ getNumItems) Q_PROPERTY(bool freezeFrustum MEMBER freezeFrustum WRITE setFreezeFrustum) - Q_PROPERTY(float LODAngle MEMBER lodAngle NOTIFY dirty) public: int numItems{ 0 }; @@ -56,7 +56,6 @@ namespace render { bool freezeFrustum{ false }; - float lodAngle{ 2.0 }; public slots: void setFreezeFrustum(bool enabled) { freezeFrustum = enabled; emit dirty(); } @@ -68,7 +67,6 @@ namespace render { bool _freezeFrustum{ false }; // initialized by Config bool _justFrozeFrustum{ false }; ViewFrustum _frozenFrustum; - float _lodAngle; public: using Config = FetchSpatialTreeConfig; @@ -159,6 +157,12 @@ namespace render { render::CullFunctor _cullFunctor; }; + + class ClearContainingZones { + public: + using JobModel = Job::Model; + void run(const RenderContextPointer& renderContext); + }; } #endif // hifi_render_CullTask_h; \ No newline at end of file diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 532964777f..f21df58368 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -154,4 +154,10 @@ namespace render { return payload->metaFetchMetaSubItems(subItems); } + template <> bool payloadPassesZoneOcclusionTest(const PayloadProxyInterface::Pointer& payload, const std::unordered_set& containingZones) { + if (!payload) { + return false; + } + return payload->passesZoneOcclusionTest(containingZones); + } } diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 3383101b5b..cb9fb32c7f 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -436,6 +436,8 @@ public: virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; + ~PayloadInterface() {} // Status interface is local to the base class @@ -487,6 +489,8 @@ public: uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const { return _payload->passesZoneOcclusionTest(containingZones); } + // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } @@ -537,6 +541,10 @@ template const ShapeKey shapeGetShapeKey(const std::shared_ptr& pay // Meta items act as the grouping object for several sub items (typically shapes). template uint32_t metaFetchMetaSubItems(const std::shared_ptr& payloadData, ItemIDs& subItems) { return 0; } +// Zone Occlusion Interface +// Allows payloads to determine if they should render or not, based on the zones that contain the current camera +template bool payloadPassesZoneOcclusionTest(const std::shared_ptr& payloadData, const std::unordered_set& containingZones) { return true; } + // THe Payload class is the real Payload to be used // THis allow anything to be turned into a Payload as long as the required interface functions are available // When creating a new kind of payload from a new "stuff" class then you need to create specialized version for "stuff" @@ -561,6 +569,8 @@ public: // Meta Type Interface virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const override { return metaFetchMetaSubItems(_data, subItems); } + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override { return payloadPassesZoneOcclusionTest(_data, containingZones); } + protected: DataPointer _data; @@ -615,6 +625,7 @@ public: virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); @@ -622,7 +633,7 @@ template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Point template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const PayloadProxyInterface::Pointer& payload, ItemIDs& subItems); template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload); - +template <> bool payloadPassesZoneOcclusionTest(const PayloadProxyInterface::Pointer& payload, const std::unordered_set& containingZones); typedef Item::PayloadPointer PayloadPointer; typedef std::vector Payloads; diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index ebcf5a432b..b2656a597f 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -74,6 +74,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto filteredLayeredOpaque = task.addJob("FilterLayeredOpaque", layeredOpaques, ItemKey::Layer::LAYER_1); const auto filteredLayeredTransparent = task.addJob("FilterLayeredTransparent", layeredTransparents, ItemKey::Layer::LAYER_1); + task.addJob("ClearContainingZones"); output = Output(BucketList{ opaques, transparents, lights, metas, filteredLayeredOpaque.getN(0), filteredLayeredTransparent.getN(0), diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 87cd269c97..97ca26b221 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -36,6 +36,7 @@ int qVectorVec3MetaTypeId = qRegisterMetaType>(); int qVectorQuatMetaTypeId = qRegisterMetaType>(); int qVectorBoolMetaTypeId = qRegisterMetaType>(); int qVectorGLMUint32MetaTypeId = qRegisterMetaType>("QVector"); +int qVectorQUuidMetaTypeId = qRegisterMetaType>(); int quatMetaTypeId = qRegisterMetaType(); int pickRayMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); @@ -58,6 +59,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, qVectorBoolToScriptValue, qVectorBoolFromScriptValue); qScriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue); qScriptRegisterMetaType(engine, qVectorIntToScriptValue, qVectorIntFromScriptValue); + qScriptRegisterMetaType(engine, qVectorQUuidToScriptValue, qVectorQUuidFromScriptValue); qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue); qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue); @@ -874,6 +876,22 @@ QVector qVectorFloatFromScriptValue(const QScriptValue& array) { return newVector; } +QScriptValue qVectorQUuidToScriptValue(QScriptEngine* engine, const QVector& vector) { + QScriptValue array = engine->newArray(); + for (int i = 0; i < vector.size(); i++) { + array.setProperty(i, quuidToScriptValue(engine, vector.at(i))); + } + return array; +} + +void qVectorQUuidFromScriptValue(const QScriptValue& array, QVector& vector) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + vector << array.property(i).toVariant().toUuid(); + } +} + QVector qVectorQUuidFromScriptValue(const QScriptValue& array) { if (!array.isArray()) { return QVector(); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 3b47bb70c6..fa7ae624b2 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -247,6 +247,8 @@ QVector qVectorFloatFromScriptValue(const QScriptValue& array); QScriptValue qVectorIntToScriptValue(QScriptEngine* engine, const QVector& vector); void qVectorIntFromScriptValue(const QScriptValue& array, QVector& vector); +QScriptValue qVectorQUuidToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorQUuidFromScriptValue(const QScriptValue& array, QVector& vector); QVector qVectorQUuidFromScriptValue(const QScriptValue& array); QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube);