diff --git a/README.md b/README.md index e056a9801..09265f293 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Additionally, this is a list of some interesting projects using fastgltf: - [Fwog](https://github.com/JuanDiegoMontoya/Fwog): The examples of this modern OpenGL 4.6 abstraction make use of fastgltf. - [wad2gltf](https://github.com/DethRaid/wad2gltf): A WAD to glTF converter - [Castor3D](https://github.com/DragonJoker/Castor3D): A multi-OS 3D engine +- [Raz](https://github.com/Razakhel/RaZ): A modern & multiplatform 3D game engine in C++17 ## License diff --git a/docs/overview.rst b/docs/overview.rst index 946d35693..970699640 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -171,6 +171,8 @@ Additionally, this is a list of some interesting projects using fastgltf: - `Fwog `_: The examples of this modern OpenGL 4.6 abstraction make use of fastgltf. - `wad2gltf `_: A WAD to glTF converter - `Castor3D `_: A multi-OS 3D engine +- `Raz `_: A modern & multiplatform 3D game engine in C++17 + .. _accessor-tools: diff --git a/include/fastgltf/core.hpp b/include/fastgltf/core.hpp index 8fa81b3b5..a8deba488 100644 --- a/include/fastgltf/core.hpp +++ b/include/fastgltf/core.hpp @@ -87,6 +87,7 @@ namespace fastgltf { UnsupportedVersion = 10, ///< The glTF version is not supported by fastgltf. InvalidURI = 11, ///< A URI from a buffer or image failed to be parsed. InvalidFileData = 12, ///< The file data is invalid, or the file type could not be determined. + FailedWritingFiles = 13, ///< The exporter failed to write some files (buffers/images) to disk. }; inline std::string_view getErrorName(Error error) { @@ -104,6 +105,7 @@ namespace fastgltf { case Error::UnsupportedVersion: return "UnsupportedVersion"; case Error::InvalidURI: return "InvalidURI"; case Error::InvalidFileData: return "InvalidFileData"; + case Error::FailedWritingFiles: return "FailedWritingFiles"; default: FASTGLTF_UNREACHABLE } } @@ -123,6 +125,7 @@ namespace fastgltf { case Error::UnsupportedVersion: return "The glTF version is not supported by fastgltf."; case Error::InvalidURI: return "A URI from a buffer or image failed to be parsed."; case Error::InvalidFileData: return "The file data is invalid, or the file type could not be determined."; + case Error::FailedWritingFiles: return "The exporter failed to write some files (buffers/images) to disk."; default: FASTGLTF_UNREACHABLE } } diff --git a/src/fastgltf.cpp b/src/fastgltf.cpp index d094a7f33..5feb92ae1 100644 --- a/src/fastgltf.cpp +++ b/src/fastgltf.cpp @@ -4205,6 +4205,10 @@ void fg::Exporter::writeBuffers(const Asset& asset, std::string& json) { bufferPaths.emplace_back(path); }, [&](const sources::ByteView& view) { + if (bufferIdx == 0 && exportingBinary) { + bufferPaths.emplace_back(std::nullopt); + return; + } auto path = getBufferFilePath(asset, bufferIdx); json += std::string(R"("uri":")") + fg::escapeString(path.string()) + '"' + ','; bufferPaths.emplace_back(path); @@ -5436,46 +5440,60 @@ fg::Expected>> fg::Exporter::writeGltfBi } namespace fastgltf { - void writeFile(const DataSource& dataSource, fs::path baseFolder, fs::path filePath) { - std::visit(visitor { - [](auto& arg) {}, + bool writeFile(const DataSource& dataSource, fs::path baseFolder, fs::path filePath) { + return std::visit(visitor { + [](auto& arg) { + return false; + }, [&](const sources::Array& vector) { std::ofstream file(baseFolder / filePath, std::ios::out | std::ios::binary); + if (!file.is_open()) + return false; file.write(reinterpret_cast(vector.bytes.data()), static_cast(vector.bytes.size())); file.close(); + return file.good(); }, [&](const sources::Vector& vector) { std::ofstream file(baseFolder / filePath, std::ios::out | std::ios::binary); + if (!file.is_open()) + return false; file.write(reinterpret_cast(vector.bytes.data()), static_cast(vector.bytes.size())); file.close(); + return file.good(); }, [&](const sources::ByteView& view) { std::ofstream file(baseFolder / filePath, std::ios::out | std::ios::binary); + if (!file.is_open()) + return false; file.write(reinterpret_cast(view.bytes.data()), static_cast(view.bytes.size())); file.close(); + return file.good(); }, }, dataSource); } - template - void writeFiles(const Asset& asset, ExportResult &result, fs::path baseFolder) { - for (std::size_t i = 0; i < asset.buffers.size(); ++i) { - auto &path = result.bufferPaths[i]; - if (path.has_value()) { - writeFile(asset.buffers[i].data, baseFolder, path.value()); - } - } + template + bool writeFiles(const Asset& asset, ExportResult &result, fs::path baseFolder) { + for (std::size_t i = 0; i < asset.buffers.size(); ++i) { + auto &path = result.bufferPaths[i]; + if (path.has_value()) { + if (!writeFile(asset.buffers[i].data, baseFolder, path.value())) + return false; + } + } - for (std::size_t i = 0; i < asset.images.size(); ++i) { - auto &path = result.imagePaths[i]; - if (path.has_value()) { - writeFile(asset.images[i].data, baseFolder, path.value()); - } - } - } + for (std::size_t i = 0; i < asset.images.size(); ++i) { + auto &path = result.imagePaths[i]; + if (path.has_value()) { + if (!writeFile(asset.images[i].data, baseFolder, path.value())) + return false; + } + } + return true; + } } // namespace fastgltf fg::Error fg::FileExporter::writeGltfJson(const Asset& asset, std::filesystem::path target, ExportOptions options) { @@ -5494,7 +5512,9 @@ fg::Error fg::FileExporter::writeGltfJson(const Asset& asset, std::filesystem::p file << result.output; file.close(); - writeFiles(asset, result, target.parent_path()); + if (!writeFiles(asset, result, target.parent_path())) { + return Error::FailedWritingFiles; + } return Error::None; } @@ -5514,7 +5534,9 @@ fg::Error fg::FileExporter::writeGltfBinary(const Asset& asset, std::filesystem: file.write(reinterpret_cast(result.output.data()), static_cast(result.output.size())); - writeFiles(asset, result, target.parent_path()); + if (!writeFiles(asset, result, target.parent_path())) { + return Error::FailedWritingFiles; + } return Error::None; } #pragma endregion