From 36c8cdf3dee0f846eef2bd82e8564925ef2077bc Mon Sep 17 00:00:00 2001 From: Evangel Date: Sat, 12 Jun 2021 11:44:28 +1000 Subject: [PATCH 1/7] Add scene metadata for glTF2 files as allowed by the glTF2 specification. --- code/AssetLib/glTF2/glTF2Asset.h | 2 ++ code/AssetLib/glTF2/glTF2Asset.inl | 3 +++ code/AssetLib/glTF2/glTF2Importer.cpp | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 6aa0f92ed..b1fba7bd5 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -922,6 +922,8 @@ struct Scene : public Object { std::string name; std::vector> nodes; + CustomExtension extensions; + Scene() {} void Read(Value &obj, Asset &r); }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index c4b1e72ee..14088353c 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1803,6 +1803,9 @@ inline void Scene::Read(Value &obj, Asset &r) { this->nodes.push_back(node); } } + if (Value *extensions = FindObject(obj, "extensions")) { + this->extensions = ReadExtensions("extensions", *extensions); + } } inline void Skin::Read(Value &obj, Asset &r) { diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index c62989c3b..9ba6270ed 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -1498,7 +1498,8 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); const bool hasCopyright = !a.asset.copyright.empty(); - if (hasVersion || hasGenerator || hasCopyright) { + const bool hasSceneMetadata = a.scene->extensions; + if (hasVersion || hasGenerator || hasCopyright || hasSceneMetadata) { mScene->mMetaData = new aiMetadata; if (hasVersion) { mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); @@ -1509,6 +1510,9 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { if (hasCopyright) { mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); } + if (hasSceneMetadata) { + ParseExtensions(mScene->mMetaData, a.scene->extensions); + } } } From 5be2330fbb969e8e8f669fc2f225cd6cb594674c Mon Sep 17 00:00:00 2001 From: Evangel Date: Sat, 12 Jun 2021 12:20:40 +1000 Subject: [PATCH 2/7] Added CustomExtension to glTF2::Object so that all subclasses have it instead of doing it piecemeal. --- code/AssetLib/glTF2/glTF2Asset.h | 95 ++++++++++++++++---------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index b1fba7bd5..4aec48586 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -356,6 +356,51 @@ struct Nullable { isPresent(true) {} }; +struct CustomExtension { + // + // A struct containing custom extension data added to a glTF2 file + // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum + // String, Double, Uint64, and Int64 are stored in the Nullables + // Object and Array are stored in the std::vector + // + std::string name; + + Nullable mStringValue; + Nullable mDoubleValue; + Nullable mUint64Value; + Nullable mInt64Value; + Nullable mBoolValue; + + // std::vector handles both Object and Array + Nullable> mValues; + + operator bool() const { + return Size() != 0; + } + + size_t Size() const { + if (mValues.isPresent) { + return mValues.value.size(); + } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) { + return 1; + } + return 0; + } + + CustomExtension() = default; + + CustomExtension(const CustomExtension &other) + : name(other.name) + , mStringValue(other.mStringValue) + , mDoubleValue(other.mDoubleValue) + , mUint64Value(other.mUint64Value) + , mInt64Value(other.mInt64Value) + , mBoolValue(other.mBoolValue) + , mValues(other.mValues) + { + } +}; + //! Base class for all glTF top-level objects struct Object { int index; //!< The index of this object within its property container @@ -363,6 +408,8 @@ struct Object { std::string id; //!< The globally unique ID used to reference this object std::string name; //!< The user-defined name of this object + CustomExtension extensions; + //! Objects marked as special are not exported (used to emulate the binary body buffer) virtual bool IsSpecial() const { return false; } @@ -834,50 +881,6 @@ struct Mesh : public Object { void Read(Value &pJSON_Object, Asset &pAsset_Root); }; -struct CustomExtension : public Object { - // - // A struct containing custom extension data added to a glTF2 file - // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum - // String, Double, Uint64, and Int64 are stored in the Nullables - // Object and Array are stored in the std::vector - // - - Nullable mStringValue; - Nullable mDoubleValue; - Nullable mUint64Value; - Nullable mInt64Value; - Nullable mBoolValue; - - // std::vector handles both Object and Array - Nullable> mValues; - - operator bool() const { - return Size() != 0; - } - - size_t Size() const { - if (mValues.isPresent) { - return mValues.value.size(); - } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) { - return 1; - } - return 0; - } - - CustomExtension() = default; - - CustomExtension(const CustomExtension &other) - : Object(other) - , mStringValue(other.mStringValue) - , mDoubleValue(other.mDoubleValue) - , mUint64Value(other.mUint64Value) - , mInt64Value(other.mInt64Value) - , mBoolValue(other.mBoolValue) - , mValues(other.mValues) - { - } -}; - struct Node : public Object { std::vector> children; std::vector> meshes; @@ -896,8 +899,6 @@ struct Node : public Object { Ref parent; //!< This is not part of the glTF specification. Used as a helper. - CustomExtension extensions; - Node() {} void Read(Value &obj, Asset &r); }; @@ -922,8 +923,6 @@ struct Scene : public Object { std::string name; std::vector> nodes; - CustomExtension extensions; - Scene() {} void Read(Value &obj, Asset &r); }; From 7f0efa0866920ec15dd5e268befb67125ff7f6c0 Mon Sep 17 00:00:00 2001 From: Evangel Date: Sat, 12 Jun 2021 12:50:44 +1000 Subject: [PATCH 3/7] Added ReadExtensions to glTF2::Object, so all objects now have their extensions read. Importer is the only place that needs to be modified to make them available on the Assimp side now. --- code/AssetLib/glTF2/glTF2Asset.h | 2 + code/AssetLib/glTF2/glTF2Asset.inl | 85 ++++++++++++++++-------------- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 4aec48586..759411b13 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -424,6 +424,8 @@ struct Object { inline Value *FindArray(Value &val, const char *id); inline Value *FindObject(Value &val, const char *id); inline Value *FindExtension(Value &val, const char *extensionId); + + inline void ReadExtensions(Value &val); }; // diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 135def597..24fc48b3e 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -304,6 +304,43 @@ inline Value *FindObject(Document &doc, const char *memberId) { inline Value *FindExtension(Value &val, const char *extensionId) { return FindExtensionInContext(val, extensionId, "the document"); } + +inline CustomExtension ReadExtensions(const char *name, Value &obj) { + CustomExtension ret; + ret.name = name; + if (obj.IsObject()) { + ret.mValues.isPresent = true; + for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { + auto &val = it->value; + ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); + } + } else if (obj.IsArray()) { + ret.mValues.value.reserve(obj.Size()); + ret.mValues.isPresent = true; + for (unsigned int i = 0; i < obj.Size(); ++i) { + ret.mValues.value.push_back(ReadExtensions(name, obj[i])); + } + } else if (obj.IsNumber()) { + if (obj.IsUint64()) { + ret.mUint64Value.value = obj.GetUint64(); + ret.mUint64Value.isPresent = true; + } else if (obj.IsInt64()) { + ret.mInt64Value.value = obj.GetInt64(); + ret.mInt64Value.isPresent = true; + } else if (obj.IsDouble()) { + ret.mDoubleValue.value = obj.GetDouble(); + ret.mDoubleValue.isPresent = true; + } + } else if (obj.IsString()) { + ReadValue(obj, ret.mStringValue); + ret.mStringValue.isPresent = true; + } else if (obj.IsBool()) { + ret.mBoolValue.value = obj.GetBool(); + ret.mBoolValue.isPresent = true; + } + return ret; +} + } // namespace inline Value *Object::FindString(Value &val, const char *memberId) { @@ -330,6 +367,12 @@ inline Value *Object::FindExtension(Value &val, const char *extensionId) { return FindExtensionInContext(val, extensionId, id.c_str(), name.c_str()); } +inline void Object::ReadExtensions(Value &val) { + if (Value *extensions = FindObject(val, "extensions")) { + this->extensions = glTF2::ReadExtensions("extensions", *extensions); + } +} + #ifdef ASSIMP_ENABLE_DRACO template @@ -569,6 +612,7 @@ Ref LazyDict::Retrieve(unsigned int i) { inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); + inst->ReadExtensions(obj); Ref result = Add(inst.release()); mRecursiveReferenceCheck.erase(i); @@ -1683,42 +1727,6 @@ inline void Light::Read(Value &obj, Asset & /*r*/) { } } -inline CustomExtension ReadExtensions(const char *name, Value &obj) { - CustomExtension ret; - ret.name = name; - if (obj.IsObject()) { - ret.mValues.isPresent = true; - for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { - auto &val = it->value; - ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); - } - } else if (obj.IsArray()) { - ret.mValues.value.reserve(obj.Size()); - ret.mValues.isPresent = true; - for (unsigned int i = 0; i < obj.Size(); ++i) { - ret.mValues.value.push_back(ReadExtensions(name, obj[i])); - } - } else if (obj.IsNumber()) { - if (obj.IsUint64()) { - ret.mUint64Value.value = obj.GetUint64(); - ret.mUint64Value.isPresent = true; - } else if (obj.IsInt64()) { - ret.mInt64Value.value = obj.GetInt64(); - ret.mInt64Value.isPresent = true; - } else if (obj.IsDouble()) { - ret.mDoubleValue.value = obj.GetDouble(); - ret.mDoubleValue.isPresent = true; - } - } else if (obj.IsString()) { - ReadValue(obj, ret.mStringValue); - ret.mStringValue.isPresent = true; - } else if (obj.IsBool()) { - ret.mBoolValue.value = obj.GetBool(); - ret.mBoolValue.isPresent = true; - } - return ret; -} - inline void Node::Read(Value &obj, Asset &r) { if (name.empty()) { name = id; @@ -1775,8 +1783,6 @@ inline void Node::Read(Value &obj, Asset &r) { Value *curExtensions = FindObject(obj, "extensions"); if (nullptr != curExtensions) { - this->extensions = ReadExtensions("extensions", *curExtensions); - if (r.extensionsUsed.KHR_lights_punctual) { if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) { Value *curLight = FindUInt(*ext, "light"); @@ -1805,9 +1811,6 @@ inline void Scene::Read(Value &obj, Asset &r) { this->nodes.push_back(node); } } - if (Value *extensions = FindObject(obj, "extensions")) { - this->extensions = ReadExtensions("extensions", *extensions); - } } inline void Skin::Read(Value &obj, Asset &r) { From a7a30baf27fd0e9dac8e512aff1c4a37cefa93eb Mon Sep 17 00:00:00 2001 From: Evangel Date: Sat, 12 Jun 2021 13:08:14 +1000 Subject: [PATCH 4/7] Renamed local variable to avoid shadowing member variable. --- code/AssetLib/glTF2/glTF2Asset.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 24fc48b3e..8175ab428 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -368,8 +368,8 @@ inline Value *Object::FindExtension(Value &val, const char *extensionId) { } inline void Object::ReadExtensions(Value &val) { - if (Value *extensions = FindObject(val, "extensions")) { - this->extensions = glTF2::ReadExtensions("extensions", *extensions); + if (Value *curExtensions = FindObject(val, "extensions")) { + this->extensions = glTF2::ReadExtensions("extensions", *curExtensions); } } From 3de20af3cc214c2459bce5013be61518ef49d7fc Mon Sep 17 00:00:00 2001 From: Evangel Date: Sat, 12 Jun 2021 13:16:53 +1000 Subject: [PATCH 5/7] Renamed glTF2::Object::extensions to customExtensions to avoid shadowing in other subclasses. --- code/AssetLib/glTF2/glTF2Asset.h | 2 +- code/AssetLib/glTF2/glTF2Asset.inl | 2 +- code/AssetLib/glTF2/glTF2Importer.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 759411b13..25e917712 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -408,7 +408,7 @@ struct Object { std::string id; //!< The globally unique ID used to reference this object std::string name; //!< The user-defined name of this object - CustomExtension extensions; + CustomExtension customExtensions; //! Objects marked as special are not exported (used to emulate the binary body buffer) virtual bool IsSpecial() const { return false; } diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 8175ab428..f88ea359d 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -369,7 +369,7 @@ inline Value *Object::FindExtension(Value &val, const char *extensionId) { inline void Object::ReadExtensions(Value &val) { if (Value *curExtensions = FindObject(val, "extensions")) { - this->extensions = glTF2::ReadExtensions("extensions", *curExtensions); + this->customExtensions = glTF2::ReadExtensions("extensions", *curExtensions); } } diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 9ba6270ed..8ccc6b058 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -489,7 +489,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { "\" does not match the vertex count"); continue; } - + auto componentType = attr.color[c]->componentType; if (componentType == glTF2::ComponentType_FLOAT) { attr.color[c]->ExtractData(aim->mColors[c]); @@ -1002,9 +1002,9 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & } } - if (node.extensions) { + if (node.customExtensions) { ainode->mMetaData = new aiMetadata; - ParseExtensions(ainode->mMetaData, node.extensions); + ParseExtensions(ainode->mMetaData, node.customExtensions); } GetNodeTransform(ainode->mTransformation, node); @@ -1498,7 +1498,7 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); const bool hasCopyright = !a.asset.copyright.empty(); - const bool hasSceneMetadata = a.scene->extensions; + const bool hasSceneMetadata = a.scene->customExtensions; if (hasVersion || hasGenerator || hasCopyright || hasSceneMetadata) { mScene->mMetaData = new aiMetadata; if (hasVersion) { @@ -1511,7 +1511,7 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); } if (hasSceneMetadata) { - ParseExtensions(mScene->mMetaData, a.scene->extensions); + ParseExtensions(mScene->mMetaData, a.scene->customExtensions); } } } From 064ffc625bef301a03a91a0e3ab7104466101605 Mon Sep 17 00:00:00 2001 From: Evangel Date: Mon, 14 Jun 2021 12:21:29 +1000 Subject: [PATCH 6/7] Const qualify aiMetadata::HasKey --- include/assimp/metadata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 551a9aba4..57fedfbfc 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -432,7 +432,7 @@ struct aiMetadata { /// Check whether there is a metadata entry for the given key. /// \param [in] Key - the key value value to check for. - inline bool HasKey(const char *key) { + inline bool HasKey(const char *key) const { if (nullptr == key) { return false; } From d18d83881265714f0ef3d859449e0e5a44450b43 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 24 Jun 2021 16:18:11 +0200 Subject: [PATCH 7/7] Fix formatting --- code/AssetLib/glTF2/glTF2Asset.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 25e917712..605cda332 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -388,16 +388,18 @@ struct CustomExtension { } CustomExtension() = default; - - CustomExtension(const CustomExtension &other) - : name(other.name) - , mStringValue(other.mStringValue) - , mDoubleValue(other.mDoubleValue) - , mUint64Value(other.mUint64Value) - , mInt64Value(other.mInt64Value) - , mBoolValue(other.mBoolValue) - , mValues(other.mValues) - { + + ~CustomExtension() = default; + + CustomExtension(const CustomExtension &other) : + name(other.name), + mStringValue(other.mStringValue), + mDoubleValue(other.mDoubleValue), + mUint64Value(other.mUint64Value), + mInt64Value(other.mInt64Value), + mBoolValue(other.mBoolValue), + mValues(other.mValues) { + // empty } };