mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-15 18:08:26 +02:00
Merge pull request #2179 from ey6es/master
Better frame rates on loading by reading cached data from disk in worker thread, render billboards if we haven't loaded the models yet, use voxel LOD parameter to control avatar LODs, too.
This commit is contained in:
commit
7ce427b35c
9 changed files with 35 additions and 28 deletions
|
@ -1612,6 +1612,13 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Application::updateLOD() {
|
||||
// adjust it unless we were asked to disable this feature
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
|
||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateMouseRay() {
|
||||
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
|
@ -1852,6 +1859,8 @@ void Application::update(float deltaTime) {
|
|||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::update()");
|
||||
|
||||
updateLOD();
|
||||
|
||||
// check what's under the mouse and update the mouse voxel
|
||||
updateMouseRay();
|
||||
|
||||
|
@ -2325,14 +2334,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... voxels...");
|
||||
|
||||
_voxels.render();
|
||||
|
||||
// double check that our LOD doesn't need to be auto-adjusted
|
||||
// adjust it unless we were asked to disable this feature
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
|
||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||
}
|
||||
}
|
||||
|
||||
// also, metavoxels
|
||||
|
|
|
@ -284,6 +284,7 @@ private:
|
|||
void update(float deltaTime);
|
||||
|
||||
// Various helper functions called during update()
|
||||
void updateLOD();
|
||||
void updateMouseRay();
|
||||
void updateFaceshift();
|
||||
void updateVisage();
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
void autoAdjustLOD(float currentFPS);
|
||||
void setVoxelSizeScale(float sizeScale);
|
||||
float getVoxelSizeScale() const { return _voxelSizeScale; }
|
||||
float getAvatarLODDistanceMultiplier() const { return DEFAULT_OCTREE_SIZE_SCALE / _voxelSizeScale; }
|
||||
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
|
|
|
@ -112,7 +112,8 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
|
|||
}
|
||||
|
||||
float Avatar::getLODDistance() const {
|
||||
return glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
|
||||
return Menu::getInstance()->getAvatarLODDistanceMultiplier() *
|
||||
glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
|
||||
}
|
||||
|
||||
void Avatar::simulate(float deltaTime) {
|
||||
|
@ -305,13 +306,11 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
}
|
||||
|
||||
void Avatar::renderBody() {
|
||||
if (_shouldRenderBillboard) {
|
||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
// render the billboard until both models are loaded
|
||||
renderBillboard();
|
||||
return;
|
||||
}
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
}
|
||||
_skeletonModel.render(1.0f);
|
||||
getHead()->render(1.0f);
|
||||
getHand()->render(false);
|
||||
|
|
|
@ -450,7 +450,7 @@ class GeometryReader : public QRunnable {
|
|||
public:
|
||||
|
||||
GeometryReader(const QWeakPointer<Resource>& geometry, const QUrl& url,
|
||||
const QByteArray& data, const QVariantHash& mapping);
|
||||
QNetworkReply* reply, const QVariantHash& mapping);
|
||||
|
||||
virtual void run();
|
||||
|
||||
|
@ -458,40 +458,41 @@ private:
|
|||
|
||||
QWeakPointer<Resource> _geometry;
|
||||
QUrl _url;
|
||||
QByteArray _data;
|
||||
QNetworkReply* _reply;
|
||||
QVariantHash _mapping;
|
||||
};
|
||||
|
||||
GeometryReader::GeometryReader(const QWeakPointer<Resource>& geometry, const QUrl& url,
|
||||
const QByteArray& data, const QVariantHash& mapping) :
|
||||
QNetworkReply* reply, const QVariantHash& mapping) :
|
||||
_geometry(geometry),
|
||||
_url(url),
|
||||
_data(data),
|
||||
_reply(reply),
|
||||
_mapping(mapping) {
|
||||
}
|
||||
|
||||
void GeometryReader::run() {
|
||||
QSharedPointer<Resource> geometry = _geometry.toStrongRef();
|
||||
if (geometry.isNull()) {
|
||||
_reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&,
|
||||
_url.path().toLower().endsWith(".svo") ? readSVO(_data) : readFBX(_data, _mapping)));
|
||||
_url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
|
||||
|
||||
} catch (const QString& error) {
|
||||
qDebug() << "Error reading " << _url << ": " << error;
|
||||
QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false));
|
||||
}
|
||||
_reply->deleteLater();
|
||||
}
|
||||
|
||||
void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
||||
QUrl url = reply->url();
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
if (url.path().toLower().endsWith(".fst")) {
|
||||
// it's a mapping file; parse it and get the mesh filename
|
||||
_mapping = readMapping(data);
|
||||
_mapping = readMapping(reply->readAll());
|
||||
reply->deleteLater();
|
||||
QString filename = _mapping.value("filename").toString();
|
||||
if (filename.isNull()) {
|
||||
qDebug() << "Mapping file " << url << " has no filename.";
|
||||
|
@ -525,7 +526,7 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
|||
}
|
||||
|
||||
// send the reader off to the thread pool
|
||||
QThreadPool::globalInstance()->start(new GeometryReader(_self, url, data, _mapping));
|
||||
QThreadPool::globalInstance()->start(new GeometryReader(_self, url, reply, _mapping));
|
||||
}
|
||||
|
||||
void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||
|
|
|
@ -273,27 +273,28 @@ NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) :
|
|||
class ImageReader : public QRunnable {
|
||||
public:
|
||||
|
||||
ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data);
|
||||
ImageReader(const QWeakPointer<Resource>& texture, QNetworkReply* reply);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
QWeakPointer<Resource> _texture;
|
||||
QByteArray _data;
|
||||
QNetworkReply* _reply;
|
||||
};
|
||||
|
||||
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data) :
|
||||
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, QNetworkReply* reply) :
|
||||
_texture(texture),
|
||||
_data(data) {
|
||||
_reply(reply) {
|
||||
}
|
||||
|
||||
void ImageReader::run() {
|
||||
QSharedPointer<Resource> texture = _texture.toStrongRef();
|
||||
if (texture.isNull()) {
|
||||
_reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
QImage image = QImage::fromData(_data);
|
||||
QImage image = QImage::fromData(_reply->readAll());
|
||||
if (image.format() != QImage::Format_ARGB32) {
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
@ -320,11 +321,12 @@ void ImageReader::run() {
|
|||
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));
|
||||
_reply->deleteLater();
|
||||
}
|
||||
|
||||
void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
||||
// send the reader off to the thread pool
|
||||
QThreadPool::globalInstance()->start(new ImageReader(_self, reply->readAll()));
|
||||
QThreadPool::globalInstance()->start(new ImageReader(_self, reply));
|
||||
}
|
||||
|
||||
void NetworkTexture::setImage(const QImage& image, const glm::vec4& averageColor, bool translucent) {
|
||||
|
|
|
@ -61,6 +61,7 @@ NetworkProgram::NetworkProgram(ScriptCache* cache, const QUrl& url) :
|
|||
|
||||
void NetworkProgram::downloadFinished(QNetworkReply* reply) {
|
||||
_program = QScriptProgram(QTextStream(reply).readAll(), reply->url().toString());
|
||||
reply->deleteLater();
|
||||
finishedLoading(true);
|
||||
emit loaded();
|
||||
}
|
||||
|
|
|
@ -161,7 +161,6 @@ void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
|||
return;
|
||||
}
|
||||
_reply->disconnect(this);
|
||||
_reply->deleteLater();
|
||||
QNetworkReply* reply = _reply;
|
||||
_reply = NULL;
|
||||
ResourceCache::requestCompleted();
|
||||
|
|
|
@ -99,6 +99,7 @@ protected slots:
|
|||
|
||||
protected:
|
||||
|
||||
/// Called when the download has finished. The recipient should delete the reply when done with it.
|
||||
virtual void downloadFinished(QNetworkReply* reply) = 0;
|
||||
|
||||
/// Should be called by subclasses when all the loading that will be done has been done.
|
||||
|
|
Loading…
Reference in a new issue