tiny_gltf 1.0.2 → 2.5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +9 -7
- data/ext/tiny_gltf/json.hpp +17300 -10953
- data/ext/tiny_gltf/rb_tiny_gltf_mesh.cpp +1 -1
- data/ext/tiny_gltf/rb_tiny_gltf_sampler.cpp +3 -1
- data/ext/tiny_gltf/tiny_gltf.h +229 -120
- data/lib/tiny_gltf/version.rb +1 -1
- metadata +3 -3
data/ext/tiny_gltf/tiny_gltf.h
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
//
|
5
5
|
// The MIT License (MIT)
|
6
6
|
//
|
7
|
-
// Copyright (c) 2015 -
|
7
|
+
// Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many
|
8
8
|
// contributors.
|
9
9
|
//
|
10
10
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -26,6 +26,9 @@
|
|
26
26
|
// THE SOFTWARE.
|
27
27
|
|
28
28
|
// Version:
|
29
|
+
// - v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
|
30
|
+
// - v2.4.3 Fix null object output when when material has all default
|
31
|
+
// parameters.
|
29
32
|
// - v2.4.2 Decode percent-encoded URI.
|
30
33
|
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
|
31
34
|
// `extras` property.
|
@@ -105,7 +108,7 @@ namespace tinygltf {
|
|
105
108
|
#define TINYGLTF_COMPONENT_TYPE_INT (5124)
|
106
109
|
#define TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT (5125)
|
107
110
|
#define TINYGLTF_COMPONENT_TYPE_FLOAT (5126)
|
108
|
-
#define TINYGLTF_COMPONENT_TYPE_DOUBLE (5130)
|
111
|
+
#define TINYGLTF_COMPONENT_TYPE_DOUBLE (5130) // OpenGL double type. Note that some of glTF 2.0 validator does not support double type even the schema seems allow any value of integer: https://github.com/KhronosGroup/glTF/blob/b9884a2fd45130b4d673dd6c8a706ee21ee5c5f7/specification/2.0/schema/accessor.schema.json#L22
|
109
112
|
|
110
113
|
#define TINYGLTF_TEXTURE_FILTER_NEAREST (9728)
|
111
114
|
#define TINYGLTF_TEXTURE_FILTER_LINEAR (9729)
|
@@ -188,14 +191,14 @@ AAssetManager *asset_manager = nullptr;
|
|
188
191
|
#endif
|
189
192
|
|
190
193
|
typedef enum {
|
191
|
-
NULL_TYPE
|
192
|
-
REAL_TYPE
|
193
|
-
INT_TYPE
|
194
|
-
BOOL_TYPE
|
195
|
-
STRING_TYPE
|
196
|
-
ARRAY_TYPE
|
197
|
-
BINARY_TYPE
|
198
|
-
OBJECT_TYPE
|
194
|
+
NULL_TYPE,
|
195
|
+
REAL_TYPE,
|
196
|
+
INT_TYPE,
|
197
|
+
BOOL_TYPE,
|
198
|
+
STRING_TYPE,
|
199
|
+
ARRAY_TYPE,
|
200
|
+
BINARY_TYPE,
|
201
|
+
OBJECT_TYPE
|
199
202
|
} Type;
|
200
203
|
|
201
204
|
static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
|
@@ -250,7 +253,6 @@ bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
|
|
250
253
|
#ifdef __clang__
|
251
254
|
#pragma clang diagnostic push
|
252
255
|
// Suppress warning for : static Value null_value
|
253
|
-
// https://stackoverflow.com/questions/15708411/how-to-deal-with-global-constructor-warning-in-clang
|
254
256
|
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
255
257
|
#pragma clang diagnostic ignored "-Wpadded"
|
256
258
|
#endif
|
@@ -295,7 +297,7 @@ class Value {
|
|
295
297
|
|
296
298
|
DEFAULT_METHODS(Value)
|
297
299
|
|
298
|
-
char Type() const { return static_cast<
|
300
|
+
char Type() const { return static_cast<char>(type_); }
|
299
301
|
|
300
302
|
bool IsBool() const { return (type_ == BOOL_TYPE); }
|
301
303
|
|
@@ -601,7 +603,7 @@ struct Sampler {
|
|
601
603
|
// `magFilter`. Set -1 in TinyGLTF(issue #186)
|
602
604
|
int minFilter =
|
603
605
|
-1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR",
|
604
|
-
// "
|
606
|
+
// "NEAREST_MIPMAP_NEAREST", "LINEAR_MIPMAP_NEAREST",
|
605
607
|
// "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_LINEAR"]
|
606
608
|
int magFilter =
|
607
609
|
-1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR"]
|
@@ -611,7 +613,7 @@ struct Sampler {
|
|
611
613
|
int wrapT =
|
612
614
|
TINYGLTF_TEXTURE_WRAP_REPEAT; // ["CLAMP_TO_EDGE", "MIRRORED_REPEAT",
|
613
615
|
// "REPEAT"], default "REPEAT"
|
614
|
-
int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension
|
616
|
+
//int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension. currently not used.
|
615
617
|
|
616
618
|
Value extras;
|
617
619
|
ExtensionMap extensions;
|
@@ -624,8 +626,7 @@ struct Sampler {
|
|
624
626
|
: minFilter(-1),
|
625
627
|
magFilter(-1),
|
626
628
|
wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
|
627
|
-
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT)
|
628
|
-
wrapR(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
|
629
|
+
wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
|
629
630
|
DEFAULT_METHODS(Sampler)
|
630
631
|
bool operator==(const Sampler &) const;
|
631
632
|
};
|
@@ -848,8 +849,10 @@ struct Accessor {
|
|
848
849
|
std::string extras_json_string;
|
849
850
|
std::string extensions_json_string;
|
850
851
|
|
851
|
-
std::vector<double>
|
852
|
-
|
852
|
+
std::vector<double>
|
853
|
+
minValues; // optional. integer value is promoted to double
|
854
|
+
std::vector<double>
|
855
|
+
maxValues; // optional. integer value is promoted to double
|
853
856
|
|
854
857
|
struct {
|
855
858
|
int count;
|
@@ -1067,7 +1070,7 @@ struct Buffer {
|
|
1067
1070
|
};
|
1068
1071
|
|
1069
1072
|
struct Asset {
|
1070
|
-
std::string version; // required
|
1073
|
+
std::string version = "2.0"; // required
|
1071
1074
|
std::string generator;
|
1072
1075
|
std::string minVersion;
|
1073
1076
|
std::string copyright;
|
@@ -1189,7 +1192,8 @@ enum SectionCheck {
|
|
1189
1192
|
///
|
1190
1193
|
typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
|
1191
1194
|
std::string *, int, int,
|
1192
|
-
const unsigned char *, int,
|
1195
|
+
const unsigned char *, int,
|
1196
|
+
void *user_pointer);
|
1193
1197
|
|
1194
1198
|
///
|
1195
1199
|
/// WriteImageDataFunction type. Signature for custom image writing callbacks.
|
@@ -1254,7 +1258,7 @@ bool FileExists(const std::string &abs_filename, void *);
|
|
1254
1258
|
|
1255
1259
|
///
|
1256
1260
|
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to
|
1257
|
-
/// `C
|
1261
|
+
/// `C:\\Users\\tinygltf\\AppData`)
|
1258
1262
|
///
|
1259
1263
|
/// @param[in] filepath File path string. Assume UTF-8
|
1260
1264
|
/// @param[in] userdata User data. Set to `nullptr` if you don't need it.
|
@@ -1345,6 +1349,11 @@ class TinyGLTF {
|
|
1345
1349
|
///
|
1346
1350
|
void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data);
|
1347
1351
|
|
1352
|
+
///
|
1353
|
+
/// Unset(remove) callback of loading image data
|
1354
|
+
///
|
1355
|
+
void RemoveImageLoader();
|
1356
|
+
|
1348
1357
|
///
|
1349
1358
|
/// Set callback to use for writing image data
|
1350
1359
|
///
|
@@ -1383,6 +1392,16 @@ class TinyGLTF {
|
|
1383
1392
|
return store_original_json_for_extras_and_extensions_;
|
1384
1393
|
}
|
1385
1394
|
|
1395
|
+
///
|
1396
|
+
/// Specify whether preserve image channales when loading images or not.
|
1397
|
+
/// (Not effective when the user suppy their own LoadImageData callbacks)
|
1398
|
+
///
|
1399
|
+
void SetPreserveImageChannels(bool onoff) {
|
1400
|
+
preserve_image_channels_ = onoff;
|
1401
|
+
}
|
1402
|
+
|
1403
|
+
bool GetPreserveImageChannels() const { return preserve_image_channels_; }
|
1404
|
+
|
1386
1405
|
private:
|
1387
1406
|
///
|
1388
1407
|
/// Loads glTF asset from string(memory).
|
@@ -1402,6 +1421,9 @@ class TinyGLTF {
|
|
1402
1421
|
|
1403
1422
|
bool store_original_json_for_extras_and_extensions_ = false;
|
1404
1423
|
|
1424
|
+
bool preserve_image_channels_ = false; /// Default false(expand channels to
|
1425
|
+
/// RGBA) for backward compatibility.
|
1426
|
+
|
1405
1427
|
FsCallbacks fs = {
|
1406
1428
|
#ifndef TINYGLTF_NO_FS
|
1407
1429
|
&tinygltf::FileExists, &tinygltf::ExpandFilePath,
|
@@ -1421,7 +1443,8 @@ class TinyGLTF {
|
|
1421
1443
|
#else
|
1422
1444
|
nullptr;
|
1423
1445
|
#endif
|
1424
|
-
void *load_image_user_data_
|
1446
|
+
void *load_image_user_data_{nullptr};
|
1447
|
+
bool user_image_loader_{false};
|
1425
1448
|
|
1426
1449
|
WriteImageDataFunction WriteImageData =
|
1427
1450
|
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
@@ -1429,7 +1452,7 @@ class TinyGLTF {
|
|
1429
1452
|
#else
|
1430
1453
|
nullptr;
|
1431
1454
|
#endif
|
1432
|
-
void *write_image_user_data_
|
1455
|
+
void *write_image_user_data_{nullptr};
|
1433
1456
|
};
|
1434
1457
|
|
1435
1458
|
#ifdef __clang__
|
@@ -1514,6 +1537,7 @@ class TinyGLTF {
|
|
1514
1537
|
#ifndef TINYGLTF_USE_RAPIDJSON
|
1515
1538
|
#include "json.hpp"
|
1516
1539
|
#else
|
1540
|
+
#ifndef TINYGLTF_NO_INCLUDE_RAPIDJSON
|
1517
1541
|
#include "document.h"
|
1518
1542
|
#include "prettywriter.h"
|
1519
1543
|
#include "rapidjson.h"
|
@@ -1521,6 +1545,7 @@ class TinyGLTF {
|
|
1521
1545
|
#include "writer.h"
|
1522
1546
|
#endif
|
1523
1547
|
#endif
|
1548
|
+
#endif
|
1524
1549
|
|
1525
1550
|
#ifdef TINYGLTF_ENABLE_DRACO
|
1526
1551
|
#include "draco/compression/decode.h"
|
@@ -1579,7 +1604,7 @@ class TinyGLTF {
|
|
1579
1604
|
|
1580
1605
|
#endif
|
1581
1606
|
|
1582
|
-
#elif !defined(__ANDROID__)
|
1607
|
+
#elif !defined(__ANDROID__) && !defined(__OpenBSD__)
|
1583
1608
|
#include <wordexp.h>
|
1584
1609
|
#endif
|
1585
1610
|
|
@@ -1683,6 +1708,19 @@ void JsonParse(JsonDocument &doc, const char *str, size_t length,
|
|
1683
1708
|
|
1684
1709
|
namespace tinygltf {
|
1685
1710
|
|
1711
|
+
///
|
1712
|
+
/// Internal LoadImageDataOption struct.
|
1713
|
+
/// This struct is passed through `user_pointer` in LoadImageData.
|
1714
|
+
/// The struct is not passed when the user supply their own LoadImageData
|
1715
|
+
/// callbacks.
|
1716
|
+
///
|
1717
|
+
struct LoadImageDataOption {
|
1718
|
+
// true: preserve image channels(e.g. load as RGB image if the image has RGB
|
1719
|
+
// channels) default `false`(channels are expanded to RGBA for backward
|
1720
|
+
// compatiblity).
|
1721
|
+
bool preserve_channels{false};
|
1722
|
+
};
|
1723
|
+
|
1686
1724
|
// Equals function for Value, for recursivity
|
1687
1725
|
static bool Equals(const tinygltf::Value &one, const tinygltf::Value &other) {
|
1688
1726
|
if (one.Type() != other.Type()) return false;
|
@@ -1895,8 +1933,10 @@ bool Sampler::operator==(const Sampler &other) const {
|
|
1895
1933
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
1896
1934
|
this->magFilter == other.magFilter &&
|
1897
1935
|
this->minFilter == other.minFilter && this->name == other.name &&
|
1898
|
-
this->
|
1936
|
+
this->wrapS == other.wrapS &&
|
1899
1937
|
this->wrapT == other.wrapT;
|
1938
|
+
|
1939
|
+
//this->wrapR == other.wrapR
|
1900
1940
|
}
|
1901
1941
|
bool Scene::operator==(const Scene &other) const {
|
1902
1942
|
return this->extensions == other.extensions && this->extras == other.extras &&
|
@@ -2000,9 +2040,11 @@ static std::string GetBaseDir(const std::string &filepath) {
|
|
2000
2040
|
return "";
|
2001
2041
|
}
|
2002
2042
|
|
2003
|
-
// https://stackoverflow.com/questions/8520560/get-a-file-name-from-a-path
|
2004
2043
|
static std::string GetBaseFilename(const std::string &filepath) {
|
2005
|
-
|
2044
|
+
auto idx = filepath.find_last_of("/\\");
|
2045
|
+
if (idx != std::string::npos)
|
2046
|
+
return filepath.substr(idx + 1);
|
2047
|
+
return filepath;
|
2006
2048
|
}
|
2007
2049
|
|
2008
2050
|
std::string base64_encode(unsigned char const *, unsigned int len);
|
@@ -2148,47 +2190,35 @@ std::string base64_decode(std::string const &encoded_string) {
|
|
2148
2190
|
// TODO(syoyo): Use uriparser https://uriparser.github.io/ for stricter Uri
|
2149
2191
|
// decoding?
|
2150
2192
|
//
|
2151
|
-
//
|
2193
|
+
// Uri Decoding from DLIB
|
2152
2194
|
// http://dlib.net/dlib/server/server_http.cpp.html
|
2153
|
-
|
2154
|
-
// --- dlib beign ------------------------------------------------------------
|
2195
|
+
// --- dlib begin ------------------------------------------------------------
|
2155
2196
|
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
2156
|
-
// License: Boost Software License
|
2157
|
-
|
2197
|
+
// License: Boost Software License
|
2198
|
+
// Boost Software License - Version 1.0 - August 17th, 2003
|
2199
|
+
|
2200
|
+
// Permission is hereby granted, free of charge, to any person or organization
|
2201
|
+
// obtaining a copy of the software and accompanying documentation covered by
|
2202
|
+
// this license (the "Software") to use, reproduce, display, distribute,
|
2203
|
+
// execute, and transmit the Software, and to prepare derivative works of the
|
2204
|
+
// Software, and to permit third-parties to whom the Software is furnished to
|
2205
|
+
// do so, all subject to the following:
|
2206
|
+
// The copyright notices in the Software and this entire statement, including
|
2207
|
+
// the above license grant, this restriction and the following disclaimer,
|
2208
|
+
// must be included in all copies of the Software, in whole or in part, and
|
2209
|
+
// all derivative works of the Software, unless such copies or derivative
|
2210
|
+
// works are solely in the form of machine-executable object code generated by
|
2211
|
+
// a source language processor.
|
2212
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2213
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
2214
|
+
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
2215
|
+
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
2216
|
+
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
2217
|
+
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
2218
|
+
// DEALINGS IN THE SOFTWARE.
|
2219
|
+
//
|
2158
2220
|
namespace dlib {
|
2159
2221
|
|
2160
|
-
#if 0
|
2161
|
-
inline unsigned char to_hex( unsigned char x )
|
2162
|
-
{
|
2163
|
-
return x + (x > 9 ? ('A'-10) : '0');
|
2164
|
-
}
|
2165
|
-
|
2166
|
-
const std::string urlencode( const std::string& s )
|
2167
|
-
{
|
2168
|
-
std::ostringstream os;
|
2169
|
-
|
2170
|
-
for ( std::string::const_iterator ci = s.begin(); ci != s.end(); ++ci )
|
2171
|
-
{
|
2172
|
-
if ( (*ci >= 'a' && *ci <= 'z') ||
|
2173
|
-
(*ci >= 'A' && *ci <= 'Z') ||
|
2174
|
-
(*ci >= '0' && *ci <= '9') )
|
2175
|
-
{ // allowed
|
2176
|
-
os << *ci;
|
2177
|
-
}
|
2178
|
-
else if ( *ci == ' ')
|
2179
|
-
{
|
2180
|
-
os << '+';
|
2181
|
-
}
|
2182
|
-
else
|
2183
|
-
{
|
2184
|
-
os << '%' << to_hex(static_cast<unsigned char>(*ci >> 4)) << to_hex(static_cast<unsigned char>(*ci % 16));
|
2185
|
-
}
|
2186
|
-
}
|
2187
|
-
|
2188
|
-
return os.str();
|
2189
|
-
}
|
2190
|
-
#endif
|
2191
|
-
|
2192
2222
|
inline unsigned char from_hex(unsigned char ch) {
|
2193
2223
|
if (ch <= '9' && ch >= '0')
|
2194
2224
|
ch -= '0';
|
@@ -2297,22 +2327,40 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
|
2297
2327
|
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
2298
2328
|
LoadImageData = func;
|
2299
2329
|
load_image_user_data_ = user_data;
|
2330
|
+
user_image_loader_ = true;
|
2331
|
+
}
|
2332
|
+
|
2333
|
+
void TinyGLTF::RemoveImageLoader() {
|
2334
|
+
LoadImageData =
|
2335
|
+
#ifndef TINYGLTF_NO_STB_IMAGE
|
2336
|
+
&tinygltf::LoadImageData;
|
2337
|
+
#else
|
2338
|
+
nullptr;
|
2339
|
+
#endif
|
2340
|
+
|
2341
|
+
load_image_user_data_ = nullptr;
|
2342
|
+
user_image_loader_ = false;
|
2300
2343
|
}
|
2301
2344
|
|
2302
2345
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
2303
2346
|
bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
2304
2347
|
std::string *warn, int req_width, int req_height,
|
2305
2348
|
const unsigned char *bytes, int size, void *user_data) {
|
2306
|
-
(void)user_data;
|
2307
2349
|
(void)warn;
|
2308
2350
|
|
2351
|
+
LoadImageDataOption option;
|
2352
|
+
if (user_data) {
|
2353
|
+
option = *reinterpret_cast<LoadImageDataOption *>(user_data);
|
2354
|
+
}
|
2355
|
+
|
2309
2356
|
int w = 0, h = 0, comp = 0, req_comp = 0;
|
2310
2357
|
|
2311
2358
|
unsigned char *data = nullptr;
|
2312
2359
|
|
2313
|
-
//
|
2314
|
-
//
|
2315
|
-
|
2360
|
+
// preserve_channels true: Use channels stored in the image file.
|
2361
|
+
// false: force 32-bit textures for common Vulkan compatibility. It appears
|
2362
|
+
// that some GPU drivers do not support 24-bit images for Vulkan
|
2363
|
+
req_comp = option.preserve_channels ? 0 : 4;
|
2316
2364
|
int bits = 8;
|
2317
2365
|
int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
2318
2366
|
|
@@ -2384,13 +2432,18 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
|
2384
2432
|
}
|
2385
2433
|
}
|
2386
2434
|
|
2435
|
+
if (req_comp != 0) {
|
2436
|
+
// loaded data has `req_comp` channels(components)
|
2437
|
+
comp = req_comp;
|
2438
|
+
}
|
2439
|
+
|
2387
2440
|
image->width = w;
|
2388
2441
|
image->height = h;
|
2389
|
-
image->component =
|
2442
|
+
image->component = comp;
|
2390
2443
|
image->bits = bits;
|
2391
2444
|
image->pixel_type = pixel_type;
|
2392
|
-
image->image.resize(static_cast<size_t>(w * h *
|
2393
|
-
std::copy(data, data + w * h *
|
2445
|
+
image->image.resize(static_cast<size_t>(w * h * comp) * size_t(bits / 8));
|
2446
|
+
std::copy(data, data + w * h * comp * (bits / 8), image->image.begin());
|
2394
2447
|
stbi_image_free(data);
|
2395
2448
|
|
2396
2449
|
return true;
|
@@ -2566,7 +2619,7 @@ std::string ExpandFilePath(const std::string &filepath, void *) {
|
|
2566
2619
|
#else
|
2567
2620
|
|
2568
2621
|
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \
|
2569
|
-
defined(__ANDROID__) || defined(__EMSCRIPTEN__)
|
2622
|
+
defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__OpenBSD__)
|
2570
2623
|
// no expansion
|
2571
2624
|
std::string s = filepath;
|
2572
2625
|
#else
|
@@ -3139,6 +3192,7 @@ static bool ParseJsonAsValue(Value *ret, const json &o) {
|
|
3139
3192
|
break;
|
3140
3193
|
case json::value_t::null:
|
3141
3194
|
case json::value_t::discarded:
|
3195
|
+
case json::value_t::binary:
|
3142
3196
|
// default:
|
3143
3197
|
break;
|
3144
3198
|
}
|
@@ -4162,7 +4216,9 @@ static bool ParseSparseAccessor(Accessor *accessor, std::string *err,
|
|
4162
4216
|
accessor->sparse.isSparse = true;
|
4163
4217
|
|
4164
4218
|
int count = 0;
|
4165
|
-
ParseIntegerProperty(&count, err, o, "count", true)
|
4219
|
+
if (!ParseIntegerProperty(&count, err, o, "count", true, "SparseAccessor")) {
|
4220
|
+
return false;
|
4221
|
+
}
|
4166
4222
|
|
4167
4223
|
json_const_iterator indices_iterator;
|
4168
4224
|
json_const_iterator values_iterator;
|
@@ -4180,18 +4236,24 @@ static bool ParseSparseAccessor(Accessor *accessor, std::string *err,
|
|
4180
4236
|
const json &values_obj = GetValue(values_iterator);
|
4181
4237
|
|
4182
4238
|
int indices_buffer_view = 0, indices_byte_offset = 0, component_type = 0;
|
4183
|
-
ParseIntegerProperty(&indices_buffer_view, err, indices_obj, "bufferView",
|
4184
|
-
true)
|
4239
|
+
if (!ParseIntegerProperty(&indices_buffer_view, err, indices_obj, "bufferView",
|
4240
|
+
true, "SparseAccessor")) {
|
4241
|
+
return false;
|
4242
|
+
}
|
4185
4243
|
ParseIntegerProperty(&indices_byte_offset, err, indices_obj, "byteOffset",
|
4186
|
-
|
4187
|
-
ParseIntegerProperty(&component_type, err, indices_obj, "componentType",
|
4188
|
-
true)
|
4244
|
+
false);
|
4245
|
+
if (!ParseIntegerProperty(&component_type, err, indices_obj, "componentType",
|
4246
|
+
true, "SparseAccessor")) {
|
4247
|
+
return false;
|
4248
|
+
}
|
4189
4249
|
|
4190
4250
|
int values_buffer_view = 0, values_byte_offset = 0;
|
4191
|
-
ParseIntegerProperty(&values_buffer_view, err, values_obj, "bufferView",
|
4192
|
-
true)
|
4251
|
+
if (!ParseIntegerProperty(&values_buffer_view, err, values_obj, "bufferView",
|
4252
|
+
true, "SparseAccessor")) {
|
4253
|
+
return false;
|
4254
|
+
}
|
4193
4255
|
ParseIntegerProperty(&values_byte_offset, err, values_obj, "byteOffset",
|
4194
|
-
|
4256
|
+
false);
|
4195
4257
|
|
4196
4258
|
accessor->sparse.count = count;
|
4197
4259
|
accessor->sparse.indices.bufferView = indices_buffer_view;
|
@@ -4200,8 +4262,6 @@ static bool ParseSparseAccessor(Accessor *accessor, std::string *err,
|
|
4200
4262
|
accessor->sparse.values.bufferView = values_buffer_view;
|
4201
4263
|
accessor->sparse.values.byteOffset = values_byte_offset;
|
4202
4264
|
|
4203
|
-
// todo check theses values
|
4204
|
-
|
4205
4265
|
return true;
|
4206
4266
|
}
|
4207
4267
|
|
@@ -4409,6 +4469,7 @@ static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
|
|
4409
4469
|
static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
4410
4470
|
std::string *err,
|
4411
4471
|
const Value &dracoExtensionValue) {
|
4472
|
+
(void)err;
|
4412
4473
|
auto bufferViewValue = dracoExtensionValue.Get("bufferView");
|
4413
4474
|
if (!bufferViewValue.IsInt()) return false;
|
4414
4475
|
auto attributesValue = dracoExtensionValue.Get("attributes");
|
@@ -4469,7 +4530,6 @@ static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
|
4469
4530
|
|
4470
4531
|
int dracoAttributeIndex = attribute.second.Get<int>();
|
4471
4532
|
const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
|
4472
|
-
const auto pBuffer = pAttribute->buffer();
|
4473
4533
|
const auto componentType =
|
4474
4534
|
model->accessors[primitiveAttribute->second].componentType;
|
4475
4535
|
|
@@ -5028,12 +5088,12 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
|
|
5028
5088
|
int magFilter = -1;
|
5029
5089
|
int wrapS = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
5030
5090
|
int wrapT = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
5031
|
-
int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
5091
|
+
//int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
|
5032
5092
|
ParseIntegerProperty(&minFilter, err, o, "minFilter", false);
|
5033
5093
|
ParseIntegerProperty(&magFilter, err, o, "magFilter", false);
|
5034
5094
|
ParseIntegerProperty(&wrapS, err, o, "wrapS", false);
|
5035
5095
|
ParseIntegerProperty(&wrapT, err, o, "wrapT", false);
|
5036
|
-
ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf extension
|
5096
|
+
//ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf extension
|
5037
5097
|
|
5038
5098
|
// TODO(syoyo): Check the value is alloed one.
|
5039
5099
|
// (e.g. we allow 9728(NEAREST), but don't allow 9727)
|
@@ -5042,7 +5102,7 @@ static bool ParseSampler(Sampler *sampler, std::string *err, const json &o,
|
|
5042
5102
|
sampler->magFilter = magFilter;
|
5043
5103
|
sampler->wrapS = wrapS;
|
5044
5104
|
sampler->wrapT = wrapT;
|
5045
|
-
sampler->wrapR = wrapR;
|
5105
|
+
//sampler->wrapR = wrapR;
|
5046
5106
|
|
5047
5107
|
ParseExtensionsProperty(&(sampler->extensions), err, o);
|
5048
5108
|
ParseExtrasProperty(&(sampler->extras), o);
|
@@ -5769,13 +5829,13 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|
5769
5829
|
{
|
5770
5830
|
json_const_iterator it;
|
5771
5831
|
if (FindMember(o, "extensions", it)) {
|
5772
|
-
|
5832
|
+
scene.extensions_json_string = JsonToString(GetValue(it));
|
5773
5833
|
}
|
5774
5834
|
}
|
5775
5835
|
{
|
5776
5836
|
json_const_iterator it;
|
5777
5837
|
if (FindMember(o, "extras", it)) {
|
5778
|
-
|
5838
|
+
scene.extras_json_string = JsonToString(GetValue(it));
|
5779
5839
|
}
|
5780
5840
|
}
|
5781
5841
|
}
|
@@ -5825,6 +5885,18 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|
5825
5885
|
}
|
5826
5886
|
|
5827
5887
|
// 11. Parse Image
|
5888
|
+
void *load_image_user_data{nullptr};
|
5889
|
+
|
5890
|
+
LoadImageDataOption load_image_option;
|
5891
|
+
|
5892
|
+
if (user_image_loader_) {
|
5893
|
+
// Use user supplied pointer
|
5894
|
+
load_image_user_data = load_image_user_data_;
|
5895
|
+
} else {
|
5896
|
+
load_image_option.preserve_channels = preserve_image_channels_;
|
5897
|
+
load_image_user_data = reinterpret_cast<void *>(&load_image_option);
|
5898
|
+
}
|
5899
|
+
|
5828
5900
|
{
|
5829
5901
|
int idx = 0;
|
5830
5902
|
bool success = ForEachInArray(v, "images", [&](const json &o) {
|
@@ -5837,7 +5909,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|
5837
5909
|
Image image;
|
5838
5910
|
if (!ParseImage(&image, idx, err, warn, o,
|
5839
5911
|
store_original_json_for_extras_and_extensions_, base_dir,
|
5840
|
-
&fs, &this->LoadImageData,
|
5912
|
+
&fs, &this->LoadImageData, load_image_user_data)) {
|
5841
5913
|
return false;
|
5842
5914
|
}
|
5843
5915
|
|
@@ -5875,7 +5947,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|
5875
5947
|
bool ret = LoadImageData(
|
5876
5948
|
&image, idx, err, warn, image.width, image.height,
|
5877
5949
|
&buffer.data[bufferView.byteOffset],
|
5878
|
-
static_cast<int>(bufferView.byteLength),
|
5950
|
+
static_cast<int>(bufferView.byteLength), load_image_user_data);
|
5879
5951
|
if (!ret) {
|
5880
5952
|
return false;
|
5881
5953
|
}
|
@@ -6551,8 +6623,33 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) {
|
|
6551
6623
|
|
6552
6624
|
SerializeNumberProperty<int>("componentType", accessor.componentType, o);
|
6553
6625
|
SerializeNumberProperty<size_t>("count", accessor.count, o);
|
6554
|
-
|
6555
|
-
|
6626
|
+
|
6627
|
+
if ((accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) ||
|
6628
|
+
(accessor.componentType == TINYGLTF_COMPONENT_TYPE_DOUBLE)) {
|
6629
|
+
SerializeNumberArrayProperty<double>("min", accessor.minValues, o);
|
6630
|
+
SerializeNumberArrayProperty<double>("max", accessor.maxValues, o);
|
6631
|
+
} else {
|
6632
|
+
// Issue #301. Serialize as integer.
|
6633
|
+
// Assume int value is within [-2**31-1, 2**31-1]
|
6634
|
+
{
|
6635
|
+
std::vector<int> values;
|
6636
|
+
std::transform(accessor.minValues.begin(), accessor.minValues.end(),
|
6637
|
+
std::back_inserter(values),
|
6638
|
+
[](double v) { return static_cast<int>(v); });
|
6639
|
+
|
6640
|
+
SerializeNumberArrayProperty<int>("min", values, o);
|
6641
|
+
}
|
6642
|
+
|
6643
|
+
{
|
6644
|
+
std::vector<int> values;
|
6645
|
+
std::transform(accessor.maxValues.begin(), accessor.maxValues.end(),
|
6646
|
+
std::back_inserter(values),
|
6647
|
+
[](double v) { return static_cast<int>(v); });
|
6648
|
+
|
6649
|
+
SerializeNumberArrayProperty<int>("max", values, o);
|
6650
|
+
}
|
6651
|
+
}
|
6652
|
+
|
6556
6653
|
if (accessor.normalized)
|
6557
6654
|
SerializeValue("normalized", Value(accessor.normalized), o);
|
6558
6655
|
std::string type;
|
@@ -6662,10 +6759,15 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
|
|
6662
6759
|
SerializeStringProperty("copyright", asset.copyright, o);
|
6663
6760
|
}
|
6664
6761
|
|
6665
|
-
if (
|
6666
|
-
|
6762
|
+
if (asset.version.empty()) {
|
6763
|
+
// Just in case
|
6764
|
+
// `version` must be defined
|
6765
|
+
asset.version = "2.0";
|
6667
6766
|
}
|
6668
6767
|
|
6768
|
+
// TODO(syoyo): Do we need to check if `version` is greater or equal to 2.0?
|
6769
|
+
SerializeStringProperty("version", asset.version, o);
|
6770
|
+
|
6669
6771
|
if (asset.extras.Keys().size()) {
|
6670
6772
|
SerializeValue("extras", asset.extras, o);
|
6671
6773
|
}
|
@@ -7063,7 +7165,7 @@ static void SerializeGltfSampler(Sampler &sampler, json &o) {
|
|
7063
7165
|
if (sampler.minFilter != -1) {
|
7064
7166
|
SerializeNumberProperty("minFilter", sampler.minFilter, o);
|
7065
7167
|
}
|
7066
|
-
SerializeNumberProperty("wrapR", sampler.wrapR, o);
|
7168
|
+
//SerializeNumberProperty("wrapR", sampler.wrapR, o);
|
7067
7169
|
SerializeNumberProperty("wrapS", sampler.wrapS, o);
|
7068
7170
|
SerializeNumberProperty("wrapT", sampler.wrapT, o);
|
7069
7171
|
|
@@ -7138,11 +7240,17 @@ static void SerializeGltfScene(Scene &scene, json &o) {
|
|
7138
7240
|
}
|
7139
7241
|
|
7140
7242
|
static void SerializeGltfSkin(Skin &skin, json &o) {
|
7141
|
-
|
7243
|
+
// required
|
7244
|
+
SerializeNumberArrayProperty<int>("joints", skin.joints, o);
|
7245
|
+
|
7246
|
+
if (skin.inverseBindMatrices >= 0) {
|
7142
7247
|
SerializeNumberProperty("inverseBindMatrices", skin.inverseBindMatrices, o);
|
7248
|
+
}
|
7249
|
+
|
7250
|
+
if (skin.skeleton >= 0) {
|
7251
|
+
SerializeNumberProperty("skeleton", skin.skeleton, o);
|
7252
|
+
}
|
7143
7253
|
|
7144
|
-
SerializeNumberArrayProperty<int>("joints", skin.joints, o);
|
7145
|
-
SerializeNumberProperty("skeleton", skin.skeleton, o);
|
7146
7254
|
if (skin.name.size()) {
|
7147
7255
|
SerializeStringProperty("name", skin.name, o);
|
7148
7256
|
}
|
@@ -7225,6 +7333,16 @@ static void SerializeGltfModel(Model *model, json &o) {
|
|
7225
7333
|
for (unsigned int i = 0; i < model->materials.size(); ++i) {
|
7226
7334
|
json material;
|
7227
7335
|
SerializeGltfMaterial(model->materials[i], material);
|
7336
|
+
|
7337
|
+
if (JsonIsNull(material)) {
|
7338
|
+
// Issue 294.
|
7339
|
+
// `material` does not have any required parameters
|
7340
|
+
// so the result may be null(unmodified) when all material parameters
|
7341
|
+
// have default value.
|
7342
|
+
//
|
7343
|
+
// null is not allowed thus we create an empty JSON object.
|
7344
|
+
JsonSetObject(material);
|
7345
|
+
}
|
7228
7346
|
JsonPushBack(materials, std::move(material));
|
7229
7347
|
}
|
7230
7348
|
JsonAddMember(o, "materials", std::move(materials));
|
@@ -7363,7 +7481,7 @@ static void SerializeGltfModel(Model *model, json &o) {
|
|
7363
7481
|
}
|
7364
7482
|
|
7365
7483
|
// Extensions used
|
7366
|
-
if (
|
7484
|
+
if (extensionsUsed.size()) {
|
7367
7485
|
SerializeStringArrayProperty("extensionsUsed", extensionsUsed, o);
|
7368
7486
|
}
|
7369
7487
|
|
@@ -7407,31 +7525,24 @@ static void WriteBinaryGltfStream(std::ostream &stream,
|
|
7407
7525
|
const std::string header = "glTF";
|
7408
7526
|
const int version = 2;
|
7409
7527
|
|
7410
|
-
|
7411
|
-
|
7412
|
-
|
7413
|
-
|
7414
|
-
|
7415
|
-
if (remainder == 0) return numToRound;
|
7416
|
-
|
7417
|
-
return numToRound + multiple - remainder;
|
7418
|
-
};
|
7419
|
-
|
7420
|
-
const uint32_t padding_size =
|
7421
|
-
roundUp(uint32_t(content.size()), 4) - uint32_t(content.size());
|
7528
|
+
const uint32_t content_size = uint32_t(content.size());
|
7529
|
+
const uint32_t binBuffer_size = uint32_t(binBuffer.size());
|
7530
|
+
// determine number of padding bytes required to ensure 4 byte alignment
|
7531
|
+
const uint32_t content_padding_size = content_size % 4 == 0 ? 0 : 4 - content_size % 4;
|
7532
|
+
const uint32_t bin_padding_size = binBuffer_size % 4 == 0 ? 0 : 4 - binBuffer_size % 4;
|
7422
7533
|
|
7423
7534
|
// 12 bytes for header, JSON content length, 8 bytes for JSON chunk info.
|
7424
|
-
// Chunk data must be located at 4-byte boundary
|
7535
|
+
// Chunk data must be located at 4-byte boundary, which may require padding
|
7425
7536
|
const uint32_t length =
|
7426
|
-
12 + 8 +
|
7427
|
-
(
|
7537
|
+
12 + 8 + content_size + content_padding_size +
|
7538
|
+
(binBuffer_size ? (8 + binBuffer_size + bin_padding_size) : 0);
|
7428
7539
|
|
7429
7540
|
stream.write(header.c_str(), std::streamsize(header.size()));
|
7430
7541
|
stream.write(reinterpret_cast<const char *>(&version), sizeof(version));
|
7431
7542
|
stream.write(reinterpret_cast<const char *>(&length), sizeof(length));
|
7432
7543
|
|
7433
7544
|
// JSON chunk info, then JSON data
|
7434
|
-
const uint32_t model_length = uint32_t(content.size()) +
|
7545
|
+
const uint32_t model_length = uint32_t(content.size()) + content_padding_size;
|
7435
7546
|
const uint32_t model_format = 0x4E4F534A;
|
7436
7547
|
stream.write(reinterpret_cast<const char *>(&model_length),
|
7437
7548
|
sizeof(model_length));
|
@@ -7440,13 +7551,11 @@ static void WriteBinaryGltfStream(std::ostream &stream,
|
|
7440
7551
|
stream.write(content.c_str(), std::streamsize(content.size()));
|
7441
7552
|
|
7442
7553
|
// Chunk must be multiplies of 4, so pad with spaces
|
7443
|
-
if (
|
7444
|
-
const std::string padding = std::string(size_t(
|
7554
|
+
if (content_padding_size > 0) {
|
7555
|
+
const std::string padding = std::string(size_t(content_padding_size), ' ');
|
7445
7556
|
stream.write(padding.c_str(), std::streamsize(padding.size()));
|
7446
7557
|
}
|
7447
7558
|
if (binBuffer.size() > 0) {
|
7448
|
-
const uint32_t bin_padding_size =
|
7449
|
-
roundUp(uint32_t(binBuffer.size()), 4) - uint32_t(binBuffer.size());
|
7450
7559
|
// BIN chunk info, then BIN data
|
7451
7560
|
const uint32_t bin_length = uint32_t(binBuffer.size()) + bin_padding_size;
|
7452
7561
|
const uint32_t bin_format = 0x004e4942;
|