mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 19:56:44 +02:00
Merge pull request #8311 from huffman/feat/angular-loading
Add priority loading for model entities
This commit is contained in:
commit
882ad2f6fb
7 changed files with 44 additions and 6 deletions
|
@ -739,7 +739,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket);
|
connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket);
|
||||||
identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
|
identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
|
||||||
|
|
||||||
ResourceCache::setRequestLimit(MAX_CONCURRENT_RESOURCE_DOWNLOADS);
|
const char** constArgv = const_cast<const char**>(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();
|
_glWidget = new GLCanvas();
|
||||||
getApplicationCompositor().setRenderingWidget(_glWidget);
|
getApplicationCompositor().setRenderingWidget(_glWidget);
|
||||||
|
@ -3240,6 +3247,18 @@ void Application::init() {
|
||||||
getEntities()->setViewFrustum(_viewFrustum);
|
getEntities()->setViewFrustum(_viewFrustum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
ObjectMotionState::setShapeManager(&_shapeManager);
|
ObjectMotionState::setShapeManager(&_shapeManager);
|
||||||
_physicsEngine->init();
|
_physicsEngine->init();
|
||||||
|
|
||||||
|
|
|
@ -529,7 +529,7 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha
|
||||||
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(message, sourceNode);
|
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(message, sourceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) {
|
ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority) {
|
||||||
ModelPointer model = nullptr;
|
ModelPointer model = nullptr;
|
||||||
|
|
||||||
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
// 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<Model>(std::make_shared<Rig>());
|
model = std::make_shared<Model>(std::make_shared<Rig>());
|
||||||
|
model->setLoadingPriority(loadingPriority);
|
||||||
model->init();
|
model->init();
|
||||||
model->setURL(QUrl(url));
|
model->setURL(QUrl(url));
|
||||||
model->setCollisionModelURL(QUrl(collisionUrl));
|
model->setCollisionModelURL(QUrl(collisionUrl));
|
||||||
|
|
|
@ -28,11 +28,14 @@ class AbstractViewStateInterface;
|
||||||
class Model;
|
class Model;
|
||||||
class ScriptEngine;
|
class ScriptEngine;
|
||||||
class ZoneEntityItem;
|
class ZoneEntityItem;
|
||||||
|
class EntityItem;
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
using ModelPointer = std::shared_ptr<Model>;
|
using ModelPointer = std::shared_ptr<Model>;
|
||||||
using ModelWeakPointer = std::weak_ptr<Model>;
|
using ModelWeakPointer = std::weak_ptr<Model>;
|
||||||
|
|
||||||
|
using CalculateEntityLoadingPriority = std::function<float(const EntityItem& item)>;
|
||||||
|
|
||||||
// Generic client side Octree renderer class.
|
// Generic client side Octree renderer class.
|
||||||
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency {
|
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -46,6 +49,10 @@ public:
|
||||||
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
|
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
|
||||||
virtual void setTree(OctreePointer newTree);
|
virtual void setTree(OctreePointer newTree);
|
||||||
|
|
||||||
|
// 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 shutdown();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
@ -66,7 +73,7 @@ public:
|
||||||
void reloadEntityScripts();
|
void reloadEntityScripts();
|
||||||
|
|
||||||
/// if a renderable entity item needs a model, we will allocate it for them
|
/// 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 loadingPriority = 0.0f);
|
||||||
|
|
||||||
/// if a renderable entity item needs to update the URL of a model, we will handle that for the entity
|
/// 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);
|
Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl);
|
||||||
|
@ -202,6 +209,10 @@ private:
|
||||||
QList<EntityItemID> _entityIDsLastInScene;
|
QList<EntityItemID> _entityIDsLastInScene;
|
||||||
|
|
||||||
static int _entitiesScriptEngineCount;
|
static int _entitiesScriptEngineCount;
|
||||||
|
|
||||||
|
CalculateEntityLoadingPriority _calculateEntityLoadingPriorityFunc = [](const EntityItem& item) -> float {
|
||||||
|
return 0.0f;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -484,7 +484,7 @@ ModelPointer RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
if (!getModelURL().isEmpty()) {
|
if (!getModelURL().isEmpty()) {
|
||||||
// If we don't have a model, allocate one *immediately*
|
// If we don't have a model, allocate one *immediately*
|
||||||
if (!_model) {
|
if (!_model) {
|
||||||
_model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL());
|
_model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL(), renderer->getEntityLoadingPriority(*this));
|
||||||
_needsInitialSimulation = true;
|
_needsInitialSimulation = true;
|
||||||
// If we need to change URLs, update it *after rendering* (to avoid access violations)
|
// If we need to change URLs, update it *after rendering* (to avoid access violations)
|
||||||
} else if ((QUrl(getModelURL()) != _model->getURL() || QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) {
|
} else if ((QUrl(getModelURL()) != _model->getURL() || QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) {
|
||||||
|
|
|
@ -52,7 +52,6 @@ public:
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
BoxFace& face, glm::vec3& surfaceNormal,
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const override;
|
void** intersectedObject, bool precisionPicking) const override;
|
||||||
|
|
||||||
ModelPointer getModel(EntityTreeRenderer* renderer);
|
ModelPointer getModel(EntityTreeRenderer* renderer);
|
||||||
|
|
||||||
virtual bool needsToCallUpdate() const override;
|
virtual bool needsToCallUpdate() const override;
|
||||||
|
|
|
@ -826,7 +826,9 @@ void Model::setURL(const QUrl& url) {
|
||||||
invalidCalculatedMeshBoxes();
|
invalidCalculatedMeshBoxes();
|
||||||
deleteGeometry();
|
deleteGeometry();
|
||||||
|
|
||||||
_renderWatcher.setResource(DependencyManager::get<ModelCache>()->getGeometryResource(url));
|
auto resource = DependencyManager::get<ModelCache>()->getGeometryResource(url);
|
||||||
|
resource->setLoadPriority(this, _loadingPriority);
|
||||||
|
_renderWatcher.setResource(resource);
|
||||||
onInvalidate();
|
onInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,8 @@ public:
|
||||||
// returns 'true' if needs fullUpdate after geometry change
|
// returns 'true' if needs fullUpdate after geometry change
|
||||||
bool updateGeometry();
|
bool updateGeometry();
|
||||||
|
|
||||||
|
void setLoadingPriority(float priority) { _loadingPriority = priority; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void loadURLFinished(bool success);
|
void loadURLFinished(bool success);
|
||||||
void loadCollisionModelURLFinished(bool success);
|
void loadCollisionModelURLFinished(bool success);
|
||||||
|
@ -405,6 +407,10 @@ protected:
|
||||||
|
|
||||||
bool _visualGeometryRequestFailed { false };
|
bool _visualGeometryRequestFailed { false };
|
||||||
bool _collisionGeometryRequestFailed { false };
|
bool _collisionGeometryRequestFailed { false };
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _loadingPriority { 0.0f };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ModelPointer)
|
Q_DECLARE_METATYPE(ModelPointer)
|
||||||
|
|
Loading…
Reference in a new issue