From ab7b21838579b9dfff1d146aca641cc1ffd9d850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Chatelain?= Date: Wed, 24 May 2017 09:53:44 +0000 Subject: [PATCH] Updates materials (glTF 2.0) glTF 2.0 has now PBR materials. Core material is Metallic/Roughness material Specular/glossiness is still in an extension Material properties can be number arrays (colors/factors) or JSON objects (textures) --- tiny_gltf_loader.h | 125 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 19 deletions(-) diff --git a/tiny_gltf_loader.h b/tiny_gltf_loader.h index aa3ee3f..9f647f1 100644 --- a/tiny_gltf_loader.h +++ b/tiny_gltf_loader.h @@ -272,8 +272,10 @@ TINYGLTF_VALUE_GET(Value::Object, object_value_) #undef TINYGLTF_VALUE_GET typedef struct { + bool bool_value; std::string string_value; std::vector number_array; + std::map json_double_value; } Parameter; typedef std::map ParameterMap; @@ -357,13 +359,18 @@ struct Texture { } }; -typedef struct { +// Each extension should be stored in a ParameterMap. +// members not in the values could be included in the ParameterMap +// to keep a single material model +struct Material { std::string name; - std::string technique; - ParameterMap values; + ParameterMap values; // PBR metal/roughness workflow + ParameterMap additionalValues; // normal/occlusion/emissive values + ParameterMap extCommonValues; // KHR_common_material extension + ParameterMap extPBRValues; Value extras; -} Material; +}; struct BufferView{ std::string name; @@ -1301,6 +1308,43 @@ static bool ParseKHRBinaryExtension(const picojson::object &o, std::string *err, return true; } +static bool ParseJSONProperty(std::map *ret, std::string *err, + const picojson::object &o, + const std::string &property, + bool required) +{ + picojson::object::const_iterator it = o.find(property); + if(it == o.end()) + { + if (required) { + if(err) { + (*err) += "'" + property + "' property is missing. \n'"; + } + } + return false; + } + + if(!it->second.is()) { + if (required) { + if (err) { + (*err) += "'" + property + "' property is not a JSON object.\n"; + } + } + return false; + } + + ret->clear(); + const picojson::object &obj = it->second.get(); + picojson::object::const_iterator it2(obj.begin()); + picojson::object::const_iterator itEnd(obj.end()); + for (; it2 != itEnd; it2++) { + if(it2->second.is()) + ret->insert(std::pair(it2->first, it2->second.get())); + } + + return true; +} + static bool ParseAsset(Asset *asset, std::string *err, const picojson::object &o) { ParseStringProperty(&asset->generator, err, o, "generator", false); @@ -1776,6 +1820,10 @@ static bool ParseParameterProperty(Parameter *param, std::string *err, } 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) { @@ -1787,28 +1835,67 @@ static bool ParseParameterProperty(Parameter *param, std::string *err, } static bool ParseMaterial(Material *material, std::string *err, - const picojson::object &o) { - ParseStringProperty(&material->name, err, o, "name", false); - ParseStringProperty(&material->technique, err, o, "technique", false); + const picojson::object &o) { material->values.clear(); - picojson::object::const_iterator valuesIt = o.find("values"); + material->extPBRValues.clear(); + material->additionalValues.clear(); - if ((valuesIt != o.end()) && (valuesIt->second).is()) { - const picojson::object &values_object = - (valuesIt->second).get(); + picojson::object::const_iterator it(o.begin()); + picojson::object::const_iterator itEnd(o.end()); - picojson::object::const_iterator it(values_object.begin()); - picojson::object::const_iterator itEnd(values_object.end()); + for (; it != itEnd; it++) { + if(it->first == "pbrMetallicRoughness") + { + if ((it->second).is()) { + const picojson::object &values_object = + (it->second).get(); - for (; it != itEnd; it++) { - Parameter param; - if (ParseParameterProperty(¶m, err, values_object, it->first, - false)) { - material->values[it->first] = param; + picojson::object::const_iterator itVal(values_object.begin()); + picojson::object::const_iterator itEnd(values_object.end()); + + for (; itVal != itEnd; itVal++) { + Parameter param; + if (ParseParameterProperty(¶m, err, values_object, itVal->first, + false)) { + material->values[itVal->first] = param; + } + } + } + } + else if(it->first == "extensions") + { + if ((it->second).is()) { + const picojson::object &extension = (it->second).get(); + + picojson::object::const_iterator extIt = extension.begin(); + if(!extIt->second.is()) + continue; + + const picojson::object &values_object = + (extIt->second).get(); + + picojson::object::const_iterator itVal(values_object.begin()); + picojson::object::const_iterator itEnd(values_object.end()); + + for (; itVal != itEnd; itVal++) { + Parameter param; + if (ParseParameterProperty(¶m, err, values_object, itVal->first, + false)) { + material->extPBRValues[itVal->first] = param; + } + } + } + } + else + { + Parameter param; + if (ParseParameterProperty(¶m, err, o, it->first, + false)) { + material->additionalValues[it->first] = param; + } } } - } ParseExtrasProperty(&(material->extras), o);