From 924d86e3628262808e5082f028a76ebd6082eec7 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 8 Oct 2018 21:15:12 +0900 Subject: [PATCH] Serialize extension with empty object. Fixes #97 Use pretty printing JSON when serializing for the readability. --- models/Extensions-issue97/test.gltf | 66 +++++++++++++++++++++++++++++ tests/tester.cc | 44 +++++++++++++++++++ tiny_gltf.h | 15 ++++++- 3 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 models/Extensions-issue97/test.gltf diff --git a/models/Extensions-issue97/test.gltf b/models/Extensions-issue97/test.gltf new file mode 100644 index 0000000..c40af40 --- /dev/null +++ b/models/Extensions-issue97/test.gltf @@ -0,0 +1,66 @@ + +{ + "scenes" : [ + { + "nodes" : [ 0 ] + } + ], + + "nodes" : [ + { + "mesh" : 0 + } + ], + + "meshes" : [ + { + "primitives" : [ { + "attributes" : { + "POSITION" : 0 + } + } ] + } + ], + + "buffers" : [ + { + "uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA", + "byteLength" : 36 + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 36, + "target" : 34962 + } + ], + "accessors" : [ + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 3, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + } + ], + + "asset" : { + "version" : "2.0" + }, + + "materials" : [ + { "name" : "WHITE", + "extensions": { + "VENDOR_material_some_ext" : { } + } + } + ], + + "extensionsUsed" : [ + "VENDOR_material_some_ext" + ] +} diff --git a/tests/tester.cc b/tests/tester.cc index ca0ced3..bb29e18 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -41,4 +41,48 @@ TEST_CASE("datauri-in-glb", "[issue-79]") { REQUIRE(true == ret); } +TEST_CASE("extension-with-empty-object", "[issue-97]") { + + tinygltf::Model model; + tinygltf::TinyGLTF ctx; + std::string err; + std::string warn; + + bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/Extensions-issue97/test.gltf"); + if (!err.empty()) { + std::cerr << err << std::endl; + } + REQUIRE(true == ret); + + REQUIRE(model.extensionsUsed.size() == 1); + REQUIRE(model.extensionsUsed[0].compare("VENDOR_material_some_ext") == 0); + + REQUIRE(model.materials.size() == 1); + REQUIRE(model.materials[0].extensions.size() == 1); + REQUIRE(model.materials[0].extensions.count("VENDOR_material_some_ext") == 1); + + // TODO(syoyo): create temp directory. + { + ret = ctx.WriteGltfSceneToFile(&model, "issue-97.gltf", true, true); + REQUIRE(true == ret); + + tinygltf::Model m; + + // read back serialized glTF + bool ret = ctx.LoadASCIIFromFile(&m, &err, &warn, "issue-97.gltf"); + if (!err.empty()) { + std::cerr << err << std::endl; + } + REQUIRE(true == ret); + + REQUIRE(m.extensionsUsed.size() == 1); + REQUIRE(m.extensionsUsed[0].compare("VENDOR_material_some_ext") == 0); + + REQUIRE(m.materials.size() == 1); + REQUIRE(m.materials[0].extensions.size() == 1); + REQUIRE(m.materials[0].extensions.count("VENDOR_material_some_ext") == 1); + } + +} + diff --git a/tiny_gltf.h b/tiny_gltf.h index 8b43da0..b42020e 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -4115,7 +4115,17 @@ static void SerializeExtensionMap(ExtensionMap &extensions, json &o) { for (ExtensionMap::iterator extIt = extensions.begin(); extIt != extensions.end(); ++extIt) { json extension_values; - SerializeValue(extIt->first, extIt->second, extMap); + + // Allow an empty object for extension(#97) + json ret; + if (ValueToJson(extIt->second, &ret)) { + extMap[extIt->first] = ret; + } else { + 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({}); + } + } } o["extensions"] = extMap; } @@ -4760,7 +4770,8 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename, SerializeValue("extras", model->extras, output); } - return WriteGltfFile(filename, output.dump()); + // pretty printing with spacing 2 + return WriteGltfFile(filename, output.dump(2)); } } // namespace tinygltf