From b609cfaa2bcccc7de4bd788a6b0de60608e4d431 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 4 Jan 2019 10:43:48 -0800 Subject: [PATCH 1/4] renderLayer --- interface/src/ui/overlays/ModelOverlay.cpp | 15 +++---- interface/src/ui/overlays/ModelOverlay.h | 3 +- .../src/RenderableEntityItem.cpp | 18 ++++++-- .../src/RenderableEntityItem.h | 3 ++ .../src/RenderableMaterialEntityItem.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 17 +++++++- .../src/RenderableModelEntityItem.h | 1 + .../RenderableParticleEffectEntityItem.cpp | 4 +- .../src/RenderablePolyLineEntityItem.cpp | 2 +- .../src/RenderablePolyVoxEntityItem.h | 2 +- libraries/entities/src/EntityItem.cpp | 27 +++++++++++- libraries/entities/src/EntityItem.h | 4 ++ .../entities/src/EntityItemProperties.cpp | 39 ++++++++++++++++++ libraries/entities/src/EntityItemProperties.h | 2 + libraries/entities/src/EntityPropertyFlags.h | 1 + .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 7 +++- libraries/octree/src/OctreePacketData.h | 2 + libraries/render-utils/src/Model.cpp | 22 ++-------- libraries/render-utils/src/Model.h | 6 +-- libraries/shared/src/BillboardMode.cpp | 4 +- libraries/shared/src/MaterialMappingMode.cpp | 2 +- libraries/shared/src/RenderLayer.cpp | 25 +++++++++++ libraries/shared/src/RenderLayer.h | 41 +++++++++++++++++++ 24 files changed, 199 insertions(+), 52 deletions(-) create mode 100644 libraries/shared/src/RenderLayer.cpp create mode 100644 libraries/shared/src/RenderLayer.h diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 14b8182abf..14e5cdc7f5 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -114,14 +114,9 @@ void ModelOverlay::update(float deltatime) { _model->setVisibleInScene(getVisible(), scene); metaDirty = true; } - if (_drawInFrontDirty) { - _drawInFrontDirty = false; - _model->setLayeredInFront(getDrawInFront(), scene); - metaDirty = true; - } - if (_drawInHUDDirty) { - _drawInHUDDirty = false; - _model->setLayeredInHUD(getDrawHUDLayer(), scene); + if (_renderLayerDirty) { + _renderLayerDirty = false; + _model->setHifiRenderLayer(_drawHUDLayer ? render::hifi::LAYER_3D_HUD : (_drawInFront ? render::hifi::LAYER_3D_FRONT : render::hifi::LAYER_3D), scene); metaDirty = true; } if (_groupCulledDirty) { @@ -175,14 +170,14 @@ void ModelOverlay::setVisible(bool visible) { void ModelOverlay::setDrawInFront(bool drawInFront) { if (drawInFront != getDrawInFront()) { Base3DOverlay::setDrawInFront(drawInFront); - _drawInFrontDirty = true; + _renderLayerDirty = true; } } void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) { if (drawHUDLayer != getDrawHUDLayer()) { Base3DOverlay::setDrawHUDLayer(drawHUDLayer); - _drawInHUDDirty = true; + _renderLayerDirty = true; } } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index bd922e258a..17a2327d02 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -126,8 +126,7 @@ private: QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints bool _visibleDirty { true }; - bool _drawInFrontDirty { false }; - bool _drawInHUDDirty { false }; + bool _renderLayerDirty { false }; bool _isGroupCulled { false }; bool _groupCulledDirty { false }; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 5fb5a15d2c..8416e8d0e2 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -163,16 +163,27 @@ render::hifi::Tag EntityRenderer::getTagMask() const { return _isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW; } +render::hifi::Layer EntityRenderer::getHifiRenderLayer() const { + switch (_renderLayer) { + case RenderLayer::WORLD: + return render::hifi::LAYER_3D; + case RenderLayer::FRONT: + return render::hifi::LAYER_3D_FRONT; + case RenderLayer::HUD: + return render::hifi::LAYER_3D_HUD; + } +} + ItemKey EntityRenderer::getKey() { if (isTransparent()) { - return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()); + return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } // This allows shapes to cast shadows if (_canCastShadow) { - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withShadowCaster(); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withShadowCaster().withLayer(getHifiRenderLayer()); } else { - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } } @@ -411,6 +422,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _moving = entity->isMovingRelativeToParent(); _visible = entity->getVisible(); setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera()); + setRenderLayer(entity->getRenderLayer()); _canCastShadow = entity->getCanCastShadow(); _cauterized = entity->getCauterized(); _needsRenderUpdate = false; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 9c4d10190c..1c83aecdbe 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -77,6 +77,7 @@ protected: virtual void render(RenderArgs* args) override final; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; virtual render::hifi::Tag getTagMask() const; + virtual render::hifi::Layer getHifiRenderLayer() const; // Returns true if the item in question needs to have updateInScene called because of internal rendering state changes virtual bool needsRenderUpdate() const; @@ -103,6 +104,7 @@ protected: inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; } virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; } + virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; } template T withReadLockResult(const std::function& f) { @@ -136,6 +138,7 @@ protected: bool _visible { false }; bool _isVisibleInSecondaryCamera { false }; bool _canCastShadow { false }; + RenderLayer _renderLayer { RenderLayer::WORLD }; bool _cauterized { false }; bool _moving { false }; bool _needsRenderUpdate { false }; diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 6451e873c9..8cc1b0f193 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -55,7 +55,7 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& ItemKey MaterialEntityRenderer::getKey() { ItemKey::Builder builder; - builder.withTypeShape().withTagBits(getTagMask()); + builder.withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); if (!_visible) { builder.withInvisible(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index dcad562ba7..255446287d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1070,9 +1070,9 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) { if (didVisualGeometryRequestSucceed) { - _itemKey = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()); + _itemKey = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } else { - _itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(getTagMask()); + _itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } } @@ -1346,6 +1346,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) { setKey(didVisualGeometryRequestSucceed); + _model->setTagMask(getTagMask()); + _model->setHifiRenderLayer(getHifiRenderLayer()); emit requestRenderUpdate(); if(didVisualGeometryRequestSucceed) { emit DependencyManager::get()-> @@ -1489,6 +1491,17 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) { Parent::setIsVisibleInSecondaryCamera(value); setKey(_didLastVisualGeometryRequestSucceed); + if (_model) { + _model->setTagMask(getTagMask()); + } +} + +void ModelEntityRenderer::setRenderLayer(RenderLayer value) { + Parent::setRenderLayer(value); + setKey(_didLastVisualGeometryRequestSucceed); + if (_model) { + _model->setHifiRenderLayer(getHifiRenderLayer()); + } } // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index ba185dee96..cd4b636e33 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -169,6 +169,7 @@ protected: render::hifi::Tag getTagMask() const override; void setIsVisibleInSecondaryCamera(bool value) override; + void setRenderLayer(RenderLayer value) override; private: void animate(const TypedEntityPointer& entity); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 38027a80ed..8f6fd5383e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -159,9 +159,9 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn ItemKey ParticleEffectEntityRenderer::getKey() { if (_visible) { - return ItemKey::Builder::transparentShape().withTagBits(getTagMask()); + return ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } else { - return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).build(); + return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()).build(); } } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index de224103ce..e3bfa04bdc 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -55,7 +55,7 @@ void PolyLineEntityRenderer::buildPipeline() { } ItemKey PolyLineEntityRenderer::getKey() { - return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()); + return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } ShapeKey PolyLineEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 366a3fdc70..7aea87535e 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -173,7 +173,7 @@ public: } protected: - virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()); } + virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } virtual ShapeKey getShapeKey() override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index bfa238d695..6f8e764973 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -94,6 +94,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_QUERY_AA_CUBE; requestedProperties += PROP_CAN_CAST_SHADOW; // requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA; // not sent over wire + requestedProperties += PROP_RENDER_LAYER; withReadLock([&] { requestedProperties += _grabProperties.getEntityProperties(params); }); @@ -265,7 +266,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint()); // TODO: handle created? APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy()); - // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, getEntityHostType()); // not sent over wire + // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, (uint32_t)getEntityHostType()); // not sent over wire // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, getOwningAvatarID()); // not sent over wire // convert AVATAR_SELF_ID to actual sessionUUID. QUuid actualParentID = getParentID(); @@ -278,6 +279,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube()); APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, getIsVisibleInSecondaryCamera()); // not sent over wire + APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)getRenderLayer()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -841,6 +843,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); // READ_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over wire + READ_ENTITY_PROPERTY(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1310,6 +1313,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube); COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); // COPY_ENTITY_PROPERTY_TO_PROPERTIES(isVisibleInSecondaryCamera, getIsVisibleInSecondaryCamera); // not sent over wire + COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderLayer, getRenderLayer); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1454,6 +1458,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube); SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderLayer, setRenderLayer); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -2888,6 +2893,26 @@ void EntityItem::setIsVisibleInSecondaryCamera(bool value) { } } +RenderLayer EntityItem::getRenderLayer() const { + return resultWithReadLock([&] { + return _renderLayer; + }); +} + +void EntityItem::setRenderLayer(RenderLayer value) { + bool changed = false; + withWriteLock([&] { + if (_renderLayer != value) { + changed = true; + _renderLayer = value; + } + }); + + if (changed) { + emit requestRenderUpdate(); + } +} + bool EntityItem::getCanCastShadow() const { bool result; withReadLock([&] { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 826a9c34a0..5053389a7b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -293,6 +293,9 @@ public: bool isVisibleInSecondaryCamera() const; void setIsVisibleInSecondaryCamera(bool value); + RenderLayer getRenderLayer() const; + void setRenderLayer(RenderLayer value); + bool getCanCastShadow() const; void setCanCastShadow(bool value); @@ -621,6 +624,7 @@ protected: float _angularDamping { ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING }; bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE }; bool _isVisibleInSecondaryCamera { ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA }; + RenderLayer _renderLayer { RenderLayer::WORLD }; bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS }; uint16_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index eda1eae5d1..00263b771e 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -343,6 +343,33 @@ void EntityItemProperties::setBillboardModeFromString(const QString& materialMap } } +QHash stringToRenderLayerLookup; + +void addRenderLayer(RenderLayer mode) { + stringToRenderLayerLookup[RenderLayerHelpers::getNameForRenderLayer(mode)] = mode; +} + +void buildStringToRenderLayerLookup() { + addRenderLayer(RenderLayer::WORLD); + addRenderLayer(RenderLayer::FRONT); + addRenderLayer(RenderLayer::HUD); +} + +QString EntityItemProperties::getRenderLayerAsString() const { + return RenderLayerHelpers::getNameForRenderLayer(_renderLayer); +} + +void EntityItemProperties::setRenderLayerFromString(const QString& materialMappingMode) { + if (stringToRenderLayerLookup.empty()) { + buildStringToRenderLayerLookup(); + } + auto renderLayerItr = stringToRenderLayerLookup.find(materialMappingMode.toLower()); + if (renderLayerItr != stringToRenderLayerLookup.end()) { + _renderLayer = renderLayerItr.value(); + _renderLayerChanged = true; + } +} + EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; @@ -367,6 +394,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_QUERY_AA_CUBE, queryAACube); CHECK_PROPERTY_CHANGE(PROP_CAN_CAST_SHADOW, canCastShadow); CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera); + CHECK_PROPERTY_CHANGE(PROP_RENDER_LAYER, renderLayer); changedProperties += _grab.getChangedProperties(); // Physics @@ -603,6 +631,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * {@link Entities.EntityType|Zone} entity with castShadows enabled in its * {@link Entities.EntityProperties-Zone|keyLight} property. * @property {boolean} isVisibleInSecondaryCamera=true - Whether or not the entity is rendered in the secondary camera. If true then the entity is rendered. + * @property {RenderLayer} renderLayer="world" - In which layer this entity renders. * * @property {Vec3} position=0,0,0 - The position of the entity. * @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates. @@ -1413,6 +1442,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_QUERY_AA_CUBE, queryAACube); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_RENDER_LAYER, renderLayer, getRenderLayerAsString()); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -1799,6 +1829,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(queryAACube, AACube, setQueryAACube); // TODO: should scripts be able to set this? COPY_PROPERTY_FROM_QSCRIPTVALUE(canCastShadow, bool, setCanCastShadow); COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(renderLayer, RenderLayer); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -2056,6 +2087,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(queryAACube); COPY_PROPERTY_IF_CHANGED(canCastShadow); COPY_PROPERTY_IF_CHANGED(isVisibleInSecondaryCamera); + COPY_PROPERTY_IF_CHANGED(renderLayer); _grab.merge(other._grab); // Physics @@ -2309,6 +2341,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue //ADD_PROPERTY_TO_MAP(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube); // not yet handled ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool); ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool); + ADD_PROPERTY_TO_MAP(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer); { // 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); @@ -2701,6 +2734,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, properties.getQueryAACube()); APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, properties.getIsVisibleInSecondaryCamera()); // Not sent over the wire + APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)properties.getRenderLayer()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3147,6 +3181,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUERY_AA_CUBE, AACube, setQueryAACube); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // Not sent over the wire + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3529,6 +3564,7 @@ void EntityItemProperties::markAllChanged() { _queryAACubeChanged = true; _canCastShadowChanged = true; _isVisibleInSecondaryCameraChanged = true; + _renderLayerChanged = true; _grab.markAllChanged(); // Physics @@ -3902,6 +3938,9 @@ QList EntityItemProperties::listChangedProperties() { if (isVisibleInSecondaryCameraChanged()) { out += "isVisibleInSecondaryCamera"; } + if (renderLayerChanged()) { + out += "renderLayer"; + } getGrab().listChangedProperties(out); // Physics diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 1590832236..e0781bab21 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -50,6 +50,7 @@ #include "MaterialMappingMode.h" #include "BillboardMode.h" +#include "RenderLayer.h" const quint64 UNKNOWN_CREATED_TIME = 0; @@ -149,6 +150,7 @@ public: DEFINE_PROPERTY_REF(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube, AACube()); DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW); DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA); + DEFINE_PROPERTY_REF_ENUM(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer, RenderLayer::WORLD); DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup); // Physics diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 34f6402a22..77e14db3a0 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -39,6 +39,7 @@ enum EntityPropertyList { PROP_QUERY_AA_CUBE, PROP_CAN_CAST_SHADOW, PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over wire + PROP_RENDER_LAYER, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 41eaa0ded0..d9eb9d32fa 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::UpdatedPolyLines); + return static_cast(EntityVersion::LAST_PACKET_TYPE); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 1b031e80dc..904ed6045d 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -253,7 +253,12 @@ enum class EntityVersion : PacketVersion { MissingTextProperties, GrabTraits, MorePropertiesCleanup, - UpdatedPolyLines + UpdatedPolyLines, + RenderLayer, + + // Add new versions above here + NUM_PACKET_TYPE, + LAST_PACKET_TYPE = NUM_PACKET_TYPE - 1 }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index bd1abf8744..68c9f8e5f7 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -35,6 +35,7 @@ #include "MaterialMappingMode.h" #include "BillboardMode.h" +#include "RenderLayer.h" #include "OctreeConstants.h" #include "OctreeElement.h" @@ -263,6 +264,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, ShapeType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, MaterialMappingMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, BillboardMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, RenderLayer& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9cefbf65a8..3ee9118252 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -925,30 +925,14 @@ bool Model::canCastShadow() const { return _renderItemKeyGlobalFlags.isShadowCaster(); } -void Model::setLayeredInFront(bool layeredInFront, const render::ScenePointer& scene) { - if (Model::isLayeredInFront() != layeredInFront) { +void Model::setHifiRenderLayer(render::hifi::Layer renderLayer, const render::ScenePointer& scene) { + if (_renderItemKeyGlobalFlags.getLayer() != renderLayer) { auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags); - _renderItemKeyGlobalFlags = (layeredInFront ? keyBuilder.withLayer(render::hifi::LAYER_3D_FRONT) : keyBuilder.withoutLayer()); + _renderItemKeyGlobalFlags = keyBuilder.withLayer(renderLayer); updateRenderItemsKey(scene); } } -bool Model::isLayeredInFront() const { - return _renderItemKeyGlobalFlags.isLayer(render::hifi::LAYER_3D_FRONT); -} - -void Model::setLayeredInHUD(bool layeredInHUD, const render::ScenePointer& scene) { - if (Model::isLayeredInHUD() != layeredInHUD) { - auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags); - _renderItemKeyGlobalFlags = (layeredInHUD ? keyBuilder.withLayer(render::hifi::LAYER_3D_HUD) : keyBuilder.withoutLayer()); - updateRenderItemsKey(scene); - } -} - -bool Model::isLayeredInHUD() const { - return _renderItemKeyGlobalFlags.isLayer(render::hifi::LAYER_3D_HUD); -} - void Model::setTagMask(uint8_t mask, const render::ScenePointer& scene) { if (Model::getTagMask() != mask) { auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 93a0626d28..9dec94e0d5 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -123,11 +123,7 @@ public: bool canCastShadow() const; void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene = nullptr); - void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene = nullptr); - void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene = nullptr); - - bool isLayeredInFront() const; - bool isLayeredInHUD() const; + void setHifiRenderLayer(render::hifi::Layer layer, const render::ScenePointer& scene = nullptr); // 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/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index 56251f53f2..4b6af5db33 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -14,10 +14,10 @@ const char* billboardModeNames[] = { "full" }; -static const size_t MATERIAL_MODE_NAMES = (sizeof(billboardModeNames) / sizeof((billboardModeNames)[0])); +static const size_t BILLBOARD_MODE_NAMES = (sizeof(billboardModeNames) / sizeof(billboardModeNames[0])); QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { - if (((int)mode <= 0) || ((int)mode >= (int)MATERIAL_MODE_NAMES)) { + if (((int)mode <= 0) || ((int)mode >= (int)BILLBOARD_MODE_NAMES)) { mode = (BillboardMode)0; } diff --git a/libraries/shared/src/MaterialMappingMode.cpp b/libraries/shared/src/MaterialMappingMode.cpp index 1ddad178a2..09a7cfd6d9 100644 --- a/libraries/shared/src/MaterialMappingMode.cpp +++ b/libraries/shared/src/MaterialMappingMode.cpp @@ -13,7 +13,7 @@ const char* materialMappingModeNames[] = { "projected" }; -static const size_t MATERIAL_MODE_NAMES = (sizeof(materialMappingModeNames) / sizeof((materialMappingModeNames)[0])); +static const size_t MATERIAL_MODE_NAMES = (sizeof(materialMappingModeNames) / sizeof(materialMappingModeNames[0])); QString MaterialMappingModeHelpers::getNameForMaterialMappingMode(MaterialMappingMode mode) { if (((int)mode <= 0) || ((int)mode >= (int)MATERIAL_MODE_NAMES)) { diff --git a/libraries/shared/src/RenderLayer.cpp b/libraries/shared/src/RenderLayer.cpp new file mode 100644 index 0000000000..7e072631e0 --- /dev/null +++ b/libraries/shared/src/RenderLayer.cpp @@ -0,0 +1,25 @@ +// +// Created by Sam Gondelman on 1/3/19 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "RenderLayer.h" + +const char* renderLayerNames[] = { + "world", + "front", + "hud" +}; + +static const size_t RENDER_LAYER_NAMES = (sizeof(renderLayerNames) / sizeof(renderLayerNames[0])); + +QString RenderLayerHelpers::getNameForRenderLayer(RenderLayer mode) { + if (((int)mode <= 0) || ((int)mode >= (int)RENDER_LAYER_NAMES)) { + mode = (RenderLayer)0; + } + + return renderLayerNames[(int)mode]; +} \ No newline at end of file diff --git a/libraries/shared/src/RenderLayer.h b/libraries/shared/src/RenderLayer.h new file mode 100644 index 0000000000..b5bf885616 --- /dev/null +++ b/libraries/shared/src/RenderLayer.h @@ -0,0 +1,41 @@ +// +// Created by Sam Gondelman on 1/3/19. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderLayer_h +#define hifi_RenderLayer_h + +#include "QString" + +/**jsdoc + *

In which layer an entity is rendered.

+ * + * + * + * + * + * + * + * + * + *
ValueDescription
worldThe entity will be drawn in the world with everything else.
frontThe entity will be drawn on top of the world layer, but behind the HUD sphere.
hudThe entity will be drawn on top of other layers and the HUD sphere.
+ * @typedef {string} RenderLayer + */ + +enum class RenderLayer { + WORLD = 0, + FRONT, + HUD +}; + +class RenderLayerHelpers { +public: + static QString getNameForRenderLayer(RenderLayer mode); +}; + +#endif // hifi_RenderLayer_h + From 1b5c1d06777fffc64563465854fc0df2b9c9a4ca Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 8 Jan 2019 10:02:03 -0800 Subject: [PATCH 2/4] working on primitiveMode and groupCulled --- .../src/RenderableEntityItem.cpp | 10 +++ .../src/RenderableEntityItem.h | 4 +- .../src/RenderableGridEntityItem.cpp | 4 ++ .../src/RenderableImageEntityItem.cpp | 4 ++ .../src/RenderableMaterialEntityItem.cpp | 4 ++ .../src/RenderableModelEntityItem.cpp | 18 +++++ .../src/RenderableModelEntityItem.h | 1 + .../RenderableParticleEffectEntityItem.cpp | 6 +- .../src/RenderablePolyLineEntityItem.cpp | 6 +- .../src/RenderablePolyVoxEntityItem.cpp | 6 +- .../src/RenderableShapeEntityItem.cpp | 10 ++- .../src/RenderableTextEntityItem.cpp | 3 + libraries/entities/src/EntityItem.cpp | 25 +++++++ libraries/entities/src/EntityItem.h | 4 ++ .../entities/src/EntityItemProperties.cpp | 65 +++++++++++++++++-- libraries/entities/src/EntityItemProperties.h | 3 + libraries/entities/src/EntityPropertyFlags.h | 20 +++--- libraries/entities/src/ModelEntityItem.cpp | 17 +++++ libraries/entities/src/ModelEntityItem.h | 4 ++ libraries/networking/src/udt/PacketHeaders.h | 2 +- libraries/octree/src/OctreePacketData.h | 2 + .../render-utils/src/CauterizedModel.cpp | 6 +- .../render-utils/src/MeshPartPayload.cpp | 3 +- libraries/render-utils/src/MeshPartPayload.h | 2 +- libraries/render-utils/src/Model.cpp | 25 ++++--- libraries/render-utils/src/Model.h | 7 +- libraries/shared/src/PrimitiveMode.cpp | 24 +++++++ libraries/shared/src/PrimitiveMode.h | 39 +++++++++++ 28 files changed, 284 insertions(+), 40 deletions(-) create mode 100644 libraries/shared/src/PrimitiveMode.cpp create mode 100644 libraries/shared/src/PrimitiveMode.h diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 8416e8d0e2..53e62ee35f 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -159,6 +159,13 @@ Item::Bound EntityRenderer::getBound() { return _bound; } +ShapeKey EntityRenderer::getShapeKey() { + if (_primitiveMode == PrimitiveMode::LINES) { + return ShapeKey::Builder().withOwnPipeline().withWireframe(); + } + return ShapeKey::Builder().withOwnPipeline(); +} + render::hifi::Tag EntityRenderer::getTagMask() const { return _isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW; } @@ -171,6 +178,8 @@ render::hifi::Layer EntityRenderer::getHifiRenderLayer() const { return render::hifi::LAYER_3D_FRONT; case RenderLayer::HUD: return render::hifi::LAYER_3D_HUD; + default: + return render::hifi::LAYER_3D; } } @@ -423,6 +432,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _visible = entity->getVisible(); setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera()); setRenderLayer(entity->getRenderLayer()); + setPrimitiveMode(entity->getPrimitiveMode()); _canCastShadow = entity->getCanCastShadow(); _cauterized = entity->getCauterized(); _needsRenderUpdate = false; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 1c83aecdbe..fde63f78fa 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -72,7 +72,7 @@ protected: // Implementing the PayloadProxyInterface methods virtual ItemKey getKey() override; - virtual ShapeKey getShapeKey() override { return ShapeKey::Builder::ownPipeline(); } + virtual ShapeKey getShapeKey() override; virtual Item::Bound getBound() override; virtual void render(RenderArgs* args) override final; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; @@ -105,6 +105,7 @@ protected: virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; } virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; } + virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; } template T withReadLockResult(const std::function& f) { @@ -139,6 +140,7 @@ protected: bool _isVisibleInSecondaryCamera { false }; bool _canCastShadow { false }; RenderLayer _renderLayer { RenderLayer::WORLD }; + PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; bool _cauterized { false }; bool _moving { false }; bool _needsRenderUpdate { false }; diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 22cf72cec6..4576358699 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -97,6 +97,10 @@ ShapeKey GridEntityRenderer::getShapeKey() { builder.withTranslucent(); } + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); } diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 7c5b7fc0da..c1d6d3211d 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -123,6 +123,10 @@ ShapeKey ImageEntityRenderer::getShapeKey() { if (_emissive) { builder.withUnlit(); } + + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } }); return builder.build(); diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 8cc1b0f193..483f9ffe1c 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -98,6 +98,10 @@ ShapeKey MaterialEntityRenderer::getShapeKey() { builder.withUnlit(); } + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 255446287d..6cde85bed0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1290,6 +1290,10 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin model->getRegistrationPoint() != entity->getRegistrationPoint()) { return true; } + + if (model->isGroupCulled() != entity->getGroupCulled()) { + return true; + } } return false; @@ -1434,6 +1438,13 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->setCanCastShadow(_canCastShadow, scene); } + { + bool groupCulled = entity->getGroupCulled(); + if (model->isGroupCulled() != groupCulled) { + model->setGroupCulled(groupCulled); + } + } + { DETAILED_PROFILE_RANGE(simulation_physics, "Fixup"); if (model->needsFixupInScene()) { @@ -1504,6 +1515,13 @@ void ModelEntityRenderer::setRenderLayer(RenderLayer value) { } } +void ModelEntityRenderer::setPrimitiveMode(PrimitiveMode value) { + Parent::setPrimitiveMode(value); + if (_model) { + _model->setPrimitiveMode(_primitiveMode); + } +} + // 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 cd4b636e33..ff266e14bb 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -170,6 +170,7 @@ protected: void setIsVisibleInSecondaryCamera(bool value) override; void setRenderLayer(RenderLayer value) override; + void setPrimitiveMode(PrimitiveMode value) override; private: void animate(const TypedEntityPointer& entity); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 8f6fd5383e..351d72baf5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -166,7 +166,11 @@ ItemKey ParticleEffectEntityRenderer::getKey() { } ShapeKey ParticleEffectEntityRenderer::getShapeKey() { - return ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).withTranslucent().build(); + auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).withTranslucent(); + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); } Item::Bound ParticleEffectEntityRenderer::getBound() { diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index aaf2b58bea..68371e4e13 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -59,7 +59,11 @@ ItemKey PolyLineEntityRenderer::getKey() { } ShapeKey PolyLineEntityRenderer::getShapeKey() { - return ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace(); + auto builder = ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace(); + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); } bool PolyLineEntityRenderer::needsRenderUpdate() const { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 514ed3cec1..183d2881f3 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1613,7 +1613,11 @@ PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : } ShapeKey PolyVoxEntityRenderer::getShapeKey() { - return ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).build(); + auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER); + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); } bool PolyVoxEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 1569c75eec..978341bb39 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -186,6 +186,10 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { builder.withUnlit(); } + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); } else { ShapeKey::Builder builder; @@ -198,6 +202,10 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { if (isTransparent()) { builder.withTranslucent(); } + + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } return builder.build(); } } @@ -242,7 +250,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); - if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 4ddb398fbf..d7da8e7e1a 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -49,6 +49,9 @@ ShapeKey TextEntityRenderer::getShapeKey() { if (isTransparent()) { builder.withTranslucent(); } + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } return builder.build(); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1a32b414c7..cf97e43b5f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -95,6 +95,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_CAN_CAST_SHADOW; // requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA; // not sent over the wire requestedProperties += PROP_RENDER_LAYER; + requestedProperties += PROP_PRIMITIVE_MODE; withReadLock([&] { requestedProperties += _grabProperties.getEntityProperties(params); }); @@ -277,6 +278,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, getIsVisibleInSecondaryCamera()); // not sent over the wire APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)getRenderLayer()); + APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)getPrimitiveMode()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -841,6 +843,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); // READ_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over the wire READ_ENTITY_PROPERTY(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); + READ_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1313,6 +1316,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); COPY_ENTITY_PROPERTY_TO_PROPERTIES(isVisibleInSecondaryCamera, isVisibleInSecondaryCamera); COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderLayer, getRenderLayer); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(primitiveMode, getPrimitiveMode); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1458,6 +1462,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera); SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderLayer, setRenderLayer); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(primitiveMode, setPrimitiveMode); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -2912,6 +2917,26 @@ void EntityItem::setRenderLayer(RenderLayer value) { } } +PrimitiveMode EntityItem::getPrimitiveMode() const { + return resultWithReadLock([&] { + return _primitiveMode; + }); +} + +void EntityItem::setPrimitiveMode(PrimitiveMode value) { + bool changed = false; + withWriteLock([&] { + if (_primitiveMode != value) { + changed = true; + _primitiveMode = value; + } + }); + + if (changed) { + emit requestRenderUpdate(); + } +} + bool EntityItem::getCanCastShadow() const { bool result; withReadLock([&] { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5053389a7b..cac4192cd5 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -296,6 +296,9 @@ public: RenderLayer getRenderLayer() const; void setRenderLayer(RenderLayer value); + PrimitiveMode getPrimitiveMode() const; + void setPrimitiveMode(PrimitiveMode value); + bool getCanCastShadow() const; void setCanCastShadow(bool value); @@ -625,6 +628,7 @@ protected: bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE }; bool _isVisibleInSecondaryCamera { ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA }; RenderLayer _renderLayer { RenderLayer::WORLD }; + PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS }; uint16_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index fee0935955..647861120c 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -328,11 +328,11 @@ QString EntityItemProperties::getBillboardModeAsString() const { return BillboardModeHelpers::getNameForBillboardMode(_billboardMode); } -void EntityItemProperties::setBillboardModeFromString(const QString& materialMappingMode) { +void EntityItemProperties::setBillboardModeFromString(const QString& billboardMode) { if (stringToBillboardModeLookup.empty()) { buildStringToBillboardModeLookup(); } - auto billboardModeItr = stringToBillboardModeLookup.find(materialMappingMode.toLower()); + auto billboardModeItr = stringToBillboardModeLookup.find(billboardMode.toLower()); if (billboardModeItr != stringToBillboardModeLookup.end()) { _billboardMode = billboardModeItr.value(); _billboardModeChanged = true; @@ -355,17 +355,43 @@ QString EntityItemProperties::getRenderLayerAsString() const { return RenderLayerHelpers::getNameForRenderLayer(_renderLayer); } -void EntityItemProperties::setRenderLayerFromString(const QString& materialMappingMode) { +void EntityItemProperties::setRenderLayerFromString(const QString& renderLayer) { if (stringToRenderLayerLookup.empty()) { buildStringToRenderLayerLookup(); } - auto renderLayerItr = stringToRenderLayerLookup.find(materialMappingMode.toLower()); + auto renderLayerItr = stringToRenderLayerLookup.find(renderLayer.toLower()); if (renderLayerItr != stringToRenderLayerLookup.end()) { _renderLayer = renderLayerItr.value(); _renderLayerChanged = true; } } +QHash stringToPrimitiveModeLookup; + +void addPrimitiveMode(PrimitiveMode mode) { + stringToPrimitiveModeLookup[PrimitiveModeHelpers::getNameForPrimitiveMode(mode)] = mode; +} + +void buildStringToPrimitiveModeLookup() { + addPrimitiveMode(PrimitiveMode::SOLID); + addPrimitiveMode(PrimitiveMode::LINES); +} + +QString EntityItemProperties::getPrimitiveModeAsString() const { + return PrimitiveModeHelpers::getNameForPrimitiveMode(_primitiveMode); +} + +void EntityItemProperties::setPrimitiveModeFromString(const QString& primitiveMode) { + if (stringToPrimitiveModeLookup.empty()) { + buildStringToPrimitiveModeLookup(); + } + auto primitiveModeItr = stringToPrimitiveModeLookup.find(primitiveMode.toLower()); + if (primitiveModeItr != stringToPrimitiveModeLookup.end()) { + _primitiveMode = primitiveModeItr.value(); + _primitiveModeChanged = true; + } +} + EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; @@ -391,6 +417,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_CAN_CAST_SHADOW, canCastShadow); CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera); CHECK_PROPERTY_CHANGE(PROP_RENDER_LAYER, renderLayer); + CHECK_PROPERTY_CHANGE(PROP_PRIMITIVE_MODE, primitiveMode); changedProperties += _grab.getChangedProperties(); // Physics @@ -490,6 +517,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); CHECK_PROPERTY_CHANGE(PROP_JOINT_TRANSLATIONS, jointTranslations); CHECK_PROPERTY_CHANGE(PROP_RELAY_PARENT_JOINTS, relayParentJoints); + CHECK_PROPERTY_CHANGE(PROP_GROUP_CULLED, groupCulled); changedProperties += _animation.getChangedProperties(); // Light @@ -595,15 +623,15 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * the shape property set for entities of these types.) Read-only. * @property {EntityHostType} entityHostType="domain" - How this entity will behave, including if and how it is sent to other people. * The value can only be set at entity creation by using the entityHostType parameter in - * {@link Entities.addEntity}. + * {@link Entities.addEntity}. Read-only. * @property {boolean} avatarEntity=false - If true then the entity is an avatar entity; An avatar entity follows you to each domain you visit, * rendering at the same world coordinates unless it's parented to your avatar. Value cannot be changed after the entity is created.
* The value can only be set at entity creation by using the entityHostType parameter in - * {@link Entities.addEntity}. clientOnly is an alias. + * {@link Entities.addEntity}. clientOnly is an alias. Read-only. * @property {boolean} localEntity=false - If true then the entity is a local entity; Local entities only render for you and are not sent over the wire. * Value cannot be changed after the entity is created.
* The value can only be set at entity creation by using the entityHostType parameter in - * {@link Entities.addEntity}. + * {@link Entities.addEntity}. Read-only. * @property {Uuid} owningAvatarID=Uuid.NULL - The session ID of the owning avatar if avatarEntity is * true, otherwise {@link Uuid|Uuid.NULL}. Read-only. * @@ -628,6 +656,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * {@link Entities.EntityProperties-Zone|keyLight} property. * @property {boolean} isVisibleInSecondaryCamera=true - Whether or not the entity is rendered in the secondary camera. If true then the entity is rendered. * @property {RenderLayer} renderLayer="world" - In which layer this entity renders. + * @property {PrimitiveMode} primitiveMode="solid" - How this entity's geometry is rendered. * * @property {Vec3} position=0,0,0 - The position of the entity. * @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates. @@ -942,6 +971,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * {@link Entities.getJointIndex|getJointIndex}. * @property {boolean} relayParentJoints=false - If true and the entity is parented to an avatar, then the * avatar's joint rotations are applied to the entity's joints. + * @property {boolean} groupCulled=false - If true, the mesh parts of the model are LOD culled as a group. + * If false, separate mesh parts will be LOD culled individually. * * @example Rez a Vive tracker puck. * var entity = Entities.addEntity({ @@ -1434,6 +1465,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_RENDER_LAYER, renderLayer, getRenderLayerAsString()); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PRIMITIVE_MODE, primitiveMode, getPrimitiveModeAsString()); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -1550,6 +1582,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS, jointTranslations); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RELAY_PARENT_JOINTS, relayParentJoints); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GROUP_CULLED, groupCulled); if (!psuedoPropertyFlagsButDesiredEmpty) { _animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); } @@ -1816,6 +1849,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(canCastShadow, bool, setCanCastShadow); COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(renderLayer, RenderLayer); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(primitiveMode, PrimitiveMode); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -1920,6 +1954,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslationsSet, qVectorBool, setJointTranslationsSet); COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslations, qVectorVec3, setJointTranslations); COPY_PROPERTY_FROM_QSCRIPTVALUE(relayParentJoints, bool, setRelayParentJoints); + COPY_PROPERTY_FROM_QSCRIPTVALUE(groupCulled, bool, setGroupCulled); _animation.copyFromScriptValue(object, _defaultSettings); // Light @@ -2076,6 +2111,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(canCastShadow); COPY_PROPERTY_IF_CHANGED(isVisibleInSecondaryCamera); COPY_PROPERTY_IF_CHANGED(renderLayer); + COPY_PROPERTY_IF_CHANGED(primitiveMode); _grab.merge(other._grab); // Physics @@ -2175,6 +2211,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(jointTranslationsSet); COPY_PROPERTY_IF_CHANGED(jointTranslations); COPY_PROPERTY_IF_CHANGED(relayParentJoints); + COPY_PROPERTY_IF_CHANGED(groupCulled); _animation.merge(other._animation); // Light @@ -2330,6 +2367,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool); ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool); ADD_PROPERTY_TO_MAP(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer); + ADD_PROPERTY_TO_MAP(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode); { // 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); @@ -2453,6 +2491,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); ADD_PROPERTY_TO_MAP(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool); + ADD_PROPERTY_TO_MAP(PROP_GROUP_CULLED, GroupCulled, groupCulled, bool); { // Animation ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); @@ -2722,6 +2761,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, properties.getIsVisibleInSecondaryCamera()); // not sent over the wire APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)properties.getRenderLayer()); + APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)properties.getPrimitiveMode()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -2828,6 +2868,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, properties.getJointTranslationsSet()); APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, properties.getJointTranslations()); APPEND_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, properties.getRelayParentJoints()); + APPEND_ENTITY_PROPERTY(PROP_GROUP_CULLED, properties.getGroupCulled()); _staticAnimation.setProperties(properties); _staticAnimation.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3164,6 +3205,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over the wire READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3268,6 +3310,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS_SET, QVector, setJointTranslationsSet); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS, QVector, setJointTranslations); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RELAY_PARENT_JOINTS, bool, setRelayParentJoints); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GROUP_CULLED, bool, setGroupCulled); properties.getAnimation().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); } @@ -3547,6 +3590,7 @@ void EntityItemProperties::markAllChanged() { _canCastShadowChanged = true; _isVisibleInSecondaryCameraChanged = true; _renderLayerChanged = true; + _primitiveModeChanged = true; _grab.markAllChanged(); // Physics @@ -3639,6 +3683,7 @@ void EntityItemProperties::markAllChanged() { _jointTranslationsSetChanged = true; _jointTranslationsChanged = true; _relayParentJointsChanged = true; + _groupCulledChanged = true; _animation.markAllChanged(); // Light @@ -3922,6 +3967,9 @@ QList EntityItemProperties::listChangedProperties() { if (renderLayerChanged()) { out += "renderLayer"; } + if (primitiveModeChanged()) { + out += "primitiveMode"; + } getGrab().listChangedProperties(out); // Physics @@ -4168,6 +4216,9 @@ QList EntityItemProperties::listChangedProperties() { if (relayParentJointsChanged()) { out += "relayParentJoints"; } + if (groupCulledChanged()) { + out += "groupCulled"; + } getAnimation().listChangedProperties(out); // Light diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index a7992ea1ab..524f72f5b7 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -52,6 +52,7 @@ #include "MaterialMappingMode.h" #include "BillboardMode.h" #include "RenderLayer.h" +#include "PrimitiveMode.h" const quint64 UNKNOWN_CREATED_TIME = 0; @@ -152,6 +153,7 @@ public: DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW); DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA); 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_GROUP(Grab, grab, GrabPropertyGroup); // Physics @@ -251,6 +253,7 @@ public: DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector, QVector()); DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC); DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS); + DEFINE_PROPERTY_REF(PROP_GROUP_CULLED, GroupCulled, groupCulled, bool, false); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); // Light diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 9d9e7ffa01..a3d0d937cb 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -40,6 +40,7 @@ enum EntityPropertyList { PROP_CAN_CAST_SHADOW, PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire PROP_RENDER_LAYER, + PROP_PRIMITIVE_MODE, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, @@ -199,16 +200,17 @@ enum EntityPropertyList { PROP_JOINT_TRANSLATIONS_SET = PROP_DERIVED_3, PROP_JOINT_TRANSLATIONS = PROP_DERIVED_4, PROP_RELAY_PARENT_JOINTS = PROP_DERIVED_5, + PROP_GROUP_CULLED = PROP_DERIVED_6, // Animation - PROP_ANIMATION_URL = PROP_DERIVED_6, - PROP_ANIMATION_ALLOW_TRANSLATION = PROP_DERIVED_7, - PROP_ANIMATION_FPS = PROP_DERIVED_8, - PROP_ANIMATION_FRAME_INDEX = PROP_DERIVED_9, - PROP_ANIMATION_PLAYING = PROP_DERIVED_10, - PROP_ANIMATION_LOOP = PROP_DERIVED_11, - PROP_ANIMATION_FIRST_FRAME = PROP_DERIVED_12, - PROP_ANIMATION_LAST_FRAME = PROP_DERIVED_13, - PROP_ANIMATION_HOLD = PROP_DERIVED_14, + PROP_ANIMATION_URL = PROP_DERIVED_7, + PROP_ANIMATION_ALLOW_TRANSLATION = PROP_DERIVED_8, + PROP_ANIMATION_FPS = PROP_DERIVED_9, + PROP_ANIMATION_FRAME_INDEX = PROP_DERIVED_10, + PROP_ANIMATION_PLAYING = PROP_DERIVED_11, + PROP_ANIMATION_LOOP = PROP_DERIVED_12, + PROP_ANIMATION_FIRST_FRAME = PROP_DERIVED_13, + PROP_ANIMATION_LAST_FRAME = PROP_DERIVED_14, + PROP_ANIMATION_HOLD = PROP_DERIVED_15, // Light PROP_IS_SPOTLIGHT = PROP_DERIVED_0, diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 55ae1c6c3b..ddbb028b6e 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -67,6 +67,7 @@ EntityItemProperties ModelEntityItem::getProperties(const EntityPropertyFlags& d COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslationsSet, getJointTranslationsSet); COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslations, getJointTranslations); COPY_ENTITY_PROPERTY_TO_PROPERTIES(relayParentJoints, getRelayParentJoints); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(groupCulled, getGroupCulled); withReadLock([&] { _animationProperties.getProperties(properties); }); @@ -88,6 +89,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointTranslationsSet, setJointTranslationsSet); SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointTranslations, setJointTranslations); SET_ENTITY_PROPERTY_FROM_PROPERTIES(relayParentJoints, setRelayParentJoints); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(groupCulled, setGroupCulled); withWriteLock([&] { AnimationPropertyGroup animationProperties = _animationProperties; @@ -130,6 +132,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, QVector, setJointTranslationsSet); READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, QVector, setJointTranslations); READ_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, bool, setRelayParentJoints); + READ_ENTITY_PROPERTY(PROP_GROUP_CULLED, bool, setGroupCulled); // grab a local copy of _animationProperties to avoid multiple locks int bytesFromAnimation; @@ -166,6 +169,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_JOINT_TRANSLATIONS_SET; requestedProperties += PROP_JOINT_TRANSLATIONS; requestedProperties += PROP_RELAY_PARENT_JOINTS; + requestedProperties += PROP_GROUP_CULLED; requestedProperties += _animationProperties.getEntityProperties(params); return requestedProperties; @@ -192,6 +196,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet()); APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); APPEND_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, getRelayParentJoints()); + APPEND_ENTITY_PROPERTY(PROP_GROUP_CULLED, getGroupCulled()); withReadLock([&] { _animationProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, @@ -548,6 +553,18 @@ bool ModelEntityItem::getRelayParentJoints() const { }); } +void ModelEntityItem::setGroupCulled(bool value) { + withWriteLock([&] { + _groupCulled = value; + }); +} + +bool ModelEntityItem::getGroupCulled() const { + return resultWithReadLock([&] { + return _groupCulled; + }); +} + QString ModelEntityItem::getCompoundShapeURL() const { return _compoundShapeURL.get(); } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 5ca3e2caa1..8c9fbdc45f 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -100,6 +100,9 @@ public: void setRelayParentJoints(bool relayJoints); bool getRelayParentJoints() const; + void setGroupCulled(bool value); + bool getGroupCulled() const; + bool getAnimationIsPlaying() const; float getAnimationCurrentFrame() const; float getAnimationFPS() const; @@ -154,6 +157,7 @@ protected: glm::u8vec3 _color; QString _modelURL; bool _relayParentJoints; + bool _groupCulled { false }; ThreadSafeValueCache _compoundShapeURL; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index c57e1966b9..b7f8dffa13 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -255,7 +255,7 @@ enum class EntityVersion : PacketVersion { MorePropertiesCleanup, FixPropertiesFromCleanup, UpdatedPolyLines, - RenderLayer, + MigrateOverlayRenderProperties, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 68c9f8e5f7..debc6786f1 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -36,6 +36,7 @@ #include "MaterialMappingMode.h" #include "BillboardMode.h" #include "RenderLayer.h" +#include "PrimitiveMode.h" #include "OctreeConstants.h" #include "OctreeElement.h" @@ -265,6 +266,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, MaterialMappingMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, BillboardMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, RenderLayer& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, PrimitiveMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 3e32d19b49..81a81c5602 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -215,7 +215,7 @@ void CauterizedModel::updateRenderItems() { modelTransform.setTranslation(self->getTranslation()); modelTransform.setRotation(self->getRotation()); - bool isWireframe = self->isWireframe(); + PrimitiveMode primitiveMode = self->getPrimitiveMode(); auto renderItemKeyGlobalFlags = self->getRenderItemKeyGlobalFlags(); bool enableCauterization = self->getEnableCauterization(); @@ -232,7 +232,7 @@ void CauterizedModel::updateRenderItems() { bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning(); transaction.updateItem(itemID, [modelTransform, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey, - isWireframe, renderItemKeyGlobalFlags, enableCauterization](ModelMeshPartPayload& mmppData) { + primitiveMode, renderItemKeyGlobalFlags, enableCauterization](ModelMeshPartPayload& mmppData) { CauterizedMeshPartPayload& data = static_cast(mmppData); if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions, @@ -276,7 +276,7 @@ void CauterizedModel::updateRenderItems() { data.setEnableCauterization(enableCauterization); data.updateKey(renderItemKeyGlobalFlags); - data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning); + data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); }); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index ca2e56862d..7a52ad77da 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -342,7 +342,7 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { _itemKey = builder.build(); } -void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe, bool useDualQuaternionSkinning) { +void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning) { if (invalidateShapeKey) { _shapeKey = ShapeKey::Builder::invalid(); return; @@ -359,6 +359,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe bool isUnlit = drawMaterialKey.isUnlit(); bool isDeformed = _isBlendShaped || _isSkinned; + bool isWireframe = primitiveMode == PrimitiveMode::LINES; if (isWireframe) { isTranslucent = hasTangents = hasLightmap = false; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 29c0091f11..3b0590b4a9 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -109,7 +109,7 @@ public: render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - void setShapeKey(bool invalidateShapeKey, bool isWireframe, bool useDualQuaternionSkinning); + void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning); // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3ee9118252..ed9f7f1a3d 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -62,7 +62,6 @@ Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) : _snapModelToRegistrationPoint(false), _snappedToRegistrationPoint(false), _url(HTTP_INVALID_COM), - _isWireframe(false), _renderItemKeyGlobalFlags(render::ItemKey::Builder().withVisible().withTagBits(render::hifi::TAG_ALL_VIEWS).build()) { // we may have been created in the network thread, but we live in the main thread @@ -223,7 +222,7 @@ void Model::updateRenderItems() { Transform modelTransform = self->getTransform(); modelTransform.setScale(glm::vec3(1.0f)); - bool isWireframe = self->isWireframe(); + PrimitiveMode primitiveMode = self->getPrimitiveMode(); auto renderItemKeyGlobalFlags = self->getRenderItemKeyGlobalFlags(); render::Transaction transaction; @@ -238,7 +237,7 @@ void Model::updateRenderItems() { bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning(); transaction.updateItem(itemID, [modelTransform, meshState, useDualQuaternionSkinning, - invalidatePayloadShapeKey, isWireframe, renderItemKeyGlobalFlags](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags](ModelMeshPartPayload& data) { if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); } else { @@ -263,7 +262,7 @@ void Model::updateRenderItems() { data.updateTransformForSkinnedMesh(renderTransform, modelTransform); data.updateKey(renderItemKeyGlobalFlags); - data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning); + data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); }); } @@ -276,6 +275,11 @@ void Model::setRenderItemsNeedUpdate() { emit requestRenderUpdate(); } +void Model::setPrimitiveMode(PrimitiveMode primitiveMode) { + _primitiveMode = primitiveMode; + setRenderItemsNeedUpdate(); +} + void Model::reset() { if (isLoaded()) { const HFMModel& hfmModel = getHFMModel(); @@ -951,6 +955,7 @@ void Model::setGroupCulled(bool groupCulled, const render::ScenePointer& scene) updateRenderItemsKey(scene); } } + bool Model::isGroupCulled() const { return _renderItemKeyGlobalFlags.isSubMetaCulled(); } @@ -1545,16 +1550,16 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; auto renderItemsKey = _renderItemKeyGlobalFlags; - bool wireframe = isWireframe(); + PrimitiveMode primitiveMode = getPrimitiveMode(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, renderItemsKey, - invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(renderItemsKey); - data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning); + data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); }); } } @@ -1568,16 +1573,16 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; auto renderItemsKey = _renderItemKeyGlobalFlags; - bool wireframe = isWireframe(); + PrimitiveMode primitiveMode = getPrimitiveMode(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, renderItemsKey, - invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.removeMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(renderItemsKey); - data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning); + data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); }); } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 9dec94e0d5..08ba13b714 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -37,6 +37,7 @@ #include "GeometryCache.h" #include "TextureCache.h" #include "Rig.h" +#include "PrimitiveMode.h" // Use dual quaternion skinning! // Must match define in Skinning.slh @@ -162,8 +163,8 @@ public: bool isLoaded() const { return (bool)_renderGeometry && _renderGeometry->isHFMModelLoaded(); } bool isAddedToScene() const { return _addedToScene; } - void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; } - bool isWireframe() const { return _isWireframe; } + void setPrimitiveMode(PrimitiveMode primitiveMode); + PrimitiveMode getPrimitiveMode() const { return _primitiveMode; } void reset(); @@ -451,7 +452,7 @@ protected: virtual void createRenderItemSet(); - bool _isWireframe; + PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; bool _useDualQuaternionSkinning { false }; // debug rendering support diff --git a/libraries/shared/src/PrimitiveMode.cpp b/libraries/shared/src/PrimitiveMode.cpp new file mode 100644 index 0000000000..c426f896b9 --- /dev/null +++ b/libraries/shared/src/PrimitiveMode.cpp @@ -0,0 +1,24 @@ +// +// Created by Sam Gondelman on 1/7/19 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "PrimitiveMode.h" + +const char* primitiveModeNames[] = { + "solid", + "lines" +}; + +static const size_t PRIMITIVE_MODE_NAMES = (sizeof(primitiveModeNames) / sizeof(primitiveModeNames[0])); + +QString PrimitiveModeHelpers::getNameForPrimitiveMode(PrimitiveMode mode) { + if (((int)mode <= 0) || ((int)mode >= (int)PRIMITIVE_MODE_NAMES)) { + mode = (PrimitiveMode)0; + } + + return primitiveModeNames[(int)mode]; +} \ No newline at end of file diff --git a/libraries/shared/src/PrimitiveMode.h b/libraries/shared/src/PrimitiveMode.h new file mode 100644 index 0000000000..6072f24fb9 --- /dev/null +++ b/libraries/shared/src/PrimitiveMode.h @@ -0,0 +1,39 @@ +// +// Created by Sam Gondelman on 1/7/19. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_PrimitiveMode_h +#define hifi_PrimitiveMode_h + +#include "QString" + +/**jsdoc + *

How the geometry of the entity is rendered.

+ * + * + * + * + * + * + * + * + *
ValueDescription
solidThe entity will be drawn as a solid shape.
linesThe entity will be drawn as wireframe.
+ * @typedef {string} PrimitiveMode + */ + +enum class PrimitiveMode { + SOLID = 0, + LINES +}; + +class PrimitiveModeHelpers { +public: + static QString getNameForPrimitiveMode(PrimitiveMode mode); +}; + +#endif // hifi_PrimitiveMode_h + From 5dd59dd9e9cd672a454be5ce91b3d5e748ebb682 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 8 Jan 2019 14:02:57 -0800 Subject: [PATCH 3/4] correct lighting of layered shapes --- .../src/RenderableShapeEntityItem.cpp | 7 ++- libraries/render-utils/src/GeometryCache.cpp | 53 +++++++++++++------ libraries/render-utils/src/GeometryCache.h | 12 ++++- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 978341bb39..c47904213b 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -249,7 +249,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } else if (!useMaterialPipeline()) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + render::ShapePipelinePointer pipeline; + if (_renderLayer == RenderLayer::WORLD) { + pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + } else { + pipeline = outColor.a < 1.0f ? geometryCache->getForwardTransparentShapePipeline() : geometryCache->getForwardOpaqueShapePipeline(); + } if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index d6d6f4903e..02f51e558a 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -721,11 +721,16 @@ QHash GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader; gpu::ShaderPointer GeometryCache::_transparentShader; gpu::ShaderPointer GeometryCache::_unlitShader; +gpu::ShaderPointer GeometryCache::_forwardSimpleShader; +gpu::ShaderPointer GeometryCache::_forwardTransparentShader; +gpu::ShaderPointer GeometryCache::_forwardUnlitShader; gpu::ShaderPointer GeometryCache::_simpleFadeShader; gpu::ShaderPointer GeometryCache::_unlitFadeShader; render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline; +render::ShapePipelinePointer GeometryCache::_forwardSimpleOpaquePipeline; +render::ShapePipelinePointer GeometryCache::_forwardSimpleTransparentPipeline; render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; @@ -805,6 +810,8 @@ void GeometryCache::initializeShapePipelines() { if (!_simpleOpaquePipeline) { _simpleOpaquePipeline = getShapePipeline(false, false, true, false); _simpleTransparentPipeline = getShapePipeline(false, true, true, false); + _forwardSimpleOpaquePipeline = getShapePipeline(false, false, true, false, false, true); + _forwardSimpleTransparentPipeline = getShapePipeline(false, true, true, false, false, true); _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false); _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false); _simpleWirePipeline = getShapePipeline(false, false, true, true); @@ -812,9 +819,9 @@ void GeometryCache::initializeShapePipelines() { } render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, - bool unlit, bool depthBias) { + bool unlit, bool depthBias, bool forward) { - return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true), nullptr, + return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true, forward), nullptr, [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get()->getWhiteTexture()); DependencyManager::get()->setupKeyLightBatch(args, batch); @@ -2165,6 +2172,7 @@ public: HAS_DEPTH_BIAS_FLAG, IS_FADING_FLAG, IS_ANTIALIASED_FLAG, + IS_FORWARD_FLAG, NUM_FLAGS, }; @@ -2177,6 +2185,7 @@ public: HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG), IS_FADING = (1 << IS_FADING_FLAG), IS_ANTIALIASED = (1 << IS_ANTIALIASED_FLAG), + IS_FORWARD = (1 << IS_FORWARD_FLAG), }; typedef unsigned short Flags; @@ -2189,6 +2198,7 @@ public: bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); } bool isFading() const { return isFlag(IS_FADING); } bool isAntiAliased() const { return isFlag(IS_ANTIALIASED); } + bool isForward() const { return isFlag(IS_FORWARD); } Flags _flags = 0; #if defined(__clang__) @@ -2200,9 +2210,9 @@ public: SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true) { + bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false) { _flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) | - (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0) | (isAntiAliased ? IS_ANTIALIASED : 0); + (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0) | (isAntiAliased ? IS_ANTIALIASED : 0) | (forward ? IS_FORWARD : 0); } SimpleProgramKey(int bitmask) : _flags(bitmask) {} @@ -2255,8 +2265,8 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra } } -gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading, bool isAntiAliased) { - SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading, isAntiAliased }; +gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading, bool isAntiAliased, bool forward) { + SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading, isAntiAliased, forward }; // If the pipeline already exists, return it auto it = _simplePrograms.find(config); @@ -2269,13 +2279,20 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp static std::once_flag once; std::call_once(once, [&]() { using namespace shader::render_utils::program; - auto PS = DISABLE_DEFERRED ? forward_simple_textured : simple_textured; - // Use the forward pipeline for both here, otherwise transparents will be unlit - auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent : forward_simple_textured_transparent; - auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit : simple_textured_unlit; - _simpleShader = gpu::Shader::createProgram(PS); - _transparentShader = gpu::Shader::createProgram(PSTransparent); - _unlitShader = gpu::Shader::createProgram(PSUnlit); + + _forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured); + _forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent); + _forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit); + if (DISABLE_DEFERRED) { + _simpleShader = _forwardSimpleShader; + _transparentShader = _forwardTransparentShader; + _unlitShader = _forwardUnlitShader; + } else { + _simpleShader = gpu::Shader::createProgram(simple_textured); + // Use the forward pipeline for both here, otherwise transparents will be unlit + _transparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent); + _unlitShader = gpu::Shader::createProgram(simple_textured_unlit); + } }); } else { static std::once_flag once; @@ -2308,8 +2325,14 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp PrepareStencil::testMaskDrawShapeNoAA(*state); } - gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : - (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader)); + gpu::ShaderPointer program; + if (config.isForward()) { + program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _forwardUnlitShader) : + (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _forwardTransparentShader : _forwardSimpleShader)); + } else { + program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : + (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader)); + } gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 589be4dcc1..e46bb4a899 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -174,7 +174,7 @@ public: bool unlit = false, bool depthBias = false, bool isAntiAliased = true); // Get the pipeline to render static geometry static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true); + bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false); void bindWebBrowserProgram(gpu::Batch& batch, bool transparent = false); gpu::PipelinePointer getWebBrowserProgram(bool transparent); @@ -183,6 +183,8 @@ public: render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; } render::ShapePipelinePointer getTransparentShapePipeline() { assert(_simpleTransparentPipeline != nullptr); return _simpleTransparentPipeline; } + render::ShapePipelinePointer getForwardOpaqueShapePipeline() { assert(_forwardSimpleOpaquePipeline != nullptr); return _forwardSimpleOpaquePipeline; } + render::ShapePipelinePointer getForwardTransparentShapePipeline() { assert(_forwardSimpleTransparentPipeline != nullptr); return _forwardSimpleTransparentPipeline; } render::ShapePipelinePointer getOpaqueFadeShapePipeline() { assert(_simpleOpaqueFadePipeline != nullptr); return _simpleOpaqueFadePipeline; } render::ShapePipelinePointer getTransparentFadeShapePipeline() { assert(_simpleTransparentFadePipeline != nullptr); return _simpleTransparentFadePipeline; } render::ShapePipelinePointer getOpaqueShapePipeline(bool isFading); @@ -465,13 +467,19 @@ private: QHash _lastRegisteredGridBuffer; QHash _registeredGridBuffers; + // FIXME: clean these up static gpu::ShaderPointer _simpleShader; static gpu::ShaderPointer _transparentShader; static gpu::ShaderPointer _unlitShader; + static gpu::ShaderPointer _forwardSimpleShader; + static gpu::ShaderPointer _forwardTransparentShader; + static gpu::ShaderPointer _forwardUnlitShader; static gpu::ShaderPointer _simpleFadeShader; static gpu::ShaderPointer _unlitFadeShader; static render::ShapePipelinePointer _simpleOpaquePipeline; static render::ShapePipelinePointer _simpleTransparentPipeline; + static render::ShapePipelinePointer _forwardSimpleOpaquePipeline; + static render::ShapePipelinePointer _forwardSimpleTransparentPipeline; static render::ShapePipelinePointer _simpleOpaqueFadePipeline; static render::ShapePipelinePointer _simpleTransparentFadePipeline; static render::ShapePipelinePointer _simpleWirePipeline; @@ -485,7 +493,7 @@ private: gpu::PipelinePointer _simpleTransparentWebBrowserPipeline; static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false); + bool unlit = false, bool depthBias = false, bool forward = false); static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false); }; From 292071febb552e9d6e5fcae2f52d594214712eab Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 8 Jan 2019 14:34:19 -0800 Subject: [PATCH 4/4] fix model groupCulled --- .../src/RenderableModelEntityItem.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 216e5204e9..7e01af04dd 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1074,10 +1074,16 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare } void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) { + auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + + if (_model && _model->isGroupCulled()) { + builder.withMetaCullGroup(); + } + if (didVisualGeometryRequestSucceed) { - _itemKey = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + _itemKey = builder.build(); } else { - _itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + _itemKey = builder.withTypeShape().build(); } } @@ -1447,6 +1453,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce bool groupCulled = entity->getGroupCulled(); if (model->isGroupCulled() != groupCulled) { model->setGroupCulled(groupCulled); + setKey(_didLastVisualGeometryRequestSucceed); } }