mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
Process geometry/textures in worker threads (via QThreadPool). Closes #2137.
This commit is contained in:
parent
0bb3752121
commit
2f27d8ecd3
10 changed files with 131 additions and 13 deletions
|
@ -28,6 +28,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
|
||||
|
||||
template<class T> QVariant readBinaryArray(QDataStream& in) {
|
||||
quint32 arrayLength;
|
||||
quint32 encoding;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef __interface__FBXReader__
|
||||
#define __interface__FBXReader__
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QUrl>
|
||||
#include <QVarLengthArray>
|
||||
#include <QVariant>
|
||||
|
@ -167,6 +168,8 @@ public:
|
|||
QVector<FBXAttachment> attachments;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FBXGeometry)
|
||||
|
||||
/// Reads an FST mapping from the supplied data.
|
||||
QVariantHash readMapping(const QByteArray& data);
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include "Application.h"
|
||||
#include "GeometryCache.h"
|
||||
|
@ -443,6 +445,46 @@ void NetworkGeometry::clearLoadPriority(const QPointer<QObject>& owner) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reads geometry in a worker thread.
|
||||
class GeometryReader : public QRunnable {
|
||||
public:
|
||||
|
||||
GeometryReader(const QWeakPointer<Resource>& geometry, const QUrl& url,
|
||||
const QByteArray& data, const QVariantHash& mapping);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
QWeakPointer<Resource> _geometry;
|
||||
QUrl _url;
|
||||
QByteArray _data;
|
||||
QVariantHash _mapping;
|
||||
};
|
||||
|
||||
GeometryReader::GeometryReader(const QWeakPointer<Resource>& geometry, const QUrl& url,
|
||||
const QByteArray& data, const QVariantHash& mapping) :
|
||||
_geometry(geometry),
|
||||
_url(url),
|
||||
_data(data),
|
||||
_mapping(mapping) {
|
||||
}
|
||||
|
||||
void GeometryReader::run() {
|
||||
QSharedPointer<Resource> geometry = _geometry.toStrongRef();
|
||||
if (geometry.isNull()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&,
|
||||
_url.path().toLower().endsWith(".svo") ? readSVO(_data) : readFBX(_data, _mapping)));
|
||||
|
||||
} catch (const QString& error) {
|
||||
qDebug() << "Error reading " << _url << ": " << error;
|
||||
QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
||||
QUrl url = reply->url();
|
||||
QByteArray data = reply->readAll();
|
||||
|
@ -467,6 +509,7 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
|||
for (QVariantHash::const_iterator it = lods.begin(); it != lods.end(); it++) {
|
||||
QSharedPointer<NetworkGeometry> geometry(new NetworkGeometry(url.resolved(it.key()),
|
||||
QSharedPointer<NetworkGeometry>(), true, _mapping, _textureBase));
|
||||
geometry->setSelf(geometry.staticCast<Resource>());
|
||||
geometry->setLODParent(_lodParent);
|
||||
_lods.insert(it.value().toFloat(), geometry);
|
||||
}
|
||||
|
@ -481,14 +524,12 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
|||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_geometry = url.path().toLower().endsWith(".svo") ? readSVO(data) : readFBX(data, _mapping);
|
||||
|
||||
} catch (const QString& error) {
|
||||
qDebug() << "Error reading " << url << ": " << error;
|
||||
finishedLoading(false);
|
||||
return;
|
||||
}
|
||||
// send the reader off to the thread pool
|
||||
QThreadPool::globalInstance()->start(new GeometryReader(_self, url, data, _mapping));
|
||||
}
|
||||
|
||||
void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||
_geometry = geometry;
|
||||
|
||||
foreach (const FBXMesh& mesh, _geometry.meshes) {
|
||||
NetworkMesh networkMesh = { QOpenGLBuffer(QOpenGLBuffer::IndexBuffer), QOpenGLBuffer(QOpenGLBuffer::VertexBuffer) };
|
||||
|
|
|
@ -90,6 +90,8 @@ protected:
|
|||
|
||||
virtual void downloadFinished(QNetworkReply* reply);
|
||||
|
||||
Q_INVOKABLE void setGeometry(const FBXGeometry& geometry);
|
||||
|
||||
private:
|
||||
|
||||
friend class GeometryCache;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <QGLWidget>
|
||||
#include <QNetworkReply>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
|
@ -129,6 +131,7 @@ QSharedPointer<NetworkTexture> TextureCache::getTexture(const QUrl& url, bool no
|
|||
QSharedPointer<NetworkTexture> texture = _dilatableNetworkTextures.value(url);
|
||||
if (texture.isNull()) {
|
||||
texture = QSharedPointer<NetworkTexture>(new DilatableNetworkTexture(url));
|
||||
texture->setSelf(texture);
|
||||
_dilatableNetworkTextures.insert(url, texture);
|
||||
}
|
||||
return texture;
|
||||
|
@ -267,8 +270,30 @@ NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) :
|
|||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
||||
QImage image = QImage::fromData(reply->readAll());
|
||||
class ImageReader : public QRunnable {
|
||||
public:
|
||||
|
||||
ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
QWeakPointer<Resource> _texture;
|
||||
QByteArray _data;
|
||||
};
|
||||
|
||||
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data) :
|
||||
_texture(texture),
|
||||
_data(data) {
|
||||
}
|
||||
|
||||
void ImageReader::run() {
|
||||
QSharedPointer<Resource> texture = _texture.toStrongRef();
|
||||
if (texture.isNull()) {
|
||||
return;
|
||||
}
|
||||
QImage image = QImage::fromData(_data);
|
||||
if (image.format() != QImage::Format_ARGB32) {
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
@ -292,8 +317,19 @@ void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
|||
}
|
||||
}
|
||||
int imageArea = image.width() * image.height();
|
||||
_averageColor = accumulated / (imageArea * EIGHT_BIT_MAXIMUM);
|
||||
_translucent = (translucentPixels >= imageArea / 2);
|
||||
QMetaObject::invokeMethod(texture.data(), "setImage", Q_ARG(const QImage&, image),
|
||||
Q_ARG(const glm::vec4&, accumulated / (imageArea * EIGHT_BIT_MAXIMUM)),
|
||||
Q_ARG(bool, translucentPixels >= imageArea / 2));
|
||||
}
|
||||
|
||||
void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
||||
// send the reader off to the thread pool
|
||||
QThreadPool::globalInstance()->start(new ImageReader(_self, reply->readAll()));
|
||||
}
|
||||
|
||||
void NetworkTexture::setImage(const QImage& image, const glm::vec4& averageColor, bool translucent) {
|
||||
_averageColor = averageColor;
|
||||
_translucent = translucent;
|
||||
|
||||
finishedLoading(true);
|
||||
imageLoaded(image);
|
||||
|
|
|
@ -129,6 +129,8 @@ protected:
|
|||
virtual void downloadFinished(QNetworkReply* reply);
|
||||
virtual void imageLoaded(const QImage& image);
|
||||
|
||||
Q_INVOKABLE void setImage(const QImage& image, const glm::vec4& averageColor, bool translucent);
|
||||
|
||||
private:
|
||||
|
||||
glm::vec4 _averageColor;
|
||||
|
|
|
@ -10,7 +10,15 @@
|
|||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
static int vec4MetaTypeId = qRegisterMetaType<glm::vec4>();
|
||||
static int vec3MetaTypeId = qRegisterMetaType<glm::vec3>();
|
||||
static int vec2MetaTypeId = qRegisterMetaType<glm::vec2>();
|
||||
static int quatMetaTypeId = qRegisterMetaType<glm::quat>();
|
||||
static int xColorMetaTypeId = qRegisterMetaType<xColor>();
|
||||
static int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
|
||||
|
||||
void registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue);
|
||||
|
@ -18,6 +26,22 @@ void registerMetaTypes(QScriptEngine* engine) {
|
|||
qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue);
|
||||
}
|
||||
|
||||
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", vec4.x);
|
||||
obj.setProperty("y", vec4.y);
|
||||
obj.setProperty("z", vec4.z);
|
||||
obj.setProperty("w", vec4.w);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4) {
|
||||
vec4.x = object.property("x").toVariant().toFloat();
|
||||
vec4.y = object.property("y").toVariant().toFloat();
|
||||
vec4.z = object.property("z").toVariant().toFloat();
|
||||
vec4.w = object.property("w").toVariant().toFloat();
|
||||
}
|
||||
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", vec3.x);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "SharedUtil.h"
|
||||
|
||||
Q_DECLARE_METATYPE(glm::vec4)
|
||||
Q_DECLARE_METATYPE(glm::vec3)
|
||||
Q_DECLARE_METATYPE(glm::vec2)
|
||||
Q_DECLARE_METATYPE(glm::quat)
|
||||
|
@ -24,6 +25,9 @@ Q_DECLARE_METATYPE(xColor)
|
|||
|
||||
void registerMetaTypes(QScriptEngine* engine);
|
||||
|
||||
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4);
|
||||
void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4);
|
||||
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
||||
void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
|
|||
if (resource.isNull()) {
|
||||
resource = createResource(url, fallback.isValid() ?
|
||||
getResource(fallback, QUrl(), true) : QSharedPointer<Resource>(), delayLoad, extra);
|
||||
resource->setSelf(resource);
|
||||
_resources.insert(url, resource);
|
||||
}
|
||||
return resource;
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
/// Checks whether the resource has loaded.
|
||||
bool isLoaded() const { return _loaded; }
|
||||
|
||||
void setSelf(const QWeakPointer<Resource>& self) { _self = self; }
|
||||
|
||||
protected slots:
|
||||
|
||||
void attemptRequest();
|
||||
|
@ -100,13 +102,14 @@ protected:
|
|||
virtual void downloadFinished(QNetworkReply* reply) = 0;
|
||||
|
||||
/// Should be called by subclasses when all the loading that will be done has been done.
|
||||
void finishedLoading(bool success);
|
||||
Q_INVOKABLE void finishedLoading(bool success);
|
||||
|
||||
QNetworkRequest _request;
|
||||
bool _startedLoading;
|
||||
bool _failedToLoad;
|
||||
bool _loaded;
|
||||
QHash<QPointer<QObject>, float> _loadPriorities;
|
||||
QWeakPointer<Resource> _self;
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
Loading…
Reference in a new issue