From d42767e63f87a2cf32594cd04a92cd8cf14d0601 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Thu, 15 Mar 2018 21:52:00 -0500 Subject: [PATCH] Store relative URI in Buffer serializer. Fixes #48. Apply clang-format. Add simple saver sample. --- examples/saver/Makefile.dev | 2 + examples/saver/README.md | 1 + examples/saver/main.cc | 33 ++++ tiny_gltf.h | 321 ++++++++++++++++++------------------ 4 files changed, 192 insertions(+), 165 deletions(-) create mode 100644 examples/saver/Makefile.dev create mode 100644 examples/saver/README.md create mode 100644 examples/saver/main.cc diff --git a/examples/saver/Makefile.dev b/examples/saver/Makefile.dev new file mode 100644 index 0000000..f36d3df --- /dev/null +++ b/examples/saver/Makefile.dev @@ -0,0 +1,2 @@ +all: + clang++ -std=c++11 -I../../ -g -O1 -o saver main.cc diff --git a/examples/saver/README.md b/examples/saver/README.md new file mode 100644 index 0000000..69e5a26 --- /dev/null +++ b/examples/saver/README.md @@ -0,0 +1 @@ +# Simple serialization API sample. diff --git a/examples/saver/main.cc b/examples/saver/main.cc new file mode 100644 index 0000000..cbc478b --- /dev/null +++ b/examples/saver/main.cc @@ -0,0 +1,33 @@ +#include +#include + +#define TINYGLTF_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include "tiny_gltf.h" + +int main(int argc, char *argv[]) +{ + if (argc != 3) { + std::cout << "Needs input.gltf output.gltf" << std::endl; + return EXIT_FAILURE; + } + + tinygltf::Model model; + tinygltf::TinyGLTF loader; + std::string err; + std::string input_filename(argv[1]); + std::string output_filename(argv[2]); + + // assume ascii glTF. + bool ret = loader.LoadASCIIFromFile(&model, &err, input_filename.c_str()); + if (!ret) { + if (!err.empty()) { + std::cerr << err << std::endl; + } + return EXIT_FAILURE; + } + loader.WriteGltfSceneToFile(&model, output_filename); + + return EXIT_SUCCESS; + +} diff --git a/tiny_gltf.h b/tiny_gltf.h index 31d118f..0964a53 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -37,13 +37,13 @@ #ifndef TINY_GLTF_H_ #define TINY_GLTF_H_ -#include +#include #include +#include #include #include #include #include -#include namespace tinygltf { @@ -145,8 +145,7 @@ typedef enum { OBJECT_TYPE = 7 } Type; -static inline int32_t GetComponentSizeInBytes(uint32_t componentType) -{ +static inline int32_t GetComponentSizeInBytes(uint32_t componentType) { if (componentType == TINYGLTF_COMPONENT_TYPE_BYTE) { return 1; } else if (componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) { @@ -169,8 +168,7 @@ static inline int32_t GetComponentSizeInBytes(uint32_t componentType) } } -static inline int32_t GetTypeSizeInBytes(uint32_t ty) -{ +static inline int32_t GetTypeSizeInBytes(uint32_t ty) { if (ty == TINYGLTF_TYPE_SCALAR) { return 1; } else if (ty == TINYGLTF_TYPE_VEC2) { @@ -307,7 +305,6 @@ class Value { #pragma clang diagnostic pop #endif - #define TINYGLTF_VALUE_GET(ctype, var) \ template <> \ inline const ctype &Value::Get() const { \ @@ -332,46 +329,44 @@ TINYGLTF_VALUE_GET(Value::Object, object_value_) #pragma clang diagnostic ignored "-Wpadded" #endif -///Agregate object for representing a color +/// Agregate object for representing a color using ColorValue = std::array; - struct Parameter { +struct Parameter { bool bool_value; std::string string_value; std::vector number_array; std::map json_double_value; - //context sensitive methods. depending the type of the Parameter you are accessing, these are either valid or not - //If this parameter represent a texture map in a material, will return the texture index + // context sensitive methods. depending the type of the Parameter you are + // accessing, these are either valid or not + // If this parameter represent a texture map in a material, will return the + // texture index - ///Return the index of a texture if this Parameter is a texture map. - ///Returned value is only valid if the parameter represent a texture from a material + /// Return the index of a texture if this Parameter is a texture map. + /// Returned value is only valid if the parameter represent a texture from a + /// material int TextureIndex() const { const auto it = json_double_value.find("index"); - if (it != std::end(json_double_value)) - { + if (it != std::end(json_double_value)) { return int(it->second); } return -1; } - ///Material factor, like the roughness or metalness of a material - ///Returned value is only valid if the parameter represent a texture from a material - double Factor() const { - return number_array[0]; - } + /// Material factor, like the roughness or metalness of a material + /// Returned value is only valid if the parameter represent a texture from a + /// material + double Factor() const { return number_array[0]; } - ///Return the color of a material - ///Returned value is only valid if the parameter represent a texture from a material + /// Return the color of a material + /// Returned value is only valid if the parameter represent a texture from a + /// material ColorValue ColorFactor() const { return { - { // this agregate intialize the std::array object, and uses C++11 RVO. - number_array[0], - number_array[1], - number_array[2], - (number_array.size() > 3 ? number_array[3] : 1.0) - } - }; + {// this agregate intialize the std::array object, and uses C++11 RVO. + number_array[0], number_array[1], number_array[2], + (number_array.size() > 3 ? number_array[3] : 1.0)}}; } }; @@ -449,7 +444,8 @@ struct Image { int component; std::vector image; int bufferView; // (required if no uri) - std::string mimeType; // (required if no uri) ["image/jpeg", "image/png", "image/bmp", "image/gif"] + std::string mimeType; // (required if no uri) ["image/jpeg", "image/png", + // "image/bmp", "image/gif"] std::string uri; // (required if no mimeType) Value extras; @@ -513,7 +509,8 @@ struct Accessor { int ByteStride(const BufferView &bufferViewObject) const { if (bufferViewObject.byteStride == 0) { // Assume data is tightly packed. - int componentSizeInBytes = GetComponentSizeInBytes(static_cast(componentType)); + int componentSizeInBytes = + GetComponentSizeInBytes(static_cast(componentType)); if (componentSizeInBytes <= 0) { return -1; } @@ -525,8 +522,10 @@ struct Accessor { return componentSizeInBytes * typeSizeInBytes; } else { - // Check if byteStride is a mulple of the size of the accessor's component type. - int componentSizeInBytes = GetComponentSizeInBytes(static_cast(componentType)); + // Check if byteStride is a mulple of the size of the accessor's component + // type. + int componentSizeInBytes = + GetComponentSizeInBytes(static_cast(componentType)); if (componentSizeInBytes <= 0) { return -1; } @@ -651,7 +650,7 @@ class Node { std::vector weights; // The weights of the instantiated Morph Target Value extras; - ParameterMap extLightsValues; // KHR_lights_cmn extension + ParameterMap extLightsValues; // KHR_lights_cmn extension }; typedef struct { @@ -728,25 +727,24 @@ enum SectionCheck { /// /// LoadImageDataFunction type. Signature for custom image loading callbacks. /// -typedef bool (*LoadImageDataFunction)(Image *, std::string *, int, int, const unsigned char *, int, void *); +typedef bool (*LoadImageDataFunction)(Image *, std::string *, int, int, + const unsigned char *, int, void *); #ifndef TINYGLTF_NO_STB_IMAGE // Declaration of default image loader callback static bool LoadImageData(Image *image, std::string *err, int req_width, - int req_height, const unsigned char *bytes, - int size, void*); + int req_height, const unsigned char *bytes, int size, + void *); #endif class TinyGLTF { public: - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wc++98-compat" #endif - TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) { - } + TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) {} #ifdef __clang__ #pragma clang diagnostic pop @@ -828,7 +826,7 @@ class TinyGLTF { }; #ifdef __clang__ -#pragma clang diagnostic pop // -Wpadded +#pragma clang diagnostic pop // -Wpadded #endif } // namespace tinygltf @@ -897,7 +895,7 @@ class TinyGLTF { using nlohmann::json; #ifdef __APPLE__ - #include "TargetConditionals.h" +#include "TargetConditionals.h" #endif #ifdef __clang__ @@ -956,7 +954,8 @@ static std::string ExpandFilePath(const std::string &filepath) { return s; #else -#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || defined(__ANDROID__) +#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \ + defined(__ANDROID__) // no expansion std::string s = filepath; #else @@ -1029,6 +1028,11 @@ static std::string GetBaseDir(const std::string &filepath) { return ""; } +// https://stackoverflow.com/questions/8520560/get-a-file-name-from-a-path +std::string GetBaseFilename(const std::string &filepath) { + return filepath.substr(filepath.find_last_of("/\\") + 1); +} + // std::string base64_encode(unsigned char const* , unsigned int len); std::string base64_decode(std::string const &s); @@ -1188,14 +1192,14 @@ static bool LoadExternalFile(std::vector *out, std::string *err, } void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) { - LoadImageData = func; - load_image_user_data_ = user_data; + LoadImageData = func; + load_image_user_data_ = user_data; } #ifndef TINYGLTF_NO_STB_IMAGE static bool LoadImageData(Image *image, std::string *err, int req_width, - int req_height, const unsigned char *bytes, - int size, void*) { + int req_height, const unsigned char *bytes, int size, + void *) { int w, h, comp; // if image cannot be decoded, ignore parsing and keep it by its path // don't break in this case @@ -1268,12 +1272,12 @@ static bool IsDataURI(const std::string &in) { } header = "data:image/bmp;base64,"; - if(in.find(header) == 0) { + if (in.find(header) == 0) { return true; } header = "data:image/gif;base64,"; - if(in.find(header) == 0) { + if (in.find(header) == 0) { return true; } @@ -1401,8 +1405,7 @@ static bool ParseExtrasProperty(Value *ret, const json &o) { return true; } -static bool ParseBooleanProperty(bool *ret, std::string *err, - const json &o, +static bool ParseBooleanProperty(bool *ret, std::string *err, const json &o, const std::string &property, const bool required, const std::string &parent_node = "") { @@ -1436,8 +1439,7 @@ static bool ParseBooleanProperty(bool *ret, std::string *err, return true; } -static bool ParseNumberProperty(double *ret, std::string *err, - const json &o, +static bool ParseNumberProperty(double *ret, std::string *err, const json &o, const std::string &property, const bool required, const std::string &parent_node = "") { @@ -1472,8 +1474,8 @@ static bool ParseNumberProperty(double *ret, std::string *err, } static bool ParseNumberArrayProperty(std::vector *ret, std::string *err, - const json &o, - const std::string &property, bool required, + const json &o, const std::string &property, + bool required, const std::string &parent_node = "") { json::const_iterator it = o.find(property); if (it == o.end()) { @@ -1503,7 +1505,8 @@ static bool ParseNumberArrayProperty(std::vector *ret, std::string *err, } ret->clear(); - for (json::const_iterator i = it.value().begin(); i != it.value().end(); i++) { + for (json::const_iterator i = it.value().begin(); i != it.value().end(); + i++) { if (!i.value().is_number()) { if (required) { if (err) { @@ -1559,13 +1562,15 @@ static bool ParseStringProperty( static bool ParseStringIntProperty(std::map *ret, std::string *err, const json &o, - const std::string &property, bool required, const std::string &parent = "") { + const std::string &property, bool required, + const std::string &parent = "") { json::const_iterator it = o.find(property); if (it == o.end()) { if (required) { if (err) { if (!parent.empty()) { - (*err) += "'" + property + "' property is missing in " + parent + ".\n"; + (*err) += + "'" + property + "' property is missing in " + parent + ".\n"; } else { (*err) += "'" + property + "' property is missing.\n"; } @@ -1634,15 +1639,13 @@ static bool ParseJSONProperty(std::map *ret, json::const_iterator itEnd(obj.end()); for (; it2 != itEnd; it2++) { if (it2.value().is_number()) - ret->insert(std::pair(it2.key(), - it2.value())); + ret->insert(std::pair(it2.key(), it2.value())); } return true; } -static bool ParseAsset(Asset *asset, std::string *err, - const json &o) { +static bool ParseAsset(Asset *asset, std::string *err, const json &o) { ParseStringProperty(&asset->version, err, o, "version", true, "Asset"); ParseStringProperty(&asset->generator, err, o, "generator", false, "Asset"); ParseStringProperty(&asset->minVersion, err, o, "minVersion", false, "Asset"); @@ -1653,10 +1656,10 @@ static bool ParseAsset(Asset *asset, std::string *err, return true; } -static bool ParseImage(Image *image, std::string *err, - const json &o, const std::string &basedir, - bool is_binary, const unsigned char *bin_data, - size_t bin_size, LoadImageDataFunction* LoadImageData = nullptr, +static bool ParseImage(Image *image, std::string *err, const json &o, + const std::string &basedir, bool is_binary, + const unsigned char *bin_data, size_t bin_size, + LoadImageDataFunction *LoadImageData = nullptr, void *user_data = nullptr) { // A glTF image must either reference a bufferView or an image uri double bufferView = -1; @@ -1697,7 +1700,8 @@ static bool ParseImage(Image *image, std::string *err, } double buffer_view = -1.0; - if (!ParseNumberProperty(&buffer_view, err, o, "bufferView", true, "Image")) { + if (!ParseNumberProperty(&buffer_view, err, o, "bufferView", true, + "Image")) { return false; } @@ -1756,11 +1760,10 @@ static bool ParseImage(Image *image, std::string *err, return false; } return (*LoadImageData)(image, err, 0, 0, &img.at(0), - static_cast(img.size()), user_data); + static_cast(img.size()), user_data); } -static bool ParseTexture(Texture *texture, std::string *err, - const json &o, +static bool ParseTexture(Texture *texture, std::string *err, const json &o, const std::string &basedir) { (void)basedir; double sampler = -1.0; @@ -1775,9 +1778,8 @@ static bool ParseTexture(Texture *texture, std::string *err, return true; } -static bool ParseBuffer(Buffer *buffer, std::string *err, - const json &o, const std::string &basedir, - bool is_binary = false, +static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o, + const std::string &basedir, bool is_binary = false, const unsigned char *bin_data = nullptr, size_t bin_size = 0) { double byteLength; @@ -1849,7 +1851,8 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, } } else { // Assume external .bin file. - if (!LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes, true)) { + if (!LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes, + true)) { return false; } } @@ -1922,8 +1925,7 @@ static bool ParseBufferView(BufferView *bufferView, std::string *err, return true; } -static bool ParseAccessor(Accessor *accessor, std::string *err, - const json &o) { +static bool ParseAccessor(Accessor *accessor, std::string *err, const json &o) { double bufferView = -1.0; if (!ParseNumberProperty(&bufferView, err, o, "bufferView", true, "Accessor")) { @@ -2032,9 +2034,9 @@ static bool ParsePrimitive(Primitive *primitive, std::string *err, // Look for morph targets json::const_iterator targetsObject = o.find("targets"); - if ((targetsObject != o.end()) && - targetsObject.value().is_array()) { - for (json::const_iterator i = targetsObject.value().begin(); i != targetsObject.value().end(); i++) { + if ((targetsObject != o.end()) && targetsObject.value().is_array()) { + for (json::const_iterator i = targetsObject.value().begin(); + i != targetsObject.value().end(); i++) { std::map targetAttribues; const json &dict = i.value(); @@ -2042,8 +2044,7 @@ static bool ParsePrimitive(Primitive *primitive, std::string *err, json::const_iterator dictItEnd(dict.end()); for (; dictIt != dictItEnd; ++dictIt) { - targetAttribues[dictIt.key()] = - static_cast(dictIt.value()); + targetAttribues[dictIt.key()] = static_cast(dictIt.value()); } primitive->targets.push_back(targetAttribues); } @@ -2060,10 +2061,10 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) { mesh->primitives.clear(); json::const_iterator primObject = o.find("primitives"); if ((primObject != o.end()) && primObject.value().is_array()) { - for (json::const_iterator i = primObject.value().begin(); i != primObject.value().end(); i++) { + for (json::const_iterator i = primObject.value().begin(); + i != primObject.value().end(); i++) { Primitive primitive; - if (ParsePrimitive(&primitive, err, - i.value())) { + if (ParsePrimitive(&primitive, err, i.value())) { // Only add the primitive if the parsing succeeds. mesh->primitives.push_back(primitive); } @@ -2072,9 +2073,9 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) { // Look for morph targets json::const_iterator targetsObject = o.find("targets"); - if ((targetsObject != o.end()) && - targetsObject.value().is_array()) { - for (json::const_iterator i = targetsObject.value().begin(); i != targetsObject.value().end(); i++) { + if ((targetsObject != o.end()) && targetsObject.value().is_array()) { + for (json::const_iterator i = targetsObject.value().begin(); + i != targetsObject.value().end(); i++) { std::map targetAttribues; const json &dict = i.value(); @@ -2082,8 +2083,7 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) { json::const_iterator dictItEnd(dict.end()); for (; dictIt != dictItEnd; ++dictIt) { - targetAttribues[dictIt.key()] = - static_cast(dictIt.value()); + targetAttribues[dictIt.key()] = static_cast(dictIt.value()); } mesh->targets.push_back(targetAttribues); } @@ -2098,8 +2098,8 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) { } static bool ParseParameterProperty(Parameter *param, std::string *err, - const json &o, - const std::string &prop, bool required) { + const json &o, const std::string &prop, + bool required) { double num_val; // A parameter value can either be a string or an array of either a boolean or @@ -2163,17 +2163,16 @@ static bool ParseNode(Node *node, std::string *err, const json &o) { node->children.clear(); json::const_iterator childrenObject = o.find("children"); - if ((childrenObject != o.end()) && - childrenObject.value().is_array()) { - for (json::const_iterator i = childrenObject.value().begin(); i != childrenObject.value().end(); i++) { + if ((childrenObject != o.end()) && childrenObject.value().is_array()) { + for (json::const_iterator i = childrenObject.value().begin(); + i != childrenObject.value().end(); i++) { if (!i.value().is_number()) { if (err) { (*err) += "Invalid `children` array.\n"; } return false; } - const int &childrenNode = - static_cast(i.value()); + const int &childrenNode = static_cast(i.value()); node->children.push_back(childrenNode); } } @@ -2181,27 +2180,23 @@ static bool ParseNode(Node *node, std::string *err, const json &o) { ParseExtrasProperty(&(node->extras), o); json::const_iterator extensions_object = o.find("extensions"); - if ((extensions_object != o.end()) && - extensions_object.value().is_object()) { - const json &ext_values_object = - extensions_object.value(); + if ((extensions_object != o.end()) && extensions_object.value().is_object()) { + const json &ext_values_object = extensions_object.value(); json::const_iterator it(ext_values_object.begin()); json::const_iterator itEnd(ext_values_object.end()); for (; it != itEnd; it++) { - if ((it.key().compare("KHR_lights_cmn") == 0) && - it.value().is_object()) { - const json &light_values_object = - it.value(); + if ((it.key().compare("KHR_lights_cmn") == 0) && it.value().is_object()) { + const json &light_values_object = it.value(); json::const_iterator itVal(light_values_object.begin()); json::const_iterator itValEnd(light_values_object.end()); for (; itVal != itValEnd; itVal++) { Parameter param; - if (ParseParameterProperty(¶m, err, light_values_object, itVal.key(), - false)) { + if (ParseParameterProperty(¶m, err, light_values_object, + itVal.key(), false)) { node->extLightsValues[itVal.key()] = param; } } @@ -2212,8 +2207,7 @@ static bool ParseNode(Node *node, std::string *err, const json &o) { return true; } -static bool ParseMaterial(Material *material, std::string *err, - const json &o) { +static bool ParseMaterial(Material *material, std::string *err, const json &o) { material->values.clear(); material->extPBRValues.clear(); material->additionalValues.clear(); @@ -2224,8 +2218,7 @@ static bool ParseMaterial(Material *material, std::string *err, for (; it != itEnd; it++) { if (it.key() == "pbrMetallicRoughness") { if (it.value().is_object()) { - const json &values_object = - it.value(); + const json &values_object = it.value(); json::const_iterator itVal(values_object.begin()); json::const_iterator itValEnd(values_object.end()); @@ -2240,14 +2233,12 @@ static bool ParseMaterial(Material *material, std::string *err, } } else if (it.key() == "extensions") { if (it.value().is_object()) { - const json &extension = - it.value(); + const json &extension = it.value(); json::const_iterator extIt = extension.begin(); if (!extIt.value().is_object()) continue; - const json &values_object = - extIt.value(); + const json &values_object = extIt.value(); json::const_iterator itVal(values_object.begin()); json::const_iterator itValEnd(values_object.end()); @@ -2277,7 +2268,8 @@ static bool ParseAnimationChannel(AnimationChannel *channel, std::string *err, const json &o) { double samplerIndex = -1.0; double targetIndex = -1.0; - if (!ParseNumberProperty(&samplerIndex, err, o, "sampler", true, "AnimationChannel")) { + if (!ParseNumberProperty(&samplerIndex, err, o, "sampler", true, + "AnimationChannel")) { if (err) { (*err) += "`sampler` field is missing in animation channels\n"; } @@ -2286,8 +2278,7 @@ static bool ParseAnimationChannel(AnimationChannel *channel, std::string *err, json::const_iterator targetIt = o.find("target"); if ((targetIt != o.end()) && targetIt.value().is_object()) { - const json &target_object = - targetIt.value(); + const json &target_object = targetIt.value(); if (!ParseNumberProperty(&targetIndex, err, target_object, "node", true)) { if (err) { @@ -2318,10 +2309,10 @@ static bool ParseAnimation(Animation *animation, std::string *err, { json::const_iterator channelsIt = o.find("channels"); if ((channelsIt != o.end()) && channelsIt.value().is_array()) { - for (json::const_iterator i = channelsIt.value().begin(); i != channelsIt.value().end(); i++) { + for (json::const_iterator i = channelsIt.value().begin(); + i != channelsIt.value().end(); i++) { AnimationChannel channel; - if (ParseAnimationChannel(&channel, err, - i.value())) { + if (ParseAnimationChannel(&channel, err, i.value())) { // Only add the channel if the parsing succeeds. animation->channels.push_back(channel); } @@ -2332,8 +2323,7 @@ static bool ParseAnimation(Animation *animation, std::string *err, { json::const_iterator samplerIt = o.find("samplers"); if ((samplerIt != o.end()) && samplerIt.value().is_array()) { - const json &sampler_array = - samplerIt.value(); + const json &sampler_array = samplerIt.value(); json::const_iterator it = sampler_array.begin(); json::const_iterator itEnd = sampler_array.end(); @@ -2377,8 +2367,7 @@ static bool ParseAnimation(Animation *animation, std::string *err, return true; } -static bool ParseSampler(Sampler *sampler, std::string *err, - const json &o) { +static bool ParseSampler(Sampler *sampler, std::string *err, const json &o) { ParseStringProperty(&sampler->name, err, o, "name", false); double minFilter = @@ -2458,8 +2447,7 @@ static bool ParsePerspectiveCamera(PerspectiveCamera *camera, std::string *err, } static bool ParseOrthographicCamera(OrthographicCamera *camera, - std::string *err, - const json &o) { + std::string *err, const json &o) { double xmag = 0.0; if (!ParseNumberProperty(&xmag, err, o, "xmag", true, "OrthographicCamera")) { return false; @@ -2493,8 +2481,7 @@ static bool ParseOrthographicCamera(OrthographicCamera *camera, return true; } -static bool ParseCamera(Camera *camera, std::string *err, - const json &o) { +static bool ParseCamera(Camera *camera, std::string *err, const json &o) { if (!ParseStringProperty(&camera->type, err, o, "type", true, "Camera")) { return false; } @@ -2519,8 +2506,7 @@ static bool ParseCamera(Camera *camera, std::string *err, return false; } - if (!ParseOrthographicCamera(&camera->orthographic, err, - v.get())) { + if (!ParseOrthographicCamera(&camera->orthographic, err, v.get())) { return false; } } else if (camera->type.compare("perspective") == 0) { @@ -2543,8 +2529,7 @@ static bool ParseCamera(Camera *camera, std::string *err, return false; } - if (!ParsePerspectiveCamera(&camera->perspective, err, - v.get())) { + if (!ParsePerspectiveCamera(&camera->perspective, err, v.get())) { return false; } } else { @@ -2576,7 +2561,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, json v; -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(TINYGLTF_NOEXCEPTION) +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \ + defined(_CPPUNWIND)) && \ + not defined(TINYGLTF_NOEXCEPTION) try { v = json::parse(str, str + length); @@ -2588,7 +2575,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, } #else { - v = json::parse(str, str + length, nullptr, /* exception */false); + v = json::parse(str, str + length, nullptr, /* exception */ false); if (!v.is_object()) { // Assume parsing was failed. @@ -2728,8 +2715,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, return false; } Buffer buffer; - if (!ParseBuffer(&buffer, err, it->get(), base_dir, - is_binary_, bin_data_, bin_size_)) { + if (!ParseBuffer(&buffer, err, it->get(), base_dir, is_binary_, + bin_data_, bin_size_)) { return false; } @@ -2844,7 +2831,6 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, if ((rootIt != v.end()) && rootIt.value().is_array()) { const json &root = rootIt.value(); - json::const_iterator it(root.begin()); json::const_iterator itEnd(root.end()); for (; it != itEnd; it++) { @@ -2928,8 +2914,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, return false; } Image image; - if (!ParseImage(&image, err, it.value(), base_dir, - is_binary_, bin_data_, bin_size_, &this->LoadImageData, load_image_user_data_)) { + if (!ParseImage(&image, err, it.value(), base_dir, is_binary_, + bin_data_, bin_size_, &this->LoadImageData, + load_image_user_data_)) { return false; } @@ -2957,7 +2944,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, } bool ret = LoadImageData(&image, err, image.width, image.height, &buffer.data[bufferView.byteOffset], - static_cast(bufferView.byteLength), load_image_user_data_); + static_cast(bufferView.byteLength), + load_image_user_data_); if (!ret) { return false; } @@ -3103,7 +3091,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, json::const_iterator itEnd(root.end()); for (; it != itEnd; ++it) { // parse KHR_lights_cmn extension - if ((it.key().compare("KHR_lights_cmn") == 0) && it.value().is_object()) { + if ((it.key().compare("KHR_lights_cmn") == 0) && + it.value().is_object()) { const json &object = it.value(); json::const_iterator itLight(object.find("lights")); json::const_iterator itLightEnd(object.end()); @@ -3282,14 +3271,15 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err, // GLTF Serialization /////////////////////// -//typedef std::pair json_object_pair; +// typedef std::pair json_object_pair; template static void SerializeNumberProperty(const std::string &key, T number, json &obj) { - //obj.insert( + // obj.insert( // json_object_pair(key, json(static_cast(number)))); - obj[key] = static_cast(number); + // obj[key] = static_cast(number); + obj[key] = number; } template @@ -3307,8 +3297,7 @@ static void SerializeNumberArrayProperty(const std::string &key, } static void SerializeStringProperty(const std::string &key, - const std::string &value, - json &obj) { + const std::string &value, json &obj) { obj[key] = value; } @@ -3341,8 +3330,7 @@ static void SerializeValue(const std::string &key, const Value &value, for (unsigned int i = 0; i < valueKeys.size(); ++i) { Value elementValue = value.Get(valueKeys[i]); if (elementValue.IsInt()) - jsonValue[valueKeys[i]] = - static_cast(elementValue.Get()); + jsonValue[valueKeys[i]] = static_cast(elementValue.Get()); } obj[key] = jsonValue; @@ -3350,8 +3338,8 @@ static void SerializeValue(const std::string &key, const Value &value, } static void SerializeGltfBufferData(const std::vector &data, - const std::string &binFilePath) { - std::ofstream output(binFilePath.c_str(), std::ofstream::binary); + const std::string &binFilename) { + std::ofstream output(binFilename.c_str(), std::ofstream::binary); output.write(reinterpret_cast(&data[0]), std::streamsize(data.size())); output.close(); @@ -3419,8 +3407,7 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) { SerializeStringProperty("type", type, o); } -static void SerializeGltfAnimationChannel(AnimationChannel &channel, - json &o) { +static void SerializeGltfAnimationChannel(AnimationChannel &channel, json &o) { SerializeNumberProperty("sampler", channel.sampler, o); json target; SerializeNumberProperty("node", channel.target_node, target); @@ -3429,8 +3416,7 @@ static void SerializeGltfAnimationChannel(AnimationChannel &channel, o["target"] = target; } -static void SerializeGltfAnimationSampler(AnimationSampler &sampler, - json &o) { +static void SerializeGltfAnimationSampler(AnimationSampler &sampler, json &o) { SerializeNumberProperty("input", sampler.input, o); SerializeNumberProperty("output", sampler.output, o); SerializeStringProperty("interpolation", sampler.interpolation, o); @@ -3473,16 +3459,16 @@ static void SerializeGltfAsset(Asset &asset, json &o) { } static void SerializeGltfBuffer(Buffer &buffer, json &o, - const std::string &binFilePath) { - SerializeGltfBufferData(buffer.data, binFilePath); + const std::string &binFilename, + const std::string &binBaseFilename) { + SerializeGltfBufferData(buffer.data, binFilename); SerializeNumberProperty("byteLength", buffer.data.size(), o); - SerializeStringProperty("uri", binFilePath, o); + SerializeStringProperty("uri", binBaseFilename, o); if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o); } -static void SerializeGltfBufferView(BufferView &bufferView, - json &o) { +static void SerializeGltfBufferView(BufferView &bufferView, json &o) { SerializeNumberProperty("buffer", bufferView.buffer, o); SerializeNumberProperty("byteLength", bufferView.byteLength, o); SerializeNumberProperty("byteStride", bufferView.byteStride, o); @@ -3613,7 +3599,6 @@ static void SerializeGltfNode(Node &node, json &o) { o["extensions"] = lightsExt; } - SerializeStringProperty("name", node.name, o); SerializeNumberArrayProperty("children", node.children, o); } @@ -3734,21 +3719,27 @@ bool TinyGLTF::WriteGltfSceneToFile( SerializeGltfAsset(model->asset, asset); output["asset"] = asset; - std::string binFilePath = filename; + std::string binFilename = GetBaseFilename(filename); std::string ext = ".bin"; - std::string::size_type pos = binFilePath.rfind('.', binFilePath.length()); + std::string::size_type pos = binFilename.rfind('.', binFilename.length()); if (pos != std::string::npos) { - binFilePath = binFilePath.substr(0, pos) + ext; + binFilename = binFilename.substr(0, pos) + ext; } else { - binFilePath = "./" + binFilePath + ".bin"; + binFilename = binFilename + ".bin"; } + std::string binSaveFilePath = GetBaseDir(filename); + if (binSaveFilePath.empty()) { + binSaveFilePath = "./"; + } + + binSaveFilePath = JoinPath(binSaveFilePath, binFilename); // BUFFERS (We expect only one buffer here) json buffers; for (unsigned int i = 0; i < model->buffers.size(); ++i) { json buffer; - SerializeGltfBuffer(model->buffers[i], buffer, binFilePath); + SerializeGltfBuffer(model->buffers[i], buffer, binSaveFilePath, binFilename); buffers.push_back(buffer); } output["buffers"] = buffers;