69#ifndef TINYGLTF_USE_CPP14
74#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
75#include <android/asset_manager.h>
80#if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 8))
81#define TINYGLTF_NOEXCEPT
83#define TINYGLTF_NOEXCEPT noexcept
86#define TINYGLTF_NOEXCEPT noexcept
89#define DEFAULT_METHODS(x) \
91 x(const x &) = default; \
92 x(x &&) TINYGLTF_NOEXCEPT = default; \
93 x &operator=(const x &) = default; \
94 x &operator=(x &&) TINYGLTF_NOEXCEPT = default;
98#define TINYGLTF_MODE_POINTS (0)
99#define TINYGLTF_MODE_LINE (1)
100#define TINYGLTF_MODE_LINE_LOOP (2)
101#define TINYGLTF_MODE_LINE_STRIP (3)
102#define TINYGLTF_MODE_TRIANGLES (4)
103#define TINYGLTF_MODE_TRIANGLE_STRIP (5)
104#define TINYGLTF_MODE_TRIANGLE_FAN (6)
106#define TINYGLTF_COMPONENT_TYPE_BYTE (5120)
107#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE (5121)
108#define TINYGLTF_COMPONENT_TYPE_SHORT (5122)
109#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT (5123)
110#define TINYGLTF_COMPONENT_TYPE_INT (5124)
111#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT (5125)
112#define TINYGLTF_COMPONENT_TYPE_FLOAT (5126)
113#define TINYGLTF_COMPONENT_TYPE_DOUBLE (5130)
115#define TINYGLTF_TEXTURE_FILTER_NEAREST (9728)
116#define TINYGLTF_TEXTURE_FILTER_LINEAR (9729)
117#define TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST (9984)
118#define TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST (9985)
119#define TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR (9986)
120#define TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR (9987)
122#define TINYGLTF_TEXTURE_WRAP_REPEAT (10497)
123#define TINYGLTF_TEXTURE_WRAP_CLAMP_TO_EDGE (33071)
124#define TINYGLTF_TEXTURE_WRAP_MIRRORED_REPEAT (33648)
127#define TINYGLTF_PARAMETER_TYPE_BYTE (5120)
128#define TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE (5121)
129#define TINYGLTF_PARAMETER_TYPE_SHORT (5122)
130#define TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT (5123)
131#define TINYGLTF_PARAMETER_TYPE_INT (5124)
132#define TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT (5125)
133#define TINYGLTF_PARAMETER_TYPE_FLOAT (5126)
135#define TINYGLTF_PARAMETER_TYPE_FLOAT_VEC2 (35664)
136#define TINYGLTF_PARAMETER_TYPE_FLOAT_VEC3 (35665)
137#define TINYGLTF_PARAMETER_TYPE_FLOAT_VEC4 (35666)
139#define TINYGLTF_PARAMETER_TYPE_INT_VEC2 (35667)
140#define TINYGLTF_PARAMETER_TYPE_INT_VEC3 (35668)
141#define TINYGLTF_PARAMETER_TYPE_INT_VEC4 (35669)
143#define TINYGLTF_PARAMETER_TYPE_BOOL (35670)
144#define TINYGLTF_PARAMETER_TYPE_BOOL_VEC2 (35671)
145#define TINYGLTF_PARAMETER_TYPE_BOOL_VEC3 (35672)
146#define TINYGLTF_PARAMETER_TYPE_BOOL_VEC4 (35673)
148#define TINYGLTF_PARAMETER_TYPE_FLOAT_MAT2 (35674)
149#define TINYGLTF_PARAMETER_TYPE_FLOAT_MAT3 (35675)
150#define TINYGLTF_PARAMETER_TYPE_FLOAT_MAT4 (35676)
152#define TINYGLTF_PARAMETER_TYPE_SAMPLER_2D (35678)
156#define TINYGLTF_TYPE_VEC2 (2)
157#define TINYGLTF_TYPE_VEC3 (3)
158#define TINYGLTF_TYPE_VEC4 (4)
159#define TINYGLTF_TYPE_MAT2 (32 + 2)
160#define TINYGLTF_TYPE_MAT3 (32 + 3)
161#define TINYGLTF_TYPE_MAT4 (32 + 4)
162#define TINYGLTF_TYPE_SCALAR (64 + 1)
163#define TINYGLTF_TYPE_VECTOR (64 + 4)
164#define TINYGLTF_TYPE_MATRIX (64 + 16)
166#define TINYGLTF_IMAGE_FORMAT_JPEG (0)
167#define TINYGLTF_IMAGE_FORMAT_PNG (1)
168#define TINYGLTF_IMAGE_FORMAT_BMP (2)
169#define TINYGLTF_IMAGE_FORMAT_GIF (3)
171#define TINYGLTF_TEXTURE_FORMAT_ALPHA (6406)
172#define TINYGLTF_TEXTURE_FORMAT_RGB (6407)
173#define TINYGLTF_TEXTURE_FORMAT_RGBA (6408)
174#define TINYGLTF_TEXTURE_FORMAT_LUMINANCE (6409)
175#define TINYGLTF_TEXTURE_FORMAT_LUMINANCE_ALPHA (6410)
177#define TINYGLTF_TEXTURE_TARGET_TEXTURE2D (3553)
178#define TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE (5121)
180#define TINYGLTF_TARGET_ARRAY_BUFFER (34962)
181#define TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER (34963)
183#define TINYGLTF_SHADER_TYPE_VERTEX_SHADER (35633)
184#define TINYGLTF_SHADER_TYPE_FRAGMENT_SHADER (35632)
186#define TINYGLTF_DOUBLE_EPS (1.e-12)
187#define TINYGLTF_DOUBLE_EQUAL(a, b) (std::fabs((b) - (a)) < TINYGLTF_DOUBLE_EPS)
190#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
191AAssetManager *asset_manager =
nullptr;
206static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
229static inline int32_t GetNumComponentsInType(uint32_t ty) {
253 const std::string &in,
size_t reqBytes,
bool checkSize);
256#pragma clang diagnostic push
259#pragma clang diagnostic ignored "-Wexit-time-destructors"
260#pragma clang diagnostic ignored "-Wpadded"
267 typedef std::map<std::string, Value>
Object;
290 explicit Value(std::vector<unsigned char> &&v) noexcept
341 template <
typename T>
343 template <
typename T>
348 static Value null_value;
358 static Value null_value;
361 return (it !=
object_value_.end()) ? it->second : null_value;
370 bool Has(
const std::string &key)
const {
377 std::vector<std::string>
Keys()
const {
378 std::vector<std::string> keys;
383 keys.push_back(it->first);
406#pragma clang diagnostic pop
409#define TINYGLTF_VALUE_GET(ctype, var) \
411 inline const ctype &Value::Get<ctype>() const { \
415 inline ctype &Value::Get<ctype>() { \
425#undef TINYGLTF_VALUE_GET
428#pragma clang diagnostic push
429#pragma clang diagnostic ignored "-Wc++98-compat"
430#pragma clang diagnostic ignored "-Wpadded"
457 return int(it->second);
468 return int(it->second);
519#pragma clang diagnostic pop
523#pragma clang diagnostic push
524#pragma clang diagnostic ignored "-Wpadded"
600 bool operator==(const
Skin &) const;
645 std::vector<unsigned char, ::GameApiAllocator<unsigned char> >
image;
677 bool operator==(const
Image &) const;
771 roughnessFactor(1.0) {}
882 int componentSizeInBytes =
883 GetComponentSizeInBytes(
static_cast<uint32_t
>(
componentType));
884 if (componentSizeInBytes <= 0) {
888 int numComponents = GetNumComponentsInType(
static_cast<uint32_t
>(
type));
889 if (numComponents <= 0) {
893 return componentSizeInBytes * numComponents;
897 int componentSizeInBytes =
898 GetComponentSizeInBytes(
static_cast<uint32_t
>(
componentType));
899 if (componentSizeInBytes <= 0) {
903 if ((bufferViewObject.
byteStride % uint32_t(componentSizeInBytes)) != 0) {
906 return static_cast<int>(bufferViewObject.
byteStride);
994 std::vector<std::map<std::string, int> >
targets;
1027 bool operator==(const
Mesh &) const;
1036 bool operator==(const
Node &) const;
1060 std::vector<unsigned char, ::GameApiAllocator<unsigned char> >
data;
1198 std::string *, int, int,
1199 const unsigned char *, int,
1200 void *user_pointer);
1206 Image *, bool,
void *);
1208#ifndef TINYGLTF_NO_STB_IMAGE
1211 std::string *warn,
int req_width,
int req_height,
1212 const unsigned char *bytes,
int size,
void *);
1215#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
1235 std::string *,
const std::string &,
1242 const std::vector<unsigned char, ::GameApiAllocator<unsigned char> > &,
1258#ifndef TINYGLTF_NO_FS
1273 const std::string &filepath,
void *);
1285#pragma clang diagnostic push
1286#pragma clang diagnostic ignored "-Wc++98-compat"
1289 TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) {}
1292#pragma clang diagnostic pop
1303 const std::string &filename,
1313 const char *
str,
const unsigned int length,
1314 const std::string &base_dir,
1323 const std::string &filename,
1333 const unsigned char *bytes,
1334 const unsigned int length,
1335 const std::string &base_dir =
"",
1342 bool prettyPrint,
bool writeBinary);
1348 bool embedImages,
bool embedBuffers,
1349 bool prettyPrint,
bool writeBinary);
1381 serialize_default_values_ = enabled;
1392 store_original_json_for_extras_and_extensions_ = enabled;
1396 return store_original_json_for_extras_and_extensions_;
1404 preserve_image_channels_ = onoff;
1416 bool LoadFromString(
Model *model, std::string *err, std::string *warn,
1417 const char *
str,
const unsigned int length,
1418 const std::string &base_dir,
unsigned int check_sections);
1420 const unsigned char *bin_data_ =
nullptr;
1421 size_t bin_size_ = 0;
1422 bool is_binary_ =
false;
1424 bool serialize_default_values_ =
false;
1426 bool store_original_json_for_extras_and_extensions_ =
false;
1428 bool preserve_image_channels_ =
false;
1432#ifndef TINYGLTF_NO_FS
1438 nullptr,
nullptr,
nullptr,
nullptr,
1445#ifndef TINYGLTF_NO_STB_IMAGE
1450 void *load_image_user_data_{
nullptr};
1451 bool user_image_loader_{
false};
1454#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
1459 void *write_image_user_data_{
nullptr};
1463#pragma clang diagnostic pop
1470#if defined(TINYGLTF_IMPLEMENTATION) || defined(__INTELLISENSE__)
1473#ifndef TINYGLTF_NO_FS
1481#pragma clang diagnostic push
1482#pragma clang diagnostic ignored "-Wfloat-equal"
1483#pragma clang diagnostic ignored "-Wexit-time-destructors"
1484#pragma clang diagnostic ignored "-Wconversion"
1485#pragma clang diagnostic ignored "-Wold-style-cast"
1486#pragma clang diagnostic ignored "-Wglobal-constructors"
1487#if __has_warning("-Wreserved-id-macro")
1488#pragma clang diagnostic ignored "-Wreserved-id-macro"
1490#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
1491#pragma clang diagnostic ignored "-Wpadded"
1492#pragma clang diagnostic ignored "-Wc++98-compat"
1493#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1494#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
1495#pragma clang diagnostic ignored "-Wswitch-enum"
1496#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
1497#pragma clang diagnostic ignored "-Wweak-vtables"
1498#pragma clang diagnostic ignored "-Wcovered-switch-default"
1499#if __has_warning("-Wdouble-promotion")
1500#pragma clang diagnostic ignored "-Wdouble-promotion"
1502#if __has_warning("-Wcomma")
1503#pragma clang diagnostic ignored "-Wcomma"
1505#if __has_warning("-Wzero-as-null-pointer-constant")
1506#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
1508#if __has_warning("-Wcast-qual")
1509#pragma clang diagnostic ignored "-Wcast-qual"
1511#if __has_warning("-Wmissing-variable-declarations")
1512#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
1514#if __has_warning("-Wmissing-prototypes")
1515#pragma clang diagnostic ignored "-Wmissing-prototypes"
1517#if __has_warning("-Wcast-align")
1518#pragma clang diagnostic ignored "-Wcast-align"
1520#if __has_warning("-Wnewline-eof")
1521#pragma clang diagnostic ignored "-Wnewline-eof"
1523#if __has_warning("-Wunused-parameter")
1524#pragma clang diagnostic ignored "-Wunused-parameter"
1526#if __has_warning("-Wmismatched-tags")
1527#pragma clang diagnostic ignored "-Wmismatched-tags"
1529#if __has_warning("-Wextra-semi-stmt")
1530#pragma clang diagnostic ignored "-Wextra-semi-stmt"
1536#pragma GCC diagnostic push
1537#pragma GCC diagnostic ignored "-Wtype-limits"
1540#ifndef TINYGLTF_NO_INCLUDE_JSON
1541#ifndef TINYGLTF_USE_RAPIDJSON
1544#ifndef TINYGLTF_NO_INCLUDE_RAPIDJSON
1545#include "document.h"
1546#include "prettywriter.h"
1547#include "rapidjson.h"
1548#include "stringbuffer.h"
1554#ifdef TINYGLTF_ENABLE_DRACO
1559#ifndef TINYGLTF_NO_STB_IMAGE
1560#ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE
1565#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
1566#ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
1572#pragma clang diagnostic pop
1576#pragma GCC diagnostic pop
1585#define TINYGLTF_INTERNAL_NOMINMAX
1589#ifndef WIN32_LEAN_AND_MEAN
1590#define WIN32_LEAN_AND_MEAN
1591#define TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
1595#ifdef TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
1596#undef WIN32_LEAN_AND_MEAN
1599#if defined(TINYGLTF_INTERNAL_NOMINMAX)
1603#if defined(__GLIBCXX__)
1607#include <ext/stdio_filebuf.h>
1611#elif !defined(__ANDROID__) && !defined(__OpenBSD__)
1615#if defined(__sparcv9)
1618#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
1619#define TINYGLTF_LITTLE_ENDIAN 1
1624#ifdef TINYGLTF_USE_RAPIDJSON
1626#ifdef TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
1630 rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
1631using json_const_iterator = json::ConstMemberIterator;
1632using json_const_array_iterator =
json const *;
1634 rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
1635rapidjson::CrtAllocator s_CrtAllocator;
1636rapidjson::CrtAllocator &GetAllocator() {
return s_CrtAllocator; }
1641using json = rapidjson::Value;
1642using json_const_iterator = json::ConstMemberIterator;
1643using json_const_array_iterator =
json const *;
1644rapidjson::Document *s_pActiveDocument =
nullptr;
1645rapidjson::Document::AllocatorType &GetAllocator() {
1646 assert(s_pActiveDocument);
1647 return s_pActiveDocument->GetAllocator();
1651#pragma clang diagnostic push
1653#pragma clang diagnostic ignored "-Wunused-member-function"
1656struct JsonDocument :
public rapidjson::Document {
1658 assert(s_pActiveDocument ==
1662 s_pActiveDocument =
this;
1664 JsonDocument(
const JsonDocument &) =
delete;
1665 JsonDocument(JsonDocument &&rhs)
noexcept
1666 : rapidjson::Document(std::move(rhs)) {
1667 s_pActiveDocument =
this;
1672 s_pActiveDocument =
nullptr;
1681#pragma clang diagnostic pop
1688using json_const_iterator = json::const_iterator;
1689using json_const_array_iterator = json_const_iterator;
1690using JsonDocument =
json;
1693void JsonParse(JsonDocument &doc,
const char *
str,
size_t length,
1694 bool throwExc =
false) {
1695#ifdef TINYGLTF_USE_RAPIDJSON
1697 doc.Parse(
str, length);
1699 doc = json::parse(
str,
str + length,
nullptr, throwExc);
1705#include "TargetConditionals.h"
1709#pragma clang diagnostic push
1710#pragma clang diagnostic ignored "-Wc++98-compat"
1721struct LoadImageDataOption {
1725 bool preserve_channels{
false};
1729static bool Equals(
const tinygltf::Value &one,
const tinygltf::Value &other) {
1730 if (one.Type() != other.
Type())
return false;
1732 switch (one.Type()) {
1736 return one.Get<
bool>() == other.
Get<
bool>();
1740 return one.Get<
int>() == other.
Get<
int>();
1744 if (oneObj.size() != otherObj.size())
return false;
1745 for (
auto &it : oneObj) {
1746 auto otherIt = otherObj.find(it.first);
1747 if (otherIt == otherObj.end())
return false;
1749 if (!
Equals(it.second, otherIt->second))
return false;
1754 if (one.Size() != other.
Size())
return false;
1755 for (
int i = 0; i < int(one.Size()); ++i)
1756 if (!
Equals(one.Get(i), other.
Get(i)))
return false;
1760 return one.Get<std::string>() == other.
Get<std::string>();
1762 return one.Get<std::vector<unsigned char> >() ==
1763 other.
Get<std::vector<unsigned char> >();
1772static bool Equals(
const std::vector<double> &one,
1773 const std::vector<double> &other) {
1774 if (one.size() != other.size())
return false;
1775 for (
int i = 0; i < int(one.size()); ++i) {
1782 return this->
bufferView == other.bufferView &&
1786 this->
extras == other.extras &&
1789 this->
normalized == other.normalized && this->
type == other.type;
1792 return this->
channels == other.channels &&
1794 this->
name == other.name && this->
samplers == other.samplers;
1797 return this->
extensions == other.extensions && this->
extras == other.extras &&
1800 this->
sampler == other.sampler;
1803 return this->
extras == other.extras && this->
extensions == other.extensions &&
1804 this->
input == other.input &&
1806 this->
output == other.output;
1809 return this->
copyright == other.copyright &&
1815 return this->
data == other.data && this->
extensions == other.extensions &&
1816 this->
extras == other.extras && this->
name == other.name &&
1817 this->
uri == other.uri;
1820 return this->
buffer == other.buffer && this->
byteLength == other.byteLength &&
1822 this->
byteStride == other.byteStride && this->
name == other.name &&
1824 this->
extras == other.extras &&
1828 return this->
name == other.name && this->
extensions == other.extensions &&
1829 this->
extras == other.extras &&
1834 return this->
bufferView == other.bufferView &&
1837 this->
height == other.height && this->
image == other.image &&
1838 this->
mimeType == other.mimeType && this->
name == other.name &&
1839 this->
uri == other.uri && this->
width == other.width;
1842 return Equals(this->
color, other.color) && this->
name == other.name &&
1843 this->
type == other.type;
1855 (this->
extras == other.extras) && (this->
values == other.values) &&
1857 (this->
name == other.name);
1860 return this->
extensions == other.extensions && this->
extras == other.extras &&
1865 return this->
accessors == other.accessors &&
1867 this->
buffers == other.buffers &&
1869 this->
cameras == other.cameras &&
1874 this->
extras == other.extras && this->
images == other.images &&
1876 this->
meshes == other.meshes && this->
nodes == other.nodes &&
1877 this->
samplers == other.samplers && this->
scenes == other.scenes &&
1878 this->
skins == other.skins && this->
textures == other.textures;
1881 return this->
camera == other.camera && this->
children == other.children &&
1890 return this->
extensions == other.extensions && this->
extras == other.extras &&
1895 return this->
extensions == other.extensions && this->
extras == other.extras &&
1903 this->has_number_value != other.has_number_value)
1912 auto otherIt = other.json_double_value.find(it.first);
1913 if (otherIt == other.json_double_value.end())
return false;
1920 if (this->
string_value != other.string_value)
return false;
1932 return this->
attributes == other.attributes && this->
extras == other.extras &&
1934 this->
mode == other.mode && this->
targets == other.targets;
1937 return this->
extensions == other.extensions && this->
extras == other.extras &&
1939 this->
minFilter == other.minFilter && this->
name == other.name &&
1940 this->
wrapT == other.wrapT;
1945 return this->
extensions == other.extensions && this->
extras == other.extras &&
1946 this->
name == other.name && this->
nodes == other.nodes;
1949 return this->
extensions == other.extensions && this->
extras == other.extras &&
1951 this->
joints == other.joints && this->
name == other.name &&
1955 return this->
extensions == other.extensions && this->
extras == other.extras &&
1956 this->
name == other.name && this->
sampler == other.sampler &&
1957 this->
source == other.source;
1960 return this->
extensions == other.extensions && this->
extras == other.extras &&
1961 this->
index == other.index && this->
texCoord == other.texCoord;
1964 return this->
extensions == other.extensions && this->
extras == other.extras &&
1965 this->
index == other.index && this->
texCoord == other.texCoord &&
1969 return this->
extensions == other.extensions && this->
extras == other.extras &&
1970 this->
index == other.index && this->
texCoord == other.texCoord &&
1974 return this->
extensions == other.extensions && this->
extras == other.extras &&
1982 return Equals(*
this, other);
1985static void swap4(
unsigned int *val) {
1986#ifdef TINYGLTF_LITTLE_ENDIAN
1989 unsigned int tmp = *val;
1990 unsigned char *dst =
reinterpret_cast<unsigned char *
>(val);
1991 unsigned char *
src =
reinterpret_cast<unsigned char *
>(&tmp);
2000static std::string JoinPath(
const std::string &path0,
2001 const std::string &path1) {
2002 if (path0.empty()) {
2006 char lastChar = *path0.rbegin();
2007 if (lastChar !=
'/') {
2008 return path0 + std::string(
"/") + path1;
2010 return path0 + path1;
2015static std::string FindFile(
const std::vector<std::string> &paths,
2017 if (fs ==
nullptr || fs->ExpandFilePath ==
nullptr ||
2018 fs->FileExists ==
nullptr) {
2020 return std::string();
2023 for (
size_t i = 0; i < paths.size(); i++) {
2024 std::string absPath =
2025 fs->ExpandFilePath(JoinPath(paths[i], filepath), fs->user_data);
2026 if (fs->FileExists(absPath, fs->user_data)) {
2031 return std::string();
2034static std::string GetFilePathExtension(
const std::string &FileName) {
2035 if (FileName.find_last_of(
".") != std::string::npos)
2036 return FileName.substr(FileName.find_last_of(
".") + 1);
2040static std::string GetBaseDir(
const std::string &filepath) {
2041 if (filepath.find_last_of(
"/\\") != std::string::npos)
2042 return filepath.substr(0, filepath.find_last_of(
"/\\"));
2047static std::string GetBaseFilename(
const std::string &filepath) {
2048 return filepath.substr(filepath.find_last_of(
"/\\") + 1);
2051std::string
base64_encode(
unsigned char const *,
unsigned int len);
2052std::string base64_decode(std::string
const &s);
2082#pragma clang diagnostic push
2083#pragma clang diagnostic ignored "-Wsign-conversion"
2084#pragma clang diagnostic ignored "-Wconversion"
2087static inline bool is_base64(
unsigned char c) {
2088 return (isalnum(c) || (c ==
'+') || (c ==
'/'));
2091std::string
base64_encode(
unsigned char const *bytes_to_encode,
2092 unsigned int in_len) {
2096 unsigned char char_array_3[3];
2097 unsigned char char_array_4[4];
2099 const char *base64_chars =
2100 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2101 "abcdefghijklmnopqrstuvwxyz"
2105 char_array_3[i++] = *(bytes_to_encode++);
2107 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
2109 ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
2111 ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
2112 char_array_4[3] = char_array_3[2] & 0x3f;
2114 for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
2120 for (j = i; j < 3; j++) char_array_3[j] =
'\0';
2122 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
2124 ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
2126 ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
2128 for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
2130 while ((i++ < 3))
ret +=
'=';
2136std::string base64_decode(std::string
const &encoded_string) {
2137 int in_len =
static_cast<int>(encoded_string.size());
2141 unsigned char char_array_4[4], char_array_3[3];
2144 const std::string base64_chars =
2145 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2146 "abcdefghijklmnopqrstuvwxyz"
2149 while (in_len-- && (encoded_string[in_] !=
'=') &&
2150 is_base64(encoded_string[in_])) {
2151 char_array_4[i++] = encoded_string[in_];
2154 for (i = 0; i < 4; i++)
2156 static_cast<unsigned char>(base64_chars.find(char_array_4[i]));
2159 (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
2161 ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
2162 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
2164 for (i = 0; (i < 3); i++)
ret += char_array_3[i];
2170 for (j = i; j < 4; j++) char_array_4[j] = 0;
2172 for (j = 0; j < 4; j++)
2174 static_cast<unsigned char>(base64_chars.find(char_array_4[j]));
2176 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
2178 ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
2179 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
2181 for (j = 0; (j < i - 1); j++)
ret += char_array_3[j];
2187#pragma clang diagnostic pop
2204 inline unsigned char to_hex(
unsigned char x )
2206 return x + (x > 9 ? (
'A'-10) :
'0');
2209 const std::string urlencode(
const std::string& s )
2211 std::ostringstream os;
2213 for ( std::string::const_iterator ci = s.begin(); ci != s.end(); ++ci )
2215 if ( (*ci >=
'a' && *ci <=
'z') ||
2216 (*ci >=
'A' && *ci <=
'Z') ||
2217 (*ci >=
'0' && *ci <=
'9') )
2221 else if ( *ci ==
' ')
2227 os << '%' << to_hex(static_cast<unsigned char>(*ci >> 4)) << to_hex(
static_cast<unsigned char>(*ci % 16));
2235inline unsigned char from_hex(
unsigned char ch) {
2236 if (ch <=
'9' && ch >=
'0')
2238 else if (ch <=
'f' && ch >=
'a')
2240 else if (ch <=
'F' && ch >=
'A')
2247static const std::string urldecode(
const std::string &
str) {
2248 using namespace std;
2250 string::size_type i;
2251 for (i = 0; i <
str.size(); ++i) {
2252 if (
str[i] ==
'+') {
2254 }
else if (
str[i] ==
'%' &&
str.size() > i + 2) {
2255 const unsigned char ch1 =
2256 from_hex(
static_cast<unsigned char>(
str[i + 1]));
2257 const unsigned char ch2 =
2258 from_hex(
static_cast<unsigned char>(
str[i + 2]));
2259 const unsigned char ch =
static_cast<unsigned char>((ch1 << 4) | ch2);
2260 result +=
static_cast<char>(ch);
2272 static bool LoadExternalFile(std::vector<
unsigned char, ::GameApiAllocator<unsigned char> > *out, std::string *err,
2273 std::string *warn,
const std::string &filename,
2274 const std::string &basedir,
bool required,
2275 size_t reqBytes,
bool checkSize,
FsCallbacks *fs) {
2276 if (fs ==
nullptr || fs->FileExists ==
nullptr ||
2277 fs->ExpandFilePath ==
nullptr || fs->ReadWholeFile ==
nullptr) {
2280 (*err) +=
"FS callback[s] not set\n";
2285 std::string *failMsgOut = required ? err : warn;
2289 std::vector<std::string> paths;
2290 paths.push_back(basedir);
2291 paths.push_back(
".");
2293 std::string filepath = FindFile(paths, filename, fs);
2294 if (filepath.empty() || filename.empty()) {
2296 (*failMsgOut) +=
"File not found : " + filename +
"\n";
2301 std::vector<unsigned char, ::GameApiAllocator<unsigned char> > buf;
2302 std::string fileReadErr;
2304 fs->ReadWholeFile(&buf, &fileReadErr, filepath, fs->user_data);
2308 "File read error : " + filepath +
" : " + fileReadErr +
"\n";
2342 LoadImageData =
func;
2343 load_image_user_data_ = user_data;
2344 user_image_loader_ =
true;
2349#ifndef TINYGLTF_NO_STB_IMAGE
2355 load_image_user_data_ =
nullptr;
2356 user_image_loader_ =
false;
2359#ifndef TINYGLTF_NO_STB_IMAGE
2361 std::string *warn,
int req_width,
int req_height,
2362 const unsigned char *bytes,
int size,
void *user_data) {
2365 LoadImageDataOption option;
2367 option = *
reinterpret_cast<LoadImageDataOption *
>(user_data);
2370 int w = 0, h = 0, comp = 0, req_comp = 0;
2372 unsigned char *
data =
nullptr;
2377 req_comp = option.preserve_channels ? 0 : 4;
2388 data =
reinterpret_cast<unsigned char *
>(
2410 "Unknown image format. STB cannot decode image data for image[" +
2411 std::to_string(image_idx) +
"] name = \"" +
image->name +
"\".\n";
2416 if ((w < 1) || (h < 1)) {
2419 (*err) +=
"Invalid image data for image[" + std::to_string(image_idx) +
2420 "] name = \"" +
image->name +
"\"\n";
2425 if (req_width > 0) {
2426 if (req_width != w) {
2429 (*err) +=
"Image width mismatch for image[" +
2430 std::to_string(image_idx) +
"] name = \"" +
image->name +
2437 if (req_height > 0) {
2438 if (req_height != h) {
2441 (*err) +=
"Image height mismatch. for image[" +
2442 std::to_string(image_idx) +
"] name = \"" +
image->name +
2449 if (req_comp != 0) {
2456 image->component = comp;
2458 image->pixel_type = pixel_type;
2459 image->image.resize(
static_cast<size_t>(w * h * comp) *
size_t(bits / 8));
2460 std::copy(
data,
data + w * h * comp * (bits / 8),
image->image.begin());
2468 WriteImageData =
func;
2469 write_image_user_data_ = user_data;
2472#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
2473static void WriteToMemory_stbi(
void *context,
void *
data,
int size) {
2474 std::vector<unsigned char> *buffer =
2475 reinterpret_cast<std::vector<unsigned char> *
>(context);
2477 unsigned char *pData =
reinterpret_cast<unsigned char *
>(
data);
2479 buffer->insert(buffer->end(), pData, pData +
size);
2482bool WriteImageData(
const std::string *basepath,
const std::string *filename,
2483 Image *
image,
bool embedImages,
void *fsPtr) {
2484 const std::string ext = GetFilePathExtension(*filename);
2488 std::vector<unsigned char, ::GameApiAllocator<unsigned char> >
data;
2491 if ((
image->bits != 8) ||
2499 &
image->image[0], 0)) {
2502 header =
"data:image/png;base64,";
2503 }
else if (ext ==
"jpg") {
2506 &
image->image[0], 100)) {
2509 header =
"data:image/jpeg;base64,";
2510 }
else if (ext ==
"bmp") {
2513 &
image->image[0])) {
2516 header =
"data:image/bmp;base64,";
2517 }
else if (!embedImages) {
2534 if ((fs !=
nullptr) && (fs->WriteWholeFile !=
nullptr)) {
2535 const std::string imagefilepath = JoinPath(*basepath, *filename);
2536 std::string writeError;
2537 if (!fs->WriteWholeFile(&writeError, imagefilepath,
data,
2545 image->uri = *filename;
2555static inline std::wstring UTF8ToWchar(
const std::string &
str) {
2557 MultiByteToWideChar(CP_UTF8, 0,
str.data(), (
int)
str.size(),
nullptr, 0);
2558 std::wstring wstr(wstr_size, 0);
2559 MultiByteToWideChar(CP_UTF8, 0,
str.data(), (
int)
str.size(), &wstr[0],
2564static inline std::string WcharToUTF8(
const std::wstring &wstr) {
2565 int str_size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (
int)wstr.size(),
2566 nullptr, 0, NULL, NULL);
2567 std::string
str(str_size, 0);
2568 WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (
int)wstr.size(), &
str[0],
2569 (
int)
str.size(), NULL, NULL);
2574#ifndef TINYGLTF_NO_FS
2577bool FileExists(
const std::string &abs_filename,
void *) {
2579#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
2580 if (asset_manager) {
2581 AAsset *asset = AAssetManager_open(asset_manager, abs_filename.c_str(),
2582 AASSET_MODE_STREAMING);
2586 AAsset_close(asset);
2593#if defined(_MSC_VER) || defined(__GLIBCXX__)
2595 errno_t err = _wfopen_s(&fp, UTF8ToWchar(abs_filename).c_str(), L
"rb");
2601 errno_t err = fopen_s(&fp, abs_filename.c_str(),
"rb");
2608 FILE *fp = fopen(abs_filename.c_str(),
"rb");
2624 std::wstring wfilepath = UTF8ToWchar(filepath);
2625 DWORD wlen = ExpandEnvironmentStringsW(wfilepath.c_str(),
nullptr, 0);
2626 wchar_t *wstr =
new wchar_t[wlen];
2627 ExpandEnvironmentStringsW(wfilepath.c_str(), wstr, wlen);
2629 std::wstring ws(wstr);
2631 return WcharToUTF8(ws);
2635#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \
2636 defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__OpenBSD__)
2638 std::string s = filepath;
2643 if (filepath.empty()) {
2648 std::string quoted_path =
"\"" + filepath +
"\"";
2650 int ret = wordexp(quoted_path.c_str(), &p, 0);
2659 s = std::string(p.we_wordv[0]);
2671 bool ReadWholeFile(std::vector<
unsigned char, ::GameApiAllocator<unsigned char> > *out, std::string *err,
2672 const std::string &filepath,
void *) {
2673#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
2674 if (asset_manager) {
2675 AAsset *asset = AAssetManager_open(asset_manager, filepath.c_str(),
2676 AASSET_MODE_STREAMING);
2679 (*err) +=
"File open error : " + filepath +
"\n";
2683 size_t size = AAsset_getLength(asset);
2686 (*err) +=
"Invalid file size : " + filepath +
2687 " (does the path point to a directory?)";
2692 AAsset_read(asset,
reinterpret_cast<char *
>(&out->at(0)),
size);
2693 AAsset_close(asset);
2697 (*err) +=
"No asset manager specified : " + filepath +
"\n";
2703#if defined(__GLIBCXX__)
2704 int file_descriptor =
2705 _wopen(UTF8ToWchar(filepath).c_str(), _O_RDONLY | _O_BINARY);
2706 __gnu_cxx::stdio_filebuf<char> wfile_buf(file_descriptor, std::ios_base::in);
2707 std::istream
f(&wfile_buf);
2708#elif defined(_MSC_VER) || defined(_LIBCPP_VERSION)
2711 std::ifstream
f(UTF8ToWchar(filepath).c_str(), std::ifstream::binary);
2714 std::ifstream
f(filepath.c_str(), std::ifstream::binary);
2717 std::ifstream
f(filepath.c_str(), std::ifstream::binary);
2721 (*err) +=
"File open error : " + filepath +
"\n";
2727 size_t sz =
static_cast<size_t>(
f.tellg());
2730 if (int64_t(sz) < 0) {
2732 (*err) +=
"Invalid file size : " + filepath +
2733 " (does the path point to a directory?)";
2736 }
else if (sz == 0) {
2738 (*err) +=
"File is empty : " + filepath +
"\n";
2744 f.read(
reinterpret_cast<char *
>(&out->at(0)),
2745 static_cast<std::streamsize
>(sz));
2751bool WriteWholeFile(std::string *err,
const std::string &filepath,
2752 const std::vector<
unsigned char, ::GameApiAllocator<unsigned char> > &contents,
void *) {
2754#if defined(__GLIBCXX__)
2755 int file_descriptor = _wopen(UTF8ToWchar(filepath).c_str(),
2756 _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY);
2757 __gnu_cxx::stdio_filebuf<char> wfile_buf(
2758 file_descriptor, std::ios_base::out | std::ios_base::binary);
2759 std::ostream
f(&wfile_buf);
2760#elif defined(_MSC_VER)
2761 std::ofstream
f(UTF8ToWchar(filepath).c_str(), std::ofstream::binary);
2763 std::ofstream
f(filepath.c_str(), std::ofstream::binary);
2766 std::ofstream
f(filepath.c_str(), std::ofstream::binary);
2770 (*err) +=
"File open error for writing : " + filepath +
"\n";
2775 f.write(
reinterpret_cast<const char *
>(&contents.at(0)),
2776 static_cast<std::streamsize
>(contents.size()));
2779 (*err) +=
"File write error: " + filepath +
"\n";
2789static std::string MimeToExt(
const std::string &mimeType) {
2790 if (mimeType ==
"image/jpeg") {
2792 }
else if (mimeType ==
"image/png") {
2794 }
else if (mimeType ==
"image/bmp") {
2796 }
else if (mimeType ==
"image/gif") {
2803static void UpdateImageObject(
Image &
image, std::string &baseDir,
int index,
2806 void *user_data =
nullptr) {
2807 std::string filename;
2810 if (
image.uri.size()) {
2811 filename = GetBaseFilename(
image.uri);
2812 ext = GetFilePathExtension(filename);
2813 }
else if (
image.bufferView != -1) {
2816 }
else if (
image.name.size()) {
2817 ext = MimeToExt(
image.mimeType);
2819 filename =
image.name +
"." + ext;
2821 ext = MimeToExt(
image.mimeType);
2823 filename = std::to_string(index) +
"." + ext;
2829 (*WriteImageData)(&baseDir, &filename, &
image, embedImages, user_data);
2834 std::string
header =
"data:application/octet-stream;base64,";
2835 if (in.find(
header) == 0) {
2839 header =
"data:image/jpeg;base64,";
2840 if (in.find(
header) == 0) {
2844 header =
"data:image/png;base64,";
2845 if (in.find(
header) == 0) {
2849 header =
"data:image/bmp;base64,";
2850 if (in.find(
header) == 0) {
2854 header =
"data:image/gif;base64,";
2855 if (in.find(
header) == 0) {
2859 header =
"data:text/plain;base64,";
2860 if (in.find(
header) == 0) {
2864 header =
"data:application/gltf-buffer;base64,";
2865 if (in.find(
header) == 0) {
2872 bool DecodeDataURI(std::vector<
unsigned char, ::GameApiAllocator<unsigned char> > *out, std::string &mime_type,
2873 const std::string &in,
size_t reqBytes,
bool checkSize) {
2874 std::string
header =
"data:application/octet-stream;base64,";
2876 if (in.find(
header) == 0) {
2877 data = base64_decode(in.substr(
header.size()));
2881 header =
"data:image/jpeg;base64,";
2882 if (in.find(
header) == 0) {
2883 mime_type =
"image/jpeg";
2884 data = base64_decode(in.substr(
header.size()));
2889 header =
"data:image/png;base64,";
2890 if (in.find(
header) == 0) {
2891 mime_type =
"image/png";
2892 data = base64_decode(in.substr(
header.size()));
2897 header =
"data:image/bmp;base64,";
2898 if (in.find(
header) == 0) {
2899 mime_type =
"image/bmp";
2900 data = base64_decode(in.substr(
header.size()));
2905 header =
"data:image/gif;base64,";
2906 if (in.find(
header) == 0) {
2907 mime_type =
"image/gif";
2908 data = base64_decode(in.substr(
header.size()));
2913 header =
"data:text/plain;base64,";
2914 if (in.find(
header) == 0) {
2915 mime_type =
"text/plain";
2916 data = base64_decode(in.substr(
header.size()));
2921 header =
"data:application/gltf-buffer;base64,";
2922 if (in.find(
header) == 0) {
2923 data = base64_decode(in.substr(
header.size()));
2933 if (
data.size() != reqBytes) {
2936 out->resize(reqBytes);
2938 out->resize(
data.size());
2940 std::copy(
data.begin(),
data.end(), out->begin());
2945bool GetInt(
const json &o,
int &val) {
2946#ifdef TINYGLTF_USE_RAPIDJSON
2947 if (!o.IsDouble()) {
2951 }
else if (o.IsUint()) {
2952 val =
static_cast<int>(o.GetUint());
2954 }
else if (o.IsInt64()) {
2955 val =
static_cast<int>(o.GetInt64());
2957 }
else if (o.IsUint64()) {
2958 val =
static_cast<int>(o.GetUint64());
2965 auto type = o.type();
2967 if ((type == json::value_t::number_integer) ||
2968 (type == json::value_t::number_unsigned)) {
2969 val =
static_cast<int>(o.get<int64_t>());
2977#ifdef TINYGLTF_USE_RAPIDJSON
2978bool GetDouble(
const json &o,
double &val) {
2980 val = o.GetDouble();
2988bool GetNumber(
const json &o,
double &val) {
2989#ifdef TINYGLTF_USE_RAPIDJSON
2991 val = o.GetDouble();
2997 if (o.is_number()) {
2998 val = o.get<
double>();
3006bool GetString(
const json &o, std::string &val) {
3007#ifdef TINYGLTF_USE_RAPIDJSON
3009 val = o.GetString();
3015 if (o.type() == json::value_t::string) {
3016 val = o.get<std::string>();
3024bool IsArray(
const json &o) {
3025#ifdef TINYGLTF_USE_RAPIDJSON
3028 return o.is_array();
3032json_const_array_iterator ArrayBegin(
const json &o) {
3033#ifdef TINYGLTF_USE_RAPIDJSON
3040json_const_array_iterator ArrayEnd(
const json &o) {
3041#ifdef TINYGLTF_USE_RAPIDJSON
3048bool IsObject(
const json &o) {
3049#ifdef TINYGLTF_USE_RAPIDJSON
3050 return o.IsObject();
3052 return o.is_object();
3056json_const_iterator ObjectBegin(
const json &o) {
3057#ifdef TINYGLTF_USE_RAPIDJSON
3058 return o.MemberBegin();
3064json_const_iterator ObjectEnd(
const json &o) {
3065#ifdef TINYGLTF_USE_RAPIDJSON
3066 return o.MemberEnd();
3074std::string GetKey(json_const_iterator &it) {
3075#ifdef TINYGLTF_USE_RAPIDJSON
3076 return it->name.GetString();
3078 return it.key().c_str();
3082bool FindMember(
const json &o,
const char *member, json_const_iterator &it) {
3083#ifdef TINYGLTF_USE_RAPIDJSON
3084 if (!o.IsObject()) {
3087 it = o.FindMember(member);
3088 return it != o.MemberEnd();
3090 it = o.find(member);
3091 return it != o.end();
3095const json &GetValue(json_const_iterator &it) {
3096#ifdef TINYGLTF_USE_RAPIDJSON
3103std::string JsonToString(
const json &o,
int spacing = -1) {
3104#ifdef TINYGLTF_USE_RAPIDJSON
3105 using namespace rapidjson;
3106 StringBuffer buffer;
3107 if (spacing == -1) {
3108 Writer<StringBuffer> writer(buffer);
3111 PrettyWriter<StringBuffer> writer(buffer);
3112 writer.SetIndent(
' ', uint32_t(spacing));
3115 return buffer.GetString();
3117 return o.dump(spacing);
3123static bool ParseJsonAsValue(
Value *
ret,
const json &o) {
3125#ifdef TINYGLTF_USE_RAPIDJSON
3126 using rapidjson::Type;
3127 switch (o.GetType()) {
3128 case Type::kObjectType: {
3130 for (
auto it = o.MemberBegin(); it != o.MemberEnd(); ++it) {
3132 ParseJsonAsValue(&entry, it->value);
3134 value_object.emplace(GetKey(it), std::move(entry));
3136 if (value_object.size() > 0) val =
Value(std::move(value_object));
3138 case Type::kArrayType: {
3140 value_array.reserve(o.Size());
3141 for (
auto it = o.Begin(); it != o.End(); ++it) {
3143 ParseJsonAsValue(&entry, *it);
3145 value_array.emplace_back(std::move(entry));
3147 if (value_array.size() > 0) val =
Value(std::move(value_array));
3149 case Type::kStringType:
3150 val =
Value(std::string(o.GetString()));
3152 case Type::kFalseType:
3153 case Type::kTrueType:
3154 val =
Value(o.GetBool());
3156 case Type::kNumberType:
3157 if (!o.IsDouble()) {
3167 case Type::kNullType:
3173 case json::value_t::object: {
3175 for (
auto it = o.begin(); it != o.end(); it++) {
3177 ParseJsonAsValue(&entry, it.value());
3179 value_object.emplace(it.key(), std::move(entry));
3181 if (value_object.size() > 0) val =
Value(std::move(value_object));
3183 case json::value_t::array: {
3185 value_array.reserve(o.size());
3186 for (
auto it = o.begin(); it != o.end(); it++) {
3188 ParseJsonAsValue(&entry, it.value());
3190 value_array.emplace_back(std::move(entry));
3192 if (value_array.size() > 0) val =
Value(std::move(value_array));
3194 case json::value_t::string:
3195 val =
Value(o.get<std::string>());
3197 case json::value_t::boolean:
3198 val =
Value(o.get<
bool>());
3200 case json::value_t::number_integer:
3201 case json::value_t::number_unsigned:
3202 val =
Value(
static_cast<int>(o.get<int64_t>()));
3204 case json::value_t::number_float:
3205 val =
Value(o.get<
double>());
3207 case json::value_t::null:
3208 case json::value_t::discarded:
3213 if (
ret) *
ret = std::move(val);
3218static bool ParseExtrasProperty(
Value *
ret,
const json &o) {
3219 json_const_iterator it;
3220 if (!FindMember(o,
"extras", it)) {
3224 return ParseJsonAsValue(
ret, GetValue(it));
3227static bool ParseBooleanProperty(
bool *
ret, std::string *err,
const json &o,
3228 const std::string &property,
3229 const bool required,
3230 const std::string &parent_node =
"") {
3231 json_const_iterator it;
3232 if (!FindMember(o, property.c_str(), it)) {
3235 (*err) +=
"'" +
property +
"' property is missing";
3236 if (!parent_node.empty()) {
3237 (*err) +=
" in " + parent_node;
3245 auto &value = GetValue(it);
3248 bool boolValue =
false;
3249#ifdef TINYGLTF_USE_RAPIDJSON
3250 isBoolean = value.IsBool();
3252 boolValue = value.GetBool();
3255 isBoolean = value.is_boolean();
3257 boolValue = value.get<
bool>();
3263 (*err) +=
"'" +
property +
"' property is not a bool type.\n";
3276static bool ParseIntegerProperty(
int *
ret, std::string *err,
const json &o,
3277 const std::string &property,
3278 const bool required,
3279 const std::string &parent_node =
"") {
3280 json_const_iterator it;
3281 if (!FindMember(o, property.c_str(), it)) {
3284 (*err) +=
"'" +
property +
"' property is missing";
3285 if (!parent_node.empty()) {
3286 (*err) +=
" in " + parent_node;
3295 bool isInt = GetInt(GetValue(it), intValue);
3299 (*err) +=
"'" +
property +
"' property is not an integer type.\n";
3312static bool ParseUnsignedProperty(
size_t *
ret, std::string *err,
const json &o,
3313 const std::string &property,
3314 const bool required,
3315 const std::string &parent_node =
"") {
3316 json_const_iterator it;
3317 if (!FindMember(o, property.c_str(), it)) {
3320 (*err) +=
"'" +
property +
"' property is missing";
3321 if (!parent_node.empty()) {
3322 (*err) +=
" in " + parent_node;
3330 auto &value = GetValue(it);
3334#ifdef TINYGLTF_USE_RAPIDJSON
3336 if (value.IsUint()) {
3337 uValue = value.GetUint();
3339 }
else if (value.IsUint64()) {
3340 uValue = value.GetUint64();
3344 isUValue = value.is_number_unsigned();
3346 uValue = value.get<
size_t>();
3352 (*err) +=
"'" +
property +
"' property is not a positive integer.\n";
3365static bool ParseNumberProperty(
double *
ret, std::string *err,
const json &o,
3366 const std::string &property,
3367 const bool required,
3368 const std::string &parent_node =
"") {
3369 json_const_iterator it;
3371 if (!FindMember(o, property.c_str(), it)) {
3374 (*err) +=
"'" +
property +
"' property is missing";
3375 if (!parent_node.empty()) {
3376 (*err) +=
" in " + parent_node;
3385 bool isNumber = GetNumber(GetValue(it), numberValue);
3390 (*err) +=
"'" +
property +
"' property is not a number type.\n";
3397 (*ret) = numberValue;
3403static bool ParseNumberArrayProperty(std::vector<double> *
ret, std::string *err,
3404 const json &o,
const std::string &property,
3406 const std::string &parent_node =
"") {
3407 json_const_iterator it;
3408 if (!FindMember(o, property.c_str(), it)) {
3411 (*err) +=
"'" +
property +
"' property is missing";
3412 if (!parent_node.empty()) {
3413 (*err) +=
" in " + parent_node;
3421 if (!IsArray(GetValue(it))) {
3424 (*err) +=
"'" +
property +
"' property is not an array";
3425 if (!parent_node.empty()) {
3426 (*err) +=
" in " + parent_node;
3435 auto end = ArrayEnd(GetValue(it));
3436 for (
auto i = ArrayBegin(GetValue(it)); i !=
end; ++i) {
3438 const bool isNumber = GetNumber(*i, numberValue);
3442 (*err) +=
"'" +
property +
"' property is not a number.\n";
3443 if (!parent_node.empty()) {
3444 (*err) +=
" in " + parent_node;
3451 ret->push_back(numberValue);
3457static bool ParseIntegerArrayProperty(std::vector<int> *
ret, std::string *err,
3459 const std::string &property,
3461 const std::string &parent_node =
"") {
3462 json_const_iterator it;
3463 if (!FindMember(o, property.c_str(), it)) {
3466 (*err) +=
"'" +
property +
"' property is missing";
3467 if (!parent_node.empty()) {
3468 (*err) +=
" in " + parent_node;
3476 if (!IsArray(GetValue(it))) {
3479 (*err) +=
"'" +
property +
"' property is not an array";
3480 if (!parent_node.empty()) {
3481 (*err) +=
" in " + parent_node;
3490 auto end = ArrayEnd(GetValue(it));
3491 for (
auto i = ArrayBegin(GetValue(it)); i !=
end; ++i) {
3493 bool isNumber = GetInt(*i, numberValue);
3497 (*err) +=
"'" +
property +
"' property is not an integer type.\n";
3498 if (!parent_node.empty()) {
3499 (*err) +=
" in " + parent_node;
3506 ret->push_back(numberValue);
3512static bool ParseStringProperty(
3513 std::string *
ret, std::string *err,
const json &o,
3514 const std::string &property,
bool required,
3515 const std::string &parent_node = std::string()) {
3516 json_const_iterator it;
3517 if (!FindMember(o, property.c_str(), it)) {
3520 (*err) +=
"'" +
property +
"' property is missing";
3521 if (parent_node.empty()) {
3524 (*err) +=
" in `" + parent_node +
"'.\n";
3531 std::string strValue;
3532 if (!GetString(GetValue(it), strValue)) {
3535 (*err) +=
"'" +
property +
"' property is not a string type.\n";
3542 (*ret) = std::move(strValue);
3548static bool ParseStringIntegerProperty(std::map<std::string, int> *
ret,
3549 std::string *err,
const json &o,
3550 const std::string &property,
3552 const std::string &parent =
"") {
3553 json_const_iterator it;
3554 if (!FindMember(o, property.c_str(), it)) {
3557 if (!parent.empty()) {
3559 "'" +
property +
"' property is missing in " + parent +
".\n";
3561 (*err) +=
"'" +
property +
"' property is missing.\n";
3568 const json &dict = GetValue(it);
3571 if (!IsObject(dict)) {
3574 (*err) +=
"'" +
property +
"' property is not an object.\n";
3582 json_const_iterator dictIt(ObjectBegin(dict));
3583 json_const_iterator dictItEnd(ObjectEnd(dict));
3585 for (; dictIt != dictItEnd; ++dictIt) {
3587 if (!GetInt(GetValue(dictIt), intVal)) {
3590 (*err) +=
"'" +
property +
"' value is not an integer type.\n";
3597 (*ret)[GetKey(dictIt)] = intVal;
3602static bool ParseJSONProperty(std::map<std::string, double> *
ret,
3603 std::string *err,
const json &o,
3604 const std::string &property,
bool required) {
3605 json_const_iterator it;
3606 if (!FindMember(o, property.c_str(), it)) {
3609 (*err) +=
"'" +
property +
"' property is missing. \n'";
3615 const json &obj = GetValue(it);
3617 if (!IsObject(obj)) {
3620 (*err) +=
"'" +
property +
"' property is not a JSON object.\n";
3628 json_const_iterator it2(ObjectBegin(obj));
3629 json_const_iterator itEnd(ObjectEnd(obj));
3630 for (; it2 != itEnd; ++it2) {
3632 if (GetNumber(GetValue(it2), numVal))
3633 ret->emplace(std::string(GetKey(it2)), numVal);
3639static bool ParseParameterProperty(
Parameter *param, std::string *err,
3640 const json &o,
const std::string &prop,
3647 if (ParseStringProperty(¶m->string_value, err, o, prop,
false)) {
3650 }
else if (ParseNumberArrayProperty(¶m->number_array, err, o, prop,
3654 }
else if (ParseNumberProperty(¶m->number_value, err, o, prop,
false)) {
3655 return param->has_number_value =
true;
3656 }
else if (ParseJSONProperty(¶m->json_double_value, err, o, prop,
3659 }
else if (ParseBooleanProperty(¶m->bool_value, err, o, prop,
false)) {
3664 (*err) +=
"parameter must be a string or number / number array.\n";
3671static bool ParseExtensionsProperty(
ExtensionMap *
ret, std::string *err,
3675 json_const_iterator it;
3676 if (!FindMember(o,
"extensions", it)) {
3680 auto &obj = GetValue(it);
3681 if (!IsObject(obj)) {
3685 json_const_iterator extIt = ObjectBegin(obj);
3686 json_const_iterator extEnd = ObjectEnd(obj);
3687 for (; extIt != extEnd; ++extIt) {
3688 auto &itObj = GetValue(extIt);
3689 if (!IsObject(itObj))
continue;
3690 std::string key(GetKey(extIt));
3691 if (!ParseJsonAsValue(&extensions[key], itObj)) {
3700 (*ret) = std::move(extensions);
3705static bool ParseAsset(
Asset *asset, std::string *err,
const json &o,
3706 bool store_original_json_for_extras_and_extensions) {
3707 ParseStringProperty(&asset->version, err, o,
"version",
true,
"Asset");
3708 ParseStringProperty(&asset->generator, err, o,
"generator",
false,
"Asset");
3709 ParseStringProperty(&asset->minVersion, err, o,
"minVersion",
false,
"Asset");
3710 ParseStringProperty(&asset->copyright, err, o,
"copyright",
false,
"Asset");
3712 ParseExtensionsProperty(&asset->extensions, err, o);
3715 ParseExtrasProperty(&(asset->extras), o);
3717 if (store_original_json_for_extras_and_extensions) {
3719 json_const_iterator it;
3720 if (FindMember(o,
"extensions", it)) {
3721 asset->extensions_json_string = JsonToString(GetValue(it));
3725 json_const_iterator it;
3726 if (FindMember(o,
"extras", it)) {
3727 asset->extras_json_string = JsonToString(GetValue(it));
3735static bool ParseImage(
Image *
image,
const int image_idx, std::string *err,
3736 std::string *warn,
const json &o,
3737 bool store_original_json_for_extras_and_extensions,
3740 void *load_image_user_data =
nullptr) {
3745 json_const_iterator it;
3746 bool hasBufferView = FindMember(o,
"bufferView", it);
3747 bool hasURI = FindMember(o,
"uri", it);
3749 ParseStringProperty(&
image->name, err, o,
"name",
false);
3751 if (hasBufferView && hasURI) {
3755 "Only one of `bufferView` or `uri` should be defined, but both are "
3756 "defined for image[" +
3757 std::to_string(image_idx) +
"] name = \"" +
image->name +
"\"\n";
3762 if (!hasBufferView && !hasURI) {
3764 (*err) +=
"Neither required `bufferView` nor `uri` defined for image[" +
3765 std::to_string(image_idx) +
"] name = \"" +
image->name +
3771 ParseExtensionsProperty(&
image->extensions, err, o);
3772 ParseExtrasProperty(&
image->extras, o);
3774 if (store_original_json_for_extras_and_extensions) {
3776 json_const_iterator eit;
3777 if (FindMember(o,
"extensions", eit)) {
3778 image->extensions_json_string = JsonToString(GetValue(eit));
3782 json_const_iterator eit;
3783 if (FindMember(o,
"extras", eit)) {
3784 image->extras_json_string = JsonToString(GetValue(eit));
3789 if (hasBufferView) {
3790 int bufferView = -1;
3791 if (!ParseIntegerProperty(&bufferView, err, o,
"bufferView",
true)) {
3793 (*err) +=
"Failed to parse `bufferView` for image[" +
3794 std::to_string(image_idx) +
"] name = \"" +
image->name +
3800 std::string mime_type;
3801 ParseStringProperty(&mime_type, err, o,
"mimeType",
false);
3804 ParseIntegerProperty(&width, err, o,
"width",
false);
3807 ParseIntegerProperty(&
height, err, o,
"height",
false);
3811 image->bufferView = bufferView;
3812 image->mimeType = mime_type;
3813 image->width = width;
3822 std::string tmp_err;
3823 if (!ParseStringProperty(&uri, &tmp_err, o,
"uri",
true)) {
3825 (*err) +=
"Failed to parse `uri` for image[" + std::to_string(image_idx) +
3826 "] name = \"" +
image->name +
"\".\n";
3831 std::vector<unsigned char, ::GameApiAllocator<unsigned char> > img;
3836 (*err) +=
"Failed to decode 'uri' for image[" +
3837 std::to_string(image_idx) +
"] name = [" +
image->name +
3846#ifdef TINYGLTF_NO_EXTERNAL_IMAGE
3849 std::string decoded_uri = dlib::urldecode(uri);
3850 if (!LoadExternalFile(&img, err, warn, decoded_uri, basedir,
3854 (*warn) +=
"Failed to load external 'uri' for image[" +
3855 std::to_string(image_idx) +
"] name = [" +
image->name +
3861 if (img.empty()) { img.push_back(
' '); }
3875 (*err) +=
"No LoadImageData callback specified.\n";
3880 static_cast<int>(img.size()), load_image_user_data);
3883static bool ParseTexture(
Texture *texture, std::string *err,
const json &o,
3884 bool store_original_json_for_extras_and_extensions,
3885 const std::string &basedir) {
3889 ParseIntegerProperty(&sampler, err, o,
"sampler",
false);
3891 ParseIntegerProperty(&source, err, o,
"source",
false);
3893 texture->sampler = sampler;
3894 texture->source = source;
3896 ParseExtensionsProperty(&texture->extensions, err, o);
3897 ParseExtrasProperty(&texture->extras, o);
3899 if (store_original_json_for_extras_and_extensions) {
3901 json_const_iterator it;
3902 if (FindMember(o,
"extensions", it)) {
3903 texture->extensions_json_string = JsonToString(GetValue(it));
3907 json_const_iterator it;
3908 if (FindMember(o,
"extras", it)) {
3909 texture->extras_json_string = JsonToString(GetValue(it));
3914 ParseStringProperty(&texture->name, err, o,
"name",
false);
3919static bool ParseTextureInfo(
3920 TextureInfo *texinfo, std::string *err,
const json &o,
3921 bool store_original_json_for_extras_and_extensions) {
3922 if (texinfo ==
nullptr) {
3926 if (!ParseIntegerProperty(&texinfo->index, err, o,
"index",
3927 true,
"TextureInfo")) {
3931 ParseIntegerProperty(&texinfo->texCoord, err, o,
"texCoord",
false);
3933 ParseExtensionsProperty(&texinfo->extensions, err, o);
3934 ParseExtrasProperty(&texinfo->extras, o);
3936 if (store_original_json_for_extras_and_extensions) {
3938 json_const_iterator it;
3939 if (FindMember(o,
"extensions", it)) {
3940 texinfo->extensions_json_string = JsonToString(GetValue(it));
3944 json_const_iterator it;
3945 if (FindMember(o,
"extras", it)) {
3946 texinfo->extras_json_string = JsonToString(GetValue(it));
3954static bool ParseNormalTextureInfo(
3956 bool store_original_json_for_extras_and_extensions) {
3957 if (texinfo ==
nullptr) {
3961 if (!ParseIntegerProperty(&texinfo->index, err, o,
"index",
3962 true,
"NormalTextureInfo")) {
3966 ParseIntegerProperty(&texinfo->texCoord, err, o,
"texCoord",
false);
3967 ParseNumberProperty(&texinfo->scale, err, o,
"scale",
false);
3969 ParseExtensionsProperty(&texinfo->extensions, err, o);
3970 ParseExtrasProperty(&texinfo->extras, o);
3972 if (store_original_json_for_extras_and_extensions) {
3974 json_const_iterator it;
3975 if (FindMember(o,
"extensions", it)) {
3976 texinfo->extensions_json_string = JsonToString(GetValue(it));
3980 json_const_iterator it;
3981 if (FindMember(o,
"extras", it)) {
3982 texinfo->extras_json_string = JsonToString(GetValue(it));
3990static bool ParseOcclusionTextureInfo(
3992 bool store_original_json_for_extras_and_extensions) {
3993 if (texinfo ==
nullptr) {
3997 if (!ParseIntegerProperty(&texinfo->index, err, o,
"index",
3998 true,
"NormalTextureInfo")) {
4002 ParseIntegerProperty(&texinfo->texCoord, err, o,
"texCoord",
false);
4003 ParseNumberProperty(&texinfo->strength, err, o,
"strength",
false);
4005 ParseExtensionsProperty(&texinfo->extensions, err, o);
4006 ParseExtrasProperty(&texinfo->extras, o);
4008 if (store_original_json_for_extras_and_extensions) {
4010 json_const_iterator it;
4011 if (FindMember(o,
"extensions", it)) {
4012 texinfo->extensions_json_string = JsonToString(GetValue(it));
4016 json_const_iterator it;
4017 if (FindMember(o,
"extras", it)) {
4018 texinfo->extras_json_string = JsonToString(GetValue(it));
4026static bool ParseBuffer(
Buffer *buffer, std::string *err,
const json &o,
4027 bool store_original_json_for_extras_and_extensions,
4029 bool is_binary =
false,
4030 const unsigned char *bin_data =
nullptr,
4031 size_t bin_size = 0) {
4033 if (!ParseUnsignedProperty(&byteLength, err, o,
"byteLength",
true,
4039 buffer->uri.clear();
4040 ParseStringProperty(&buffer->uri, err, o,
"uri",
false,
"Buffer");
4043 if (!is_binary && buffer->uri.empty()) {
4045 (*err) +=
"'uri' is missing from non binary glTF file buffer.\n";
4049 json_const_iterator type;
4050 if (FindMember(o,
"type", type)) {
4051 std::string typeStr;
4052 if (GetString(GetValue(type), typeStr)) {
4053 if (typeStr.compare(
"arraybuffer") == 0) {
4061 if (!buffer->uri.empty()) {
4064 std::string mime_type;
4065 if (!
DecodeDataURI(&buffer->data, mime_type, buffer->uri, byteLength,
4069 "Failed to decode 'uri' : " + buffer->uri +
" in Buffer\n";
4075 std::string decoded_uri = dlib::urldecode(buffer->uri);
4076 if (!LoadExternalFile(&buffer->data, err,
nullptr,
4077 decoded_uri, basedir,
true,
4078 byteLength,
false, fs)) {
4085 if ((bin_size == 0) || (bin_data ==
nullptr)) {
4087 (*err) +=
"Invalid binary data in `Buffer'.\n";
4092 if (byteLength > bin_size) {
4094 std::stringstream ss;
4095 ss <<
"Invalid `byteLength'. Must be equal or less than binary size: "
4097 << byteLength <<
", binary size = " << bin_size << std::endl;
4104 buffer->data.resize(
static_cast<size_t>(byteLength));
4105 memcpy(&(buffer->data.at(0)), bin_data,
static_cast<size_t>(byteLength));
4110 std::string mime_type;
4111 if (!
DecodeDataURI(&buffer->data, mime_type, buffer->uri, byteLength,
4114 (*err) +=
"Failed to decode 'uri' : " + buffer->uri +
" in Buffer\n";
4120 std::string decoded_uri = dlib::urldecode(buffer->uri);
4121 if (!LoadExternalFile(&buffer->data, err,
nullptr, decoded_uri,
4122 basedir,
true, byteLength,
4129 ParseStringProperty(&buffer->name, err, o,
"name",
false);
4131 ParseExtensionsProperty(&buffer->extensions, err, o);
4132 ParseExtrasProperty(&buffer->extras, o);
4134 if (store_original_json_for_extras_and_extensions) {
4136 json_const_iterator it;
4137 if (FindMember(o,
"extensions", it)) {
4138 buffer->extensions_json_string = JsonToString(GetValue(it));
4142 json_const_iterator it;
4143 if (FindMember(o,
"extras", it)) {
4144 buffer->extras_json_string = JsonToString(GetValue(it));
4152static bool ParseBufferView(
4153 BufferView *bufferView, std::string *err,
const json &o,
4154 bool store_original_json_for_extras_and_extensions) {
4156 if (!ParseIntegerProperty(&buffer, err, o,
"buffer",
true,
"BufferView")) {
4160 size_t byteOffset = 0;
4161 ParseUnsignedProperty(&byteOffset, err, o,
"byteOffset",
false);
4163 size_t byteLength = 1;
4164 if (!ParseUnsignedProperty(&byteLength, err, o,
"byteLength",
true,
4169 size_t byteStride = 0;
4170 if (!ParseUnsignedProperty(&byteStride, err, o,
"byteStride",
false)) {
4179 if ((byteStride > 252) || ((byteStride % 4) != 0)) {
4181 std::stringstream ss;
4182 ss <<
"Invalid `byteStride' value. `byteStride' must be the multiple of "
4184 << byteStride << std::endl;
4192 ParseIntegerProperty(&target, err, o,
"target",
false);
4199 bufferView->target = target;
4201 ParseStringProperty(&bufferView->name, err, o,
"name",
false);
4203 ParseExtensionsProperty(&bufferView->extensions, err, o);
4204 ParseExtrasProperty(&bufferView->extras, o);
4206 if (store_original_json_for_extras_and_extensions) {
4208 json_const_iterator it;
4209 if (FindMember(o,
"extensions", it)) {
4210 bufferView->extensions_json_string = JsonToString(GetValue(it));
4214 json_const_iterator it;
4215 if (FindMember(o,
"extras", it)) {
4216 bufferView->extras_json_string = JsonToString(GetValue(it));
4221 bufferView->buffer = buffer;
4222 bufferView->byteOffset = byteOffset;
4223 bufferView->byteLength = byteLength;
4224 bufferView->byteStride = byteStride;
4228static bool ParseSparseAccessor(
Accessor *accessor, std::string *err,
4230 accessor->sparse.isSparse =
true;
4233 ParseIntegerProperty(&count, err, o,
"count",
true);
4235 json_const_iterator indices_iterator;
4236 json_const_iterator values_iterator;
4237 if (!FindMember(o,
"indices", indices_iterator)) {
4238 (*err) =
"the sparse object of this accessor doesn't have indices";
4242 if (!FindMember(o,
"values", values_iterator)) {
4243 (*err) =
"the sparse object ob ths accessor doesn't have values";
4247 const json &indices_obj = GetValue(indices_iterator);
4248 const json &values_obj = GetValue(values_iterator);
4250 int indices_buffer_view = 0, indices_byte_offset = 0, component_type = 0;
4251 ParseIntegerProperty(&indices_buffer_view, err, indices_obj,
"bufferView",
4253 ParseIntegerProperty(&indices_byte_offset, err, indices_obj,
"byteOffset",
4255 ParseIntegerProperty(&component_type, err, indices_obj,
"componentType",
4258 int values_buffer_view = 0, values_byte_offset = 0;
4259 ParseIntegerProperty(&values_buffer_view, err, values_obj,
"bufferView",
4261 ParseIntegerProperty(&values_byte_offset, err, values_obj,
"byteOffset",
4264 accessor->sparse.count =
count;
4265 accessor->sparse.indices.bufferView = indices_buffer_view;
4266 accessor->sparse.indices.byteOffset = indices_byte_offset;
4267 accessor->sparse.indices.componentType = component_type;
4268 accessor->sparse.values.bufferView = values_buffer_view;
4269 accessor->sparse.values.byteOffset = values_byte_offset;
4276static bool ParseAccessor(
Accessor *accessor, std::string *err,
const json &o,
4277 bool store_original_json_for_extras_and_extensions) {
4278 int bufferView = -1;
4279 ParseIntegerProperty(&bufferView, err, o,
"bufferView",
false,
"Accessor");
4281 size_t byteOffset = 0;
4282 ParseUnsignedProperty(&byteOffset, err, o,
"byteOffset",
false,
"Accessor");
4284 bool normalized =
false;
4285 ParseBooleanProperty(&normalized, err, o,
"normalized",
false,
"Accessor");
4287 size_t componentType = 0;
4288 if (!ParseUnsignedProperty(&componentType, err, o,
"componentType",
true,
4294 if (!ParseUnsignedProperty(&count, err, o,
"count",
true,
"Accessor")) {
4299 if (!ParseStringProperty(&type, err, o,
"type",
true,
"Accessor")) {
4303 if (type.compare(
"SCALAR") == 0) {
4305 }
else if (type.compare(
"VEC2") == 0) {
4307 }
else if (type.compare(
"VEC3") == 0) {
4309 }
else if (type.compare(
"VEC4") == 0) {
4311 }
else if (type.compare(
"MAT2") == 0) {
4313 }
else if (type.compare(
"MAT3") == 0) {
4315 }
else if (type.compare(
"MAT4") == 0) {
4318 std::stringstream ss;
4319 ss <<
"Unsupported `type` for accessor object. Got \"" << type <<
"\"\n";
4326 ParseStringProperty(&accessor->name, err, o,
"name",
false);
4328 accessor->minValues.clear();
4329 accessor->maxValues.clear();
4330 ParseNumberArrayProperty(&accessor->minValues, err, o,
"min",
false,
4333 ParseNumberArrayProperty(&accessor->maxValues, err, o,
"max",
false,
4336 accessor->count =
count;
4337 accessor->bufferView = bufferView;
4338 accessor->byteOffset = byteOffset;
4339 accessor->normalized = normalized;
4344 accessor->componentType = int(componentType);
4346 std::stringstream ss;
4347 ss <<
"Invalid `componentType` in accessor. Got " << componentType
4356 ParseExtensionsProperty(&(accessor->extensions), err, o);
4357 ParseExtrasProperty(&(accessor->extras), o);
4359 if (store_original_json_for_extras_and_extensions) {
4361 json_const_iterator it;
4362 if (FindMember(o,
"extensions", it)) {
4363 accessor->extensions_json_string = JsonToString(GetValue(it));
4367 json_const_iterator it;
4368 if (FindMember(o,
"extras", it)) {
4369 accessor->extras_json_string = JsonToString(GetValue(it));
4375 json_const_iterator iterator;
4376 if (FindMember(o,
"sparse", iterator)) {
4378 return ParseSparseAccessor(accessor, err, GetValue(iterator));
4384#ifdef TINYGLTF_ENABLE_DRACO
4386static void DecodeIndexBuffer(draco::Mesh *mesh,
size_t componentSize,
4387 std::vector<uint8_t, ::GameApiAllocator<uint8_t> > &outBuffer) {
4388 if (componentSize == 4) {
4393 size_t faceStride = componentSize * 3;
4396 if (componentSize == 2) {
4397 uint16_t indices[3] = {(uint16_t)face[0].value(),
4398 (uint16_t)face[1].value(),
4399 (uint16_t)face[2].value()};
4400 memcpy(outBuffer.data() +
f.value() * faceStride, &indices[0],
4403 uint8_t indices[3] = {(uint8_t)face[0].value(),
4404 (uint8_t)face[1].value(),
4405 (uint8_t)face[2].value()};
4406 memcpy(outBuffer.data() +
f.value() * faceStride, &indices[0],
4413template <
typename T>
4414static bool GetAttributeForAllPoints(draco::Mesh *mesh,
4415 const draco::PointAttribute *pAttribute,
4416 std::vector<uint8_t,::GameApiAllocator<uint8_t> > &outBuffer) {
4417 size_t byteOffset = 0;
4418 T values[4] = {0, 0, 0, 0};
4419 for (draco::PointIndex i(0); i < mesh->
num_points(); ++i) {
4420 const draco::AttributeValueIndex val_index = pAttribute->
mapped_index(i);
4425 memcpy(outBuffer.data() + byteOffset, &values[0],
4433static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
4434 const draco::PointAttribute *pAttribute,
4435 std::vector<uint8_t, ::GameApiAllocator<uint8_t> > &outBuffer) {
4436 bool decodeResult =
false;
4437 switch (componentType) {
4440 GetAttributeForAllPoints<uint8_t>(mesh, pAttribute, outBuffer);
4444 GetAttributeForAllPoints<int8_t>(mesh, pAttribute, outBuffer);
4448 GetAttributeForAllPoints<uint16_t>(mesh, pAttribute, outBuffer);
4452 GetAttributeForAllPoints<int16_t>(mesh, pAttribute, outBuffer);
4456 GetAttributeForAllPoints<int32_t>(mesh, pAttribute, outBuffer);
4460 GetAttributeForAllPoints<uint32_t>(mesh, pAttribute, outBuffer);
4464 GetAttributeForAllPoints<float>(mesh, pAttribute, outBuffer);
4468 GetAttributeForAllPoints<double>(mesh, pAttribute, outBuffer);
4474 return decodeResult;
4477static bool ParseDracoExtension(
Primitive *primitive,
Model *model,
4479 const Value &dracoExtensionValue) {
4481 auto bufferViewValue = dracoExtensionValue.Get(
"bufferView");
4482 if (!bufferViewValue.IsInt())
return false;
4483 auto attributesValue = dracoExtensionValue.Get(
"attributes");
4484 if (!attributesValue.IsObject())
return false;
4486 auto attributesObject = attributesValue.Get<
Value::Object>();
4487 int bufferView = bufferViewValue.Get<
int>();
4489 BufferView &view = model->bufferViews[bufferView];
4490 Buffer &buffer = model->buffers[view.buffer];
4492 if (view.dracoDecoded)
return true;
4493 view.dracoDecoded =
true;
4495 const char *bufferViewData =
4496 reinterpret_cast<const char *
>(buffer.data.data() + view.byteOffset);
4497 size_t bufferViewSize = view.byteLength;
4500 draco::DecoderBuffer decoderBuffer;
4501 decoderBuffer.
Init(bufferViewData, bufferViewSize);
4502 draco::Decoder decoder;
4504 if (!decodeResult.ok()) {
4507 const std::unique_ptr<draco::Mesh> &mesh = decodeResult.value();
4510 if (primitive->indices >= 0) {
4511 int32_t componentSize = GetComponentSizeInBytes(
4512 model->accessors[primitive->indices].componentType);
4513 Buffer decodedIndexBuffer;
4514 decodedIndexBuffer.
data.resize(mesh->num_faces() * 3 * componentSize);
4516 DecodeIndexBuffer(mesh.get(), componentSize, decodedIndexBuffer.data);
4518 model->buffers.emplace_back(std::move(decodedIndexBuffer));
4521 decodedIndexBufferView.
buffer = int(model->buffers.size() - 1);
4522 decodedIndexBufferView.byteLength =
4523 int(mesh->num_faces() * 3 * componentSize);
4524 decodedIndexBufferView.byteOffset = 0;
4525 decodedIndexBufferView.byteStride = 0;
4527 model->bufferViews.emplace_back(std::move(decodedIndexBufferView));
4529 model->accessors[primitive->indices].bufferView =
4530 int(model->bufferViews.size() - 1);
4531 model->accessors[primitive->indices].count = int(mesh->num_faces() * 3);
4534 for (
const auto &attribute : attributesObject) {
4535 if (!attribute.second.IsInt())
return false;
4536 auto primitiveAttribute = primitive->attributes.find(attribute.first);
4537 if (primitiveAttribute == primitive->attributes.end())
return false;
4539 int dracoAttributeIndex = attribute.second.Get<
int>();
4540 const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
4541 const auto componentType =
4542 model->accessors[primitiveAttribute->second].componentType;
4546 size_t bufferSize = mesh->num_points() * pAttribute->num_components() *
4547 GetComponentSizeInBytes(componentType);
4548 decodedBuffer.data.resize(bufferSize);
4550 if (!GetAttributeForAllPoints(componentType, mesh.get(), pAttribute,
4551 decodedBuffer.data))
4554 model->buffers.emplace_back(std::move(decodedBuffer));
4557 decodedBufferView.
buffer = int(model->buffers.size() - 1);
4558 decodedBufferView.byteLength = bufferSize;
4559 decodedBufferView.byteOffset = pAttribute->byte_offset();
4560 decodedBufferView.byteStride = pAttribute->byte_stride();
4561 decodedBufferView.target = primitive->indices >= 0
4564 model->bufferViews.emplace_back(std::move(decodedBufferView));
4566 model->accessors[primitiveAttribute->second].bufferView =
4567 int(model->bufferViews.size() - 1);
4568 model->accessors[primitiveAttribute->second].count =
4569 int(mesh->num_points());
4576static bool ParsePrimitive(
Primitive *primitive,
Model *model, std::string *err,
4578 bool store_original_json_for_extras_and_extensions) {
4580 ParseIntegerProperty(&material, err, o,
"material",
false);
4581 primitive->material = material;
4584 ParseIntegerProperty(&mode, err, o,
"mode",
false);
4585 primitive->mode = mode;
4588 ParseIntegerProperty(&indices, err, o,
"indices",
false);
4589 primitive->indices = indices;
4590 if (!ParseStringIntegerProperty(&primitive->attributes, err, o,
"attributes",
4591 true,
"Primitive")) {
4596 json_const_iterator targetsObject;
4597 if (FindMember(o,
"targets", targetsObject) &&
4598 IsArray(GetValue(targetsObject))) {
4599 auto targetsObjectEnd = ArrayEnd(GetValue(targetsObject));
4600 for (json_const_array_iterator i = ArrayBegin(GetValue(targetsObject));
4601 i != targetsObjectEnd; ++i) {
4602 std::map<std::string, int> targetAttribues;
4604 const json &dict = *i;
4605 if (IsObject(dict)) {
4606 json_const_iterator dictIt(ObjectBegin(dict));
4607 json_const_iterator dictItEnd(ObjectEnd(dict));
4609 for (; dictIt != dictItEnd; ++dictIt) {
4611 if (GetInt(GetValue(dictIt), iVal))
4612 targetAttribues[GetKey(dictIt)] = iVal;
4614 primitive->targets.emplace_back(std::move(targetAttribues));
4619 ParseExtrasProperty(&(primitive->extras), o);
4620 ParseExtensionsProperty(&primitive->extensions, err, o);
4622 if (store_original_json_for_extras_and_extensions) {
4624 json_const_iterator it;
4625 if (FindMember(o,
"extensions", it)) {
4626 primitive->extensions_json_string = JsonToString(GetValue(it));
4630 json_const_iterator it;
4631 if (FindMember(o,
"extras", it)) {
4632 primitive->extras_json_string = JsonToString(GetValue(it));
4637#ifdef TINYGLTF_ENABLE_DRACO
4638 auto dracoExtension =
4639 primitive->extensions.find(
"KHR_draco_mesh_compression");
4640 if (dracoExtension != primitive->extensions.end()) {
4641 ParseDracoExtension(primitive, model, err, dracoExtension->second);
4650static bool ParseMesh(
Mesh *mesh,
Model *model, std::string *err,
const json &o,
4651 bool store_original_json_for_extras_and_extensions) {
4652 ParseStringProperty(&mesh->name, err, o,
"name",
false);
4654 mesh->primitives.clear();
4655 json_const_iterator primObject;
4656 if (FindMember(o,
"primitives", primObject) &&
4657 IsArray(GetValue(primObject))) {
4658 json_const_array_iterator primEnd = ArrayEnd(GetValue(primObject));
4659 for (json_const_array_iterator i = ArrayBegin(GetValue(primObject));
4660 i != primEnd; ++i) {
4662 if (ParsePrimitive(&primitive, model, err, *i,
4663 store_original_json_for_extras_and_extensions)) {
4665 mesh->primitives.emplace_back(std::move(primitive));
4671 ParseNumberArrayProperty(&mesh->weights, err, o,
"weights",
false);
4673 ParseExtensionsProperty(&mesh->extensions, err, o);
4674 ParseExtrasProperty(&(mesh->extras), o);
4676 if (store_original_json_for_extras_and_extensions) {
4678 json_const_iterator it;
4679 if (FindMember(o,
"extensions", it)) {
4680 mesh->extensions_json_string = JsonToString(GetValue(it));
4684 json_const_iterator it;
4685 if (FindMember(o,
"extras", it)) {
4686 mesh->extras_json_string = JsonToString(GetValue(it));
4694static bool ParseNode(
Node *node, std::string *err,
const json &o,
4695 bool store_original_json_for_extras_and_extensions) {
4696 ParseStringProperty(&node->name, err, o,
"name",
false);
4699 ParseIntegerProperty(&skin, err, o,
"skin",
false);
4703 if (!ParseNumberArrayProperty(&node->matrix, err, o,
"matrix",
false)) {
4704 ParseNumberArrayProperty(&node->rotation, err, o,
"rotation",
false);
4705 ParseNumberArrayProperty(&node->scale, err, o,
"scale",
false);
4706 ParseNumberArrayProperty(&node->translation, err, o,
"translation",
false);
4710 ParseIntegerProperty(&camera, err, o,
"camera",
false);
4711 node->camera = camera;
4714 ParseIntegerProperty(&mesh, err, o,
"mesh",
false);
4717 node->children.clear();
4718 ParseIntegerArrayProperty(&node->children, err, o,
"children",
false);
4720 ParseNumberArrayProperty(&node->weights, err, o,
"weights",
false);
4722 ParseExtensionsProperty(&node->extensions, err, o);
4723 ParseExtrasProperty(&(node->extras), o);
4725 if (store_original_json_for_extras_and_extensions) {
4727 json_const_iterator it;
4728 if (FindMember(o,
"extensions", it)) {
4729 node->extensions_json_string = JsonToString(GetValue(it));
4733 json_const_iterator it;
4734 if (FindMember(o,
"extras", it)) {
4735 node->extras_json_string = JsonToString(GetValue(it));
4743static bool ParsePbrMetallicRoughness(
4745 bool store_original_json_for_extras_and_extensions) {
4746 if (pbr ==
nullptr) {
4750 std::vector<double> baseColorFactor;
4751 if (ParseNumberArrayProperty(&baseColorFactor, err, o,
"baseColorFactor",
4753 if (baseColorFactor.size() != 4) {
4756 "Array length of `baseColorFactor` parameter in "
4757 "pbrMetallicRoughness must be 4, but got " +
4758 std::to_string(baseColorFactor.size()) +
"\n";
4762 pbr->baseColorFactor = baseColorFactor;
4766 json_const_iterator it;
4767 if (FindMember(o,
"baseColorTexture", it)) {
4768 ParseTextureInfo(&pbr->baseColorTexture, err, GetValue(it),
4769 store_original_json_for_extras_and_extensions);
4774 json_const_iterator it;
4775 if (FindMember(o,
"metallicRoughnessTexture", it)) {
4776 ParseTextureInfo(&pbr->metallicRoughnessTexture, err, GetValue(it),
4777 store_original_json_for_extras_and_extensions);
4781 ParseNumberProperty(&pbr->metallicFactor, err, o,
"metallicFactor",
false);
4782 ParseNumberProperty(&pbr->roughnessFactor, err, o,
"roughnessFactor",
false);
4784 ParseExtensionsProperty(&pbr->extensions, err, o);
4785 ParseExtrasProperty(&pbr->extras, o);
4787 if (store_original_json_for_extras_and_extensions) {
4789 json_const_iterator it;
4790 if (FindMember(o,
"extensions", it)) {
4791 pbr->extensions_json_string = JsonToString(GetValue(it));
4795 json_const_iterator it;
4796 if (FindMember(o,
"extras", it)) {
4797 pbr->extras_json_string = JsonToString(GetValue(it));
4805static bool ParseMaterial(
Material *material, std::string *err,
const json &o,
4806 bool store_original_json_for_extras_and_extensions) {
4807 ParseStringProperty(&material->name, err, o,
"name",
false);
4809 if (ParseNumberArrayProperty(&material->emissiveFactor, err, o,
4812 if (material->emissiveFactor.size() != 3) {
4815 "Array length of `emissiveFactor` parameter in "
4816 "material must be 3, but got " +
4817 std::to_string(material->emissiveFactor.size()) +
"\n";
4823 material->emissiveFactor = {0.0, 0.0, 0.0};
4826 ParseStringProperty(&material->alphaMode, err, o,
"alphaMode",
4828 ParseNumberProperty(&material->alphaCutoff, err, o,
"alphaCutoff",
4830 ParseBooleanProperty(&material->doubleSided, err, o,
"doubleSided",
4834 json_const_iterator it;
4835 if (FindMember(o,
"pbrMetallicRoughness", it)) {
4836 ParsePbrMetallicRoughness(&material->pbrMetallicRoughness, err,
4838 store_original_json_for_extras_and_extensions);
4843 json_const_iterator it;
4844 if (FindMember(o,
"normalTexture", it)) {
4845 ParseNormalTextureInfo(&material->normalTexture, err, GetValue(it),
4846 store_original_json_for_extras_and_extensions);
4851 json_const_iterator it;
4852 if (FindMember(o,
"occlusionTexture", it)) {
4853 ParseOcclusionTextureInfo(&material->occlusionTexture, err, GetValue(it),
4854 store_original_json_for_extras_and_extensions);
4859 json_const_iterator it;
4860 if (FindMember(o,
"emissiveTexture", it)) {
4861 ParseTextureInfo(&material->emissiveTexture, err, GetValue(it),
4862 store_original_json_for_extras_and_extensions);
4871 material->values.clear();
4872 material->additionalValues.clear();
4874 json_const_iterator it(ObjectBegin(o));
4875 json_const_iterator itEnd(ObjectEnd(o));
4877 for (; it != itEnd; ++it) {
4878 std::string key(GetKey(it));
4879 if (key ==
"pbrMetallicRoughness") {
4880 if (IsObject(GetValue(it))) {
4881 const json &values_object = GetValue(it);
4883 json_const_iterator itVal(ObjectBegin(values_object));
4884 json_const_iterator itValEnd(ObjectEnd(values_object));
4886 for (; itVal != itValEnd; ++itVal) {
4888 if (ParseParameterProperty(¶m, err, values_object, GetKey(itVal),
4890 material->values.emplace(GetKey(itVal), std::move(param));
4894 }
else if (key ==
"extensions" || key ==
"extras") {
4899 if (ParseParameterProperty(¶m, err, o, key,
false)) {
4903 material->additionalValues.emplace(std::move(key), std::move(param));
4908 material->extensions.clear();
4909 ParseExtensionsProperty(&material->extensions, err, o);
4910 ParseExtrasProperty(&(material->extras), o);
4912 if (store_original_json_for_extras_and_extensions) {
4914 json_const_iterator eit;
4915 if (FindMember(o,
"extensions", eit)) {
4916 material->extensions_json_string = JsonToString(GetValue(eit));
4920 json_const_iterator eit;
4921 if (FindMember(o,
"extras", eit)) {
4922 material->extras_json_string = JsonToString(GetValue(eit));
4930static bool ParseAnimationChannel(
4932 bool store_original_json_for_extras_and_extensions) {
4933 int samplerIndex = -1;
4934 int targetIndex = -1;
4935 if (!ParseIntegerProperty(&samplerIndex, err, o,
"sampler",
true,
4936 "AnimationChannel")) {
4938 (*err) +=
"`sampler` field is missing in animation channels\n";
4943 json_const_iterator targetIt;
4944 if (FindMember(o,
"target", targetIt) && IsObject(GetValue(targetIt))) {
4945 const json &target_object = GetValue(targetIt);
4947 if (!ParseIntegerProperty(&targetIndex, err, target_object,
"node",
true)) {
4949 (*err) +=
"`node` field is missing in animation.channels.target\n";
4954 if (!ParseStringProperty(&channel->target_path, err, target_object,
"path",
4957 (*err) +=
"`path` field is missing in animation.channels.target\n";
4961 ParseExtensionsProperty(&channel->target_extensions, err, target_object);
4962 if (store_original_json_for_extras_and_extensions) {
4963 json_const_iterator it;
4964 if (FindMember(target_object,
"extensions", it)) {
4965 channel->target_extensions_json_string = JsonToString(GetValue(it));
4970 channel->sampler = samplerIndex;
4971 channel->target_node = targetIndex;
4973 ParseExtensionsProperty(&channel->extensions, err, o);
4974 ParseExtrasProperty(&(channel->extras), o);
4976 if (store_original_json_for_extras_and_extensions) {
4978 json_const_iterator it;
4979 if (FindMember(o,
"extensions", it)) {
4980 channel->extensions_json_string = JsonToString(GetValue(it));
4984 json_const_iterator it;
4985 if (FindMember(o,
"extras", it)) {
4986 channel->extras_json_string = JsonToString(GetValue(it));
4994static bool ParseAnimation(
Animation *animation, std::string *err,
4996 bool store_original_json_for_extras_and_extensions) {
4998 json_const_iterator channelsIt;
4999 if (FindMember(o,
"channels", channelsIt) &&
5000 IsArray(GetValue(channelsIt))) {
5001 json_const_array_iterator channelEnd = ArrayEnd(GetValue(channelsIt));
5002 for (json_const_array_iterator i = ArrayBegin(GetValue(channelsIt));
5003 i != channelEnd; ++i) {
5005 if (ParseAnimationChannel(
5007 store_original_json_for_extras_and_extensions)) {
5009 animation->channels.emplace_back(std::move(channel));
5016 json_const_iterator samplerIt;
5017 if (FindMember(o,
"samplers", samplerIt) && IsArray(GetValue(samplerIt))) {
5018 const json &sampler_array = GetValue(samplerIt);
5020 json_const_array_iterator it = ArrayBegin(sampler_array);
5021 json_const_array_iterator itEnd = ArrayEnd(sampler_array);
5023 for (; it != itEnd; ++it) {
5024 const json &s = *it;
5027 int inputIndex = -1;
5028 int outputIndex = -1;
5029 if (!ParseIntegerProperty(&inputIndex, err, s,
"input",
true)) {
5031 (*err) +=
"`input` field is missing in animation.sampler\n";
5035 ParseStringProperty(&sampler.interpolation, err, s,
"interpolation",
5037 if (!ParseIntegerProperty(&outputIndex, err, s,
"output",
true)) {
5039 (*err) +=
"`output` field is missing in animation.sampler\n";
5043 sampler.input = inputIndex;
5044 sampler.output = outputIndex;
5045 ParseExtensionsProperty(&(sampler.extensions), err, o);
5046 ParseExtrasProperty(&(sampler.extras), s);
5048 if (store_original_json_for_extras_and_extensions) {
5050 json_const_iterator eit;
5051 if (FindMember(o,
"extensions", eit)) {
5052 sampler.extensions_json_string = JsonToString(GetValue(eit));
5056 json_const_iterator eit;
5057 if (FindMember(o,
"extras", eit)) {
5058 sampler.extras_json_string = JsonToString(GetValue(eit));
5063 animation->samplers.emplace_back(std::move(sampler));
5068 ParseStringProperty(&animation->name, err, o,
"name",
false);
5070 ParseExtensionsProperty(&animation->extensions, err, o);
5071 ParseExtrasProperty(&(animation->extras), o);
5073 if (store_original_json_for_extras_and_extensions) {
5075 json_const_iterator it;
5076 if (FindMember(o,
"extensions", it)) {
5077 animation->extensions_json_string = JsonToString(GetValue(it));
5081 json_const_iterator it;
5082 if (FindMember(o,
"extras", it)) {
5083 animation->extras_json_string = JsonToString(GetValue(it));
5091static bool ParseSampler(
Sampler *sampler, std::string *err,
const json &o,
5092 bool store_original_json_for_extras_and_extensions) {
5093 ParseStringProperty(&sampler->name, err, o,
"name",
false);
5100 ParseIntegerProperty(&minFilter, err, o,
"minFilter",
false);
5101 ParseIntegerProperty(&magFilter, err, o,
"magFilter",
false);
5102 ParseIntegerProperty(&wrapS, err, o,
"wrapS",
false);
5103 ParseIntegerProperty(&wrapT, err, o,
"wrapT",
false);
5109 sampler->minFilter = minFilter;
5110 sampler->magFilter = magFilter;
5111 sampler->wrapS = wrapS;
5112 sampler->wrapT = wrapT;
5115 ParseExtensionsProperty(&(sampler->extensions), err, o);
5116 ParseExtrasProperty(&(sampler->extras), o);
5118 if (store_original_json_for_extras_and_extensions) {
5120 json_const_iterator it;
5121 if (FindMember(o,
"extensions", it)) {
5122 sampler->extensions_json_string = JsonToString(GetValue(it));
5126 json_const_iterator it;
5127 if (FindMember(o,
"extras", it)) {
5128 sampler->extras_json_string = JsonToString(GetValue(it));
5136static bool ParseSkin(
Skin *skin, std::string *err,
const json &o,
5137 bool store_original_json_for_extras_and_extensions) {
5138 ParseStringProperty(&skin->name, err, o,
"name",
false,
"Skin");
5140 std::vector<int> joints;
5141 if (!ParseIntegerArrayProperty(&joints, err, o,
"joints",
false,
"Skin")) {
5144 skin->joints = std::move(joints);
5147 ParseIntegerProperty(&skeleton, err, o,
"skeleton",
false,
"Skin");
5148 skin->skeleton = skeleton;
5151 ParseIntegerProperty(&invBind, err, o,
"inverseBindMatrices",
true,
"Skin");
5152 skin->inverseBindMatrices = invBind;
5154 ParseExtensionsProperty(&(skin->extensions), err, o);
5155 ParseExtrasProperty(&(skin->extras), o);
5157 if (store_original_json_for_extras_and_extensions) {
5159 json_const_iterator it;
5160 if (FindMember(o,
"extensions", it)) {
5161 skin->extensions_json_string = JsonToString(GetValue(it));
5165 json_const_iterator it;
5166 if (FindMember(o,
"extras", it)) {
5167 skin->extras_json_string = JsonToString(GetValue(it));
5175static bool ParsePerspectiveCamera(
5177 bool store_original_json_for_extras_and_extensions) {
5179 if (!ParseNumberProperty(&yfov, err, o,
"yfov",
true,
"OrthographicCamera")) {
5184 if (!ParseNumberProperty(&znear, err, o,
"znear",
true,
5185 "PerspectiveCamera")) {
5189 double aspectRatio = 0.0;
5190 ParseNumberProperty(&aspectRatio, err, o,
"aspectRatio",
false,
5191 "PerspectiveCamera");
5194 ParseNumberProperty(&zfar, err, o,
"zfar",
false,
"PerspectiveCamera");
5196 camera->aspectRatio = aspectRatio;
5197 camera->zfar = zfar;
5198 camera->yfov = yfov;
5199 camera->znear = znear;
5201 ParseExtensionsProperty(&camera->extensions, err, o);
5202 ParseExtrasProperty(&(camera->extras), o);
5204 if (store_original_json_for_extras_and_extensions) {
5206 json_const_iterator it;
5207 if (FindMember(o,
"extensions", it)) {
5208 camera->extensions_json_string = JsonToString(GetValue(it));
5212 json_const_iterator it;
5213 if (FindMember(o,
"extras", it)) {
5214 camera->extras_json_string = JsonToString(GetValue(it));
5224static bool ParseSpotLight(
SpotLight *light, std::string *err,
const json &o,
5225 bool store_original_json_for_extras_and_extensions) {
5226 ParseNumberProperty(&light->innerConeAngle, err, o,
"innerConeAngle",
false);
5227 ParseNumberProperty(&light->outerConeAngle, err, o,
"outerConeAngle",
false);
5229 ParseExtensionsProperty(&light->extensions, err, o);
5230 ParseExtrasProperty(&light->extras, o);
5232 if (store_original_json_for_extras_and_extensions) {
5234 json_const_iterator it;
5235 if (FindMember(o,
"extensions", it)) {
5236 light->extensions_json_string = JsonToString(GetValue(it));
5240 json_const_iterator it;
5241 if (FindMember(o,
"extras", it)) {
5242 light->extras_json_string = JsonToString(GetValue(it));
5252static bool ParseOrthographicCamera(
5254 bool store_original_json_for_extras_and_extensions) {
5256 if (!ParseNumberProperty(&xmag, err, o,
"xmag",
true,
"OrthographicCamera")) {
5261 if (!ParseNumberProperty(&ymag, err, o,
"ymag",
true,
"OrthographicCamera")) {
5266 if (!ParseNumberProperty(&zfar, err, o,
"zfar",
true,
"OrthographicCamera")) {
5271 if (!ParseNumberProperty(&znear, err, o,
"znear",
true,
5272 "OrthographicCamera")) {
5276 ParseExtensionsProperty(&camera->extensions, err, o);
5277 ParseExtrasProperty(&(camera->extras), o);
5279 if (store_original_json_for_extras_and_extensions) {
5281 json_const_iterator it;
5282 if (FindMember(o,
"extensions", it)) {
5283 camera->extensions_json_string = JsonToString(GetValue(it));
5287 json_const_iterator it;
5288 if (FindMember(o,
"extras", it)) {
5289 camera->extras_json_string = JsonToString(GetValue(it));
5294 camera->xmag = xmag;
5295 camera->ymag = ymag;
5296 camera->zfar = zfar;
5297 camera->znear = znear;
5304static bool ParseCamera(
Camera *camera, std::string *err,
const json &o,
5305 bool store_original_json_for_extras_and_extensions) {
5306 if (!ParseStringProperty(&camera->type, err, o,
"type",
true,
"Camera")) {
5310 if (camera->type.compare(
"orthographic") == 0) {
5311 json_const_iterator orthoIt;
5312 if (!FindMember(o,
"orthographic", orthoIt)) {
5314 std::stringstream ss;
5315 ss <<
"Orhographic camera description not found." << std::endl;
5321 const json &v = GetValue(orthoIt);
5324 std::stringstream ss;
5325 ss <<
"\"orthographic\" is not a JSON object." << std::endl;
5331 if (!ParseOrthographicCamera(
5332 &camera->orthographic, err, v,
5333 store_original_json_for_extras_and_extensions)) {
5336 }
else if (camera->type.compare(
"perspective") == 0) {
5337 json_const_iterator perspIt;
5338 if (!FindMember(o,
"perspective", perspIt)) {
5340 std::stringstream ss;
5341 ss <<
"Perspective camera description not found." << std::endl;
5347 const json &v = GetValue(perspIt);
5350 std::stringstream ss;
5351 ss <<
"\"perspective\" is not a JSON object." << std::endl;
5357 if (!ParsePerspectiveCamera(
5358 &camera->perspective, err, v,
5359 store_original_json_for_extras_and_extensions)) {
5364 std::stringstream ss;
5365 ss <<
"Invalid camera type: \"" << camera->type
5366 <<
"\". Must be \"perspective\" or \"orthographic\"" << std::endl;
5372 ParseStringProperty(&camera->name, err, o,
"name",
false);
5374 ParseExtensionsProperty(&camera->extensions, err, o);
5375 ParseExtrasProperty(&(camera->extras), o);
5377 if (store_original_json_for_extras_and_extensions) {
5379 json_const_iterator it;
5380 if (FindMember(o,
"extensions", it)) {
5381 camera->extensions_json_string = JsonToString(GetValue(it));
5385 json_const_iterator it;
5386 if (FindMember(o,
"extras", it)) {
5387 camera->extras_json_string = JsonToString(GetValue(it));
5395static bool ParseLight(
Light *light, std::string *err,
const json &o,
5396 bool store_original_json_for_extras_and_extensions) {
5397 if (!ParseStringProperty(&light->type, err, o,
"type",
true)) {
5401 if (light->type ==
"spot") {
5402 json_const_iterator spotIt;
5403 if (!FindMember(o,
"spot", spotIt)) {
5405 std::stringstream ss;
5406 ss <<
"Spot light description not found." << std::endl;
5412 const json &v = GetValue(spotIt);
5415 std::stringstream ss;
5416 ss <<
"\"spot\" is not a JSON object." << std::endl;
5422 if (!ParseSpotLight(&light->spot, err, v,
5423 store_original_json_for_extras_and_extensions)) {
5428 ParseStringProperty(&light->name, err, o,
"name",
false);
5429 ParseNumberArrayProperty(&light->color, err, o,
"color",
false);
5430 ParseNumberProperty(&light->range, err, o,
"range",
false);
5431 ParseNumberProperty(&light->intensity, err, o,
"intensity",
false);
5432 ParseExtensionsProperty(&light->extensions, err, o);
5433 ParseExtrasProperty(&(light->extras), o);
5435 if (store_original_json_for_extras_and_extensions) {
5437 json_const_iterator it;
5438 if (FindMember(o,
"extensions", it)) {
5439 light->extensions_json_string = JsonToString(GetValue(it));
5443 json_const_iterator it;
5444 if (FindMember(o,
"extras", it)) {
5445 light->extras_json_string = JsonToString(GetValue(it));
5453bool TinyGLTF::LoadFromString(
Model *model, std::string *err, std::string *warn,
5454 const char *json_str,
5455 unsigned int json_str_length,
5456 const std::string &base_dir,
5457 unsigned int check_sections) {
5458 if (json_str_length < 4) {
5460 (*err) =
"JSON string too short.\n";
5467#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \
5468 defined(_CPPUNWIND)) && \
5469 !defined(TINYGLTF_NOEXCEPTION)
5471 JsonParse(v, json_str, json_str_length,
true);
5473 }
catch (
const std::exception &
e) {
5481 JsonParse(v, json_str, json_str_length);
5486 (*err) =
"Failed to parse JSON object\n";
5496 (*err) =
"Root element is not a JSON object\n";
5502 bool version_found =
false;
5503 json_const_iterator it;
5504 if (FindMember(v,
"asset", it) && IsObject(GetValue(it))) {
5505 auto &itObj = GetValue(it);
5506 json_const_iterator version_it;
5507 std::string versionStr;
5508 if (FindMember(itObj,
"version", version_it) &&
5509 GetString(GetValue(version_it), versionStr)) {
5510 version_found =
true;
5513 if (version_found) {
5517 (*err) +=
"\"asset\" object not found in .gltf or not an object type\n";
5526 auto IsArrayMemberPresent = [](
const json &_v,
const char *
name) ->
bool {
5527 json_const_iterator it;
5528 return FindMember(_v,
name, it) && IsArray(GetValue(it));
5533 !IsArrayMemberPresent(v,
"scenes")) {
5535 (*err) +=
"\"scenes\" object not found in .gltf or not an array type\n";
5542 if ((check_sections &
REQUIRE_NODES) && !IsArrayMemberPresent(v,
"nodes")) {
5544 (*err) +=
"\"nodes\" object not found in .gltf\n";
5552 !IsArrayMemberPresent(v,
"accessors")) {
5554 (*err) +=
"\"accessors\" object not found in .gltf\n";
5562 !IsArrayMemberPresent(v,
"buffers")) {
5564 (*err) +=
"\"buffers\" object not found in .gltf\n";
5572 !IsArrayMemberPresent(v,
"bufferViews")) {
5574 (*err) +=
"\"bufferViews\" object not found in .gltf\n";
5580 model->buffers.clear();
5581 model->bufferViews.clear();
5582 model->accessors.clear();
5583 model->meshes.clear();
5584 model->cameras.clear();
5585 model->nodes.clear();
5586 model->extensionsUsed.clear();
5587 model->extensionsRequired.clear();
5588 model->extensions.clear();
5589 model->defaultScene = -1;
5593 json_const_iterator it;
5594 if (FindMember(v,
"asset", it) && IsObject(GetValue(it))) {
5595 const json &root = GetValue(it);
5597 ParseAsset(&model->asset, err, root,
5598 store_original_json_for_extras_and_extensions_);
5602#ifdef TINYGLTF_USE_CPP14
5603 auto ForEachInArray = [](
const json &_v,
const char *member,
5604 const auto &cb) ->
bool
5609 auto ForEachInArray = [](
const json &_v,
const char *member,
5610 const std::function<
bool(
const json &)> &cb) ->
bool
5613 json_const_iterator itm;
5614 if (FindMember(_v, member, itm) && IsArray(GetValue(itm))) {
5615 const json &root = GetValue(itm);
5616 auto it = ArrayBegin(root);
5617 auto end = ArrayEnd(root);
5618 for (; it !=
end; ++it) {
5619 if (!cb(*it))
return false;
5627 ForEachInArray(v,
"extensionsUsed", [&](
const json &o) {
5630 model->extensionsUsed.emplace_back(std::move(
str));
5636 ForEachInArray(v,
"extensionsRequired", [&](
const json &o) {
5639 model->extensionsRequired.emplace_back(std::move(
str));
5646 bool success = ForEachInArray(v,
"buffers", [&](
const json &o) {
5649 (*err) +=
"`buffers' does not contain an JSON object.";
5654 if (!ParseBuffer(&buffer, err, o,
5655 store_original_json_for_extras_and_extensions_, &fs,
5656 base_dir, is_binary_, bin_data_, bin_size_)) {
5660 model->buffers.emplace_back(std::move(buffer));
5670 bool success = ForEachInArray(v,
"bufferViews", [&](
const json &o) {
5673 (*err) +=
"`bufferViews' does not contain an JSON object.";
5677 BufferView bufferView;
5678 if (!ParseBufferView(&bufferView, err, o,
5679 store_original_json_for_extras_and_extensions_)) {
5683 model->bufferViews.emplace_back(std::move(bufferView));
5694 bool success = ForEachInArray(v,
"accessors", [&](
const json &o) {
5697 (*err) +=
"`accessors' does not contain an JSON object.";
5702 if (!ParseAccessor(&accessor, err, o,
5703 store_original_json_for_extras_and_extensions_)) {
5707 model->accessors.emplace_back(std::move(accessor));
5718 bool success = ForEachInArray(v,
"meshes", [&](
const json &o) {
5721 (*err) +=
"`meshes' does not contain an JSON object.";
5726 if (!ParseMesh(&mesh, model, err, o,
5727 store_original_json_for_extras_and_extensions_)) {
5731 model->meshes.emplace_back(std::move(mesh));
5743 for (
auto &mesh : model->meshes) {
5744 for (
auto &primitive : mesh.primitives) {
5745 if (primitive.indices >
5748 if (
size_t(primitive.indices) >= model->accessors.size()) {
5750 (*err) +=
"primitive indices accessor out of bounds";
5756 model->accessors[size_t(primitive.indices)].bufferView;
5757 if (bufferView < 0 ||
size_t(bufferView) >= model->bufferViews.size()) {
5759 (*err) +=
"accessor[" + std::to_string(primitive.indices) +
5760 "] invalid bufferView";
5765 model->bufferViews[size_t(bufferView)].target =
5771 for (
auto &attribute : primitive.attributes) {
5773 ->bufferViews[size_t(
5774 model->accessors[
size_t(attribute.second)].bufferView)]
5778 for (
auto &target : primitive.targets) {
5779 for (
auto &attribute : target) {
5781 model->accessors[size_t(attribute.second)].bufferView;
5783 if (bufferView >= 0) {
5784 model->bufferViews[size_t(bufferView)].target =
5794 bool success = ForEachInArray(v,
"nodes", [&](
const json &o) {
5797 (*err) +=
"`nodes' does not contain an JSON object.";
5802 if (!ParseNode(&node, err, o,
5803 store_original_json_for_extras_and_extensions_)) {
5807 model->nodes.emplace_back(std::move(node));
5818 bool success = ForEachInArray(v,
"scenes", [&](
const json &o) {
5821 (*err) +=
"`scenes' does not contain an JSON object.";
5825 std::vector<int> nodes;
5826 ParseIntegerArrayProperty(&nodes, err, o,
"nodes",
false);
5829 scene.nodes = std::move(nodes);
5831 ParseStringProperty(&scene.name, err, o,
"name",
false);
5833 ParseExtensionsProperty(&scene.extensions, err, o);
5834 ParseExtrasProperty(&scene.extras, o);
5836 if (store_original_json_for_extras_and_extensions_) {
5838 json_const_iterator it;
5839 if (FindMember(o,
"extensions", it)) {
5840 scene.extensions_json_string = JsonToString(GetValue(it));
5844 json_const_iterator it;
5845 if (FindMember(o,
"extras", it)) {
5846 scene.extras_json_string = JsonToString(GetValue(it));
5851 model->scenes.emplace_back(std::move(scene));
5862 json_const_iterator rootIt;
5864 if (FindMember(v,
"scene", rootIt) && GetInt(GetValue(rootIt), iVal)) {
5865 model->defaultScene = iVal;
5871 bool success = ForEachInArray(v,
"materials", [&](
const json &o) {
5874 (*err) +=
"`materials' does not contain an JSON object.";
5879 ParseStringProperty(&material.name, err, o,
"name",
false);
5881 if (!ParseMaterial(&material, err, o,
5882 store_original_json_for_extras_and_extensions_)) {
5886 model->materials.emplace_back(std::move(material));
5896 void *load_image_user_data{
nullptr};
5898 LoadImageDataOption load_image_option;
5900 if (user_image_loader_) {
5902 load_image_user_data = load_image_user_data_;
5904 load_image_option.preserve_channels = preserve_image_channels_;
5905 load_image_user_data =
reinterpret_cast<void *
>(&load_image_option);
5910 bool success = ForEachInArray(v,
"images", [&](
const json &o) {
5913 (*err) +=
"image[" + std::to_string(idx) +
"] is not a JSON object.";
5918 if (!ParseImage(&
image, idx, err, warn, o,
5919 store_original_json_for_extras_and_extensions_, base_dir,
5920 &fs, &this->LoadImageData, load_image_user_data)) {
5924 if (
image.bufferView != -1) {
5926 if (
size_t(
image.bufferView) >= model->bufferViews.size()) {
5928 std::stringstream ss;
5929 ss <<
"image[" << idx <<
"] bufferView \"" <<
image.bufferView
5930 <<
"\" not found in the scene." << std::endl;
5936 const BufferView &bufferView =
5937 model->bufferViews[size_t(
image.bufferView)];
5938 if (
size_t(bufferView.buffer) >= model->buffers.size()) {
5940 std::stringstream ss;
5941 ss <<
"image[" << idx <<
"] buffer \"" << bufferView.buffer
5942 <<
"\" not found in the scene." << std::endl;
5947 const Buffer &buffer = model->buffers[size_t(bufferView.buffer)];
5949 if (*LoadImageData ==
nullptr) {
5951 (*err) +=
"No LoadImageData callback specified.\n";
5955 bool ret = LoadImageData(
5957 &buffer.data[bufferView.byteOffset],
5958 static_cast<int>(bufferView.byteLength), load_image_user_data);
5964 model->images.emplace_back(std::move(
image));
5976 bool success = ForEachInArray(v,
"textures", [&](
const json &o) {
5979 (*err) +=
"`textures' does not contain an JSON object.";
5984 if (!ParseTexture(&texture, err, o,
5985 store_original_json_for_extras_and_extensions_,
5990 model->textures.emplace_back(std::move(texture));
6001 bool success = ForEachInArray(v,
"animations", [&](
const json &o) {
6004 (*err) +=
"`animations' does not contain an JSON object.";
6008 Animation animation;
6009 if (!ParseAnimation(&animation, err, o,
6010 store_original_json_for_extras_and_extensions_)) {
6014 model->animations.emplace_back(std::move(animation));
6025 bool success = ForEachInArray(v,
"skins", [&](
const json &o) {
6028 (*err) +=
"`skins' does not contain an JSON object.";
6033 if (!ParseSkin(&skin, err, o,
6034 store_original_json_for_extras_and_extensions_)) {
6038 model->skins.emplace_back(std::move(skin));
6049 bool success = ForEachInArray(v,
"samplers", [&](
const json &o) {
6052 (*err) +=
"`samplers' does not contain an JSON object.";
6057 if (!ParseSampler(&sampler, err, o,
6058 store_original_json_for_extras_and_extensions_)) {
6062 model->samplers.emplace_back(std::move(sampler));
6073 bool success = ForEachInArray(v,
"cameras", [&](
const json &o) {
6076 (*err) +=
"`cameras' does not contain an JSON object.";
6081 if (!ParseCamera(&camera, err, o,
6082 store_original_json_for_extras_and_extensions_)) {
6086 model->cameras.emplace_back(std::move(camera));
6096 ParseExtensionsProperty(&model->extensions, err, v);
6100 json_const_iterator rootIt;
6101 if (FindMember(v,
"extensions", rootIt) && IsObject(GetValue(rootIt))) {
6102 const json &root = GetValue(rootIt);
6104 json_const_iterator it(ObjectBegin(root));
6105 json_const_iterator itEnd(ObjectEnd(root));
6106 for (; it != itEnd; ++it) {
6108 std::string key(GetKey(it));
6109 if ((key ==
"KHR_lights_punctual") && IsObject(GetValue(it))) {
6110 const json &
object = GetValue(it);
6111 json_const_iterator itLight;
6112 if (FindMember(
object,
"lights", itLight)) {
6113 const json &lights = GetValue(itLight);
6114 if (!IsArray(lights)) {
6118 auto arrayIt(ArrayBegin(lights));
6119 auto arrayItEnd(ArrayEnd(lights));
6120 for (; arrayIt != arrayItEnd; ++arrayIt) {
6122 if (!ParseLight(&light, err, *arrayIt,
6123 store_original_json_for_extras_and_extensions_)) {
6126 model->lights.emplace_back(std::move(light));
6135 ParseExtrasProperty(&model->extras, v);
6137 if (store_original_json_for_extras_and_extensions_) {
6138 model->extras_json_string = JsonToString(v[
"extras"]);
6139 model->extensions_json_string = JsonToString(v[
"extensions"]);
6146 std::string *warn,
const char *
str,
6147 unsigned int length,
6148 const std::string &base_dir,
6149 unsigned int check_sections) {
6151 bin_data_ =
nullptr;
6154 return LoadFromString(model, err, warn,
str, length, base_dir,
6159 std::string *warn,
const std::string &filename,
6160 unsigned int check_sections) {
6161 std::stringstream ss;
6163 if (fs.ReadWholeFile ==
nullptr) {
6165 ss <<
"Failed to read file: " << filename
6166 <<
": one or more FS callback not set" << std::endl;
6173 std::vector<unsigned char, ::GameApiAllocator<unsigned char> >
data;
6174 std::string fileerr;
6175 bool fileread = fs.ReadWholeFile(&
data, &fileerr, filename, fs.user_data);
6177 ss <<
"Failed to read file: " << filename <<
": " << fileerr << std::endl;
6184 size_t sz =
data.size();
6187 (*err) =
"Empty file.";
6192 std::string basedir = GetBaseDir(filename);
6195 model, err, warn,
reinterpret_cast<const char *
>(&
data.at(0)),
6196 static_cast<unsigned int>(
data.size()), basedir, check_sections);
6203 const unsigned char *bytes,
6205 const std::string &base_dir,
6206 unsigned int check_sections) {
6209 (*err) =
"Too short data size for glTF Binary.";
6214 if (bytes[0] ==
'g' && bytes[1] ==
'l' && bytes[2] ==
'T' &&
6219 (*err) =
"Invalid magic.";
6224 unsigned int version;
6225 unsigned int length;
6226 unsigned int model_length;
6227 unsigned int model_format;
6230 memcpy(&version, bytes + 4, 4);
6232 memcpy(&length, bytes + 8, 4);
6234 memcpy(&model_length, bytes + 12, 4);
6235 swap4(&model_length);
6236 memcpy(&model_format, bytes + 16, 4);
6237 swap4(&model_format);
6242 if ((20 + model_length >
size) || (model_length < 1) || (length >
size) ||
6243 (20 + model_length > length) ||
6244 (model_format != 0x4E4F534A)) {
6246 (*err) =
"Invalid glTF binary.";
6252 std::string jsonString(
reinterpret_cast<const char *
>(&bytes[20]),
6256 bin_data_ = bytes + 20 + model_length +
6259 length - (20 + model_length);
6261 bool ret = LoadFromString(model, err, warn,
6262 reinterpret_cast<const char *
>(&bytes[20]),
6263 model_length, base_dir, check_sections);
6273 const std::string &filename,
6274 unsigned int check_sections) {
6275 std::stringstream ss;
6277 if (fs.ReadWholeFile ==
nullptr) {
6279 ss <<
"Failed to read file: " << filename
6280 <<
": one or more FS callback not set" << std::endl;
6287 std::vector<unsigned char, ::GameApiAllocator<unsigned char> >
data;
6288 std::string fileerr;
6289 bool fileread = fs.ReadWholeFile(&
data, &fileerr, filename, fs.user_data);
6291 ss <<
"Failed to read file: " << filename <<
": " << fileerr << std::endl;
6298 std::string basedir = GetBaseDir(filename);
6301 static_cast<unsigned int>(
data.size()),
6302 basedir, check_sections);
6311json JsonFromString(
const char *s) {
6312#ifdef TINYGLTF_USE_RAPIDJSON
6313 return json(s, GetAllocator());
6319void JsonAssign(json &dest,
const json &
src) {
6320#ifdef TINYGLTF_USE_RAPIDJSON
6321 dest.CopyFrom(
src, GetAllocator());
6327void JsonAddMember(json &o,
const char *key, json &&value) {
6328#ifdef TINYGLTF_USE_RAPIDJSON
6329 if (!o.IsObject()) {
6332 o.AddMember(
json(key, GetAllocator()), std::move(value), GetAllocator());
6334 o[key] = std::move(value);
6338void JsonPushBack(json &o, json &&value) {
6339#ifdef TINYGLTF_USE_RAPIDJSON
6340 o.PushBack(std::move(value), GetAllocator());
6342 o.push_back(std::move(value));
6346bool JsonIsNull(
const json &o) {
6347#ifdef TINYGLTF_USE_RAPIDJSON
6354void JsonSetObject(json &o) {
6355#ifdef TINYGLTF_USE_RAPIDJSON
6362void JsonReserveArray(json &o,
size_t s) {
6363#ifdef TINYGLTF_USE_RAPIDJSON
6365 o.Reserve(
static_cast<rapidjson::SizeType
>(s), GetAllocator());
6374template <
typename T>
6375static void SerializeNumberProperty(
const std::string &key, T number,
6380 JsonAddMember(obj, key.c_str(),
json(number));
6383#ifdef TINYGLTF_USE_RAPIDJSON
6385void SerializeNumberProperty(
const std::string &key,
size_t number, json &obj) {
6386 JsonAddMember(obj, key.c_str(),
json(
static_cast<uint64_t
>(number)));
6390template <
typename T>
6391static void SerializeNumberArrayProperty(
const std::string &key,
6392 const std::vector<T> &value,
6394 if (value.empty())
return;
6397 JsonReserveArray(ary, value.size());
6398 for (
const auto &s : value) {
6399 JsonPushBack(ary,
json(s));
6401 JsonAddMember(obj, key.c_str(), std::move(ary));
6404static void SerializeStringProperty(
const std::string &key,
6405 const std::string &value, json &obj) {
6406 JsonAddMember(obj, key.c_str(), JsonFromString(value.c_str()));
6409static void SerializeStringArrayProperty(
const std::string &key,
6410 const std::vector<std::string> &value,
6413 JsonReserveArray(ary, value.size());
6414 for (
auto &s : value) {
6415 JsonPushBack(ary, JsonFromString(s.c_str()));
6417 JsonAddMember(obj, key.c_str(), std::move(ary));
6420static bool ValueToJson(
const Value &value, json *
ret) {
6422#ifdef TINYGLTF_USE_RAPIDJSON
6423 switch (value.Type()) {
6425 obj.SetDouble(value.Get<
double>());
6428 obj.SetInt(value.Get<
int>());
6431 obj.SetBool(value.Get<
bool>());
6434 obj.SetString(value.Get<std::string>().c_str(), GetAllocator());
6438 obj.Reserve(
static_cast<rapidjson::SizeType
>(value.ArrayLen()),
6440 for (
unsigned int i = 0; i < value.ArrayLen(); ++i) {
6441 Value elementValue = value.Get(
int(i));
6443 if (ValueToJson(value.Get(
int(i)), &elementJson))
6444 obj.PushBack(std::move(elementJson), GetAllocator());
6456 for (
auto &it : objMap) {
6458 if (ValueToJson(it.second, &elementJson)) {
6459 obj.AddMember(
json(it.first.c_str(), GetAllocator()),
6460 std::move(elementJson), GetAllocator());
6470 switch (value.Type()) {
6472 obj =
json(value.Get<
double>());
6475 obj =
json(value.Get<
int>());
6478 obj =
json(value.Get<
bool>());
6481 obj =
json(value.Get<std::string>());
6484 for (
unsigned int i = 0; i < value.ArrayLen(); ++i) {
6485 Value elementValue = value.Get(
int(i));
6487 if (ValueToJson(value.Get(
int(i)), &elementJson))
6488 obj.push_back(elementJson);
6499 for (
auto &it : objMap) {
6501 if (ValueToJson(it.second, &elementJson)) obj[it.first] = elementJson;
6510 if (
ret) *
ret = std::move(obj);
6514static void SerializeValue(
const std::string &key,
const Value &value,
6517 if (ValueToJson(value, &
ret)) {
6518 JsonAddMember(obj, key.c_str(), std::move(
ret));
6522 static void SerializeGltfBufferData(
const std::vector<
unsigned char, ::GameApiAllocator<unsigned char> > &
data,
6524 std::string
header =
"data:application/octet-stream;base64,";
6525 if (
data.size() > 0) {
6526 std::string encodedData =
6528 SerializeStringProperty(
"uri",
header + encodedData, o);
6532 SerializeStringProperty(
"uri",
header, o);
6536 static bool SerializeGltfBufferData(
const std::vector<
unsigned char,GameApiAllocator<unsigned char> > &
data,
6537 const std::string &binFilename) {
6539#if defined(__GLIBCXX__)
6540 int file_descriptor = _wopen(UTF8ToWchar(binFilename).c_str(),
6541 _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY);
6542 __gnu_cxx::stdio_filebuf<char> wfile_buf(
6543 file_descriptor, std::ios_base::out | std::ios_base::binary);
6544 std::ostream output(&wfile_buf);
6545 if (!wfile_buf.is_open())
return false;
6546#elif defined(_MSC_VER)
6547 std::ofstream output(UTF8ToWchar(binFilename).c_str(), std::ofstream::binary);
6548 if (!output.is_open())
return false;
6550 std::ofstream output(binFilename.c_str(), std::ofstream::binary);
6551 if (!output.is_open())
return false;
6554 std::ofstream output(binFilename.c_str(), std::ofstream::binary);
6555 if (!output.is_open())
return false;
6557 if (
data.size() > 0) {
6558 output.write(
reinterpret_cast<const char *
>(&
data[0]),
6559 std::streamsize(
data.size()));
6569static void SerializeParameterMap(
ParameterMap ¶m, json &o) {
6570 for (ParameterMap::iterator paramIt = param.begin(); paramIt != param.end();
6572 if (paramIt->second.number_array.size()) {
6573 SerializeNumberArrayProperty<double>(paramIt->first,
6574 paramIt->second.number_array, o);
6575 }
else if (paramIt->second.json_double_value.size()) {
6576 json json_double_value;
6577 for (std::map<std::string, double>::iterator it =
6578 paramIt->second.json_double_value.begin();
6579 it != paramIt->second.json_double_value.end(); ++it) {
6580 if (it->first ==
"index") {
6581 json_double_value[it->first] = paramIt->second.TextureIndex();
6583 json_double_value[it->first] = it->second;
6587 o[paramIt->first] = json_double_value;
6588 }
else if (!paramIt->second.string_value.empty()) {
6589 SerializeStringProperty(paramIt->first, paramIt->second.string_value, o);
6590 }
else if (paramIt->second.has_number_value) {
6591 o[paramIt->first] = paramIt->second.number_value;
6593 o[paramIt->first] = paramIt->second.bool_value;
6599static void SerializeExtensionMap(
const ExtensionMap &extensions, json &o) {
6600 if (!extensions.size())
return;
6603 for (ExtensionMap::const_iterator extIt = extensions.begin();
6604 extIt != extensions.end(); ++extIt) {
6608 if (ValueToJson(extIt->second, &
ret)) {
6609 isNull = JsonIsNull(
ret);
6610 JsonAddMember(extMap, extIt->first.c_str(), std::move(
ret));
6613 if (!(extIt->first.empty())) {
6617 JsonSetObject(
empty);
6618 JsonAddMember(extMap, extIt->first.c_str(), std::move(
empty));
6622 JsonAddMember(o,
"extensions", std::move(extMap));
6625static void SerializeGltfAccessor(
Accessor &accessor, json &o) {
6626 if (accessor.bufferView >= 0)
6627 SerializeNumberProperty<int>(
"bufferView", accessor.bufferView, o);
6629 if (accessor.byteOffset != 0)
6630 SerializeNumberProperty<int>(
"byteOffset",
int(accessor.byteOffset), o);
6632 SerializeNumberProperty<int>(
"componentType", accessor.componentType, o);
6633 SerializeNumberProperty<size_t>(
"count", accessor.count, o);
6637 SerializeNumberArrayProperty<double>(
"min", accessor.minValues, o);
6638 SerializeNumberArrayProperty<double>(
"max", accessor.maxValues, o);
6643 std::vector<int> values;
6644 std::transform(accessor.minValues.begin(), accessor.minValues.end(),
6645 std::back_inserter(values),
6646 [](
double v) { return static_cast<int>(v); });
6648 SerializeNumberArrayProperty<int>(
"min", values, o);
6652 std::vector<int> values;
6653 std::transform(accessor.maxValues.begin(), accessor.maxValues.end(),
6654 std::back_inserter(values),
6655 [](
double v) { return static_cast<int>(v); });
6657 SerializeNumberArrayProperty<int>(
"max", values, o);
6661 if (accessor.normalized)
6662 SerializeValue(
"normalized",
Value(accessor.normalized), o);
6664 switch (accessor.type) {
6688 SerializeStringProperty(
"type", type, o);
6689 if (!accessor.name.empty()) SerializeStringProperty(
"name", accessor.name, o);
6691 if (accessor.extras.Type() !=
NULL_TYPE) {
6692 SerializeValue(
"extras", accessor.extras, o);
6696static void SerializeGltfAnimationChannel(
AnimationChannel &channel, json &o) {
6697 SerializeNumberProperty(
"sampler", channel.sampler, o);
6700 SerializeNumberProperty(
"node", channel.target_node, target);
6701 SerializeStringProperty(
"path", channel.target_path, target);
6703 SerializeExtensionMap(channel.target_extensions, target);
6705 JsonAddMember(o,
"target", std::move(target));
6708 if (channel.extras.Type() !=
NULL_TYPE) {
6709 SerializeValue(
"extras", channel.extras, o);
6712 SerializeExtensionMap(channel.extensions, o);
6715static void SerializeGltfAnimationSampler(
AnimationSampler &sampler, json &o) {
6716 SerializeNumberProperty(
"input", sampler.input, o);
6717 SerializeNumberProperty(
"output", sampler.output, o);
6718 SerializeStringProperty(
"interpolation", sampler.interpolation, o);
6720 if (sampler.extras.Type() !=
NULL_TYPE) {
6721 SerializeValue(
"extras", sampler.extras, o);
6725static void SerializeGltfAnimation(
Animation &animation, json &o) {
6726 if (!animation.name.empty())
6727 SerializeStringProperty(
"name", animation.name, o);
6731 JsonReserveArray(channels, animation.channels.size());
6732 for (
unsigned int i = 0; i < animation.channels.size(); ++i) {
6735 SerializeGltfAnimationChannel(gltfChannel, channel);
6736 JsonPushBack(channels, std::move(channel));
6739 JsonAddMember(o,
"channels", std::move(channels));
6744 JsonReserveArray(samplers, animation.samplers.size());
6745 for (
unsigned int i = 0; i < animation.samplers.size(); ++i) {
6748 SerializeGltfAnimationSampler(gltfSampler, sampler);
6749 JsonPushBack(samplers, std::move(sampler));
6751 JsonAddMember(o,
"samplers", std::move(samplers));
6754 if (animation.extras.Type() !=
NULL_TYPE) {
6755 SerializeValue(
"extras", animation.extras, o);
6758 SerializeExtensionMap(animation.extensions, o);
6761static void SerializeGltfAsset(
Asset &asset, json &o) {
6762 if (!asset.generator.empty()) {
6763 SerializeStringProperty(
"generator", asset.generator, o);
6766 if (!asset.copyright.empty()) {
6767 SerializeStringProperty(
"copyright", asset.copyright, o);
6770 if (asset.version.empty()) {
6773 asset.version =
"2.0";
6777 SerializeStringProperty(
"version", asset.version, o);
6779 if (asset.extras.Keys().size()) {
6780 SerializeValue(
"extras", asset.extras, o);
6783 SerializeExtensionMap(asset.extensions, o);
6786static void SerializeGltfBufferBin(
Buffer &buffer, json &o,
6787 std::vector<
unsigned char, ::GameApiAllocator<unsigned char> > &binBuffer) {
6788 SerializeNumberProperty(
"byteLength", buffer.data.size(), o);
6789 binBuffer = buffer.data;
6791 if (buffer.name.size()) SerializeStringProperty(
"name", buffer.name, o);
6793 if (buffer.extras.Type() !=
NULL_TYPE) {
6794 SerializeValue(
"extras", buffer.extras, o);
6798static void SerializeGltfBuffer(
Buffer &buffer, json &o) {
6799 SerializeNumberProperty(
"byteLength", buffer.data.size(), o);
6800 SerializeGltfBufferData(buffer.data, o);
6802 if (buffer.name.size()) SerializeStringProperty(
"name", buffer.name, o);
6804 if (buffer.extras.Type() !=
NULL_TYPE) {
6805 SerializeValue(
"extras", buffer.extras, o);
6809static bool SerializeGltfBuffer(
Buffer &buffer, json &o,
6810 const std::string &binFilename,
6811 const std::string &binBaseFilename) {
6812 if (!SerializeGltfBufferData(buffer.data, binFilename))
return false;
6813 SerializeNumberProperty(
"byteLength", buffer.data.size(), o);
6814 SerializeStringProperty(
"uri", binBaseFilename, o);
6816 if (buffer.name.size()) SerializeStringProperty(
"name", buffer.name, o);
6818 if (buffer.extras.Type() !=
NULL_TYPE) {
6819 SerializeValue(
"extras", buffer.extras, o);
6824static void SerializeGltfBufferView(
BufferView &bufferView, json &o) {
6825 SerializeNumberProperty(
"buffer", bufferView.buffer, o);
6826 SerializeNumberProperty<size_t>(
"byteLength", bufferView.byteLength, o);
6829 if (bufferView.byteStride >= 4) {
6830 SerializeNumberProperty<size_t>(
"byteStride", bufferView.byteStride, o);
6833 if (bufferView.byteOffset > 0) {
6834 SerializeNumberProperty<size_t>(
"byteOffset", bufferView.byteOffset, o);
6839 SerializeNumberProperty(
"target", bufferView.target, o);
6841 if (bufferView.name.size()) {
6842 SerializeStringProperty(
"name", bufferView.name, o);
6845 if (bufferView.extras.Type() !=
NULL_TYPE) {
6846 SerializeValue(
"extras", bufferView.extras, o);
6850static void SerializeGltfImage(
Image &
image, json &o) {
6852 if (
image.uri.empty()) {
6853 SerializeStringProperty(
"mimeType",
image.mimeType, o);
6854 SerializeNumberProperty<int>(
"bufferView",
image.bufferView, o);
6857 SerializeStringProperty(
"uri",
image.uri, o);
6860 if (
image.name.size()) {
6861 SerializeStringProperty(
"name",
image.name, o);
6865 SerializeValue(
"extras",
image.extras, o);
6868 SerializeExtensionMap(
image.extensions, o);
6871static void SerializeGltfTextureInfo(
TextureInfo &texinfo, json &o) {
6872 SerializeNumberProperty(
"index", texinfo.index, o);
6874 if (texinfo.texCoord != 0) {
6875 SerializeNumberProperty(
"texCoord", texinfo.texCoord, o);
6878 if (texinfo.extras.Type() !=
NULL_TYPE) {
6879 SerializeValue(
"extras", texinfo.extras, o);
6882 SerializeExtensionMap(texinfo.extensions, o);
6887 SerializeNumberProperty(
"index", texinfo.index, o);
6889 if (texinfo.texCoord != 0) {
6890 SerializeNumberProperty(
"texCoord", texinfo.texCoord, o);
6894 SerializeNumberProperty(
"scale", texinfo.scale, o);
6897 if (texinfo.extras.Type() !=
NULL_TYPE) {
6898 SerializeValue(
"extras", texinfo.extras, o);
6901 SerializeExtensionMap(texinfo.extensions, o);
6906 SerializeNumberProperty(
"index", texinfo.index, o);
6908 if (texinfo.texCoord != 0) {
6909 SerializeNumberProperty(
"texCoord", texinfo.texCoord, o);
6913 SerializeNumberProperty(
"strength", texinfo.strength, o);
6916 if (texinfo.extras.Type() !=
NULL_TYPE) {
6917 SerializeValue(
"extras", texinfo.extras, o);
6920 SerializeExtensionMap(texinfo.extensions, o);
6925 std::vector<double> default_baseColorFactor = {1.0, 1.0, 1.0, 1.0};
6926 if (!
Equals(pbr.baseColorFactor, default_baseColorFactor)) {
6927 SerializeNumberArrayProperty<double>(
"baseColorFactor", pbr.baseColorFactor,
6932 SerializeNumberProperty(
"metallicFactor", pbr.metallicFactor, o);
6936 SerializeNumberProperty(
"roughnessFactor", pbr.roughnessFactor, o);
6939 if (pbr.baseColorTexture.index > -1) {
6941 SerializeGltfTextureInfo(pbr.baseColorTexture, texinfo);
6942 JsonAddMember(o,
"baseColorTexture", std::move(texinfo));
6945 if (pbr.metallicRoughnessTexture.index > -1) {
6947 SerializeGltfTextureInfo(pbr.metallicRoughnessTexture, texinfo);
6948 JsonAddMember(o,
"metallicRoughnessTexture", std::move(texinfo));
6951 SerializeExtensionMap(pbr.extensions, o);
6954 SerializeValue(
"extras", pbr.extras, o);
6958static void SerializeGltfMaterial(
Material &material, json &o) {
6959 if (material.name.size()) {
6960 SerializeStringProperty(
"name", material.name, o);
6966 SerializeNumberProperty(
"alphaCutoff", material.alphaCutoff, o);
6969 if (material.alphaMode.compare(
"OPAQUE") != 0) {
6970 SerializeStringProperty(
"alphaMode", material.alphaMode, o);
6973 if (material.doubleSided !=
false)
6974 JsonAddMember(o,
"doubleSided",
json(material.doubleSided));
6976 if (material.normalTexture.index > -1) {
6978 SerializeGltfNormalTextureInfo(material.normalTexture, texinfo);
6979 JsonAddMember(o,
"normalTexture", std::move(texinfo));
6982 if (material.occlusionTexture.index > -1) {
6984 SerializeGltfOcclusionTextureInfo(material.occlusionTexture, texinfo);
6985 JsonAddMember(o,
"occlusionTexture", std::move(texinfo));
6988 if (material.emissiveTexture.index > -1) {
6990 SerializeGltfTextureInfo(material.emissiveTexture, texinfo);
6991 JsonAddMember(o,
"emissiveTexture", std::move(texinfo));
6994 std::vector<double> default_emissiveFactor = {0.0, 0.0, 0.0};
6995 if (!
Equals(material.emissiveFactor, default_emissiveFactor)) {
6996 SerializeNumberArrayProperty<double>(
"emissiveFactor",
6997 material.emissiveFactor, o);
7001 json pbrMetallicRoughness;
7002 SerializeGltfPbrMetallicRoughness(material.pbrMetallicRoughness,
7003 pbrMetallicRoughness);
7010 if (!JsonIsNull(pbrMetallicRoughness)) {
7011 JsonAddMember(o,
"pbrMetallicRoughness", std::move(pbrMetallicRoughness));
7016 if (material.values.size()) {
7017 json pbrMetallicRoughness;
7018 SerializeParameterMap(material.values, pbrMetallicRoughness);
7019 JsonAddMember(o,
"pbrMetallicRoughness", std::move(pbrMetallicRoughness));
7022 SerializeParameterMap(material.additionalValues, o);
7027 SerializeExtensionMap(material.extensions, o);
7029 if (material.extras.Type() !=
NULL_TYPE) {
7030 SerializeValue(
"extras", material.extras, o);
7034static void SerializeGltfMesh(
Mesh &mesh, json &o) {
7036 JsonReserveArray(primitives, mesh.primitives.size());
7037 for (
unsigned int i = 0; i < mesh.primitives.size(); ++i) {
7039 const Primitive &gltfPrimitive = mesh.primitives[i];
7042 for (
auto attrIt = gltfPrimitive.attributes.begin();
7043 attrIt != gltfPrimitive.attributes.end(); ++attrIt) {
7044 SerializeNumberProperty<int>(attrIt->first, attrIt->second, attributes);
7047 JsonAddMember(primitive,
"attributes", std::move(attributes));
7051 if (gltfPrimitive.indices > -1) {
7052 SerializeNumberProperty<int>(
"indices", gltfPrimitive.indices, primitive);
7055 if (gltfPrimitive.material > -1) {
7056 SerializeNumberProperty<int>(
"material", gltfPrimitive.material,
7059 SerializeNumberProperty<int>(
"mode", gltfPrimitive.mode, primitive);
7062 if (gltfPrimitive.targets.size()) {
7064 JsonReserveArray(targets, gltfPrimitive.targets.size());
7065 for (
unsigned int k = 0; k < gltfPrimitive.targets.size(); ++k) {
7066 json targetAttributes;
7067 std::map<std::string, int> targetData = gltfPrimitive.targets[k];
7068 for (std::map<std::string, int>::iterator attrIt = targetData.begin();
7069 attrIt != targetData.end(); ++attrIt) {
7070 SerializeNumberProperty<int>(attrIt->first, attrIt->second,
7073 JsonPushBack(targets, std::move(targetAttributes));
7075 JsonAddMember(primitive,
"targets", std::move(targets));
7078 SerializeExtensionMap(gltfPrimitive.extensions, primitive);
7080 if (gltfPrimitive.extras.Type() !=
NULL_TYPE) {
7081 SerializeValue(
"extras", gltfPrimitive.extras, primitive);
7084 JsonPushBack(primitives, std::move(primitive));
7087 JsonAddMember(o,
"primitives", std::move(primitives));
7089 if (mesh.weights.size()) {
7090 SerializeNumberArrayProperty<double>(
"weights", mesh.weights, o);
7093 if (mesh.name.size()) {
7094 SerializeStringProperty(
"name", mesh.name, o);
7097 SerializeExtensionMap(mesh.extensions, o);
7099 SerializeValue(
"extras", mesh.extras, o);
7103static void SerializeSpotLight(
SpotLight &spot, json &o) {
7104 SerializeNumberProperty(
"innerConeAngle", spot.innerConeAngle, o);
7105 SerializeNumberProperty(
"outerConeAngle", spot.outerConeAngle, o);
7106 SerializeExtensionMap(spot.extensions, o);
7108 SerializeValue(
"extras", spot.extras, o);
7112static void SerializeGltfLight(
Light &light, json &o) {
7113 if (!light.name.empty()) SerializeStringProperty(
"name", light.name, o);
7114 SerializeNumberProperty(
"intensity", light.intensity, o);
7115 if (light.range > 0.0) {
7116 SerializeNumberProperty(
"range", light.range, o);
7118 SerializeNumberArrayProperty(
"color", light.color, o);
7119 SerializeStringProperty(
"type", light.type, o);
7120 if (light.type ==
"spot") {
7122 SerializeSpotLight(light.spot, spot);
7123 JsonAddMember(o,
"spot", std::move(spot));
7125 SerializeExtensionMap(light.extensions, o);
7127 SerializeValue(
"extras", light.extras, o);
7131static void SerializeGltfNode(
Node &node, json &o) {
7132 if (node.translation.size() > 0) {
7133 SerializeNumberArrayProperty<double>(
"translation", node.translation, o);
7135 if (node.rotation.size() > 0) {
7136 SerializeNumberArrayProperty<double>(
"rotation", node.rotation, o);
7138 if (node.scale.size() > 0) {
7139 SerializeNumberArrayProperty<double>(
"scale", node.scale, o);
7141 if (node.matrix.size() > 0) {
7142 SerializeNumberArrayProperty<double>(
"matrix", node.matrix, o);
7144 if (node.mesh != -1) {
7145 SerializeNumberProperty<int>(
"mesh", node.mesh, o);
7148 if (node.skin != -1) {
7149 SerializeNumberProperty<int>(
"skin", node.skin, o);
7152 if (node.camera != -1) {
7153 SerializeNumberProperty<int>(
"camera", node.camera, o);
7156 if (node.weights.size() > 0) {
7157 SerializeNumberArrayProperty<double>(
"weights", node.weights, o);
7161 SerializeValue(
"extras", node.extras, o);
7164 SerializeExtensionMap(node.extensions, o);
7165 if (!node.name.empty()) SerializeStringProperty(
"name", node.name, o);
7166 SerializeNumberArrayProperty<int>(
"children", node.children, o);
7169static void SerializeGltfSampler(
Sampler &sampler, json &o) {
7170 if (sampler.magFilter != -1) {
7171 SerializeNumberProperty(
"magFilter", sampler.magFilter, o);
7173 if (sampler.minFilter != -1) {
7174 SerializeNumberProperty(
"minFilter", sampler.minFilter, o);
7177 SerializeNumberProperty(
"wrapS", sampler.wrapS, o);
7178 SerializeNumberProperty(
"wrapT", sampler.wrapT, o);
7180 if (sampler.extras.Type() !=
NULL_TYPE) {
7181 SerializeValue(
"extras", sampler.extras, o);
7187 SerializeNumberProperty(
"zfar", camera.zfar, o);
7188 SerializeNumberProperty(
"znear", camera.znear, o);
7189 SerializeNumberProperty(
"xmag", camera.xmag, o);
7190 SerializeNumberProperty(
"ymag", camera.ymag, o);
7192 if (camera.extras.Type() !=
NULL_TYPE) {
7193 SerializeValue(
"extras", camera.extras, o);
7199 SerializeNumberProperty(
"zfar", camera.zfar, o);
7200 SerializeNumberProperty(
"znear", camera.znear, o);
7201 if (camera.aspectRatio > 0) {
7202 SerializeNumberProperty(
"aspectRatio", camera.aspectRatio, o);
7205 if (camera.yfov > 0) {
7206 SerializeNumberProperty(
"yfov", camera.yfov, o);
7209 if (camera.extras.Type() !=
NULL_TYPE) {
7210 SerializeValue(
"extras", camera.extras, o);
7214static void SerializeGltfCamera(
const Camera &camera, json &o) {
7215 SerializeStringProperty(
"type", camera.type, o);
7216 if (!camera.name.empty()) {
7217 SerializeStringProperty(
"name", camera.name, o);
7220 if (camera.type.compare(
"orthographic") == 0) {
7222 SerializeGltfOrthographicCamera(camera.orthographic, orthographic);
7223 JsonAddMember(o,
"orthographic", std::move(orthographic));
7224 }
else if (camera.type.compare(
"perspective") == 0) {
7226 SerializeGltfPerspectiveCamera(camera.perspective, perspective);
7227 JsonAddMember(o,
"perspective", std::move(perspective));
7232 if (camera.extras.Type() !=
NULL_TYPE) {
7233 SerializeValue(
"extras", camera.extras, o);
7235 SerializeExtensionMap(camera.extensions, o);
7238static void SerializeGltfScene(
Scene &scene, json &o) {
7239 SerializeNumberArrayProperty<int>(
"nodes", scene.nodes, o);
7241 if (scene.name.size()) {
7242 SerializeStringProperty(
"name", scene.name, o);
7245 SerializeValue(
"extras", scene.extras, o);
7247 SerializeExtensionMap(scene.extensions, o);
7250static void SerializeGltfSkin(
Skin &skin, json &o) {
7252 SerializeNumberArrayProperty<int>(
"joints", skin.joints, o);
7254 if (skin.inverseBindMatrices >= 0) {
7255 SerializeNumberProperty(
"inverseBindMatrices", skin.inverseBindMatrices, o);
7258 if (skin.skeleton >= 0) {
7259 SerializeNumberProperty(
"skeleton", skin.skeleton, o);
7262 if (skin.name.size()) {
7263 SerializeStringProperty(
"name", skin.name, o);
7267static void SerializeGltfTexture(
Texture &texture, json &o) {
7268 if (texture.sampler > -1) {
7269 SerializeNumberProperty(
"sampler", texture.sampler, o);
7271 if (texture.source > -1) {
7272 SerializeNumberProperty(
"source", texture.source, o);
7274 if (texture.name.size()) {
7275 SerializeStringProperty(
"name", texture.name, o);
7277 if (texture.extras.Type() !=
NULL_TYPE) {
7278 SerializeValue(
"extras", texture.extras, o);
7280 SerializeExtensionMap(texture.extensions, o);
7286static void SerializeGltfModel(
Model *model, json &o) {
7288 if (model->accessors.size()) {
7290 JsonReserveArray(accessors, model->accessors.size());
7291 for (
unsigned int i = 0; i < model->accessors.size(); ++i) {
7293 SerializeGltfAccessor(model->accessors[i], accessor);
7294 JsonPushBack(accessors, std::move(accessor));
7296 JsonAddMember(o,
"accessors", std::move(accessors));
7300 if (model->animations.size()) {
7302 JsonReserveArray(animations, model->animations.size());
7303 for (
unsigned int i = 0; i < model->animations.size(); ++i) {
7304 if (model->animations[i].channels.size()) {
7306 SerializeGltfAnimation(model->animations[i], animation);
7307 JsonPushBack(animations, std::move(animation));
7311 JsonAddMember(o,
"animations", std::move(animations));
7316 SerializeGltfAsset(model->asset, asset);
7317 JsonAddMember(o,
"asset", std::move(asset));
7320 if (model->bufferViews.size()) {
7322 JsonReserveArray(bufferViews, model->bufferViews.size());
7323 for (
unsigned int i = 0; i < model->bufferViews.size(); ++i) {
7325 SerializeGltfBufferView(model->bufferViews[i], bufferView);
7326 JsonPushBack(bufferViews, std::move(bufferView));
7328 JsonAddMember(o,
"bufferViews", std::move(bufferViews));
7332 if (model->extensionsRequired.size()) {
7333 SerializeStringArrayProperty(
"extensionsRequired",
7334 model->extensionsRequired, o);
7338 if (model->materials.size()) {
7340 JsonReserveArray(materials, model->materials.size());
7341 for (
unsigned int i = 0; i < model->materials.size(); ++i) {
7343 SerializeGltfMaterial(model->materials[i], material);
7345 if (JsonIsNull(material)) {
7352 JsonSetObject(material);
7354 JsonPushBack(materials, std::move(material));
7356 JsonAddMember(o,
"materials", std::move(materials));
7360 if (model->meshes.size()) {
7362 JsonReserveArray(meshes, model->meshes.size());
7363 for (
unsigned int i = 0; i < model->meshes.size(); ++i) {
7365 SerializeGltfMesh(model->meshes[i], mesh);
7366 JsonPushBack(meshes, std::move(mesh));
7368 JsonAddMember(o,
"meshes", std::move(meshes));
7372 if (model->nodes.size()) {
7374 JsonReserveArray(nodes, model->nodes.size());
7375 for (
unsigned int i = 0; i < model->nodes.size(); ++i) {
7377 SerializeGltfNode(model->nodes[i], node);
7378 JsonPushBack(nodes, std::move(node));
7380 JsonAddMember(o,
"nodes", std::move(nodes));
7384 if (model->defaultScene > -1) {
7385 SerializeNumberProperty<int>(
"scene", model->defaultScene, o);
7389 if (model->scenes.size()) {
7391 JsonReserveArray(scenes, model->scenes.size());
7392 for (
unsigned int i = 0; i < model->scenes.size(); ++i) {
7394 SerializeGltfScene(model->scenes[i], currentScene);
7395 JsonPushBack(scenes, std::move(currentScene));
7397 JsonAddMember(o,
"scenes", std::move(scenes));
7401 if (model->skins.size()) {
7403 JsonReserveArray(skins, model->skins.size());
7404 for (
unsigned int i = 0; i < model->skins.size(); ++i) {
7406 SerializeGltfSkin(model->skins[i], skin);
7407 JsonPushBack(skins, std::move(skin));
7409 JsonAddMember(o,
"skins", std::move(skins));
7413 if (model->textures.size()) {
7415 JsonReserveArray(textures, model->textures.size());
7416 for (
unsigned int i = 0; i < model->textures.size(); ++i) {
7418 SerializeGltfTexture(model->textures[i], texture);
7419 JsonPushBack(textures, std::move(texture));
7421 JsonAddMember(o,
"textures", std::move(textures));
7425 if (model->samplers.size()) {
7427 JsonReserveArray(samplers, model->samplers.size());
7428 for (
unsigned int i = 0; i < model->samplers.size(); ++i) {
7430 SerializeGltfSampler(model->samplers[i], sampler);
7431 JsonPushBack(samplers, std::move(sampler));
7433 JsonAddMember(o,
"samplers", std::move(samplers));
7437 if (model->cameras.size()) {
7439 JsonReserveArray(cameras, model->cameras.size());
7440 for (
unsigned int i = 0; i < model->cameras.size(); ++i) {
7442 SerializeGltfCamera(model->cameras[i], camera);
7443 JsonPushBack(cameras, std::move(camera));
7445 JsonAddMember(o,
"cameras", std::move(cameras));
7449 SerializeExtensionMap(model->extensions, o);
7451 auto extensionsUsed = model->extensionsUsed;
7454 if (model->lights.size()) {
7456 JsonReserveArray(lights, model->lights.size());
7457 for (
unsigned int i = 0; i < model->lights.size(); ++i) {
7459 SerializeGltfLight(model->lights[i], light);
7460 JsonPushBack(lights, std::move(light));
7462 json khr_lights_cmn;
7463 JsonAddMember(khr_lights_cmn,
"lights", std::move(lights));
7467 json_const_iterator it;
7468 if (FindMember(o,
"extensions", it)) {
7469 JsonAssign(ext_j, GetValue(it));
7473 JsonAddMember(ext_j,
"KHR_lights_punctual", std::move(khr_lights_cmn));
7475 JsonAddMember(o,
"extensions", std::move(ext_j));
7479 auto has_khr_lights_punctual =
7480 std::find_if(extensionsUsed.begin(), extensionsUsed.end(),
7481 [](
const std::string &s) {
7482 return (s.compare(
"KHR_lights_punctual") == 0);
7485 if (has_khr_lights_punctual == extensionsUsed.end()) {
7486 extensionsUsed.push_back(
"KHR_lights_punctual");
7492 if (extensionsUsed.size()) {
7493 SerializeStringArrayProperty(
"extensionsUsed", extensionsUsed, o);
7497 if (model->extras.Type() !=
NULL_TYPE) {
7498 SerializeValue(
"extras", model->extras, o);
7502static bool WriteGltfStream(std::ostream &stream,
const std::string &content) {
7503 stream << content << std::endl;
7507static bool WriteGltfFile(
const std::string &output,
7508 const std::string &content) {
7510#if defined(_MSC_VER)
7511 std::ofstream gltfFile(UTF8ToWchar(output).c_str());
7512#elif defined(__GLIBCXX__)
7513 int file_descriptor = _wopen(UTF8ToWchar(output).c_str(),
7514 _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY);
7515 __gnu_cxx::stdio_filebuf<char> wfile_buf(
7516 file_descriptor, std::ios_base::out | std::ios_base::binary);
7517 std::ostream gltfFile(&wfile_buf);
7518 if (!wfile_buf.is_open())
return false;
7520 std::ofstream gltfFile(output.c_str());
7521 if (!gltfFile.is_open())
return false;
7524 std::ofstream gltfFile(output.c_str());
7525 if (!gltfFile.is_open())
return false;
7527 return WriteGltfStream(gltfFile, content);
7530static void WriteBinaryGltfStream(std::ostream &stream,
7531 const std::string &content,
7532 const std::vector<
unsigned char,GameApiAllocator<unsigned char> > &binBuffer) {
7533 const std::string
header =
"glTF";
7534 const int version = 2;
7537 auto roundUp = [](uint32_t numToRound, uint32_t multiple) {
7538 if (multiple == 0)
return numToRound;
7540 uint32_t
remainder = numToRound % multiple;
7541 if (remainder == 0)
return numToRound;
7543 return numToRound + multiple -
remainder;
7546 const uint32_t padding_size =
7547 roundUp(uint32_t(content.size()), 4) - uint32_t(content.size());
7551 const uint32_t length =
7552 12 + 8 + roundUp(uint32_t(content.size()), 4) +
7553 (binBuffer.size() ? (8 + roundUp(uint32_t(binBuffer.size()), 4)) : 0);
7555 stream.write(
header.c_str(), std::streamsize(
header.size()));
7556 stream.write(
reinterpret_cast<const char *
>(&version),
sizeof(version));
7557 stream.write(
reinterpret_cast<const char *
>(&length),
sizeof(length));
7560 const uint32_t model_length = uint32_t(content.size()) + padding_size;
7561 const uint32_t model_format = 0x4E4F534A;
7562 stream.write(
reinterpret_cast<const char *
>(&model_length),
7563 sizeof(model_length));
7564 stream.write(
reinterpret_cast<const char *
>(&model_format),
7565 sizeof(model_format));
7566 stream.write(content.c_str(), std::streamsize(content.size()));
7569 if (padding_size > 0) {
7570 const std::string padding = std::string(
size_t(padding_size),
' ');
7571 stream.write(padding.c_str(), std::streamsize(padding.size()));
7573 if (binBuffer.size() > 0) {
7574 const uint32_t bin_padding_size =
7575 roundUp(uint32_t(binBuffer.size()), 4) - uint32_t(binBuffer.size());
7577 const uint32_t bin_length = uint32_t(binBuffer.size()) + bin_padding_size;
7578 const uint32_t bin_format = 0x004e4942;
7579 stream.write(
reinterpret_cast<const char *
>(&bin_length),
7580 sizeof(bin_length));
7581 stream.write(
reinterpret_cast<const char *
>(&bin_format),
7582 sizeof(bin_format));
7583 stream.write(
reinterpret_cast<const char *
>(binBuffer.data()),
7584 std::streamsize(binBuffer.size()));
7586 if (bin_padding_size > 0) {
7587 const std::vector<unsigned char> padding =
7588 std::vector<unsigned char>(
size_t(bin_padding_size), 0);
7589 stream.write(
reinterpret_cast<const char *
>(padding.data()),
7590 std::streamsize(padding.size()));
7595static void WriteBinaryGltfFile(
const std::string &output,
7596 const std::string &content,
7597 const std::vector<
unsigned char,GameApiAllocator<unsigned char> > &binBuffer) {
7599#if defined(_MSC_VER)
7600 std::ofstream gltfFile(UTF8ToWchar(output).c_str(), std::ios::binary);
7601#elif defined(__GLIBCXX__)
7602 int file_descriptor = _wopen(UTF8ToWchar(output).c_str(),
7603 _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY);
7604 __gnu_cxx::stdio_filebuf<char> wfile_buf(
7605 file_descriptor, std::ios_base::out | std::ios_base::binary);
7606 std::ostream gltfFile(&wfile_buf);
7608 std::ofstream gltfFile(output.c_str(), std::ios::binary);
7611 std::ofstream gltfFile(output.c_str(), std::ios::binary);
7613 WriteBinaryGltfStream(gltfFile, content, binBuffer);
7617 bool prettyPrint =
true,
7618 bool writeBinary =
false) {
7619 JsonDocument output;
7622 SerializeGltfModel(model, output);
7625 std::vector<unsigned char, ::GameApiAllocator<unsigned char> > binBuffer;
7626 if (model->buffers.size()) {
7628 JsonReserveArray(buffers, model->buffers.size());
7629 for (
unsigned int i = 0; i < model->buffers.size(); ++i) {
7631 if (writeBinary && i == 0 && model->buffers[i].uri.empty()) {
7632 SerializeGltfBufferBin(model->buffers[i], buffer, binBuffer);
7634 SerializeGltfBuffer(model->buffers[i], buffer);
7636 JsonPushBack(buffers, std::move(buffer));
7638 JsonAddMember(output,
"buffers", std::move(buffers));
7642 if (model->images.size()) {
7644 JsonReserveArray(images, model->images.size());
7645 for (
unsigned int i = 0; i < model->images.size(); ++i) {
7648 std::string dummystring =
"";
7652 UpdateImageObject(model->images[i], dummystring,
int(i),
false,
7653 &this->WriteImageData, this->write_image_user_data_);
7654 SerializeGltfImage(model->images[i],
image);
7655 JsonPushBack(images, std::move(
image));
7657 JsonAddMember(output,
"images", std::move(images));
7661 WriteBinaryGltfStream(stream, JsonToString(output), binBuffer);
7663 WriteGltfStream(stream, JsonToString(output, prettyPrint ? 2 : -1));
7670 bool embedImages =
false,
7671 bool embedBuffers =
false,
7672 bool prettyPrint =
true,
7673 bool writeBinary =
false) {
7674 JsonDocument output;
7675 std::string defaultBinFilename = GetBaseFilename(filename);
7676 std::string defaultBinFileExt =
".bin";
7677 std::string::size_type pos =
7678 defaultBinFilename.rfind(
'.', defaultBinFilename.length());
7680 if (pos != std::string::npos) {
7681 defaultBinFilename = defaultBinFilename.substr(0, pos);
7683 std::string baseDir = GetBaseDir(filename);
7684 if (baseDir.empty()) {
7688 SerializeGltfModel(model, output);
7691 std::vector<std::string> usedUris;
7692 std::vector<unsigned char,GameApiAllocator<unsigned char> > binBuffer;
7693 if (model->buffers.size()) {
7695 JsonReserveArray(buffers, model->buffers.size());
7696 for (
unsigned int i = 0; i < model->buffers.size(); ++i) {
7698 if (writeBinary && i == 0 && model->buffers[i].uri.empty()) {
7699 SerializeGltfBufferBin(model->buffers[i], buffer, binBuffer);
7700 }
else if (embedBuffers) {
7701 SerializeGltfBuffer(model->buffers[i], buffer);
7703 std::string binSavePath;
7705 if (!model->buffers[i].uri.empty() &&
7707 binUri = model->buffers[i].uri;
7709 binUri = defaultBinFilename + defaultBinFileExt;
7714 for (
const std::string &usedName : usedUris) {
7715 if (binUri.compare(usedName) != 0)
continue;
7717 binUri = defaultBinFilename + std::to_string(numUsed++) +
7723 usedUris.push_back(binUri);
7724 binSavePath = JoinPath(baseDir, binUri);
7725 if (!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
7730 JsonPushBack(buffers, std::move(buffer));
7732 JsonAddMember(output,
"buffers", std::move(buffers));
7736 if (model->images.size()) {
7738 JsonReserveArray(images, model->images.size());
7739 for (
unsigned int i = 0; i < model->images.size(); ++i) {
7742 UpdateImageObject(model->images[i], baseDir,
int(i), embedImages,
7743 &this->WriteImageData, this->write_image_user_data_);
7744 SerializeGltfImage(model->images[i],
image);
7745 JsonPushBack(images, std::move(
image));
7747 JsonAddMember(output,
"images", std::move(images));
7751 WriteBinaryGltfFile(filename, JsonToString(output), binBuffer);
7753 WriteGltfFile(filename, JsonToString(output, (prettyPrint ? 2 : -1)));
7762#pragma clang diagnostic pop
P func(int c, EveryApi &ev)
Definition test.cpp:59
Env e
Definition Common.cc:2
Type
Definition Database.hh:9
bool ReadWholeFile(std::vector< unsigned char, GameApiAllocator< unsigned char > > *out, std::string *err, const std::string &filepath, void *ptr)
Definition GameApi_gltf.cc:2012
bool WriteWholeFile(std::string *err, const std::string &filepath, const std::vector< unsigned char, GameApiAllocator< unsigned char > > &contents, void *ptr)
Definition GameApi_gltf.cc:2065
std::string ExpandFilePath(const std::string &str, void *ptr)
Definition GameApi_gltf.cc:2000
bool LoadImageData(tinygltf::Image *image, const int image_idx, std::string *err, std::string *warn, int req_width, int req_height, const unsigned char *bytes, int size, void *ptr)
Definition GameApi_gltf.cc:2400
bool WriteImageData(const std::string *basepath, const std::string *filename, tinygltf::Image *image, bool b, void *ptr)
Definition GameApi_gltf.cc:2485
bool FileExists(const std::string &abs_filename, void *ptr)
Definition GameApi_gltf.cc:1994
header('
Definition cert.php:38
void Init(const char *data, size_t data_size)
Definition decoder_buffer.cc:29
StatusOr< std::unique_ptr< Mesh > > DecodeMeshFromBuffer(DecoderBuffer *in_buffer)
Definition decode.cc:86
uint8_t num_components() const
Definition geometry_attribute.h:263
bool ConvertValue(AttributeValueIndex att_id, OutT *out_val) const
Definition geometry_attribute.h:169
FaceIndex::ValueType num_faces() const
Definition mesh.h:76
const Face & face(FaceIndex face_id) const
Definition mesh.h:79
std::array< PointIndex, 3 > Face
Definition mesh.h:54
AttributeValueIndex mapped_index(PointIndex point_index) const
Definition point_attribute.h:56
PointIndex::ValueType num_points() const
Definition point_cloud.h:185
Definition tiny_gltf.h:1146
Asset asset
Definition tiny_gltf.h:1172
Value extras
Definition tiny_gltf.h:1174
std::string extras_json_string
Definition tiny_gltf.h:1178
std::vector< Accessor > accessors
Definition tiny_gltf.h:1153
std::vector< Node > nodes
Definition tiny_gltf.h:1159
std::vector< Camera > cameras
Definition tiny_gltf.h:1164
std::vector< Sampler > samplers
Definition tiny_gltf.h:1163
int defaultScene
Definition tiny_gltf.h:1168
std::vector< Buffer > buffers
Definition tiny_gltf.h:1155
std::vector< Texture > textures
Definition tiny_gltf.h:1160
ExtensionMap extensions
Definition tiny_gltf.h:1175
std::vector< Skin > skins
Definition tiny_gltf.h:1162
std::vector< Scene > scenes
Definition tiny_gltf.h:1165
bool operator==(const Model &) const
std::string extensions_json_string
Definition tiny_gltf.h:1179
std::vector< Animation > animations
Definition tiny_gltf.h:1154
std::vector< Image > images
Definition tiny_gltf.h:1161
std::vector< std::string > extensionsRequired
Definition tiny_gltf.h:1170
std::vector< Mesh > meshes
Definition tiny_gltf.h:1158
std::vector< Light > lights
Definition tiny_gltf.h:1166
std::vector< std::string > extensionsUsed
Definition tiny_gltf.h:1169
std::vector< Material > materials
Definition tiny_gltf.h:1157
std::vector< BufferView > bufferViews
Definition tiny_gltf.h:1156
Definition tiny_gltf.h:1030
int camera
Definition tiny_gltf.h:1038
bool operator==(const Node &) const
Node()
Definition tiny_gltf.h:1032
int mesh
Definition tiny_gltf.h:1042
std::vector< double > matrix
Definition tiny_gltf.h:1047
std::string extensions_json_string
Definition tiny_gltf.h:1055
std::vector< double > rotation
Definition tiny_gltf.h:1044
Value extras
Definition tiny_gltf.h:1051
std::vector< double > weights
Definition tiny_gltf.h:1048
std::vector< int > children
Definition tiny_gltf.h:1043
std::string name
Definition tiny_gltf.h:1040
std::vector< double > scale
Definition tiny_gltf.h:1045
int skin
Definition tiny_gltf.h:1041
ExtensionMap extensions
Definition tiny_gltf.h:1050
std::string extras_json_string
Definition tiny_gltf.h:1054
std::vector< double > translation
Definition tiny_gltf.h:1046
void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data)
bool LoadBinaryFromMemory(Model *model, std::string *err, std::string *warn, const unsigned char *bytes, const unsigned int length, const std::string &base_dir="", unsigned int check_sections=REQUIRE_VERSION)
bool WriteGltfSceneToFile(Model *model, const std::string &filename, bool embedImages, bool embedBuffers, bool prettyPrint, bool writeBinary)
bool GetStoreOriginalJSONForExtrasAndExtensions() const
Definition tiny_gltf.h:1395
bool GetSerializeDefaultValues() const
Definition tiny_gltf.h:1384
void SetImageWriter(WriteImageDataFunction WriteImageData, void *user_data)
void SetSerializeDefaultValues(const bool enabled)
Definition tiny_gltf.h:1380
bool LoadBinaryFromFile(Model *model, std::string *err, std::string *warn, const std::string &filename, unsigned int check_sections=REQUIRE_VERSION)
bool LoadASCIIFromString(Model *model, std::string *err, std::string *warn, const char *str, const unsigned int length, const std::string &base_dir, unsigned int check_sections=REQUIRE_VERSION)
bool GetPreserveImageChannels() const
Definition tiny_gltf.h:1407
void SetFsCallbacks(FsCallbacks callbacks)
void SetPreserveImageChannels(bool onoff)
Definition tiny_gltf.h:1403
bool WriteGltfSceneToStream(Model *model, std::ostream &stream, bool prettyPrint, bool writeBinary)
TinyGLTF()
Definition tiny_gltf.h:1289
void SetStoreOriginalJSONForExtrasAndExtensions(const bool enabled)
Definition tiny_gltf.h:1391
~TinyGLTF()
Definition tiny_gltf.h:1295
bool LoadASCIIFromFile(Model *model, std::string *err, std::string *warn, const std::string &filename, unsigned int check_sections=REQUIRE_VERSION)
Definition tiny_gltf.h:264
Value(double n)
Definition tiny_gltf.h:280
std::map< std::string, Value > Object
Definition tiny_gltf.h:267
bool IsInt() const
Definition tiny_gltf.h:307
Value(Array &&a) noexcept
Definition tiny_gltf.h:294
Value(std::vector< unsigned char > &&v) noexcept
Definition tiny_gltf.h:290
bool IsObject() const
Definition tiny_gltf.h:319
std::vector< std::string > Keys() const
Definition tiny_gltf.h:377
Value(const Object &o)
Definition tiny_gltf.h:297
double real_value_
Definition tiny_gltf.h:397
std::vector< unsigned char > binary_value_
Definition tiny_gltf.h:399
double GetNumberAsDouble() const
Definition tiny_gltf.h:322
Array array_value_
Definition tiny_gltf.h:400
size_t Size() const
Definition tiny_gltf.h:389
bool IsBool() const
Definition tiny_gltf.h:305
const Value & Get(const std::string &key) const
Definition tiny_gltf.h:357
bool IsReal() const
Definition tiny_gltf.h:311
size_t ArrayLen() const
Definition tiny_gltf.h:364
Value(Object &&o) noexcept
Definition tiny_gltf.h:298
bool operator==(const tinygltf::Value &other) const
int GetNumberAsInt() const
Definition tiny_gltf.h:332
char Type() const
Definition tiny_gltf.h:303
bool IsString() const
Definition tiny_gltf.h:313
Value(const unsigned char *p, size_t n)
Definition tiny_gltf.h:286
std::string string_value_
Definition tiny_gltf.h:398
Value()
Definition tiny_gltf.h:269
bool boolean_value_
Definition tiny_gltf.h:402
Value(std::string &&s)
Definition tiny_gltf.h:284
bool IsBinary() const
Definition tiny_gltf.h:315
int type_
Definition tiny_gltf.h:394
bool Has(const std::string &key) const
Definition tiny_gltf.h:370
Value(const Array &a)
Definition tiny_gltf.h:293
Value(const std::string &s)
Definition tiny_gltf.h:281
Object object_value_
Definition tiny_gltf.h:401
Value(bool b)
Definition tiny_gltf.h:275
std::vector< Value > Array
Definition tiny_gltf.h:266
Value(int i)
Definition tiny_gltf.h:276
bool IsArray() const
Definition tiny_gltf.h:317
const Value & Get(int idx) const
Definition tiny_gltf.h:347
int int_value_
Definition tiny_gltf.h:396
bool IsNumber() const
Definition tiny_gltf.h:309
ret($return)
Definition mesh_login_result.php:5
d
Definition meshpage.php:3895
iVBORw0KGgoAAAANSUhEUgAAANcAAAB5CAMAAACdtUQZAAAA51BMVEX</div ></div >< div style="padding: 0px 0px; width: 1324px;">< div style="height: 400px; width: 1324px;"></div >< div itemscope itemtype="https: </div><div itemscope itemtype="https:</div >< div itemscope itemtype="https: </div></div><p><div style="padding:0px 0px;width:1324px;"><div></div><div itemscope itemtype="https:< ul >< li >< b > Application name
8AkrcAgqgAs9wqQ0ey2tkAo8gAuuQfeI4hPUH09fXHy8z4+fng4uNKXF/Lz9BzfoAcgpkQMTUAKjAbOT4Qr9AXhJ8Rl7ktMCwTosA...
Definition meshpage.php:1610
lazy data
Definition meshpage.php:1583
str
Definition meshpage.php:1778
line height
Definition meshpage.php:3536
tag src
Definition meshpage.php:1786
n< br > font size
Definition meshpage.php:3536
background image
Definition meshpage_bootstrap.php:1723
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
void remainder(Module &m)
Definition operators.hpp:210
size_t count(const T &t_target, const typename T::key_type &t_key)
Definition bootstrap_stl.hpp:104
FaceIndex FaceIndex
Definition mesh_edgebreaker_encoder_impl.cc:36
std::string base64_encode(const std::string &in)
Definition httplib.h:4599
basic_json<> json
default JSON class
Definition json.hpp:111
*specialization for std::less< value_t > *see nlohmann::detail::value_t rhs const noexcept
Definition json.hpp:20328
Definition tiny_gltf.h:96
std::array< double, 4 > ColorValue
Agregate object for representing a color.
Definition tiny_gltf.h:434
@ NULL_TYPE
Definition tiny_gltf.h:196
@ BINARY_TYPE
Definition tiny_gltf.h:202
@ STRING_TYPE
Definition tiny_gltf.h:200
@ BOOL_TYPE
Definition tiny_gltf.h:199
@ ARRAY_TYPE
Definition tiny_gltf.h:201
@ REAL_TYPE
Definition tiny_gltf.h:197
@ OBJECT_TYPE
Definition tiny_gltf.h:203
@ INT_TYPE
Definition tiny_gltf.h:198
std::string ExpandFilePath(const std::string &filepath, void *userdata)
std::map< std::string, Value > ExtensionMap
Definition tiny_gltf.h:528
std::string(* ExpandFilePathFunction)(const std::string &, void *)
Definition tiny_gltf.h:1229
bool(* WriteWholeFileFunction)(std::string *, const std::string &, const std::vector< unsigned char, ::GameApiAllocator< unsigned char > > &, void *)
Definition tiny_gltf.h:1241
bool ReadWholeFile(std::vector< unsigned char, ::GameApiAllocator< unsigned char > > *out, std::string *err, const std::string &filepath, void *)
bool(* WriteImageDataFunction)(const std::string *, const std::string *, Image *, bool, void *)
Definition tiny_gltf.h:1205
SectionCheck
Definition tiny_gltf.h:1182
@ REQUIRE_SCENE
Definition tiny_gltf.h:1185
@ REQUIRE_BUFFER_VIEWS
Definition tiny_gltf.h:1190
@ REQUIRE_ACCESSORS
Definition tiny_gltf.h:1188
@ REQUIRE_NODES
Definition tiny_gltf.h:1187
@ REQUIRE_VERSION
Definition tiny_gltf.h:1184
@ NO_REQUIRE
Definition tiny_gltf.h:1183
@ REQUIRE_BUFFERS
Definition tiny_gltf.h:1189
@ REQUIRE_ALL
Definition tiny_gltf.h:1191
@ REQUIRE_SCENES
Definition tiny_gltf.h:1186
bool FileExists(const std::string &abs_filename, void *)
bool(* FileExistsFunction)(const std::string &abs_filename, void *)
Definition tiny_gltf.h:1224
std::map< std::string, Parameter > ParameterMap
Definition tiny_gltf.h:527
bool DecodeDataURI(std::vector< unsigned char > *out, std::string &mime_type, const std::string &in, size_t reqBytes, bool checkSize)
bool WriteImageData(const std::string *basepath, const std::string *filename, Image *image, bool embedImages, void *)
bool WriteWholeFile(std::string *err, const std::string &filepath, const std::vector< unsigned char, ::GameApiAllocator< unsigned char > > &contents, void *)
bool IsDataURI(const std::string &in)
bool(* LoadImageDataFunction)(Image *, const int, std::string *, std::string *, int, int, const unsigned char *, int, void *user_pointer)
Definition tiny_gltf.h:1197
bool(* ReadWholeFileFunction)(std::vector< unsigned char, ::GameApiAllocator< unsigned char > > *, std::string *, const std::string &, void *)
Definition tiny_gltf.h:1234
bool LoadImageData(Image *image, const int image_idx, std::string *err, std::string *warn, int req_width, int req_height, const unsigned char *bytes, int size, void *)
double f(const std::string &, double, bool) noexcept
Definition profile_cpp_calls_2.cpp:4
STBIDEF stbi_uc * stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
STBIDEF void stbi_image_free(void *retval_from_stbi_load)
STBIDEF stbi_us * stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes)
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
Definition tiny_gltf.h:840
std::vector< double > minValues
Definition tiny_gltf.h:857
std::string name
Definition tiny_gltf.h:843
ExtensionMap extensions
Definition tiny_gltf.h:850
std::string extras_json_string
Definition tiny_gltf.h:853
int ByteStride(const BufferView &bufferViewObject) const
Definition tiny_gltf.h:879
bool isSparse
Definition tiny_gltf.h:863
bool operator==(const tinygltf::Accessor &) const
int componentType
Definition tiny_gltf.h:846
bool normalized
Definition tiny_gltf.h:845
Value extras
Definition tiny_gltf.h:849
std::string extensions_json_string
Definition tiny_gltf.h:854
Accessor()
Definition tiny_gltf.h:912
std::vector< double > maxValues
Definition tiny_gltf.h:859
size_t byteOffset
Definition tiny_gltf.h:844
int type
Definition tiny_gltf.h:848
struct tinygltf::Accessor::@225003275052212074340112271007003164351115214271 sparse
size_t count
Definition tiny_gltf.h:847
int bufferView
Definition tiny_gltf.h:841
Definition tiny_gltf.h:530
std::string target_path
Definition tiny_gltf.h:533
AnimationChannel()
Definition tiny_gltf.h:544
ExtensionMap extensions
Definition tiny_gltf.h:536
bool operator==(const AnimationChannel &) const
ExtensionMap target_extensions
Definition tiny_gltf.h:537
std::string target_extensions_json_string
Definition tiny_gltf.h:542
int target_node
Definition tiny_gltf.h:532
int sampler
Definition tiny_gltf.h:531
Value extras
Definition tiny_gltf.h:535
std::string extras_json_string
Definition tiny_gltf.h:540
std::string extensions_json_string
Definition tiny_gltf.h:541
Definition tiny_gltf.h:549
std::string extensions_json_string
Definition tiny_gltf.h:559
std::string extras_json_string
Definition tiny_gltf.h:558
Value extras
Definition tiny_gltf.h:554
int input
Definition tiny_gltf.h:550
bool operator==(const AnimationSampler &) const
AnimationSampler()
Definition tiny_gltf.h:561
int output
Definition tiny_gltf.h:551
std::string interpolation
Definition tiny_gltf.h:552
ExtensionMap extensions
Definition tiny_gltf.h:555
Definition tiny_gltf.h:566
std::string extensions_json_string
Definition tiny_gltf.h:575
std::string extras_json_string
Definition tiny_gltf.h:574
bool operator==(const Animation &) const
std::string name
Definition tiny_gltf.h:567
std::vector< AnimationChannel > channels
Definition tiny_gltf.h:568
ExtensionMap extensions
Definition tiny_gltf.h:571
Value extras
Definition tiny_gltf.h:570
std::vector< AnimationSampler > samplers
Definition tiny_gltf.h:569
Definition tiny_gltf.h:1076
std::string generator
Definition tiny_gltf.h:1078
std::string extras_json_string
Definition tiny_gltf.h:1085
std::string extensions_json_string
Definition tiny_gltf.h:1086
std::string version
Definition tiny_gltf.h:1077
std::string copyright
Definition tiny_gltf.h:1080
ExtensionMap extensions
Definition tiny_gltf.h:1081
bool operator==(const Asset &) const
Value extras
Definition tiny_gltf.h:1082
std::string minVersion
Definition tiny_gltf.h:1079
Definition tiny_gltf.h:811
bool operator==(const BufferView &) const
size_t byteLength
Definition tiny_gltf.h:815
ExtensionMap extensions
Definition tiny_gltf.h:821
Value extras
Definition tiny_gltf.h:820
std::string extras_json_string
Definition tiny_gltf.h:824
size_t byteOffset
Definition tiny_gltf.h:814
std::string extensions_json_string
Definition tiny_gltf.h:825
int buffer
Definition tiny_gltf.h:813
BufferView()
Definition tiny_gltf.h:829
int target
Definition tiny_gltf.h:818
size_t byteStride
Definition tiny_gltf.h:816
std::string name
Definition tiny_gltf.h:812
bool dracoDecoded
Definition tiny_gltf.h:827
Definition tiny_gltf.h:1058
std::string uri
Definition tiny_gltf.h:1062
std::string name
Definition tiny_gltf.h:1059
std::vector< unsigned char, ::GameApiAllocator< unsigned char > > data
Definition tiny_gltf.h:1060
ExtensionMap extensions
Definition tiny_gltf.h:1065
std::string extras_json_string
Definition tiny_gltf.h:1068
std::string extensions_json_string
Definition tiny_gltf.h:1069
Value extras
Definition tiny_gltf.h:1064
bool operator==(const Buffer &) const
Definition tiny_gltf.h:966
OrthographicCamera orthographic
Definition tiny_gltf.h:971
std::string type
Definition tiny_gltf.h:967
Camera()
Definition tiny_gltf.h:973
std::string extensions_json_string
Definition tiny_gltf.h:982
ExtensionMap extensions
Definition tiny_gltf.h:977
PerspectiveCamera perspective
Definition tiny_gltf.h:970
bool operator==(const Camera &) const
Value extras
Definition tiny_gltf.h:978
std::string extras_json_string
Definition tiny_gltf.h:981
std::string name
Definition tiny_gltf.h:968
Definition tiny_gltf.h:1249
void * user_data
Definition tiny_gltf.h:1255
ReadWholeFileFunction ReadWholeFile
Definition tiny_gltf.h:1252
ExpandFilePathFunction ExpandFilePath
Definition tiny_gltf.h:1251
FileExistsFunction FileExists
Definition tiny_gltf.h:1250
WriteWholeFileFunction WriteWholeFile
Definition tiny_gltf.h:1253
Definition tiny_gltf.h:637
unsigned char * data
Definition tiny_gltf.h:646
std::vector< unsigned char, ::GameApiAllocator< unsigned char > > image
Definition tiny_gltf.h:645
int height
Definition tiny_gltf.h:640
std::string name
Definition tiny_gltf.h:638
int bits
Definition tiny_gltf.h:642
std::string mimeType
Definition tiny_gltf.h:648
Image()
Definition tiny_gltf.h:667
Value extras
Definition tiny_gltf.h:652
bool operator==(const Image &) const
int width
Definition tiny_gltf.h:639
bool as_is
Definition tiny_gltf.h:665
int bufferView
Definition tiny_gltf.h:647
ExtensionMap extensions
Definition tiny_gltf.h:653
int component
Definition tiny_gltf.h:641
std::string extensions_json_string
Definition tiny_gltf.h:657
std::string uri
Definition tiny_gltf.h:650
std::string extras_json_string
Definition tiny_gltf.h:656
int pixel_type
Definition tiny_gltf.h:643
Definition tiny_gltf.h:1125
Light()
Definition tiny_gltf.h:1133
Value extras
Definition tiny_gltf.h:1139
double intensity
Definition tiny_gltf.h:1128
std::string extras_json_string
Definition tiny_gltf.h:1142
std::vector< double > color
Definition tiny_gltf.h:1127
ExtensionMap extensions
Definition tiny_gltf.h:1138
std::string name
Definition tiny_gltf.h:1126
double range
Definition tiny_gltf.h:1130
std::string extensions_json_string
Definition tiny_gltf.h:1143
SpotLight spot
Definition tiny_gltf.h:1131
bool operator==(const Light &) const
std::string type
Definition tiny_gltf.h:1129
Definition tiny_gltf.h:779
std::string name
Definition tiny_gltf.h:780
ExtensionMap extensions
Definition tiny_gltf.h:798
double alphaCutoff
Definition tiny_gltf.h:784
ParameterMap additionalValues
Definition tiny_gltf.h:796
Value extras
Definition tiny_gltf.h:799
std::string extras_json_string
Definition tiny_gltf.h:802
Material()
Definition tiny_gltf.h:805
bool doubleSided
Definition tiny_gltf.h:785
ParameterMap values
Definition tiny_gltf.h:795
NormalTextureInfo normalTexture
Definition tiny_gltf.h:789
bool operator==(const Material &) const
std::string extensions_json_string
Definition tiny_gltf.h:803
PbrMetallicRoughness pbrMetallicRoughness
Definition tiny_gltf.h:787
std::string alphaMode
Definition tiny_gltf.h:783
TextureInfo emissiveTexture
Definition tiny_gltf.h:791
std::vector< double > emissiveFactor
Definition tiny_gltf.h:782
OcclusionTextureInfo occlusionTexture
Definition tiny_gltf.h:790
Definition tiny_gltf.h:1014
std::string extras_json_string
Definition tiny_gltf.h:1022
std::vector< double > weights
Definition tiny_gltf.h:1017
bool operator==(const Mesh &) const
std::string extensions_json_string
Definition tiny_gltf.h:1023
std::string name
Definition tiny_gltf.h:1015
std::vector< Primitive > primitives
Definition tiny_gltf.h:1016
Value extras
Definition tiny_gltf.h:1019
ExtensionMap extensions
Definition tiny_gltf.h:1018
Definition tiny_gltf.h:715
ExtensionMap extensions
Definition tiny_gltf.h:723
Value extras
Definition tiny_gltf.h:722
std::string extras_json_string
Definition tiny_gltf.h:726
bool operator==(const NormalTextureInfo &) const
int texCoord
Definition tiny_gltf.h:717
NormalTextureInfo()
Definition tiny_gltf.h:729
double scale
Definition tiny_gltf.h:719
int index
Definition tiny_gltf.h:716
std::string extensions_json_string
Definition tiny_gltf.h:727
Definition tiny_gltf.h:734
bool operator==(const OcclusionTextureInfo &) const
int texCoord
Definition tiny_gltf.h:736
ExtensionMap extensions
Definition tiny_gltf.h:742
std::string extensions_json_string
Definition tiny_gltf.h:746
std::string extras_json_string
Definition tiny_gltf.h:745
int index
Definition tiny_gltf.h:735
Value extras
Definition tiny_gltf.h:741
double strength
Definition tiny_gltf.h:738
OcclusionTextureInfo()
Definition tiny_gltf.h:748
Definition tiny_gltf.h:948
std::string extras_json_string
Definition tiny_gltf.h:962
double xmag
Definition tiny_gltf.h:949
bool operator==(const OrthographicCamera &) const
double zfar
Definition tiny_gltf.h:951
double znear
Definition tiny_gltf.h:952
double ymag
Definition tiny_gltf.h:950
OrthographicCamera()
Definition tiny_gltf.h:954
Value extras
Definition tiny_gltf.h:959
std::string extensions_json_string
Definition tiny_gltf.h:963
ExtensionMap extensions
Definition tiny_gltf.h:958
Definition tiny_gltf.h:438
int TextureIndex() const
Definition tiny_gltf.h:454
bool operator==(const Parameter &) const
std::map< std::string, double > json_double_value
Definition tiny_gltf.h:443
double number_value
Definition tiny_gltf.h:444
double TextureScale() const
Definition tiny_gltf.h:477
std::vector< double > number_array
Definition tiny_gltf.h:442
double TextureStrength() const
Definition tiny_gltf.h:489
bool has_number_value
Definition tiny_gltf.h:440
ColorValue ColorFactor() const
Definition tiny_gltf.h:506
int TextureTexCoord() const
Definition tiny_gltf.h:465
std::string string_value
Definition tiny_gltf.h:441
double Factor() const
Definition tiny_gltf.h:501
bool bool_value
Definition tiny_gltf.h:439
Definition tiny_gltf.h:925
std::string extras_json_string
Definition tiny_gltf.h:944
ExtensionMap extensions
Definition tiny_gltf.h:940
double zfar
Definition tiny_gltf.h:928
PerspectiveCamera()
Definition tiny_gltf.h:931
double znear
Definition tiny_gltf.h:929
bool operator==(const PerspectiveCamera &) const
double yfov
Definition tiny_gltf.h:927
Value extras
Definition tiny_gltf.h:941
double aspectRatio
Definition tiny_gltf.h:926
std::string extensions_json_string
Definition tiny_gltf.h:945
Definition tiny_gltf.h:985
std::string extensions_json_string
Definition tiny_gltf.h:1003
int material
Definition tiny_gltf.h:990
int mode
Definition tiny_gltf.h:993
std::map< std::string, int > attributes
Definition tiny_gltf.h:986
Primitive()
Definition tiny_gltf.h:1005
ExtensionMap extensions
Definition tiny_gltf.h:998
Value extras
Definition tiny_gltf.h:999
int indices
Definition tiny_gltf.h:992
bool operator==(const Primitive &) const
std::string extras_json_string
Definition tiny_gltf.h:1002
std::vector< std::map< std::string, int > > targets
Definition tiny_gltf.h:994
Definition tiny_gltf.h:603
int wrapS
Definition tiny_gltf.h:613
Value extras
Definition tiny_gltf.h:621
ExtensionMap extensions
Definition tiny_gltf.h:622
int magFilter
Definition tiny_gltf.h:611
int wrapT
Definition tiny_gltf.h:616
std::string extensions_json_string
Definition tiny_gltf.h:626
std::string extras_json_string
Definition tiny_gltf.h:625
int minFilter
Definition tiny_gltf.h:607
bool operator==(const Sampler &) const
std::string name
Definition tiny_gltf.h:604
Sampler()
Definition tiny_gltf.h:628
Definition tiny_gltf.h:1093
std::string extensions_json_string
Definition tiny_gltf.h:1102
ExtensionMap extensions
Definition tiny_gltf.h:1097
std::string name
Definition tiny_gltf.h:1094
std::string extras_json_string
Definition tiny_gltf.h:1101
bool operator==(const Scene &) const
Value extras
Definition tiny_gltf.h:1098
std::vector< int > nodes
Definition tiny_gltf.h:1095
Definition tiny_gltf.h:582
int skeleton
Definition tiny_gltf.h:585
ExtensionMap extensions
Definition tiny_gltf.h:589
std::string extras_json_string
Definition tiny_gltf.h:592
bool operator==(const Skin &) const
int inverseBindMatrices
Definition tiny_gltf.h:584
std::vector< int > joints
Definition tiny_gltf.h:586
Skin()
Definition tiny_gltf.h:595
std::string name
Definition tiny_gltf.h:583
Value extras
Definition tiny_gltf.h:588
std::string extensions_json_string
Definition tiny_gltf.h:593
Definition tiny_gltf.h:1109
std::string extensions_json_string
Definition tiny_gltf.h:1122
Value extras
Definition tiny_gltf.h:1118
SpotLight()
Definition tiny_gltf.h:1113
double innerConeAngle
Definition tiny_gltf.h:1110
std::string extras_json_string
Definition tiny_gltf.h:1121
double outerConeAngle
Definition tiny_gltf.h:1111
ExtensionMap extensions
Definition tiny_gltf.h:1117
bool operator==(const SpotLight &) const
Definition tiny_gltf.h:698
TextureInfo()
Definition tiny_gltf.h:710
Value extras
Definition tiny_gltf.h:703
std::string extras_json_string
Definition tiny_gltf.h:707
ExtensionMap extensions
Definition tiny_gltf.h:704
bool operator==(const TextureInfo &) const
int texCoord
Definition tiny_gltf.h:700
int index
Definition tiny_gltf.h:699
std::string extensions_json_string
Definition tiny_gltf.h:708
Definition tiny_gltf.h:680
int sampler
Definition tiny_gltf.h:683
std::string name
Definition tiny_gltf.h:681
Value extras
Definition tiny_gltf.h:685
Texture()
Definition tiny_gltf.h:692
int source
Definition tiny_gltf.h:684
std::string extensions_json_string
Definition tiny_gltf.h:690
ExtensionMap extensions
Definition tiny_gltf.h:686
std::string extras_json_string
Definition tiny_gltf.h:689
bool operator==(const Texture &) const
#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT
Definition tiny_gltf.h:111
#define TINYGLTF_TYPE_VEC4
Definition tiny_gltf.h:158
#define TINYGLTF_MODE_TRIANGLES
Definition tiny_gltf.h:102
#define TINYGLTF_COMPONENT_TYPE_FLOAT
Definition tiny_gltf.h:112
#define TINYGLTF_VALUE_GET(ctype, var)
Definition tiny_gltf.h:409
#define TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER
Definition tiny_gltf.h:181
#define TINYGLTF_COMPONENT_TYPE_INT
Definition tiny_gltf.h:110
#define TINYGLTF_TEXTURE_WRAP_REPEAT
Definition tiny_gltf.h:122
#define TINYGLTF_COMPONENT_TYPE_BYTE
Definition tiny_gltf.h:106
#define TINYGLTF_DOUBLE_EQUAL(a, b)
Definition tiny_gltf.h:187
#define TINYGLTF_COMPONENT_TYPE_DOUBLE
Definition tiny_gltf.h:113
#define TINYGLTF_TYPE_SCALAR
Definition tiny_gltf.h:162
#define TINYGLTF_TYPE_VEC3
Definition tiny_gltf.h:157
#define TINYGLTF_TYPE_MAT2
Definition tiny_gltf.h:159
#define TINYGLTF_TYPE_VEC2
Definition tiny_gltf.h:156
#define DEFAULT_METHODS(x)
Definition tiny_gltf.h:89
#define TINYGLTF_COMPONENT_TYPE_SHORT
Definition tiny_gltf.h:108
#define TINYGLTF_TARGET_ARRAY_BUFFER
Definition tiny_gltf.h:180
#define TINYGLTF_TYPE_MAT3
Definition tiny_gltf.h:160
#define TINYGLTF_TYPE_MAT4
Definition tiny_gltf.h:161
#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE
Definition tiny_gltf.h:107
#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT
Definition tiny_gltf.h:109
W empty()
Definition ui.cc:634