Compare commits

...

22 Commits

Author SHA1 Message Date
Syoyo Fujita
584f1dfbe4 Merge branch 'release' of github.com:syoyo/tinygltf into release 2022-12-29 21:13:48 +09:00
Syoyo Fujita
a40ca4c5ab Merge pull request #393 from pknowlesnv/serialize_const
allow serializing a const Model
2022-12-29 21:00:24 +09:00
Pyarelal Knowles
de75d87cfd allow serializing a const Model
Adds 'const' to all Serialize*() methods.

Updates WriteImageData callback to take a URI out pointer that was
previously being written to the Image::uri, which is now const.

This breaks the WriteImageData API and as a side effect, Image::uri will
no longer contain the written image URI after saving.

Adds test serialize-const-image, which verifies the model's image is not
changed (because it's const), but the uri written to the gltf json is
still correct.

Adds test serialize-image-callback that defines a WriteImageDataFunction
and also verifies the uri can be overwritten.
2022-12-28 17:20:09 -08:00
Syoyo Fujita
cf11842e64 Merge pull request #395 from ethanpepro/cmake-export
Add CMake export configuration
2022-12-28 18:33:36 +09:00
James Luke
38003032e3 Add CMake export configuration 2022-12-27 21:12:54 -05:00
Syoyo Fujita
186016bf11 Merge branch 'release' of github.com:syoyo/tinygltf into release 2022-12-03 19:42:27 +09:00
Syoyo Fujita
5ee08f9274 Remove Python 2 description. 2022-12-03 19:40:50 +09:00
Syoyo Fujita
aa613a1f57 Update README.md
Remove Python 2.x description
2022-12-03 19:40:45 +09:00
Syoyo Fujita
222454cc6d Create FUNDING.yml 2022-12-03 18:33:05 +09:00
Syoyo Fujita
16c2d3a8bf Merge pull request #390 from eduardodoria/patch-1
Added Supernova Engine to Projects using TinyGLTF
2022-11-07 21:18:50 +09:00
Eduardo Doria
186093657a Added Supernova Engine to Projects using TinyGLTF 2022-11-07 08:53:47 -03:00
Syoyo Fujita
9bdd256625 Merge pull request #388 from stromaster/patch-1
Avoid multiple asset_manager definitions on Android
2022-10-31 17:40:40 +09:00
Serdar Kocdemir
264ae4c131 Avoid multiple asset_manager definition on Android
Using TINYGLTF_IMPLEMENTATION to make the actual definition of the 'asset_manager' global variable.
2022-10-30 22:32:59 +00:00
Syoyo Fujita
091a1fcc1a Merge pull request #386 from geometrian/master
Fix Clang Compile Warnings/Errors (and Typos)
2022-10-08 19:08:22 +09:00
imallett
3a295887d6 Patch to fix previous commit for MinGW. 2022-10-07 11:20:39 -07:00
imallett
d9ce9eb9d2 Fix a gazillion typos. 2022-10-07 10:37:09 -07:00
imallett
56e1098993 Fix various type mismatches and header include case (fixes compile warnings on Clang). 2022-10-07 10:35:16 -07:00
Syoyo Fujita
9bb5806df4 Merge pull request #385 from operatios/master
Fix UTF-8 filepath on LLVM MinGW
2022-09-25 05:35:36 +09:00
operatios
1668d1ecc5 Fix UTF-8 filepath on LLVM MinGW 2022-09-24 22:37:14 +03:00
Syoyo Fujita
6e8a858c45 Add WASI build procedure. 2022-09-22 04:36:58 +09:00
Syoyo Fujita
e0b625561c v2.6.3 2022-09-19 03:36:58 +09:00
Syoyo Fujita
18450eafe7 Merge pull request #382 from syoyo/glb-zero-chunk
Fix parsing GLB file with empty Chunk1(BIN data).
2022-09-19 03:34:09 +09:00
10 changed files with 265 additions and 125 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: syoyo
#patreon: # Replace with a single Patreon username
#open_collective: # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
#liberapay: # Replace with a single Liberapay username
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.6)
PROJECT (tinygltf)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
SET(CMAKE_CXX_STANDARD 11)
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example(load glTF and dump infos)" ON)
@@ -54,7 +57,10 @@ else (TINYGLTF_HEADER_ONLY)
endif (TINYGLTF_HEADER_ONLY)
if (TINYGLTF_INSTALL)
install(TARGETS tinygltf EXPORT tinygltfTargets)
install(EXPORT tinygltfTargets NAMESPACE tinygltf:: FILE TinyGLTFTargets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/TinyGLTFConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/TinyGLTFConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/TinyGLTFConfig.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
# Do not install .lib even if !TINYGLTF_HEADER_ONLY
INSTALL ( FILES
@@ -67,10 +73,4 @@ if (TINYGLTF_INSTALL)
include
)
INSTALL ( FILES
cmake/TinyGLTFConfig.cmake
DESTINATION
cmake
)
endif(TINYGLTF_INSTALL)

View File

@@ -86,6 +86,12 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [basic](examples/basic) : Basic glTF viewer with texturing support.
* [build-gltf](examples/build-gltf) : Build simple glTF scene from a scratch.
### WASI/WASM build
Users who want to run TinyGLTF securely and safely(e.g. need to handle malcious glTF file to serve online glTF conver),
I recommend to build TinyGLTF for WASM target.
WASI build example is located in [wasm](wasm) .
## Projects using TinyGLTF
* px_render Single header C++ Libraries for Thread Scheduling, Rendering, and so on... https://github.com/pplux/px
@@ -100,6 +106,7 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [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
* [Open3D](http://www.open3d.org/) - A Modern Library for 3D Data Processing
* [Supernova Engine](https://github.com/supernovaengine/supernova) - Game engine for 2D and 3D projects with Lua or C++ in data oriented design.
* Your projects here! (Please send PR)
## TODOs
@@ -222,7 +229,7 @@ add_subdirectory(/path/to/tinygltf)
#### Setup
Python 2.6 or 2.7 required.
Python required.
Git clone https://github.com/KhronosGroup/glTF-Sample-Models to your local dir.
#### Run parsing test

View File

@@ -1,15 +0,0 @@
# -*- cmake -*-
# - Find TinyGLTF
# TinyGLTF_INCLUDE_DIR TinyGLTF's include directory
FIND_PACKAGE ( PackageHandleStandardArgs )
SET ( TinyGLTF_INCLUDE_DIR "${TinyGLTF_DIR}/../include" CACHE STRING "TinyGLTF include directory")
FIND_FILE ( TinyGLTF_HEADER tiny_gltf.h PATHS ${TinyGLTF_INCLUDE_DIR} )
IF (NOT TinyGLTF_HEADER)
MESSAGE ( FATAL_ERROR "Unable to find tiny_gltf.h, TinyGLTF_INCLUDE_DIR = ${TinyGLTF_INCLUDE_DIR}")
ENDIF ()

View File

@@ -0,0 +1,3 @@
@PACKAGE_INIT@
include(${CMAKE_CURRENT_LIST_DIR}/TinyGLTFTargets.cmake)

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python
# Assume python 2.6 or 2.7
import glob
import os
import subprocess

View File

@@ -540,3 +540,66 @@ TEST_CASE("empty-bin-buffer", "[issue-382]") {
}
REQUIRE(true == ret);
}
TEST_CASE("serialize-const-image", "[issue-394]") {
tinygltf::Model m;
tinygltf::Image i;
i.width = 1;
i.height = 1;
i.component = 4;
i.bits = 8;
i.pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
i.image = {255, 255, 255, 255};
i.uri = "image.png";
m.images.push_back(i);
std::stringstream os;
tinygltf::TinyGLTF ctx;
ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
REQUIRE(m.images[0].uri == i.uri);
// use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str());
REQUIRE(1 == j["images"].size());
REQUIRE(j["images"][0].is_object());
REQUIRE(j["images"][0]["uri"].get<std::string>() != i.uri);
REQUIRE(j["images"][0]["uri"].get<std::string>().rfind("data:", 0) == 0);
}
TEST_CASE("serialize-image-callback", "[issue-394]") {
tinygltf::Model m;
tinygltf::Image i;
i.width = 1;
i.height = 1;
i.bits = 32;
i.image = {255, 255, 255, 255};
i.uri = "foo";
m.images.push_back(i);
std::stringstream os;
auto writer = [](const std::string *basepath, const std::string *filename,
const tinygltf::Image *image, bool embedImages,
std::string *out_uri, void *user_pointer) -> bool {
REQUIRE(*filename == "foo");
REQUIRE(embedImages == true);
REQUIRE(user_pointer == (void *)0xba5e1e55);
*out_uri = "bar";
return true;
};
tinygltf::TinyGLTF ctx;
ctx.SetImageWriter(writer, (void *)0xba5e1e55);
ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
// use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str());
REQUIRE(1 == j["images"].size());
REQUIRE(j["images"][0].is_object());
REQUIRE(j["images"][0]["uri"].get<std::string>() == "bar");
}

View File

@@ -26,12 +26,14 @@
// THE SOFTWARE.
// Version:
// - v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393.
// - v2.6.3 Fix GLB file with empty BIN chunk was not handled. PR#382 and PR#383.
// - v2.6.2 Fix out-of-bounds access of accessors. PR#379.
// - v2.6.1 Better GLB validation check when loading.
// - v2.6.0 Support serializing sparse accessor(Thanks to @fynv).
// Disable expanding file path for security(no use of awkward `wordexp` anymore).
// - 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
// - v2.4.3 Fix null object output when material has all default
// parameters.
// - v2.4.2 Decode percent-encoded URI.
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
@@ -45,7 +47,7 @@
// - v2.2.0 Add loading 16bit PNG support. Add Sparse accessor support(Thanks
// to @Ybalrid)
// - v2.1.0 Add draco compression.
// - v2.0.1 Add comparsion feature(Thanks to @Selmar).
// - v2.0.1 Add comparison feature(Thanks to @Selmar).
// - v2.0.0 glTF 2.0!.
//
// Tiny glTF loader is using following third party libraries:
@@ -199,7 +201,11 @@ namespace tinygltf {
#ifdef __ANDROID__
#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
#ifdef TINYGLTF_IMPLEMENTATION
AAssetManager *asset_manager = nullptr;
#else
extern AAssetManager *asset_manager;
#endif
#endif
#endif
@@ -232,7 +238,7 @@ static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
} else if (componentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) {
return 8;
} else {
// Unknown componenty type
// Unknown component type
return -1;
}
}
@@ -253,7 +259,7 @@ static inline int32_t GetNumComponentsInType(uint32_t ty) {
} else if (ty == TINYGLTF_TYPE_MAT4) {
return 16;
} else {
// Unknown componenty type
// Unknown component type
return -1;
}
}
@@ -440,7 +446,7 @@ TINYGLTF_VALUE_GET(Value::Object, object_value_)
#pragma clang diagnostic ignored "-Wpadded"
#endif
/// Agregate object for representing a color
/// Aggregate object for representing a color
using ColorValue = std::array<double, 4>;
// === legacy interface ====
@@ -477,7 +483,7 @@ struct Parameter {
if (it != std::end(json_double_value)) {
return int(it->second);
}
// As per the spec, if texCoord is ommited, this parameter is 0
// As per the spec, if texCoord is omitted, this parameter is 0
return 0;
}
@@ -489,7 +495,7 @@ struct Parameter {
if (it != std::end(json_double_value)) {
return it->second;
}
// As per the spec, if scale is ommited, this paramter is 1
// As per the spec, if scale is omitted, this parameter is 1
return 1;
}
@@ -501,7 +507,7 @@ struct Parameter {
if (it != std::end(json_double_value)) {
return it->second;
}
// As per the spec, if strenghth is ommited, this parameter is 1
// As per the spec, if strength is omitted, this parameter is 1
return 1;
}
@@ -515,7 +521,7 @@ struct Parameter {
/// material
ColorValue ColorFactor() const {
return {
{// this agregate intialize the std::array object, and uses C++11 RVO.
{// this aggregate initialize the std::array object, and uses C++11 RVO.
number_array[0], number_array[1], number_array[2],
(number_array.size() > 3 ? number_array[3] : 1.0)}};
}
@@ -826,7 +832,7 @@ struct BufferView {
size_t byteStride{0}; // minimum 4, maximum 252 (multiple of 4), default 0 =
// understood to be tightly packed
int target{0}; // ["ARRAY_BUFFER", "ELEMENT_ARRAY_BUFFER"] for vertex indices
// or atttribs. Could be 0 for other data
// or attribs. Could be 0 for other data
Value extras;
ExtensionMap extensions;
@@ -902,7 +908,7 @@ struct Accessor {
return componentSizeInBytes * numComponents;
} else {
// Check if byteStride is a mulple of the size of the accessor's component
// Check if byteStride is a multiple of the size of the accessor's component
// type.
int componentSizeInBytes =
GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
@@ -941,7 +947,7 @@ struct PerspectiveCamera {
PerspectiveCamera()
: aspectRatio(0.0),
yfov(0.0),
zfar(0.0) // 0 = use infinite projecton matrix
zfar(0.0) // 0 = use infinite projection matrix
,
znear(0.0) {}
DEFAULT_METHODS(PerspectiveCamera)
@@ -1002,7 +1008,7 @@ struct Primitive {
int indices; // The index of the accessor that contains the indices.
int mode; // one of TINYGLTF_MODE_***
std::vector<std::map<std::string, int> > targets; // array of morph targets,
// where each target is a dict with attribues in ["POSITION, "NORMAL",
// where each target is a dict with attributes in ["POSITION, "NORMAL",
// "TANGENT"] pointing
// to their corresponding accessors
ExtensionMap extensions;
@@ -1137,7 +1143,7 @@ struct Light {
std::vector<double> color;
double intensity{1.0};
std::string type;
double range{0.0}; // 0.0 = inifinite
double range{0.0}; // 0.0 = infinite
SpotLight spot;
Light() : intensity(1.0), range(0.0) {}
@@ -1211,9 +1217,13 @@ typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
///
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
/// The out_uri parameter becomes the URI written to the gltf and may reference
/// a file or contain a data URI.
///
typedef bool (*WriteImageDataFunction)(const std::string *, const std::string *,
Image *, bool, void *);
typedef bool (*WriteImageDataFunction)(const std::string *basepath,
const std::string *filename,
const Image *image, bool embedImages,
std::string *out_uri, void *user_pointer);
#ifndef TINYGLTF_NO_STB_IMAGE
// Declaration of default image loader callback
@@ -1225,7 +1235,8 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
// Declaration of default image writer callback
bool WriteImageData(const std::string *basepath, const std::string *filename,
Image *image, bool embedImages, void *);
const Image *image, bool embedImages, std::string *out_uri,
void *);
#endif
///
@@ -1287,7 +1298,7 @@ bool WriteWholeFile(std::string *err, const std::string &filepath,
#endif
///
/// glTF Parser/Serialier context.
/// glTF Parser/Serializer context.
///
class TinyGLTF {
public:
@@ -1350,15 +1361,15 @@ class TinyGLTF {
unsigned int check_sections = REQUIRE_VERSION);
///
/// Write glTF to stream, buffers and images will be embeded
/// Write glTF to stream, buffers and images will be embedded
///
bool WriteGltfSceneToStream(Model *model, std::ostream &stream,
bool WriteGltfSceneToStream(const Model *model, std::ostream &stream,
bool prettyPrint, bool writeBinary);
///
/// Write glTF to file.
///
bool WriteGltfSceneToFile(Model *model, const std::string &filename,
bool WriteGltfSceneToFile(const Model *model, const std::string &filename,
bool embedImages, bool embedBuffers,
bool prettyPrint, bool writeBinary);
@@ -1385,7 +1396,7 @@ class TinyGLTF {
///
/// Set serializing default values(default = false).
/// When true, default values are force serialized to .glTF.
/// This may be helpfull if you want to serialize a full description of glTF
/// This may be helpful if you want to serialize a full description of glTF
/// data.
///
/// TODO(LTE): Supply parsing option as function arguments to
@@ -1411,8 +1422,8 @@ class TinyGLTF {
}
///
/// Specify whether preserve image channales when loading images or not.
/// (Not effective when the user suppy their own LoadImageData callbacks)
/// Specify whether preserve image channels when loading images or not.
/// (Not effective when the user supplies their own LoadImageData callbacks)
///
void SetPreserveImageChannels(bool onoff) {
preserve_image_channels_ = onoff;
@@ -1549,7 +1560,7 @@ class TinyGLTF {
#endif
#endif
// Disable GCC warnigs
// Disable GCC warnings
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
@@ -1598,7 +1609,7 @@ class TinyGLTF {
// issue 143.
// Define NOMINMAX to avoid min/max defines,
// but undef it after included windows.h
// but undef it after included Windows.h
#ifndef NOMINMAX
#define TINYGLTF_INTERNAL_NOMINMAX
#define NOMINMAX
@@ -1608,7 +1619,11 @@ class TinyGLTF {
#define WIN32_LEAN_AND_MEAN
#define TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
#endif
#include <windows.h> // include API for expanding a file path
#ifndef __MINGW32__
#include <Windows.h> // include API for expanding a file path
#else
#include <windows.h>
#endif
#ifdef TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
@@ -1739,7 +1754,7 @@ namespace tinygltf {
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).
// compatibility).
bool preserve_channels{false};
};
@@ -2386,7 +2401,7 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
// It is possible that the image we want to load is a 16bit per channel image
// We are going to attempt to load it as 16bit per channel, and if it worked,
// set the image data accodingly. We are casting the returned pointer into
// set the image data accordingly. We are casting the returned pointer into
// unsigned char, because we are representing "bytes". But we are updating
// the Image metadata to signal that this image uses 2 bytes (16bits) per
// channel:
@@ -2401,7 +2416,7 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
// at this point, if data is still NULL, it means that the image wasn't
// 16bit per channel, we are going to load it as a normal 8bit per channel
// mage as we used to do:
// image as we used to do:
// if image cannot be decoded, ignore parsing and keep it by its path
// don't break in this case
// FIXME we should only enter this function if the image is embedded. If
@@ -2486,7 +2501,8 @@ static void WriteToMemory_stbi(void *context, void *data, int size) {
}
bool WriteImageData(const std::string *basepath, const std::string *filename,
Image *image, bool embedImages, void *fsPtr) {
const Image *image, bool embedImages, std::string *out_uri,
void *fsPtr) {
const std::string ext = GetFilePathExtension(*filename);
// Write image to temporary buffer
@@ -2528,9 +2544,8 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
if (embedImages) {
// Embed base64-encoded image into URI
if (data.size()) {
image->uri =
header +
base64_encode(&data[0], static_cast<unsigned int>(data.size()));
*out_uri = header +
base64_encode(&data[0], static_cast<unsigned int>(data.size()));
} else {
// Throw error?
}
@@ -2548,7 +2563,7 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
} else {
// Throw error?
}
image->uri = *filename;
*out_uri = *filename;
}
return true;
@@ -2561,7 +2576,7 @@ void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) { fs = callbacks; }
static inline std::wstring UTF8ToWchar(const std::string &str) {
int wstr_size =
MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0);
std::wstring wstr(wstr_size, 0);
std::wstring wstr((size_t)wstr_size, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &wstr[0],
(int)wstr.size());
return wstr;
@@ -2569,10 +2584,10 @@ static inline std::wstring UTF8ToWchar(const std::string &str) {
static inline std::string WcharToUTF8(const std::wstring &wstr) {
int str_size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(),
nullptr, 0, NULL, NULL);
std::string str(str_size, 0);
nullptr, 0, nullptr, nullptr);
std::string str((size_t)str_size, 0);
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), &str[0],
(int)str.size(), NULL, NULL);
(int)str.size(), nullptr, nullptr);
return str;
}
#endif
@@ -2596,7 +2611,7 @@ bool FileExists(const std::string &abs_filename, void *) {
}
#else
#ifdef _WIN32
#if defined(_MSC_VER) || defined(__GLIBCXX__)
#if defined(_MSC_VER) || defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
FILE *fp = nullptr;
errno_t err = _wfopen_s(&fp, UTF8ToWchar(abs_filename).c_str(), L"rb");
if (err != 0) {
@@ -2819,13 +2834,13 @@ static std::string MimeToExt(const std::string &mimeType) {
return "";
}
static void UpdateImageObject(Image &image, std::string &baseDir, int index,
bool embedImages,
WriteImageDataFunction *WriteImageData = nullptr,
void *user_data = nullptr) {
static void UpdateImageObject(const Image &image, std::string &baseDir,
int index, bool embedImages,
WriteImageDataFunction *WriteImageData,
std::string *out_uri, void *user_data) {
std::string filename;
std::string ext;
// If image has uri, use it it as a filename
// If image has uri, use it as a filename
if (image.uri.size()) {
filename = GetBaseFilename(image.uri);
ext = GetFilePathExtension(filename);
@@ -2843,9 +2858,15 @@ static void UpdateImageObject(Image &image, std::string &baseDir, int index,
}
// If callback is set, modify image data object
bool imageWritten = false;
if (*WriteImageData != nullptr && !filename.empty()) {
std::string uri;
(*WriteImageData)(&baseDir, &filename, &image, embedImages, user_data);
imageWritten = (*WriteImageData)(&baseDir, &filename, &image, embedImages,
out_uri, user_data);
}
// Use the original uri if the image was not written.
if (!imageWritten) {
*out_uri = image.uri;
}
}
@@ -4271,7 +4292,7 @@ static bool ParseSparseAccessor(Accessor *accessor, std::string *err,
}
if (!FindMember(o, "values", values_iterator)) {
(*err) = "the sparse object ob ths accessor doesn't have values";
(*err) = "the sparse object of this accessor doesn't have values";
return false;
}
@@ -4617,7 +4638,7 @@ static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
int mode = TINYGLTF_MODE_TRIANGLES;
ParseIntegerProperty(&mode, err, o, "mode", false);
primitive->mode = mode; // Why only triangled were supported ?
primitive->mode = mode; // Why only triangles were supported ?
int indices = -1;
ParseIntegerProperty(&indices, err, o, "indices", false);
@@ -4900,7 +4921,7 @@ static bool ParseMaterial(Material *material, std::string *err, const json &o,
// Old code path. For backward compatibility, we still store material values
// as Parameter. This will create duplicated information for
// example(pbrMetallicRoughness), but should be neglible in terms of memory
// example(pbrMetallicRoughness), but should be negligible in terms of memory
// consumption.
// TODO(syoyo): Remove in the next major release.
material->values.clear();
@@ -4933,7 +4954,7 @@ static bool ParseMaterial(Material *material, std::string *err, const json &o,
Parameter param;
if (ParseParameterProperty(&param, err, o, key, false)) {
// names of materials have already been parsed. Putting it in this map
// doesn't correctly reflext the glTF specification
// doesn't correctly reflect the glTF specification
if (key != "name")
material->additionalValues.emplace(std::move(key), std::move(param));
}
@@ -5139,7 +5160,7 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
// ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf
// extension
// TODO(syoyo): Check the value is alloed one.
// TODO(syoyo): Check the value is allowed one.
// (e.g. we allow 9728(NEAREST), but don't allow 9727)
sampler->minFilter = minFilter;
@@ -5348,7 +5369,7 @@ static bool ParseCamera(Camera *camera, std::string *err, const json &o,
if (!FindMember(o, "orthographic", orthoIt)) {
if (err) {
std::stringstream ss;
ss << "Orhographic camera description not found." << std::endl;
ss << "Orthographic camera description not found." << std::endl;
(*err) += ss.str();
}
return false;
@@ -5800,7 +5821,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
model->bufferViews[size_t(bufferView)].target =
TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
// we could optionally check if acessors' bufferView type is Scalar, as
// we could optionally check if accessors' bufferView type is Scalar, as
// it should be
}
@@ -5809,7 +5830,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
if (accessorsIndex < model->accessors.size()) {
const auto bufferView = model->accessors[accessorsIndex].bufferView;
// bufferView could be null(-1) for sparse morph target
if (bufferView >= 0 && bufferView < model->bufferViews.size()) {
if (bufferView >= 0 && bufferView < (int)model->bufferViews.size()) {
model->bufferViews[size_t(bufferView)].target =
TINYGLTF_TARGET_ARRAY_BUFFER;
}
@@ -5822,7 +5843,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
if (accessorsIndex < model->accessors.size()) {
const auto bufferView = model->accessors[accessorsIndex].bufferView;
// bufferView could be null(-1) for sparse morph target
if (bufferView >= 0 && bufferView < model->bufferViews.size()) {
if (bufferView >= 0 && bufferView < (int)model->bufferViews.size()) {
model->bufferViews[size_t(bufferView)].target =
TINYGLTF_TARGET_ARRAY_BUFFER;
}
@@ -6323,7 +6344,7 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
bin_size_ = 0;
} else {
// Read Chunk1 info(BIN data)
// At least Chunk1 should have 12 bytes(8 bytes(header) + 4 bytes(bin payload could be 1~3 bytes, but need to be aliged to 4 bytes)
// At least Chunk1 should have 12 bytes(8 bytes(header) + 4 bytes(bin payload could be 1~3 bytes, but need to be aligned to 4 bytes)
if ((header_and_json_size + 12ull) > uint64_t(length)) {
if (err) {
(*err) = "Insufficient storage space for Chunk1(BIN data). At least Chunk1 Must have 4 bytes or more bytes, but got " + std::to_string((header_and_json_size + 12ull) - uint64_t(length)) + ".\n";
@@ -6363,7 +6384,7 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
if (chunk1_format != 0x004e4942) {
if (err) {
(*err) = "Invlid type for chunk1 data.";
(*err) = "Invalid type for chunk1 data.";
}
return false;
}
@@ -6652,7 +6673,7 @@ static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
SerializeStringProperty("uri", header + encodedData, o);
} else {
// Issue #229
// size 0 is allowd. Just emit mime header.
// size 0 is allowed. Just emit mime header.
SerializeStringProperty("uri", header, o);
}
}
@@ -6746,7 +6767,7 @@ static void SerializeExtensionMap(const ExtensionMap &extensions, json &o) {
JsonAddMember(o, "extensions", std::move(extMap));
}
static void SerializeGltfAccessor(Accessor &accessor, json &o) {
static void SerializeGltfAccessor(const Accessor &accessor, json &o) {
if (accessor.bufferView >= 0)
SerializeNumberProperty<int>("bufferView", accessor.bufferView, o);
@@ -6838,7 +6859,8 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) {
}
}
static void SerializeGltfAnimationChannel(AnimationChannel &channel, json &o) {
static void SerializeGltfAnimationChannel(const AnimationChannel &channel,
json &o) {
SerializeNumberProperty("sampler", channel.sampler, o);
{
json target;
@@ -6857,7 +6879,8 @@ static void SerializeGltfAnimationChannel(AnimationChannel &channel, json &o) {
SerializeExtensionMap(channel.extensions, o);
}
static void SerializeGltfAnimationSampler(AnimationSampler &sampler, json &o) {
static void SerializeGltfAnimationSampler(const AnimationSampler &sampler,
json &o) {
SerializeNumberProperty("input", sampler.input, o);
SerializeNumberProperty("output", sampler.output, o);
SerializeStringProperty("interpolation", sampler.interpolation, o);
@@ -6867,7 +6890,7 @@ static void SerializeGltfAnimationSampler(AnimationSampler &sampler, json &o) {
}
}
static void SerializeGltfAnimation(Animation &animation, json &o) {
static void SerializeGltfAnimation(const Animation &animation, json &o) {
if (!animation.name.empty())
SerializeStringProperty("name", animation.name, o);
@@ -6903,7 +6926,7 @@ static void SerializeGltfAnimation(Animation &animation, json &o) {
SerializeExtensionMap(animation.extensions, o);
}
static void SerializeGltfAsset(Asset &asset, json &o) {
static void SerializeGltfAsset(const Asset &asset, json &o) {
if (!asset.generator.empty()) {
SerializeStringProperty("generator", asset.generator, o);
}
@@ -6912,14 +6935,15 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
SerializeStringProperty("copyright", asset.copyright, o);
}
if (asset.version.empty()) {
auto version = asset.version;
if (version.empty()) {
// Just in case
// `version` must be defined
asset.version = "2.0";
version = "2.0";
}
// TODO(syoyo): Do we need to check if `version` is greater or equal to 2.0?
SerializeStringProperty("version", asset.version, o);
SerializeStringProperty("version", version, o);
if (asset.extras.Keys().size()) {
SerializeValue("extras", asset.extras, o);
@@ -6928,7 +6952,7 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
SerializeExtensionMap(asset.extensions, o);
}
static void SerializeGltfBufferBin(Buffer &buffer, json &o,
static void SerializeGltfBufferBin(const Buffer &buffer, json &o,
std::vector<unsigned char> &binBuffer) {
SerializeNumberProperty("byteLength", buffer.data.size(), o);
binBuffer = buffer.data;
@@ -6940,7 +6964,7 @@ static void SerializeGltfBufferBin(Buffer &buffer, json &o,
}
}
static void SerializeGltfBuffer(Buffer &buffer, json &o) {
static void SerializeGltfBuffer(const Buffer &buffer, json &o) {
SerializeNumberProperty("byteLength", buffer.data.size(), o);
SerializeGltfBufferData(buffer.data, o);
@@ -6951,7 +6975,7 @@ static void SerializeGltfBuffer(Buffer &buffer, json &o) {
}
}
static bool SerializeGltfBuffer(Buffer &buffer, json &o,
static bool SerializeGltfBuffer(const Buffer &buffer, json &o,
const std::string &binFilename,
const std::string &binBaseFilename) {
if (!SerializeGltfBufferData(buffer.data, binFilename)) return false;
@@ -6966,7 +6990,7 @@ static bool SerializeGltfBuffer(Buffer &buffer, json &o,
return true;
}
static void SerializeGltfBufferView(BufferView &bufferView, json &o) {
static void SerializeGltfBufferView(const BufferView &bufferView, json &o) {
SerializeNumberProperty("buffer", bufferView.buffer, o);
SerializeNumberProperty<size_t>("byteLength", bufferView.byteLength, o);
@@ -6992,14 +7016,16 @@ static void SerializeGltfBufferView(BufferView &bufferView, json &o) {
}
}
static void SerializeGltfImage(Image &image, json &o) {
// if uri empty, the mimeType and bufferview should be set
if (image.uri.empty()) {
static void SerializeGltfImage(const Image &image, const std::string uri,
json &o) {
// From 2.7.0, we look for `uri` parameter, not `Image.uri`
// if uri is empty, the mimeType and bufferview should be set
if (uri.empty()) {
SerializeStringProperty("mimeType", image.mimeType, o);
SerializeNumberProperty<int>("bufferView", image.bufferView, o);
} else {
// TODO(syoyo): dlib::urilencode?
SerializeStringProperty("uri", image.uri, o);
SerializeStringProperty("uri", uri, o);
}
if (image.name.size()) {
@@ -7013,7 +7039,7 @@ static void SerializeGltfImage(Image &image, json &o) {
SerializeExtensionMap(image.extensions, o);
}
static void SerializeGltfTextureInfo(TextureInfo &texinfo, json &o) {
static void SerializeGltfTextureInfo(const TextureInfo &texinfo, json &o) {
SerializeNumberProperty("index", texinfo.index, o);
if (texinfo.texCoord != 0) {
@@ -7027,7 +7053,7 @@ static void SerializeGltfTextureInfo(TextureInfo &texinfo, json &o) {
SerializeExtensionMap(texinfo.extensions, o);
}
static void SerializeGltfNormalTextureInfo(NormalTextureInfo &texinfo,
static void SerializeGltfNormalTextureInfo(const NormalTextureInfo &texinfo,
json &o) {
SerializeNumberProperty("index", texinfo.index, o);
@@ -7046,8 +7072,8 @@ static void SerializeGltfNormalTextureInfo(NormalTextureInfo &texinfo,
SerializeExtensionMap(texinfo.extensions, o);
}
static void SerializeGltfOcclusionTextureInfo(OcclusionTextureInfo &texinfo,
json &o) {
static void SerializeGltfOcclusionTextureInfo(
const OcclusionTextureInfo &texinfo, json &o) {
SerializeNumberProperty("index", texinfo.index, o);
if (texinfo.texCoord != 0) {
@@ -7065,7 +7091,7 @@ static void SerializeGltfOcclusionTextureInfo(OcclusionTextureInfo &texinfo,
SerializeExtensionMap(texinfo.extensions, o);
}
static void SerializeGltfPbrMetallicRoughness(PbrMetallicRoughness &pbr,
static void SerializeGltfPbrMetallicRoughness(const PbrMetallicRoughness &pbr,
json &o) {
std::vector<double> default_baseColorFactor = {1.0, 1.0, 1.0, 1.0};
if (!Equals(pbr.baseColorFactor, default_baseColorFactor)) {
@@ -7100,7 +7126,7 @@ static void SerializeGltfPbrMetallicRoughness(PbrMetallicRoughness &pbr,
}
}
static void SerializeGltfMaterial(Material &material, json &o) {
static void SerializeGltfMaterial(const Material &material, json &o) {
if (material.name.size()) {
SerializeStringProperty("name", material.name, o);
}
@@ -7150,7 +7176,7 @@ static void SerializeGltfMaterial(Material &material, json &o) {
// Do not serialize `pbrMetallicRoughness` if pbrMetallicRoughness has all
// default values(json is null). Otherwise it will serialize to
// `pbrMetallicRoughness : null`, which cannot be read by other glTF
// importers(and validators).
// importers (and validators).
//
if (!JsonIsNull(pbrMetallicRoughness)) {
JsonAddMember(o, "pbrMetallicRoughness", std::move(pbrMetallicRoughness));
@@ -7176,7 +7202,7 @@ static void SerializeGltfMaterial(Material &material, json &o) {
}
}
static void SerializeGltfMesh(Mesh &mesh, json &o) {
static void SerializeGltfMesh(const Mesh &mesh, json &o) {
json primitives;
JsonReserveArray(primitives, mesh.primitives.size());
for (unsigned int i = 0; i < mesh.primitives.size(); ++i) {
@@ -7192,7 +7218,7 @@ static void SerializeGltfMesh(Mesh &mesh, json &o) {
JsonAddMember(primitive, "attributes", std::move(attributes));
}
// Indicies is optional
// Indices is optional
if (gltfPrimitive.indices > -1) {
SerializeNumberProperty<int>("indices", gltfPrimitive.indices, primitive);
}
@@ -7245,7 +7271,7 @@ static void SerializeGltfMesh(Mesh &mesh, json &o) {
}
}
static void SerializeSpotLight(SpotLight &spot, json &o) {
static void SerializeSpotLight(const SpotLight &spot, json &o) {
SerializeNumberProperty("innerConeAngle", spot.innerConeAngle, o);
SerializeNumberProperty("outerConeAngle", spot.outerConeAngle, o);
SerializeExtensionMap(spot.extensions, o);
@@ -7254,7 +7280,7 @@ static void SerializeSpotLight(SpotLight &spot, json &o) {
}
}
static void SerializeGltfLight(Light &light, json &o) {
static void SerializeGltfLight(const Light &light, json &o) {
if (!light.name.empty()) SerializeStringProperty("name", light.name, o);
SerializeNumberProperty("intensity", light.intensity, o);
if (light.range > 0.0) {
@@ -7273,7 +7299,7 @@ static void SerializeGltfLight(Light &light, json &o) {
}
}
static void SerializeGltfNode(Node &node, json &o) {
static void SerializeGltfNode(const Node &node, json &o) {
if (node.translation.size() > 0) {
SerializeNumberArrayProperty<double>("translation", node.translation, o);
}
@@ -7311,7 +7337,7 @@ static void SerializeGltfNode(Node &node, json &o) {
SerializeNumberArrayProperty<int>("children", node.children, o);
}
static void SerializeGltfSampler(Sampler &sampler, json &o) {
static void SerializeGltfSampler(const Sampler &sampler, json &o) {
if (sampler.magFilter != -1) {
SerializeNumberProperty("magFilter", sampler.magFilter, o);
}
@@ -7380,7 +7406,7 @@ static void SerializeGltfCamera(const Camera &camera, json &o) {
SerializeExtensionMap(camera.extensions, o);
}
static void SerializeGltfScene(Scene &scene, json &o) {
static void SerializeGltfScene(const Scene &scene, json &o) {
SerializeNumberArrayProperty<int>("nodes", scene.nodes, o);
if (scene.name.size()) {
@@ -7392,7 +7418,7 @@ static void SerializeGltfScene(Scene &scene, json &o) {
SerializeExtensionMap(scene.extensions, o);
}
static void SerializeGltfSkin(Skin &skin, json &o) {
static void SerializeGltfSkin(const Skin &skin, json &o) {
// required
SerializeNumberArrayProperty<int>("joints", skin.joints, o);
@@ -7409,7 +7435,7 @@ static void SerializeGltfSkin(Skin &skin, json &o) {
}
}
static void SerializeGltfTexture(Texture &texture, json &o) {
static void SerializeGltfTexture(const Texture &texture, json &o) {
if (texture.sampler > -1) {
SerializeNumberProperty("sampler", texture.sampler, o);
}
@@ -7428,7 +7454,7 @@ static void SerializeGltfTexture(Texture &texture, json &o) {
///
/// Serialize all properties except buffers and images.
///
static void SerializeGltfModel(Model *model, json &o) {
static void SerializeGltfModel(const Model *model, json &o) {
// ACCESSORS
if (model->accessors.size()) {
json accessors;
@@ -7754,7 +7780,7 @@ static bool WriteBinaryGltfFile(const std::string &output,
return WriteBinaryGltfStream(gltfFile, content, binBuffer);
}
bool TinyGLTF::WriteGltfSceneToStream(Model *model, std::ostream &stream,
bool TinyGLTF::WriteGltfSceneToStream(const Model *model, std::ostream &stream,
bool prettyPrint = true,
bool writeBinary = false) {
JsonDocument output;
@@ -7790,9 +7816,11 @@ bool TinyGLTF::WriteGltfSceneToStream(Model *model, std::ostream &stream,
// UpdateImageObject need baseDir but only uses it if embeddedImages is
// enabled, since we won't write separate images when writing to a stream
// we
std::string uri;
UpdateImageObject(model->images[i], dummystring, int(i), true,
&this->WriteImageData, this->write_image_user_data_);
SerializeGltfImage(model->images[i], image);
&this->WriteImageData, &uri,
this->write_image_user_data_);
SerializeGltfImage(model->images[i], uri, image);
JsonPushBack(images, std::move(image));
}
JsonAddMember(output, "images", std::move(images));
@@ -7803,10 +7831,10 @@ bool TinyGLTF::WriteGltfSceneToStream(Model *model, std::ostream &stream,
} else {
return WriteGltfStream(stream, JsonToString(output, prettyPrint ? 2 : -1));
}
}
bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
const std::string &filename,
bool embedImages = false,
bool embedBuffers = false,
bool prettyPrint = true,
@@ -7879,9 +7907,11 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
for (unsigned int i = 0; i < model->images.size(); ++i) {
json image;
std::string uri;
UpdateImageObject(model->images[i], baseDir, int(i), embedImages,
&this->WriteImageData, this->write_image_user_data_);
SerializeGltfImage(model->images[i], image);
&this->WriteImageData, &uri,
this->write_image_user_data_);
SerializeGltfImage(model->images[i], uri, image);
JsonPushBack(images, std::move(image));
}
JsonAddMember(output, "images", std::move(images));
@@ -7892,7 +7922,6 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
} else {
return WriteGltfFile(filename, JsonToString(output, (prettyPrint ? 2 : -1)));
}
}
} // namespace tinygltf

11
wasm/Makefile Normal file
View File

@@ -0,0 +1,11 @@
WASI_VERSION=16
WASI_VERSION_FULL=${WASI_VERSION}.0
WASI_SDK_PATH=$(HOME)/local/wasi-sdk-${WASI_VERSION_FULL}
CC=${WASI_SDK_PATH}/bin/clang
CXX=${WASI_SDK_PATH}/bin/clang++
CXXFLAGS=-fno-rtti -fno-exceptions -g -Os
all:
$(CXX) ../loader_example.cc $(CXXFLAGS) -I../

31
wasm/README.md Normal file
View File

@@ -0,0 +1,31 @@
Experimental WASI/WASM build
## Build
Download wasi-sdk https://github.com/WebAssembly/wasi-sdk
Compile tinygltf with C++ exceptions and threads off. See `Makefile` for details
(NOTE: TinyGLTF itself does not use RTTI and threading feature(C++ threads, posix, win32 thread))
## Build examples and Run
Build `loader_example.cc`
```
$ /path/to/wasi-sdk-16.0/bin/clang++ ../loader_example.cc -fno-rtti -fno-exceptions -g -Os -I../ -o loader_example.wasi
```
Tested with wasmtime. https://github.com/bytecodealliance/wasmtime
Set a folder containing .gltf file to `--dir`
```
$ wasmtime --dir=../models loader_example.wasi ../models/Cube/Cube.gltf
```
## Emscripen
T.B.W. ...
EoL.