diff --git a/.gitignore b/.gitignore index 7ae5cdd..760f38d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ npm/fbx2gltf/node_modules/ npm/tests/node_modules/ npm/tests/test/*.js npm/tests/test/*.js.map +build +sdk diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index 7c8948d..3f545b6 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -326,7 +326,7 @@ int main(int argc, char* argv[]) { if (verboseOutput) { fmt::printf("Loading FBX File: %s\n", inputPath); } - if (!LoadFBXFile(raw, inputPath, {"png", "jpg", "jpeg"}, gltfOptions)) { + if (!LoadFBXFile(raw, inputPath, {"png", "jpg", "jpeg", "tga"}, gltfOptions)) { fmt::fprintf(stderr, "ERROR:: Failed to parse FBX: %s\n", inputPath); return 1; } diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 351bd85..90033b2 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -32,6 +32,14 @@ #include "materials/RoughnessMetallicMaterials.hpp" #include "materials/TraditionalMaterials.hpp" +#ifdef _WIN32 +#define SLASH_CHAR '\\' +#define ALTERNATIVE_SLASH_CHAR '/' +#else +#define SLASH_CHAR '/' +#define ALTERNATIVE_SLASH_CHAR '\\' +#endif + float scaleFactor; static std::string NativeToUTF8(const std::string& str) { @@ -1032,6 +1040,16 @@ static std::string FindFbxTexture( return FileUtils::GetAbsolutePath(fileLocation); } } + //Replace slashes with alternative platform version (e.g. '/' instead of '\\') + std::string textureFileNameAltSlash = textureFileName; + std::replace( textureFileNameAltSlash.begin(), textureFileNameAltSlash.end(), ALTERNATIVE_SLASH_CHAR, SLASH_CHAR); + // finally look with alternative slashes + for (int ii = 0; ii < folders.size(); ii++) { + const auto& fileLocation = FindFileLoosely(textureFileNameAltSlash, folders[ii], folderContents[ii]); + if (!fileLocation.empty()) { + return FileUtils::GetAbsolutePath(fileLocation); + } + } return ""; } diff --git a/src/gltf/TextureBuilder.cpp b/src/gltf/TextureBuilder.cpp index 7424a5a..19235f6 100644 --- a/src/gltf/TextureBuilder.cpp +++ b/src/gltf/TextureBuilder.cpp @@ -177,15 +177,61 @@ std::shared_ptr TextureBuilder::simple(int rawTexIndex, const std:: return iter->second; } - const RawTexture& rawTexture = raw.GetTexture(rawTexIndex); - const std::string textureName = FileUtils::GetFileBase(rawTexture.name); - const std::string relativeFilename = FileUtils::GetFileName(rawTexture.fileLocation); + + RawTexture rawTexture = raw.GetTexture(rawTexIndex); + std::string textureName = FileUtils::GetFileBase(rawTexture.name); + std::string relativeFilename = FileUtils::GetFileName(rawTexture.fileLocation); + auto suffix = FileUtils::GetFileSuffix(rawTexture.fileLocation); + + //TGAs are not supported by GLTF spec, convert to PNG + if(suffix.has_value() && suffix->compare("tga")==0) { + std::string tmpFolder; + if(outputFolder.empty()) + tmpFolder = "./convertedTextures"; + else + tmpFolder = outputFolder+"/convertedTextures"; + + //Check for existence of ImageMagick convert binary in path + if(std::system("convert -version")!=0) { //GAM TODO - Pipe to /dev/null or NUL to avoid console spew (also should check the output to make sure its really ImageMagick) + fmt::printf("Warning: Failed to find installed version of ImageMagick 'convert'. TGA conversion requires ImageMagick (https://imagemagick.org/) installation in system path)\n"); + //If we can't find convert set the file path to empty string, so next step will fail and set to error texture + rawTexture.fileLocation = ""; + rawTexture.name = ""; + } else { + //Ensure output folder exists + std::string mkdirCmd = "mkdir -p "+tmpFolder; + std::system(mkdirCmd.c_str()); + + std::string baseName= FileUtils::GetFileBase(relativeFilename); + std::string tmpPath = tmpFolder+"/"+baseName+".png"; + + std::string cmdStr = "convert \""+rawTexture.fileLocation+"\" \""+tmpPath+"\"";//GAM TODO - Pipe to /dev/null or NUL to avoid console spew + auto res = std::system(cmdStr.c_str()); + if(res==0) { + rawTexture.fileLocation = tmpPath; + rawTexture.name = baseName+".png"; + if (verboseOutput) { + fmt::printf("Converted TGA texture '%s' to output folder: %s\n", rawTexture.fileLocation, tmpPath); + } + } else { + //If we fail, set the file path to empty string, so next step will fail and set to error texture + fmt::printf("Warning: Failed to convert TGA:%s to %s\n", rawTexture.fileLocation, tmpPath); + rawTexture.fileLocation = ""; + rawTexture.name = ""; + } + } + + //Update the texture details + textureName = FileUtils::GetFileBase(rawTexture.name); + relativeFilename = FileUtils::GetFileName(rawTexture.fileLocation); + suffix = FileUtils::GetFileSuffix(rawTexture.fileLocation); + } ImageData* image = nullptr; + if (options.outputBinary) { auto bufferView = gltf.AddBufferViewForFile(*gltf.defaultBuffer, rawTexture.fileLocation); if (bufferView) { - const auto& suffix = FileUtils::GetFileSuffix(rawTexture.fileLocation); std::string mimeType; if (suffix) { mimeType = ImageUtils::suffixToMimeType(suffix.value()); @@ -212,6 +258,8 @@ std::shared_ptr TextureBuilder::simple(int rawTexIndex, const std:: // reference, even if the copy failed. } } + + if (!image) { // fallback is tiny transparent PNG image = new ImageData(