mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-06-08 19:23:50 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a6df34d99 | ||
|
|
147a00a601 | ||
|
|
350c296802 | ||
|
|
cc93e1fd25 | ||
|
|
59cc44ad4f | ||
|
|
1a5046e06b | ||
|
|
877d856e71 | ||
|
|
b534b6b0d8 | ||
|
|
ecfd37dee2 | ||
|
|
5c06b7d03b | ||
|
|
a75355b018 | ||
|
|
a977f7a16f | ||
|
|
5a6c55870e | ||
|
|
49caa65177 |
54
.github/workflows/c-cpp.yml
vendored
54
.github/workflows/c-cpp.yml
vendored
@@ -4,41 +4,43 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
# compile with older gcc4.8
|
||||
build-gcc48:
|
||||
# gcc4.8 is too old and ubuntu-18.04 image is not supported in GitHub Actions anymore,
|
||||
# so disable this build.
|
||||
## compile with older gcc4.8
|
||||
#build-gcc48:
|
||||
|
||||
runs-on: ubuntu-18.04
|
||||
name: Build with gcc 4.8
|
||||
# runs-on: ubuntu-18.04
|
||||
# name: Build with gcc 4.8
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v1
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential
|
||||
sudo apt-get install -y gcc-4.8 g++-4.8
|
||||
g++-4.8 -std=c++11 -o loader_example loader_example.cc
|
||||
# - name: Build
|
||||
# run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y build-essential
|
||||
# sudo apt-get install -y gcc-4.8 g++-4.8
|
||||
# g++-4.8 -std=c++11 -o loader_example loader_example.cc
|
||||
|
||||
- name: NoexceptBuild
|
||||
run: |
|
||||
g++-4.8 -DTINYGLTF_NOEXCEPTION -std=c++11 -o loader_example loader_example.cc
|
||||
# - name: NoexceptBuild
|
||||
# run: |
|
||||
# g++-4.8 -DTINYGLTF_NOEXCEPTION -std=c++11 -o loader_example loader_example.cc
|
||||
|
||||
- name: RapidjsonBuild
|
||||
run: |
|
||||
git clone https://github.com/Tencent/rapidjson
|
||||
g++-4.8 -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -o loader_example loader_example.cc
|
||||
# - name: RapidjsonBuild
|
||||
# run: |
|
||||
# git clone https://github.com/Tencent/rapidjson
|
||||
# g++-4.8 -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -o loader_example loader_example.cc
|
||||
|
||||
# compile with mingw gcc cross
|
||||
build-mingw-cross:
|
||||
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
name: Build with MinGW gcc cross
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -133,20 +135,20 @@ jobs:
|
||||
# Cross-compile for aarch64 linux target
|
||||
build-cross-aarch64:
|
||||
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
name: Build on cross aarch64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential
|
||||
sudo apt-get install -y gcc-8-aarch64-linux-gnu g++-8-aarch64-linux-gnu
|
||||
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
|
||||
|
||||
git clone https://github.com/Tencent/rapidjson
|
||||
aarch64-linux-gnu-g++-8 -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc
|
||||
aarch64-linux-gnu-g++ -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc
|
||||
|
||||
# macOS clang
|
||||
build-macos:
|
||||
|
||||
@@ -197,6 +197,7 @@ if (!ret) {
|
||||
* `TINYGLTF_USE_RAPIDJSON` : Use RapidJSON as a JSON parser/serializer. RapidJSON files are not included in TinyGLTF repo. Please set an include path to RapidJSON if you enable this feature.
|
||||
* `TINYGLTF_USE_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11.
|
||||
|
||||
|
||||
## CMake options
|
||||
|
||||
You can add tinygltf using `add_subdirectory` feature.
|
||||
|
||||
1
tests/issue-416.gltf
Normal file
1
tests/issue-416.gltf
Normal file
@@ -0,0 +1 @@
|
||||
{"images":[{"uri":"%!QAAAQAAA5"}],"asset":{"version":""}}
|
||||
@@ -721,3 +721,39 @@ TEST_CASE("serialize-image-failure", "[issue-394]") {
|
||||
REQUIRE(false == result);
|
||||
REQUIRE(os.str().size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("filesize-check", "[issue-416]") {
|
||||
|
||||
tinygltf::Model model;
|
||||
tinygltf::TinyGLTF ctx;
|
||||
std::string err;
|
||||
std::string warn;
|
||||
|
||||
ctx.SetMaxExternalFileSize(10); // 10 bytes. will fail to load texture image.
|
||||
|
||||
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/Cube/Cube.gltf");
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
REQUIRE(false == ret);
|
||||
}
|
||||
|
||||
TEST_CASE("load-issue-416-model", "[issue-416]") {
|
||||
|
||||
tinygltf::Model model;
|
||||
tinygltf::TinyGLTF ctx;
|
||||
std::string err;
|
||||
std::string warn;
|
||||
|
||||
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "issue-416.gltf");
|
||||
if (!warn.empty()) {
|
||||
std::cout << "WARN:" << warn << std::endl;
|
||||
}
|
||||
if (!err.empty()) {
|
||||
std::cerr << "ERR:" << err << std::endl;
|
||||
}
|
||||
|
||||
// external file load fails, but reading glTF itself is ok.
|
||||
REQUIRE(true == ret);
|
||||
}
|
||||
|
||||
270
tiny_gltf.h
270
tiny_gltf.h
@@ -25,32 +25,8 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// Version:
|
||||
// - v2.8.1 Missed serialization texture sampler name fixed. PR#399.
|
||||
// - v2.8.0 Add URICallbacks for custom URI handling in Buffer and Image. PR#397.
|
||||
// - v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393.
|
||||
// - v2.6.3 Fix GLB file with empty BIN chunk was not handled. PR#382 and PR#383.
|
||||
// - v2.6.2 Fix out-of-bounds access of accessors. PR#379.
|
||||
// - v2.6.1 Better GLB validation check when loading.
|
||||
// - v2.6.0 Support serializing sparse accessor(Thanks to @fynv).
|
||||
// Disable expanding file path for security(no use of awkward `wordexp` anymore).
|
||||
// - v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
|
||||
// - v2.4.3 Fix null object output when material has all default
|
||||
// parameters.
|
||||
// - v2.4.2 Decode percent-encoded URI.
|
||||
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
|
||||
// `extras` property.
|
||||
// - v2.4.0 Experimental RapidJSON and C++14 support(Thanks to @jrkoone).
|
||||
// - v2.3.1 Set default value of minFilter and magFilter in Sampler to -1.
|
||||
// - v2.3.0 Modified Material representation according to glTF 2.0 schema
|
||||
// (and introduced TextureInfo class)
|
||||
// Change the behavior of `Value::IsNumber`. It return true either the
|
||||
// value is int or real.
|
||||
// - v2.2.0 Add loading 16bit PNG support. Add Sparse accessor support(Thanks
|
||||
// to @Ybalrid)
|
||||
// - v2.1.0 Add draco compression.
|
||||
// - v2.0.1 Add comparison feature(Thanks to @Selmar).
|
||||
// - v2.0.0 glTF 2.0!.
|
||||
// Version: - v2.8.10
|
||||
// See https://github.com/syoyo/tinygltf/releases for release history.
|
||||
//
|
||||
// Tiny glTF loader is using following third party libraries:
|
||||
//
|
||||
@@ -301,6 +277,9 @@ class Value {
|
||||
}
|
||||
explicit Value(std::string &&s)
|
||||
: type_(STRING_TYPE), string_value_(std::move(s)) {}
|
||||
explicit Value(const char *s) : type_(STRING_TYPE) {
|
||||
string_value_ = s;
|
||||
}
|
||||
explicit Value(const unsigned char *p, size_t n) : type_(BINARY_TYPE) {
|
||||
binary_value_.resize(n);
|
||||
memcpy(binary_value_.data(), p, n);
|
||||
@@ -1301,6 +1280,12 @@ typedef bool (*WriteWholeFileFunction)(std::string *, const std::string &,
|
||||
const std::vector<unsigned char> &,
|
||||
void *);
|
||||
|
||||
///
|
||||
/// GetFileSizeFunction type. Signature for custom filesystem callbacks.
|
||||
///
|
||||
typedef bool (*GetFileSizeFunction)(size_t *filesize_out, std::string *err, const std::string &abs_filename,
|
||||
void *userdata);
|
||||
|
||||
///
|
||||
/// A structure containing all required filesystem callbacks and a pointer to
|
||||
/// their user data.
|
||||
@@ -1310,6 +1295,7 @@ struct FsCallbacks {
|
||||
ExpandFilePathFunction ExpandFilePath;
|
||||
ReadWholeFileFunction ReadWholeFile;
|
||||
WriteWholeFileFunction WriteWholeFile;
|
||||
GetFileSizeFunction GetFileSizeInBytes; // To avoid GetFileSize Win32 API, add `InBytes` suffix.
|
||||
|
||||
void *user_data; // An argument that is passed to all fs callbacks
|
||||
};
|
||||
@@ -1333,6 +1319,9 @@ bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
|
||||
|
||||
bool WriteWholeFile(std::string *err, const std::string &filepath,
|
||||
const std::vector<unsigned char> &contents, void *);
|
||||
|
||||
bool GetFileSizeInBytes(size_t *filesize_out, std::string *err, const std::string &filepath,
|
||||
void *);
|
||||
#endif
|
||||
|
||||
///
|
||||
@@ -1472,6 +1461,19 @@ class TinyGLTF {
|
||||
preserve_image_channels_ = onoff;
|
||||
}
|
||||
|
||||
///
|
||||
/// Set maximum allowed external file size in bytes.
|
||||
/// Default: 2GB
|
||||
/// Only effective for built-in ReadWholeFileFunction FS function.
|
||||
///
|
||||
void SetMaxExternalFileSize(size_t max_bytes) {
|
||||
max_external_file_size_ = max_bytes;
|
||||
}
|
||||
|
||||
size_t GetMaxExternalFileSize() const {
|
||||
return max_external_file_size_;
|
||||
}
|
||||
|
||||
bool GetPreserveImageChannels() const { return preserve_image_channels_; }
|
||||
|
||||
private:
|
||||
@@ -1496,6 +1498,8 @@ class TinyGLTF {
|
||||
bool preserve_image_channels_ = false; /// Default false(expand channels to
|
||||
/// RGBA) for backward compatibility.
|
||||
|
||||
size_t max_external_file_size_{size_t((std::numeric_limits<int32_t>::max)())}; // Default 2GB
|
||||
|
||||
// Warning & error messages
|
||||
std::string warn_;
|
||||
std::string err_;
|
||||
@@ -1503,11 +1507,11 @@ class TinyGLTF {
|
||||
FsCallbacks fs = {
|
||||
#ifndef TINYGLTF_NO_FS
|
||||
&tinygltf::FileExists, &tinygltf::ExpandFilePath,
|
||||
&tinygltf::ReadWholeFile, &tinygltf::WriteWholeFile,
|
||||
&tinygltf::ReadWholeFile, &tinygltf::WriteWholeFile, &tinygltf::GetFileSizeInBytes,
|
||||
|
||||
nullptr // Fs callback user data
|
||||
#else
|
||||
nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
|
||||
nullptr // Fs callback user data
|
||||
#endif
|
||||
@@ -1554,6 +1558,7 @@ class TinyGLTF {
|
||||
#ifndef TINYGLTF_NO_FS
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h> // for is_directory check
|
||||
#endif
|
||||
#include <sstream>
|
||||
|
||||
@@ -2107,9 +2112,19 @@ static std::string FindFile(const std::vector<std::string> &paths,
|
||||
return std::string();
|
||||
}
|
||||
|
||||
// https://github.com/syoyo/tinygltf/issues/416
|
||||
// Use strlen() since std::string's size/length reports the number of elements in the buffer, not the length of string(null-terminated)
|
||||
// strip null-character in the middle of string.
|
||||
size_t slength = strlen(filepath.c_str());
|
||||
if (slength == 0) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string cleaned_filepath = std::string(filepath.c_str());
|
||||
|
||||
for (size_t i = 0; i < paths.size(); i++) {
|
||||
std::string absPath =
|
||||
fs->ExpandFilePath(JoinPath(paths[i], filepath), fs->user_data);
|
||||
fs->ExpandFilePath(JoinPath(paths[i], cleaned_filepath), fs->user_data);
|
||||
if (fs->FileExists(absPath, fs->user_data)) {
|
||||
return absPath;
|
||||
}
|
||||
@@ -2355,7 +2370,7 @@ bool URIDecode(const std::string &in_uri, std::string *out_uri,
|
||||
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
||||
std::string *warn, const std::string &filename,
|
||||
const std::string &basedir, bool required,
|
||||
size_t reqBytes, bool checkSize, FsCallbacks *fs) {
|
||||
size_t reqBytes, bool checkSize, size_t maxFileSize, FsCallbacks *fs) {
|
||||
if (fs == nullptr || fs->FileExists == nullptr ||
|
||||
fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
|
||||
// This is a developer error, assert() ?
|
||||
@@ -2381,6 +2396,29 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check file size
|
||||
if (fs->GetFileSizeInBytes) {
|
||||
|
||||
size_t file_size{0};
|
||||
std::string _err;
|
||||
bool ok = fs->GetFileSizeInBytes(&file_size, &_err, filepath, fs->user_data);
|
||||
if (!ok) {
|
||||
if (_err.size()) {
|
||||
if (failMsgOut) {
|
||||
(*failMsgOut) += "Getting file size failed : " + filename + ", err = " + _err + "\n";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file_size > maxFileSize) {
|
||||
if (failMsgOut) {
|
||||
(*failMsgOut) += "File size " + std::to_string(file_size) + " exceeds maximum allowed file size " + std::to_string(maxFileSize) + " : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> buf;
|
||||
std::string fileReadErr;
|
||||
bool fileRead =
|
||||
@@ -2687,12 +2725,23 @@ bool FileExists(const std::string &abs_filename, void *) {
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#if defined(_MSC_VER) || defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
|
||||
|
||||
// First check if a file is a directory.
|
||||
DWORD result = GetFileAttributesW(UTF8ToWchar(abs_filename).c_str());
|
||||
if (result == INVALID_FILE_ATTRIBUTES) {
|
||||
return false;
|
||||
}
|
||||
if (result & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *fp = nullptr;
|
||||
errno_t err = _wfopen_s(&fp, UTF8ToWchar(abs_filename).c_str(), L"rb");
|
||||
if (err != 0) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// TODO: is_directory check
|
||||
FILE *fp = nullptr;
|
||||
errno_t err = fopen_s(&fp, abs_filename.c_str(), "rb");
|
||||
if (err != 0) {
|
||||
@@ -2701,6 +2750,14 @@ bool FileExists(const std::string &abs_filename, void *) {
|
||||
#endif
|
||||
|
||||
#else
|
||||
struct stat sb;
|
||||
if (stat(abs_filename.c_str(), &sb)) {
|
||||
return false;
|
||||
}
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(abs_filename.c_str(), "rb");
|
||||
#endif
|
||||
if (fp) {
|
||||
@@ -2777,6 +2834,100 @@ std::string ExpandFilePath(const std::string &filepath, void *) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetFileSizeInBytes(size_t *filesize_out, std::string *err,
|
||||
const std::string &filepath, void *userdata) {
|
||||
(void)userdata;
|
||||
|
||||
#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
|
||||
if (asset_manager) {
|
||||
AAsset *asset = AAssetManager_open(asset_manager, filepath.c_str(),
|
||||
AASSET_MODE_STREAMING);
|
||||
if (!asset) {
|
||||
if (err) {
|
||||
(*err) += "File open error : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
size_t size = AAsset_getLength(asset);
|
||||
|
||||
if (size == 0) {
|
||||
if (err) {
|
||||
(*err) += "Invalid file size : " + filepath +
|
||||
" (does the path point to a directory?)";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if (err) {
|
||||
(*err) += "No asset manager specified : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#if defined(__GLIBCXX__) // mingw
|
||||
int file_descriptor =
|
||||
_wopen(UTF8ToWchar(filepath).c_str(), _O_RDONLY | _O_BINARY);
|
||||
__gnu_cxx::stdio_filebuf<char> wfile_buf(file_descriptor, std::ios_base::in);
|
||||
std::istream f(&wfile_buf);
|
||||
#elif defined(_MSC_VER) || defined(_LIBCPP_VERSION)
|
||||
// For libcxx, assume _LIBCPP_HAS_OPEN_WITH_WCHAR is defined to accept
|
||||
// `wchar_t *`
|
||||
std::ifstream f(UTF8ToWchar(filepath).c_str(), std::ifstream::binary);
|
||||
#else
|
||||
// Unknown compiler/runtime
|
||||
std::ifstream f(filepath.c_str(), std::ifstream::binary);
|
||||
#endif
|
||||
#else
|
||||
std::ifstream f(filepath.c_str(), std::ifstream::binary);
|
||||
#endif
|
||||
if (!f) {
|
||||
if (err) {
|
||||
(*err) += "File open error : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// For directory(and pipe?), peek() will fail(Posix gnustl/libc++ only)
|
||||
int buf = f.peek();
|
||||
if (!f) {
|
||||
if (err) {
|
||||
(*err) += "File read error. Maybe empty file or invalid file : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
f.seekg(0, f.end);
|
||||
size_t sz = static_cast<size_t>(f.tellg());
|
||||
|
||||
//std::cout << "sz = " << sz << "\n";
|
||||
f.seekg(0, f.beg);
|
||||
|
||||
if (int64_t(sz) < 0) {
|
||||
if (err) {
|
||||
(*err) += "Invalid file size : " + filepath +
|
||||
" (does the path point to a directory?)";
|
||||
}
|
||||
return false;
|
||||
} else if (sz == 0) {
|
||||
if (err) {
|
||||
(*err) += "File is empty : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
} else if (sz >= (std::numeric_limits<std::streamoff>::max)()) {
|
||||
if (err) {
|
||||
(*err) += "Invalid file size : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
(*filesize_out) = sz;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
|
||||
const std::string &filepath, void *) {
|
||||
#ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
|
||||
@@ -2832,8 +2983,19 @@ bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
|
||||
return false;
|
||||
}
|
||||
|
||||
// For directory(and pipe?), peek() will fail(Posix gnustl/libc++ only)
|
||||
int buf = f.peek();
|
||||
if (!f) {
|
||||
if (err) {
|
||||
(*err) += "File read error. Maybe empty file or invalid file : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
f.seekg(0, f.end);
|
||||
size_t sz = static_cast<size_t>(f.tellg());
|
||||
|
||||
//std::cout << "sz = " << sz << "\n";
|
||||
f.seekg(0, f.beg);
|
||||
|
||||
if (int64_t(sz) < 0) {
|
||||
@@ -2847,6 +3009,11 @@ bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
|
||||
(*err) += "File is empty : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
} else if (sz >= (std::numeric_limits<std::streamoff>::max)()) {
|
||||
if (err) {
|
||||
(*err) += "Invalid file size : " + filepath + "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
out->resize(sz);
|
||||
@@ -3873,7 +4040,7 @@ static bool ParseAsset(Asset *asset, std::string *err, const detail::json &o,
|
||||
static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
||||
std::string *warn, const detail::json &o,
|
||||
bool store_original_json_for_extras_and_extensions,
|
||||
const std::string &basedir, FsCallbacks *fs,
|
||||
const std::string &basedir, const size_t max_file_size, FsCallbacks *fs,
|
||||
const URICallbacks *uri_cb,
|
||||
LoadImageDataFunction *LoadImageData = nullptr,
|
||||
void *load_image_user_data = nullptr) {
|
||||
@@ -3973,8 +4140,8 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
||||
if (!DecodeDataURI(&img, image->mimeType, uri, 0, false)) {
|
||||
if (err) {
|
||||
(*err) += "Failed to decode 'uri' for image[" +
|
||||
std::to_string(image_idx) + "] name = [" + image->name +
|
||||
"]\n";
|
||||
std::to_string(image_idx) + "] name = \"" + image->name +
|
||||
"\"\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -3989,8 +4156,8 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
||||
if (!uri_cb->decode(uri, &decoded_uri, uri_cb->user_data)) {
|
||||
if (warn) {
|
||||
(*warn) += "Failed to decode 'uri' for image[" +
|
||||
std::to_string(image_idx) + "] name = [" + image->name +
|
||||
"]\n";
|
||||
std::to_string(image_idx) + "] name = \"" + image->name +
|
||||
"\"\n";
|
||||
}
|
||||
|
||||
// Image loading failure is not critical to overall gltf loading.
|
||||
@@ -3999,11 +4166,11 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
||||
|
||||
if (!LoadExternalFile(&img, err, warn, decoded_uri, basedir,
|
||||
/* required */ false, /* required bytes */ 0,
|
||||
/* checksize */ false, fs)) {
|
||||
/* checksize */ false, /* max file size */ max_file_size, fs)) {
|
||||
if (warn) {
|
||||
(*warn) += "Failed to load external 'uri' for image[" +
|
||||
std::to_string(image_idx) + "] name = [" + image->name +
|
||||
"]\n";
|
||||
std::to_string(image_idx) + "] name = \"" + decoded_uri +
|
||||
"\"\n";
|
||||
}
|
||||
// If the image cannot be loaded, keep uri as image->uri.
|
||||
return true;
|
||||
@@ -4012,8 +4179,8 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
||||
if (img.empty()) {
|
||||
if (warn) {
|
||||
(*warn) += "Image data is empty for image[" +
|
||||
std::to_string(image_idx) + "] name = [" + image->name +
|
||||
"] \n";
|
||||
std::to_string(image_idx) + "] name = \"" + image->name +
|
||||
"\" \n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -4176,7 +4343,7 @@ static bool ParseOcclusionTextureInfo(
|
||||
static bool ParseBuffer(Buffer *buffer, std::string *err, const detail::json &o,
|
||||
bool store_original_json_for_extras_and_extensions,
|
||||
FsCallbacks *fs, const URICallbacks *uri_cb,
|
||||
const std::string &basedir, bool is_binary = false,
|
||||
const std::string &basedir, const size_t max_buffer_size, bool is_binary = false,
|
||||
const unsigned char *bin_data = nullptr,
|
||||
size_t bin_size = 0) {
|
||||
size_t byteLength;
|
||||
@@ -4228,7 +4395,7 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const detail::json &o,
|
||||
}
|
||||
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr,
|
||||
decoded_uri, basedir, /* required */ true,
|
||||
byteLength, /* checkSize */ true, fs)) {
|
||||
byteLength, /* checkSize */ true, /* max_file_size */max_buffer_size, fs)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4276,7 +4443,7 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const detail::json &o,
|
||||
}
|
||||
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, decoded_uri,
|
||||
basedir, /* required */ true, byteLength,
|
||||
/* checkSize */ true, fs)) {
|
||||
/* checkSize */ true, /* max file size */max_buffer_size, fs)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -5811,7 +5978,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
Buffer buffer;
|
||||
if (!ParseBuffer(&buffer, err, o,
|
||||
store_original_json_for_extras_and_extensions_, &fs,
|
||||
&uri_cb, base_dir, is_binary_, bin_data_, bin_size_)) {
|
||||
&uri_cb, base_dir, max_external_file_size_, is_binary_, bin_data_, bin_size_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6082,7 +6249,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
Image image;
|
||||
if (!ParseImage(&image, idx, err, warn, o,
|
||||
store_original_json_for_extras_and_extensions_, base_dir,
|
||||
&fs, &uri_cb, &this->LoadImageData,
|
||||
max_external_file_size_, &fs, &uri_cb, &this->LoadImageData,
|
||||
load_image_user_data)) {
|
||||
return false;
|
||||
}
|
||||
@@ -6576,7 +6743,16 @@ void JsonAddMember(detail::json &o, const char *key, detail::json &&value) {
|
||||
if (!o.IsObject()) {
|
||||
o.SetObject();
|
||||
}
|
||||
o.AddMember(detail::json(key, detail::GetAllocator()), std::move(value), detail::GetAllocator());
|
||||
|
||||
// Issue 420.
|
||||
// AddMember may create duplicated key, so use [] API when a key already exists.
|
||||
// https://github.com/Tencent/rapidjson/issues/771#issuecomment-254386863
|
||||
detail::json_const_iterator it;
|
||||
if (detail::FindMember(o, key, it)) {
|
||||
o[key] = std::move(value); // replace
|
||||
} else {
|
||||
o.AddMember(detail::json(key, detail::GetAllocator()), std::move(value), detail::GetAllocator());
|
||||
}
|
||||
#else
|
||||
o[key] = std::move(value);
|
||||
#endif
|
||||
@@ -6967,7 +7143,7 @@ static void SerializeGltfAnimationChannel(const AnimationChannel &channel,
|
||||
{
|
||||
detail::json target;
|
||||
|
||||
if (channel.target_node > 0) {
|
||||
if (channel.target_node >= 0) {
|
||||
SerializeNumberProperty("node", channel.target_node, target);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user