From ef2f49ff1966ee9a8d0475f72b92e41278ead319 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Sun, 5 Nov 2017 17:18:46 +0900 Subject: [PATCH 1/4] User lowercase for Windows.h. Fixes #22. --- tiny_gltf.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tiny_gltf.h b/tiny_gltf.h index 901ade8..3df699c 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -661,15 +661,9 @@ class TinyGLTF { #pragma clang diagnostic ignored "-Wreserved-id-macro" #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" #pragma clang diagnostic ignored "-Wpadded" -#ifdef __APPLE__ -#if __clang_major__ >= 8 && __clang_minor__ >= 1 +#if __has_warning("-Wcomma") #pragma clang diagnostic ignored "-Wcomma" #endif -#else // __APPLE__ -#if (__clang_major__ >= 4) || (__clang_major__ >= 3 && __clang_minor__ > 8) -#pragma clang diagnostic ignored "-Wcomma" -#endif -#endif // __APPLE__ #endif #define PICOJSON_USE_INT64 @@ -680,7 +674,7 @@ class TinyGLTF { #endif #ifdef _WIN32 -#include +#include #elif !defined(__ANDROID__) #include #endif From 186322bed665c80e1ce3dca2cc1319b31dbccdd4 Mon Sep 17 00:00:00 2001 From: Emanuel Schrade Date: Mon, 6 Nov 2017 11:14:41 +0100 Subject: [PATCH 2/4] Parse KHR_Lights_cmn extension --- tiny_gltf.h | 159 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 128 insertions(+), 31 deletions(-) diff --git a/tiny_gltf.h b/tiny_gltf.h index 3df699c..80597f2 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -505,6 +505,7 @@ class Node { std::vector weights; // The weights of the instantiated Morph Target Value extras; + ParameterMap extLightsValues; // KHR_lights_cmn extension }; typedef struct { @@ -532,6 +533,12 @@ struct Scene { ParameterMap extras; }; +struct Light { + std::string name; + std::vector color; + std::string type; +}; + class Model { public: Model() {} @@ -550,6 +557,7 @@ class Model { std::vector samplers; std::vector cameras; std::vector scenes; + std::vector lights; int defaultScene; std::vector extensionsUsed; @@ -1838,6 +1846,48 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const picojson::object &o) { return true; } +static bool ParseParameterProperty(Parameter *param, std::string *err, + const picojson::object &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 + // a number. Booleans of any kind aren't supported here. Granted, it + // complicates the Parameter structure and breaks it semantically in the sense + // that the client probably works off the assumption that if the string is + // empty the vector is used, etc. Would a tagged union work? + if (ParseStringProperty(¶m->string_value, err, o, prop, false)) { + // Found string property. + return true; + } else if (ParseNumberArrayProperty(¶m->number_array, err, o, prop, + false)) { + // Found a number array. + return true; + } else if (ParseNumberProperty(&num_val, err, o, prop, false)) { + param->number_array.push_back(num_val); + return true; + } else if (ParseJSONProperty(¶m->json_double_value, err, o, prop, + false)) { + return true; + } else if (ParseBooleanProperty(¶m->bool_value, err, o, prop, false)) { + return true; + } else { + if (required) { + if (err) { + (*err) += "parameter must be a string or number / number array.\n"; + } + } + return false; + } +} + +static bool ParseLight(Light *light, std::string *err, const picojson::object &o) { + ParseStringProperty(&light->name, err, o, "name", false); + ParseNumberArrayProperty(&light->color, err, o, "color", false); + ParseStringProperty(&light->type, err, o, "type", false); + return true; +} + static bool ParseNode(Node *node, std::string *err, const picojson::object &o) { ParseStringProperty(&node->name, err, o, "name", false); @@ -1881,42 +1931,36 @@ static bool ParseNode(Node *node, std::string *err, const picojson::object &o) { ParseExtrasProperty(&(node->extras), o); - return true; -} + picojson::object::const_iterator extensions_object = o.find("extensions"); + if ((extensions_object != o.end()) && + (extensions_object->second).is()) { + const picojson::object &values_object = + (extensions_object->second).get(); -static bool ParseParameterProperty(Parameter *param, std::string *err, - const picojson::object &o, - const std::string &prop, bool required) { - double num_val; + picojson::object::const_iterator it(values_object.begin()); + picojson::object::const_iterator itEnd(values_object.end()); - // A parameter value can either be a string or an array of either a boolean or - // a number. Booleans of any kind aren't supported here. Granted, it - // complicates the Parameter structure and breaks it semantically in the sense - // that the client probably works off the assumption that if the string is - // empty the vector is used, etc. Would a tagged union work? - if (ParseStringProperty(¶m->string_value, err, o, prop, false)) { - // Found string property. - return true; - } else if (ParseNumberArrayProperty(¶m->number_array, err, o, prop, - false)) { - // Found a number array. - return true; - } else if (ParseNumberProperty(&num_val, err, o, prop, false)) { - param->number_array.push_back(num_val); - return true; - } else if (ParseJSONProperty(¶m->json_double_value, err, o, prop, - false)) { - return true; - } else if (ParseBooleanProperty(¶m->bool_value, err, o, prop, false)) { - return true; - } else { - if (required) { - if (err) { - (*err) += "parameter must be a string or number / number array.\n"; + for (; it != itEnd; it++) { + if (it->first == "KHR_lights_cmn" && + (it->second).is()) { + const picojson::object &values_object = + (it->second).get(); + + picojson::object::const_iterator itVal(values_object.begin()); + picojson::object::const_iterator itValEnd(values_object.end()); + + for (; itVal != itValEnd; itVal++) { + Parameter param; + if (ParseParameterProperty(¶m, err, values_object, itVal->first, + false)) { + node->extLightsValues[itVal->first] = param; + } + } } } - return false; } + + return true; } static bool ParseMaterial(Material *material, std::string *err, @@ -2722,6 +2766,35 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str, model->cameras.push_back(camera); } } + + // 15. Parse Extensions + if (v.contains("extensions") && v.get("extensions").is()) { + const picojson::object &root = v.get("extensions").get(); + picojson::object::const_iterator it(root.begin()); + picojson::object::const_iterator itEnd(root.end()); + for (; it != itEnd; ++it) { + // parse KHR_lights_cmn extension + if (it->first == "KHR_lights_cmn" && it->second.is()) { + const picojson::object &object = it->second.get(); + picojson::object::const_iterator it(object.find("lights")); + picojson::object::const_iterator itEnd(object.end()); + if (it == itEnd) + continue; + + const picojson::array &lights = it->second.get(); + picojson::array::const_iterator arrayIt(lights.begin()); + picojson::array::const_iterator arrayItEnd(lights.end()); + for (; arrayIt != arrayItEnd; ++arrayIt) { + Light light; + if (!ParseLight(&light, err, arrayIt->get())) { + return false; + } + model->lights.push_back(light); + } + } + } + + } return true; } @@ -3172,6 +3245,12 @@ static void SerializeGltfMesh(Mesh &mesh, picojson::object &o) { } } +static void SerializeGltfLight(Light &light, picojson::object &o) { + SerializeStringProperty("name", light.name, o); + SerializeNumberArrayProperty("color", light.color, o); + SerializeStringProperty("type", light.type, o); +} + static void SerializeGltfNode(Node &node, picojson::object &o) { if (node.translation.size() > 0) { SerializeNumberArrayProperty("translation", node.translation, o); @@ -3197,6 +3276,15 @@ static void SerializeGltfNode(Node &node, picojson::object &o) { SerializeNumberProperty("camera", node.camera, o); } + if (node.extLightsValues.size()) { + picojson::object values; + SerializeParameterMap(node.extLightsValues, values); + picojson::object lightsExt; + lightsExt.insert(json_object_pair("KHR_lights_cmn", picojson::value(values))); + o.insert(json_object_pair("extensions", picojson::value(lightsExt))); + } + + SerializeStringProperty("name", node.name, o); SerializeNumberArrayProperty("children", node.children, o); } @@ -3443,6 +3531,15 @@ bool TinyGLTF::WriteGltfSceneToFile( } output.insert(json_object_pair("cameras", picojson::value(cameras))); + // LIGHTS + picojson::array lights; + for (unsigned int i = 0; i < model->lights.size(); ++i) { + picojson::object light; + SerializeGltfLight(model->lights[i], light); + lights.push_back(picojson::value(light)); + } + output.insert(json_object_pair("lights", picojson::value(lights))); + WriteGltfFile(filename, picojson::value(output).serialize()); return true; } From b23f6fe492b3df76ced69da9bc6b369c88f32cbd Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Wed, 15 Nov 2017 01:03:09 +0900 Subject: [PATCH 3/4] Fix compile on iOS. Fixes #24. --- tiny_gltf.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tiny_gltf.h b/tiny_gltf.h index 80597f2..b1b5288 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -695,6 +695,10 @@ class TinyGLTF { #endif #endif +#if __APPLE__ + #include "TargetConditionals.h" +#endif + namespace tinygltf { static void swap4(unsigned int *val) { From cd1ddf341d66a9d7887a71e07b79d0d640ea983c Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Wed, 15 Nov 2017 13:55:14 +0900 Subject: [PATCH 4/4] Describe supported platforms in README. Better isnan/isinf availabity test(I guess). --- README.md | 8 +++++++- picojson.h | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bf3aa58..815d036 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,13 @@ Work in process(`devel` branch). Very near to release, but need more tests and e ## Features -* Portable C++. C++-03 with STL dependency only. +* Written in portable C++. C++-03 with STL dependency only. + * [x] macOS + clang(LLVM) + * [x] iOS + clang + * [x] Linux + gcc/clang + * [x] Windows + MinGW + * [x] Android + CrystaX(NDK drop-in replacement) GCC + * [x] Web using Emscripten(LLVM) * Moderate parsing time and memory consumption. * glTF specification v2.0.0 * [x] ASCII glTF diff --git a/picojson.h b/picojson.h index f75c399..939c5d3 100644 --- a/picojson.h +++ b/picojson.h @@ -231,10 +231,13 @@ inline value::value(double n) : type_(number_type), u_() { if ( #ifdef _MSC_VER !_finite(n) -#elif __cplusplus >= 201103L || !(defined(isnan) && defined(isinf)) +#elif __cplusplus >= 201103L std::isnan(n) || std::isinf(n) -#else +#elif defined(isnan) && defined(isinf) isnan(n) || isinf(n) +#else + // ???. No nan&inf check + 0 #endif ) { throw std::overflow_error("");