Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: glTF Exporter #33

Merged
merged 25 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
54c8f2b
Update test deps
spnda Jan 28, 2024
7823455
Add: Composer for writing glTF files
spnda Jun 25, 2023
23fbb51
Note write support in documentation
spnda Sep 27, 2023
0fecac5
Fix defaults and add some missing fields
spnda Oct 5, 2023
731e864
Add all missing material fields
spnda Oct 5, 2023
0fc1de6
Add support for writing textures & fix samplers
spnda Oct 27, 2023
bb5a806
Rename to Exporter & support other DataSources
spnda Dec 30, 2023
e6d1afe
Fix some generation errors
spnda Dec 30, 2023
6248660
Add ExportOptions and use Asset references
spnda Jan 1, 2024
4a8f258
Add pretty print option, and fix imageFolder
spnda Jan 2, 2024
caedb6f
Add GLB exporting
spnda Jan 2, 2024
b98f7e4
Add embedded GLB buffer & customization
spnda Jan 2, 2024
389dfd2
Make FileExporter inherit from Exporter again
spnda Jan 2, 2024
0c43e0e
Escape strings & fix pretty print function
spnda Jan 2, 2024
c33cda1
Extract the JSON writing into a writeJson function
spnda Jan 3, 2024
f8f0d95
Add stringifyExtensionBits, fix some docs, add some extensions
spnda Jan 26, 2024
a2f9f6f
Add all of the remaining material extensions
spnda Jan 27, 2024
a4e16d5
Remove remaining usages of float
spnda Jan 27, 2024
b22bea6
Add missing algorithm include
spnda Jan 27, 2024
2055543
Add material extension write tests & fix issues
spnda Jan 27, 2024
45f12d7
Update docs, remove ExportAsGLB, allow ByteView for images
spnda Jan 27, 2024
06d7631
Fix multiple issues with the exporter
spnda Jan 28, 2024
379853f
Fix asserts on Catch2 SKIP macros
spnda Jan 28, 2024
ba7a7a1
Fix glm with C++17 &constexpr
spnda Jan 28, 2024
a04184f
Last changes
spnda Jan 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ tests/gltf/good-froge/
tests/gltf/deccer-cubes/
tests/gltf/bistro/
tests/gltf_loaders/
tests/gltf/export/
tests/gltf/export_glb/

# gltf Rust wrapper
tests/gltf-rs/target
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler_flags.cmake)
# Create the library target
add_library(fastgltf
"src/fastgltf.cpp" "src/base64.cpp"
"include/fastgltf/base64.hpp" "include/fastgltf/glm_element_traits.hpp" "include/fastgltf/parser.hpp" "include/fastgltf/tools.hpp" "include/fastgltf/types.hpp" "include/fastgltf/util.hpp")
"include/fastgltf/base64.hpp" "include/fastgltf/glm_element_traits.hpp" "include/fastgltf/core.hpp" "include/fastgltf/tools.hpp" "include/fastgltf/types.hpp" "include/fastgltf/util.hpp")
add_library(fastgltf::fastgltf ALIAS fastgltf)

fastgltf_compiler_flags(fastgltf)
Expand Down Expand Up @@ -100,7 +100,7 @@ if (ANDROID)
endif()

install(
FILES "include/fastgltf/base64.hpp" "include/fastgltf/glm_element_traits.hpp" "include/fastgltf/parser.hpp" "include/fastgltf/tools.hpp" "include/fastgltf/types.hpp" "include/fastgltf/util.hpp"
FILES "include/fastgltf/base64.hpp" "include/fastgltf/glm_element_traits.hpp" "include/fastgltf/core.hpp" "include/fastgltf/tools.hpp" "include/fastgltf/types.hpp" "include/fastgltf/util.hpp"
DESTINATION include/fastgltf
)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
[![Documentation Status](https://readthedocs.org/projects/fastgltf/badge/?version=latest)](https://fastgltf.readthedocs.io/latest/?badge=latest)


**fastgltf** is a speed and usability focused glTF 2.0 parser written in modern C++17 with minimal dependencies.
**fastgltf** is a speed and usability focused glTF 2.0 library written in modern C++17 with minimal dependencies.
It uses SIMD in various areas to decrease the time the application spends parsing and loading glTF data.
By taking advantage of modern C++17 (and optionally C++20) it also provides easy and safe access to the properties and data.

The parser supports the entirety of glTF 2.0 specification, including many extensions.
The library supports the entirety of glTF 2.0 specification, including many extensions.
By default, fastgltf will only do the absolute minimum to work with a glTF model.
However, it brings many additional features to ease working with the data,
including accessor tools, the ability to directly write to mapped GPU buffers, and decomposing transform matrices.
Expand Down
8 changes: 8 additions & 0 deletions deps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ endif()
# glm
if(EXISTS "${FASTGLTF_DEPS_DIR}/glm")
message(STATUS "fastgltf: Found glm")

# glm breaks because it apparently can't properly detect constexpr/C++ version and
# sets -Weverything which enables C++98 compatibility on Clang??
option(GLM_ENABLE_CXX_17 "" ON)

add_subdirectory("${FASTGLTF_DEPS_DIR}/glm")
add_library(glm::glm ALIAS glm)

Expand Down Expand Up @@ -51,6 +56,9 @@ if (EXISTS "${FASTGLTF_DEPS_DIR}/catch2")
option(CATCH_CONFIG_CPP17_BYTE "" ON)
option(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS "" ON)

# Make sure that exceptions are never disabled, as some other library seems to disable them.
option(CATCH_CONFIG_NO_DISABLE_EXCEPTIONS "" ON)

if (MSVC)
option(CATCH_CONFIG_WINDOWS_CRTDBG "" ON)
endif()
Expand Down
29 changes: 25 additions & 4 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@ Asset
:undoc-members:


Parser
======
Reading & Writing
=================

This section contains all types that one requires to load a glTF file using fastgltf.
This includes the Parser class, options, and data buffers.
This section contains all types that one requires to read or write a glTF file using fastgltf.
This includes the Parser class, Exporter class, options, and data buffers.


Error
Expand Down Expand Up @@ -177,6 +177,14 @@ Options
.. doxygenenum:: fastgltf::Options


.. _exportoptions:

ExportOptions
-------------

.. doxygenenum:: fastgltf::ExportOptions


Expected
--------

Expand Down Expand Up @@ -208,6 +216,19 @@ Parser
:members:


Exporter
--------

.. doxygenfunction:: fastgltf::stringifyExtensionBits

.. doxygenclass:: fastgltf::Exporter
:members:
:undoc-members:

.. doxygenclass:: fastgltf::FileExporter
:members:
:undoc-members:

Utility
=======

Expand Down
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
fastgltf
========

**fastgltf** is a speed and usability focused glTF 2.0 parser written in modern C++17 with minimal dependencies.
**fastgltf** is a speed and usability focused glTF 2.0 library written in modern C++17 with minimal dependencies.
It uses SIMD in various areas to decrease the time the application spends parsing and loading glTF data.
By taking advantage of modern C++17 (and optionally C++20) it also provides easy and safe access to the properties and data.

The parser supports the entirety of glTF 2.0 specification, including many extensions.
The library supports the entirety of glTF 2.0 specification, including many extensions.
By default, fastgltf will only do the absolute minimum to work with a glTF model.
However, it brings many additional features to ease working with the data,
including accessor tools, the ability to directly write to mapped GPU buffers, and decomposing transform matrices.
Expand Down
6 changes: 6 additions & 0 deletions docs/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,9 @@ Parsing options
===============

For more information about the options when parsing a file, see :ref:`the API reference<options>`.


Exporting options
=================

For more information about the options when exporting a file, see :ref:`the API reference<exportoptions>`.
8 changes: 4 additions & 4 deletions docs/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Overview

.. contents:: Table of Contents

**fastgltf** is a speed and usability focused glTF 2.0 parser written in modern C++17 with minimal dependencies.
**fastgltf** is a speed and usability focused glTF 2.0 library written in modern C++17 with minimal dependencies.
It uses SIMD in various areas to decrease the time the application spends parsing and loading glTF data.
By taking advantage of modern C++17 (and optionally C++20) it also provides easy and safe access to the properties and data.

The parser supports the entirety of glTF 2.0 specification, including many extensions.
The library supports the entirety of glTF 2.0 specification, including many extensions.
By default, fastgltf will only do the absolute minimum to work with a glTF model.
However, it brings many additional features to ease working with the data,
including accessor tools, the ability to directly write to mapped GPU buffers, and decomposing transform matrices.
Expand Down Expand Up @@ -42,7 +42,7 @@ glTF libraries.
* - glTF 2.0 writing
- ✔️
- ✔️
-
- ✔️
* - Extension support
- ✔️
- 🟡¹
Expand Down Expand Up @@ -118,7 +118,7 @@ The following snippet illustrates how to use fastgltf to load a glTF file.

.. code:: c++

#include <fastgltf/parser.hpp>
#include <fastgltf/core.hpp>
#include <fastgltf/types.hpp>

void load(std::filesystem::path path) {
Expand Down
6 changes: 4 additions & 2 deletions docs/tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ For example, ``glm::vec3`` would be a vector of 3 floats, which would be defined
template <>
struct fastgltf::ElementTraits<glm::vec3> : fastgltf::ElementTraitsBase<glm::vec3, AccessorType::Vec3, float> {};

Note that, for glm types, there is a header with all pre-defined types shipped with fastgltf: ``fastgltf/glm_element_traits.hpp``.
This header includes the ElementTraits definition for all relevant glm types.
.. note::

Note that, for glm types, there is a header with all pre-defined types shipped with fastgltf: ``fastgltf/glm_element_traits.hpp``.
This header includes the ElementTraits definition for all relevant glm types.


.. warning::
Expand Down
5 changes: 4 additions & 1 deletion examples/gl_viewer/gl_viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@

#include <glad/gl.h>
#include <GLFW/glfw3.h>

// All headers not in the root directory require this
#define GLM_ENABLE_EXPERIMENTAL 1
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
Expand All @@ -37,7 +40,7 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <fastgltf/parser.hpp>
#include <fastgltf/core.hpp>
#include <fastgltf/types.hpp>

constexpr std::string_view vertexShaderSource = R"(
Expand Down
6 changes: 3 additions & 3 deletions fetch_test_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
import zipfile

example_deps_urls = {
'glfw': "https://github.com/glfw/glfw/releases/download/3.3.8/glfw-3.3.8.zip",
'glm': "https://github.com/g-truc/glm/releases/download/0.9.9.8/glm-0.9.9.8.zip",
'glfw': "https://github.com/glfw/glfw/releases/download/3.3.9/glfw-3.3.9.zip",
'glm': "https://github.com/g-truc/glm/archive/refs/tags/1.0.0.zip",
'stb': "https://github.com/nothings/stb/archive/refs/heads/master.zip",
'glad': "https://github.com/Dav1dde/glad/archive/refs/heads/glad2.zip",
}
test_deps_urls = {
'catch2': "https://github.com/catchorg/Catch2/archive/refs/tags/v3.3.2.zip",
'catch2': "https://github.com/catchorg/Catch2/archive/refs/tags/v3.5.2.zip",
'corrosion': "https://github.com/corrosion-rs/corrosion/archive/refs/heads/master.zip",
}
deps_folder = "deps/"
Expand Down
139 changes: 139 additions & 0 deletions include/fastgltf/parser.hpp → include/fastgltf/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,32 @@ namespace fastgltf {
*/
GenerateMeshIndices = 1 << 8,
};

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

/**
* Calls fastgltf::validate for the passed asset before writing.
*/
ValidateAsset = 1 << 1,

/**
* Pretty-prints the outputted JSON. This option is ignored for binary glTFs.
*/
PrettyPrintJson = 1 << 2,
};
// clang-format on

FASTGLTF_ARITHMETIC_OP_TEMPLATE_MACRO(Options, Options, |)
FASTGLTF_ARITHMETIC_OP_TEMPLATE_MACRO(Options, Options, &)
FASTGLTF_ASSIGNMENT_OP_TEMPLATE_MACRO(Options, Options, |)
FASTGLTF_ASSIGNMENT_OP_TEMPLATE_MACRO(Options, Options, &)
FASTGLTF_UNARY_OP_TEMPLATE_MACRO(Options, ~)
FASTGLTF_ARITHMETIC_OP_TEMPLATE_MACRO(ExportOptions, ExportOptions, |)
FASTGLTF_ARITHMETIC_OP_TEMPLATE_MACRO(ExportOptions, ExportOptions, &)
FASTGLTF_ASSIGNMENT_OP_TEMPLATE_MACRO(ExportOptions, ExportOptions, |)
FASTGLTF_ASSIGNMENT_OP_TEMPLATE_MACRO(ExportOptions, ExportOptions, &)
FASTGLTF_UNARY_OP_TEMPLATE_MACRO(ExportOptions, ~)

// String representations of glTF 2.0 extension identifiers.
namespace extensions {
Expand Down Expand Up @@ -762,6 +781,126 @@ namespace fastgltf {
void setBase64DecodeCallback(Base64DecodeCallback* decodeCallback) noexcept;
void setUserPointer(void* pointer) noexcept;
};

/**
* This converts a compacted JSON string into a more readable pretty format.
*/
void prettyPrintJson(std::string& json);

/**
* Escapes a string for use in JSON.
*/
std::string escapeString(std::string_view string);

/**
* Returns a list of extension names based on the given extension flags.
*/
auto stringifyExtensionBits(Extensions extensions) -> decltype(Asset::extensionsRequired);

template <typename T>
struct ExportResult {
T output;

std::vector<std::optional<std::filesystem::path>> bufferPaths;
std::vector<std::optional<std::filesystem::path>> imagePaths;
};

/**
* A exporter for serializing one or more glTF assets into JSON and GLB forms.
*
* @note This does not write anything to any files. This class only serializes data
* into memory structures, which can then be used to manually write them to disk.
* If you want to let fastgltf handle the file writing too, use fastgltf::FileExporter.
*/
class Exporter {
protected:
Error errorCode = Error::None;
ExportOptions options = ExportOptions::None;
bool exportingBinary = false;

std::filesystem::path bufferFolder = "";
std::filesystem::path imageFolder = "";

std::vector<std::optional<std::filesystem::path>> bufferPaths;
std::vector<std::optional<std::filesystem::path>> imagePaths;

void writeAccessors(const Asset& asset, std::string& json);
void writeBuffers(const Asset& asset, std::string& json);
void writeBufferViews(const Asset& asset, std::string& json);
void writeCameras(const Asset& asset, std::string& json);
void writeImages(const Asset& asset, std::string& json);
void writeLights(const Asset& asset, std::string& json);
void writeMaterials(const Asset& asset, std::string& json);
void writeMeshes(const Asset& asset, std::string& json);
void writeNodes(const Asset& asset, std::string& json);
void writeSamplers(const Asset& asset, std::string& json);
void writeScenes(const Asset& asset, std::string& json);
void writeSkins(const Asset& asset, std::string& json);
void writeTextures(const Asset& asset, std::string& json);
void writeExtensions(const Asset& asset, std::string& json);

std::filesystem::path getBufferFilePath(const Asset& asset, std::size_t index);
std::filesystem::path getImageFilePath(const Asset& asset, std::size_t index, MimeType mimeType);

std::string writeJson(const Asset& asset);

public:
/**
* Sets the relative base path for buffer URIs.
*
* If folder.is_relative() returns false, this has no effect.
*/
void setBufferPath(std::filesystem::path folder);
/**
* Sets the relative base path for image URIs.
*
* If folder.is_relative() returns false, this has no effect.
*/
void setImagePath(std::filesystem::path folder);

/**
* Generates a glTF JSON string from the given asset.
*/
Expected<ExportResult<std::string>> writeGltfJson(const Asset& asset, ExportOptions options = ExportOptions::None);

/**
* Generates a glTF binary (GLB) blob from the given asset.
*
* If the first buffer holds a sources::Vector or sources::ByteView and the byte length is smaller than 2^32 (4.2GB),
* it will be embedded into the binary. Note that the returned vector might therefore get quite large.
*/
Expected<ExportResult<std::vector<std::byte>>> writeGltfBinary(const Asset& asset, ExportOptions options = ExportOptions::None);
};

/**
* A exporter for serializing one or more glTF files into JSON and GLB forms.
* This exporter builds upon Exporter by writing all files automatically to the
* given paths.
*/
class FileExporter : public Exporter {
using Exporter::writeGltfJson;
using Exporter::writeGltfBinary;

public:
/**
* Writes a glTF JSON string generated from the given asset to the specified target file. This will also write
* all buffers and textures to disk using the buffer and image paths set using Exporter::setBufferPath and
* Exporter::setImagePath.
*/
Error writeGltfJson(const Asset& asset, std::filesystem::path target, ExportOptions options = ExportOptions::None);

/**
* Writes a glTF binary (GLB) blob from the given asset to the specified target file. This will also write
* all buffers and textures to disk using the buffer and image paths set using Exporter::setBufferPath and
* Exporter::setImagePath.
*
* If the first buffer holds a sources::Vector or sources::ByteView and the byte length is smaller than 2^32 (4.2GB),
* it will be embedded into the binary.
*
* \see Exporter::writeGltfBinary
*/
Error writeGltfBinary(const Asset& asset, std::filesystem::path target, ExportOptions options = ExportOptions::None);
};
} // namespace fastgltf

#ifdef _MSC_VER
Expand Down
Loading
Loading