Revert "fix relative/absolute path handling for external FBX textures"

This commit is contained in:
Stephen Birarda 2017-04-10 14:31:02 -07:00 committed by GitHub
parent 04ebdf14a2
commit e86db26224
6 changed files with 39 additions and 57 deletions

View file

@ -74,7 +74,7 @@ void AnimationReader::run() {
// Parse the FBX directly from the QNetworkReply // Parse the FBX directly from the QNetworkReply
FBXGeometry::Pointer fbxgeo; FBXGeometry::Pointer fbxgeo;
if (_url.path().toLower().endsWith(".fbx")) { if (_url.path().toLower().endsWith(".fbx")) {
fbxgeo.reset(readFBX(_data, QVariantHash(), _url)); fbxgeo.reset(readFBX(_data, QVariantHash(), _url.path()));
} else { } else {
QString errorStr("usupported format"); QString errorStr("usupported format");
emit onError(299, errorStr); emit onError(299, errorStr);

View file

@ -376,10 +376,10 @@ public:
}; };
bool checkMaterialsHaveTextures(const QHash<QString, FBXMaterial>& materials, bool checkMaterialsHaveTextures(const QHash<QString, FBXMaterial>& materials,
const QHash<QString, QByteArray>& textureFilepaths, const QMultiMap<QString, QString>& _connectionChildMap) { const QHash<QString, QByteArray>& textureFilenames, const QMultiMap<QString, QString>& _connectionChildMap) {
foreach (const QString& materialID, materials.keys()) { foreach (const QString& materialID, materials.keys()) {
foreach (const QString& childID, _connectionChildMap.values(materialID)) { foreach (const QString& childID, _connectionChildMap.values(materialID)) {
if (textureFilepaths.contains(childID)) { if (textureFilenames.contains(childID)) {
return true; return true;
} }
} }
@ -443,48 +443,21 @@ FBXLight extractLight(const FBXNode& object) {
return light; return light;
} }
QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, QUrl url) { QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) {
// first setup a QFileInfo for the passed relative filepath, with backslashes replaced by forward slashes QString path = QFileInfo(url).path();
auto fileInfo = QFileInfo { fbxRelativeFilepath.replace("\\", "/") }; QByteArray filename = filepath;
QFileInfo checkFile(path + "/" + filepath);
#ifndef Q_OS_WIN // check if the file exists at the RelativeFilename
// it turns out that absolute windows paths starting with drive letters look like relative paths to QFileInfo on UNIX if (!(checkFile.exists() && checkFile.isFile())) {
// so we add a check for that here to work around it // if not, assume it is in the fbx directory
bool isRelative = fbxRelativeFilepath[1] != ':' && fileInfo.isRelative(); filename = filename.mid(filename.lastIndexOf('/') + 1);
#else
bool isRelative = fileInfo.isRelative();
#endif
if (isRelative) {
// the RelativeFilename pulled from the FBX is already correctly relative
// so simply return this as the filepath to use
return fbxRelativeFilepath;
} else {
// the RelativeFilename pulled from the FBX is an absolute path
// use the URL to figure out where the FBX is being loaded from
auto filename = fileInfo.fileName();
if (url.isLocalFile()) {
// the FBX is being loaded from the local filesystem
if (fileInfo.exists() && fileInfo.isFile()) {
// found a file at the absolute path in the FBX, return that path
return fbxRelativeFilepath;
} else {
// didn't find a file at the absolute path, assume it is right beside the FBX
// return just the filename as the relative path
return filename.toUtf8();
}
} else {
// this is a remote file, meaning we can't really do anything with the absolute path to the texture
// so assume it will be right beside the fbx
return filename.toUtf8();
}
} }
return filename;
} }
FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QUrl& url) { FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) {
const FBXNode& node = _fbxNode; const FBXNode& node = _fbxNode;
QMap<QString, ExtractedMesh> meshes; QMap<QString, ExtractedMesh> meshes;
QHash<QString, QString> modelIDsToNames; QHash<QString, QString> modelIDsToNames;
@ -860,9 +833,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
const int MODEL_UV_SCALING_MIN_SIZE = 2; const int MODEL_UV_SCALING_MIN_SIZE = 2;
const int CROPPING_MIN_SIZE = 4; const int CROPPING_MIN_SIZE = 4;
if (subobject.name == "RelativeFilename" && subobject.properties.length() >= RELATIVE_FILENAME_MIN_SIZE) { if (subobject.name == "RelativeFilename" && subobject.properties.length() >= RELATIVE_FILENAME_MIN_SIZE) {
auto filepath = fixedTextureFilepath(subobject.properties.at(0).toByteArray(), url); QByteArray filename = subobject.properties.at(0).toByteArray();
QByteArray filepath = filename.replace('\\', '/');
filename = fileOnUrl(filepath, url);
_textureFilepaths.insert(getID(object.properties), filepath); _textureFilepaths.insert(getID(object.properties), filepath);
_textureFilenames.insert(getID(object.properties), filename);
} else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) { } else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) {
// trim the name from the timestamp // trim the name from the timestamp
QString name = QString(subobject.properties.at(0).toByteArray()); QString name = QString(subobject.properties.at(0).toByteArray());
@ -955,7 +930,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
QByteArray content; QByteArray content;
foreach (const FBXNode& subobject, object.children) { foreach (const FBXNode& subobject, object.children) {
if (subobject.name == "RelativeFilename") { if (subobject.name == "RelativeFilename") {
filepath = subobject.properties.at(0).toByteArray(); filepath= subobject.properties.at(0).toByteArray();
filepath = filepath.replace('\\', '/'); filepath = filepath.replace('\\', '/');
} else if (subobject.name == "Content" && !subobject.properties.isEmpty()) { } else if (subobject.name == "Content" && !subobject.properties.isEmpty()) {
@ -1527,7 +1502,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
geometry.materials = _fbxMaterials; geometry.materials = _fbxMaterials;
// see if any materials have texture children // see if any materials have texture children
bool materialsHaveTextures = checkMaterialsHaveTextures(_fbxMaterials, _textureFilepaths, _connectionChildMap); bool materialsHaveTextures = checkMaterialsHaveTextures(_fbxMaterials, _textureFilenames, _connectionChildMap);
for (QMap<QString, ExtractedMesh>::iterator it = meshes.begin(); it != meshes.end(); it++) { for (QMap<QString, ExtractedMesh>::iterator it = meshes.begin(); it != meshes.end(); it++) {
ExtractedMesh& extracted = it.value(); ExtractedMesh& extracted = it.value();
@ -1572,7 +1547,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
materialIndex++; materialIndex++;
} else if (_textureFilepaths.contains(childID)) { } else if (_textureFilenames.contains(childID)) {
FBXTexture texture = getTexture(childID); FBXTexture texture = getTexture(childID);
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
int partTexture = extracted.partMaterialTextures.at(j).second; int partTexture = extracted.partMaterialTextures.at(j).second;
@ -1843,13 +1818,13 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
return geometryPtr; return geometryPtr;
} }
FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QUrl& url, bool loadLightmaps, float lightmapLevel) { FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) {
QBuffer buffer(const_cast<QByteArray*>(&model)); QBuffer buffer(const_cast<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel);
} }
FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QUrl& url, bool loadLightmaps, float lightmapLevel) { FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) {
FBXReader reader; FBXReader reader;
reader._fbxNode = FBXReader::parseFBX(device); reader._fbxNode = FBXReader::parseFBX(device);
reader._loadLightmaps = loadLightmaps; reader._loadLightmaps = loadLightmaps;

View file

@ -268,7 +268,7 @@ class FBXGeometry {
public: public:
using Pointer = std::shared_ptr<FBXGeometry>; using Pointer = std::shared_ptr<FBXGeometry>;
QUrl originalURL; QString originalURL;
QString author; QString author;
QString applicationName; ///< the name of the application that generated the model QString applicationName; ///< the name of the application that generated the model
@ -330,11 +330,11 @@ Q_DECLARE_METATYPE(FBXGeometry::Pointer)
/// Reads FBX geometry from the supplied model and mapping data. /// Reads FBX geometry from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing /// \exception QString if an error occurs in parsing
FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QUrl& url = QUrl(), 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. /// Reads FBX geometry from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing /// \exception QString if an error occurs in parsing
FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QUrl& url = QUrl(), bool loadLightmaps = true, float lightmapLevel = 1.0f); FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
class TextureParam { class TextureParam {
public: public:
@ -402,17 +402,19 @@ public:
FBXNode _fbxNode; FBXNode _fbxNode;
static FBXNode parseFBX(QIODevice* device); static FBXNode parseFBX(QIODevice* device);
FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QUrl& url); FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QString& url);
ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex); ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex);
QHash<QString, ExtractedMesh> meshes; QHash<QString, ExtractedMesh> meshes;
static void buildModelMesh(FBXMesh& extractedMesh, const QUrl& url); static void buildModelMesh(FBXMesh& extractedMesh, const QString& url);
FBXTexture getTexture(const QString& textureID); FBXTexture getTexture(const QString& textureID);
QHash<QString, QString> _textureNames; QHash<QString, QString> _textureNames;
// Hashes the original RelativeFilename of textures // Hashes the original RelativeFilename of textures
QHash<QString, QByteArray> _textureFilepaths; QHash<QString, QByteArray> _textureFilepaths;
// Hashes the place to look for textures, in case they are not inlined
QHash<QString, QByteArray> _textureFilenames;
// Hashes texture content by filepath, in case they are inlined // Hashes texture content by filepath, in case they are inlined
QHash<QByteArray, QByteArray> _textureContent; QHash<QByteArray, QByteArray> _textureContent;
QHash<QString, TextureParam> _textureParams; QHash<QString, TextureParam> _textureParams;

View file

@ -85,7 +85,12 @@ FBXTexture FBXReader::getTexture(const QString& textureID) {
FBXTexture texture; FBXTexture texture;
const QByteArray& filepath = _textureFilepaths.value(textureID); const QByteArray& filepath = _textureFilepaths.value(textureID);
texture.content = _textureContent.value(filepath); texture.content = _textureContent.value(filepath);
texture.filename = filepath;
if (texture.content.isEmpty()) { // the content is not inlined
texture.filename = _textureFilenames.value(textureID);
} else { // use supplied filepath for inlined content
texture.filename = filepath;
}
texture.name = _textureNames.value(textureID); texture.name = _textureNames.value(textureID);
texture.transform.setIdentity(); texture.transform.setIdentity();
@ -150,7 +155,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
// FBX files generated by 3DSMax have an intermediate texture parent, apparently // FBX files generated by 3DSMax have an intermediate texture parent, apparently
foreach(const QString& childTextureID, _connectionChildMap.values(diffuseTextureID)) { foreach(const QString& childTextureID, _connectionChildMap.values(diffuseTextureID)) {
if (_textureFilepaths.contains(childTextureID)) { if (_textureFilenames.contains(childTextureID)) {
diffuseTexture = getTexture(diffuseTextureID); diffuseTexture = getTexture(diffuseTextureID);
} }
} }

View file

@ -388,7 +388,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
return data.extracted; return data.extracted;
} }
void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QUrl& url) { void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*"); static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*");
unsigned int totalSourceIndices = 0; unsigned int totalSourceIndices = 0;

View file

@ -173,7 +173,7 @@ void GeometryReader::run() {
FBXGeometry::Pointer fbxGeometry; FBXGeometry::Pointer fbxGeometry;
if (_url.path().toLower().endsWith(".fbx")) { if (_url.path().toLower().endsWith(".fbx")) {
fbxGeometry.reset(readFBX(_data, _mapping, _url)); fbxGeometry.reset(readFBX(_data, _mapping, _url.path()));
if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) { if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) {
throw QString("empty geometry, possibly due to an unsupported FBX version"); throw QString("empty geometry, possibly due to an unsupported FBX version");
} }