diff --git a/examples/example/entities/zoneEntityExample.js b/examples/example/entities/zoneEntityExample.js index 84d87d1370..052de06a1d 100644 --- a/examples/example/entities/zoneEntityExample.js +++ b/examples/example/entities/zoneEntityExample.js @@ -29,7 +29,7 @@ print("zoneEntityA:" + zoneEntityA); var zoneEntityB = Entities.addEntity({ type: "Zone", - position: { x: 1, y: 1, z: 21 }, + position: { x: 5, y: 5, z: 5 }, dimensions: { x: 2, y: 2, z: 2 }, keyLightColor: { red: 0, green: 255, blue: 0 }, keyLightIntensity: 0.9, @@ -46,7 +46,7 @@ print("zoneEntityB:" + zoneEntityB); var zoneEntityC = Entities.addEntity({ type: "Zone", - position: { x: 5, y: 5, z: 15 }, + position: { x: 5, y: 10, z: 5 }, dimensions: { x: 10, y: 10, z: 10 }, keyLightColor: { red: 0, green: 0, blue: 255 }, keyLightIntensity: 0.75, diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c14a821a38..f6557b5f9a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -395,67 +395,14 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _tree->lockForRead(); - // Implement some kind of a stack/union mechanism here... - // - // * As you enter a zone (A), you use it's properties - // * if already in a zone, and you enter the union of that zone and a new zone (A + B) - // you use the settings of the new zone (B) you entered.. but remember that you were previously - // in zone A - // * if you enter a new zone and are in the union of 3 zones (A+B+C) then use zone C and remember - // you were most recently in B - _lastZones = _currentZones; - _currentZones.clear(); + // Whenever you're in an intersection between zones, we will always choose the smallest zone. + _bestZone = NULL; + _bestZoneVolume = std::numeric_limits::max(); _tree->recurseTreeWithOperation(renderOperation, &args); - const ZoneEntityItem* bestZone = NULL; - - if (_currentZones.empty()) { - // if we're not in any current zone, then we can completely erase our zoneHistory - _zoneHistory.clear(); - } else { - // we're in some zone... check to see if we've changed zones.. - QSet newZones = _currentZones - _lastZones; - if (!newZones.empty()) { - // we just entered a new zone, so we want to make a shift - EntityItemID theNewZone = *(newZones.begin()); // random we don't care, if it's one, then this works. - _zoneHistory << _currentZone; // remember the single zone we used to be in. - _currentZone = theNewZone; // change to our new zone - - // do something to remove any item of _zoneHistory that is not in _currentZones - QStack newHistory; - QStack::iterator i = _zoneHistory.begin(); - while(i != _zoneHistory.end()) { - EntityItemID zoneID = *i; - if (_currentZones.contains(zoneID)) { - newHistory << zoneID; - } - ++i; - } - - _zoneHistory = newHistory; - bestZone = dynamic_cast( - static_cast(_tree)->findEntityByEntityItemID(_currentZone)); - } else { - - if (_currentZones.contains(_currentZone)) { - // No change in zone, keep the current zone - bestZone = dynamic_cast( - static_cast(_tree)->findEntityByEntityItemID(_currentZone)); - } else { - if (!_zoneHistory.empty()) { - _currentZone = _zoneHistory.pop(); - bestZone = dynamic_cast( - static_cast(_tree)->findEntityByEntityItemID(_currentZone)); - } - - } - - } - } - QSharedPointer scene = DependencyManager::get(); - if (bestZone) { + if (_bestZone) { if (!_hasPreviousZone) { _previousKeyLightColor = scene->getKeyLightColor(); _previousKeyLightIntensity = scene->getKeyLightIntensity(); @@ -469,18 +416,16 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _previousStageDay = scene->getStageYearTime(); _hasPreviousZone = true; } - scene->setKeyLightColor(bestZone->getKeyLightColorVec3()); - scene->setKeyLightIntensity(bestZone->getKeyLightIntensity()); - scene->setKeyLightAmbientIntensity(bestZone->getKeyLightAmbientIntensity()); - scene->setKeyLightDirection(bestZone->getKeyLightDirection()); - scene->setStageSunModelEnable(bestZone->getStageSunModelEnabled()); - scene->setStageLocation(bestZone->getStageLongitude(), bestZone->getStageLatitude(), - bestZone->getStageAltitude()); - scene->setStageDayTime(bestZone->getStageHour()); - scene->setStageYearTime(bestZone->getStageDay()); - + scene->setKeyLightColor(_bestZone->getKeyLightColorVec3()); + scene->setKeyLightIntensity(_bestZone->getKeyLightIntensity()); + scene->setKeyLightAmbientIntensity(_bestZone->getKeyLightAmbientIntensity()); + scene->setKeyLightDirection(_bestZone->getKeyLightDirection()); + scene->setStageSunModelEnable(_bestZone->getStageSunModelEnabled()); + scene->setStageLocation(_bestZone->getStageLongitude(), _bestZone->getStageLatitude(), + _bestZone->getStageAltitude()); + scene->setStageDayTime(_bestZone->getStageHour()); + scene->setStageYearTime(_bestZone->getStageDay()); } else { - _currentZone = EntityItemID(); // clear out current zone if (_hasPreviousZone) { scene->setKeyLightColor(_previousKeyLightColor); scene->setKeyLightIntensity(_previousKeyLightIntensity); @@ -698,7 +643,23 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) // like other entity types. So we will skip the normal rendering tests if (entityItem->getType() == EntityTypes::Zone) { if (entityItem->contains(args->_viewFrustum->getPosition())) { - _currentZones << entityItem->getEntityItemID(); + float entityVolumeEstimate = entityItem->getVolumeEstimate(); + if (entityVolumeEstimate < _bestZoneVolume) { + _bestZoneVolume = entityVolumeEstimate; + _bestZone = dynamic_cast(entityItem); + } else if (entityVolumeEstimate == _bestZoneVolume) { + if (!_bestZone) { + _bestZoneVolume = entityVolumeEstimate; + _bestZone = dynamic_cast(entityItem); + } else { + // in the case of the volume being equal, we will use the + // EntityItemID to deterministically pick one entity over the other + if (entityItem->getEntityItemID() < _bestZone->getEntityItemID()) { + _bestZoneVolume = entityVolumeEstimate; + _bestZone = dynamic_cast(entityItem); + } + } + } } } else { // render entityItem diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index fd979fc9f9..8f720e5e48 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -167,12 +167,9 @@ private: QMultiMap _waitingOnPreload; - QSet _lastZones; - QSet _currentZones; - QStack _zoneHistory; - EntityItemID _currentZone; - bool _hasPreviousZone = false; + const ZoneEntityItem* _bestZone; + float _bestZoneVolume; glm::vec3 _previousKeyLightColor; float _previousKeyLightIntensity; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ad856698a2..28f1c7790b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -272,6 +272,7 @@ public: virtual bool isReadyToComputeShape() { return true; } virtual void computeShapeInfo(ShapeInfo& info); + virtual float getVolumeEstimate() const { return _dimensions.x * _dimensions.y * _dimensions.z; } /// return preferred shape type (actual physical shape may differ) virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; }