diff --git a/README.md b/README.md index f913471..1ca54d3 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,7 @@ You need to install the MVSC redistributable on Windows. https://support.microso ## Build Instructions Reference the Github workflow. + +```bash +conan install . -i build -s build_type=Release -s compiler.cppstd=17 -s compiler.runtime=static --build=missing +``` \ No newline at end of file diff --git a/demo/addons/fbx/import_fbx.gd b/demo/addons/fbx/import_fbx.gd index 6f38ae0..f214244 100644 --- a/demo/addons/fbx/import_fbx.gd +++ b/demo/addons/fbx/import_fbx.gd @@ -32,11 +32,12 @@ func _import_scene(path: String, flags: int, bake_fps: int): ProjectSettings.add_property_info(property_info) var user_path_base = OS.get_user_data_dir() var path_global : String = ProjectSettings.globalize_path(path) - var output_path : String = "res://.godot/imported/" + path.get_file().get_basename() + "-" + path.md5_text() + ".glb" + var output_path : String = "res://.godot/imported/" + path.get_file().get_basename() + "-" + path.md5_text() + ".gltf" var output_path_global = ProjectSettings.globalize_path(output_path) var stdout = [].duplicate() var temp_dir_global = ProjectSettings.globalize_path("res://.godot/imported/") var ret = OS.execute(fbx2gltf_path, [ + "--keep-originals", "--fbx-temp-dir", temp_dir_global, "-i", path_global, "-o", output_path_global], stdout, true) diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index 5bb8841..3233a29 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -40,9 +40,8 @@ int main(int argc, char* argv[]) { exit(0); }); - std::string inputPath; - app.add_option("FBX Model", inputPath, "The FBX model to convert.")->check(CLI::ExistingFile); - app.add_option("-i,--input", inputPath, "The FBX model to convert.")->check(CLI::ExistingFile); + app.add_option("FBX Model", gltfOptions.inputPath, "The FBX model to convert.")->check(CLI::ExistingFile); + app.add_option("-i,--input", gltfOptions.inputPath, "The FBX model to convert.")->check(CLI::ExistingFile); std::string outputPath; app.add_option("-o,--output", outputPath, "Where to generate the output, without suffix."); @@ -52,6 +51,12 @@ int main(int argc, char* argv[]) { gltfOptions.embedResources, "Inline buffers as data:// URIs within generated non-binary glTF."); + + app.add_flag( + "--keep-originals", + gltfOptions.keepOriginals, + "Keep the originals paths in a non-binary glTF."); + app.add_flag( "-t,--separate-textures", gltfOptions.separateTextures, "Write texture files out separately"); @@ -291,7 +296,7 @@ int main(int argc, char* argv[]) { } } - if (inputPath.empty()) { + if (gltfOptions.inputPath.empty()) { fmt::printf("You must supply a FBX file to convert.\n"); exit(1); } @@ -306,10 +311,10 @@ int main(int argc, char* argv[]) { if (gltfOptions.embedResources && gltfOptions.outputBinary) { fmt::printf("Note: Ignoring --embed; it's meaningless with --binary.\n"); } - + if (outputPath.empty()) { // if -o is not given, default to the basename of the .fbx - outputPath = "./" + FileUtils::GetFileBase(inputPath); + outputPath = "./" + FileUtils::GetFileBase(gltfOptions.inputPath); } // the output folder in .gltf mode, not used for .glb std::string outputFolder; @@ -349,10 +354,10 @@ int main(int argc, char* argv[]) { RawModel raw; if (verboseOutput) { - fmt::printf("Loading FBX File: %s\n", inputPath); + fmt::printf("Loading FBX File: %s\n", gltfOptions.inputPath); } - if (!LoadFBXFile(raw, inputPath, {"png", "jpg", "jpeg"}, gltfOptions)) { - fmt::fprintf(stderr, "ERROR:: Failed to parse FBX: %s\n", inputPath); + if (!LoadFBXFile(raw, gltfOptions.inputPath, {"png", "jpg", "jpeg"}, gltfOptions)) { + fmt::fprintf(stderr, "ERROR:: Failed to parse FBX: %s\n", gltfOptions.inputPath); return 1; } @@ -394,7 +399,7 @@ int main(int argc, char* argv[]) { assert(!outputFolder.empty()); - const std::string binaryPath = outputFolder + extBufferFilename; + const std::string binaryPath = outputFolder + FileUtils::GetFileBase(gltfOptions.inputPath) + extBufferFilename; FILE* fp = fopen(binaryPath.c_str(), "wb"); if (fp == nullptr) { fmt::fprintf(stderr, "ERROR:: Couldn't open file '%s' for writing.\n", binaryPath); diff --git a/src/FBX2glTF.h b/src/FBX2glTF.h index e9ee876..10b4e2a 100644 --- a/src/FBX2glTF.h +++ b/src/FBX2glTF.h @@ -78,6 +78,7 @@ enum class AnimationFramerateOptions { * User-supplied options that dictate the nature of the glTF being generated. */ struct GltfOptions { + std::string inputPath; /** * If negative, disabled. Otherwise, a bitfield of RawVertexAttributes that * specify the largest set of attributes that'll ever be kept for a vertex. @@ -90,6 +91,8 @@ struct GltfOptions { /** If non-binary, whether to inline all resources, for a single (large) .glTF file. */ bool embedResources{false}; + bool keepOriginals{false}; + bool separateTextures{true}; /** Whether and how to use KHR_draco_mesh_compression to minimize static geometry size. */ diff --git a/src/gltf/TextureBuilder.cpp b/src/gltf/TextureBuilder.cpp index 0a930dc..e3ace2f 100644 --- a/src/gltf/TextureBuilder.cpp +++ b/src/gltf/TextureBuilder.cpp @@ -185,7 +185,18 @@ std::shared_ptr TextureBuilder::simple(int rawTexIndex, const std:: const std::string textureName = FileUtils::GetFileBase(rawTexture.name); const std::string relativeFilename = FileUtils::GetFileName(rawTexture.fileLocation); ImageData* image = nullptr; - if (options.outputBinary) { + if (options.keepOriginals && !relativeFilename.empty()) { + image = new ImageData(textureName, relativeFilename); + } else if (options.keepOriginals && relativeFilename.empty()) { + std::string inputPathBase = FileUtils::GetFileBase(options.inputPath); + std::string outputPath = inputPathBase + "/textures/" + textureName; + image = new ImageData(textureName, outputPath); + if (FileUtils::CopyFile(rawTexture.fileLocation, outputPath, true)) { + if (verboseOutput) { + fmt::printf("Copied texture '%s' to output folder: %s\n", textureName, outputPath); + } + } + } else if (options.outputBinary) { auto bufferView = gltf.AddBufferViewForFile(*gltf.defaultBuffer, rawTexture.fileLocation); if (bufferView) { const auto& suffix = FileUtils::GetFileSuffix(rawTexture.fileLocation); @@ -201,22 +212,17 @@ std::shared_ptr TextureBuilder::simple(int rawTexIndex, const std:: } image = new ImageData(relativeFilename, *bufferView, mimeType); } - - } else if (!relativeFilename.empty()) { - std::string outputPath = outputFolder + "/" + relativeFilename; - auto dstAbs = FileUtils::GetAbsolutePath(outputPath); + } else if (!relativeFilename.empty()) { image = new ImageData(relativeFilename, relativeFilename); - auto srcAbs = FileUtils::GetAbsolutePath(rawTexture.fileLocation); - if (!FileUtils::FileExists(outputPath) && srcAbs != dstAbs) { - if (FileUtils::CopyFile(rawTexture.fileLocation, outputPath, true)) { - if (verboseOutput) { - fmt::printf("Copied texture '%s' to output folder: %s\n", textureName, outputPath); - } - } else { - // no point commenting further on read/write error; CopyFile() does enough of that, and we - // certainly want to to add an image struct to the glTF JSON, with the correct relative - // path reference, even if the copy failed. + std::string outputPath = outputFolder + "/" + relativeFilename; + if (FileUtils::CopyFile(rawTexture.fileLocation, outputPath, true)) { + if (verboseOutput) { + fmt::printf("Copied texture '%s' to output folder: %s\n", textureName, outputPath); } + } else { + // no point commenting further on read/write error; CopyFile() does enough of that, and we + // certainly want to to add an image struct to the glTF JSON, with the correct relative path + // reference, even if the copy failed. } } if (!image) {