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