Mostly rewrite texture lookup code.
This commit is contained in:
parent
02e5eb684d
commit
d6043151df
|
@ -916,38 +916,61 @@ static void ReadAnimations(RawModel& raw, FbxScene* pScene) {
|
|||
}
|
||||
}
|
||||
|
||||
static std::string GetInferredFileName(
|
||||
static std::string FindFileLoosely(
|
||||
const std::string& fbxFileName,
|
||||
const std::string& directory,
|
||||
const std::vector<std::string>& directoryFileList) {
|
||||
if (FileUtils::FileExists(fbxFileName)) {
|
||||
return fbxFileName;
|
||||
}
|
||||
// Get the file name with file extension.
|
||||
|
||||
// From e.g. C:/Assets/Texture.jpg, extract 'Texture.jpg'
|
||||
const std::string fileName = FileUtils::GetFileName(fbxFileName);
|
||||
|
||||
// Try to find a match with extension.
|
||||
for (const auto& file : directoryFileList) {
|
||||
if (StringUtils::CompareNoCase(fileName, file) == 0) {
|
||||
return std::string(directory) + file;
|
||||
if (StringUtils::CompareNoCase(fileName, FileUtils::GetFileName(file)) == 0) {
|
||||
return directory + "/" + file;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the file name without file extension.
|
||||
const std::string fileBase = FileUtils::GetFileBase(fileName);
|
||||
|
||||
// Try to find a match without file extension.
|
||||
// Try to find a match that ignores file extension
|
||||
for (const auto& file : directoryFileList) {
|
||||
// If the two extension-less base names match.
|
||||
if (StringUtils::CompareNoCase(fileBase, FileUtils::GetFileBase(file)) == 0) {
|
||||
// Return the name with extension of the file in the directory.
|
||||
return std::string(directory) + file;
|
||||
return directory + "/" + file;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to locate the best match to the given texture filename, as provided in the FBX,
|
||||
* possibly searching through the provided folders for a reasonable-looking match.
|
||||
*
|
||||
* Returns empty string if no match can be found, else the absolute path of the file.
|
||||
**/
|
||||
static std::string FindFbxTexture(
|
||||
const std::string& textureFileName,
|
||||
const std::vector<std::string>& folders,
|
||||
const std::vector<std::vector<std::string>>& folderContents) {
|
||||
// it might exist exactly as-is on the running machine's filesystem
|
||||
if (FileUtils::FileExists(textureFileName)) {
|
||||
return textureFileName;
|
||||
}
|
||||
// else look in other designated folders
|
||||
for (int ii = 0; ii < folders.size(); ii++) {
|
||||
const auto& fileLocation = FindFileLoosely(textureFileName, folders[ii], folderContents[ii]);
|
||||
if (!fileLocation.empty()) {
|
||||
return FileUtils::GetAbsolutePath(fileLocation);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
The texture file names inside of the FBX often contain some long author-specific
|
||||
path with the wrong extensions. For instance, all of the art assets may be PSD
|
||||
|
@ -959,39 +982,45 @@ static std::string GetInferredFileName(
|
|||
*/
|
||||
static void FindFbxTextures(
|
||||
FbxScene* pScene,
|
||||
const std::string fbxFileName,
|
||||
const std::string& fbxFileName,
|
||||
const std::set<std::string>& extensions,
|
||||
std::map<const FbxTexture*, FbxString>& textureLocations) {
|
||||
// Get the folder the FBX file is in.
|
||||
const std::string folder = FileUtils::getFolder(fbxFileName);
|
||||
// figure out what folder the FBX file is in,
|
||||
const auto& fbxFolder = FileUtils::getFolder(fbxFileName);
|
||||
std::vector<std::string> folders{
|
||||
// first search filename.fbm folder which the SDK itself expands embedded textures into,
|
||||
fbxFolder + "/" + FileUtils::GetFileBase(fbxFileName) + ".fbm", // filename.fbm
|
||||
// then the FBX folder itself,
|
||||
fbxFolder,
|
||||
// then finally our working directory
|
||||
FileUtils::GetCurrentFolder(),
|
||||
};
|
||||
|
||||
// Check if there is a filename.fbm folder to which embedded textures were extracted.
|
||||
const std::string fbmFolderName = folder + FileUtils::GetFileBase(fbxFileName) + ".fbm/";
|
||||
|
||||
// Search either in the folder with embedded textures or in the same folder as the FBX file.
|
||||
const std::string searchFolder = FileUtils::FolderExists(fbmFolderName) ? fbmFolderName : folder;
|
||||
|
||||
// Get a list with all the texture files from either the folder with embedded textures or the same
|
||||
// folder as the FBX file.
|
||||
std::vector<std::string> fileList = FileUtils::ListFolderFiles(searchFolder.c_str(), extensions);
|
||||
// List the contents of each of these folders (if they exist)
|
||||
std::vector<std::vector<std::string>> folderContents;
|
||||
for (const auto& folder : folders) {
|
||||
if (FileUtils::FolderExists(folder)) {
|
||||
folderContents.push_back(FileUtils::ListFolderFiles(folder, extensions));
|
||||
} else {
|
||||
folderContents.push_back({});
|
||||
}
|
||||
}
|
||||
|
||||
// Try to match the FBX texture names with the actual files on disk.
|
||||
for (int i = 0; i < pScene->GetTextureCount(); i++) {
|
||||
const FbxFileTexture* pFileTexture = FbxCast<FbxFileTexture>(pScene->GetTexture(i));
|
||||
if (pFileTexture == nullptr) {
|
||||
continue;
|
||||
if (pFileTexture != nullptr) {
|
||||
const std::string fileLocation =
|
||||
FindFbxTexture(pFileTexture->GetFileName(), folders, folderContents);
|
||||
// always extend the mapping (even for files we didn't find)
|
||||
textureLocations.emplace(pFileTexture, fileLocation.c_str());
|
||||
if (fileLocation.empty()) {
|
||||
fmt::printf(
|
||||
"Warning: could not find a image file for texture: %s.\n", pFileTexture->GetName());
|
||||
} else if (verboseOutput) {
|
||||
fmt::printf("Found texture '%s' at: %s\n", pFileTexture->GetName(), fileLocation);
|
||||
}
|
||||
}
|
||||
const std::string inferredName =
|
||||
GetInferredFileName(pFileTexture->GetFileName(), searchFolder, fileList);
|
||||
if (inferredName.empty()) {
|
||||
fmt::printf(
|
||||
"Warning: could not find a local image file for texture: %s.\n"
|
||||
"Original filename: %s\n",
|
||||
pFileTexture->GetName(),
|
||||
pFileTexture->GetFileName());
|
||||
}
|
||||
// always extend the mapping, even for files we didn't find
|
||||
textureLocations.emplace(pFileTexture, inferredName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,13 +23,19 @@
|
|||
namespace FileUtils {
|
||||
|
||||
std::vector<std::string> ListFolderFiles(
|
||||
const std::string folder,
|
||||
std::string folder,
|
||||
const std::set<std::string>& matchExtensions) {
|
||||
std::vector<std::string> fileList;
|
||||
for (const std::filesystem::directory_entry& entry : std::filesystem::directory_iterator(folder)) {
|
||||
const std::filesystem::path& path = entry.path();
|
||||
if (matchExtensions.find(path.extension().string()) != matchExtensions.end()) {
|
||||
fileList.push_back(path.string());
|
||||
if (folder.empty()) {
|
||||
folder = ".";
|
||||
}
|
||||
for (const auto& entry : std::filesystem::directory_iterator(folder)) {
|
||||
const auto& suffix = FileUtils::GetFileSuffix(entry.path());
|
||||
if (suffix.has_value()) {
|
||||
const auto& suffix_str = StringUtils::ToLower(suffix.value());
|
||||
if (matchExtensions.find(suffix_str) != matchExtensions.end()) {
|
||||
fileList.push_back(entry.path().filename().string());
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileList;
|
||||
|
|
|
@ -34,8 +34,12 @@ bool CopyFile(
|
|||
const std::string& dstFilename,
|
||||
bool createPath = false);
|
||||
|
||||
inline std::string GetAbsolutePath(const std::string& filePath) {
|
||||
return std::filesystem::absolute(filePath).string();
|
||||
}
|
||||
|
||||
inline std::string GetCurrentFolder() {
|
||||
return std::filesystem::current_path().string() + "/";
|
||||
return std::filesystem::current_path().string();
|
||||
}
|
||||
|
||||
inline bool FileExists(const std::string& filePath) {
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include "String_Utils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace StringUtils {
|
||||
|
||||
int CompareNoCase(const std::string& s1, const std::string& s2) {
|
||||
return strncasecmp(s1.c_str(), s2.c_str(), std::max(s1.length(), s2.length()));
|
||||
}
|
||||
|
||||
} // namespace StringUtils
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
@ -16,11 +18,15 @@
|
|||
|
||||
#if defined(_MSC_VER)
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
namespace StringUtils {
|
||||
|
||||
inline std::string ToLower(std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](uint8_t c) { return std::tolower(c); });
|
||||
return s;
|
||||
}
|
||||
|
||||
inline int CompareNoCase(const std::string& s1, const std::string& s2) {
|
||||
return strncasecmp(s1.c_str(), s2.c_str(), std::max(s1.length(), s2.length()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue