Merge pull request #5109 from assimp/C-Tech-Development-Corp-gltf2_metadata_export

C tech development corp gltf2 metadata export
pull/5114/head
Kim Kulling 2023-05-30 11:38:02 +02:00 committed by GitHub
commit bee751b5f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 11 deletions

View File

@ -371,6 +371,15 @@ struct CustomExtension {
CustomExtension& operator=(const CustomExtension&) = default; CustomExtension& operator=(const CustomExtension&) = default;
}; };
//! Represents metadata in an glTF2 object
struct Extras {
std::vector<CustomExtension> mValues;
inline bool HasExtras() const {
return !mValues.empty();
}
};
//! Base class for all glTF top-level objects //! Base class for all glTF top-level objects
struct Object { struct Object {
int index; //!< The index of this object within its property container int index; //!< The index of this object within its property container
@ -379,7 +388,7 @@ struct Object {
std::string name; //!< The user-defined name of this object std::string name; //!< The user-defined name of this object
CustomExtension customExtensions; CustomExtension customExtensions;
CustomExtension extras; Extras extras;
//! Objects marked as special are not exported (used to emulate the binary body buffer) //! Objects marked as special are not exported (used to emulate the binary body buffer)
virtual bool IsSpecial() const { return false; } virtual bool IsSpecial() const { return false; }

View File

@ -139,6 +139,18 @@ inline CustomExtension ReadExtensions(const char *name, Value &obj) {
return ret; return ret;
} }
inline Extras ReadExtras(Value &obj) {
Extras ret;
ret.mValues.reserve(obj.MemberCount());
for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
auto &val = it->value;
ret.mValues.emplace_back(ReadExtensions(it->name.GetString(), val));
}
return ret;
}
inline void CopyData(size_t count, const uint8_t *src, size_t src_stride, inline void CopyData(size_t count, const uint8_t *src, size_t src_stride,
uint8_t *dst, size_t dst_stride) { uint8_t *dst, size_t dst_stride) {
if (src_stride == dst_stride) { if (src_stride == dst_stride) {
@ -248,7 +260,7 @@ inline void Object::ReadExtensions(Value &val) {
inline void Object::ReadExtras(Value &val) { inline void Object::ReadExtras(Value &val) {
if (Value *curExtras = FindObject(val, "extras")) { if (Value *curExtras = FindObject(val, "extras")) {
this->extras = glTF2::ReadExtensions("extras", *curExtras); this->extras = glTF2::ReadExtras(*curExtras);
} }
} }

View File

@ -654,6 +654,44 @@ namespace glTF2 {
} }
} }
inline void WriteExtrasValue(Value &parent, const CustomExtension &value, AssetWriter &w) {
Value valueNode;
if (value.mStringValue.isPresent) {
MakeValue(valueNode, value.mStringValue.value.c_str(), w.mAl);
} else if (value.mDoubleValue.isPresent) {
MakeValue(valueNode, value.mDoubleValue.value, w.mAl);
} else if (value.mUint64Value.isPresent) {
MakeValue(valueNode, value.mUint64Value.value, w.mAl);
} else if (value.mInt64Value.isPresent) {
MakeValue(valueNode, value.mInt64Value.value, w.mAl);
} else if (value.mBoolValue.isPresent) {
MakeValue(valueNode, value.mBoolValue.value, w.mAl);
} else if (value.mValues.isPresent) {
valueNode.SetObject();
for (auto const &subvalue : value.mValues.value) {
WriteExtrasValue(valueNode, subvalue, w);
}
}
parent.AddMember(StringRef(value.name), valueNode, w.mAl);
}
inline void WriteExtras(Value &obj, const Extras &extras, AssetWriter &w) {
if (!extras.HasExtras()) {
return;
}
Value extrasNode;
extrasNode.SetObject();
for (auto const &value : extras.mValues) {
WriteExtrasValue(extrasNode, value, w);
}
obj.AddMember("extras", extrasNode, w.mAl);
}
inline void Write(Value& obj, Node& n, AssetWriter& w) inline void Write(Value& obj, Node& n, AssetWriter& w)
{ {
if (n.matrix.isPresent) { if (n.matrix.isPresent) {
@ -689,6 +727,8 @@ namespace glTF2 {
if(n.skeletons.size()) { if(n.skeletons.size()) {
AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
} }
WriteExtras(obj, n.extras, w);
} }
inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/) inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
@ -762,7 +802,6 @@ namespace glTF2 {
} }
} }
inline AssetWriter::AssetWriter(Asset& a) inline AssetWriter::AssetWriter(Asset& a)
: mDoc() : mDoc()
, mAsset(a) , mAsset(a)

View File

@ -443,6 +443,61 @@ inline Ref<Accessor> ExportData(Asset &a, std::string &meshName, Ref<Buffer> &bu
return acc; return acc;
} }
inline void ExportNodeExtras(const aiMetadataEntry &metadataEntry, aiString name, CustomExtension &value) {
value.name = name.C_Str();
switch (metadataEntry.mType) {
case AI_BOOL:
value.mBoolValue.value = *static_cast<bool *>(metadataEntry.mData);
value.mBoolValue.isPresent = true;
break;
case AI_INT32:
value.mInt64Value.value = *static_cast<int32_t *>(metadataEntry.mData);
value.mInt64Value.isPresent = true;
break;
case AI_UINT64:
value.mUint64Value.value = *static_cast<uint64_t *>(metadataEntry.mData);
value.mUint64Value.isPresent = true;
break;
case AI_FLOAT:
value.mDoubleValue.value = *static_cast<float *>(metadataEntry.mData);
value.mDoubleValue.isPresent = true;
break;
case AI_DOUBLE:
value.mDoubleValue.value = *static_cast<double *>(metadataEntry.mData);
value.mDoubleValue.isPresent = true;
break;
case AI_AISTRING:
value.mStringValue.value = static_cast<aiString *>(metadataEntry.mData)->C_Str();
value.mStringValue.isPresent = true;
break;
case AI_AIMETADATA: {
const aiMetadata *subMetadata = static_cast<aiMetadata *>(metadataEntry.mData);
value.mValues.value.resize(subMetadata->mNumProperties);
value.mValues.isPresent = true;
for (unsigned i = 0; i < subMetadata->mNumProperties; ++i) {
ExportNodeExtras(subMetadata->mValues[i], subMetadata->mKeys[i], value.mValues.value.at(i));
}
break;
}
default:
// AI_AIVECTOR3D not handled
break;
}
}
inline void ExportNodeExtras(const aiMetadata *metadata, Extras &extras) {
if (metadata == nullptr || metadata->mNumProperties == 0) {
return;
}
extras.mValues.resize(metadata->mNumProperties);
for (unsigned int i = 0; i < metadata->mNumProperties; ++i) {
ExportNodeExtras(metadata->mValues[i], metadata->mKeys[i], extras.mValues.at(i));
}
}
inline void SetSamplerWrap(SamplerWrap &wrap, aiTextureMapMode map) { inline void SetSamplerWrap(SamplerWrap &wrap, aiTextureMapMode map) {
switch (map) { switch (map) {
case aiTextureMapMode_Clamp: case aiTextureMapMode_Clamp:
@ -1375,7 +1430,7 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
return node.GetIndex(); return node.GetIndex();
} }
/* /*
* Export node and recursively calls ExportNode for all children. * Export node and recursively calls ExportNode for all children.
* Since these nodes are not the root node, we also export the parent Ref<Node> * Since these nodes are not the root node, we also export the parent Ref<Node>
*/ */
@ -1386,6 +1441,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref<Node> &parent) {
node->parent = parent; node->parent = parent;
node->name = name; node->name = name;
ExportNodeExtras(n->mMetaData, node->extras);
if (!n->mTransformation.IsIdentity()) { if (!n->mTransformation.IsIdentity()) {
if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) { if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) {
aiQuaternion quaternion; aiQuaternion quaternion;

View File

@ -1103,11 +1103,9 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
} }
} }
void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) { void ParseExtras(aiMetadata* metadata, const Extras& extras) {
if (extension.mValues.isPresent) { for (auto const &value : extras.mValues) {
for (auto const &subExtension : extension.mValues.value) { ParseExtensions(metadata, value);
ParseExtensions(metadata, subExtension);
}
} }
} }
@ -1129,12 +1127,12 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
} }
} }
if (node.customExtensions || node.extras) { if (node.customExtensions || node.extras.HasExtras()) {
ainode->mMetaData = new aiMetadata; ainode->mMetaData = new aiMetadata;
if (node.customExtensions) { if (node.customExtensions) {
ParseExtensions(ainode->mMetaData, node.customExtensions); ParseExtensions(ainode->mMetaData, node.customExtensions);
} }
if (node.extras) { if (node.extras.HasExtras()) {
ParseExtras(ainode->mMetaData, node.extras); ParseExtras(ainode->mMetaData, node.extras);
} }
} }