From c594dcdf9f3b5083147a00b1fb42a86fa92d386d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 25 Jul 2016 10:52:31 -0700 Subject: [PATCH 1/7] Add priority loading for model entities --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 3 ++- libraries/entities-renderer/src/EntityTreeRenderer.h | 4 +++- .../entities-renderer/src/RenderableModelEntityItem.cpp | 6 +++++- libraries/render-utils/src/Model.cpp | 5 ++++- libraries/render-utils/src/Model.h | 2 ++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 1ec934be92..378e78d0cc 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -529,7 +529,7 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha std::static_pointer_cast(_tree)->processEraseMessage(message, sourceNode); } -ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) { +ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl, float priority) { ModelPointer model = nullptr; // Only create and delete models on the thread that owns the EntityTreeRenderer @@ -543,6 +543,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString } model = std::make_shared(std::make_shared()); + model->priority = priority; model->init(); model->setURL(QUrl(url)); model->setCollisionModelURL(QUrl(collisionUrl)); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index b0d0d2bacc..b0044b603f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -46,6 +46,8 @@ public: virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; } virtual void setTree(OctreePointer newTree); + glm::vec3 cameraPosition {}; + void shutdown(); void update(); @@ -66,7 +68,7 @@ public: void reloadEntityScripts(); /// if a renderable entity item needs a model, we will allocate it for them - Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl); + Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl, float priority = 0); /// if a renderable entity item needs to update the URL of a model, we will handle that for the entity Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index eba2d4cf4b..bfcd604288 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -484,7 +484,11 @@ ModelPointer RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { if (!getModelURL().isEmpty()) { // If we don't have a model, allocate one *immediately* if (!_model) { - _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL()); + auto dims = this->getDimensions(); + auto maxSize = glm::max(dims.x, dims.y, dims.z); + auto distance = glm::distance(renderer->cameraPosition, getPosition()); + float priority = atan2(maxSize / 2, distance); + _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL(), priority); _needsInitialSimulation = true; // If we need to change URLs, update it *after rendering* (to avoid access violations) } else if ((QUrl(getModelURL()) != _model->getURL() || QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d755dc3aca..86d1116717 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -826,7 +826,10 @@ void Model::setURL(const QUrl& url) { invalidCalculatedMeshBoxes(); deleteGeometry(); - _renderWatcher.setResource(DependencyManager::get()->getGeometryResource(url)); + auto resource = DependencyManager::get()->getGeometryResource(url); + resource->setLoadPriority(this, priority); + qDebug() << "Setting priority to: " << priority; + _renderWatcher.setResource(resource); onInvalidate(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index f7bf83ca5b..1713951366 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -238,6 +238,8 @@ public: // returns 'true' if needs fullUpdate after geometry change bool updateGeometry(); + float priority { 0 }; + public slots: void loadURLFinished(bool success); void loadCollisionModelURLFinished(bool success); From 77e993510eeb205da58febdeda9b96df626bf5ef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 09:57:01 -0700 Subject: [PATCH 2/7] Cleanup implementation of angular loading --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- libraries/entities-renderer/src/EntityTreeRenderer.h | 4 +--- libraries/render-utils/src/Model.cpp | 1 - libraries/render-utils/src/Model.h | 6 +++++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 378e78d0cc..24827ea111 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -529,7 +529,7 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha std::static_pointer_cast(_tree)->processEraseMessage(message, sourceNode); } -ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl, float priority) { +ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority) { ModelPointer model = nullptr; // Only create and delete models on the thread that owns the EntityTreeRenderer @@ -543,7 +543,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString } model = std::make_shared(std::make_shared()); - model->priority = priority; + model->setLoadingPriority(loadingPriority); model->init(); model->setURL(QUrl(url)); model->setCollisionModelURL(QUrl(collisionUrl)); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index b0044b603f..4111207e00 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -46,8 +46,6 @@ public: virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; } virtual void setTree(OctreePointer newTree); - glm::vec3 cameraPosition {}; - void shutdown(); void update(); @@ -68,7 +66,7 @@ public: void reloadEntityScripts(); /// if a renderable entity item needs a model, we will allocate it for them - Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl, float priority = 0); + Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority = 0); /// if a renderable entity item needs to update the URL of a model, we will handle that for the entity Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 86d1116717..e36c9d8d40 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -828,7 +828,6 @@ void Model::setURL(const QUrl& url) { auto resource = DependencyManager::get()->getGeometryResource(url); resource->setLoadPriority(this, priority); - qDebug() << "Setting priority to: " << priority; _renderWatcher.setResource(resource); onInvalidate(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1713951366..4b93d19d35 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -238,7 +238,7 @@ public: // returns 'true' if needs fullUpdate after geometry change bool updateGeometry(); - float priority { 0 }; + float setLoadingPriority(float priority) { _loadingPriority = priority; } public slots: void loadURLFinished(bool success); @@ -407,6 +407,10 @@ protected: bool _visualGeometryRequestFailed { false }; bool _collisionGeometryRequestFailed { false }; + +private: + float _loadingPriority { 0 }; + }; Q_DECLARE_METATYPE(ModelPointer) From 4f9be2ae72e3231297a46869536d464ee548cd8d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 13:19:53 -0700 Subject: [PATCH 3/7] Fix camera position not being set for angular loading --- interface/src/Application.cpp | 2 ++ libraries/entities-renderer/src/EntityTreeRenderer.h | 2 ++ libraries/render-utils/src/Model.cpp | 2 +- libraries/render-utils/src/Model.h | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5d50a1c9fe..52677abff6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1635,6 +1635,8 @@ void Application::paintGL() { return; } + DependencyManager::get()->cameraPosition = getMyAvatar()->getPosition(); + _inPaint = true; Finally clearFlag([this] { _inPaint = false; }); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 4111207e00..ec14e2f269 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -46,6 +46,8 @@ public: virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; } virtual void setTree(OctreePointer newTree); + glm::vec3 cameraPosition {}; + void shutdown(); void update(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e36c9d8d40..1ddc3cda47 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -827,7 +827,7 @@ void Model::setURL(const QUrl& url) { deleteGeometry(); auto resource = DependencyManager::get()->getGeometryResource(url); - resource->setLoadPriority(this, priority); + resource->setLoadPriority(this, _loadingPriority); _renderWatcher.setResource(resource); onInvalidate(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 4b93d19d35..0ddfcd32c3 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -238,7 +238,7 @@ public: // returns 'true' if needs fullUpdate after geometry change bool updateGeometry(); - float setLoadingPriority(float priority) { _loadingPriority = priority; } + void setLoadingPriority(float priority) { _loadingPriority = priority; } public slots: void loadURLFinished(bool success); From d48bc96cf94b2a3b93870ec7d7ee5f2187aa2618 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 14:29:36 -0700 Subject: [PATCH 4/7] Add ability to set number of concurrent downloads --- interface/src/Application.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 52677abff6..9b6ef9f9c2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -739,7 +739,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket); identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); - ResourceCache::setRequestLimit(MAX_CONCURRENT_RESOURCE_DOWNLOADS); + const char** constArgv = const_cast(argv); + QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads"); + bool success; + int concurrentDownloads = concurrentDownloadsStr.toInt(&success); + if (!success) { + concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS; + } + ResourceCache::setRequestLimit(concurrentDownloads); _glWidget = new GLCanvas(); getApplicationCompositor().setRenderingWidget(_glWidget); From d367583426e0728a3d89bb6b8e83e678b197c156 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Aug 2016 16:30:38 -0700 Subject: [PATCH 5/7] Clean up priority loading implementation --- interface/src/Application.cpp | 9 +++++++-- libraries/entities-renderer/src/EntityTreeRenderer.h | 11 ++++++++++- .../src/RenderableModelEntityItem.cpp | 6 +----- .../entities-renderer/src/RenderableModelEntityItem.h | 1 - 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9b6ef9f9c2..30d992ede9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1642,8 +1642,6 @@ void Application::paintGL() { return; } - DependencyManager::get()->cameraPosition = getMyAvatar()->getPosition(); - _inPaint = true; Finally clearFlag([this] { _inPaint = false; }); @@ -3249,6 +3247,13 @@ void Application::init() { getEntities()->setViewFrustum(_viewFrustum); } + getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) { + auto dims = item.getDimensions(); + auto maxSize = glm::max(dims.x, dims.y, dims.z); + auto distance = glm::distance(getMyAvatar()->getPosition(), item.getPosition()); + return atan2(maxSize, distance); + }); + ObjectMotionState::setShapeManager(&_shapeManager); _physicsEngine->init(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index ec14e2f269..2ead511048 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -28,11 +28,14 @@ class AbstractViewStateInterface; class Model; class ScriptEngine; class ZoneEntityItem; +class EntityItem; class Model; using ModelPointer = std::shared_ptr; using ModelWeakPointer = std::weak_ptr; +using CalculateEntityLoadingPriority = std::function; + // Generic client side Octree renderer class. class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency { Q_OBJECT @@ -46,7 +49,9 @@ public: virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; } virtual void setTree(OctreePointer newTree); - glm::vec3 cameraPosition {}; + // Returns the priority at which an entity should be loaded. Higher values indicate higher priority. + float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); } + void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { this->_calculateEntityLoadingPriorityFunc = fn; } void shutdown(); void update(); @@ -204,6 +209,10 @@ private: QList _entityIDsLastInScene; static int _entitiesScriptEngineCount; + + CalculateEntityLoadingPriority _calculateEntityLoadingPriorityFunc = [](const EntityItem& item) -> float { + return 0.0f; + }; }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index bfcd604288..29992e897a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -484,11 +484,7 @@ ModelPointer RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { if (!getModelURL().isEmpty()) { // If we don't have a model, allocate one *immediately* if (!_model) { - auto dims = this->getDimensions(); - auto maxSize = glm::max(dims.x, dims.y, dims.z); - auto distance = glm::distance(renderer->cameraPosition, getPosition()); - float priority = atan2(maxSize / 2, distance); - _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL(), priority); + _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL(), renderer->getEntityLoadingPriority(*this)); _needsInitialSimulation = true; // If we need to change URLs, update it *after rendering* (to avoid access violations) } else if ((QUrl(getModelURL()) != _model->getURL() || QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index f487e79880..f63ffcbdb4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -52,7 +52,6 @@ public: bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; - ModelPointer getModel(EntityTreeRenderer* renderer); virtual bool needsToCallUpdate() const override; From 2a071c4329df4cea2ef5a575df1395419caa612f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 10:31:00 -0700 Subject: [PATCH 6/7] Fix improperly formatted floats --- libraries/entities-renderer/src/EntityTreeRenderer.h | 2 +- libraries/render-utils/src/Model.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 2ead511048..99c62ab5f6 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -73,7 +73,7 @@ public: void reloadEntityScripts(); /// if a renderable entity item needs a model, we will allocate it for them - Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority = 0); + Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority = 0.0f); /// if a renderable entity item needs to update the URL of a model, we will handle that for the entity Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 0ddfcd32c3..aecbcf2510 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -409,7 +409,7 @@ protected: bool _collisionGeometryRequestFailed { false }; private: - float _loadingPriority { 0 }; + float _loadingPriority { 0.0f }; }; From fb14628a7ebff15c9bbf70d839aa83730f1d624e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 10:33:15 -0700 Subject: [PATCH 7/7] Handle case in entity loading priority function where max dim size is <= 0 --- interface/src/Application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 30d992ede9..7695bd1b99 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3250,6 +3250,11 @@ void Application::init() { getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) { auto dims = item.getDimensions(); auto maxSize = glm::max(dims.x, dims.y, dims.z); + + if (maxSize <= 0.0f) { + return 0.0f; + } + auto distance = glm::distance(getMyAvatar()->getPosition(), item.getPosition()); return atan2(maxSize, distance); });