mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-26 01:35:14 +02:00
Merge pull request #11258 from huffman/feat/auto-bake-2
Fix loading standalone baked textures from Asset Server
This commit is contained in:
commit
e735c12e70
9 changed files with 63 additions and 18 deletions
|
@ -49,7 +49,7 @@ static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
||||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||||
|
|
||||||
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
||||||
static const QList<QByteArray> BAKEABLE_TEXTURE_EXTENSIONS = QImageReader::supportedImageFormats();
|
static QStringList BAKEABLE_TEXTURE_EXTENSIONS;
|
||||||
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
|
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
|
||||||
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
||||||
|
|
||||||
|
@ -71,7 +71,8 @@ void BakeAssetTask::run() {
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
baker = std::unique_ptr<TextureBaker> {
|
baker = std::unique_ptr<TextureBaker> {
|
||||||
new TextureBaker(QUrl("file:///" + _filePath), image::TextureUsage::CUBE_TEXTURE, PathUtils::generateTemporaryDir())
|
new TextureBaker(QUrl("file:///" + _filePath), image::TextureUsage::CUBE_TEXTURE,
|
||||||
|
PathUtils::generateTemporaryDir())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,6 +248,8 @@ AssetServer::AssetServer(ReceivedMessage& message) :
|
||||||
_transferTaskPool(this),
|
_transferTaskPool(this),
|
||||||
_bakingTaskPool(this)
|
_bakingTaskPool(this)
|
||||||
{
|
{
|
||||||
|
BAKEABLE_TEXTURE_EXTENSIONS = TextureBaker::getSupportedFormats();
|
||||||
|
qDebug() << "Supported baking texture formats:" << BAKEABLE_MODEL_EXTENSIONS;
|
||||||
|
|
||||||
// Most of the work will be I/O bound, reading from disk and constructing packet objects,
|
// Most of the work will be I/O bound, reading from disk and constructing packet objects,
|
||||||
// so the ideal is greater than the number of cores on the system.
|
// so the ideal is greater than the number of cores on the system.
|
||||||
|
|
|
@ -43,6 +43,14 @@ void TextureBaker::bake() {
|
||||||
loadTexture();
|
loadTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QStringList TextureBaker::getSupportedFormats() {
|
||||||
|
auto formats = QImageReader::supportedImageFormats();
|
||||||
|
QStringList stringFormats;
|
||||||
|
std::transform(formats.begin(), formats.end(), std::back_inserter(stringFormats),
|
||||||
|
[](auto& format) -> QString { return format; });
|
||||||
|
return stringFormats;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureBaker::loadTexture() {
|
void TextureBaker::loadTexture() {
|
||||||
// check if the texture is local or first needs to be downloaded
|
// check if the texture is local or first needs to be downloaded
|
||||||
if (_textureURL.isLocalFile()) {
|
if (_textureURL.isLocalFile()) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtCore/QRunnable>
|
#include <QtCore/QRunnable>
|
||||||
|
#include <QImageReader>
|
||||||
|
|
||||||
#include <image/Image.h>
|
#include <image/Image.h>
|
||||||
|
|
||||||
|
@ -28,6 +29,8 @@ class TextureBaker : public Baker {
|
||||||
public:
|
public:
|
||||||
TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, const QDir& outputDirectory);
|
TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, const QDir& outputDirectory);
|
||||||
|
|
||||||
|
static const QStringList getSupportedFormats();
|
||||||
|
|
||||||
const QByteArray& getOriginalTexture() const { return _originalTexture; }
|
const QByteArray& getOriginalTexture() const { return _originalTexture; }
|
||||||
|
|
||||||
QUrl getTextureURL() const { return _textureURL; }
|
QUrl getTextureURL() const { return _textureURL; }
|
||||||
|
|
|
@ -299,6 +299,8 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type,
|
||||||
_textureSource = std::make_shared<gpu::TextureSource>();
|
_textureSource = std::make_shared<gpu::TextureSource>();
|
||||||
_lowestRequestedMipLevel = 0;
|
_lowestRequestedMipLevel = 0;
|
||||||
|
|
||||||
|
_shouldFailOnRedirect = !_sourceIsKTX;
|
||||||
|
|
||||||
if (type == image::TextureUsage::CUBE_TEXTURE) {
|
if (type == image::TextureUsage::CUBE_TEXTURE) {
|
||||||
setLoadPriority(this, SKYBOX_LOAD_PRIORITY);
|
setLoadPriority(this, SKYBOX_LOAD_PRIORITY);
|
||||||
} else if (_sourceIsKTX) {
|
} else if (_sourceIsKTX) {
|
||||||
|
@ -428,6 +430,21 @@ void NetworkTexture::makeRequest() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) {
|
||||||
|
if (!_sourceIsKTX && result == ResourceRequest::Result::RedirectFail) {
|
||||||
|
auto newPath = _request->getRelativePathUrl();
|
||||||
|
if (newPath.fileName().endsWith(".ktx")) {
|
||||||
|
qDebug() << "Redirecting to" << newPath << "from" << _url;
|
||||||
|
_sourceIsKTX = true;
|
||||||
|
_activeUrl = newPath;
|
||||||
|
_shouldFailOnRedirect = false;
|
||||||
|
makeRequest();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Resource::handleFailedRequest(result);
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkTexture::startRequestForNextMipLevel() {
|
void NetworkTexture::startRequestForNextMipLevel() {
|
||||||
auto self = _self.lock();
|
auto self = _self.lock();
|
||||||
if (!self) {
|
if (!self) {
|
||||||
|
@ -527,7 +544,7 @@ void NetworkTexture::ktxInitialDataRequestFinished() {
|
||||||
_ktxHighMipData = _ktxMipRequest->getData();
|
_ktxHighMipData = _ktxMipRequest->getData();
|
||||||
handleFinishedInitialLoad();
|
handleFinishedInitialLoad();
|
||||||
} else {
|
} else {
|
||||||
if (handleFailedRequest(result)) {
|
if (Resource::handleFailedRequest(result)) {
|
||||||
_ktxResourceState = PENDING_INITIAL_LOAD;
|
_ktxResourceState = PENDING_INITIAL_LOAD;
|
||||||
} else {
|
} else {
|
||||||
_ktxResourceState = FAILED_TO_LOAD;
|
_ktxResourceState = FAILED_TO_LOAD;
|
||||||
|
@ -616,7 +633,7 @@ void NetworkTexture::ktxMipRequestFinished() {
|
||||||
finishedLoading(false);
|
finishedLoading(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (handleFailedRequest(result)) {
|
if (Resource::handleFailedRequest(result)) {
|
||||||
_ktxResourceState = PENDING_MIP_REQUEST;
|
_ktxResourceState = PENDING_MIP_REQUEST;
|
||||||
} else {
|
} else {
|
||||||
_ktxResourceState = FAILED_TO_LOAD;
|
_ktxResourceState = FAILED_TO_LOAD;
|
||||||
|
|
|
@ -75,6 +75,8 @@ protected:
|
||||||
|
|
||||||
virtual void downloadFinished(const QByteArray& data) override;
|
virtual void downloadFinished(const QByteArray& data) override;
|
||||||
|
|
||||||
|
bool handleFailedRequest(ResourceRequest::Result result) override;
|
||||||
|
|
||||||
Q_INVOKABLE void loadContent(const QByteArray& content);
|
Q_INVOKABLE void loadContent(const QByteArray& content);
|
||||||
Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight);
|
Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight);
|
||||||
|
|
||||||
|
|
|
@ -82,19 +82,23 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
|
||||||
Q_ASSERT(_state == InProgress);
|
Q_ASSERT(_state == InProgress);
|
||||||
Q_ASSERT(request == _assetMappingRequest);
|
Q_ASSERT(request == _assetMappingRequest);
|
||||||
|
|
||||||
|
bool failed = false;
|
||||||
|
|
||||||
switch (request->getError()) {
|
switch (request->getError()) {
|
||||||
case MappingRequest::NoError:
|
case MappingRequest::NoError:
|
||||||
// we have no error, we should have a resulting hash - use that to send of a request for that asset
|
// we have no error, we should have a resulting hash - use that to send of a request for that asset
|
||||||
qCDebug(networking) << "Got mapping for:" << path << "=>" << request->getHash();
|
qCDebug(networking) << "Got mapping for:" << path << "=>" << request->getHash();
|
||||||
|
|
||||||
requestHash(request->getHash());
|
|
||||||
|
|
||||||
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_SUCCESS);
|
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_SUCCESS);
|
||||||
|
|
||||||
// if we got a redirected path we need to store that with the resource request as relative path URL
|
// if we got a redirected path we need to store that with the resource request as relative path URL
|
||||||
if (request->wasRedirected()) {
|
if (request->wasRedirected() && _failOnRedirect) {
|
||||||
qDebug() << "Request was redirected";
|
|
||||||
_relativePathURL = ATP_SCHEME + request->getRedirectedPath();
|
_relativePathURL = ATP_SCHEME + request->getRedirectedPath();
|
||||||
|
_result = RedirectFail;
|
||||||
|
|
||||||
|
failed = true;
|
||||||
|
} else {
|
||||||
|
requestHash(request->getHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -113,17 +117,20 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// since we've failed we know we are finished
|
failed = true;
|
||||||
_state = Finished;
|
|
||||||
emit finished();
|
|
||||||
|
|
||||||
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_FAILED);
|
|
||||||
statTracker->incrementStat(STAT_ATP_REQUEST_FAILED);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
_state = Finished;
|
||||||
|
emit finished();
|
||||||
|
|
||||||
|
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_FAILED);
|
||||||
|
statTracker->incrementStat(STAT_ATP_REQUEST_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
_assetMappingRequest->deleteLater();
|
_assetMappingRequest->deleteLater();
|
||||||
_assetMappingRequest = nullptr;
|
_assetMappingRequest = nullptr;
|
||||||
});
|
});
|
||||||
|
|
|
@ -689,6 +689,7 @@ void Resource::makeRequest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_request->setByteRange(_requestByteRange);
|
_request->setByteRange(_requestByteRange);
|
||||||
|
_request->setFailOnRedirect(_shouldFailOnRedirect);
|
||||||
|
|
||||||
qCDebug(resourceLog).noquote() << "Starting request for:" << _url.toDisplayString();
|
qCDebug(resourceLog).noquote() << "Starting request for:" << _url.toDisplayString();
|
||||||
emit loading();
|
emit loading();
|
||||||
|
|
|
@ -449,12 +449,13 @@ protected:
|
||||||
Q_INVOKABLE void allReferencesCleared();
|
Q_INVOKABLE void allReferencesCleared();
|
||||||
|
|
||||||
/// Return true if the resource will be retried
|
/// Return true if the resource will be retried
|
||||||
bool handleFailedRequest(ResourceRequest::Result result);
|
virtual bool handleFailedRequest(ResourceRequest::Result result);
|
||||||
|
|
||||||
QUrl _url;
|
QUrl _url;
|
||||||
QUrl _effectiveBaseURL{ _url };
|
QUrl _effectiveBaseURL{ _url };
|
||||||
QUrl _activeUrl;
|
QUrl _activeUrl;
|
||||||
ByteRange _requestByteRange;
|
ByteRange _requestByteRange;
|
||||||
|
bool _shouldFailOnRedirect { false };
|
||||||
|
|
||||||
// _loaded == true means we are in a loaded and usable state. It is possible that there may still be
|
// _loaded == true means we are in a loaded and usable state. It is possible that there may still be
|
||||||
// active requests/loading while in this state. Example: Progressive KTX downloads, where higher resolution
|
// active requests/loading while in this state. Example: Progressive KTX downloads, where higher resolution
|
||||||
|
|
|
@ -57,7 +57,8 @@ public:
|
||||||
AccessDenied,
|
AccessDenied,
|
||||||
InvalidByteRange,
|
InvalidByteRange,
|
||||||
InvalidURL,
|
InvalidURL,
|
||||||
NotFound
|
NotFound,
|
||||||
|
RedirectFail
|
||||||
};
|
};
|
||||||
Q_ENUM(Result)
|
Q_ENUM(Result)
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ public:
|
||||||
bool loadedFromCache() const { return _loadedFromCache; }
|
bool loadedFromCache() const { return _loadedFromCache; }
|
||||||
bool getRangeRequestSuccessful() const { return _rangeRequestSuccessful; }
|
bool getRangeRequestSuccessful() const { return _rangeRequestSuccessful; }
|
||||||
bool getTotalSizeOfResource() const { return _totalSizeOfResource; }
|
bool getTotalSizeOfResource() const { return _totalSizeOfResource; }
|
||||||
|
void setFailOnRedirect(bool failOnRedirect) { _failOnRedirect = failOnRedirect; }
|
||||||
|
|
||||||
void setCacheEnabled(bool value) { _cacheEnabled = value; }
|
void setCacheEnabled(bool value) { _cacheEnabled = value; }
|
||||||
void setByteRange(ByteRange byteRange) { _byteRange = byteRange; }
|
void setByteRange(ByteRange byteRange) { _byteRange = byteRange; }
|
||||||
|
@ -89,6 +91,7 @@ protected:
|
||||||
State _state { NotStarted };
|
State _state { NotStarted };
|
||||||
Result _result;
|
Result _result;
|
||||||
QByteArray _data;
|
QByteArray _data;
|
||||||
|
bool _failOnRedirect { false };
|
||||||
bool _cacheEnabled { true };
|
bool _cacheEnabled { true };
|
||||||
bool _loadedFromCache { false };
|
bool _loadedFromCache { false };
|
||||||
ByteRange _byteRange;
|
ByteRange _byteRange;
|
||||||
|
|
Loading…
Reference in a new issue