mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-08-14 12:55:52 +08:00
Merge pull request #69 from benbuzbee/serialization-fixes
Serialization fixes for single-number values and integers
This commit is contained in:
commit
7c56f8eb9e
164
tiny_gltf.h
164
tiny_gltf.h
@ -334,10 +334,11 @@ using ColorValue = std::array<double, 4>;
|
|||||||
|
|
||||||
struct Parameter {
|
struct Parameter {
|
||||||
bool bool_value;
|
bool bool_value;
|
||||||
|
bool has_number_value = false;
|
||||||
std::string string_value;
|
std::string string_value;
|
||||||
std::vector<double> number_array;
|
std::vector<double> number_array;
|
||||||
std::map<std::string, double> json_double_value;
|
std::map<std::string, double> json_double_value;
|
||||||
|
double number_value;
|
||||||
// context sensitive methods. depending the type of the Parameter you are
|
// context sensitive methods. depending the type of the Parameter you are
|
||||||
// accessing, these are either valid or not
|
// accessing, these are either valid or not
|
||||||
// If this parameter represent a texture map in a material, will return the
|
// If this parameter represent a texture map in a material, will return the
|
||||||
@ -357,7 +358,7 @@ struct Parameter {
|
|||||||
/// Material factor, like the roughness or metalness of a material
|
/// Material factor, like the roughness or metalness of a material
|
||||||
/// Returned value is only valid if the parameter represent a texture from a
|
/// Returned value is only valid if the parameter represent a texture from a
|
||||||
/// material
|
/// material
|
||||||
double Factor() const { return number_array[0]; }
|
double Factor() const { return number_value; }
|
||||||
|
|
||||||
/// Return the color of a material
|
/// Return the color of a material
|
||||||
/// Returned value is only valid if the parameter represent a texture from a
|
/// Returned value is only valid if the parameter represent a texture from a
|
||||||
@ -650,7 +651,7 @@ class Node {
|
|||||||
std::vector<double> translation; // length must be 0 or 3
|
std::vector<double> translation; // length must be 0 or 3
|
||||||
std::vector<double> matrix; // length must be 0 or 16
|
std::vector<double> matrix; // length must be 0 or 16
|
||||||
std::vector<double> weights; // The weights of the instantiated Morph Target
|
std::vector<double> weights; // The weights of the instantiated Morph Target
|
||||||
|
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
Value extras;
|
Value extras;
|
||||||
};
|
};
|
||||||
@ -1425,9 +1426,9 @@ static std::string MimeToExt(const std::string &mimeType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateImageObject(Image &image, std::string &baseDir, int index,
|
static void UpdateImageObject(Image &image, std::string &baseDir, int index,
|
||||||
bool embedImages,
|
bool embedImages,
|
||||||
WriteImageDataFunction *WriteImageData = nullptr,
|
WriteImageDataFunction *WriteImageData = nullptr,
|
||||||
void *user_data = nullptr) {
|
void *user_data = nullptr) {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string ext;
|
std::string ext;
|
||||||
|
|
||||||
@ -1564,37 +1565,27 @@ static bool DecodeDataURI(std::vector<unsigned char> *out,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseJsonAsValue(Value* ret, const json &o)
|
static bool ParseJsonAsValue(Value *ret, const json &o) {
|
||||||
{
|
|
||||||
Value val{};
|
Value val{};
|
||||||
switch (o.type())
|
switch (o.type()) {
|
||||||
{
|
case json::value_t::object: {
|
||||||
case json::value_t::object:
|
|
||||||
{
|
|
||||||
Value::Object value_object;
|
Value::Object value_object;
|
||||||
for (auto it = o.begin(); it != o.end(); it++) {
|
for (auto it = o.begin(); it != o.end(); it++) {
|
||||||
Value entry;
|
Value entry;
|
||||||
ParseJsonAsValue(&entry, it.value());
|
ParseJsonAsValue(&entry, it.value());
|
||||||
if (entry.Type() != NULL_TYPE)
|
if (entry.Type() != NULL_TYPE) value_object[it.key()] = entry;
|
||||||
value_object[it.key()] = entry;
|
|
||||||
}
|
}
|
||||||
if (value_object.size() > 0)
|
if (value_object.size() > 0) val = Value(value_object);
|
||||||
val = Value(value_object);
|
} break;
|
||||||
}
|
case json::value_t::array: {
|
||||||
break;
|
|
||||||
case json::value_t::array:
|
|
||||||
{
|
|
||||||
Value::Array value_array;
|
Value::Array value_array;
|
||||||
for (auto it = o.begin(); it != o.end(); it++) {
|
for (auto it = o.begin(); it != o.end(); it++) {
|
||||||
Value entry;
|
Value entry;
|
||||||
ParseJsonAsValue(&entry, it.value());
|
ParseJsonAsValue(&entry, it.value());
|
||||||
if (entry.Type() != NULL_TYPE)
|
if (entry.Type() != NULL_TYPE) value_array.push_back(entry);
|
||||||
value_array.push_back(entry);
|
|
||||||
}
|
}
|
||||||
if (value_array.size() > 0)
|
if (value_array.size() > 0) val = Value(value_array);
|
||||||
val = Value(value_array);
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case json::value_t::string:
|
case json::value_t::string:
|
||||||
val = Value(o.get<std::string>());
|
val = Value(o.get<std::string>());
|
||||||
break;
|
break;
|
||||||
@ -1610,12 +1601,11 @@ static bool ParseJsonAsValue(Value* ret, const json &o)
|
|||||||
break;
|
break;
|
||||||
case json::value_t::null:
|
case json::value_t::null:
|
||||||
case json::value_t::discarded:
|
case json::value_t::discarded:
|
||||||
//default:
|
// default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret) *ret = val;
|
||||||
*ret = val;
|
|
||||||
|
|
||||||
return val.Type() != NULL_TYPE;
|
return val.Type() != NULL_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1869,10 +1859,8 @@ static bool ParseJSONProperty(std::map<std::string, double> *ret,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseParameterProperty(Parameter *param, std::string *err,
|
static bool ParseParameterProperty(Parameter *param, std::string *err,
|
||||||
const json &o,
|
const json &o, const std::string &prop,
|
||||||
const std::string &prop, bool required) {
|
bool required) {
|
||||||
double num_val;
|
|
||||||
|
|
||||||
// A parameter value can either be a string or an array of either a boolean or
|
// 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
|
// a number. Booleans of any kind aren't supported here. Granted, it
|
||||||
// complicates the Parameter structure and breaks it semantically in the sense
|
// complicates the Parameter structure and breaks it semantically in the sense
|
||||||
@ -1885,9 +1873,8 @@ static bool ParseParameterProperty(Parameter *param, std::string *err,
|
|||||||
false)) {
|
false)) {
|
||||||
// Found a number array.
|
// Found a number array.
|
||||||
return true;
|
return true;
|
||||||
} else if (ParseNumberProperty(&num_val, err, o, prop, false)) {
|
} else if (ParseNumberProperty(¶m->number_value, err, o, prop, false)) {
|
||||||
param->number_array.push_back(num_val);
|
return param->has_number_value = true;
|
||||||
return true;
|
|
||||||
} else if (ParseJSONProperty(¶m->json_double_value, err, o, prop,
|
} else if (ParseJSONProperty(¶m->json_double_value, err, o, prop,
|
||||||
false)) {
|
false)) {
|
||||||
return true;
|
return true;
|
||||||
@ -1903,8 +1890,8 @@ static bool ParseParameterProperty(Parameter *param, std::string *err,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseExtensionsProperty(ExtensionMap *ret, std::string* err, const json &o)
|
static bool ParseExtensionsProperty(ExtensionMap *ret, std::string *err,
|
||||||
{
|
const json &o) {
|
||||||
(void)err;
|
(void)err;
|
||||||
|
|
||||||
json::const_iterator it = o.find("extensions");
|
json::const_iterator it = o.find("extensions");
|
||||||
@ -1916,12 +1903,11 @@ static bool ParseExtensionsProperty(ExtensionMap *ret, std::string* err, const j
|
|||||||
}
|
}
|
||||||
ExtensionMap extensions;
|
ExtensionMap extensions;
|
||||||
json::const_iterator extIt = it.value().begin();
|
json::const_iterator extIt = it.value().begin();
|
||||||
for(; extIt != it.value().end(); extIt++) {
|
for (; extIt != it.value().end(); extIt++) {
|
||||||
if (!extIt.value().is_object())
|
if (!extIt.value().is_object()) continue;
|
||||||
continue;
|
|
||||||
ParseJsonAsValue(&extensions[extIt.key()], extIt.value());
|
ParseJsonAsValue(&extensions[extIt.key()], extIt.value());
|
||||||
}
|
}
|
||||||
if(ret) {
|
if (ret) {
|
||||||
(*ret) = extensions;
|
(*ret) = extensions;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -2062,7 +2048,7 @@ static bool ParseTexture(Texture *texture, std::string *err, const json &o,
|
|||||||
|
|
||||||
texture->sampler = static_cast<int>(sampler);
|
texture->sampler = static_cast<int>(sampler);
|
||||||
texture->source = static_cast<int>(source);
|
texture->source = static_cast<int>(source);
|
||||||
|
|
||||||
ParseExtensionsProperty(&texture->extensions, err, o);
|
ParseExtensionsProperty(&texture->extensions, err, o);
|
||||||
ParseExtrasProperty(&texture->extras, o);
|
ParseExtrasProperty(&texture->extras, o);
|
||||||
|
|
||||||
@ -2465,9 +2451,10 @@ static bool ParseMaterial(Material *material, std::string *err, const json &o) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (it.key() == "extensions" || it.key() == "extras") {
|
} else if (it.key() == "extensions" || it.key() == "extras") {
|
||||||
// done later, skip, otherwise poorly parsed contents will be saved in the parametermap and serialized again later
|
// done later, skip, otherwise poorly parsed contents will be saved in the
|
||||||
} else {
|
// parametermap and serialized again later
|
||||||
|
} else {
|
||||||
Parameter param;
|
Parameter param;
|
||||||
if (ParseParameterProperty(¶m, err, o, it.key(), false)) {
|
if (ParseParameterProperty(¶m, err, o, it.key(), false)) {
|
||||||
material->additionalValues[it.key()] = param;
|
material->additionalValues[it.key()] = param;
|
||||||
@ -3519,7 +3506,7 @@ static void SerializeNumberArrayProperty(const std::string &key,
|
|||||||
json vals;
|
json vals;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < value.size(); ++i) {
|
for (unsigned int i = 0; i < value.size(); ++i) {
|
||||||
vals.push_back(static_cast<double>(value[i]));
|
vals.push_back(static_cast<T>(value[i]));
|
||||||
}
|
}
|
||||||
if (!vals.is_null()) {
|
if (!vals.is_null()) {
|
||||||
obj[key] = vals;
|
obj[key] = vals;
|
||||||
@ -3544,62 +3531,55 @@ static void SerializeStringArrayProperty(const std::string &key,
|
|||||||
obj[key] = vals;
|
obj[key] = vals;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ValueToJson(const Value& value, json *ret)
|
static bool ValueToJson(const Value &value, json *ret) {
|
||||||
{
|
|
||||||
json obj;
|
json obj;
|
||||||
switch (value.Type())
|
switch (value.Type()) {
|
||||||
{
|
|
||||||
case NUMBER_TYPE:
|
case NUMBER_TYPE:
|
||||||
obj = json(value.Get<double>());
|
obj = json(value.Get<double>());
|
||||||
break;
|
break;
|
||||||
case INT_TYPE:
|
case INT_TYPE:
|
||||||
obj = json(value.Get<int>());
|
obj = json(value.Get<int>());
|
||||||
break;
|
break;
|
||||||
case BOOL_TYPE:
|
case BOOL_TYPE:
|
||||||
obj = json(value.Get<bool>());
|
obj = json(value.Get<bool>());
|
||||||
break;
|
break;
|
||||||
case STRING_TYPE:
|
case STRING_TYPE:
|
||||||
obj = json(value.Get<std::string>());
|
obj = json(value.Get<std::string>());
|
||||||
break;
|
break;
|
||||||
case ARRAY_TYPE:
|
case ARRAY_TYPE: {
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < value.ArrayLen(); ++i) {
|
for (unsigned int i = 0; i < value.ArrayLen(); ++i) {
|
||||||
Value elementValue = value.Get(int(i));
|
Value elementValue = value.Get(int(i));
|
||||||
json elementJson;
|
json elementJson;
|
||||||
if(ValueToJson(value.Get(int(i)), &elementJson))
|
if (ValueToJson(value.Get(int(i)), &elementJson))
|
||||||
obj.push_back(elementJson);
|
obj.push_back(elementJson);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BINARY_TYPE:
|
case BINARY_TYPE:
|
||||||
//TODO
|
// TODO
|
||||||
//obj = json(value.Get<std::vector<unsigned char>>());
|
// obj = json(value.Get<std::vector<unsigned char>>());
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case OBJECT_TYPE:
|
case OBJECT_TYPE: {
|
||||||
{
|
|
||||||
Value::Object objMap = value.Get<Value::Object>();
|
Value::Object objMap = value.Get<Value::Object>();
|
||||||
for (auto& it : objMap) {
|
for (auto &it : objMap) {
|
||||||
json elementJson;
|
json elementJson;
|
||||||
if (ValueToJson(it.second, &elementJson))
|
if (ValueToJson(it.second, &elementJson)) obj[it.first] = elementJson;
|
||||||
obj[it.first] = elementJson;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NULL_TYPE:
|
case NULL_TYPE:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret) *ret = obj;
|
||||||
*ret = obj;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeValue(const std::string &key, const Value &value,
|
static void SerializeValue(const std::string &key, const Value &value,
|
||||||
json &obj) {
|
json &obj) {
|
||||||
json ret;
|
json ret;
|
||||||
if (ValueToJson(value, &ret))
|
if (ValueToJson(value, &ret)) obj[key] = ret;
|
||||||
obj[key] = ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
|
static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
|
||||||
@ -3626,31 +3606,35 @@ static void SerializeParameterMap(ParameterMap ¶m, json &o) {
|
|||||||
paramIt->second.number_array, o);
|
paramIt->second.number_array, o);
|
||||||
} else if (paramIt->second.json_double_value.size()) {
|
} else if (paramIt->second.json_double_value.size()) {
|
||||||
json json_double_value;
|
json json_double_value;
|
||||||
|
|
||||||
for (std::map<std::string, double>::iterator it =
|
for (std::map<std::string, double>::iterator it =
|
||||||
paramIt->second.json_double_value.begin();
|
paramIt->second.json_double_value.begin();
|
||||||
it != paramIt->second.json_double_value.end(); ++it) {
|
it != paramIt->second.json_double_value.end(); ++it) {
|
||||||
json_double_value[it->first] = it->second;
|
if (it->first == "index") {
|
||||||
|
json_double_value[it->first] = paramIt->second.TextureIndex();
|
||||||
|
} else {
|
||||||
|
json_double_value[it->first] = it->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
o[paramIt->first] = json_double_value;
|
o[paramIt->first] = json_double_value;
|
||||||
} else if (!paramIt->second.string_value.empty()) {
|
} else if (!paramIt->second.string_value.empty()) {
|
||||||
SerializeStringProperty(paramIt->first, paramIt->second.string_value, o);
|
SerializeStringProperty(paramIt->first, paramIt->second.string_value, o);
|
||||||
|
} else if (paramIt->second.has_number_value) {
|
||||||
|
o[paramIt->first] = paramIt->second.number_value;
|
||||||
} else {
|
} else {
|
||||||
o[paramIt->first] = paramIt->second.bool_value;
|
o[paramIt->first] = paramIt->second.bool_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeExtensionMap(ExtensionMap &extensions, json &o)
|
static void SerializeExtensionMap(ExtensionMap &extensions, json &o) {
|
||||||
{
|
if (!extensions.size()) return;
|
||||||
if(!extensions.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
json extMap;
|
json extMap;
|
||||||
for(ExtensionMap::iterator extIt = extensions.begin(); extIt != extensions.end(); ++extIt) {
|
for (ExtensionMap::iterator extIt = extensions.begin();
|
||||||
|
extIt != extensions.end(); ++extIt) {
|
||||||
json extension_values;
|
json extension_values;
|
||||||
SerializeValue(extIt->first, extIt->second, extMap);
|
SerializeValue(extIt->first, extIt->second, extMap);
|
||||||
}
|
}
|
||||||
o["extensions"] = extMap;
|
o["extensions"] = extMap;
|
||||||
}
|
}
|
||||||
@ -3742,7 +3726,7 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
|
|||||||
if (asset.extras.Keys().size()) {
|
if (asset.extras.Keys().size()) {
|
||||||
SerializeValue("extras", asset.extras, o);
|
SerializeValue("extras", asset.extras, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializeExtensionMap(asset.extensions, o);
|
SerializeExtensionMap(asset.extensions, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3794,9 +3778,7 @@ static void SerializeGltfImage(Image &image, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfMaterial(Material &material, json &o) {
|
static void SerializeGltfMaterial(Material &material, json &o) {
|
||||||
|
if (material.extras.Size()) SerializeValue("extras", material.extras, o);
|
||||||
if (material.extras.Size())
|
|
||||||
SerializeValue("extras", material.extras, o);
|
|
||||||
SerializeExtensionMap(material.extensions, o);
|
SerializeExtensionMap(material.extensions, o);
|
||||||
|
|
||||||
if (material.values.size()) {
|
if (material.values.size()) {
|
||||||
@ -4205,7 +4187,7 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
|
|||||||
ext_j["KHR_lights_cmn"] = khr_lights_cmn;
|
ext_j["KHR_lights_cmn"] = khr_lights_cmn;
|
||||||
|
|
||||||
output["extensions"] = ext_j;
|
output["extensions"] = ext_j;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteGltfFile(filename, output.dump());
|
WriteGltfFile(filename, output.dump());
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user