Skip to content

Commit

Permalink
Add embedded GLB buffer & customization
Browse files Browse the repository at this point in the history
  • Loading branch information
spnda committed Jan 2, 2024
1 parent a902b3a commit f1cfd62
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
8 changes: 8 additions & 0 deletions include/fastgltf/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ namespace fastgltf {

enum class ExportOptions : std::uint64_t {
None = 0,

/**
* Calls fastgltf::validate for the passed asset before writing.
*/
Expand All @@ -279,6 +280,12 @@ namespace fastgltf {
* Pretty-prints the outputted JSON. This option is ignored for binary glTFs.
*/
PrettyPrintJson = 1 << 2,

/**
* This is used by the internal GLB exporter to let the JSON exporter know to treat the first buffer
* as a embedded buffer. This will most likely not be useful for any user.
*/
ExportAsGLB = 1 << 3,
};
// clang-format on

Expand Down Expand Up @@ -804,6 +811,7 @@ namespace fastgltf {
class Exporter {
protected:
Error errorCode = Error::None;
ExportOptions options = ExportOptions::None;

std::filesystem::path bufferFolder = "";
std::filesystem::path imageFolder = "";
Expand Down
31 changes: 26 additions & 5 deletions src/fastgltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3639,13 +3639,17 @@ void fg::Exporter::writeBuffers(const Asset& asset, std::string& json) {
for (auto it = asset.buffers.begin(); it != asset.buffers.end(); ++it) {
json += '{';

auto bufferIdx = std::distance(asset.buffers.begin(), it);
auto bufferIdx = static_cast<std::size_t>(std::distance(asset.buffers.begin(), it));
std::visit(visitor {
[&](auto arg) {
// Covers BufferView and CustomBuffer.
errorCode = Error::InvalidGltf;
},
[&](const sources::Vector& vector) {
if (bufferIdx == 0 && hasBit(options, ExportOptions::ExportAsGLB)) {
bufferPaths.emplace_back(std::nullopt);
return;
}
auto path = getBufferFilePath(asset, bufferIdx);
json += std::string(R"("uri":")") + path.string() + '"' + ',';
bufferPaths.emplace_back(path);
Expand Down Expand Up @@ -4301,9 +4305,10 @@ fs::path fg::Exporter::getImageFilePath(const Asset& asset, std::size_t index, M
return imageFolder / (name + std::to_string(index) + std::string(extension));
}

fg::Expected<fg::ExportResult<std::string>> fg::Exporter::writeGltfJson(const Asset& asset, ExportOptions options) {
fg::Expected<fg::ExportResult<std::string>> fg::Exporter::writeGltfJson(const Asset& asset, ExportOptions nOptions) {
bufferPaths.clear();
imagePaths.clear();
options = nOptions;

if (hasBit(options, ExportOptions::ValidateAsset)) {
auto validation = validate(asset);
Expand Down Expand Up @@ -4362,10 +4367,12 @@ fg::Expected<fg::ExportResult<std::string>> fg::Exporter::writeGltfJson(const As
return Expected { std::move(result) };
}

fg::Expected<fg::ExportResult<std::vector<std::byte>>> fg::Exporter::writeGltfBinary(const Asset& asset, ExportOptions options) {
fg::Expected<fg::ExportResult<std::vector<std::byte>>> fg::Exporter::writeGltfBinary(const Asset& asset, ExportOptions nOptions) {
bufferPaths.clear();
imagePaths.clear();
options = nOptions;

options |= ExportOptions::ExportAsGLB;
options &= (~ExportOptions::PrettyPrintJson);

ExportResult<std::vector<std::byte>> result;
Expand All @@ -4379,8 +4386,10 @@ fg::Expected<fg::ExportResult<std::vector<std::byte>>> fg::Exporter::writeGltfBi
result.bufferPaths = std::move(json.bufferPaths);
result.imagePaths = std::move(json.imagePaths);

const bool withEmbeddedBuffer = false;
//const bool withEmbeddedBuffer = !asset.buffers.empty() || asset.buffers.front().byteLength < std::numeric_limits<std::uint32_t>::max();
const bool withEmbeddedBuffer = !asset.buffers.empty()
&& std::get_if<sources::Vector>(&asset.buffers.front().data) != nullptr // We only support writing Vectors as embedded buffers
&& asset.buffers.front().byteLength < std::numeric_limits<decltype(BinaryGltfChunk::chunkLength)>::max();

std::size_t binarySize = sizeof(BinaryGltfHeader) + sizeof(BinaryGltfChunk) + json.output.size();
if (withEmbeddedBuffer) {
binarySize += sizeof(BinaryGltfChunk) + asset.buffers.front().byteLength;
Expand All @@ -4405,6 +4414,18 @@ fg::Expected<fg::ExportResult<std::vector<std::byte>>> fg::Exporter::writeGltfBi

write(json.output.data(), json.output.size() * sizeof(decltype(json.output)::value_type));

if (withEmbeddedBuffer) {
const auto& buffer = asset.buffers.front();

BinaryGltfChunk dataChunk;
dataChunk.chunkType = binaryGltfDataChunkMagic;
dataChunk.chunkLength = buffer.byteLength;
write(&dataChunk, sizeof dataChunk);

const auto* vector = std::get_if<sources::Vector>(&buffer.data);
write(vector->bytes.data(), buffer.byteLength);
}

return Expected { std::move(result) };
}

Expand Down

0 comments on commit f1cfd62

Please sign in to comment.