mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 15:23:56 +02:00
cap size of textures from FBX files
This commit is contained in:
parent
24b1f3ddbc
commit
b3ae6f9aec
5 changed files with 54 additions and 27 deletions
|
@ -100,22 +100,25 @@ public:
|
|||
/// A single binding to a joint in an FBX document.
|
||||
class FBXCluster {
|
||||
public:
|
||||
|
||||
|
||||
int jointIndex;
|
||||
glm::mat4 inverseBindMatrix;
|
||||
};
|
||||
|
||||
const int MAX_FBX_TEXTURE_SIZE = 1024 * 1024;
|
||||
|
||||
/// A texture map in an FBX document.
|
||||
class FBXTexture {
|
||||
public:
|
||||
QString name;
|
||||
QByteArray filename;
|
||||
QByteArray content;
|
||||
|
||||
|
||||
Transform transform;
|
||||
int maxSize { MAX_FBX_TEXTURE_SIZE };
|
||||
int texcoordSet;
|
||||
QString texcoordSetName;
|
||||
|
||||
|
||||
bool isBumpmap{ false };
|
||||
|
||||
bool isNull() const { return name.isEmpty() && filename.isEmpty() && content.isEmpty(); }
|
||||
|
|
|
@ -472,7 +472,7 @@ QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& textu
|
|||
model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture,
|
||||
TextureType type, MapChannel channel) {
|
||||
const auto url = getTextureUrl(baseUrl, fbxTexture);
|
||||
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, fbxTexture.content);
|
||||
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, fbxTexture.content, fbxTexture.maxSize);
|
||||
_textures[channel] = Texture { fbxTexture.name, texture };
|
||||
|
||||
auto map = std::make_shared<model::TextureMap>();
|
||||
|
|
|
@ -167,16 +167,17 @@ class TextureExtra {
|
|||
public:
|
||||
NetworkTexture::Type type;
|
||||
const QByteArray& content;
|
||||
int maxSize;
|
||||
};
|
||||
|
||||
ScriptableResource* TextureCache::prefetch(const QUrl& url, int type) {
|
||||
ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxSize) {
|
||||
auto byteArray = QByteArray();
|
||||
TextureExtra extra = { (Type)type, byteArray };
|
||||
TextureExtra extra = { (Type)type, byteArray, maxSize };
|
||||
return ResourceCache::prefetch(url, &extra);
|
||||
}
|
||||
|
||||
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const QByteArray& content) {
|
||||
TextureExtra extra = { type, content };
|
||||
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const QByteArray& content, int maxSize) {
|
||||
TextureExtra extra = { type, content, maxSize };
|
||||
return ResourceCache::getResource(url, QUrl(), &extra).staticCast<NetworkTexture>();
|
||||
}
|
||||
|
||||
|
@ -251,13 +252,15 @@ QSharedPointer<Resource> TextureCache::createResource(const QUrl& url, const QSh
|
|||
const TextureExtra* textureExtra = static_cast<const TextureExtra*>(extra);
|
||||
auto type = textureExtra ? textureExtra->type : Type::DEFAULT_TEXTURE;
|
||||
auto content = textureExtra ? textureExtra->content : QByteArray();
|
||||
return QSharedPointer<Resource>(new NetworkTexture(url, type, content),
|
||||
auto maxSize = textureExtra ? textureExtra->maxSize : ABSOLUTE_MAX_TEXTURE_SIZE;
|
||||
return QSharedPointer<Resource>(new NetworkTexture(url, type, content, maxSize),
|
||||
&Resource::deleter);
|
||||
}
|
||||
|
||||
NetworkTexture::NetworkTexture(const QUrl& url, Type type, const QByteArray& content) :
|
||||
NetworkTexture::NetworkTexture(const QUrl& url, Type type, const QByteArray& content, int maxSize) :
|
||||
Resource(url),
|
||||
_type(type)
|
||||
_type(type),
|
||||
_maxSize(maxSize)
|
||||
{
|
||||
_textureSource = std::make_shared<gpu::TextureSource>();
|
||||
|
||||
|
@ -274,7 +277,7 @@ NetworkTexture::NetworkTexture(const QUrl& url, Type type, const QByteArray& con
|
|||
}
|
||||
|
||||
NetworkTexture::NetworkTexture(const QUrl& url, const TextureLoaderFunc& textureLoader, const QByteArray& content) :
|
||||
NetworkTexture(url, CUSTOM_TEXTURE, content)
|
||||
NetworkTexture(url, CUSTOM_TEXTURE, content, ABSOLUTE_MAX_TEXTURE_SIZE)
|
||||
{
|
||||
_textureLoader = textureLoader;
|
||||
}
|
||||
|
@ -290,7 +293,8 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
|
|||
class ImageReader : public QRunnable {
|
||||
public:
|
||||
|
||||
ImageReader(const QWeakPointer<Resource>& resource, const QByteArray& data, const QUrl& url = QUrl());
|
||||
ImageReader(const QWeakPointer<Resource>& resource, const QByteArray& data,
|
||||
const QUrl& url = QUrl(), int maxSize = ABSOLUTE_MAX_TEXTURE_SIZE);
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
|
@ -300,6 +304,7 @@ private:
|
|||
QWeakPointer<Resource> _resource;
|
||||
QUrl _url;
|
||||
QByteArray _content;
|
||||
int _maxSize;
|
||||
};
|
||||
|
||||
void NetworkTexture::downloadFinished(const QByteArray& data) {
|
||||
|
@ -308,14 +313,15 @@ void NetworkTexture::downloadFinished(const QByteArray& data) {
|
|||
}
|
||||
|
||||
void NetworkTexture::loadContent(const QByteArray& content) {
|
||||
QThreadPool::globalInstance()->start(new ImageReader(_self, content, _url));
|
||||
QThreadPool::globalInstance()->start(new ImageReader(_self, content, _url, _maxSize));
|
||||
}
|
||||
|
||||
ImageReader::ImageReader(const QWeakPointer<Resource>& resource, const QByteArray& data,
|
||||
const QUrl& url) :
|
||||
const QUrl& url, int maxSize) :
|
||||
_resource(resource),
|
||||
_url(url),
|
||||
_content(data)
|
||||
_content(data),
|
||||
_maxSize(maxSize)
|
||||
{
|
||||
#if DEBUG_DUMP_TEXTURE_LOADS
|
||||
static auto start = usecTimestampNow() / USECS_PER_MSEC;
|
||||
|
@ -375,10 +381,10 @@ void ImageReader::run() {
|
|||
|
||||
// Note that QImage.format is the pixel format which is different from the "format" of the image file...
|
||||
auto imageFormat = image.format();
|
||||
int originalWidth = image.width();
|
||||
int originalHeight = image.height();
|
||||
int imageWidth = image.width();
|
||||
int imageHeight = image.height();
|
||||
|
||||
if (originalWidth == 0 || originalHeight == 0 || imageFormat == QImage::Format_Invalid) {
|
||||
if (imageWidth == 0 || imageHeight == 0 || imageFormat == QImage::Format_Invalid) {
|
||||
if (filenameExtension.empty()) {
|
||||
qCDebug(modelnetworking) << "QImage failed to create from content, no file extension:" << _url;
|
||||
} else {
|
||||
|
@ -386,6 +392,21 @@ void ImageReader::run() {
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (imageWidth * imageHeight > _maxSize) {
|
||||
float scaleFactor = sqrtf(_maxSize / (float)(imageWidth * imageHeight));
|
||||
int originalWidth = imageWidth;
|
||||
int originalHeight = imageHeight;
|
||||
imageWidth = (int)(scaleFactor * (float)imageWidth + 0.5f);
|
||||
imageHeight = (int)(scaleFactor * (float)imageHeight + 0.5f);
|
||||
//QSize newSize(imageWidth, imageHeight);
|
||||
QImage newImage = image.scaled(QSize(imageWidth, imageHeight), Qt::IgnoreAspectRatio);
|
||||
image.swap(newImage);
|
||||
qCDebug(modelnetworking) << "Downscale image" << _url
|
||||
<< "from" << originalWidth << "x" << originalHeight
|
||||
<< "to" << imageWidth << "x" << imageHeight;
|
||||
}
|
||||
|
||||
gpu::TexturePointer texture = nullptr;
|
||||
{
|
||||
// Double-check the resource still exists between long operations.
|
||||
|
@ -408,7 +429,7 @@ void ImageReader::run() {
|
|||
} else {
|
||||
QMetaObject::invokeMethod(resource.data(), "setImage",
|
||||
Q_ARG(gpu::TexturePointer, texture),
|
||||
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
|
||||
Q_ARG(int, imageWidth), Q_ARG(int, imageHeight));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <ResourceCache.h>
|
||||
#include <model/TextureMap.h>
|
||||
|
||||
const int ABSOLUTE_MAX_TEXTURE_SIZE = 8192 * 8192;
|
||||
|
||||
namespace gpu {
|
||||
class Batch;
|
||||
}
|
||||
|
@ -60,7 +62,7 @@ public:
|
|||
typedef gpu::Texture* TextureLoader(const QImage& image, const std::string& srcImageName);
|
||||
using TextureLoaderFunc = std::function<TextureLoader>;
|
||||
|
||||
NetworkTexture(const QUrl& url, Type type, const QByteArray& content);
|
||||
NetworkTexture(const QUrl& url, Type type, const QByteArray& content, int maxSize);
|
||||
NetworkTexture(const QUrl& url, const TextureLoaderFunc& textureLoader, const QByteArray& content);
|
||||
|
||||
QString getType() const override { return "NetworkTexture"; }
|
||||
|
@ -70,7 +72,7 @@ public:
|
|||
int getWidth() const { return _width; }
|
||||
int getHeight() const { return _height; }
|
||||
Type getTextureType() const { return _type; }
|
||||
|
||||
|
||||
TextureLoaderFunc getTextureLoader() const;
|
||||
|
||||
signals:
|
||||
|
@ -81,7 +83,7 @@ protected:
|
|||
virtual bool isCacheable() const override { return _loaded; }
|
||||
|
||||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
|
||||
Q_INVOKABLE void loadContent(const QByteArray& content);
|
||||
Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight);
|
||||
|
||||
|
@ -92,6 +94,7 @@ private:
|
|||
int _originalHeight { 0 };
|
||||
int _width { 0 };
|
||||
int _height { 0 };
|
||||
int _maxSize { ABSOLUTE_MAX_TEXTURE_SIZE };
|
||||
};
|
||||
|
||||
using NetworkTexturePointer = QSharedPointer<NetworkTexture>;
|
||||
|
@ -129,11 +132,11 @@ public:
|
|||
|
||||
/// Loads a texture from the specified URL.
|
||||
NetworkTexturePointer getTexture(const QUrl& url, Type type = Type::DEFAULT_TEXTURE,
|
||||
const QByteArray& content = QByteArray());
|
||||
const QByteArray& content = QByteArray(), int maxSize = ABSOLUTE_MAX_TEXTURE_SIZE);
|
||||
|
||||
protected:
|
||||
// Overload ResourceCache::prefetch to allow specifying texture type for loads
|
||||
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type);
|
||||
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxSize = ABSOLUTE_MAX_TEXTURE_SIZE);
|
||||
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||
const void* extra) override;
|
||||
|
|
|
@ -86,7 +86,7 @@ private:
|
|||
/// Wrapper to expose resources to JS/QML
|
||||
class ScriptableResource : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUrl url READ getUrl)
|
||||
Q_PROPERTY(QUrl url READ getURL)
|
||||
Q_PROPERTY(int state READ getState NOTIFY stateChanged)
|
||||
|
||||
/**jsdoc
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void release();
|
||||
|
||||
const QUrl& getUrl() const { return _url; }
|
||||
const QUrl& getURL() const { return _url; }
|
||||
int getState() const { return (int)_state; }
|
||||
const QSharedPointer<Resource>& getResource() const { return _resource; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue