Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization fixes #64

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 82 additions & 84 deletions tiny_gltf.h
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ class Node {
std::vector<double> translation; // length must be 0 or 3
std::vector<double> matrix; // length must be 0 or 16
std::vector<double> weights; // The weights of the instantiated Morph Target

ExtensionMap extensions;
Value extras;
};
Expand Down Expand Up @@ -1425,9 +1425,9 @@ static std::string MimeToExt(const std::string &mimeType) {
}

static void UpdateImageObject(Image &image, std::string &baseDir, int index,
bool embedImages,
WriteImageDataFunction *WriteImageData = nullptr,
void *user_data = nullptr) {
bool embedImages,
WriteImageDataFunction *WriteImageData = nullptr,
void *user_data = nullptr) {
std::string filename;
std::string ext;

Expand Down Expand Up @@ -1564,37 +1564,27 @@ static bool DecodeDataURI(std::vector<unsigned char> *out,
return true;
}

static bool ParseJsonAsValue(Value* ret, const json &o)
{
static bool ParseJsonAsValue(Value *ret, const json &o) {
Value val{};
switch (o.type())
{
case json::value_t::object:
{
switch (o.type()) {
case json::value_t::object: {
Value::Object value_object;
for (auto it = o.begin(); it != o.end(); it++) {
Value entry;
ParseJsonAsValue(&entry, it.value());
if (entry.Type() != NULL_TYPE)
value_object[it.key()] = entry;
if (entry.Type() != NULL_TYPE) value_object[it.key()] = entry;
}
if (value_object.size() > 0)
val = Value(value_object);
}
break;
case json::value_t::array:
{
if (value_object.size() > 0) val = Value(value_object);
} break;
case json::value_t::array: {
Value::Array value_array;
for (auto it = o.begin(); it != o.end(); it++) {
Value entry;
ParseJsonAsValue(&entry, it.value());
if (entry.Type() != NULL_TYPE)
value_array.push_back(entry);
if (entry.Type() != NULL_TYPE) value_array.push_back(entry);
}
if (value_array.size() > 0)
val = Value(value_array);
}
break;
if (value_array.size() > 0) val = Value(value_array);
} break;
case json::value_t::string:
val = Value(o.get<std::string>());
break;
Expand All @@ -1613,9 +1603,8 @@ static bool ParseJsonAsValue(Value* ret, const json &o)
default:
break;
}
if (ret)
*ret = val;

if (ret) *ret = val;

return val.Type() != NULL_TYPE;
}

Expand Down Expand Up @@ -1869,8 +1858,8 @@ static bool ParseJSONProperty(std::map<std::string, double> *ret,
}

static bool ParseParameterProperty(Parameter *param, std::string *err,
const json &o,
const std::string &prop, bool required) {
const json &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
Expand Down Expand Up @@ -1903,8 +1892,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) {
json::const_iterator it = o.find("extensions");
if (it == o.end()) {
return false;
Expand All @@ -1914,12 +1903,11 @@ static bool ParseExtensionsProperty(ExtensionMap *ret, std::string* err, const j
}
ExtensionMap extensions;
json::const_iterator extIt = it.value().begin();
for(; extIt != it.value().end(); extIt++) {
if (!extIt.value().is_object())
continue;
for (; extIt != it.value().end(); extIt++) {
if (!extIt.value().is_object()) continue;
ParseJsonAsValue(&extensions[extIt.key()], extIt.value());
}
if(ret) {
if (ret) {
(*ret) = extensions;
}
return true;
Expand Down Expand Up @@ -2060,7 +2048,7 @@ static bool ParseTexture(Texture *texture, std::string *err, const json &o,

texture->sampler = static_cast<int>(sampler);
texture->source = static_cast<int>(source);

ParseExtensionsProperty(&texture->extensions, err, o);
ParseExtrasProperty(&texture->extras, o);

Expand Down Expand Up @@ -2463,9 +2451,10 @@ static bool ParseMaterial(Material *material, std::string *err, const json &o) {
}
}
}
} 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
} else {
} 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
} else {
Parameter param;
if (ParseParameterProperty(&param, err, o, it.key(), false)) {
material->additionalValues[it.key()] = param;
Expand Down Expand Up @@ -3498,7 +3487,16 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
// GLTF Serialization
///////////////////////

// typedef std::pair<std::string, json> json_object_pair;
static bool isIdentityMatrix(const std::vector<double> &matrix) {
if (matrix.size() != 16) return false;

return matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 &&
matrix[3] == 0.0 && matrix[4] == 0.0 && matrix[5] == 1.0 &&
matrix[6] == 0.0 && matrix[7] == 0.0 && matrix[8] == 0.0 &&
matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 &&
matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 &&
matrix[15] == 1.0;
}

template <typename T>
static void SerializeNumberProperty(const std::string &key, T number,
Expand Down Expand Up @@ -3542,62 +3540,58 @@ static void SerializeStringArrayProperty(const std::string &key,
obj[key] = vals;
}

static bool ValueToJson(const Value& value, json *ret)
{
static bool ValueToJson(const Value &value, json *ret) {
json obj;
switch (value.Type())
{
switch (value.Type()) {
case NUMBER_TYPE:
obj = json(value.Get<double>());
break;
break;
case INT_TYPE:
obj = json(value.Get<int>());
break;
break;
case BOOL_TYPE:
obj = json(value.Get<bool>());
break;
break;
case STRING_TYPE:
obj = json(value.Get<std::string>());
break;
case ARRAY_TYPE:
{
break;
case ARRAY_TYPE: {
for (unsigned int i = 0; i < value.ArrayLen(); ++i) {
Value elementValue = value.Get(int(i));
json elementJson;
if(ValueToJson(value.Get(int(i)), &elementJson))
json elementJson;
if (ValueToJson(value.Get(int(i)), &elementJson))
obj.push_back(elementJson);
}
break;
}
break;
}
case BINARY_TYPE:
//TODO
//obj = json(value.Get<std::vector<unsigned char>>());
// TODO
// obj = json(value.Get<std::vector<unsigned char>>());
return false;
break;
case OBJECT_TYPE:
{
case OBJECT_TYPE: {
Value::Object objMap = value.Get<Value::Object>();
for (auto& it : objMap) {
for (auto &it : objMap) {
json elementJson;
if (ValueToJson(it.second, &elementJson))
obj[it.first] = elementJson;
if (ValueToJson(it.second, &elementJson)) obj[it.first] = elementJson;
}
break;
}
case NULL_TYPE:
default:
return false;
}
if (ret)
*ret = obj;
break;
}
case NULL_TYPE: {
obj = json::object({});
break;
}
default:
return false;
}
if (ret) *ret = obj;
return true;
}

static void SerializeValue(const std::string &key, const Value &value,
json &obj) {
json ret;
if (ValueToJson(value, &ret))
obj[key] = ret;
if (ValueToJson(value, &ret)) obj[key] = ret;
}

static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
Expand All @@ -3619,7 +3613,9 @@ static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
static void SerializeParameterMap(ParameterMap &param, json &o) {
for (ParameterMap::iterator paramIt = param.begin(); paramIt != param.end();
++paramIt) {
if (paramIt->second.number_array.size()) {
if (paramIt->second.number_array.size() == 1) {
SerializeNumberProperty(paramIt->first, paramIt->second.Factor(), o);
} else if (paramIt->second.number_array.size() > 1) {
SerializeNumberArrayProperty<double>(paramIt->first,
paramIt->second.number_array, o);
} else if (paramIt->second.json_double_value.size()) {
Expand All @@ -3640,15 +3636,14 @@ static void SerializeParameterMap(ParameterMap &param, json &o) {
}
}

static void SerializeExtensionMap(ExtensionMap &extensions, json &o)
{
if(!extensions.size())
return;
static void SerializeExtensionMap(ExtensionMap &extensions, json &o) {
if (!extensions.size()) return;

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;
SerializeValue(extIt->first, extIt->second, extMap);
SerializeValue(extIt->first, extIt->second, extMap);
}
o["extensions"] = extMap;
}
Expand Down Expand Up @@ -3740,7 +3735,7 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
if (asset.extras.Keys().size()) {
SerializeValue("extras", asset.extras, o);
}

SerializeExtensionMap(asset.extensions, o);
}

Expand Down Expand Up @@ -3792,10 +3787,13 @@ static void SerializeGltfImage(Image &image, json &o) {
}

static void SerializeGltfMaterial(Material &material, json &o) {

if (material.extras.Size())
if (material.extras.Size()) {
SerializeValue("extras", material.extras, o);
SerializeExtensionMap(material.extensions, o);
}

if (material.extensions.size()) {
SerializeExtensionMap(material.extensions, o);
}

if (material.values.size()) {
json pbrMetallicRoughness;
Expand Down Expand Up @@ -3881,7 +3879,7 @@ static void SerializeGltfNode(Node &node, json &o) {
if (node.scale.size() > 0) {
SerializeNumberArrayProperty<double>("scale", node.scale, o);
}
if (node.matrix.size() > 0) {
if (node.matrix.size() > 0 && !isIdentityMatrix(node.matrix)) {
SerializeNumberArrayProperty<double>("matrix", node.matrix, o);
}
if (node.mesh != -1) {
Expand Down Expand Up @@ -4203,7 +4201,7 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
ext_j["KHR_lights_cmn"] = khr_lights_cmn;

output["extensions"] = ext_j;
}
}

WriteGltfFile(filename, output.dump());
return true;
Expand Down