mirror of
https://github.com/overte-org/overte.git
synced 2025-04-11 23:08:21 +02:00
Revert "fix relative/absolute path handling for external FBX textures"
This commit is contained in:
parent
04ebdf14a2
commit
e86db26224
6 changed files with 39 additions and 57 deletions
|
@ -74,7 +74,7 @@ void AnimationReader::run() {
|
|||
// Parse the FBX directly from the QNetworkReply
|
||||
FBXGeometry::Pointer fbxgeo;
|
||||
if (_url.path().toLower().endsWith(".fbx")) {
|
||||
fbxgeo.reset(readFBX(_data, QVariantHash(), _url));
|
||||
fbxgeo.reset(readFBX(_data, QVariantHash(), _url.path()));
|
||||
} else {
|
||||
QString errorStr("usupported format");
|
||||
emit onError(299, errorStr);
|
||||
|
|
|
@ -376,10 +376,10 @@ public:
|
|||
};
|
||||
|
||||
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& childID, _connectionChildMap.values(materialID)) {
|
||||
if (textureFilepaths.contains(childID)) {
|
||||
if (textureFilenames.contains(childID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -443,48 +443,21 @@ FBXLight extractLight(const FBXNode& object) {
|
|||
return light;
|
||||
}
|
||||
|
||||
QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, QUrl url) {
|
||||
// first setup a QFileInfo for the passed relative filepath, with backslashes replaced by forward slashes
|
||||
auto fileInfo = QFileInfo { fbxRelativeFilepath.replace("\\", "/") };
|
||||
QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) {
|
||||
QString path = QFileInfo(url).path();
|
||||
QByteArray filename = filepath;
|
||||
QFileInfo checkFile(path + "/" + filepath);
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
// it turns out that absolute windows paths starting with drive letters look like relative paths to QFileInfo on UNIX
|
||||
// so we add a check for that here to work around it
|
||||
bool isRelative = fbxRelativeFilepath[1] != ':' && fileInfo.isRelative();
|
||||
#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();
|
||||
}
|
||||
// check if the file exists at the RelativeFilename
|
||||
if (!(checkFile.exists() && checkFile.isFile())) {
|
||||
// if not, assume it is in the fbx directory
|
||||
filename = filename.mid(filename.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QUrl& url) {
|
||||
FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) {
|
||||
const FBXNode& node = _fbxNode;
|
||||
QMap<QString, ExtractedMesh> meshes;
|
||||
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 CROPPING_MIN_SIZE = 4;
|
||||
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);
|
||||
_textureFilenames.insert(getID(object.properties), filename);
|
||||
} else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) {
|
||||
// trim the name from the timestamp
|
||||
QString name = QString(subobject.properties.at(0).toByteArray());
|
||||
|
@ -955,7 +930,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
|
|||
QByteArray content;
|
||||
foreach (const FBXNode& subobject, object.children) {
|
||||
if (subobject.name == "RelativeFilename") {
|
||||
filepath = subobject.properties.at(0).toByteArray();
|
||||
filepath= subobject.properties.at(0).toByteArray();
|
||||
filepath = filepath.replace('\\', '/');
|
||||
|
||||
} else if (subobject.name == "Content" && !subobject.properties.isEmpty()) {
|
||||
|
@ -1527,7 +1502,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
|
|||
geometry.materials = _fbxMaterials;
|
||||
|
||||
// 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++) {
|
||||
ExtractedMesh& extracted = it.value();
|
||||
|
@ -1572,7 +1547,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
|
|||
|
||||
materialIndex++;
|
||||
|
||||
} else if (_textureFilepaths.contains(childID)) {
|
||||
} else if (_textureFilenames.contains(childID)) {
|
||||
FBXTexture texture = getTexture(childID);
|
||||
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
|
||||
int partTexture = extracted.partMaterialTextures.at(j).second;
|
||||
|
@ -1843,13 +1818,13 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QU
|
|||
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));
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
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;
|
||||
reader._fbxNode = FBXReader::parseFBX(device);
|
||||
reader._loadLightmaps = loadLightmaps;
|
||||
|
|
|
@ -268,7 +268,7 @@ class FBXGeometry {
|
|||
public:
|
||||
using Pointer = std::shared_ptr<FBXGeometry>;
|
||||
|
||||
QUrl originalURL;
|
||||
QString originalURL;
|
||||
QString author;
|
||||
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.
|
||||
/// \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.
|
||||
/// \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 {
|
||||
public:
|
||||
|
@ -402,17 +402,19 @@ public:
|
|||
FBXNode _fbxNode;
|
||||
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);
|
||||
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);
|
||||
|
||||
QHash<QString, QString> _textureNames;
|
||||
// Hashes the original RelativeFilename of textures
|
||||
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
|
||||
QHash<QByteArray, QByteArray> _textureContent;
|
||||
QHash<QString, TextureParam> _textureParams;
|
||||
|
|
|
@ -85,7 +85,12 @@ FBXTexture FBXReader::getTexture(const QString& textureID) {
|
|||
FBXTexture texture;
|
||||
const QByteArray& filepath = _textureFilepaths.value(textureID);
|
||||
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.transform.setIdentity();
|
||||
|
@ -150,7 +155,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
|
|||
|
||||
// FBX files generated by 3DSMax have an intermediate texture parent, apparently
|
||||
foreach(const QString& childTextureID, _connectionChildMap.values(diffuseTextureID)) {
|
||||
if (_textureFilepaths.contains(childTextureID)) {
|
||||
if (_textureFilenames.contains(childTextureID)) {
|
||||
diffuseTexture = getTexture(diffuseTextureID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -388,7 +388,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
|
|||
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 -- .*");
|
||||
|
||||
unsigned int totalSourceIndices = 0;
|
||||
|
|
|
@ -173,7 +173,7 @@ void GeometryReader::run() {
|
|||
FBXGeometry::Pointer fbxGeometry;
|
||||
|
||||
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) {
|
||||
throw QString("empty geometry, possibly due to an unsupported FBX version");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue