From fac497dadc139f3c1e649178c1ccf2fc2c0e4e14 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Tue, 14 Jul 2015 15:31:56 +0200 Subject: [PATCH 1/4] Removed the file where the directory is stripped off the RelativeFilename, and replace \ with /. However this introduces a new problem with the current fbx files who do not have their textures in the original dir but moved it to the dir where the fbx file lives. Suppose there should be some logic when the texture is not found to look if the texture lives in the dir above the RelativeFilename. In any case it is not obvious when there is a texture missing on a model, it simply renders black. --- libraries/fbx/src/FBXReader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 236e2979f5..24cbc983ed 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1781,9 +1781,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, TextureParam tex; foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { - // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); - filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + filename = filename.replace('\\', '/'); textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName") { // trim the name from the timestamp From 8f0893ba2153b5a10f22aa0cff4cd573de3063cf Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Wed, 22 Jul 2015 22:34:45 +0200 Subject: [PATCH 2/4] Added fileOnUrl to check if a texture exist at the location. It return the correct filename of where the texture lives. Added the url of the fix file to extractFBXGeometry and readFBX and updated the calls to readFBX to include the url of the fix file. So it now does not break existing content. Found a second place in the FBXReader.cpp where the RelativeFileName stripped out the dir location. --- interface/src/ModelPackager.cpp | 2 +- libraries/animation/src/AnimationCache.cpp | 2 +- libraries/fbx/src/FBXReader.cpp | 31 +++++++++++++++----- libraries/fbx/src/FBXReader.h | 4 +-- libraries/render-utils/src/GeometryCache.cpp | 2 +- tools/vhacd-util/src/VHACDUtil.cpp | 2 +- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 2864738f9c..09d572c31d 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -106,7 +106,7 @@ bool ModelPackager::loadModel() { } qCDebug(interfaceapp) << "Reading FBX file : " << _fbxInfo.filePath(); QByteArray fbxContents = fbx.readAll(); - _geometry = readFBX(fbxContents, QVariantHash()); + _geometry = readFBX(fbxContents, QVariantHash(), _fbxInfo.filePath()); // make sure we have some basic mappings populateBasicMapping(_mapping, _fbxInfo.filePath(), _geometry); diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 6c02ccbd2b..0aa5c34544 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -65,7 +65,7 @@ void AnimationReader::run() { QSharedPointer animation = _animation.toStrongRef(); if (!animation.isNull()) { QMetaObject::invokeMethod(animation.data(), "setGeometry", - Q_ARG(const FBXGeometry&, readFBX(_reply->readAll(), QVariantHash()))); + Q_ARG(const FBXGeometry&, readFBX(_reply->readAll(), QVariantHash(), _reply->property("url").toString()))); } _reply->deleteLater(); } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 24cbc983ed..554d56ee5a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1454,9 +1455,23 @@ void buildModelMesh(ExtractedMesh& extracted) { } #endif // USE_MODEL_MESH +QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { + QString path = QFileInfo(url).path(); + QByteArray filename = filenameString; + QFileInfo checkFile(path + "/" + filename.replace('\\', '/')); + //check if the file exists at the RelativeFileName + if (checkFile.exists() && checkFile.isFile()) { + filename = filename.replace('\\', '/'); + } else { + // there is not texture at the filename. Assume it is in the root dir. + filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + } + filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + filename = filename.replace('\\', '/'); + return filename; +} - -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString url, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1782,7 +1797,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { QByteArray filename = subobject.properties.at(0).toByteArray(); - filename = filename.replace('\\', '/'); + filename = fileOnUrl(filename, url); textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName") { // trim the name from the timestamp @@ -1856,7 +1871,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { filename = subobject.properties.at(0).toByteArray(); - filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + filename = fileOnUrl(filename, url); } else if (subobject.name == "Content" && !subobject.properties.isEmpty()) { content = subobject.properties.at(0).toByteArray(); @@ -2709,12 +2724,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, return geometry; } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return readFBX(&buffer, mapping, loadLightmaps, lightmapLevel); + return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); } -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { - return extractFBXGeometry(parseFBX(device), mapping, loadLightmaps, lightmapLevel); +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { + return extractFBXGeometry(parseFBX(device), mapping, url, loadLightmaps, lightmapLevel); } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 200cd4a121..cf86c304ac 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -268,10 +268,10 @@ Q_DECLARE_METATYPE(FBXGeometry) /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); #endif // hifi_FBXReader_h diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 02e59bfa3a..3d32ba74ad 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2185,7 +2185,7 @@ void GeometryReader::run() { } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { lightmapLevel = 3.5f; } - fbxgeo = readFBX(_reply, _mapping, grabLightmaps, lightmapLevel); + fbxgeo = readFBX(_reply, _mapping, _url.path(), grabLightmaps, lightmapLevel); } else if (_url.path().toLower().endsWith(".obj")) { fbxgeo = OBJReader().readOBJ(_reply, _mapping, &_url); } diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index f1ff0e9e4f..d775244b9c 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -38,7 +38,7 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { if (filename.toLower().endsWith(".obj")) { result = OBJReader().readOBJ(fbxContents, QVariantHash()); } else if (filename.toLower().endsWith(".fbx")) { - result = readFBX(fbxContents, QVariantHash()); + result = readFBX(fbxContents, QVariantHash(), filename); } else { qDebug() << "unknown file extension"; return false; From d25e09af74544db662a2e92637439386b00cb284 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Sun, 26 Jul 2015 00:48:31 +0200 Subject: [PATCH 3/4] removed the last 2 filename lines, they should not be there. --- libraries/fbx/src/FBXReader.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 554d56ee5a..69482a8c81 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1463,11 +1463,9 @@ QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { if (checkFile.exists() && checkFile.isFile()) { filename = filename.replace('\\', '/'); } else { - // there is not texture at the filename. Assume it is in the root dir. + // there is no texture at the fbx dir with the filename added. Assume it is in the fbx dir. filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); } - filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); - filename = filename.replace('\\', '/'); return filename; } From fa6d6a51230de1c91b8d2bf0ff29ddc5fe757603 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Thu, 30 Jul 2015 15:08:02 +0200 Subject: [PATCH 4/4] Added the & references to the const variables --- libraries/fbx/src/FBXReader.cpp | 8 ++++---- libraries/fbx/src/FBXReader.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 69482a8c81..8b83acdca4 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1455,7 +1455,7 @@ void buildModelMesh(ExtractedMesh& extracted) { } #endif // USE_MODEL_MESH -QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { +QByteArray fileOnUrl(const QByteArray& filenameString, const QString& url) { QString path = QFileInfo(url).path(); QByteArray filename = filenameString; QFileInfo checkFile(path + "/" + filename.replace('\\', '/')); @@ -1469,7 +1469,7 @@ QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { return filename; } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -2722,12 +2722,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, return geometry; } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); } -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { return extractFBXGeometry(parseFBX(device), mapping, url, loadLightmaps, lightmapLevel); } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index cf86c304ac..776b78b3bb 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -268,10 +268,10 @@ Q_DECLARE_METATYPE(FBXGeometry) /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); #endif // hifi_FBXReader_h