From 678effdb4818a47872eb224d5512245adfe12d9e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 26 May 2018 23:28:59 -0700 Subject: [PATCH] Cleaning up the Model set ItemKey flags and bringing Item::Layer in the ItemKey --- interface/src/avatar/MyAvatar.cpp | 14 +- interface/src/ui/overlays/ModelOverlay.cpp | 6 +- interface/src/ui/overlays/OverlaysPayload.cpp | 8 +- .../src/avatars-renderer/Avatar.cpp | 32 +++-- .../src/avatars-renderer/SkeletonModel.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 12 +- .../render-utils/src/MeshPartPayload.cpp | 50 +++++-- libraries/render-utils/src/MeshPartPayload.h | 4 +- libraries/render-utils/src/Model.cpp | 131 ++++++++---------- libraries/render-utils/src/Model.h | 16 +-- libraries/render/src/render/Item.cpp | 8 +- libraries/render/src/render/Item.h | 79 ++++++++--- 12 files changed, 227 insertions(+), 135 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 69f81ab257..ced6d55784 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1483,7 +1483,10 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); - _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); + _skeletonModel->setViewMask(render::ItemKey::TAG_BITS_NONE); + _skeletonModel->setGroupCulled(true); + _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene()); + _headBoneSet.clear(); _cauterizationNeedsUpdate = true; @@ -2060,12 +2063,11 @@ void MyAvatar::preDisplaySide(const RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { uint8_t modelRenderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE; modelRenderTagBits |= render::ItemKey::TAG_BITS_1; - _attachmentModels[i]->setVisibleInScene(true, qApp->getMain3DScene(), - modelRenderTagBits, false); - uint8_t castShadowRenderTagBits = render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1; - _attachmentModels[i]->setCanCastShadow(true, qApp->getMain3DScene(), - castShadowRenderTagBits, false); + _attachmentModels[i]->setViewMask(modelRenderTagBits); + _attachmentModels[i]->setGroupCulled(false); + _attachmentModels[i]->setCanCastShadow(true); + _attachmentModels[i]->setVisibleInScene(true, qApp->getMain3DScene()); } } } diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 27e3bd0e2d..cb66828dc5 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -103,10 +103,12 @@ void ModelOverlay::update(float deltatime) { if (_visibleDirty) { _visibleDirty = false; // don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true - _model->setVisibleInScene(getVisible(), scene, + _model->setViewMask((_isVisibleInSecondaryCamera ? render::ItemKey::TAG_BITS_1 : render::ItemKey::TAG_BITS_NONE), scene); + _model->setVisibleInScene(getVisible(), scene); + /*, render::ItemKey::TAG_BITS_0 | (_isVisibleInSecondaryCamera ? render::ItemKey::TAG_BITS_1 : render::ItemKey::TAG_BITS_NONE), - false); + false);*/ } if (_drawInFrontDirty) { _drawInFrontDirty = false; diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 185547a333..1a79c54ac2 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -35,14 +35,18 @@ namespace render { auto builder = ItemKey::Builder().withTypeShape(); if (overlay->is3D()) { auto overlay3D = std::static_pointer_cast(overlay); - if (overlay3D->getDrawInFront() || overlay3D->getDrawHUDLayer()) { - builder.withLayered(); + if (overlay3D->getDrawInFront()) { + builder.withLayer(render::Item::LAYER_3D_FRONT); + } else if (overlay3D->getDrawHUDLayer()) { + builder.withLayer(render::Item::LAYER_3D_HUD); } + if (overlay->isTransparent()) { builder.withTransparent(); } } else { builder.withViewSpace(); + builder.withLayer(render::Item::LAYER_2D); } if (!overlay->getVisible()) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 924fded652..2d675088f7 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -588,13 +588,18 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc _renderBound = getBounds(); transaction.resetItem(_renderItemID, avatarPayloadPointer); _skeletonModel->addToScene(scene, transaction); - _skeletonModel->setVisibleInScene(_isMeshEnableVisible, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, true); - _skeletonModel->setCanCastShadow(true, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, true); + _skeletonModel->setViewMask(Model::AllViews); + _skeletonModel->setGroupCulled(true); + _skeletonModel->setCanCastShadow(true); + _skeletonModel->setVisibleInScene(_isMeshEnableVisible, scene); + processMaterials(); for (auto& attachmentModel : _attachmentModels) { attachmentModel->addToScene(scene, transaction); - attachmentModel->setVisibleInScene(_isMeshEnableVisible, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, false); - attachmentModel->setCanCastShadow(true, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, false); + attachmentModel->setViewMask(Model::AllViews); + attachmentModel->setGroupCulled(true); + attachmentModel->setCanCastShadow(true); + attachmentModel->setVisibleInScene(_isMeshEnableVisible, scene); } _mustFadeIn = true; @@ -806,8 +811,12 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { _skeletonModel->removeFromScene(scene, transaction); _skeletonModel->addToScene(scene, transaction); - _skeletonModel->setVisibleInScene(_isMeshEnableVisible, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, true); - _skeletonModel->setCanCastShadow(true, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, true); + + _skeletonModel->setViewMask(Model::AllViews); + _skeletonModel->setGroupCulled(true); + _skeletonModel->setCanCastShadow(true); + _skeletonModel->setVisibleInScene(_isMeshEnableVisible, scene); + processMaterials(); canTryFade = true; _isAnimatingScale = true; @@ -816,16 +825,19 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) { attachmentModel->removeFromScene(scene, transaction); attachmentModel->addToScene(scene, transaction); - attachmentModel->setVisibleInScene(_isMeshEnableVisible, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, false); - attachmentModel->setCanCastShadow(true, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, false); + + attachmentModel->setViewMask(Model::AllViews); + attachmentModel->setGroupCulled(true); + attachmentModel->setCanCastShadow(true); + attachmentModel->setVisibleInScene(_isMeshEnableVisible, scene); } } if (_needMeshVisibleSwitch) { - _skeletonModel->setVisibleInScene(_isMeshEnableVisible, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, true); + _skeletonModel->setVisibleInScene(_isMeshEnableVisible, scene); for (auto attachmentModel : _attachmentModels) { if (attachmentModel->isRenderable()) { - attachmentModel->setVisibleInScene(_isMeshEnableVisible, scene, render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1, false); + attachmentModel->setVisibleInScene(_isMeshEnableVisible, scene); } } updateRenderItem(transaction); diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 428f86f0ab..de8c02f10e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -35,7 +35,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _useDualQuaternionSkinning = true; // Avatars all cast shadow - _canCastShadow = true; + setCanCastShadow(true); assert(_owningAvatar); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c4fa71a488..6a300ca587 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1391,16 +1391,22 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce render::ItemKey::TAG_BITS_1 : // draw in every view except the main one (view zero) render::ItemKey::TAG_BITS_ALL; // draw in all views - if (model->isVisible() != _visible || model->getViewTagBits() != viewTaskBits) { + if (model->isVisible() != _visible) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - model->setVisibleInScene(_visible, scene, viewTaskBits, false); + // model->setVisibleInScene(_visible, scene, viewTaskBits, false); + model->setVisibleInScene(_visible, scene); } + + if (model->getViewMask() != viewTaskBits) { + model->setViewMask(viewTaskBits, scene); + } + // TODO? early exit here when not visible? if (model->canCastShadow() != _canCastShadow) { - model->setCanCastShadow(_canCastShadow, scene, viewTaskBits, false); + model->setCanCastShadow(_canCastShadow, scene); } if (_needsCollisionGeometryUpdate) { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 72a4b7e0a4..fa8a8ebfc9 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -79,7 +79,7 @@ void MeshPartPayload::removeMaterial(graphics::MaterialPointer material) { _drawMaterials.remove(material); } -void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { +void MeshPartPayload::updateKey(bool isVisible, uint8_t layer, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { ItemKey::Builder builder; builder.withTypeShape(); @@ -89,9 +89,10 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShad builder.withTagBits(tagBits); - if (isLayered) { - builder.withLayered(); - } + // if (layer) { + // builder.withLayered(); + builder.withLayer((ItemKey::Layer) layer); + // } if (canCastShadow) { builder.withShadowCaster(); @@ -111,6 +112,20 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShad _itemKey = builder.build(); } +void MeshPartPayload::updateKey(const render::ItemKey& key) { + ItemKey::Builder builder(key); + builder.withTypeShape(); + + if (topMaterialExists()) { + auto matKey = _drawMaterials.top().material->getKey(); + if (matKey.isTranslucent()) { + builder.withTransparent(); + } + } + + _itemKey = builder.build(); +} + ItemKey MeshPartPayload::getKey() const { return _itemKey; } @@ -332,7 +347,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render } // Note that this method is called for models but not for shapes -void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { +void ModelMeshPartPayload::updateKey(bool isVisible, uint8_t layer, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { ItemKey::Builder builder; builder.withTypeShape(); @@ -342,9 +357,9 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCas builder.withTagBits(tagBits); - if (isLayered) { - builder.withLayered(); - } + // if (isLayered) { + builder.withLayer((ItemKey::Layer) layer); + // } if (canCastShadow) { builder.withShadowCaster(); @@ -368,6 +383,25 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCas _itemKey = builder.build(); } +void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { + ItemKey::Builder builder(key); + builder.withTypeShape(); + + if (_isBlendShaped || _isSkinned) { + builder.withDeformed(); + } + + if (topMaterialExists()) { + auto matKey = _drawMaterials.top().material->getKey(); + if (matKey.isTranslucent()) { + builder.withTransparent(); + } + } + + _itemKey = builder.build(); +} + + void ModelMeshPartPayload::setLayer(bool isLayeredInFront, bool isLayeredInHUD) { if (isLayeredInFront) { _layer = Item::LAYER_3D_FRONT; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 53ed0ada78..f6ca09d2f0 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -32,7 +32,7 @@ public: typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - virtual void updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false); + virtual void updateKey(bool isVisible, uint8_t layer, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false); virtual void updateKey(const render::ItemKey& key); virtual void updateMeshPart(const std::shared_ptr& drawMesh, int partIndex); @@ -96,7 +96,7 @@ public: void notifyLocationChanged() override; - void updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false) override; + void updateKey(bool isVisible, uint8_t layer, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false) override; void updateKey(const render::ItemKey& key) override; // matrix palette skinning diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 5ac84ec913..533705f2ba 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -271,7 +271,7 @@ void Model::updateRenderItems() { bool isWireframe = self->isWireframe(); bool isVisible = self->isVisible(); bool canCastShadow = self->canCastShadow(); - uint8_t viewTagBits = self->getViewVisibilityMask(); + uint8_t viewTagBits = self->getViewMask(); bool isLayeredInFront = self->isLayeredInFront(); bool isLayeredInHUD = self->isLayeredInHUD(); bool isGroupCulled = self->isGroupCulled(); @@ -802,6 +802,10 @@ void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, */ void Model::updateRenderItemsKey(const render::ScenePointer& scene) { + if (!scene) { + _needsFixupInScene = true; + return; + } auto renderItemsKey = _renderItemsKey; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { @@ -817,84 +821,76 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) { scene->enqueueTransaction(transaction); } -void Model::setVisibleInScene(bool pisVisible, const render::ScenePointer& scene) { - if (isVisible() != pisVisible) { +void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene) { + if (Model::isVisible() != isVisible) { auto keyBuilder = render::ItemKey::Builder(_renderItemsKey); - _renderItemsKey = (pisVisible ? keyBuilder.withVisible() : keyBuilder.withInvisible()); + _renderItemsKey = (isVisible ? keyBuilder.withVisible() : keyBuilder.withInvisible()); updateRenderItemsKey(scene); } } bool Model::isVisible() const { - + return _renderItemsKey.isVisible(); } -void Model::setCanCastShadow(bool pcanCastShadow, const render::ScenePointer& scene) { - if (canCastShadow() != pcanCastShadow) { +void Model::setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene) { + if (Model::canCastShadow() != canCastShadow) { auto keyBuilder = render::ItemKey::Builder(_renderItemsKey); - _renderItemsKey = (pcanCastShadow ? keyBuilder.withShadowCaster() : keyBuilder.withoutShadowCaster()); + _renderItemsKey = (canCastShadow ? keyBuilder.withShadowCaster() : keyBuilder.withoutShadowCaster()); updateRenderItemsKey(scene); } } +bool Model::canCastShadow() const { + return _renderItemsKey.isShadowCaster(); +} + void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene) { - if (_isLayeredInFront != isLayeredInFront) { - _isLayeredInFront = isLayeredInFront; - - bool isVisible = _isVisible; - bool canCastShadow = _canCastShadow; - uint8_t viewTagBits = _viewTagBits; - bool isLayeredInHUD = _isLayeredInHUD; - bool isGroupCulled = _isGroupCulled; - - render::Transaction transaction; - foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, - isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); - data.setLayer(isLayeredInFront, isLayeredInHUD); - }); - } - foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, - isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); - data.setLayer(isLayeredInFront, isLayeredInHUD); - }); - } - scene->enqueueTransaction(transaction); + if (Model::isLayeredInFront() != isLayeredInFront) { + auto keyBuilder = render::ItemKey::Builder(_renderItemsKey); + _renderItemsKey = (isLayeredInFront ? keyBuilder.withLayer(render::Item::LAYER_3D_FRONT) : keyBuilder.withoutLayer()); + updateRenderItemsKey(scene); } } +bool Model::isLayeredInFront() const { + return _renderItemsKey.isLayer(render::Item::LAYER_3D_FRONT); +} + void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene) { - if (_isLayeredInHUD != isLayeredInHUD) { - _isLayeredInHUD = isLayeredInHUD; - - bool isVisible = _isVisible; - bool canCastShadow = _canCastShadow; - uint8_t viewTagBits = _viewTagBits; - bool isLayeredInFront = _isLayeredInFront; - bool isGroupCulled = _isGroupCulled; - - render::Transaction transaction; - foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, - isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); - data.setLayer(isLayeredInFront, isLayeredInHUD); - }); - } - foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, - isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); - data.setLayer(isLayeredInFront, isLayeredInHUD); - }); - } - scene->enqueueTransaction(transaction); + if (Model::isLayeredInHUD() != isLayeredInHUD) { + auto keyBuilder = render::ItemKey::Builder(_renderItemsKey); + _renderItemsKey = (isLayeredInHUD ? keyBuilder.withLayer(render::Item::LAYER_3D_HUD) : keyBuilder.withoutLayer()); + updateRenderItemsKey(scene); } } +bool Model::isLayeredInHUD() const { + return _renderItemsKey.isLayer(render::Item::LAYER_3D_HUD); +} + +void Model::setViewMask(uint8_t mask, const render::ScenePointer& scene) { + if (Model::getViewMask() != mask) { + auto keyBuilder = render::ItemKey::Builder(_renderItemsKey); + _renderItemsKey = keyBuilder.withTagBits(mask); + updateRenderItemsKey(scene); + } +} +Model::ViewMask Model::getViewMask() const { + return (Model::ViewMask) _renderItemsKey.getTagBits(); +} + +void Model::setGroupCulled(bool isGroupCulled, const render::ScenePointer& scene) { + if (Model::isGroupCulled() != isGroupCulled) { + auto keyBuilder = render::ItemKey::Builder(_renderItemsKey); + _renderItemsKey = (isGroupCulled ? keyBuilder.withSubMetaCulled() : keyBuilder.withoutSubMetaCulled()); + updateRenderItemsKey(scene); + } +} +bool Model::isGroupCulled() const { + return _renderItemsKey.isSubMetaCulled(); +} + bool Model::addToScene(const render::ScenePointer& scene, render::Transaction& transaction, render::Item::Status::Getters& statusGetters) { @@ -1694,20 +1690,16 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par for (auto shapeID : shapeIDs) { if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; - bool visible = isVisible(); - uint8_t viewTagBits = getViewTagBits(); - bool layeredInFront = isLayeredInFront(); - bool layeredInHUD = isLayeredInHUD(); - bool canCastShadow = _canCastShadow; + auto renderItemsKey = _renderItemsKey; bool wireframe = isWireframe(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); bool useDualQuaternionSkinning = _useDualQuaternionSkinning; - transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, canCastShadow, + transaction.updateItem(itemID, [material, renderItemsKey, invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); // if the material changed, we might need to update our item key or shape key - data.updateKey(visible, layeredInFront || layeredInHUD, canCastShadow, viewTagBits); + data.updateKey(renderItemsKey); data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning); }); } @@ -1722,19 +1714,16 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; bool visible = isVisible(); - uint8_t viewTagBits = getViewTagBits(); - bool layeredInFront = isLayeredInFront(); - bool layeredInHUD = isLayeredInHUD(); - bool canCastShadow = _canCastShadow; + auto renderItemsKey = _renderItemsKey; bool wireframe = isWireframe(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); bool useDualQuaternionSkinning = _useDualQuaternionSkinning; - transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, canCastShadow, + transaction.updateItem(itemID, [material, visible, renderItemsKey, invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.removeMaterial(material); // if the material changed, we might need to update our item key or shape key - data.updateKey(visible, layeredInFront || layeredInHUD, canCastShadow, viewTagBits); + data.updateKey(renderItemsKey); data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 0fec5ace04..fb72f3bf23 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -87,25 +87,25 @@ public: const QUrl& getURL() const { return _url; } // new Scene/Engine rendering support - void setVisibleInScene(bool isVisible, const render::ScenePointer& scene); + void setVisibleInScene(bool isVisible, const render::ScenePointer& scene = nullptr); bool isVisible() const; - enum ViewVisibilityMask : uint8_t { + enum ViewMask : uint8_t { MainView = 0x01, //render::ItemKey::TAG_BITS_0, SecondaryView = 0x02, //render::ItemKey::TAG_BITS_1, AllViews = 0xFF, //render::ItemKey::TAG_BITS_ALL, }; - ViewVisibilityMask getViewVisibilityMask() const; - void setViewVisibilityMask(uint8_t mask, const render::ScenePointer& scene); + ViewMask getViewMask() const; + void setViewMask(uint8_t mask, const render::ScenePointer& scene = nullptr); bool isGroupCulled() const; - void setGroupCulled(bool isGroupCulled); + void setGroupCulled(bool isGroupCulled, const render::ScenePointer& scene = nullptr); bool canCastShadow() const; - void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene); + void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene = nullptr); - void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); - void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); + void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene = nullptr); + void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene = nullptr); bool isLayeredInFront() const; bool isLayeredInHUD() const; diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 9c5efb9fa7..95cb3c9aed 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -29,10 +29,11 @@ const float Item::Status::Value::CYAN = 180.0f; const float Item::Status::Value::BLUE = 240.0f; const float Item::Status::Value::MAGENTA = 300.0f; -const int Item::LAYER_2D = 0; +/*const int Item::LAYER_2D = 0; const int Item::LAYER_3D = 1; const int Item::LAYER_3D_FRONT = 2; const int Item::LAYER_3D_HUD = 3; +*/ const uint8_t ItemKey::TAG_BITS_ALL { 0xFF }; const uint8_t ItemKey::TAG_BITS_NONE { 0x00 }; @@ -47,6 +48,11 @@ const uint8_t ItemKey::TAG_BITS_7 { 0x80 }; const uint32_t ItemKey::KEY_TAG_BITS_MASK = ((uint32_t) ItemKey::TAG_BITS_ALL) << FIRST_TAG_BIT; +// Layer bits are derived from the Layer enum, the number of bits needed to represent integer 0 to NUM_LAYERS +//const uint8_t ItemKey::NUM_LAYER_BITS { 3 }; +const uint8_t ItemKey::LAYER_BITS_ALL { 0x07 }; + +const uint32_t ItemKey::KEY_LAYER_BITS_MASK = ((uint32_t)ItemKey::LAYER_BITS_ALL) << FIRST_LAYER_BIT; void Item::Status::Value::setScale(float scale) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index b8a3fbf0f8..6353dca1a3 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -66,9 +66,30 @@ public: const static uint8_t TAG_BITS_6; const static uint8_t TAG_BITS_7; + // Items are organized in layers, an item belongs to one of the 8 Layers available. + // By default an item is in the 'LAYER_NONE' meaning that it is NOT layered. + // Which is equivalent to say that LAYER_NONE, is the default Layer. + // THere is NO ordering relationship between layers. + enum Layer : uint8_t { + LAYER_NONE = 0, // layer 0 is a 'NOT' layer, items are not considered layered, this is the default value + LAYER_1, + LAYER_2, + LAYER_3, + LAYER_4, + LAYER_5, + LAYER_6, + LAYER_BACKGROUND, // Last Layer is the background by convention + + NUM_LAYERS, + NUM_LAYER_BITS = 3 + }; + // Layer bits are derived from the Layer enum, the number of bits needed to represent integer 0 to NUM_LAYERS + const static uint8_t LAYER_BITS_ALL; + enum FlagBit : uint32_t { - TYPE_SHAPE = 0, // Item is a Shape - TYPE_LIGHT, // Item is a Light + TYPE_SHAPE = 0, // Item is a Shape: Implements the Shape Interface that draw a Geometry rendered with a Material + TYPE_LIGHT, // Item is a Light: Implements the Light Interface that + TYPE_CAMERA, // Item is a Camera: Implements the Camera Interface TYPE_META, // Item is a Meta: meanning it s used to represent a higher level object, potentially represented by other render items TRANSLUCENT, // Transparent and not opaque, for some odd reason TRANSPARENCY doesn't work... @@ -77,13 +98,15 @@ public: DEFORMED, // Deformed within bound, not solid INVISIBLE, // Visible or not in the scene? SHADOW_CASTER, // Item cast shadows - LAYERED, // Item belongs to one of the layers different from the default layer 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 FIRST_TAG_BIT, // 8 Tags available to organize the items and filter them against LAST_TAG_BIT = FIRST_TAG_BIT + NUM_TAGS, + FIRST_LAYER_BIT, // 8 Exclusive Layers (encoded in 3 bits) available to organize the items in layers, an item can only belong to ONE layer + LAST_LAYER_BIT = FIRST_LAYER_BIT + NUM_LAYER_BITS, + __SMALLER, // Reserved bit for spatialized item to indicate that it is smaller than expected in the cell in which it belongs (probably because it overlaps over several smaller cells) NUM_FLAGS, // Not a valid flag @@ -96,6 +119,12 @@ public: return (keyBits & ~KEY_TAG_BITS_MASK) | (((uint32_t)tagBits) << FIRST_TAG_BIT); } + // All the bits touching layer bits sets to true + const static uint32_t KEY_LAYER_BITS_MASK; + static uint32_t evalLayerBitsWithKeyBits(uint8_t layer, const uint32_t keyBits) { + return (keyBits & ~KEY_LAYER_BITS_MASK) | (((uint32_t)layer & LAYER_BITS_ALL) << FIRST_LAYER_BIT); + } + // The key is the Flags Flags _flags; @@ -124,19 +153,24 @@ public: Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withVisible() { _flags.reset(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } - Builder& withLayered() { _flags.set(LAYERED); return (*this); } + Builder& withoutShadowCaster() { _flags.reset(SHADOW_CASTER); return (*this); } Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); } + 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& withTag(Tag tag) { _flags.set(FIRST_TAG_BIT + tag); return (*this); } // Set ALL the tags in one call using the Tag bits Builder& withTagBits(uint8_t tagBits) { _flags = evalTagBitsWithKeyBits(tagBits, _flags.to_ulong()); return (*this); } + Builder& withLayer(uint8_t layer) { _flags = evalLayerBitsWithKeyBits(layer, _flags.to_ulong()); return (*this); } + Builder& withoutLayer() { return withLayer(LAYER_NONE); } + // Convenient standard keys that we will keep on using all over the place static Builder opaqueShape() { return Builder().withTypeShape(); } static Builder transparentShape() { return Builder().withTypeShape().withTransparent(); } static Builder light() { return Builder().withTypeLight(); } - static Builder background() { return Builder().withViewSpace().withLayered(); } + static Builder background() { return Builder().withViewSpace().withLayer(LAYER_BACKGROUND); } }; ItemKey(const Builder& builder) : ItemKey(builder._flags) {} @@ -161,9 +195,6 @@ public: bool isShadowCaster() const { return _flags[SHADOW_CASTER]; } - bool isLayered() const { return _flags[LAYERED]; } - bool isSpatial() const { return !isLayered(); } - bool isMetaCullGroup() const { return _flags[META_CULL_GROUP]; } void setMetaCullGroup(bool cullGroup) { (cullGroup ? _flags.set(META_CULL_GROUP) : _flags.reset(META_CULL_GROUP)); } @@ -173,6 +204,11 @@ public: 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); } + uint8_t getLayer() const { return ((_flags.to_ulong() & KEY_LAYER_BITS_MASK) >> FIRST_LAYER_BIT); } + bool isLayer(uint8_t layer) const { return getLayer() == layer; } + bool isLayered() const { return getLayer() != LAYER_NONE; } + bool isSpatial() const { return !isLayered(); } + // Probably not public, flags used by the scene bool isSmall() const { return _flags[__SMALLER]; } void setSmaller(bool smaller) { (smaller ? _flags.set(__SMALLER) : _flags.reset(__SMALLER)); } @@ -230,9 +266,6 @@ public: Builder& withNoShadowCaster() { _value.reset(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } Builder& withShadowCaster() { _value.set(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } - Builder& withoutLayered() { _value.reset(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } - Builder& withLayered() { _value.set(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } - Builder& withoutMetaCullGroup() { _value.reset(ItemKey::META_CULL_GROUP); _mask.set(ItemKey::META_CULL_GROUP); return (*this); } Builder& withMetaCullGroup() { _value.set(ItemKey::META_CULL_GROUP); _mask.set(ItemKey::META_CULL_GROUP); return (*this); } @@ -244,6 +277,9 @@ public: // Set ALL the tags in one call using the Tag bits and the Tag bits touched Builder& withTagBits(uint8_t tagBits, uint8_t tagMask) { _value = ItemKey::evalTagBitsWithKeyBits(tagBits, _value.to_ulong()); _mask = ItemKey::evalTagBitsWithKeyBits(tagMask, _mask.to_ulong()); return (*this); } + Builder& withoutLayered() { _value = ItemKey::evalLayerBitsWithKeyBits(ItemKey::LAYER_NONE, _value.to_ulong()); _mask |= ItemKey::KEY_LAYER_BITS_MASK; return (*this); } + Builder& withLayer(uint8_t layer) { _value = ItemKey::evalLayerBitsWithKeyBits(layer, _value.to_ulong()); _mask |= ItemKey::KEY_LAYER_BITS_MASK; return (*this); } + Builder& withNothing() { _value.reset(); _mask.reset(); return (*this); } // Convenient standard keys that we will keep on using all over the place @@ -252,9 +288,9 @@ public: static Builder transparentShape() { return Builder().withTypeShape().withTransparent().withWorldSpace(); } static Builder light() { return Builder().withTypeLight(); } static Builder meta() { return Builder().withTypeMeta(); } - static Builder background() { return Builder().withViewSpace().withLayered(); } - static Builder opaqueShapeLayered() { return Builder().withTypeShape().withOpaque().withWorldSpace().withLayered(); } - static Builder transparentShapeLayered() { return Builder().withTypeShape().withTransparent().withWorldSpace().withLayered(); } + static Builder background() { return Builder().withViewSpace().withLayer(ItemKey::LAYER_BACKGROUND); } + // static Builder opaqueShapeLayered() { return Builder().withTypeShape().withOpaque().withWorldSpace().withLayered(); } + // static Builder transparentShapeLayered() { return Builder().withTypeShape().withTransparent().withWorldSpace().withLayered(); } static Builder nothing() { return Builder().withNothing(); } }; @@ -377,7 +413,7 @@ public: public: virtual const ItemKey getKey() const = 0; virtual const Bound getBound() const = 0; - virtual int getLayer() const = 0; + // virtual int getLayer() const = 0; virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; @@ -423,12 +459,13 @@ public: const Bound getBound() const { return _payload->getBound(); } // Get the layer where the item belongs. - int getLayer() const { return _payload->getLayer(); } + // int getLayer() const { return _payload->getLayer(); } + int getLayer() const { return _key.getLayer(); } - static const int LAYER_2D; - static const int LAYER_3D; - static const int LAYER_3D_FRONT; - static const int LAYER_3D_HUD; + static const uint8_t LAYER_2D{ ItemKey::LAYER_1 }; + static const uint8_t LAYER_3D{ ItemKey::LAYER_NONE }; + static const uint8_t LAYER_3D_FRONT{ ItemKey::LAYER_2 }; + static const uint8_t LAYER_3D_HUD{ ItemKey::LAYER_3 }; // Render call for the item void render(RenderArgs* args) const { _payload->render(args); } @@ -505,7 +542,7 @@ public: // Payload general interface virtual const ItemKey getKey() const override { return payloadGetKey(_data); } virtual const Item::Bound getBound() const override { return payloadGetBound(_data); } - virtual int getLayer() const override { return payloadGetLayer(_data); } + // virtual int getLayer() const override { return payloadGetLayer(_data); } virtual void render(RenderArgs* args) override { payloadRender(_data, args); }