Merge pull request #3955 from Evangel63/master
Add scene metadata for glTF2 files as allowed by the glTF2 specificationpull/3959/head
commit
bd9b28bc45
|
@ -356,6 +356,53 @@ 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<std::string> mStringValue;
|
||||
Nullable<double> mDoubleValue;
|
||||
Nullable<uint64_t> mUint64Value;
|
||||
Nullable<int64_t> mInt64Value;
|
||||
Nullable<bool> mBoolValue;
|
||||
|
||||
// std::vector<CustomExtension> handles both Object and Array
|
||||
Nullable<std::vector<CustomExtension>> 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() = 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
|
||||
}
|
||||
};
|
||||
|
||||
//! Base class for all glTF top-level objects
|
||||
struct Object {
|
||||
int index; //!< The index of this object within its property container
|
||||
|
@ -363,6 +410,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 customExtensions;
|
||||
|
||||
//! Objects marked as special are not exported (used to emulate the binary body buffer)
|
||||
virtual bool IsSpecial() const { return false; }
|
||||
|
||||
|
@ -377,6 +426,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);
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -834,50 +885,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<std::string> mStringValue;
|
||||
Nullable<double> mDoubleValue;
|
||||
Nullable<uint64_t> mUint64Value;
|
||||
Nullable<int64_t> mInt64Value;
|
||||
Nullable<bool> mBoolValue;
|
||||
|
||||
// std::vector<CustomExtension> handles both Object and Array
|
||||
Nullable<std::vector<CustomExtension>> 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<Ref<Node>> children;
|
||||
std::vector<Ref<Mesh>> meshes;
|
||||
|
@ -896,8 +903,6 @@ struct Node : public Object {
|
|||
|
||||
Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
|
||||
|
||||
CustomExtension extensions;
|
||||
|
||||
Node() {}
|
||||
void Read(Value &obj, Asset &r);
|
||||
};
|
||||
|
|
|
@ -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 *curExtensions = FindObject(val, "extensions")) {
|
||||
this->customExtensions = glTF2::ReadExtensions("extensions", *curExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_ENABLE_DRACO
|
||||
|
||||
template <typename T>
|
||||
|
@ -569,6 +612,7 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
|
|||
inst->oIndex = i;
|
||||
ReadMember(obj, "name", inst->name);
|
||||
inst->Read(obj, mAsset);
|
||||
inst->ReadExtensions(obj);
|
||||
|
||||
Ref<T> 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");
|
||||
|
|
|
@ -503,7 +503,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]);
|
||||
|
@ -1016,9 +1016,9 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
}
|
||||
}
|
||||
|
||||
if (node.extensions) {
|
||||
if (node.customExtensions) {
|
||||
ainode->mMetaData = new aiMetadata;
|
||||
ParseExtensions(ainode->mMetaData, node.extensions);
|
||||
ParseExtensions(ainode->mMetaData, node.customExtensions);
|
||||
}
|
||||
|
||||
GetNodeTransform(ainode->mTransformation, node);
|
||||
|
@ -1512,7 +1512,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->customExtensions;
|
||||
if (hasVersion || hasGenerator || hasCopyright || hasSceneMetadata) {
|
||||
mScene->mMetaData = new aiMetadata;
|
||||
if (hasVersion) {
|
||||
mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
|
||||
|
@ -1523,6 +1524,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->customExtensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue