mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-06-13 10:48:56 +00:00
Compare commits
59 Commits
empty-mate
...
github-act
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfab524125 | ||
|
|
9229971bcb | ||
|
|
051149311c | ||
|
|
4749b0989d | ||
|
|
0bfcb4f49e | ||
|
|
17e6e310ce | ||
|
|
07ceb4c313 | ||
|
|
e7f1ff5c59 | ||
|
|
fd904063c9 | ||
|
|
38398cc2da | ||
|
|
ed1a294bc4 | ||
|
|
b86eb6c079 | ||
|
|
e4bc6c7bd4 | ||
|
|
13803659f8 | ||
|
|
a3d5d5d1c9 | ||
|
|
9e3d1f6db5 | ||
|
|
190382aecd | ||
|
|
c6501530e3 | ||
|
|
ed48224f4b | ||
|
|
19a41d20ec | ||
|
|
0598a20cce | ||
|
|
514167b475 | ||
|
|
0f76561ebf | ||
|
|
f3dc4acaa4 | ||
|
|
1588e75e26 | ||
|
|
d1453b5e5e | ||
|
|
7e83ef9fb4 | ||
|
|
425195bf9c | ||
|
|
ce3a30e612 | ||
|
|
8a35b8f6fe | ||
|
|
f66f3bfeb3 | ||
|
|
e29ba7c49a | ||
|
|
bc753d4ac5 | ||
|
|
688ba8a60e | ||
|
|
d07b976d59 | ||
|
|
08a7dd8dad | ||
|
|
87da1e775f | ||
|
|
151495558e | ||
|
|
84e15260ba | ||
|
|
03cdef430d | ||
|
|
fb4bd82e2c | ||
|
|
3ddf8301f6 | ||
|
|
298c37a954 | ||
|
|
b702de755f | ||
|
|
58ceed1d89 | ||
|
|
d1b6b3a5aa | ||
|
|
c56d069726 | ||
|
|
d1e32865f1 | ||
|
|
869a9d273c | ||
|
|
1208f057d6 | ||
|
|
f684dde9f1 | ||
|
|
7905a5b4dc | ||
|
|
f161782001 | ||
|
|
654bcf733c | ||
|
|
001c870051 | ||
|
|
2c521b3432 | ||
|
|
a159945db9 | ||
|
|
010ee9c67b | ||
|
|
a23971c603 |
6
.github/workflows/c-cpp.yml
vendored
6
.github/workflows/c-cpp.yml
vendored
@@ -47,7 +47,8 @@ jobs:
|
|||||||
sudo apt-get install -y mingw-w64
|
sudo apt-get install -y mingw-w64
|
||||||
x86_64-w64-mingw32-g++ -std=c++11 -o loader_example loader_example.cc
|
x86_64-w64-mingw32-g++ -std=c++11 -o loader_example loader_example.cc
|
||||||
|
|
||||||
# Windows(x64) + Visual Studio 2019 build
|
# Windows(x64) + Visual Studio 2022 build
|
||||||
|
# Assume windows-latest have VS2022 installed
|
||||||
build-windows-msvc:
|
build-windows-msvc:
|
||||||
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
@@ -62,7 +63,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -G "Visual Studio 16 2019" -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On ..
|
cmake --help
|
||||||
|
cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On ..
|
||||||
cd ..
|
cd ..
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --config Release
|
run: cmake --build build --config Release
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ PROJECT (tinygltf)
|
|||||||
|
|
||||||
SET(CMAKE_CXX_STANDARD 11)
|
SET(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example" ON)
|
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example(load glTF and dump infos)" ON)
|
||||||
option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF)
|
option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF)
|
||||||
option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator exampe" OFF)
|
option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator exampe" OFF)
|
||||||
|
option(TINYGLTF_BUILD_BUILDER_EXAMPLE "Build glTF builder example" OFF)
|
||||||
|
option(TINYGLTF_HEADER_ONLY "On: header-only mode. Off: create tinygltf library(No TINYGLTF_IMPLEMENTATION required in your project)" OFF)
|
||||||
|
option(TINYGLTF_INSTALL "Install tinygltf files during install step. Usually set to OFF if you include tinygltf through add_subdirectory()" ON)
|
||||||
|
|
||||||
if (TINYGLTF_BUILD_LOADER_EXAMPLE)
|
if (TINYGLTF_BUILD_LOADER_EXAMPLE)
|
||||||
ADD_EXECUTABLE ( loader_example
|
ADD_EXECUTABLE ( loader_example
|
||||||
@@ -22,20 +25,52 @@ endif (TINYGLTF_BUILD_GL_EXAMPLES)
|
|||||||
if (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
|
if (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
|
||||||
ADD_SUBDIRECTORY ( examples/validator )
|
ADD_SUBDIRECTORY ( examples/validator )
|
||||||
endif (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
|
endif (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
|
||||||
|
|
||||||
|
if (TINYGLTF_BUILD_BUILDER_EXAMPLE)
|
||||||
|
ADD_SUBDIRECTORY ( examples/build-gltf )
|
||||||
|
endif (TINYGLTF_BUILD_BUILDER_EXAMPLE)
|
||||||
|
|
||||||
#
|
#
|
||||||
# TinuGLTF is a header-only library, so no library build. just install header files.
|
# for add_subdirectory and standalone build
|
||||||
#
|
#
|
||||||
INSTALL ( FILES
|
if (TINYGLTF_HEADER_ONLY)
|
||||||
json.hpp
|
add_library(tinygltf INTERFACE)
|
||||||
stb_image.h
|
|
||||||
stb_image_write.h
|
target_include_directories(tinygltf
|
||||||
tiny_gltf.h
|
INTERFACE
|
||||||
DESTINATION
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
include
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
)
|
)
|
||||||
|
|
||||||
INSTALL ( FILES
|
else (TINYGLTF_HEADER_ONLY)
|
||||||
cmake/TinyGLTFConfig.cmake
|
add_library(tinygltf)
|
||||||
DESTINATION
|
target_sources(tinygltf PRIVATE
|
||||||
cmake
|
${CMAKE_CURRENT_SOURCE_DIR}/tiny_gltf.cc)
|
||||||
)
|
target_include_directories(tinygltf
|
||||||
|
INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
endif (TINYGLTF_HEADER_ONLY)
|
||||||
|
|
||||||
|
if (TINYGLTF_INSTALL)
|
||||||
|
|
||||||
|
# Do not install .lib even if !TINYGLTF_HEADER_ONLY
|
||||||
|
|
||||||
|
INSTALL ( FILES
|
||||||
|
json.hpp
|
||||||
|
stb_image.h
|
||||||
|
stb_image_write.h
|
||||||
|
tiny_gltf.h
|
||||||
|
${TINYGLTF_EXTRA_SOUECES}
|
||||||
|
DESTINATION
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALL ( FILES
|
||||||
|
cmake/TinyGLTFConfig.cmake
|
||||||
|
DESTINATION
|
||||||
|
cmake
|
||||||
|
)
|
||||||
|
|
||||||
|
endif(TINYGLTF_INSTALL)
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -7,6 +7,8 @@ If you are looking for old, C++03 version, please use `devel-picojson` branch(bu
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
|
Currently TinyGLTF is stable and maintainance mode. No drastic changes and feature addition planned.
|
||||||
|
|
||||||
- v2.4.0 Experimental RapidJSON support. Experimental C++14 support(C++14 may give better performance)
|
- v2.4.0 Experimental RapidJSON support. Experimental C++14 support(C++14 may give better performance)
|
||||||
- v2.3.0 Modified Material representation according to glTF 2.0 schema(and introduced TextureInfo class)
|
- v2.3.0 Modified Material representation according to glTF 2.0 schema(and introduced TextureInfo class)
|
||||||
- v2.2.0 release(Support loading 16bit PNG. Sparse accessor support)
|
- v2.2.0 release(Support loading 16bit PNG. Sparse accessor support)
|
||||||
@@ -77,6 +79,7 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
|
|||||||
* [glview](examples/glview) : Simple glTF geometry viewer.
|
* [glview](examples/glview) : Simple glTF geometry viewer.
|
||||||
* [validator](examples/validator) : Simple glTF validator with JSON schema.
|
* [validator](examples/validator) : Simple glTF validator with JSON schema.
|
||||||
* [basic](examples/basic) : Basic glTF viewer with texturing support.
|
* [basic](examples/basic) : Basic glTF viewer with texturing support.
|
||||||
|
* [build-gltf](examples/build-gltf) : Build simple glTF scene from a scratch.
|
||||||
|
|
||||||
## Projects using TinyGLTF
|
## Projects using TinyGLTF
|
||||||
|
|
||||||
@@ -90,6 +93,7 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
|
|||||||
* [GlslViewer](https://github.com/patriciogonzalezvivo/glslViewer) - live GLSL coding for MacOS and Linux
|
* [GlslViewer](https://github.com/patriciogonzalezvivo/glslViewer) - live GLSL coding for MacOS and Linux
|
||||||
* [Vulkan-Samples](https://github.com/KhronosGroup/Vulkan-Samples) - The Vulkan Samples is collection of resources to help you develop optimized Vulkan applications.
|
* [Vulkan-Samples](https://github.com/KhronosGroup/Vulkan-Samples) - The Vulkan Samples is collection of resources to help you develop optimized Vulkan applications.
|
||||||
* [TDME2](https://github.com/andreasdr/tdme2) - TDME2 - ThreeDeeMiniEngine2 is a lightweight 3D engine including tools suited for 3D game development using C++11
|
* [TDME2](https://github.com/andreasdr/tdme2) - TDME2 - ThreeDeeMiniEngine2 is a lightweight 3D engine including tools suited for 3D game development using C++11
|
||||||
|
* [SanityEngine](https://github.com/DethRaid/SanityEngine) - A C++/D3D12 renderer focused on the personal and proessional development of its developer
|
||||||
* Your projects here! (Please send PR)
|
* Your projects here! (Please send PR)
|
||||||
|
|
||||||
## TODOs
|
## TODOs
|
||||||
@@ -155,6 +159,10 @@ if (!ret) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Loader options
|
||||||
|
|
||||||
|
* `TinyGLTF::SetPreserveimageChannels(bool onoff)`. `true` to preserve image channels as stored in image file for loaded image. `false` by default for backward compatibility(image channels are widen to `RGBA` 4 channels). Effective only when using builtin image loader(STB image loader).
|
||||||
|
|
||||||
## Compile options
|
## Compile options
|
||||||
|
|
||||||
* `TINYGLTF_NOEXCEPTION` : Disable C++ exception in JSON parsing. You can use `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION` and `TINYGLTF_NOEXCEPTION` to fully remove C++ exception codes when compiling TinyGLTF.
|
* `TINYGLTF_NOEXCEPTION` : Disable C++ exception in JSON parsing. You can use `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION` and `TINYGLTF_NOEXCEPTION` to fully remove C++ exception codes when compiling TinyGLTF.
|
||||||
@@ -164,11 +172,26 @@ if (!ret) {
|
|||||||
* `TINYGLTF_ANDROID_LOAD_FROM_ASSETS`: Load all files from packaged app assets instead of the regular file system. **Note:** You must pass a valid asset manager from your android app to `tinygltf::asset_manager` beforehand.
|
* `TINYGLTF_ANDROID_LOAD_FROM_ASSETS`: Load all files from packaged app assets instead of the regular file system. **Note:** You must pass a valid asset manager from your android app to `tinygltf::asset_manager` beforehand.
|
||||||
* `TINYGLTF_ENABLE_DRACO`: Enable Draco compression. User must provide include path and link correspnding libraries in your project file.
|
* `TINYGLTF_ENABLE_DRACO`: Enable Draco compression. User must provide include path and link correspnding libraries in your project file.
|
||||||
* `TINYGLTF_NO_INCLUDE_JSON `: Disable including `json.hpp` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
* `TINYGLTF_NO_INCLUDE_JSON `: Disable including `json.hpp` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
||||||
|
* `TINYGLTF_NO_INCLUDE_RAPIDJSON `: Disable including RapidJson's header files from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
||||||
* `TINYGLTF_NO_INCLUDE_STB_IMAGE `: Disable including `stb_image.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
* `TINYGLTF_NO_INCLUDE_STB_IMAGE `: Disable including `stb_image.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
||||||
* `TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE `: Disable including `stb_image_write.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
* `TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE `: Disable including `stb_image_write.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
|
||||||
* `TINYGLTF_USE_RAPIDJSON` : Use RapidJSON as a JSON parser/serializer. RapidJSON files are not included in TinyGLTF repo. Please set an include path to RapidJSON if you enable this featrure.
|
* `TINYGLTF_USE_RAPIDJSON` : Use RapidJSON as a JSON parser/serializer. RapidJSON files are not included in TinyGLTF repo. Please set an include path to RapidJSON if you enable this feature.
|
||||||
* `TINYGLTF_USE_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11.
|
* `TINYGLTF_USE_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11.
|
||||||
|
|
||||||
|
## CMake options
|
||||||
|
|
||||||
|
You can add tinygltf using `add_subdirectory` feature.
|
||||||
|
If you add tinygltf to your project using `add_subdirectory`, it would be better to set `TINYGLTF_HEADER_ONLY` on(just add an include path to tinygltf) and `TINYGLTF_INSTALL` off(Which does not install tinygltf files).
|
||||||
|
|
||||||
|
```
|
||||||
|
// Your project's CMakeLists.txt
|
||||||
|
...
|
||||||
|
|
||||||
|
set(TINYGLTF_HEADER_ONLY ON CACHE INTERNAL "" FORCE)
|
||||||
|
set(TINYGLTF_INSTALL OFF CACHE INTERNAL "" FORCE)
|
||||||
|
add_subdirectory(/path/to/tinygltf)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Saving gltTF 2.0 model
|
### Saving gltTF 2.0 model
|
||||||
|
|
||||||
|
|||||||
2
examples/build-gltf/Makefile
Normal file
2
examples/build-gltf/Makefile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
all:
|
||||||
|
$(CXX) -o create_triangle_gltf -I../../ create_triangle_gltf.cpp
|
||||||
121
examples/build-gltf/create_triangle_gltf.cpp
Normal file
121
examples/build-gltf/create_triangle_gltf.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// An example of how to generate a gltf file from scratch. This example
|
||||||
|
// was translated from the pygltlib documentation in the pypi project page,
|
||||||
|
// which in turn is based on the Khronos Sample Models at:
|
||||||
|
//
|
||||||
|
// https://github.com/KhronosGroup/glTF-Sample-Models
|
||||||
|
//
|
||||||
|
// This example is released under the MIT license.
|
||||||
|
//
|
||||||
|
// 2021-02-25 Thu
|
||||||
|
// Dov Grobgeld <dov.grobgeld@gmail.com>
|
||||||
|
|
||||||
|
|
||||||
|
// Define these only in *one* .cc file.
|
||||||
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling.
|
||||||
|
#include "tiny_gltf.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// Create a model with a single mesh and save it as a gltf file
|
||||||
|
tinygltf::Model m;
|
||||||
|
tinygltf::Scene scene;
|
||||||
|
tinygltf::Mesh mesh;
|
||||||
|
tinygltf::Primitive primitive;
|
||||||
|
tinygltf::Node node;
|
||||||
|
tinygltf::Buffer buffer;
|
||||||
|
tinygltf::BufferView bufferView1;
|
||||||
|
tinygltf::BufferView bufferView2;
|
||||||
|
tinygltf::Accessor accessor1;
|
||||||
|
tinygltf::Accessor accessor2;
|
||||||
|
tinygltf::Asset asset;
|
||||||
|
|
||||||
|
// This is the raw data buffer.
|
||||||
|
buffer.data = {
|
||||||
|
// 6 bytes of indices and two bytes of padding
|
||||||
|
0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,
|
||||||
|
// 36 bytes of floating point numbers
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,
|
||||||
|
0x00,0x00,0x00,0x00};
|
||||||
|
|
||||||
|
// "The indices of the vertices (ELEMENT_ARRAY_BUFFER) take up 6 bytes in the
|
||||||
|
// start of the buffer.
|
||||||
|
bufferView1.buffer = 0;
|
||||||
|
bufferView1.byteOffset=0;
|
||||||
|
bufferView1.byteLength=6;
|
||||||
|
bufferView1.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
|
||||||
|
|
||||||
|
// The vertices take up 36 bytes (3 vertices * 3 floating points * 4 bytes)
|
||||||
|
// at position 8 in the buffer and are of type ARRAY_BUFFER
|
||||||
|
bufferView2.buffer = 0;
|
||||||
|
bufferView2.byteOffset=8;
|
||||||
|
bufferView2.byteLength=36;
|
||||||
|
bufferView2.target = TINYGLTF_TARGET_ARRAY_BUFFER;
|
||||||
|
|
||||||
|
// Describe the layout of bufferView1, the indices of the vertices
|
||||||
|
accessor1.bufferView = 0;
|
||||||
|
accessor1.byteOffset = 0;
|
||||||
|
accessor1.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
|
||||||
|
accessor1.count = 3;
|
||||||
|
accessor1.type = TINYGLTF_TYPE_SCALAR;
|
||||||
|
accessor1.maxValues.push_back(2);
|
||||||
|
accessor1.minValues.push_back(0);
|
||||||
|
|
||||||
|
// Describe the layout of bufferView2, the vertices themself
|
||||||
|
accessor2.bufferView = 1;
|
||||||
|
accessor2.byteOffset = 0;
|
||||||
|
accessor2.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||||
|
accessor2.count = 3;
|
||||||
|
accessor2.type = TINYGLTF_TYPE_VEC3;
|
||||||
|
accessor2.maxValues = {1.0, 1.0, 0.0};
|
||||||
|
accessor2.minValues = {0.0, 0.0, 0.0};
|
||||||
|
|
||||||
|
// Build the mesh primitive and add it to the mesh
|
||||||
|
primitive.indices = 0; // The index of the accessor for the vertex indices
|
||||||
|
primitive.attributes["POSITION"] = 1; // The index of the accessor for positions
|
||||||
|
primitive.material = 0;
|
||||||
|
primitive.mode = TINYGLTF_MODE_TRIANGLES;
|
||||||
|
mesh.primitives.push_back(primitive);
|
||||||
|
|
||||||
|
// Other tie ups
|
||||||
|
node.mesh = 0;
|
||||||
|
scene.nodes.push_back(0); // Default scene
|
||||||
|
|
||||||
|
// Define the asset. The version is required
|
||||||
|
asset.version = "2.0";
|
||||||
|
asset.generator = "tinygltf";
|
||||||
|
|
||||||
|
// Now all that remains is to tie back all the loose objects into the
|
||||||
|
// our single model.
|
||||||
|
m.scenes.push_back(scene);
|
||||||
|
m.meshes.push_back(mesh);
|
||||||
|
m.nodes.push_back(node);
|
||||||
|
m.buffers.push_back(buffer);
|
||||||
|
m.bufferViews.push_back(bufferView1);
|
||||||
|
m.bufferViews.push_back(bufferView2);
|
||||||
|
m.accessors.push_back(accessor1);
|
||||||
|
m.accessors.push_back(accessor2);
|
||||||
|
m.asset = asset;
|
||||||
|
|
||||||
|
// Create a simple material
|
||||||
|
tinygltf::Material mat;
|
||||||
|
mat.pbrMetallicRoughness.baseColorFactor = {1.0f, 0.9f, 0.9f, 1.0f};
|
||||||
|
mat.doubleSided = true;
|
||||||
|
m.materials.push_back(mat);
|
||||||
|
|
||||||
|
// Save it to a file
|
||||||
|
tinygltf::TinyGLTF gltf;
|
||||||
|
gltf.WriteGltfSceneToFile(&m, "triangle.gltf",
|
||||||
|
true, // embedImages
|
||||||
|
true, // embedBuffers
|
||||||
|
true, // pretty print
|
||||||
|
false); // write binary
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
@@ -610,7 +610,7 @@ void Viewer::buildSamplerDescs() {
|
|||||||
|
|
||||||
samplerDesc.AddressU = toTextureAddressMode(glTFSampler.wrapS);
|
samplerDesc.AddressU = toTextureAddressMode(glTFSampler.wrapS);
|
||||||
samplerDesc.AddressV = toTextureAddressMode(glTFSampler.wrapT);
|
samplerDesc.AddressV = toTextureAddressMode(glTFSampler.wrapT);
|
||||||
samplerDesc.AddressW = toTextureAddressMode(glTFSampler.wrapR);
|
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
samplerDesc.MaxLOD = 256;
|
samplerDesc.MaxLOD = 256;
|
||||||
|
|
||||||
samplerDescs_.push_back(samplerDesc);
|
samplerDescs_.push_back(samplerDesc);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ add_executable(glview
|
|||||||
target_link_libraries ( glview
|
target_link_libraries ( glview
|
||||||
${DRACO_LIBRARY}
|
${DRACO_LIBRARY}
|
||||||
${GLFW3_UNIX_LINK_LIBRARIES}
|
${GLFW3_UNIX_LINK_LIBRARIES}
|
||||||
${GLEW_LIBRARY}
|
${GLEW_LIBRARIES}
|
||||||
${GLFW3_glfw_LIBRARY}
|
${GLFW3_glfw_LIBRARY}
|
||||||
${OPENGL_gl_LIBRARY}
|
${OPENGL_gl_LIBRARY}
|
||||||
${OPENGL_glu_LIBRARY}
|
${OPENGL_glu_LIBRARY}
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
std::cout << Indent(1) << "channels : [ " << std::endl;
|
std::cout << Indent(1) << "channels : [ " << std::endl;
|
||||||
for (size_t j = 0; i < animation.channels.size(); i++) {
|
for (size_t j = 0; j < animation.channels.size(); j++) {
|
||||||
std::cout << Indent(2)
|
std::cout << Indent(2)
|
||||||
<< "sampler : " << animation.channels[j].sampler
|
<< "sampler : " << animation.channels[j].sampler
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|||||||
267
models/regression/unassigned-skeleton.gltf
Normal file
267
models/regression/unassigned-skeleton.gltf
Normal file
File diff suppressed because one or more lines are too long
@@ -432,11 +432,40 @@ TEST_CASE("serialize-empty-material", "[issue-294]") {
|
|||||||
nlohmann::json j = nlohmann::json::parse(os.str());
|
nlohmann::json j = nlohmann::json::parse(os.str());
|
||||||
|
|
||||||
REQUIRE(1 == j["materials"].size());
|
REQUIRE(1 == j["materials"].size());
|
||||||
REQUIRE(j["asset"].is_null());
|
|
||||||
REQUIRE(j["materials"][0].is_object());
|
REQUIRE(j["materials"][0].is_object());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("empty-skeleton-id", "[issue-321]") {
|
||||||
|
|
||||||
|
tinygltf::Model model;
|
||||||
|
tinygltf::TinyGLTF ctx;
|
||||||
|
std::string err;
|
||||||
|
std::string warn;
|
||||||
|
|
||||||
|
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/regression/unassigned-skeleton.gltf");
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
|
||||||
|
REQUIRE(model.skins.size() == 1);
|
||||||
|
REQUIRE(model.skins[0].skeleton == -1); // unassigned
|
||||||
|
|
||||||
|
std::stringstream os;
|
||||||
|
|
||||||
|
ctx.WriteGltfSceneToStream(&model, os, false, false);
|
||||||
|
|
||||||
|
// use nlohmann json
|
||||||
|
nlohmann::json j = nlohmann::json::parse(os.str());
|
||||||
|
|
||||||
|
// Ensure `skeleton` property is not written to .gltf(was serialized as -1)
|
||||||
|
REQUIRE(1 == j["skins"].size());
|
||||||
|
REQUIRE(j["skins"][0].is_object());
|
||||||
|
REQUIRE(j["skins"][0].count("skeleton") == 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef TINYGLTF_NO_FS
|
#ifndef TINYGLTF_NO_FS
|
||||||
TEST_CASE("expandpath-utf-8", "[pr-226]") {
|
TEST_CASE("expandpath-utf-8", "[pr-226]") {
|
||||||
|
|
||||||
|
|||||||
4
tiny_gltf.cc
Normal file
4
tiny_gltf.cc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include "tiny_gltf.h"
|
||||||
313
tiny_gltf.h
313
tiny_gltf.h
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2015 - 2020 Syoyo Fujita, Aurélien Chatelain and many
|
// Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many
|
||||||
// contributors.
|
// contributors.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@@ -26,7 +26,9 @@
|
|||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
// Version:
|
// Version:
|
||||||
// - v2.4.3 Fix null object output when when material has all default parameters.
|
// - v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
|
||||||
|
// - v2.4.3 Fix null object output when when material has all default
|
||||||
|
// parameters.
|
||||||
// - v2.4.2 Decode percent-encoded URI.
|
// - v2.4.2 Decode percent-encoded URI.
|
||||||
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
|
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
|
||||||
// `extras` property.
|
// `extras` property.
|
||||||
@@ -189,14 +191,14 @@ AAssetManager *asset_manager = nullptr;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NULL_TYPE = 0,
|
NULL_TYPE,
|
||||||
REAL_TYPE = 1,
|
REAL_TYPE,
|
||||||
INT_TYPE = 2,
|
INT_TYPE,
|
||||||
BOOL_TYPE = 3,
|
BOOL_TYPE,
|
||||||
STRING_TYPE = 4,
|
STRING_TYPE,
|
||||||
ARRAY_TYPE = 5,
|
ARRAY_TYPE,
|
||||||
BINARY_TYPE = 6,
|
BINARY_TYPE,
|
||||||
OBJECT_TYPE = 7
|
OBJECT_TYPE
|
||||||
} Type;
|
} Type;
|
||||||
|
|
||||||
static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
|
static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
|
||||||
@@ -251,7 +253,6 @@ bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
// Suppress warning for : static Value null_value
|
// Suppress warning for : static Value null_value
|
||||||
// https://stackoverflow.com/questions/15708411/how-to-deal-with-global-constructor-warning-in-clang
|
|
||||||
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
#pragma clang diagnostic ignored "-Wpadded"
|
#pragma clang diagnostic ignored "-Wpadded"
|
||||||
#endif
|
#endif
|
||||||
@@ -296,7 +297,7 @@ class Value {
|
|||||||
|
|
||||||
DEFAULT_METHODS(Value)
|
DEFAULT_METHODS(Value)
|
||||||
|
|
||||||
char Type() const { return static_cast<const char>(type_); }
|
char Type() const { return static_cast<char>(type_); }
|
||||||
|
|
||||||
bool IsBool() const { return (type_ == BOOL_TYPE); }
|
bool IsBool() const { return (type_ == BOOL_TYPE); }
|
||||||
|
|
||||||
@@ -602,7 +603,7 @@ struct Sampler {
|
|||||||
// `magFilter`. Set -1 in TinyGLTF(issue #186)
|
// `magFilter`. Set -1 in TinyGLTF(issue #186)
|
||||||
int minFilter =
|
int minFilter =
|
||||||
-1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR",
|
-1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR",
|
||||||
// "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_NEAREST",
|
// "NEAREST_MIPMAP_NEAREST", "LINEAR_MIPMAP_NEAREST",
|
||||||
// "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_LINEAR"]
|
// "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_LINEAR"]
|
||||||
int magFilter =
|
int magFilter =
|
||||||
-1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR"]
|
-1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR"]
|
||||||
@@ -612,7 +613,7 @@ struct Sampler {
|
|||||||
int wrapT =
|
int wrapT =
|
||||||
TINYGLTF_TEXTURE_WRAP_REPEAT; // ["CLAMP_TO_EDGE", "MIRRORED_REPEAT",
|
TINYGLTF_TEXTURE_WRAP_REPEAT; // ["CLAMP_TO_EDGE", "MIRRORED_REPEAT",
|
||||||
// "REPEAT"], default "REPEAT"
|
// "REPEAT"], default "REPEAT"
|
||||||
int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension
|
//int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension. currently not used.
|
||||||
|
|
||||||
Value extras;
|
Value extras;
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
@@ -625,8 +626,7 @@ struct Sampler {
|
|||||||
: minFilter(-1),
|
: minFilter(-1),
|
||||||
magFilter(-1),
|
magFilter(-1),
|
||||||
wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
|
wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
|
||||||
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT),
|
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
|
||||||
wrapR(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
|
|
||||||
DEFAULT_METHODS(Sampler)
|
DEFAULT_METHODS(Sampler)
|
||||||
bool operator==(const Sampler &) const;
|
bool operator==(const Sampler &) const;
|
||||||
};
|
};
|
||||||
@@ -849,8 +849,10 @@ struct Accessor {
|
|||||||
std::string extras_json_string;
|
std::string extras_json_string;
|
||||||
std::string extensions_json_string;
|
std::string extensions_json_string;
|
||||||
|
|
||||||
std::vector<double> minValues; // optional
|
std::vector<double>
|
||||||
std::vector<double> maxValues; // optional
|
minValues; // optional. integer value is promoted to double
|
||||||
|
std::vector<double>
|
||||||
|
maxValues; // optional. integer value is promoted to double
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int count;
|
int count;
|
||||||
@@ -1068,7 +1070,7 @@ struct Buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Asset {
|
struct Asset {
|
||||||
std::string version; // required
|
std::string version = "2.0"; // required
|
||||||
std::string generator;
|
std::string generator;
|
||||||
std::string minVersion;
|
std::string minVersion;
|
||||||
std::string copyright;
|
std::string copyright;
|
||||||
@@ -1190,7 +1192,8 @@ enum SectionCheck {
|
|||||||
///
|
///
|
||||||
typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
|
typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
|
||||||
std::string *, int, int,
|
std::string *, int, int,
|
||||||
const unsigned char *, int, void *);
|
const unsigned char *, int,
|
||||||
|
void *user_pointer);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
|
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
|
||||||
@@ -1255,7 +1258,7 @@ bool FileExists(const std::string &abs_filename, void *);
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to
|
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to
|
||||||
/// `C:\Users\tinygltf\AppData`)
|
/// `C:\\Users\\tinygltf\\AppData`)
|
||||||
///
|
///
|
||||||
/// @param[in] filepath File path string. Assume UTF-8
|
/// @param[in] filepath File path string. Assume UTF-8
|
||||||
/// @param[in] userdata User data. Set to `nullptr` if you don't need it.
|
/// @param[in] userdata User data. Set to `nullptr` if you don't need it.
|
||||||
@@ -1346,6 +1349,11 @@ class TinyGLTF {
|
|||||||
///
|
///
|
||||||
void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data);
|
void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Unset(remove) callback of loading image data
|
||||||
|
///
|
||||||
|
void RemoveImageLoader();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Set callback to use for writing image data
|
/// Set callback to use for writing image data
|
||||||
///
|
///
|
||||||
@@ -1384,6 +1392,16 @@ class TinyGLTF {
|
|||||||
return store_original_json_for_extras_and_extensions_;
|
return store_original_json_for_extras_and_extensions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Specify whether preserve image channales when loading images or not.
|
||||||
|
/// (Not effective when the user suppy their own LoadImageData callbacks)
|
||||||
|
///
|
||||||
|
void SetPreserveImageChannels(bool onoff) {
|
||||||
|
preserve_image_channels_ = onoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetPreserveImageChannels() const { return preserve_image_channels_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///
|
///
|
||||||
/// Loads glTF asset from string(memory).
|
/// Loads glTF asset from string(memory).
|
||||||
@@ -1403,6 +1421,9 @@ class TinyGLTF {
|
|||||||
|
|
||||||
bool store_original_json_for_extras_and_extensions_ = false;
|
bool store_original_json_for_extras_and_extensions_ = false;
|
||||||
|
|
||||||
|
bool preserve_image_channels_ = false; /// Default false(expand channels to
|
||||||
|
/// RGBA) for backward compatibility.
|
||||||
|
|
||||||
FsCallbacks fs = {
|
FsCallbacks fs = {
|
||||||
#ifndef TINYGLTF_NO_FS
|
#ifndef TINYGLTF_NO_FS
|
||||||
&tinygltf::FileExists, &tinygltf::ExpandFilePath,
|
&tinygltf::FileExists, &tinygltf::ExpandFilePath,
|
||||||
@@ -1422,7 +1443,8 @@ class TinyGLTF {
|
|||||||
#else
|
#else
|
||||||
nullptr;
|
nullptr;
|
||||||
#endif
|
#endif
|
||||||
void *load_image_user_data_ = reinterpret_cast<void *>(&fs);
|
void *load_image_user_data_{nullptr};
|
||||||
|
bool user_image_loader_{false};
|
||||||
|
|
||||||
WriteImageDataFunction WriteImageData =
|
WriteImageDataFunction WriteImageData =
|
||||||
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
||||||
@@ -1430,7 +1452,7 @@ class TinyGLTF {
|
|||||||
#else
|
#else
|
||||||
nullptr;
|
nullptr;
|
||||||
#endif
|
#endif
|
||||||
void *write_image_user_data_ = reinterpret_cast<void *>(&fs);
|
void *write_image_user_data_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@@ -1515,6 +1537,7 @@ class TinyGLTF {
|
|||||||
#ifndef TINYGLTF_USE_RAPIDJSON
|
#ifndef TINYGLTF_USE_RAPIDJSON
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#else
|
#else
|
||||||
|
#ifndef TINYGLTF_NO_INCLUDE_RAPIDJSON
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "prettywriter.h"
|
#include "prettywriter.h"
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
@@ -1522,6 +1545,7 @@ class TinyGLTF {
|
|||||||
#include "writer.h"
|
#include "writer.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TINYGLTF_ENABLE_DRACO
|
#ifdef TINYGLTF_ENABLE_DRACO
|
||||||
#include "draco/compression/decode.h"
|
#include "draco/compression/decode.h"
|
||||||
@@ -1580,7 +1604,7 @@ class TinyGLTF {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif !defined(__ANDROID__)
|
#elif !defined(__ANDROID__) && !defined(__OpenBSD__)
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1684,6 +1708,19 @@ void JsonParse(JsonDocument &doc, const char *str, size_t length,
|
|||||||
|
|
||||||
namespace tinygltf {
|
namespace tinygltf {
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Internal LoadImageDataOption struct.
|
||||||
|
/// This struct is passed through `user_pointer` in LoadImageData.
|
||||||
|
/// The struct is not passed when the user supply their own LoadImageData
|
||||||
|
/// callbacks.
|
||||||
|
///
|
||||||
|
struct LoadImageDataOption {
|
||||||
|
// true: preserve image channels(e.g. load as RGB image if the image has RGB
|
||||||
|
// channels) default `false`(channels are expanded to RGBA for backward
|
||||||
|
// compatiblity).
|
||||||
|
bool preserve_channels{false};
|
||||||
|
};
|
||||||
|
|
||||||
// Equals function for Value, for recursivity
|
// Equals function for Value, for recursivity
|
||||||
static bool Equals(const tinygltf::Value &one, const tinygltf::Value &other) {
|
static bool Equals(const tinygltf::Value &one, const tinygltf::Value &other) {
|
||||||
if (one.Type() != other.Type()) return false;
|
if (one.Type() != other.Type()) return false;
|
||||||
@@ -1896,8 +1933,9 @@ bool Sampler::operator==(const Sampler &other) const {
|
|||||||
return this->extensions == other.extensions && this->extras == other.extras &&
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
this->magFilter == other.magFilter &&
|
this->magFilter == other.magFilter &&
|
||||||
this->minFilter == other.minFilter && this->name == other.name &&
|
this->minFilter == other.minFilter && this->name == other.name &&
|
||||||
this->wrapR == other.wrapR && this->wrapS == other.wrapS &&
|
|
||||||
this->wrapT == other.wrapT;
|
this->wrapT == other.wrapT;
|
||||||
|
|
||||||
|
//this->wrapR == other.wrapR && this->wrapS == other.wrapS &&
|
||||||
}
|
}
|
||||||
bool Scene::operator==(const Scene &other) const {
|
bool Scene::operator==(const Scene &other) const {
|
||||||
return this->extensions == other.extensions && this->extras == other.extras &&
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
||||||
@@ -2001,9 +2039,12 @@ static std::string GetBaseDir(const std::string &filepath) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/8520560/get-a-file-name-from-a-path
|
|
||||||
static std::string GetBaseFilename(const std::string &filepath) {
|
static std::string GetBaseFilename(const std::string &filepath) {
|
||||||
return filepath.substr(filepath.find_last_of("/\\") + 1);
|
constexpr char path_separators[2] = { '/', '\\' };
|
||||||
|
auto idx = filepath.find_last_of(path_separators);
|
||||||
|
if (idx != std::string::npos)
|
||||||
|
return filepath.substr(idx + 1);
|
||||||
|
return filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string base64_encode(unsigned char const *, unsigned int len);
|
std::string base64_encode(unsigned char const *, unsigned int len);
|
||||||
@@ -2149,47 +2190,35 @@ std::string base64_decode(std::string const &encoded_string) {
|
|||||||
// TODO(syoyo): Use uriparser https://uriparser.github.io/ for stricter Uri
|
// TODO(syoyo): Use uriparser https://uriparser.github.io/ for stricter Uri
|
||||||
// decoding?
|
// decoding?
|
||||||
//
|
//
|
||||||
// https://stackoverflow.com/questions/18307429/encode-decode-url-in-c
|
// Uri Decoding from DLIB
|
||||||
// http://dlib.net/dlib/server/server_http.cpp.html
|
// http://dlib.net/dlib/server/server_http.cpp.html
|
||||||
|
// --- dlib begin ------------------------------------------------------------
|
||||||
// --- dlib beign ------------------------------------------------------------
|
|
||||||
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
||||||
// License: Boost Software License See LICENSE.txt for the full license.
|
// License: Boost Software License
|
||||||
|
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
// obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
// this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
// execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
// Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
// do so, all subject to the following:
|
||||||
|
// The copyright notices in the Software and this entire statement, including
|
||||||
|
// the above license grant, this restriction and the following disclaimer,
|
||||||
|
// must be included in all copies of the Software, in whole or in part, and
|
||||||
|
// all derivative works of the Software, unless such copies or derivative
|
||||||
|
// works are solely in the form of machine-executable object code generated by
|
||||||
|
// a source language processor.
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
namespace dlib {
|
namespace dlib {
|
||||||
|
|
||||||
#if 0
|
|
||||||
inline unsigned char to_hex( unsigned char x )
|
|
||||||
{
|
|
||||||
return x + (x > 9 ? ('A'-10) : '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string urlencode( const std::string& s )
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
|
|
||||||
for ( std::string::const_iterator ci = s.begin(); ci != s.end(); ++ci )
|
|
||||||
{
|
|
||||||
if ( (*ci >= 'a' && *ci <= 'z') ||
|
|
||||||
(*ci >= 'A' && *ci <= 'Z') ||
|
|
||||||
(*ci >= '0' && *ci <= '9') )
|
|
||||||
{ // allowed
|
|
||||||
os << *ci;
|
|
||||||
}
|
|
||||||
else if ( *ci == ' ')
|
|
||||||
{
|
|
||||||
os << '+';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
os << '%' << to_hex(static_cast<unsigned char>(*ci >> 4)) << to_hex(static_cast<unsigned char>(*ci % 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline unsigned char from_hex(unsigned char ch) {
|
inline unsigned char from_hex(unsigned char ch) {
|
||||||
if (ch <= '9' && ch >= '0')
|
if (ch <= '9' && ch >= '0')
|
||||||
ch -= '0';
|
ch -= '0';
|
||||||
@@ -2298,22 +2327,40 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
|||||||
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
||||||
LoadImageData = func;
|
LoadImageData = func;
|
||||||
load_image_user_data_ = user_data;
|
load_image_user_data_ = user_data;
|
||||||
|
user_image_loader_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TinyGLTF::RemoveImageLoader() {
|
||||||
|
LoadImageData =
|
||||||
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||||
|
&tinygltf::LoadImageData;
|
||||||
|
#else
|
||||||
|
nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
load_image_user_data_ = nullptr;
|
||||||
|
user_image_loader_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TINYGLTF_NO_STB_IMAGE
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||||
bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
||||||
std::string *warn, int req_width, int req_height,
|
std::string *warn, int req_width, int req_height,
|
||||||
const unsigned char *bytes, int size, void *user_data) {
|
const unsigned char *bytes, int size, void *user_data) {
|
||||||
(void)user_data;
|
|
||||||
(void)warn;
|
(void)warn;
|
||||||
|
|
||||||
|
LoadImageDataOption option;
|
||||||
|
if (user_data) {
|
||||||
|
option = *reinterpret_cast<LoadImageDataOption *>(user_data);
|
||||||
|
}
|
||||||
|
|
||||||
int w = 0, h = 0, comp = 0, req_comp = 0;
|
int w = 0, h = 0, comp = 0, req_comp = 0;
|
||||||
|
|
||||||
unsigned char *data = nullptr;
|
unsigned char *data = nullptr;
|
||||||
|
|
||||||
// force 32-bit textures for common Vulkan compatibility. It appears that
|
// preserve_channels true: Use channels stored in the image file.
|
||||||
// some GPU drivers do not support 24-bit images for Vulkan
|
// false: force 32-bit textures for common Vulkan compatibility. It appears
|
||||||
req_comp = 4;
|
// that some GPU drivers do not support 24-bit images for Vulkan
|
||||||
|
req_comp = option.preserve_channels ? 0 : 4;
|
||||||
int bits = 8;
|
int bits = 8;
|
||||||
int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||||
|
|
||||||
@@ -2385,13 +2432,18 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req_comp != 0) {
|
||||||
|
// loaded data has `req_comp` channels(components)
|
||||||
|
comp = req_comp;
|
||||||
|
}
|
||||||
|
|
||||||
image->width = w;
|
image->width = w;
|
||||||
image->height = h;
|
image->height = h;
|
||||||
image->component = req_comp;
|
image->component = comp;
|
||||||
image->bits = bits;
|
image->bits = bits;
|
||||||
image->pixel_type = pixel_type;
|
image->pixel_type = pixel_type;
|
||||||
image->image.resize(static_cast<size_t>(w * h * req_comp) * size_t(bits / 8));
|
image->image.resize(static_cast<size_t>(w * h * comp) * size_t(bits / 8));
|
||||||
std::copy(data, data + w * h * req_comp * (bits / 8), image->image.begin());
|
std::copy(data, data + w * h * comp * (bits / 8), image->image.begin());
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -2567,7 +2619,7 @@ std::string ExpandFilePath(const std::string &filepath, void *) {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \
|
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \
|
||||||
defined(__ANDROID__) || defined(__EMSCRIPTEN__)
|
defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__OpenBSD__)
|
||||||
// no expansion
|
// no expansion
|
||||||
std::string s = filepath;
|
std::string s = filepath;
|
||||||
#else
|
#else
|
||||||
@@ -3140,6 +3192,7 @@ static bool ParseJsonAsValue(Value *ret, const json &o) {
|
|||||||
break;
|
break;
|
||||||
case json::value_t::null:
|
case json::value_t::null:
|
||||||
case json::value_t::discarded:
|
case json::value_t::discarded:
|
||||||
|
case json::value_t::binary:
|
||||||
// default:
|
// default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4410,6 +4463,7 @@ static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
|
|||||||
static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
||||||
std::string *err,
|
std::string *err,
|
||||||
const Value &dracoExtensionValue) {
|
const Value &dracoExtensionValue) {
|
||||||
|
(void)err;
|
||||||
auto bufferViewValue = dracoExtensionValue.Get("bufferView");
|
auto bufferViewValue = dracoExtensionValue.Get("bufferView");
|
||||||
if (!bufferViewValue.IsInt()) return false;
|
if (!bufferViewValue.IsInt()) return false;
|
||||||
auto attributesValue = dracoExtensionValue.Get("attributes");
|
auto attributesValue = dracoExtensionValue.Get("attributes");
|
||||||
@@ -4470,7 +4524,6 @@ static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
|||||||
|
|
||||||
int dracoAttributeIndex = attribute.second.Get<int>();
|
int dracoAttributeIndex = attribute.second.Get<int>();
|
||||||
const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
|
const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
|
||||||
const auto pBuffer = pAttribute->buffer();
|
|
||||||
const auto componentType =
|
const auto componentType =
|
||||||
model->accessors[primitiveAttribute->second].componentType;
|
model->accessors[primitiveAttribute->second].componentType;
|
||||||
|
|
||||||
@@ -5029,12 +5082,12 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
|
|||||||
int magFilter = -1;
|
int magFilter = -1;
|
||||||
int wrapS = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
int wrapS = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
||||||
int wrapT = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
int wrapT = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
||||||
int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
//int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
||||||
ParseIntegerProperty(&minFilter, err, o, "minFilter", false);
|
ParseIntegerProperty(&minFilter, err, o, "minFilter", false);
|
||||||
ParseIntegerProperty(&magFilter, err, o, "magFilter", false);
|
ParseIntegerProperty(&magFilter, err, o, "magFilter", false);
|
||||||
ParseIntegerProperty(&wrapS, err, o, "wrapS", false);
|
ParseIntegerProperty(&wrapS, err, o, "wrapS", false);
|
||||||
ParseIntegerProperty(&wrapT, err, o, "wrapT", false);
|
ParseIntegerProperty(&wrapT, err, o, "wrapT", false);
|
||||||
ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf extension
|
//ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf extension
|
||||||
|
|
||||||
// TODO(syoyo): Check the value is alloed one.
|
// TODO(syoyo): Check the value is alloed one.
|
||||||
// (e.g. we allow 9728(NEAREST), but don't allow 9727)
|
// (e.g. we allow 9728(NEAREST), but don't allow 9727)
|
||||||
@@ -5043,7 +5096,7 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
|
|||||||
sampler->magFilter = magFilter;
|
sampler->magFilter = magFilter;
|
||||||
sampler->wrapS = wrapS;
|
sampler->wrapS = wrapS;
|
||||||
sampler->wrapT = wrapT;
|
sampler->wrapT = wrapT;
|
||||||
sampler->wrapR = wrapR;
|
//sampler->wrapR = wrapR;
|
||||||
|
|
||||||
ParseExtensionsProperty(&(sampler->extensions), err, o);
|
ParseExtensionsProperty(&(sampler->extensions), err, o);
|
||||||
ParseExtrasProperty(&(sampler->extras), o);
|
ParseExtrasProperty(&(sampler->extras), o);
|
||||||
@@ -5770,13 +5823,13 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|||||||
{
|
{
|
||||||
json_const_iterator it;
|
json_const_iterator it;
|
||||||
if (FindMember(o, "extensions", it)) {
|
if (FindMember(o, "extensions", it)) {
|
||||||
model->extensions_json_string = JsonToString(GetValue(it));
|
scene.extensions_json_string = JsonToString(GetValue(it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json_const_iterator it;
|
json_const_iterator it;
|
||||||
if (FindMember(o, "extras", it)) {
|
if (FindMember(o, "extras", it)) {
|
||||||
model->extras_json_string = JsonToString(GetValue(it));
|
scene.extras_json_string = JsonToString(GetValue(it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5826,6 +5879,18 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 11. Parse Image
|
// 11. Parse Image
|
||||||
|
void *load_image_user_data{nullptr};
|
||||||
|
|
||||||
|
LoadImageDataOption load_image_option;
|
||||||
|
|
||||||
|
if (user_image_loader_) {
|
||||||
|
// Use user supplied pointer
|
||||||
|
load_image_user_data = load_image_user_data_;
|
||||||
|
} else {
|
||||||
|
load_image_option.preserve_channels = preserve_image_channels_;
|
||||||
|
load_image_user_data = reinterpret_cast<void *>(&load_image_option);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
bool success = ForEachInArray(v, "images", [&](const json &o) {
|
bool success = ForEachInArray(v, "images", [&](const json &o) {
|
||||||
@@ -5838,7 +5903,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|||||||
Image image;
|
Image image;
|
||||||
if (!ParseImage(&image, idx, err, warn, o,
|
if (!ParseImage(&image, idx, err, warn, o,
|
||||||
store_original_json_for_extras_and_extensions_, base_dir,
|
store_original_json_for_extras_and_extensions_, base_dir,
|
||||||
&fs, &this->LoadImageData, load_image_user_data_)) {
|
&fs, &this->LoadImageData, load_image_user_data)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5876,7 +5941,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|||||||
bool ret = LoadImageData(
|
bool ret = LoadImageData(
|
||||||
&image, idx, err, warn, image.width, image.height,
|
&image, idx, err, warn, image.width, image.height,
|
||||||
&buffer.data[bufferView.byteOffset],
|
&buffer.data[bufferView.byteOffset],
|
||||||
static_cast<int>(bufferView.byteLength), load_image_user_data_);
|
static_cast<int>(bufferView.byteLength), load_image_user_data);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -6552,8 +6617,33 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) {
|
|||||||
|
|
||||||
SerializeNumberProperty<int>("componentType", accessor.componentType, o);
|
SerializeNumberProperty<int>("componentType", accessor.componentType, o);
|
||||||
SerializeNumberProperty<size_t>("count", accessor.count, o);
|
SerializeNumberProperty<size_t>("count", accessor.count, o);
|
||||||
SerializeNumberArrayProperty<double>("min", accessor.minValues, o);
|
|
||||||
SerializeNumberArrayProperty<double>("max", accessor.maxValues, o);
|
if ((accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) ||
|
||||||
|
(accessor.componentType == TINYGLTF_COMPONENT_TYPE_DOUBLE)) {
|
||||||
|
SerializeNumberArrayProperty<double>("min", accessor.minValues, o);
|
||||||
|
SerializeNumberArrayProperty<double>("max", accessor.maxValues, o);
|
||||||
|
} else {
|
||||||
|
// Issue #301. Serialize as integer.
|
||||||
|
// Assume int value is within [-2**31-1, 2**31-1]
|
||||||
|
{
|
||||||
|
std::vector<int> values;
|
||||||
|
std::transform(accessor.minValues.begin(), accessor.minValues.end(),
|
||||||
|
std::back_inserter(values),
|
||||||
|
[](double v) { return static_cast<int>(v); });
|
||||||
|
|
||||||
|
SerializeNumberArrayProperty<int>("min", values, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::vector<int> values;
|
||||||
|
std::transform(accessor.maxValues.begin(), accessor.maxValues.end(),
|
||||||
|
std::back_inserter(values),
|
||||||
|
[](double v) { return static_cast<int>(v); });
|
||||||
|
|
||||||
|
SerializeNumberArrayProperty<int>("max", values, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (accessor.normalized)
|
if (accessor.normalized)
|
||||||
SerializeValue("normalized", Value(accessor.normalized), o);
|
SerializeValue("normalized", Value(accessor.normalized), o);
|
||||||
std::string type;
|
std::string type;
|
||||||
@@ -6663,10 +6753,15 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
|
|||||||
SerializeStringProperty("copyright", asset.copyright, o);
|
SerializeStringProperty("copyright", asset.copyright, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asset.version.empty()) {
|
if (asset.version.empty()) {
|
||||||
SerializeStringProperty("version", asset.version, o);
|
// Just in case
|
||||||
|
// `version` must be defined
|
||||||
|
asset.version = "2.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(syoyo): Do we need to check if `version` is greater or equal to 2.0?
|
||||||
|
SerializeStringProperty("version", asset.version, o);
|
||||||
|
|
||||||
if (asset.extras.Keys().size()) {
|
if (asset.extras.Keys().size()) {
|
||||||
SerializeValue("extras", asset.extras, o);
|
SerializeValue("extras", asset.extras, o);
|
||||||
}
|
}
|
||||||
@@ -7064,7 +7159,7 @@ static void SerializeGltfSampler(Sampler &sampler, json &o) {
|
|||||||
if (sampler.minFilter != -1) {
|
if (sampler.minFilter != -1) {
|
||||||
SerializeNumberProperty("minFilter", sampler.minFilter, o);
|
SerializeNumberProperty("minFilter", sampler.minFilter, o);
|
||||||
}
|
}
|
||||||
SerializeNumberProperty("wrapR", sampler.wrapR, o);
|
//SerializeNumberProperty("wrapR", sampler.wrapR, o);
|
||||||
SerializeNumberProperty("wrapS", sampler.wrapS, o);
|
SerializeNumberProperty("wrapS", sampler.wrapS, o);
|
||||||
SerializeNumberProperty("wrapT", sampler.wrapT, o);
|
SerializeNumberProperty("wrapT", sampler.wrapT, o);
|
||||||
|
|
||||||
@@ -7139,11 +7234,17 @@ static void SerializeGltfScene(Scene &scene, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfSkin(Skin &skin, json &o) {
|
static void SerializeGltfSkin(Skin &skin, json &o) {
|
||||||
if (skin.inverseBindMatrices != -1)
|
// required
|
||||||
SerializeNumberProperty("inverseBindMatrices", skin.inverseBindMatrices, o);
|
|
||||||
|
|
||||||
SerializeNumberArrayProperty<int>("joints", skin.joints, o);
|
SerializeNumberArrayProperty<int>("joints", skin.joints, o);
|
||||||
SerializeNumberProperty("skeleton", skin.skeleton, o);
|
|
||||||
|
if (skin.inverseBindMatrices >= 0) {
|
||||||
|
SerializeNumberProperty("inverseBindMatrices", skin.inverseBindMatrices, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skin.skeleton >= 0) {
|
||||||
|
SerializeNumberProperty("skeleton", skin.skeleton, o);
|
||||||
|
}
|
||||||
|
|
||||||
if (skin.name.size()) {
|
if (skin.name.size()) {
|
||||||
SerializeStringProperty("name", skin.name, o);
|
SerializeStringProperty("name", skin.name, o);
|
||||||
}
|
}
|
||||||
@@ -7230,7 +7331,8 @@ static void SerializeGltfModel(Model *model, json &o) {
|
|||||||
if (JsonIsNull(material)) {
|
if (JsonIsNull(material)) {
|
||||||
// Issue 294.
|
// Issue 294.
|
||||||
// `material` does not have any required parameters
|
// `material` does not have any required parameters
|
||||||
// so the result may be null(unmodified) when all material parameters have default value.
|
// so the result may be null(unmodified) when all material parameters
|
||||||
|
// have default value.
|
||||||
//
|
//
|
||||||
// null is not allowed thus we create an empty JSON object.
|
// null is not allowed thus we create an empty JSON object.
|
||||||
JsonSetObject(material);
|
JsonSetObject(material);
|
||||||
@@ -7373,7 +7475,7 @@ static void SerializeGltfModel(Model *model, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extensions used
|
// Extensions used
|
||||||
if (model->extensionsUsed.size()) {
|
if (extensionsUsed.size()) {
|
||||||
SerializeStringArrayProperty("extensionsUsed", extensionsUsed, o);
|
SerializeStringArrayProperty("extensionsUsed", extensionsUsed, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7417,31 +7519,24 @@ static void WriteBinaryGltfStream(std::ostream &stream,
|
|||||||
const std::string header = "glTF";
|
const std::string header = "glTF";
|
||||||
const int version = 2;
|
const int version = 2;
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number
|
const uint32_t content_size = uint32_t(content.size());
|
||||||
auto roundUp = [](uint32_t numToRound, uint32_t multiple) {
|
const uint32_t binBuffer_size = uint32_t(binBuffer.size());
|
||||||
if (multiple == 0) return numToRound;
|
// determine number of padding bytes required to ensure 4 byte alignment
|
||||||
|
const uint32_t content_padding_size = content_size % 4 == 0 ? 0 : 4 - content_size % 4;
|
||||||
uint32_t remainder = numToRound % multiple;
|
const uint32_t bin_padding_size = binBuffer_size % 4 == 0 ? 0 : 4 - binBuffer_size % 4;
|
||||||
if (remainder == 0) return numToRound;
|
|
||||||
|
|
||||||
return numToRound + multiple - remainder;
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32_t padding_size =
|
|
||||||
roundUp(uint32_t(content.size()), 4) - uint32_t(content.size());
|
|
||||||
|
|
||||||
// 12 bytes for header, JSON content length, 8 bytes for JSON chunk info.
|
// 12 bytes for header, JSON content length, 8 bytes for JSON chunk info.
|
||||||
// Chunk data must be located at 4-byte boundary.
|
// Chunk data must be located at 4-byte boundary, which may require padding
|
||||||
const uint32_t length =
|
const uint32_t length =
|
||||||
12 + 8 + roundUp(uint32_t(content.size()), 4) +
|
12 + 8 + content_size + content_padding_size +
|
||||||
(binBuffer.size() ? (8 + roundUp(uint32_t(binBuffer.size()), 4)) : 0);
|
(binBuffer_size ? (8 + binBuffer_size + bin_padding_size) : 0);
|
||||||
|
|
||||||
stream.write(header.c_str(), std::streamsize(header.size()));
|
stream.write(header.c_str(), std::streamsize(header.size()));
|
||||||
stream.write(reinterpret_cast<const char *>(&version), sizeof(version));
|
stream.write(reinterpret_cast<const char *>(&version), sizeof(version));
|
||||||
stream.write(reinterpret_cast<const char *>(&length), sizeof(length));
|
stream.write(reinterpret_cast<const char *>(&length), sizeof(length));
|
||||||
|
|
||||||
// JSON chunk info, then JSON data
|
// JSON chunk info, then JSON data
|
||||||
const uint32_t model_length = uint32_t(content.size()) + padding_size;
|
const uint32_t model_length = uint32_t(content.size()) + content_padding_size;
|
||||||
const uint32_t model_format = 0x4E4F534A;
|
const uint32_t model_format = 0x4E4F534A;
|
||||||
stream.write(reinterpret_cast<const char *>(&model_length),
|
stream.write(reinterpret_cast<const char *>(&model_length),
|
||||||
sizeof(model_length));
|
sizeof(model_length));
|
||||||
@@ -7450,13 +7545,11 @@ static void WriteBinaryGltfStream(std::ostream &stream,
|
|||||||
stream.write(content.c_str(), std::streamsize(content.size()));
|
stream.write(content.c_str(), std::streamsize(content.size()));
|
||||||
|
|
||||||
// Chunk must be multiplies of 4, so pad with spaces
|
// Chunk must be multiplies of 4, so pad with spaces
|
||||||
if (padding_size > 0) {
|
if (content_padding_size > 0) {
|
||||||
const std::string padding = std::string(size_t(padding_size), ' ');
|
const std::string padding = std::string(size_t(content_padding_size), ' ');
|
||||||
stream.write(padding.c_str(), std::streamsize(padding.size()));
|
stream.write(padding.c_str(), std::streamsize(padding.size()));
|
||||||
}
|
}
|
||||||
if (binBuffer.size() > 0) {
|
if (binBuffer.size() > 0) {
|
||||||
const uint32_t bin_padding_size =
|
|
||||||
roundUp(uint32_t(binBuffer.size()), 4) - uint32_t(binBuffer.size());
|
|
||||||
// BIN chunk info, then BIN data
|
// BIN chunk info, then BIN data
|
||||||
const uint32_t bin_length = uint32_t(binBuffer.size()) + bin_padding_size;
|
const uint32_t bin_length = uint32_t(binBuffer.size()) + bin_padding_size;
|
||||||
const uint32_t bin_format = 0x004e4942;
|
const uint32_t bin_format = 0x004e4942;
|
||||||
|
|||||||
Reference in New Issue
Block a user