Merge pull request #13227 from SamGondelman/entityMirror

Add local-only isVisibleInSecondaryCamera flag to entities
This commit is contained in:
John Conklin II 2018-06-04 11:06:00 -07:00 committed by GitHub
commit 08fcad1932
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 88 additions and 21 deletions

View file

@ -54,9 +54,7 @@ namespace render {
}
// always visible in primary view. if isVisibleInSecondaryCamera, also draw in secondary view
uint32_t viewTagBits = render::hifi::TAG_MAIN_VIEW |
(overlay->getIsVisibleInSecondaryCamera() ? render::hifi::TAG_SECONDARY_VIEW : render::hifi::TAG_NONE);
render::hifi::Tag viewTagBits = overlay->getIsVisibleInSecondaryCamera() ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW;
builder.withTagBits(viewTagBits);
return builder.build();

View file

@ -157,16 +157,20 @@ Item::Bound EntityRenderer::getBound() {
return _bound;
}
render::hifi::Tag EntityRenderer::getTagMask() const {
return _isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW;
}
ItemKey EntityRenderer::getKey() {
if (isTransparent()) {
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask());
}
// This allows shapes to cast shadows
if (_canCastShadow) {
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster();
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withShadowCaster();
} else {
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask());
}
}
@ -380,6 +384,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
_moving = entity->isMovingRelativeToParent();
_visible = entity->getVisible();
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
_canCastShadow = entity->getCanCastShadow();
_cauterized = entity->getCauterized();
_needsRenderUpdate = false;

View file

@ -18,6 +18,7 @@
#include "AbstractViewStateInterface.h"
#include "EntitiesRendererLogging.h"
#include <graphics-scripting/Forward.h>
#include <RenderHifi.h>
class EntityTreeRenderer;
@ -74,6 +75,7 @@ protected:
virtual Item::Bound getBound() override;
virtual void render(RenderArgs* args) override final;
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override;
virtual render::hifi::Tag getTagMask() const;
// Returns true if the item in question needs to have updateInScene called because of internal rendering state changes
virtual bool needsRenderUpdate() const;
@ -97,6 +99,8 @@ protected:
bool isFading() const { return _isFading; }
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
template <typename F, typename T>
T withReadLockResult(const std::function<T()>& f) {
@ -129,6 +133,7 @@ protected:
bool _isFading{ _entitiesShouldFadeFunction() };
bool _prevIsTransparent { false };
bool _visible { false };
bool _isVisibleInSecondaryCamera { false };
bool _canCastShadow { false };
bool _cauterized { false };
bool _moving { false };

View file

@ -43,7 +43,7 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
ItemKey MaterialEntityRenderer::getKey() {
ItemKey::Builder builder;
builder.withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
builder.withTypeShape().withTagBits(getTagMask());
if (!_visible) {
builder.withInvisible();

View file

@ -1060,9 +1060,9 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
if (didVisualGeometryRequestSucceed) {
_itemKey = ItemKey::Builder().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
_itemKey = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask());
} else {
_itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
_itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(getTagMask());
}
}
@ -1070,6 +1070,13 @@ ItemKey ModelEntityRenderer::getKey() {
return _itemKey;
}
render::hifi::Tag ModelEntityRenderer::getTagMask() const {
// Default behavior for model is to not be visible in main view if cauterized (aka parented to the avatar's neck joint)
return _cauterized ?
(_isVisibleInSecondaryCamera ? render::hifi::TAG_SECONDARY_VIEW : render::hifi::TAG_NONE) :
Parent::getTagMask(); // calculate which views to be shown in
}
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) {
if (_model) {
auto metaSubItems = _subRenderItemIDs;
@ -1329,6 +1336,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, _model);
}
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
});
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate);
@ -1386,11 +1394,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
entity->updateModelBounds();
entity->stopModelOverrideIfNoParent();
// Default behavior for model is to not be visible in main view if cauterized (aka parented to the avatar's neck joint)
auto tagMask = _cauterized ?
render::hifi::TAG_SECONDARY_VIEW : // draw in every view except the main one (view zero)
render::hifi::TAG_ALL_VIEWS; // draw in all views
render::hifi::Tag tagMask = getTagMask();
if (model->isVisible() != _visible) {
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
// the renderable item. As it stands now the model checks it's visible/invisible state
@ -1478,6 +1482,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
}
}
void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) {
Parent::setIsVisibleInSecondaryCamera(value);
setKey(_didLastVisualGeometryRequestSucceed);
}
void ModelEntityRenderer::flagForCollisionGeometryUpdate() {
_needsCollisionGeometryUpdate = true;
emit requestRenderUpdate();

View file

@ -164,6 +164,10 @@ protected:
void flagForCollisionGeometryUpdate();
void setCollisionMeshKey(const void* key);
render::hifi::Tag getTagMask() const override;
void setIsVisibleInSecondaryCamera(bool value) override;
private:
void animate(const TypedEntityPointer& entity);
void mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames);
@ -202,6 +206,8 @@ private:
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
bool _didLastVisualGeometryRequestSucceed { false };
void processMaterials();
};

View file

@ -147,9 +147,9 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn
ItemKey ParticleEffectEntityRenderer::getKey() {
if (_visible) {
return ItemKey::Builder::transparentShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
return ItemKey::Builder::transparentShape().withTagBits(getTagMask());
} else {
return ItemKey::Builder().withInvisible().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).build();
return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).build();
}
}

View file

@ -112,7 +112,7 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
}
ItemKey PolyLineEntityRenderer::getKey() {
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask());
}
ShapeKey PolyLineEntityRenderer::getShapeKey() {

View file

@ -169,7 +169,7 @@ public:
}
protected:
virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); }
virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()); }
virtual ShapeKey getShapeKey() override;
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;

View file

@ -139,7 +139,7 @@ bool ShapeEntityRenderer::isTransparent() const {
ItemKey ShapeEntityRenderer::getKey() {
ItemKey::Builder builder;
builder.withTypeShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
builder.withTypeShape().withTypeMeta().withTagBits(getTagMask());
withReadLock([&] {
if (isTransparent()) {

View file

@ -269,7 +269,7 @@ void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
ItemKey ZoneEntityRenderer::getKey() {
return ItemKey::Builder().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).build();
return ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).build();
}
bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {

View file

@ -1383,6 +1383,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera);
// Certifiable Properties
SET_ENTITY_PROPERTY_FROM_PROPERTIES(itemName, setItemName);
@ -2760,6 +2761,28 @@ void EntityItem::setVisible(bool value) {
}
}
bool EntityItem::isVisibleInSecondaryCamera() const {
bool result;
withReadLock([&] {
result = _isVisibleInSecondaryCamera;
});
return result;
}
void EntityItem::setIsVisibleInSecondaryCamera(bool value) {
bool changed = false;
withWriteLock([&] {
if (_isVisibleInSecondaryCamera != value) {
changed = true;
_isVisibleInSecondaryCamera = value;
}
});
if (changed) {
emit requestRenderUpdate();
}
}
bool EntityItem::getCanCastShadow() const {
bool result;
withReadLock([&] {

View file

@ -277,6 +277,9 @@ public:
bool getVisible() const;
void setVisible(bool value);
bool isVisibleInSecondaryCamera() const;
void setIsVisibleInSecondaryCamera(bool value);
bool getCanCastShadow() const;
void setCanCastShadow(bool value);
@ -578,6 +581,7 @@ protected:
glm::vec3 _registrationPoint { ENTITY_ITEM_DEFAULT_REGISTRATION_POINT };
float _angularDamping { ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING };
bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE };
bool _isVisibleInSecondaryCamera { ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA };
bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW };
bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS };
uint16_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT };

View file

@ -368,6 +368,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData);
CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
// Certifiable Properties
CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName);
@ -490,6 +491,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities. Shadows are cast if inside a
* {@link Entities.EntityType|Zone} entity with <code>castShadows</code> 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 <code>true</code> then the entity 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.
@ -1226,6 +1228,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
// Certifiable Properties
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ITEM_NAME, itemName);
@ -1565,6 +1568,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale);
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot);
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData);
COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera);
// Certifiable Properties
COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName);
@ -1944,6 +1948,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float);
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString);
ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool);
// Certifiable Properties
ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString);
ADD_PROPERTY_TO_MAP(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString);
@ -3041,6 +3047,8 @@ void EntityItemProperties::markAllChanged() {
_cloneDynamicChanged = true;
_cloneAvatarEntityChanged = true;
_cloneOriginIDChanged = true;
_isVisibleInSecondaryCameraChanged = true;
}
// The minimum bounding box for the entity.
@ -3319,6 +3327,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
if (materialDataChanged()) {
out += "materialData";
}
if (isVisibleInSecondaryCameraChanged()) {
out += "isVisibleInSecondaryCamera";
}
// Certifiable Properties
if (itemNameChanged()) {

View file

@ -233,6 +233,8 @@ public:
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0);
DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, "");
DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA);
// Certifiable Properties - related to Proof of Purchase certificates
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);
DEFINE_PROPERTY_REF(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString, ENTITY_ITEM_DEFAULT_ITEM_DESCRIPTION);

View file

@ -46,6 +46,7 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0;
const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f;
const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
const bool ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA = true;
const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { true };
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");

View file

@ -249,6 +249,8 @@ enum EntityPropertyList {
PROP_MATERIAL_MAPPING_ROT,
PROP_MATERIAL_DATA,
PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire, only used locally
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line
PROP_AFTER_LAST_ITEM,

View file

@ -83,7 +83,8 @@
"position": cameraPosition,
"shapeType": "simple-compound",
"type": "Model",
"userData": "{\"grabbableKey\":{\"grabbable\":true}}"
"userData": "{\"grabbableKey\":{\"grabbable\":true}}",
"isVisibleInSecondaryCamera": false
}, true);
spectatorCameraConfig.attachedEntityId = camera;
updateOverlay();