Merge branch '16bit-lodepng'
diff --git a/README.md b/README.md
index dc33e8c..0bd6fbc 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
 
 ## Status
 
-v2.2.0 release(Support loading 16bit PNG)
+v2.2.0 release(Support loading 16bit PNG. Sparse accessor support)
 v2.1.0 release(Draco support)
 v2.0.0 release(22 Aug, 2018)!
 
@@ -45,7 +45,9 @@
   * [x] Load BMP
   * [x] Load GIF
   * [x] Custom Image decoder callback(e.g. for decoding OpenEXR image)
-* Load from memory
+* Morph traget
+  * [x] Sparse accessor
+* Load glTF from memory
 * Custom callback handler
   * [x] Image load
   * [x] Image save
@@ -71,15 +73,13 @@
 * [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing.
 * [ ] Mesh Compression/decompression(Open3DGC, etc)
   * [x] Load Draco compressed mesh
-  * [x] Save Draco compressed mesh
+  * [ ] Save Draco compressed mesh
   * [ ] Open3DGC?
 * [ ] Support `extensions` and `extras` property
 * [ ] HDR image?
   * [ ] OpenEXR extension through TinyEXR.
 * [ ] 16bit PNG support in Serialization
 * [ ] Write example and tests for `animation` and `skin`
-  * [ ] Skinning
-  * [ ] Morph targets
 
 ## Licenses
 
@@ -139,6 +139,10 @@
 * `TINYGLTF_NO_EXTERNAL_IMAGE` : Do not try to load external image file. This option woulde be helpful if you do not want load image file during glTF parsing.
 * `TINYGLTF_ANDROID_LOAD_FROM_ASSETS`: Load all files from packaged app assets instead of the regular file system. **Note:** You must pass a valid asset manager from your android app to `tinygltf::asset_manager` beforehand.
 * `TINYGLTF_ENABLE_DRACO`: Enable Draco compression. User must provide include path and link correspnding libraries in your project file.
+* `TINYGLTF_NO_INCLUDE_JSON `: Disable including `json.hpp` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
+* `TINYGLTF_NO_INCLUDE_STB_IMAGE `: Disable including `stb_image.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
+* `TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE `: Disable including `stb_image_write.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
+
 
 ### Saving gltTF 2.0 model
 * [ ] Buffers.
diff --git a/examples/glview/glview.cc b/examples/glview/glview.cc
index b2a3d70..375b556 100644
--- a/examples/glview/glview.cc
+++ b/examples/glview/glview.cc
@@ -28,7 +28,6 @@
 #include "tiny_gltf.h"
 #endif
 
-
 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
 
 #define CheckGLErrors(desc)                                                   \
@@ -55,7 +54,9 @@
 
 GLFWwindow *window;
 
-typedef struct { GLuint vb; } GLBufferState;
+typedef struct {
+  GLuint vb;
+} GLBufferState;
 
 typedef struct {
   std::vector<GLuint> diffuseTex;  // for each primitive in mesh
@@ -254,6 +255,26 @@
   prevMouseY = mouse_y;
 }
 
+static size_t ComponentTypeByteSize(int type) {
+  switch (type) {
+    case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
+    case TINYGLTF_COMPONENT_TYPE_BYTE:
+      return sizeof(char);
+    case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
+    case TINYGLTF_COMPONENT_TYPE_SHORT:
+      return sizeof(short);
+    case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
+    case TINYGLTF_COMPONENT_TYPE_INT:
+      return sizeof(int);
+    case TINYGLTF_COMPONENT_TYPE_FLOAT:
+      return sizeof(float);
+    case TINYGLTF_COMPONENT_TYPE_DOUBLE:
+      return sizeof(double);
+    default:
+      return 0;
+  }
+}
+
 static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
   // Buffer
   {
@@ -264,14 +285,117 @@
         continue;  // Unsupported bufferView.
       }
 
+      int sparse_accessor = -1;
+      for (size_t a_i = 0; a_i < model.accessors.size(); ++a_i) {
+        const auto &accessor = model.accessors[a_i];
+        if (accessor.bufferView == i) {
+          std::cout << i << " is used by accessor " << a_i << std::endl;
+          if (accessor.sparse.isSparse) {
+            std::cout
+                << "WARN: this bufferView has at least one sparse accessor to "
+                   "it. We are going to load the data as patched by this "
+                   "sparse accessor, not the original data"
+                << std::endl;
+            sparse_accessor = a_i;
+            break;
+          }
+        }
+      }
+
       const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
       GLBufferState state;
       glGenBuffers(1, &state.vb);
       glBindBuffer(bufferView.target, state.vb);
       std::cout << "buffer.size= " << buffer.data.size()
                 << ", byteOffset = " << bufferView.byteOffset << std::endl;
-      glBufferData(bufferView.target, bufferView.byteLength,
-                   &buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
+
+      if (sparse_accessor < 0)
+        glBufferData(bufferView.target, bufferView.byteLength,
+                     &buffer.data.at(0) + bufferView.byteOffset,
+                     GL_STATIC_DRAW);
+      else {
+        const auto accessor = model.accessors[sparse_accessor];
+        // copy the buffer to a temporary one for sparse patching
+        unsigned char *tmp_buffer = new unsigned char[bufferView.byteLength];
+        memcpy(tmp_buffer, buffer.data.data() + bufferView.byteOffset,
+               bufferView.byteLength);
+
+        const size_t size_of_object_in_buffer =
+            ComponentTypeByteSize(accessor.componentType);
+        const size_t size_of_sparse_indices =
+            ComponentTypeByteSize(accessor.sparse.indices.componentType);
+
+        const auto &indices_buffer_view =
+            model.bufferViews[accessor.sparse.indices.bufferView];
+        const auto &indices_buffer = model.buffers[indices_buffer_view.buffer];
+
+        const auto &values_buffer_view =
+            model.bufferViews[accessor.sparse.values.bufferView];
+        const auto &values_buffer = model.buffers[values_buffer_view.buffer];
+
+        for (size_t sparse_index = 0; sparse_index < accessor.sparse.count;
+             ++sparse_index) {
+          int index = 0;
+          // std::cout << "accessor.sparse.indices.componentType = " <<
+          // accessor.sparse.indices.componentType << std::endl;
+          switch (accessor.sparse.indices.componentType) {
+            case TINYGLTF_COMPONENT_TYPE_BYTE:
+            case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
+              index = (int)*(
+                  unsigned char *)(indices_buffer.data.data() +
+                                   indices_buffer_view.byteOffset +
+                                   accessor.sparse.indices.byteOffset +
+                                   (sparse_index * size_of_sparse_indices));
+              break;
+            case TINYGLTF_COMPONENT_TYPE_SHORT:
+            case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
+              index = (int)*(
+                  unsigned short *)(indices_buffer.data.data() +
+                                    indices_buffer_view.byteOffset +
+                                    accessor.sparse.indices.byteOffset +
+                                    (sparse_index * size_of_sparse_indices));
+              break;
+            case TINYGLTF_COMPONENT_TYPE_INT:
+            case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
+              index = (int)*(
+                  unsigned int *)(indices_buffer.data.data() +
+                                  indices_buffer_view.byteOffset +
+                                  accessor.sparse.indices.byteOffset +
+                                  (sparse_index * size_of_sparse_indices));
+              break;
+          }
+          std::cout << "updating sparse data at index  : " << index
+                    << std::endl;
+          // index is now the target of the sparse index to patch in
+          const unsigned char *read_from =
+              values_buffer.data.data() +
+              (values_buffer_view.byteOffset +
+               accessor.sparse.values.byteOffset) +
+              (sparse_index * (size_of_object_in_buffer * accessor.type));
+
+          /*
+          std::cout << ((float*)read_from)[0] << "\n";
+          std::cout << ((float*)read_from)[1] << "\n";
+          std::cout << ((float*)read_from)[2] << "\n";
+          */
+
+          unsigned char *write_to =
+              tmp_buffer + index * (size_of_object_in_buffer * accessor.type);
+
+          memcpy(write_to, read_from, size_of_object_in_buffer * accessor.type);
+        }
+
+        // debug:
+        /*for(size_t p = 0; p < bufferView.byteLength/sizeof(float); p++)
+        {
+          float* b = (float*)tmp_buffer;
+          std::cout << "modified_buffer [" << p << "] = " << b[p] << '\n';
+        }*/
+
+        glBufferData(bufferView.target, bufferView.byteLength, tmp_buffer,
+                     GL_STATIC_DRAW);
+        delete[] tmp_buffer;
+      }
       glBindBuffer(bufferView.target, 0);
 
       gBufferState[i] = state;
@@ -279,55 +403,55 @@
   }
 
 #if 0  // TODO(syoyo): Implement
-  // Texture
-  {
-    for (size_t i = 0; i < model.meshes.size(); i++) {
-      const tinygltf::Mesh &mesh = model.meshes[i];
+	// Texture
+	{
+		for (size_t i = 0; i < model.meshes.size(); i++) {
+			const tinygltf::Mesh &mesh = model.meshes[i];
 
-      gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
-      for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
-        const tinygltf::Primitive &primitive = mesh.primitives[primId];
+			gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
+			for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
+				const tinygltf::Primitive &primitive = mesh.primitives[primId];
 
-        gMeshState[mesh.name].diffuseTex[primId] = 0;
+				gMeshState[mesh.name].diffuseTex[primId] = 0;
 
-        if (primitive.material < 0) {
-          continue;
-        }
-        tinygltf::Material &mat = model.materials[primitive.material];
-        // printf("material.name = %s\n", mat.name.c_str());
-        if (mat.values.find("diffuse") != mat.values.end()) {
-          std::string diffuseTexName = mat.values["diffuse"].string_value;
-          if (model.textures.find(diffuseTexName) != model.textures.end()) {
-            tinygltf::Texture &tex = model.textures[diffuseTexName];
-            if (scene.images.find(tex.source) != model.images.end()) {
-              tinygltf::Image &image = model.images[tex.source];
-              GLuint texId;
-              glGenTextures(1, &texId);
-              glBindTexture(tex.target, texId);
-              glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-              glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-              glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+				if (primitive.material < 0) {
+					continue;
+				}
+				tinygltf::Material &mat = model.materials[primitive.material];
+				// printf("material.name = %s\n", mat.name.c_str());
+				if (mat.values.find("diffuse") != mat.values.end()) {
+					std::string diffuseTexName = mat.values["diffuse"].string_value;
+					if (model.textures.find(diffuseTexName) != model.textures.end()) {
+						tinygltf::Texture &tex = model.textures[diffuseTexName];
+						if (scene.images.find(tex.source) != model.images.end()) {
+							tinygltf::Image &image = model.images[tex.source];
+							GLuint texId;
+							glGenTextures(1, &texId);
+							glBindTexture(tex.target, texId);
+							glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+							glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+							glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-              // Ignore Texture.fomat.
-              GLenum format = GL_RGBA;
-              if (image.component == 3) {
-                format = GL_RGB;
-              }
-              glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
-                           image.height, 0, format, tex.type,
-                           &image.image.at(0));
+							// Ignore Texture.fomat.
+							GLenum format = GL_RGBA;
+							if (image.component == 3) {
+								format = GL_RGB;
+							}
+							glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
+									image.height, 0, format, tex.type,
+									&image.image.at(0));
 
-              CheckErrors("texImage2D");
-              glBindTexture(tex.target, 0);
+							CheckErrors("texImage2D");
+							glBindTexture(tex.target, 0);
 
-              printf("TexId = %d\n", texId);
-              gMeshState[mesh.name].diffuseTex[primId] = texId;
-            }
-          }
-        }
-      }
-    }
-  }
+							printf("TexId = %d\n", texId);
+							gMeshState[mesh.name].diffuseTex[primId] = texId;
+						}
+					}
+				}
+			}
+		}
+	}
 #endif
 
   glUseProgram(progId);
@@ -348,164 +472,164 @@
 #if 0  // TODO(syoyo): Implement
 // Setup curves geometry extension
 static void SetupCurvesState(tinygltf::Scene &scene, GLuint progId) {
-  // Find curves primitive.
-  {
-    std::map<std::string, tinygltf::Mesh>::const_iterator it(
-        scene.meshes.begin());
-    std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(
-        scene.meshes.end());
+	// Find curves primitive.
+	{
+		std::map<std::string, tinygltf::Mesh>::const_iterator it(
+				scene.meshes.begin());
+		std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(
+				scene.meshes.end());
 
-    for (; it != itEnd; it++) {
-      const tinygltf::Mesh &mesh = it->second;
+		for (; it != itEnd; it++) {
+			const tinygltf::Mesh &mesh = it->second;
 
-      // Currently we only support one primitive per mesh.
-      if (mesh.primitives.size() > 1) {
-        continue;
-      }
+			// Currently we only support one primitive per mesh.
+			if (mesh.primitives.size() > 1) {
+				continue;
+			}
 
-      for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
-        const tinygltf::Primitive &primitive = mesh.primitives[primId];
+			for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
+				const tinygltf::Primitive &primitive = mesh.primitives[primId];
 
-        gMeshState[mesh.name].diffuseTex[primId] = 0;
+				gMeshState[mesh.name].diffuseTex[primId] = 0;
 
-        if (primitive.material.empty()) {
-          continue;
-        }
+				if (primitive.material.empty()) {
+					continue;
+				}
 
-        bool has_curves = false;
-        if (primitive.extras.IsObject()) {
-          if (primitive.extras.Has("ext_mode")) {
-            const tinygltf::Value::Object &o =
-                primitive.extras.Get<tinygltf::Value::Object>();
-            const tinygltf::Value &ext_mode = o.find("ext_mode")->second;
+				bool has_curves = false;
+				if (primitive.extras.IsObject()) {
+					if (primitive.extras.Has("ext_mode")) {
+						const tinygltf::Value::Object &o =
+							primitive.extras.Get<tinygltf::Value::Object>();
+						const tinygltf::Value &ext_mode = o.find("ext_mode")->second;
 
-            if (ext_mode.IsString()) {
-              const std::string &str = ext_mode.Get<std::string>();
-              if (str.compare("curves") == 0) {
-                has_curves = true;
-              }
-            }
-          }
-        }
+						if (ext_mode.IsString()) {
+							const std::string &str = ext_mode.Get<std::string>();
+							if (str.compare("curves") == 0) {
+								has_curves = true;
+							}
+						}
+					}
+				}
 
-        if (!has_curves) {
-          continue;
-        }
+				if (!has_curves) {
+					continue;
+				}
 
-        // Construct curves buffer
-        const tinygltf::Accessor &vtx_accessor =
-            scene.accessors[primitive.attributes.find("POSITION")->second];
-        const tinygltf::Accessor &nverts_accessor =
-            scene.accessors[primitive.attributes.find("NVERTS")->second];
-        const tinygltf::BufferView &vtx_bufferView =
-            scene.bufferViews[vtx_accessor.bufferView];
-        const tinygltf::BufferView &nverts_bufferView =
-            scene.bufferViews[nverts_accessor.bufferView];
-        const tinygltf::Buffer &vtx_buffer =
-            scene.buffers[vtx_bufferView.buffer];
-        const tinygltf::Buffer &nverts_buffer =
-            scene.buffers[nverts_bufferView.buffer];
+				// Construct curves buffer
+				const tinygltf::Accessor &vtx_accessor =
+					scene.accessors[primitive.attributes.find("POSITION")->second];
+				const tinygltf::Accessor &nverts_accessor =
+					scene.accessors[primitive.attributes.find("NVERTS")->second];
+				const tinygltf::BufferView &vtx_bufferView =
+					scene.bufferViews[vtx_accessor.bufferView];
+				const tinygltf::BufferView &nverts_bufferView =
+					scene.bufferViews[nverts_accessor.bufferView];
+				const tinygltf::Buffer &vtx_buffer =
+					scene.buffers[vtx_bufferView.buffer];
+				const tinygltf::Buffer &nverts_buffer =
+					scene.buffers[nverts_bufferView.buffer];
 
-        // std::cout << "vtx_bufferView = " << vtx_accessor.bufferView <<
-        // std::endl;
-        // std::cout << "nverts_bufferView = " << nverts_accessor.bufferView <<
-        // std::endl;
-        // std::cout << "vtx_buffer.size = " << vtx_buffer.data.size() <<
-        // std::endl;
-        // std::cout << "nverts_buffer.size = " << nverts_buffer.data.size() <<
-        // std::endl;
+				// std::cout << "vtx_bufferView = " << vtx_accessor.bufferView <<
+				// std::endl;
+				// std::cout << "nverts_bufferView = " << nverts_accessor.bufferView <<
+				// std::endl;
+				// std::cout << "vtx_buffer.size = " << vtx_buffer.data.size() <<
+				// std::endl;
+				// std::cout << "nverts_buffer.size = " << nverts_buffer.data.size() <<
+				// std::endl;
 
-        const int *nverts =
-            reinterpret_cast<const int *>(nverts_buffer.data.data());
-        const float *vtx =
-            reinterpret_cast<const float *>(vtx_buffer.data.data());
+				const int *nverts =
+					reinterpret_cast<const int *>(nverts_buffer.data.data());
+				const float *vtx =
+					reinterpret_cast<const float *>(vtx_buffer.data.data());
 
-        // Convert to GL_LINES data.
-        std::vector<float> line_pts;
-        size_t vtx_offset = 0;
-        for (int k = 0; k < static_cast<int>(nverts_accessor.count); k++) {
-          for (int n = 0; n < nverts[k] - 1; n++) {
+				// Convert to GL_LINES data.
+				std::vector<float> line_pts;
+				size_t vtx_offset = 0;
+				for (int k = 0; k < static_cast<int>(nverts_accessor.count); k++) {
+					for (int n = 0; n < nverts[k] - 1; n++) {
 
-            line_pts.push_back(vtx[3 * (vtx_offset + n) + 0]);
-            line_pts.push_back(vtx[3 * (vtx_offset + n) + 1]);
-            line_pts.push_back(vtx[3 * (vtx_offset + n) + 2]);
+						line_pts.push_back(vtx[3 * (vtx_offset + n) + 0]);
+						line_pts.push_back(vtx[3 * (vtx_offset + n) + 1]);
+						line_pts.push_back(vtx[3 * (vtx_offset + n) + 2]);
 
-            line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 0]);
-            line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 1]);
-            line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 2]);
+						line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 0]);
+						line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 1]);
+						line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 2]);
 
-            // std::cout << "p0 " << vtx[3 * (vtx_offset + n) + 0] << ", "
-            //                  << vtx[3 * (vtx_offset + n) + 1] << ", "
-            //                  << vtx[3 * (vtx_offset + n) + 2] << std::endl;
+						// std::cout << "p0 " << vtx[3 * (vtx_offset + n) + 0] << ", "
+						//                  << vtx[3 * (vtx_offset + n) + 1] << ", "
+						//                  << vtx[3 * (vtx_offset + n) + 2] << std::endl;
 
-            // std::cout << "p1 " << vtx[3 * (vtx_offset + n+1) + 0] << ", "
-            //                  << vtx[3 * (vtx_offset + n+1) + 1] << ", "
-            //                  << vtx[3 * (vtx_offset + n+1) + 2] << std::endl;
-          }
+						// std::cout << "p1 " << vtx[3 * (vtx_offset + n+1) + 0] << ", "
+						//                  << vtx[3 * (vtx_offset + n+1) + 1] << ", "
+						//                  << vtx[3 * (vtx_offset + n+1) + 2] << std::endl;
+					}
 
-          vtx_offset += nverts[k];
-        }
+					vtx_offset += nverts[k];
+				}
 
-        GLCurvesState state;
-        glGenBuffers(1, &state.vb);
-        glBindBuffer(GL_ARRAY_BUFFER, state.vb);
-        glBufferData(GL_ARRAY_BUFFER, line_pts.size() * sizeof(float),
-                     line_pts.data(), GL_STATIC_DRAW);
-        glBindBuffer(GL_ARRAY_BUFFER, 0);
+				GLCurvesState state;
+				glGenBuffers(1, &state.vb);
+				glBindBuffer(GL_ARRAY_BUFFER, state.vb);
+				glBufferData(GL_ARRAY_BUFFER, line_pts.size() * sizeof(float),
+						line_pts.data(), GL_STATIC_DRAW);
+				glBindBuffer(GL_ARRAY_BUFFER, 0);
 
-        state.count = line_pts.size() / 3;
-        gCurvesMesh[mesh.name] = state;
+				state.count = line_pts.size() / 3;
+				gCurvesMesh[mesh.name] = state;
 
-        // Material
-        tinygltf::Material &mat = scene.materials[primitive.material];
-        // printf("material.name = %s\n", mat.name.c_str());
-        if (mat.values.find("diffuse") != mat.values.end()) {
-          std::string diffuseTexName = mat.values["diffuse"].string_value;
-          if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
-            tinygltf::Texture &tex = scene.textures[diffuseTexName];
-            if (scene.images.find(tex.source) != scene.images.end()) {
-              tinygltf::Image &image = scene.images[tex.source];
-              GLuint texId;
-              glGenTextures(1, &texId);
-              glBindTexture(tex.target, texId);
-              glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-              glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-              glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+				// Material
+				tinygltf::Material &mat = scene.materials[primitive.material];
+				// printf("material.name = %s\n", mat.name.c_str());
+				if (mat.values.find("diffuse") != mat.values.end()) {
+					std::string diffuseTexName = mat.values["diffuse"].string_value;
+					if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
+						tinygltf::Texture &tex = scene.textures[diffuseTexName];
+						if (scene.images.find(tex.source) != scene.images.end()) {
+							tinygltf::Image &image = scene.images[tex.source];
+							GLuint texId;
+							glGenTextures(1, &texId);
+							glBindTexture(tex.target, texId);
+							glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+							glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+							glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-              // Ignore Texture.fomat.
-              GLenum format = GL_RGBA;
-              if (image.component == 3) {
-                format = GL_RGB;
-              }
-              glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
-                           image.height, 0, format, tex.type,
-                           &image.image.at(0));
+							// Ignore Texture.fomat.
+							GLenum format = GL_RGBA;
+							if (image.component == 3) {
+								format = GL_RGB;
+							}
+							glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
+									image.height, 0, format, tex.type,
+									&image.image.at(0));
 
-              CheckErrors("texImage2D");
-              glBindTexture(tex.target, 0);
+							CheckErrors("texImage2D");
+							glBindTexture(tex.target, 0);
 
-              printf("TexId = %d\n", texId);
-              gMeshState[mesh.name].diffuseTex[primId] = texId;
-            }
-          }
-        }
-      }
-    }
-  }
+							printf("TexId = %d\n", texId);
+							gMeshState[mesh.name].diffuseTex[primId] = texId;
+						}
+					}
+				}
+			}
+		}
+	}
 
-  glUseProgram(progId);
-  GLint vtloc = glGetAttribLocation(progId, "in_vertex");
-  GLint nrmloc = glGetAttribLocation(progId, "in_normal");
-  GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
+	glUseProgram(progId);
+	GLint vtloc = glGetAttribLocation(progId, "in_vertex");
+	GLint nrmloc = glGetAttribLocation(progId, "in_normal");
+	GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
 
-  GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
-  GLint isCurvesLoc = glGetUniformLocation(progId, "uIsCurves");
+	GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
+	GLint isCurvesLoc = glGetUniformLocation(progId, "uIsCurves");
 
-  gGLProgramState.attribs["POSITION"] = vtloc;
-  gGLProgramState.attribs["NORMAL"] = nrmloc;
-  gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
-  gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
-  gGLProgramState.uniforms["uIsCurves"] = isCurvesLoc;
+	gGLProgramState.attribs["POSITION"] = vtloc;
+	gGLProgramState.attribs["NORMAL"] = nrmloc;
+	gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
+	gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
+	gGLProgramState.uniforms["uIsCurves"] = isCurvesLoc;
 };
 #endif
 
@@ -558,12 +682,13 @@
           (it->first.compare("TEXCOORD_0") == 0)) {
         if (gGLProgramState.attribs[it->first] >= 0) {
           // Compute byteStride from Accessor + BufferView combination.
-          int byteStride = accessor.ByteStride(model.bufferViews[accessor.bufferView]);
+          int byteStride =
+              accessor.ByteStride(model.bufferViews[accessor.bufferView]);
           assert(byteStride != -1);
           glVertexAttribPointer(gGLProgramState.attribs[it->first], size,
-                                accessor.componentType, accessor.normalized ? GL_TRUE : GL_FALSE,
-                                byteStride,
-                                BUFFER_OFFSET(accessor.byteOffset));
+                                accessor.componentType,
+                                accessor.normalized ? GL_TRUE : GL_FALSE,
+                                byteStride, BUFFER_OFFSET(accessor.byteOffset));
           CheckErrors("vertex attrib pointer");
           glEnableVertexAttribArray(gGLProgramState.attribs[it->first]);
           CheckErrors("enable vertex attrib array");
@@ -617,32 +742,32 @@
 
 #if 0  // TODO(syoyo): Implement
 static void DrawCurves(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
-  (void)scene;
+	(void)scene;
 
-  if (gCurvesMesh.find(mesh.name) == gCurvesMesh.end()) {
-    return;
-  }
+	if (gCurvesMesh.find(mesh.name) == gCurvesMesh.end()) {
+		return;
+	}
 
-  if (gGLProgramState.uniforms["isCurvesLoc"] >= 0) {
-    glUniform1i(gGLProgramState.uniforms["isCurvesLoc"], 1);
-  }
+	if (gGLProgramState.uniforms["isCurvesLoc"] >= 0) {
+		glUniform1i(gGLProgramState.uniforms["isCurvesLoc"], 1);
+	}
 
-  GLCurvesState &state = gCurvesMesh[mesh.name];
+	GLCurvesState &state = gCurvesMesh[mesh.name];
 
-  if (gGLProgramState.attribs["POSITION"] >= 0) {
-    glBindBuffer(GL_ARRAY_BUFFER, state.vb);
-    glVertexAttribPointer(gGLProgramState.attribs["POSITION"], 3, GL_FLOAT,
-                          GL_FALSE, /* stride */ 0, BUFFER_OFFSET(0));
-    CheckErrors("curve: vertex attrib pointer");
-    glEnableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
-    CheckErrors("curve: enable vertex attrib array");
-  }
+	if (gGLProgramState.attribs["POSITION"] >= 0) {
+		glBindBuffer(GL_ARRAY_BUFFER, state.vb);
+		glVertexAttribPointer(gGLProgramState.attribs["POSITION"], 3, GL_FLOAT,
+				GL_FALSE, /* stride */ 0, BUFFER_OFFSET(0));
+		CheckErrors("curve: vertex attrib pointer");
+		glEnableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
+		CheckErrors("curve: enable vertex attrib array");
+	}
 
-  glDrawArrays(GL_LINES, 0, state.count);
+	glDrawArrays(GL_LINES, 0, state.count);
 
-  if (gGLProgramState.attribs["POSITION"] >= 0) {
-    glDisableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
-  }
+	if (gGLProgramState.attribs["POSITION"] >= 0) {
+		glDisableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
+	}
 }
 #endif
 
@@ -693,16 +818,16 @@
 
 static void DrawModel(tinygltf::Model &model) {
 #if 0
-  std::map<std::string, tinygltf::Mesh>::const_iterator it(scene.meshes.begin());
-  std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(scene.meshes.end());
+	std::map<std::string, tinygltf::Mesh>::const_iterator it(scene.meshes.begin());
+	std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(scene.meshes.end());
 
-  for (; it != itEnd; it++) {
-    DrawMesh(scene, it->second);
-    DrawCurves(scene, it->second);
-  }
+	for (; it != itEnd; it++) {
+		DrawMesh(scene, it->second);
+		DrawCurves(scene, it->second);
+	}
 #else
-  //If the glTF asset has at least one scene, and doesn't define a default one
-  //just show the first one we can find
+  // If the glTF asset has at least one scene, and doesn't define a default one
+  // just show the first one we can find
   assert(model.scenes.size() > 0);
   int scene_to_display = model.defaultScene > -1 ? model.defaultScene : 0;
   const tinygltf::Scene &scene = model.scenes[scene_to_display];
@@ -752,7 +877,8 @@
 
 #ifdef _WIN32
 #ifdef _DEBUG
-    std::string input_filename(argv[1] ? argv[1] : "../../../models/Cube/Cube.gltf");
+  std::string input_filename(argv[1] ? argv[1]
+                                     : "../../../models/Cube/Cube.gltf");
 #endif
 #else
   std::string input_filename(argv[1] ? argv[1] : "../../models/Cube/Cube.gltf");
@@ -763,7 +889,8 @@
   bool ret = false;
   if (ext.compare("glb") == 0) {
     // assume binary glTF.
-    ret = loader.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
+    ret =
+        loader.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
   } else {
     // assume ascii glTF.
     ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
@@ -825,15 +952,14 @@
 
 #ifdef _WIN32
 #ifdef _DEBUG
-    const char *shader_frag_filename = "../shader.frag";
-    const char *shader_vert_filename = "../shader.vert";
+  const char *shader_frag_filename = "../shader.frag";
+  const char *shader_vert_filename = "../shader.vert";
 #endif
 #else
   const char *shader_frag_filename = "shader.frag";
   const char *shader_vert_filename = "shader.vert";
 #endif
 
-
   if (false == LoadShader(GL_VERTEX_SHADER, vertId, shader_vert_filename)) {
     return -1;
   }
diff --git a/loader_example.cc b/loader_example.cc
index 7f8a426..c0eec95 100644
--- a/loader_example.cc
+++ b/loader_example.cc
@@ -228,7 +228,8 @@
 #endif
 
 static std::string PrintValue(const std::string &name,
-                              const tinygltf::Value &value, const int indent, const bool tag = true) {
+                              const tinygltf::Value &value, const int indent,
+                              const bool tag = true) {
   std::stringstream ss;
 
   if (value.IsObject()) {
@@ -265,11 +266,10 @@
   } else if (value.IsArray()) {
     ss << Indent(indent) << name << " [ ";
     for (size_t i = 0; i < value.Size(); i++) {
-      ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */false);
-      if (i != (value.ArrayLen()-1)) {
+      ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */ false);
+      if (i != (value.ArrayLen() - 1)) {
         ss << ", ";
       }
-
     }
     ss << Indent(indent) << "] ";
   }
@@ -330,13 +330,13 @@
             << PrintValue("extras", primitive.extras, indent + 1) << std::endl;
 }
 
-static void DumpExtensions(const tinygltf::ExtensionMap &extension, const int indent)
-{
+static void DumpExtensions(const tinygltf::ExtensionMap &extension,
+                           const int indent) {
   // TODO(syoyo): pritty print Value
   for (auto &e : extension) {
     std::cout << Indent(indent) << e.first << std::endl;
-    std::cout << PrintValue("extensions", e.second, indent+1) << std::endl;
-  }  
+    std::cout << PrintValue("extensions", e.second, indent + 1) << std::endl;
+  }
 }
 
 static void Dump(const tinygltf::Model &model) {
@@ -409,6 +409,30 @@
         }
         std::cout << "]" << std::endl;
       }
+
+      if (accessor.sparse.isSparse) {
+        std::cout << Indent(2) << "sparse:" << std::endl;
+        std::cout << Indent(3) << "count  : " << accessor.sparse.count
+                  << std::endl;
+        std::cout << Indent(3) << "indices: " << std::endl;
+        std::cout << Indent(4)
+                  << "bufferView   : " << accessor.sparse.indices.bufferView
+                  << std::endl;
+        std::cout << Indent(4)
+                  << "byteOffset   : " << accessor.sparse.indices.byteOffset
+                  << std::endl;
+        std::cout << Indent(4) << "componentType: "
+                  << PrintComponentType(accessor.sparse.indices.componentType)
+                  << "(" << accessor.sparse.indices.componentType << ")"
+                  << std::endl;
+        std::cout << Indent(3) << "values : " << std::endl;
+        std::cout << Indent(4)
+                  << "bufferView   : " << accessor.sparse.values.bufferView
+                  << std::endl;
+        std::cout << Indent(4)
+                  << "byteOffset   : " << accessor.sparse.values.byteOffset
+                  << std::endl;
+      }
     }
   }
 
@@ -585,10 +609,11 @@
       }
     }
   }
-  
+
   // toplevel extensions
   {
-    std::cout << "extensions(items=" << model.extensions.size() << ")" << std::endl;
+    std::cout << "extensions(items=" << model.extensions.size() << ")"
+              << std::endl;
     DumpExtensions(model.extensions, 1);
   }
 }
@@ -602,7 +627,7 @@
   tinygltf::Model model;
   tinygltf::TinyGLTF gltf_ctx;
   std::string err;
-  std::string warn; 
+  std::string warn;
   std::string input_filename(argv[1]);
   std::string ext = GetFilePathExtension(input_filename);
 
@@ -610,18 +635,19 @@
   if (ext.compare("glb") == 0) {
     std::cout << "Reading binary glTF" << std::endl;
     // assume binary glTF.
-    ret = gltf_ctx.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
+    ret = gltf_ctx.LoadBinaryFromFile(&model, &err, &warn,
+                                      input_filename.c_str());
   } else {
     std::cout << "Reading ASCII glTF" << std::endl;
     // assume ascii glTF.
-    ret = gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, 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()) {
     printf("Err: %s\n", err.c_str());
   }
diff --git a/tiny_gltf.h b/tiny_gltf.h
index d675777..3c1015a 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -4,7 +4,7 @@
 //
 // The MIT License (MIT)
 //
-// Copyright (c) 2015 - 2018 Syoyo Fujita, Aurélien Chatelain and many
+// Copyright (c) 2015 - 2019 Syoyo Fujita, Aurélien Chatelain and many
 // contributors.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,7 +26,8 @@
 // THE SOFTWARE.
 
 // Version:
-//  - v2.2.0 Add loading 16bit PNG support.
+//  - 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 comparsion feature(Thanks to @Selmar).
 //  - v2.0.0 glTF 2.0!.
@@ -150,7 +151,7 @@
 
 #ifdef __ANDROID__
 #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
-  AAssetManager* asset_manager = nullptr;
+AAssetManager *asset_manager = nullptr;
 #endif
 #endif
 
@@ -381,15 +382,15 @@
     return -1;
   }
 
-  /// Return the index of a texture coordinate set 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 coordinate set if this Parameter is a
+  /// texture map. Returned value is only valid if the parameter represent a
+  /// texture from a material
   int TextureTexCoord() const {
-      const auto it = json_double_value.find("texCoord");
-      if (it != std::end(json_double_value)) {
-          return int(it->second);
-      }
-      return 0;
+    const auto it = json_double_value.find("texCoord");
+    if (it != std::end(json_double_value)) {
+      return int(it->second);
+    }
+    return 0;
   }
 
   /// Material factor, like the roughness or metalness of a material
@@ -484,7 +485,7 @@
         magFilter(TINYGLTF_TEXTURE_FILTER_LINEAR),
         wrapS(TINYGLTF_TEXTURE_WRAP_REPEAT),
         wrapT(TINYGLTF_TEXTURE_WRAP_REPEAT),
-        wrapR(TINYGLTF_TEXTURE_WRAP_REPEAT){}
+        wrapR(TINYGLTF_TEXTURE_WRAP_REPEAT) {}
   bool operator==(const Sampler &) const;
 };
 
@@ -493,8 +494,9 @@
   int width;
   int height;
   int component;
-  int bits; // bit depth per channel. 8(byte), 16 or 32.
-  int pixel_type; // pixel type(TINYGLTF_COMPONENT_TYPE_***). usually UBYTE(bits = 8) or USHORT(bits = 16)
+  int bits;        // bit depth per channel. 8(byte), 16 or 32.
+  int pixel_type;  // pixel type(TINYGLTF_COMPONENT_TYPE_***). usually
+                   // UBYTE(bits = 8) or USHORT(bits = 16)
   std::vector<unsigned char> image;
   int bufferView;        // (required if no uri)
   std::string mimeType;  // (required if no uri) ["image/jpeg", "image/png",
@@ -576,7 +578,19 @@
   std::vector<double> minValues;  // optional
   std::vector<double> maxValues;  // optional
 
-  // TODO(syoyo): "sparse"
+  struct {
+    int count;
+    bool isSparse;
+    struct {
+      int byteOffset;
+      int bufferView;
+      int componentType;  // a TINYGLTF_COMPONENT_TYPE_ value
+    } indices;
+    struct {
+      int bufferView;
+      int byteOffset;
+    } values;
+  } sparse;
 
   ///
   /// Utility function to compute byteStride for a given bufferView object.
@@ -615,7 +629,10 @@
     return 0;
   }
 
-  Accessor() { bufferView = -1; }
+  Accessor() {
+    bufferView = -1;
+    sparse.isSparse = false;
+  }
   bool operator==(const tinygltf::Accessor &) const;
 };
 
@@ -821,9 +838,9 @@
 ///
 /// LoadImageDataFunction type. Signature for custom image loading callbacks.
 ///
-typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *, std::string *,
-                                      int, int, const unsigned char *, int,
-                                      void *);
+typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
+                                      std::string *, int, int,
+                                      const unsigned char *, int, void *);
 
 ///
 /// WriteImageDataFunction type. Signature for custom image writing callbacks.
@@ -833,9 +850,9 @@
 
 #ifndef TINYGLTF_NO_STB_IMAGE
 // Declaration of default image loader callback
-bool LoadImageData(Image *image, const int image_idx, std::string *err, std::string *warn,
-                   int req_width, int req_height, const unsigned char *bytes,
-                   int size, void *);
+bool LoadImageData(Image *image, const int image_idx, std::string *err,
+                   std::string *warn, int req_width, int req_height,
+                   const unsigned char *bytes, int size, void *);
 #endif
 
 #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
@@ -955,10 +972,8 @@
   /// Write glTF to file.
   ///
   bool WriteGltfSceneToFile(Model *model, const std::string &filename,
-                            bool embedImages,
-                            bool embedBuffers,
-                            bool prettyPrint,
-                            bool writeBinary);
+                            bool embedImages, bool embedBuffers,
+                            bool prettyPrint, bool writeBinary);
 
   ///
   /// Set callback to use for loading image data
@@ -1090,22 +1105,28 @@
 #ifdef __GNUC__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wtype-limits"
-#endif // __GNUC__
+#endif  // __GNUC__
 
+#ifndef TINYGLTF_NO_INCLUDE_JSON
 #include "json.hpp"
+#endif
 
 #ifdef TINYGLTF_ENABLE_DRACO
-#include "draco/core/decoder_buffer.h"
 #include "draco/compression/decode.h"
+#include "draco/core/decoder_buffer.h"
 #endif
 
 #ifndef TINYGLTF_NO_STB_IMAGE
+#ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE
 #include "stb_image.h"
 #endif
+#endif
 
 #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
+#ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
 #include "stb_image_write.h"
 #endif
+#endif
 
 #ifdef __clang__
 #pragma clang diagnostic pop
@@ -1129,7 +1150,7 @@
 #define WIN32_LEAN_AND_MEAN
 #define TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
 #endif
-#include <windows.h> // include API for expanding a file path
+#include <windows.h>  // include API for expanding a file path
 
 #ifdef TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
 #undef WIN32_LEAN_AND_MEAN
@@ -1773,7 +1794,8 @@
   std::vector<unsigned char> data;
 
   if (ext == "png") {
-    if ((image->bits != 8) || (image->pixel_type != TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)) {
+    if ((image->bits != 8) ||
+        (image->pixel_type != TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)) {
       // Unsupported pixel format
       return false;
     }
@@ -1841,16 +1863,17 @@
 bool FileExists(const std::string &abs_filename, void *) {
   bool ret;
 #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
-    if (asset_manager) {
-        AAsset* asset = AAssetManager_open(asset_manager, abs_filename.c_str(), AASSET_MODE_STREAMING);
-        if (!asset) {
-            return false;
-        }
-        AAsset_close(asset);
-        ret = true;
-    } else {
+  if (asset_manager) {
+    AAsset *asset = AAssetManager_open(asset_manager, abs_filename.c_str(),
+                                       AASSET_MODE_STREAMING);
+    if (!asset) {
       return false;
     }
+    AAsset_close(asset);
+    ret = true;
+  } else {
+    return false;
+  }
 #else
 #ifdef _WIN32
   FILE *fp;
@@ -1923,7 +1946,8 @@
                    const std::string &filepath, void *) {
 #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
   if (asset_manager) {
-    AAsset* asset = AAssetManager_open(asset_manager, filepath.c_str(), AASSET_MODE_STREAMING);
+    AAsset *asset = AAssetManager_open(asset_manager, filepath.c_str(),
+                                       AASSET_MODE_STREAMING);
     if (!asset) {
       if (err) {
         (*err) += "File open error : " + filepath + "\n";
@@ -2500,12 +2524,13 @@
   json::const_iterator extIt = it.value().begin();
   for (; extIt != it.value().end(); extIt++) {
     if (!extIt.value().is_object()) continue;
-	if (!ParseJsonAsValue(&extensions[extIt.key()], extIt.value())) {
+    if (!ParseJsonAsValue(&extensions[extIt.key()], extIt.value())) {
       if (!extIt.key().empty()) {
-        // create empty object so that an extension object is still of type object
-        extensions[extIt.key()] = Value{ Value::Object{} };
+        // create empty object so that an extension object is still of type
+        // object
+        extensions[extIt.key()] = Value{Value::Object{}};
       }
-	}
+    }
   }
   if (ret) {
     (*ret) = extensions;
@@ -2526,9 +2551,9 @@
   return true;
 }
 
-static bool ParseImage(Image *image, const int image_idx, std::string *err, std::string *warn,
-                       const json &o, const std::string &basedir,
-                       FsCallbacks *fs,
+static bool ParseImage(Image *image, const int image_idx, std::string *err,
+                       std::string *warn, const json &o,
+                       const std::string &basedir, FsCallbacks *fs,
                        LoadImageDataFunction *LoadImageData = nullptr,
                        void *load_image_user_data = nullptr) {
   // A glTF image must either reference a bufferView or an image uri
@@ -2545,14 +2570,17 @@
     if (err) {
       (*err) +=
           "Only one of `bufferView` or `uri` should be defined, but both are "
-          "defined for image[" + std::to_string(image_idx) + "] name = \"" + image->name + "\"\n";
+          "defined for image[" +
+          std::to_string(image_idx) + "] name = \"" + image->name + "\"\n";
     }
     return false;
   }
 
   if (!hasBufferView && !hasURI) {
     if (err) {
-      (*err) += "Neither required `bufferView` nor `uri` defined for image[" + std::to_string(image_idx) + "] name = \"" + image->name + "\"\n";
+      (*err) += "Neither required `bufferView` nor `uri` defined for image[" +
+                std::to_string(image_idx) + "] name = \"" + image->name +
+                "\"\n";
     }
     return false;
   }
@@ -2564,7 +2592,9 @@
     double bufferView = -1;
     if (!ParseNumberProperty(&bufferView, err, o, "bufferView", true)) {
       if (err) {
-        (*err) += "Failed to parse `bufferView` for image[" + std::to_string(image_idx) + "] name = \"" + image->name + "\"\n";
+        (*err) += "Failed to parse `bufferView` for image[" +
+                  std::to_string(image_idx) + "] name = \"" + image->name +
+                  "\"\n";
       }
       return false;
     }
@@ -2594,7 +2624,8 @@
   std::string tmp_err;
   if (!ParseStringProperty(&uri, &tmp_err, o, "uri", true)) {
     if (err) {
-      (*err) += "Failed to parse `uri` for image[" + std::to_string(image_idx) + "] name = \"" + image->name + "\".\n";
+      (*err) += "Failed to parse `uri` for image[" + std::to_string(image_idx) +
+                "] name = \"" + image->name + "\".\n";
     }
     return false;
   }
@@ -2604,7 +2635,9 @@
   if (IsDataURI(uri)) {
     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";
+        (*err) += "Failed to decode 'uri' for image[" +
+                  std::to_string(image_idx) + "] name = [" + image->name +
+                  "]\n";
       }
       return false;
     }
@@ -2617,7 +2650,9 @@
 #endif
     if (!LoadExternalFile(&img, err, warn, uri, basedir, false, 0, false, fs)) {
       if (warn) {
-        (*warn) += "Failed to load external 'uri' for image[" + std::to_string(image_idx) + "] name = [" + image->name + "]\n";
+        (*warn) += "Failed to load external 'uri' for image[" +
+                   std::to_string(image_idx) + "] name = [" + image->name +
+                   "]\n";
       }
       // If the image cannot be loaded, keep uri as image->uri.
       return true;
@@ -2625,7 +2660,9 @@
 
     if (img.empty()) {
       if (warn) {
-        (*warn) += "Image data is empty for image[" + std::to_string(image_idx) + "] name = [" + image->name + "] \n";
+        (*warn) += "Image data is empty for image[" +
+                   std::to_string(image_idx) + "] name = [" + image->name +
+                   "] \n";
       }
       return false;
     }
@@ -2821,6 +2858,51 @@
   bufferView->byteOffset = static_cast<size_t>(byteOffset);
   bufferView->byteLength = static_cast<size_t>(byteLength);
   bufferView->byteStride = static_cast<size_t>(byteStride);
+  return true;
+}
+
+static bool ParseSparseAccessor(Accessor *accessor, std::string *err,
+                                const json &o) {
+  accessor->sparse.isSparse = true;
+
+  double count = 0.0;
+  ParseNumberProperty(&count, err, o, "count", true);
+
+  const auto indices_iterator = o.find("indices");
+  const auto values_iterator = o.find("values");
+  if (indices_iterator == o.end()) {
+    (*err) = "the sparse object of this accessor doesn't have indices";
+    return false;
+  }
+
+  if (values_iterator == o.end()) {
+    (*err) = "the sparse object ob ths accessor doesn't have values";
+    return false;
+  }
+
+  const json &indices_obj = *indices_iterator;
+  const json &values_obj = *values_iterator;
+
+  double indices_buffer_view = 0.0, indices_byte_offset = 0.0,
+         component_type = 0.0;
+  ParseNumberProperty(&indices_buffer_view, err, indices_obj, "bufferView",
+                      true);
+  ParseNumberProperty(&indices_byte_offset, err, indices_obj, "byteOffset",
+                      true);
+  ParseNumberProperty(&component_type, err, indices_obj, "componentType", true);
+
+  double values_buffer_view = 0.0, values_byte_offset = 0.0;
+  ParseNumberProperty(&values_buffer_view, err, values_obj, "bufferView", true);
+  ParseNumberProperty(&values_byte_offset, err, values_obj, "byteOffset", true);
+
+  accessor->sparse.count = static_cast<int>(count);
+  accessor->sparse.indices.bufferView = static_cast<int>(indices_buffer_view);
+  accessor->sparse.indices.byteOffset = static_cast<int>(indices_byte_offset);
+  accessor->sparse.indices.componentType = static_cast<int>(component_type);
+  accessor->sparse.values.bufferView = static_cast<int>(values_buffer_view);
+  accessor->sparse.values.byteOffset = static_cast<int>(values_byte_offset);
+
+  // todo check theses values
 
   return true;
 }
@@ -2906,112 +2988,128 @@
 
   ParseExtrasProperty(&(accessor->extras), o);
 
+  // check if accessor has a "sparse" object:
+  const auto iterator = o.find("sparse");
+  if (iterator != o.end()) {
+    // here this accessor has a "sparse" subobject
+    return ParseSparseAccessor(accessor, err, *iterator);
+  }
+
   return true;
 }
 
 #ifdef TINYGLTF_ENABLE_DRACO
 
-static void DecodeIndexBuffer(draco::Mesh* mesh, size_t componentSize, std::vector<uint8_t>& outBuffer)
-{
-  if (componentSize == 4)
-  {
+static void DecodeIndexBuffer(draco::Mesh *mesh, size_t componentSize,
+                              std::vector<uint8_t> &outBuffer) {
+  if (componentSize == 4) {
     assert(sizeof(mesh->face(draco::FaceIndex(0))[0]) == componentSize);
-    memcpy(outBuffer.data(), &mesh->face(draco::FaceIndex(0))[0], outBuffer.size());
-  }
-  else
-  {
+    memcpy(outBuffer.data(), &mesh->face(draco::FaceIndex(0))[0],
+           outBuffer.size());
+  } else {
     size_t faceStride = componentSize * 3;
-    for (draco::FaceIndex f(0); f < mesh->num_faces(); ++f)
-    {
-      const draco::Mesh::Face& face = mesh->face(f);
-      if (componentSize == 2)
-      {
-        uint16_t indices[3] = { (uint16_t)face[0].value(), (uint16_t)face[1].value(), (uint16_t)face[2].value() };
-        memcpy(outBuffer.data() + f.value() * faceStride, &indices[0], faceStride);
-      }
-      else
-      {
-        uint8_t indices[3] = { (uint8_t)face[0].value(), (uint8_t)face[1].value(), (uint8_t)face[2].value() };
-        memcpy(outBuffer.data() + f.value() * faceStride, &indices[0], faceStride);
+    for (draco::FaceIndex f(0); f < mesh->num_faces(); ++f) {
+      const draco::Mesh::Face &face = mesh->face(f);
+      if (componentSize == 2) {
+        uint16_t indices[3] = {(uint16_t)face[0].value(),
+                               (uint16_t)face[1].value(),
+                               (uint16_t)face[2].value()};
+        memcpy(outBuffer.data() + f.value() * faceStride, &indices[0],
+               faceStride);
+      } else {
+        uint8_t indices[3] = {(uint8_t)face[0].value(),
+                              (uint8_t)face[1].value(),
+                              (uint8_t)face[2].value()};
+        memcpy(outBuffer.data() + f.value() * faceStride, &indices[0],
+               faceStride);
       }
     }
   }
 }
 
-template<typename T>
-static bool GetAttributeForAllPoints(draco::Mesh* mesh, const draco::PointAttribute* pAttribute, std::vector<uint8_t>& outBuffer)
-{
+template <typename T>
+static bool GetAttributeForAllPoints(draco::Mesh *mesh,
+                                     const draco::PointAttribute *pAttribute,
+                                     std::vector<uint8_t> &outBuffer) {
   size_t byteOffset = 0;
-  T values[4] = { 0, 0, 0, 0 };
-  for (draco::PointIndex i(0); i < mesh->num_points(); ++i)
-  {
+  T values[4] = {0, 0, 0, 0};
+  for (draco::PointIndex i(0); i < mesh->num_points(); ++i) {
     const draco::AttributeValueIndex val_index = pAttribute->mapped_index(i);
-    if (!pAttribute->ConvertValue<T>(val_index, pAttribute->num_components(), values))
+    if (!pAttribute->ConvertValue<T>(val_index, pAttribute->num_components(),
+                                     values))
       return false;
 
-    memcpy(outBuffer.data() + byteOffset, &values[0], sizeof(T) * pAttribute->num_components());
+    memcpy(outBuffer.data() + byteOffset, &values[0],
+           sizeof(T) * pAttribute->num_components());
     byteOffset += sizeof(T) * pAttribute->num_components();
   }
 
   return true;
 }
 
-static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh* mesh, const draco::PointAttribute* pAttribute, std::vector<uint8_t>& outBuffer)
-{
+static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
+                                     const draco::PointAttribute *pAttribute,
+                                     std::vector<uint8_t> &outBuffer) {
   bool decodeResult = false;
-  switch (componentType)
-  {
-  case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
-    decodeResult = GetAttributeForAllPoints<uint8_t>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_BYTE:
-    decodeResult = GetAttributeForAllPoints<int8_t>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
-    decodeResult = GetAttributeForAllPoints<uint16_t>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_SHORT:
-    decodeResult = GetAttributeForAllPoints<int16_t>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_INT:
-    decodeResult = GetAttributeForAllPoints<int32_t>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
-    decodeResult = GetAttributeForAllPoints<uint32_t>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_FLOAT:
-    decodeResult = GetAttributeForAllPoints<float>(mesh, pAttribute, outBuffer);
-    break;
-  case TINYGLTF_COMPONENT_TYPE_DOUBLE:
-    decodeResult = GetAttributeForAllPoints<double>(mesh, pAttribute, outBuffer);
-    break;
-  default:
-    return false;
+  switch (componentType) {
+    case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
+      decodeResult =
+          GetAttributeForAllPoints<uint8_t>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_BYTE:
+      decodeResult =
+          GetAttributeForAllPoints<int8_t>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
+      decodeResult =
+          GetAttributeForAllPoints<uint16_t>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_SHORT:
+      decodeResult =
+          GetAttributeForAllPoints<int16_t>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_INT:
+      decodeResult =
+          GetAttributeForAllPoints<int32_t>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
+      decodeResult =
+          GetAttributeForAllPoints<uint32_t>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_FLOAT:
+      decodeResult =
+          GetAttributeForAllPoints<float>(mesh, pAttribute, outBuffer);
+      break;
+    case TINYGLTF_COMPONENT_TYPE_DOUBLE:
+      decodeResult =
+          GetAttributeForAllPoints<double>(mesh, pAttribute, outBuffer);
+      break;
+    default:
+      return false;
   }
 
   return decodeResult;
 }
 
-static bool ParseDracoExtension(Primitive *primitive, Model *model, std::string *err, const Value &dracoExtensionValue)
-{
+static bool ParseDracoExtension(Primitive *primitive, Model *model,
+                                std::string *err,
+                                const Value &dracoExtensionValue) {
   auto bufferViewValue = dracoExtensionValue.Get("bufferView");
-  if (!bufferViewValue.IsInt())
-    return false;
+  if (!bufferViewValue.IsInt()) return false;
   auto attributesValue = dracoExtensionValue.Get("attributes");
-  if (!attributesValue.IsObject())
-    return false;
+  if (!attributesValue.IsObject()) return false;
 
   auto attributesObject = attributesValue.Get<Value::Object>();
   int bufferView = bufferViewValue.Get<int>();
 
-  BufferView& view = model->bufferViews[bufferView];
-  Buffer& buffer = model->buffers[view.buffer];
+  BufferView &view = model->bufferViews[bufferView];
+  Buffer &buffer = model->buffers[view.buffer];
   // BufferView has already been decoded
-  if (view.dracoDecoded)
-    return true;
+  if (view.dracoDecoded) return true;
   view.dracoDecoded = true;
 
-  const char* bufferViewData = reinterpret_cast<const char*>(buffer.data.data() + view.byteOffset);
+  const char *bufferViewData =
+      reinterpret_cast<const char *>(buffer.data.data() + view.byteOffset);
   size_t bufferViewSize = view.byteLength;
 
   // decode draco
@@ -3022,12 +3120,12 @@
   if (!decodeResult.ok()) {
     return false;
   }
-  const std::unique_ptr<draco::Mesh>& mesh = decodeResult.value();
+  const std::unique_ptr<draco::Mesh> &mesh = decodeResult.value();
 
   // create new bufferView for indices
-  if (primitive->indices >= 0)
-  {
-    int32_t componentSize = GetComponentSizeInBytes(model->accessors[primitive->indices].componentType);
+  if (primitive->indices >= 0) {
+    int32_t componentSize = GetComponentSizeInBytes(
+        model->accessors[primitive->indices].componentType);
     Buffer decodedIndexBuffer;
     decodedIndexBuffer.data.resize(mesh->num_faces() * 3 * componentSize);
 
@@ -3037,35 +3135,37 @@
 
     BufferView decodedIndexBufferView;
     decodedIndexBufferView.buffer = int(model->buffers.size() - 1);
-    decodedIndexBufferView.byteLength = int(mesh->num_faces() * 3 * componentSize);
+    decodedIndexBufferView.byteLength =
+        int(mesh->num_faces() * 3 * componentSize);
     decodedIndexBufferView.byteOffset = 0;
     decodedIndexBufferView.byteStride = 0;
     decodedIndexBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
     model->bufferViews.emplace_back(std::move(decodedIndexBufferView));
 
-    model->accessors[primitive->indices].bufferView = int(model->bufferViews.size() - 1);
+    model->accessors[primitive->indices].bufferView =
+        int(model->bufferViews.size() - 1);
     model->accessors[primitive->indices].count = int(mesh->num_faces() * 3);
   }
 
-  for (const auto& attribute : attributesObject)
-  {
-    if (!attribute.second.IsInt())
-      return false;
+  for (const auto &attribute : attributesObject) {
+    if (!attribute.second.IsInt()) return false;
     auto primitiveAttribute = primitive->attributes.find(attribute.first);
-    if (primitiveAttribute == primitive->attributes.end())
-      return false;
+    if (primitiveAttribute == primitive->attributes.end()) return false;
 
     int dracoAttributeIndex = attribute.second.Get<int>();
     const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
     const auto pBuffer = pAttribute->buffer();
-    const auto componentType = model->accessors[primitiveAttribute->second].componentType;
+    const auto componentType =
+        model->accessors[primitiveAttribute->second].componentType;
 
     // Create a new buffer for this decoded buffer
     Buffer decodedBuffer;
-    size_t bufferSize = mesh->num_points() * pAttribute->num_components() * GetComponentSizeInBytes(componentType);
+    size_t bufferSize = mesh->num_points() * pAttribute->num_components() *
+                        GetComponentSizeInBytes(componentType);
     decodedBuffer.data.resize(bufferSize);
 
-    if (!GetAttributeForAllPoints(componentType, mesh.get(), pAttribute, decodedBuffer.data))
+    if (!GetAttributeForAllPoints(componentType, mesh.get(), pAttribute,
+                                  decodedBuffer.data))
       return false;
 
     model->buffers.emplace_back(std::move(decodedBuffer));
@@ -3075,11 +3175,15 @@
     decodedBufferView.byteLength = bufferSize;
     decodedBufferView.byteOffset = pAttribute->byte_offset();
     decodedBufferView.byteStride = pAttribute->byte_stride();
-    decodedBufferView.target = primitive->indices >= 0 ? TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER : TINYGLTF_TARGET_ARRAY_BUFFER;
+    decodedBufferView.target = primitive->indices >= 0
+                                   ? TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER
+                                   : TINYGLTF_TARGET_ARRAY_BUFFER;
     model->bufferViews.emplace_back(std::move(decodedBufferView));
 
-    model->accessors[primitiveAttribute->second].bufferView = int(model->bufferViews.size() - 1);
-    model->accessors[primitiveAttribute->second].count = int(mesh->num_points());
+    model->accessors[primitiveAttribute->second].bufferView =
+        int(model->bufferViews.size() - 1);
+    model->accessors[primitiveAttribute->second].count =
+        int(mesh->num_points());
   }
 
   return true;
@@ -3129,10 +3233,10 @@
   ParseExtensionsProperty(&primitive->extensions, err, o);
 
 #ifdef TINYGLTF_ENABLE_DRACO
-  auto dracoExtension = primitive->extensions.find("KHR_draco_mesh_compression");
-  if (dracoExtension != primitive->extensions.end())
-  {
-      ParseDracoExtension(primitive, model, err, dracoExtension->second);
+  auto dracoExtension =
+      primitive->extensions.find("KHR_draco_mesh_compression");
+  if (dracoExtension != primitive->extensions.end()) {
+    ParseDracoExtension(primitive, model, err, dracoExtension->second);
   }
 #else
   (void)model;
@@ -3141,7 +3245,8 @@
   return true;
 }
 
-static bool ParseMesh(Mesh *mesh, Model *model, std::string *err, const json &o) {
+static bool ParseMesh(Mesh *mesh, Model *model, std::string *err,
+                      const json &o) {
   ParseStringProperty(&mesh->name, err, o, "name", false);
 
   mesh->primitives.clear();
@@ -3816,22 +3921,22 @@
   // Assign missing bufferView target types
   // - Look for missing Mesh indices
   // - Look for missing bufferView targets
-  for (auto &mesh : model->meshes)
-  {
-    for (auto &primitive : mesh.primitives)
-    {
-      if (primitive.indices > -1) // has indices from parsing step, must be Element Array Buffer
+  for (auto &mesh : model->meshes) {
+    for (auto &primitive : mesh.primitives) {
+      if (primitive.indices >
+          -1)  // has indices from parsing step, must be Element Array Buffer
       {
         model->bufferViews[model->accessors[primitive.indices].bufferView]
             .target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
-        // we could optionally check if acessors' bufferView type is Scalar, as it should be
+        // we could optionally check if acessors' bufferView type is Scalar, as
+        // it should be
       }
     }
   }
-  // find any missing targets, must be an array buffer type if not fulfilled from previous check
-  for (auto &bufferView : model->bufferViews)
-  {
-    if (bufferView.target == 0) // missing target type
+  // find any missing targets, must be an array buffer type if not fulfilled
+  // from previous check
+  for (auto &bufferView : model->bufferViews) {
+    if (bufferView.target == 0)  // missing target type
     {
       bufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
     }
@@ -3950,7 +4055,8 @@
       for (; it != itEnd; it++, idx++) {
         if (!it.value().is_object()) {
           if (err) {
-            (*err) += "image[" + std::to_string(idx) + "] is not a JSON object.";
+            (*err) +=
+                "image[" + std::to_string(idx) + "] is not a JSON object.";
           }
           return false;
         }
@@ -3982,10 +4088,10 @@
             }
             return false;
           }
-          bool ret = LoadImageData(&image, idx, err, warn, image.width, image.height,
-                                   &buffer.data[bufferView.byteOffset],
-                                   static_cast<int>(bufferView.byteLength),
-                                   load_image_user_data_);
+          bool ret = LoadImageData(
+              &image, idx, err, warn, image.width, image.height,
+              &buffer.data[bufferView.byteOffset],
+              static_cast<int>(bufferView.byteLength), load_image_user_data_);
           if (!ret) {
             return false;
           }
@@ -4439,7 +4545,7 @@
 static bool SerializeGltfBufferData(const std::vector<unsigned char> &data,
                                     const std::string &binFilename) {
   std::ofstream output(binFilename.c_str(), std::ofstream::binary);
-  if(!output.is_open()) return false;
+  if (!output.is_open()) return false;
   output.write(reinterpret_cast<const char *>(&data[0]),
                std::streamsize(data.size()));
   output.close();
@@ -4488,9 +4594,10 @@
     if (ValueToJson(extIt->second, &ret)) {
       extMap[extIt->first] = ret;
     }
-    if(ret.is_null()) {
-      if (!(extIt->first.empty())) { // name should not be empty, but for sure
-        // create empty object so that an extension name is still included in json.
+    if (ret.is_null()) {
+      if (!(extIt->first.empty())) {  // name should not be empty, but for sure
+        // create empty object so that an extension name is still included in
+        // json.
         extMap[extIt->first] = json({});
       }
     }
@@ -4621,7 +4728,7 @@
 static bool SerializeGltfBuffer(Buffer &buffer, json &o,
                                 const std::string &binFilename,
                                 const std::string &binBaseFilename) {
-  if(!SerializeGltfBufferData(buffer.data, binFilename)) return false;
+  if (!SerializeGltfBufferData(buffer.data, binFilename)) return false;
   SerializeNumberProperty("byteLength", buffer.data.size(), o);
   SerializeStringProperty("uri", binBaseFilename, o);
 
@@ -4909,7 +5016,8 @@
   const int version = 2;
   const int padding_size = content.size() % 4;
 
-  // 12 bytes for header, JSON content length, 8 bytes for JSON chunk info, padding
+  // 12 bytes for header, JSON content length, 8 bytes for JSON chunk info,
+  // padding
   const int length = 12 + 8 + int(content.size()) + padding_size;
 
   gltfFile.write(header.c_str(), header.size());
@@ -4919,8 +5027,10 @@
   // JSON chunk info, then JSON data
   const int model_length = int(content.size()) + padding_size;
   const int model_format = 0x4E4F534A;
-  gltfFile.write(reinterpret_cast<const char *>(&model_length), sizeof(model_length));
-  gltfFile.write(reinterpret_cast<const char *>(&model_format), sizeof(model_format));
+  gltfFile.write(reinterpret_cast<const char *>(&model_length),
+                 sizeof(model_length));
+  gltfFile.write(reinterpret_cast<const char *>(&model_format),
+                 sizeof(model_format));
   gltfFile.write(content.c_str(), content.size());
 
   // Chunk must be multiplies of 4, so pad with spaces
@@ -4966,7 +5076,8 @@
 
   std::string defaultBinFilename = GetBaseFilename(filename);
   std::string defaultBinFileExt = ".bin";
-  std::string::size_type pos = defaultBinFilename.rfind('.', defaultBinFilename.length());
+  std::string::size_type pos =
+      defaultBinFilename.rfind('.', defaultBinFilename.length());
 
   if (pos != std::string::npos) {
     defaultBinFilename = defaultBinFilename.substr(0, pos);
@@ -4986,28 +5097,27 @@
     } else {
       std::string binSavePath;
       std::string binUri;
-      if (!model->buffers[i].uri.empty()
-        && !IsDataURI(model->buffers[i].uri)) {
+      if (!model->buffers[i].uri.empty() && !IsDataURI(model->buffers[i].uri)) {
         binUri = model->buffers[i].uri;
-      }
-      else {
+      } else {
         binUri = defaultBinFilename + defaultBinFileExt;
         bool inUse = true;
         int numUsed = 0;
-        while(inUse) {
+        while (inUse) {
           inUse = false;
-          for (const std::string& usedName : usedUris) {
+          for (const std::string &usedName : usedUris) {
             if (binUri.compare(usedName) != 0) continue;
             inUse = true;
-            binUri = defaultBinFilename + std::to_string(numUsed++) + defaultBinFileExt;
+            binUri = defaultBinFilename + std::to_string(numUsed++) +
+                     defaultBinFileExt;
             break;
           }
         }
       }
       usedUris.push_back(binUri);
-	  binSavePath = JoinPath(baseDir, binUri);
-      if(!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
-                          binUri)) {
+      binSavePath = JoinPath(baseDir, binUri);
+      if (!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
+                               binUri)) {
         return false;
       }
     }