Added 'warning' message parameter to glTF loader API.

Asset loading failure messages(e.g. image file is missing) are now stored in `warning` message, not `error` message.
This commit is contained in:
Syoyo Fujita 2018-07-27 16:49:10 +09:00
parent a71be9cc98
commit 7c8d4ed748
7 changed files with 162 additions and 154 deletions

View File

@ -69,13 +69,14 @@ int parse_args(int argc, char** argv) {
tinygltf::TinyGLTF loader; tinygltf::TinyGLTF loader;
tinygltf::Model model; tinygltf::Model model;
std::string error; std::string error;
std::string warning;
bool state; bool state;
switch (detectType(config.input_path)) { switch (detectType(config.input_path)) {
case FileType::Ascii: case FileType::Ascii:
state = loader.LoadASCIIFromFile(&model, &error, config.input_path); state = loader.LoadASCIIFromFile(&model, &error, &warning, config.input_path);
break; break;
case FileType::Binary: case FileType::Binary:
state = loader.LoadBinaryFromFile(&model, &error, config.input_path); state = loader.LoadBinaryFromFile(&model, &error, &warning, config.input_path);
break; break;
case FileType::Unknown: case FileType::Unknown:
default: default:

View File

@ -1,4 +1,5 @@
#include <iostream> #include <iostream>
#include <algorithm>
#include "stb_image_write.h" #include "stb_image_write.h"
#include "texture_dumper.h" #include "texture_dumper.h"

View File

@ -16,6 +16,7 @@
#define TINYGLTF_IMPLEMENTATION #define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "tiny_gltf.h" #include "tiny_gltf.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i)) #define BUFFER_OFFSET(i) ((char *)NULL + (i))
@ -732,16 +733,21 @@ int main(int argc, char **argv) {
tinygltf::Model model; tinygltf::Model model;
tinygltf::TinyGLTF loader; tinygltf::TinyGLTF loader;
std::string err; std::string err;
std::string warn;
std::string input_filename(argv[1]); std::string input_filename(argv[1]);
std::string ext = GetFilePathExtension(input_filename); std::string ext = GetFilePathExtension(input_filename);
bool ret = false; bool ret = false;
if (ext.compare("glb") == 0) { if (ext.compare("glb") == 0) {
// assume binary glTF. // assume binary glTF.
ret = loader.LoadBinaryFromFile(&model, &err, input_filename.c_str()); ret = loader.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
} else { } else {
// assume ascii glTF. // assume ascii glTF.
ret = loader.LoadASCIIFromFile(&model, &err, input_filename.c_str()); ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
}
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
} }
if (!err.empty()) { if (!err.empty()) {

View File

@ -26,15 +26,20 @@ bool LoadGLTF(const std::string &filename, float scale,
tinygltf::Model model; tinygltf::Model model;
tinygltf::TinyGLTF loader; tinygltf::TinyGLTF loader;
std::string err; std::string err;
std::string warn;
const std::string ext = GetFilePathExtension(filename); const std::string ext = GetFilePathExtension(filename);
bool ret = false; bool ret = false;
if (ext.compare("glb") == 0) { if (ext.compare("glb") == 0) {
// assume binary glTF. // assume binary glTF.
ret = loader.LoadBinaryFromFile(&model, &err, filename.c_str()); ret = loader.LoadBinaryFromFile(&model, &err, &warn, filename.c_str());
} else { } else {
// assume ascii glTF. // assume ascii glTF.
ret = loader.LoadASCIIFromFile(&model, &err, filename.c_str()); ret = loader.LoadASCIIFromFile(&model, &err, &warn, filename.c_str());
}
if (!warn.empty()) {
std::cout << "glTF parse warning: " << warn << std::endl;
} }
if (!err.empty()) { if (!err.empty()) {

View File

@ -25,13 +25,17 @@ int main(int argc, char *argv[]) {
tinygltf::Model model; tinygltf::Model model;
tinygltf::TinyGLTF loader; tinygltf::TinyGLTF loader;
std::string err; std::string err;
std::string warn;
std::string input_filename(argv[1]); std::string input_filename(argv[1]);
std::string output_filename(argv[2]); std::string output_filename(argv[2]);
std::string embedded_filename = std::string embedded_filename =
output_filename.substr(0, output_filename.size() - 5) + "-Embedded.gltf"; output_filename.substr(0, output_filename.size() - 5) + "-Embedded.gltf";
// assume ascii glTF. // assume ascii glTF.
bool ret = loader.LoadASCIIFromFile(&model, &err, input_filename.c_str()); bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
if (!warn.empty()) {
std::cout << "warn : " << warn << std::endl;
}
if (!ret) { if (!ret) {
if (!err.empty()) { if (!err.empty()) {
std::cerr << err << std::endl; std::cerr << err << std::endl;

View File

@ -597,6 +597,7 @@ int main(int argc, char **argv) {
tinygltf::Model model; tinygltf::Model model;
tinygltf::TinyGLTF gltf_ctx; tinygltf::TinyGLTF gltf_ctx;
std::string err; std::string err;
std::string warn;
std::string input_filename(argv[1]); std::string input_filename(argv[1]);
std::string ext = GetFilePathExtension(input_filename); std::string ext = GetFilePathExtension(input_filename);
@ -604,13 +605,18 @@ int main(int argc, char **argv) {
if (ext.compare("glb") == 0) { if (ext.compare("glb") == 0) {
std::cout << "Reading binary glTF" << std::endl; std::cout << "Reading binary glTF" << std::endl;
// assume binary glTF. // assume binary glTF.
ret = gltf_ctx.LoadBinaryFromFile(&model, &err, input_filename.c_str()); ret = gltf_ctx.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
} else { } else {
std::cout << "Reading ASCII glTF" << std::endl; std::cout << "Reading ASCII glTF" << std::endl;
// assume ascii glTF. // assume ascii glTF.
ret = gltf_ctx.LoadASCIIFromFile(&model, &err, input_filename.c_str()); ret = gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
} }
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
}
if (!err.empty()) { if (!err.empty()) {
printf("Err: %s\n", err.c_str()); printf("Err: %s\n", err.c_str());
} }

View File

@ -734,8 +734,9 @@ enum SectionCheck {
/// ///
/// LoadImageDataFunction type. Signature for custom image loading callbacks. /// LoadImageDataFunction type. Signature for custom image loading callbacks.
/// ///
typedef bool (*LoadImageDataFunction)(Image *, std::string *, int, int, typedef bool (*LoadImageDataFunction)(Image *, std::string *, std::string *,
const unsigned char *, int, void *); int, int, const unsigned char *, int,
void *);
/// ///
/// WriteImageDataFunction type. Signature for custom image writing callbacks. /// WriteImageDataFunction type. Signature for custom image writing callbacks.
@ -745,9 +746,9 @@ typedef bool (*WriteImageDataFunction)(const std::string *, const std::string *,
#ifndef TINYGLTF_NO_STB_IMAGE #ifndef TINYGLTF_NO_STB_IMAGE
// Declaration of default image loader callback // Declaration of default image loader callback
bool LoadImageData(Image *image, std::string *err, int req_width, bool LoadImageData(Image *image, std::string *err, std::string *warn,
int req_height, const unsigned char *bytes, int size, int req_width, int req_height, const unsigned char *bytes,
void *); int size, void *);
#endif #endif
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
@ -759,28 +760,24 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
/// ///
/// FilExistsFunction type. Signature for custom filesystem callbacks. /// FilExistsFunction type. Signature for custom filesystem callbacks.
/// ///
typedef bool (*FileExistsFunction)(const std::string &abs_filename, typedef bool (*FileExistsFunction)(const std::string &abs_filename, void *);
void *);
/// ///
/// ExpandFilePathFunction type. Signature for custom filesystem callbacks. /// ExpandFilePathFunction type. Signature for custom filesystem callbacks.
/// ///
typedef std::string (*ExpandFilePathFunction)(const std::string &, typedef std::string (*ExpandFilePathFunction)(const std::string &, void *);
void *);
/// ///
/// ReadWholeFileFunction type. Signature for custom filesystem callbacks. /// ReadWholeFileFunction type. Signature for custom filesystem callbacks.
/// ///
typedef bool (*ReadWholeFileFunction)(std::vector<unsigned char> *, typedef bool (*ReadWholeFileFunction)(std::vector<unsigned char> *,
std::string *, std::string *, const std::string &,
const std::string &,
void *); void *);
/// ///
/// WriteWholeFileFunction type. Signature for custom filesystem callbacks. /// WriteWholeFileFunction type. Signature for custom filesystem callbacks.
/// ///
typedef bool (*WriteWholeFileFunction)(std::string *, typedef bool (*WriteWholeFileFunction)(std::string *, const std::string &,
const std::string &,
const std::vector<unsigned char> &, const std::vector<unsigned char> &,
void *); void *);
@ -788,8 +785,7 @@ typedef bool (*WriteWholeFileFunction)(std::string *,
/// A structure containing all required filesystem callbacks and a pointer to /// A structure containing all required filesystem callbacks and a pointer to
/// their user data. /// their user data.
/// ///
struct FsCallbacks struct FsCallbacks {
{
FileExistsFunction FileExists; FileExistsFunction FileExists;
ExpandFilePathFunction ExpandFilePath; ExpandFilePathFunction ExpandFilePath;
ReadWholeFileFunction ReadWholeFile; ReadWholeFileFunction ReadWholeFile;
@ -801,20 +797,15 @@ struct FsCallbacks
#ifndef TINYGLTF_NO_FS #ifndef TINYGLTF_NO_FS
// Declaration of default filesystem callbacks // Declaration of default filesystem callbacks
bool FileExists(const std::string &abs_filename, bool FileExists(const std::string &abs_filename, void *);
void *);
std::string ExpandFilePath(const std::string &filepath, std::string ExpandFilePath(const std::string &filepath, void *);
void *);
bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err, bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
const std::string &filepath, const std::string &filepath, void *);
void *);
bool WriteWholeFile(std::string *err, bool WriteWholeFile(std::string *err, const std::string &filepath,
const std::string &filepath, const std::vector<unsigned char> &contents, void *);
const std::vector<unsigned char> &contents,
void *);
#endif #endif
class TinyGLTF { class TinyGLTF {
@ -834,36 +825,40 @@ class TinyGLTF {
/// ///
/// Loads glTF ASCII asset from a file. /// Loads glTF ASCII asset from a file.
/// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error. /// Returns false and set error string to `err` if there's an error.
/// ///
bool LoadASCIIFromFile(Model *model, std::string *err, bool LoadASCIIFromFile(Model *model, std::string *err, std::string *warn,
const std::string &filename, const std::string &filename,
unsigned int check_sections = REQUIRE_ALL); unsigned int check_sections = REQUIRE_ALL);
/// ///
/// Loads glTF ASCII asset from string(memory). /// Loads glTF ASCII asset from string(memory).
/// `length` = strlen(str); /// `length` = strlen(str);
/// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error. /// Returns false and set error string to `err` if there's an error.
/// ///
bool LoadASCIIFromString(Model *model, std::string *err, const char *str, bool LoadASCIIFromString(Model *model, std::string *err, std::string *warn,
const unsigned int length, const char *str, const unsigned int length,
const std::string &base_dir, const std::string &base_dir,
unsigned int check_sections = REQUIRE_ALL); unsigned int check_sections = REQUIRE_ALL);
/// ///
/// Loads glTF binary asset from a file. /// Loads glTF binary asset from a file.
/// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error. /// Returns false and set error string to `err` if there's an error.
/// ///
bool LoadBinaryFromFile(Model *model, std::string *err, bool LoadBinaryFromFile(Model *model, std::string *err, std::string *warn,
const std::string &filename, const std::string &filename,
unsigned int check_sections = REQUIRE_ALL); unsigned int check_sections = REQUIRE_ALL);
/// ///
/// Loads glTF binary asset from memory. /// Loads glTF binary asset from memory.
/// `length` = strlen(str); /// `length` = strlen(str);
/// Set warning message to `warn` for example it fails to load asserts.
/// Returns false and set error string to `err` if there's an error. /// Returns false and set error string to `err` if there's an error.
/// ///
bool LoadBinaryFromMemory(Model *model, std::string *err, bool LoadBinaryFromMemory(Model *model, std::string *err, std::string *warn,
const unsigned char *bytes, const unsigned char *bytes,
const unsigned int length, const unsigned int length,
const std::string &base_dir = "", const std::string &base_dir = "",
@ -895,11 +890,12 @@ class TinyGLTF {
/// ///
/// Loads glTF asset from string(memory). /// Loads glTF asset from string(memory).
/// `length` = strlen(str); /// `length` = strlen(str);
/// Set warning message to `warn` for example it fails to load asserts
/// Returns false and set error string to `err` if there's an error. /// Returns false and set error string to `err` if there's an error.
/// ///
bool LoadFromString(Model *model, std::string *err, const char *str, bool LoadFromString(Model *model, std::string *err, std::string *warn,
const unsigned int length, const std::string &base_dir, const char *str, const unsigned int length,
unsigned int check_sections); const std::string &base_dir, unsigned int check_sections);
const unsigned char *bin_data_; const unsigned char *bin_data_;
size_t bin_size_; size_t bin_size_;
@ -907,17 +903,12 @@ class TinyGLTF {
FsCallbacks fs = { FsCallbacks fs = {
#ifndef TINYGLTF_NO_FS #ifndef TINYGLTF_NO_FS
&tinygltf::FileExists, &tinygltf::FileExists, &tinygltf::ExpandFilePath,
&tinygltf::ExpandFilePath, &tinygltf::ReadWholeFile, &tinygltf::WriteWholeFile,
&tinygltf::ReadWholeFile,
&tinygltf::WriteWholeFile,
nullptr // Fs callback user data nullptr // Fs callback user data
#else #else
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr // Fs callback user data nullptr // Fs callback user data
#endif #endif
@ -938,7 +929,6 @@ class TinyGLTF {
nullptr; nullptr;
#endif #endif
void *write_image_user_data_ = reinterpret_cast<void *>(&fs); void *write_image_user_data_ = reinterpret_cast<void *>(&fs);
}; };
#ifdef __clang__ #ifdef __clang__
@ -1071,19 +1061,16 @@ static std::string JoinPath(const std::string &path0,
} }
static std::string FindFile(const std::vector<std::string> &paths, static std::string FindFile(const std::vector<std::string> &paths,
const std::string &filepath, const std::string &filepath, FsCallbacks *fs) {
FsCallbacks* fs) {
if (fs == nullptr || fs->ExpandFilePath == nullptr || if (fs == nullptr || fs->ExpandFilePath == nullptr ||
fs->FileExists == nullptr) { fs->FileExists == nullptr) {
// Error, fs callback[s] missing // Error, fs callback[s] missing
return std::string(); return std::string();
} }
for (size_t i = 0; i < paths.size(); i++) { for (size_t i = 0; i < paths.size(); i++) {
std::string absPath = fs->ExpandFilePath(JoinPath(paths[i], filepath), std::string absPath =
fs->user_data); fs->ExpandFilePath(JoinPath(paths[i], filepath), fs->user_data);
if (fs->FileExists(absPath, fs->user_data)) { if (fs->FileExists(absPath, fs->user_data)) {
return absPath; return absPath;
} }
@ -1245,14 +1232,11 @@ std::string base64_decode(std::string const &encoded_string) {
#endif #endif
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err, static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
const std::string &filename, std::string *warn, const std::string &filename,
const std::string &basedir, size_t reqBytes, const std::string &basedir, size_t reqBytes,
bool checkSize, bool checkSize, FsCallbacks *fs) {
FsCallbacks *fs) { if (fs == nullptr || fs->FileExists == nullptr ||
fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
if (fs == nullptr || fs->FileExists == nullptr
|| fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
// This is a developer error, assert() ? // This is a developer error, assert() ?
if (err) { if (err) {
(*err) += "FS callback[s] not set\n"; (*err) += "FS callback[s] not set\n";
@ -1268,16 +1252,16 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
std::string filepath = FindFile(paths, filename, fs); std::string filepath = FindFile(paths, filename, fs);
if (filepath.empty() || filename.empty()) { if (filepath.empty() || filename.empty()) {
if (err) { if (warn) {
(*err) += "File not found : " + filename + "\n"; (*warn) += "File not found : " + filename + "\n";
} }
return false; return false;
} }
std::vector<unsigned char> buf; std::vector<unsigned char> buf;
std::string fileReadErr; std::string fileReadErr;
bool fileRead = fs->ReadWholeFile(&buf, &fileReadErr, filepath, bool fileRead =
fs->user_data); fs->ReadWholeFile(&buf, &fileReadErr, filepath, fs->user_data);
if (!fileRead) { if (!fileRead) {
if (err) { if (err) {
(*err) += "File read error : " + filepath + " : " + fileReadErr + "\n"; (*err) += "File read error : " + filepath + " : " + fileReadErr + "\n";
@ -1316,9 +1300,11 @@ void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
} }
#ifndef TINYGLTF_NO_STB_IMAGE #ifndef TINYGLTF_NO_STB_IMAGE
bool LoadImageData(Image *image, std::string *err, int req_width, bool LoadImageData(Image *image, std::string *err, std::string *warn,
int req_height, const unsigned char *bytes, int size, int req_width, int req_height, const unsigned char *bytes,
void *) { int size, void *) {
(void)warn;
int w, h, comp; int w, h, comp;
// if image cannot be decoded, ignore parsing and keep it by its path // if image cannot be decoded, ignore parsing and keep it by its path
// don't break in this case // don't break in this case
@ -1328,6 +1314,7 @@ bool LoadImageData(Image *image, std::string *err, int req_width,
// mandatory (to support other formats) // mandatory (to support other formats)
unsigned char *data = stbi_load_from_memory(bytes, size, &w, &h, &comp, 0); unsigned char *data = stbi_load_from_memory(bytes, size, &w, &h, &comp, 0);
if (!data) { if (!data) {
// NOTE: you can use `warn` instead of `err`
if (err) { if (err) {
(*err) += "Unknown image format.\n"; (*err) += "Unknown image format.\n";
} }
@ -1428,11 +1415,11 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
} else { } else {
// Write image to disc // Write image to disc
FsCallbacks *fs = reinterpret_cast<FsCallbacks *>(fsPtr); FsCallbacks *fs = reinterpret_cast<FsCallbacks *>(fsPtr);
if (fs != nullptr && fs->WriteWholeFile == nullptr) if (fs != nullptr && fs->WriteWholeFile == nullptr) {
{
const std::string imagefilepath = JoinPath(*basepath, *filename); const std::string imagefilepath = JoinPath(*basepath, *filename);
std::string writeError; std::string writeError;
if(!fs->WriteWholeFile(&writeError, imagefilepath, data, fs->user_data)) { if (!fs->WriteWholeFile(&writeError, imagefilepath, data,
fs->user_data)) {
// Could not write image file to disc; Throw error ? // Could not write image file to disc; Throw error ?
} }
} else { } else {
@ -1445,10 +1432,7 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
} }
#endif #endif
void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) { fs = callbacks; }
{
fs = callbacks;
}
#ifndef TINYGLTF_NO_FS #ifndef TINYGLTF_NO_FS
// Default implementations of filesystem functions // Default implementations of filesystem functions
@ -1523,7 +1507,6 @@ std::string ExpandFilePath(const std::string &filepath, void *) {
bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err, bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
const std::string &filepath, void *) { const std::string &filepath, void *) {
std::ifstream f(filepath.c_str(), std::ifstream::binary); std::ifstream f(filepath.c_str(), std::ifstream::binary);
if (!f) { if (!f) {
if (err) { if (err) {
@ -1538,7 +1521,8 @@ bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
if (int(sz) < 0) { if (int(sz) < 0) {
if (err) { if (err) {
(*err) += "Invalid file size : " + filepath + " (does the path point to a directory?)"; (*err) += "Invalid file size : " + filepath +
" (does the path point to a directory?)";
} }
return false; return false;
} else if (sz == 0) { } else if (sz == 0) {
@ -1556,11 +1540,8 @@ bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
return true; return true;
} }
bool WriteWholeFile(std::string *err, bool WriteWholeFile(std::string *err, const std::string &filepath,
const std::string &filepath, const std::vector<unsigned char> &contents, void *) {
const std::vector<unsigned char> &contents,
void *) {
std::ofstream f(filepath.c_str(), std::ofstream::binary); std::ofstream f(filepath.c_str(), std::ofstream::binary);
if (!f) { if (!f) {
if (err) { if (err) {
@ -2099,8 +2080,8 @@ static bool ParseAsset(Asset *asset, std::string *err, const json &o) {
return true; return true;
} }
static bool ParseImage(Image *image, std::string *err, const json &o, static bool ParseImage(Image *image, std::string *err, std::string *warn,
const std::string &basedir, const json &o, const std::string &basedir,
FsCallbacks *fs, FsCallbacks *fs,
LoadImageDataFunction *LoadImageData = nullptr, LoadImageDataFunction *LoadImageData = nullptr,
void *load_image_user_data = nullptr) { void *load_image_user_data = nullptr) {
@ -2185,17 +2166,17 @@ static bool ParseImage(Image *image, std::string *err, const json &o,
#ifdef TINYGLTF_NO_EXTERNAL_IMAGE #ifdef TINYGLTF_NO_EXTERNAL_IMAGE
return true; return true;
#endif #endif
if (!LoadExternalFile(&img, err, uri, basedir, 0, false, fs)) { if (!LoadExternalFile(&img, err, warn, uri, basedir, 0, false, fs)) {
if (err) { if (warn) {
(*err) += "Failed to load external 'uri' for image parameter\n"; (*warn) += "Failed to load external 'uri' for image parameter\n";
} }
// If the image cannot be loaded, keep uri as image->uri. // If the image cannot be loaded, keep uri as image->uri.
return true; return true;
} }
if (img.empty()) { if (img.empty()) {
if (err) { if (warn) {
(*err) += "Image is empty.\n"; (*warn) += "Image is empty.\n";
} }
return false; return false;
} }
@ -2207,7 +2188,7 @@ static bool ParseImage(Image *image, std::string *err, const json &o,
} }
return false; return false;
} }
return (*LoadImageData)(image, err, 0, 0, &img.at(0), return (*LoadImageData)(image, err, warn, 0, 0, &img.at(0),
static_cast<int>(img.size()), load_image_user_data); static_cast<int>(img.size()), load_image_user_data);
} }
@ -2232,8 +2213,8 @@ static bool ParseTexture(Texture *texture, std::string *err, const json &o,
} }
static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o, static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
FsCallbacks* fs, FsCallbacks *fs, const std::string &basedir,
const std::string &basedir, bool is_binary = false, bool is_binary = false,
const unsigned char *bin_data = nullptr, const unsigned char *bin_data = nullptr,
size_t bin_size = 0) { size_t bin_size = 0) {
double byteLength; double byteLength;
@ -2269,15 +2250,18 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
// First try embedded data URI. // First try embedded data URI.
if (IsDataURI(buffer->uri)) { if (IsDataURI(buffer->uri)) {
std::string mime_type; std::string mime_type;
if (!DecodeDataURI(&buffer->data, mime_type, buffer->uri, bytes, true)) { if (!DecodeDataURI(&buffer->data, mime_type, buffer->uri, bytes,
true)) {
if (err) { if (err) {
(*err) += "Failed to decode 'uri' : " + buffer->uri + " in Buffer\n"; (*err) +=
"Failed to decode 'uri' : " + buffer->uri + " in Buffer\n";
} }
return false; return false;
} }
} else { } else {
// External .bin file. // External .bin file.
LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes, true, fs); LoadExternalFile(&buffer->data, err, /* warn */ nullptr, buffer->uri,
basedir, bytes, true, fs);
} }
} else { } else {
// load data from (embedded) binary data // load data from (embedded) binary data
@ -2316,8 +2300,8 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
} }
} else { } else {
// Assume external .bin file. // Assume external .bin file.
if (!LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes, if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, buffer->uri,
true, fs)) { basedir, bytes, true, fs)) {
return false; return false;
} }
} }
@ -2944,8 +2928,9 @@ static bool ParseCamera(Camera *camera, std::string *err, const json &o) {
return true; return true;
} }
bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
unsigned int length, const std::string &base_dir, const char *str, unsigned int length,
const std::string &base_dir,
unsigned int check_sections) { unsigned int check_sections) {
if (length < 4) { if (length < 4) {
if (err) { if (err) {
@ -3111,9 +3096,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
return false; return false;
} }
Buffer buffer; Buffer buffer;
if (!ParseBuffer(&buffer, err, it->get<json>(), if (!ParseBuffer(&buffer, err, it->get<json>(), &fs, base_dir,
&fs, base_dir, is_binary_, is_binary_, bin_data_, bin_size_)) {
bin_data_, bin_size_)) {
return false; return false;
} }
@ -3314,9 +3298,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
return false; return false;
} }
Image image; Image image;
if (!ParseImage(&image, err, it.value(), if (!ParseImage(&image, err, warn, it.value(), base_dir, &fs,
base_dir, &fs, &this->LoadImageData, &this->LoadImageData, load_image_user_data_)) {
load_image_user_data_)) {
return false; return false;
} }
@ -3342,7 +3325,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
} }
return false; return false;
} }
bool ret = LoadImageData(&image, err, image.width, image.height, bool ret = LoadImageData(&image, err, warn, image.width, image.height,
&buffer.data[bufferView.byteOffset], &buffer.data[bufferView.byteOffset],
static_cast<int>(bufferView.byteLength), static_cast<int>(bufferView.byteLength),
load_image_user_data_); load_image_user_data_);
@ -3529,25 +3512,27 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
} }
bool TinyGLTF::LoadASCIIFromString(Model *model, std::string *err, bool TinyGLTF::LoadASCIIFromString(Model *model, std::string *err,
const char *str, unsigned int length, std::string *warn, const char *str,
unsigned int length,
const std::string &base_dir, const std::string &base_dir,
unsigned int check_sections) { unsigned int check_sections) {
is_binary_ = false; is_binary_ = false;
bin_data_ = nullptr; bin_data_ = nullptr;
bin_size_ = 0; bin_size_ = 0;
return LoadFromString(model, err, str, length, base_dir, check_sections); return LoadFromString(model, err, warn, str, length, base_dir,
check_sections);
} }
bool TinyGLTF::LoadASCIIFromFile(Model *model, std::string *err, bool TinyGLTF::LoadASCIIFromFile(Model *model, std::string *err,
const std::string &filename, std::string *warn, const std::string &filename,
unsigned int check_sections) { unsigned int check_sections) {
std::stringstream ss; std::stringstream ss;
if (fs.ReadWholeFile == nullptr) { if (fs.ReadWholeFile == nullptr) {
// Programmer error, assert() ? // Programmer error, assert() ?
ss << "Failed to read file: " << filename << ss << "Failed to read file: " << filename
": one or more FS callback not set" << std::endl; << ": one or more FS callback not set" << std::endl;
if (err) { if (err) {
(*err) = ss.str(); (*err) = ss.str();
} }
@ -3575,16 +3560,15 @@ bool TinyGLTF::LoadASCIIFromFile(Model *model, std::string *err,
std::string basedir = GetBaseDir(filename); std::string basedir = GetBaseDir(filename);
bool ret = LoadASCIIFromString(model, err, bool ret = LoadASCIIFromString(
reinterpret_cast<const char *>(&data.at(0)), model, err, warn, reinterpret_cast<const char *>(&data.at(0)),
static_cast<unsigned int>(data.size()), static_cast<unsigned int>(data.size()), basedir, check_sections);
basedir,
check_sections);
return ret; return ret;
} }
bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err, bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
std::string *warn,
const unsigned char *bytes, const unsigned char *bytes,
unsigned int size, unsigned int size,
const std::string &base_dir, const std::string &base_dir,
@ -3642,8 +3626,8 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
bin_size_ = bin_size_ =
length - (20 + model_length); // extract header + JSON scene data. length - (20 + model_length); // extract header + JSON scene data.
bool ret = bool ret = LoadFromString(model, err, warn,
LoadFromString(model, err, reinterpret_cast<const char *>(&bytes[20]), reinterpret_cast<const char *>(&bytes[20]),
model_length, base_dir, check_sections); model_length, base_dir, check_sections);
if (!ret) { if (!ret) {
return ret; return ret;
@ -3653,14 +3637,15 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
} }
bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err, bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
std::string *warn,
const std::string &filename, const std::string &filename,
unsigned int check_sections) { unsigned int check_sections) {
std::stringstream ss; std::stringstream ss;
if (fs.ReadWholeFile == nullptr) { if (fs.ReadWholeFile == nullptr) {
// Programmer error, assert() ? // Programmer error, assert() ?
ss << "Failed to read file: " << filename << ss << "Failed to read file: " << filename
": one or more FS callback not set" << std::endl; << ": one or more FS callback not set" << std::endl;
if (err) { if (err) {
(*err) = ss.str(); (*err) = ss.str();
} }
@ -3680,9 +3665,9 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
std::string basedir = GetBaseDir(filename); std::string basedir = GetBaseDir(filename);
bool ret = LoadBinaryFromMemory( bool ret = LoadBinaryFromMemory(model, err, warn, &data.at(0),
model, err, &data.at(0), static_cast<unsigned int>(data.size()),
static_cast<unsigned int>(data.size()), basedir, check_sections); basedir, check_sections);
return ret; return ret;
} }