Merge branch 'update-interstitial' of https://github.com/danteruiz/hifi into interstitialMerged

This commit is contained in:
Wayne Chen 2018-09-26 16:45:22 -07:00
commit 813defebfc
8 changed files with 122 additions and 85 deletions

View file

@ -122,6 +122,7 @@
#include <RecordingScriptingInterface.h> #include <RecordingScriptingInterface.h>
#include <UpdateSceneTask.h> #include <UpdateSceneTask.h>
#include <RenderViewTask.h> #include <RenderViewTask.h>
#include <render/EngineStats.h>
#include <SecondaryCamera.h> #include <SecondaryCamera.h>
#include <ResourceCache.h> #include <ResourceCache.h>
#include <ResourceRequest.h> #include <ResourceRequest.h>
@ -5349,8 +5350,8 @@ void Application::resetPhysicsReadyInformation() {
// collision information of nearby entities to make running bullet be safe. // collision information of nearby entities to make running bullet be safe.
_fullSceneReceivedCounter = 0; _fullSceneReceivedCounter = 0;
_fullSceneCounterAtLastPhysicsCheck = 0; _fullSceneCounterAtLastPhysicsCheck = 0;
_nearbyEntitiesCountAtLastPhysicsCheck = 0; _gpuTextureMemSizeStabilityCount = 0;
_nearbyEntitiesStabilityCount = 0; _gpuTextureMemSizeAtLastCheck = 0;
_physicsEnabled = false; _physicsEnabled = false;
_octreeProcessor.startEntitySequence(); _octreeProcessor.startEntitySequence();
} }
@ -5589,18 +5590,20 @@ void Application::update(float deltaTime) {
// for nearby entities before starting bullet up. // for nearby entities before starting bullet up.
quint64 now = usecTimestampNow(); quint64 now = usecTimestampNow();
if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) { if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) {
// we've received a new full-scene octree stats packet, or it's been long enough to try again anyway if (gpuTextureMemSizeStable()) {
_lastPhysicsCheckTime = now; // we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
_fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter; _lastPhysicsCheckTime = now;
_lastQueriedViews.clear(); // Force new view. _fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
_lastQueriedViews.clear(); // Force new view.
// process octree stats packets are sent in between full sends of a scene (this isn't currently true). // process octree stats packets are sent in between full sends of a scene (this isn't currently true).
// We keep physics disabled until we've received a full scene and everything near the avatar in that // We keep physics disabled until we've received a full scene and everything near the avatar in that
// scene is ready to compute its collision shape. // scene is ready to compute its collision shape.
if (getMyAvatar()->isReadyForPhysics()) { if (getMyAvatar()->isReadyForPhysics()) {
_physicsEnabled = true; _physicsEnabled = true;
setIsInterstitialMode(false); setIsInterstitialMode(false);
getMyAvatar()->updateMotionBehaviorFromMenu(); getMyAvatar()->updateMotionBehaviorFromMenu();
}
} }
} }
} else if (domainLoadingInProgress) { } else if (domainLoadingInProgress) {
@ -6237,9 +6240,19 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
const bool isModifiedQuery = !_physicsEnabled; const bool isModifiedQuery = !_physicsEnabled;
if (isModifiedQuery) { if (isModifiedQuery) {
// Create modified view that is a simple sphere. // Create modified view that is a simple sphere.
bool interstitialModeEnabled = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
ConicalViewFrustum sphericalView; ConicalViewFrustum sphericalView;
sphericalView.setSimpleRadius(INITIAL_QUERY_RADIUS); sphericalView.setSimpleRadius(INITIAL_QUERY_RADIUS);
_octreeQuery.setConicalViews({ sphericalView });
if (interstitialModeEnabled) {
ConicalViewFrustum farView;
farView.set(_viewFrustum);
_octreeQuery.setConicalViews({ sphericalView, farView });
} else {
_octreeQuery.setConicalViews({ sphericalView });
}
_octreeQuery.setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE); _octreeQuery.setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
static constexpr float MIN_LOD_ADJUST = -20.0f; static constexpr float MIN_LOD_ADJUST = -20.0f;
_octreeQuery.setBoundaryLevelAdjust(MIN_LOD_ADJUST); _octreeQuery.setBoundaryLevelAdjust(MIN_LOD_ADJUST);
@ -6551,69 +6564,22 @@ void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNode
} }
} }
bool Application::nearbyEntitiesAreReadyForPhysics() { bool Application::gpuTextureMemSizeStable() {
// this is used to avoid the following scenario: auto renderConfig = qApp->getRenderEngine()->getConfiguration();
// A table has some items sitting on top of it. The items are at rest, meaning they aren't active in bullet. auto renderStats = renderConfig->getConfig<render::EngineStats>("Stats");
// Someone logs in close to the table. They receive information about the items on the table before they
// receive information about the table. The items are very close to the avatar's capsule, so they become
// activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet.
EntityTreePointer entityTree = getEntities()->getTree();
if (!entityTree) {
return false;
}
// We don't want to use EntityTree::findEntities(AABox, ...) method because that scan will snarf parented entities quint64 textureResourceGPUMemSize = renderStats->textureResourceGPUMemSize;
// whose bounding boxes cannot be computed (it is too loose for our purposes here). Instead we manufacture quint64 texturePopulatedGPUMemSize = renderStats->textureResourcePopulatedGPUMemSize;
// custom filters and use the general-purpose EntityTree::findEntities(filter, ...)
QVector<EntityItemPointer> entities;
AABox avatarBox(getMyAvatar()->getWorldPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
// create two functions that use avatarBox (entityScan and elementScan), the second calls the first
std::function<bool (EntityItemPointer&)> entityScan = [=](EntityItemPointer& entity) {
if (entity->shouldBePhysical()) {
bool success = false;
AABox entityBox = entity->getAABox(success);
// important: bail for entities that cannot supply a valid AABox
return success && avatarBox.touches(entityBox);
}
return false;
};
std::function<bool(const OctreeElementPointer&, void*)> elementScan = [&](const OctreeElementPointer& element, void* unused) {
if (element->getAACube().touches(avatarBox)) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->getEntities(entityScan, entities);
return true;
}
return false;
};
entityTree->withReadLock([&] { if (_gpuTextureMemSizeAtLastCheck == textureResourceGPUMemSize) {
// Pass the second function to the general-purpose EntityTree::findEntities() _gpuTextureMemSizeStabilityCount++;
// which will traverse the tree, apply the two filter functions (to element, then to entities)
// as it traverses. The end result will be a list of entities that match.
entityTree->findEntities(elementScan, entities);
});
uint32_t nearbyCount = entities.size();
if (nearbyCount == _nearbyEntitiesCountAtLastPhysicsCheck) {
_nearbyEntitiesStabilityCount++;
} else { } else {
_nearbyEntitiesStabilityCount = 0; _gpuTextureMemSizeStabilityCount = 0;
} }
_nearbyEntitiesCountAtLastPhysicsCheck = nearbyCount; _gpuTextureMemSizeAtLastCheck = textureResourceGPUMemSize;
const uint32_t MINIMUM_NEARBY_ENTITIES_STABILITY_COUNT = 3; if (_gpuTextureMemSizeStabilityCount >= _minimumGPUTextureMemSizeStabilityCount) {
if (_nearbyEntitiesStabilityCount >= MINIMUM_NEARBY_ENTITIES_STABILITY_COUNT) { return (textureResourceGPUMemSize == texturePopulatedGPUMemSize);
// We've seen the same number of nearby entities for several stats packets in a row. assume we've got all
// the local entities.
bool result = true;
foreach (EntityItemPointer entity, entities) {
if (entity->shouldBePhysical() && !entity->isReadyToComputeShape()) {
HIFI_FCDEBUG(interfaceapp(), "Physics disabled until entity loads: " << entity->getID() << entity->getName());
// don't break here because we want all the relevant entities to start their downloads
result = false;
}
}
return result;
} }
return false; return false;
} }

View file

@ -233,6 +233,8 @@ public:
float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); } float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); }
void setSettingConstrainToolbarPosition(bool setting); void setSettingConstrainToolbarPosition(bool setting);
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int stabilityCount) { _minimumGPUTextureMemSizeStabilityCount = stabilityCount; }
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; } NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
@ -528,7 +530,7 @@ private:
bool importFromZIP(const QString& filePath); bool importFromZIP(const QString& filePath);
bool importImage(const QString& urlString); bool importImage(const QString& urlString);
bool nearbyEntitiesAreReadyForPhysics(); bool gpuTextureMemSizeStable();
int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode);
void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket); void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket);
@ -585,6 +587,8 @@ private:
QElapsedTimer _lastTimeUpdated; QElapsedTimer _lastTimeUpdated;
QElapsedTimer _lastTimeRendered; QElapsedTimer _lastTimeRendered;
int _minimumGPUTextureMemSizeStabilityCount { 15 };
ShapeManager _shapeManager; ShapeManager _shapeManager;
PhysicalEntitySimulationPointer _entitySimulation; PhysicalEntitySimulationPointer _entitySimulation;
PhysicsEnginePointer _physicsEngine; PhysicsEnginePointer _physicsEngine;
@ -725,8 +729,10 @@ private:
std::atomic<uint32_t> _fullSceneReceivedCounter { 0 }; // how many times have we received a full-scene octree stats packet std::atomic<uint32_t> _fullSceneReceivedCounter { 0 }; // how many times have we received a full-scene octree stats packet
uint32_t _fullSceneCounterAtLastPhysicsCheck { 0 }; // _fullSceneReceivedCounter last time we checked physics ready uint32_t _fullSceneCounterAtLastPhysicsCheck { 0 }; // _fullSceneReceivedCounter last time we checked physics ready
uint32_t _nearbyEntitiesCountAtLastPhysicsCheck { 0 }; // how many in-range entities last time we checked physics ready
uint32_t _nearbyEntitiesStabilityCount { 0 }; // how many times has _nearbyEntitiesCountAtLastPhysicsCheck been the same quint64 _gpuTextureMemSizeStabilityCount { 0 };
quint64 _gpuTextureMemSizeAtLastCheck { 0 };
quint64 _lastPhysicsCheckTime { usecTimestampNow() }; // when did we last check to see if physics was ready quint64 _lastPhysicsCheckTime { usecTimestampNow() }; // when did we last check to see if physics was ready
bool _keyboardDeviceHasFocus { true }; bool _keyboardDeviceHasFocus { true };

View file

@ -10,6 +10,9 @@
// //
#include "SafeLanding.h" #include "SafeLanding.h"
#include <SharedUtil.h>
#include "EntityTreeRenderer.h" #include "EntityTreeRenderer.h"
#include "ModelEntityItem.h" #include "ModelEntityItem.h"
#include "InterfaceLogging.h" #include "InterfaceLogging.h"
@ -39,6 +42,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
_entityTree = entityTree; _entityTree = entityTree;
_trackedEntities.clear(); _trackedEntities.clear();
_trackingEntities = true; _trackingEntities = true;
_maxTrackedEntityCount = 0;
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(), connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity); &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(), connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
@ -47,6 +51,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
_sequenceNumbers.clear(); _sequenceNumbers.clear();
_initialStart = INVALID_SEQUENCE; _initialStart = INVALID_SEQUENCE;
_initialEnd = INVALID_SEQUENCE; _initialEnd = INVALID_SEQUENCE;
_startTime = usecTimestampNow();
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority); EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
} }
} }
@ -55,6 +60,7 @@ void SafeLanding::stopEntitySequence() {
Locker lock(_lock); Locker lock(_lock);
_trackingEntities = false; _trackingEntities = false;
_maxTrackedEntityCount = 0; _maxTrackedEntityCount = 0;
_trackedEntityStabilityCount = 0;
_initialStart = INVALID_SEQUENCE; _initialStart = INVALID_SEQUENCE;
_initialEnd = INVALID_SEQUENCE; _initialEnd = INVALID_SEQUENCE;
_trackedEntities.clear(); _trackedEntities.clear();
@ -66,13 +72,14 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
Locker lock(_lock); Locker lock(_lock);
EntityItemPointer entity = _entityTree->findEntityByID(entityID); EntityItemPointer entity = _entityTree->findEntityByID(entityID);
if (entity) { if (entity && entity->getCreated() < _startTime) {
_trackedEntities.emplace(entityID, entity); _trackedEntities.emplace(entityID, entity);
int trackedEntityCount = (int)_trackedEntities.size(); int trackedEntityCount = (int)_trackedEntities.size();
if (trackedEntityCount > _maxTrackedEntityCount) { if (trackedEntityCount > _maxTrackedEntityCount) {
_maxTrackedEntityCount = trackedEntityCount; _maxTrackedEntityCount = trackedEntityCount;
_trackedEntityStabilityCount = 0;
} }
qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName(); qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
} }
@ -116,11 +123,19 @@ bool SafeLanding::isLoadSequenceComplete() {
float SafeLanding::loadingProgressPercentage() { float SafeLanding::loadingProgressPercentage() {
Locker lock(_lock); Locker lock(_lock);
static const int MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
float percentage = 0.0f;
if (_maxTrackedEntityCount > 0) { if (_maxTrackedEntityCount > 0) {
return ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount); percentage = ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount);
} }
return 0.0f; if (_trackedEntityStabilityCount < MINIMUM_TRACKED_ENTITY_STABILITY_COUNT) {
percentage *= 0.20f;
}
return percentage;
} }
bool SafeLanding::isSequenceNumbersComplete() { bool SafeLanding::isSequenceNumbersComplete() {
@ -166,16 +181,19 @@ bool SafeLanding::isEntityLoadingComplete() {
auto entityTree = qApp->getEntities(); auto entityTree = qApp->getEntities();
auto entityMapIter = _trackedEntities.begin(); auto entityMapIter = _trackedEntities.begin();
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
while (entityMapIter != _trackedEntities.end()) { while (entityMapIter != _trackedEntities.end()) {
auto entity = entityMapIter->second; auto entity = entityMapIter->second;
bool isVisuallyReady = true; bool isVisuallyReady = true;
Settings settings;
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled(); bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
if (enableInterstitial) { if (enableInterstitial) {
isVisuallyReady = (entity->isVisuallyReady() || !entityTree->renderableForEntityId(entityMapIter->first)); isVisuallyReady = (entity->isVisuallyReady() || !entityTree->renderableForEntityId(entityMapIter->first));
qDebug() << "EntityTpye" << EntityTypes::getEntityTypeName(entity->getType()) << entity->getEntityItemID() << isVisuallyReady;
} }
if (isEntityPhysicsReady(entity) && isVisuallyReady) { if (isEntityPhysicsReady(entity) && isVisuallyReady) {
@ -188,6 +206,13 @@ bool SafeLanding::isEntityLoadingComplete() {
entityMapIter++; entityMapIter++;
} }
} }
if (enableInterstitial) {
_trackedEntityStabilityCount++;
qDebug() << "EntityList size" << _trackedEntities.size() << "\n";
}
return _trackedEntities.empty(); return _trackedEntities.empty();
} }

View file

@ -52,6 +52,9 @@ private:
int _initialStart { INVALID_SEQUENCE }; int _initialStart { INVALID_SEQUENCE };
int _initialEnd { INVALID_SEQUENCE }; int _initialEnd { INVALID_SEQUENCE };
int _maxTrackedEntityCount { 0 }; int _maxTrackedEntityCount { 0 };
int _trackedEntityStabilityCount { 0 };
quint64 _startTime { 0 };
struct SequenceLessThan { struct SequenceLessThan {
bool operator()(const int& a, const int& b) const; bool operator()(const int& a, const int& b) const;

View file

@ -398,6 +398,10 @@ void WindowScriptingInterface::showAssetServer(const QString& upload) {
QMetaObject::invokeMethod(qApp, "showAssetServerWidget", Qt::QueuedConnection, Q_ARG(QString, upload)); QMetaObject::invokeMethod(qApp, "showAssetServerWidget", Qt::QueuedConnection, Q_ARG(QString, upload));
} }
void WindowScriptingInterface::setMinimumGPUTextureMemSizeStabilityCount(int stabilityCount) {
QMetaObject::invokeMethod(qApp, " setMinimumGPUTextureMemStabilityCount", Qt::QueuedConnection, Q_ARG(int, stabilityCount));
}
QString WindowScriptingInterface::checkVersion() { QString WindowScriptingInterface::checkVersion() {
return QCoreApplication::applicationVersion(); return QCoreApplication::applicationVersion();
} }

View file

@ -571,6 +571,8 @@ public slots:
float domainLoadingProgress(); float domainLoadingProgress();
void setMinimumGPUTextureMemSizeStabilityCount(int stabilityCount);
private slots: private slots:
void onWindowGeometryChanged(const QRect& geometry); void onWindowGeometryChanged(const QRect& geometry);
void onMessageBoxSelected(int button); void onMessageBoxSelected(int button);

View file

@ -75,4 +75,4 @@ Item {
} }
} }
} }

View file

@ -188,6 +188,8 @@
var currentDomain = "no domain"; var currentDomain = "no domain";
var timer = null; var timer = null;
var target = 0; var target = 0;
var textureMemSizeStabilityCount = 0;
var textureMemSizeAtLastCheck = 0;
var connectionToDomainFailed = false; var connectionToDomainFailed = false;
@ -229,6 +231,8 @@
updateOverlays(false); updateOverlays(false);
startAudio(); startAudio();
target = 0; target = 0;
textureMemSizeStabilityCount = 0;
textureMemSizeAtLastCheck = 0;
currentProgress = 0.1; currentProgress = 0.1;
connectionToDomainFailed = false; connectionToDomainFailed = false;
previousCameraMode = Camera.mode; previousCameraMode = Camera.mode;
@ -356,9 +360,11 @@
Overlays.editOverlay(loadingBarPlacard, properties); Overlays.editOverlay(loadingBarPlacard, properties);
Overlays.editOverlay(loadingBarProgress, loadingBarProperties); Overlays.editOverlay(loadingBarProgress, loadingBarProperties);
Menu.setIsOptionChecked("Show Overlays", physicsEnabled); if (!DEBUG) {
if (!HMD.active) { Menu.setIsOptionChecked("Show Overlays", physicsEnabled);
toolbar.writeProperty("visible", physicsEnabled); if (!HMD.active) {
toolbar.writeProperty("visible", physicsEnabled);
}
} }
resetValues(); resetValues();
@ -389,18 +395,43 @@
} }
function update() { function update() {
var renderStats = Render.getConfig("Stats");
var physicsEnabled = Window.isPhysicsEnabled(); var physicsEnabled = Window.isPhysicsEnabled();
var thisInterval = Date.now(); var thisInterval = Date.now();
var deltaTime = (thisInterval - lastInterval); var deltaTime = (thisInterval - lastInterval);
lastInterval = thisInterval; lastInterval = thisInterval;
var domainLoadingProgressPercentage = Window.domainLoadingProgress(); var domainLoadingProgressPercentage = Window.domainLoadingProgress();
var progress = ((TOTAL_LOADING_PROGRESS * 0.4) * domainLoadingProgressPercentage);
var progress = MIN_LOADING_PROGRESS * domainLoadingProgressPercentage;
if (progress >= target) { if (progress >= target) {
target = progress; target = progress;
} }
if (currentProgress >= (TOTAL_LOADING_PROGRESS * 0.4)) {
var textureResourceGPUMemSize = renderStats.textureResourceGPUMemSize;
var texturePopulatedGPUMemSize = renderStats.textureResourcePopulatedGPUMemSize;
if (textureMemSizeAtLastCheck === textureResourceGPUMemSize) {
textureMemSizeStabilityCount++;
} else {
textureMemSizeStabilityCount = 0;
}
textureMemSizeAtLastCheck = textureResourceGPUMemSize;
if (textureMemSizeStabilityCount >= 15) {
if (textureResourceGPUMemSize > 0) {
print((texturePopulatedGPUMemSize / textureResourceGPUMemSize));
var gpuPercantage = (TOTAL_LOADING_PROGRESS * 0.6) * (texturePopulatedGPUMemSize / textureResourceGPUMemSize);
var totalProgress = progress + gpuPercantage;
if (totalProgress >= target) {
target = totalProgress;
}
}
}
}
if ((physicsEnabled && (currentProgress < TOTAL_LOADING_PROGRESS))) { if ((physicsEnabled && (currentProgress < TOTAL_LOADING_PROGRESS))) {
target = TOTAL_LOADING_PROGRESS; target = TOTAL_LOADING_PROGRESS;
} }