Merge branch 'master' into patch-2

pull/3293/head
Kim Kulling 2020-06-29 09:55:55 +02:00 committed by GitHub
commit eeb4a981bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 241 additions and 6 deletions

View File

@ -784,6 +784,50 @@ 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();
}
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;
@ -802,6 +846,8 @@ 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);
};

View File

@ -1207,6 +1207,47 @@ 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;
@ -1261,6 +1302,8 @@ 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");

View File

@ -847,6 +847,26 @@ static std::string GetNodeName(const Node &node) {
return node.name.empty() ? node.id : node.name;
}
void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
if (extension.mStringValue.isPresent) {
metadata->Add(extension.name.c_str(), aiString(extension.mStringValue.value));
} else if (extension.mDoubleValue.isPresent) {
metadata->Add(extension.name.c_str(), extension.mDoubleValue.value);
} else if (extension.mUint64Value.isPresent) {
metadata->Add(extension.name.c_str(), extension.mUint64Value.value);
} else if (extension.mInt64Value.isPresent) {
metadata->Add(extension.name.c_str(), static_cast<int32_t>(extension.mInt64Value.value));
} else if (extension.mBoolValue.isPresent) {
metadata->Add(extension.name.c_str(), extension.mBoolValue.value);
} else if (extension.mValues.isPresent) {
aiMetadata val;
for (size_t i = 0; i < extension.mValues.value.size(); ++i) {
ParseExtensions(&val, extension.mValues.value[i]);
}
metadata->Add(extension.name.c_str(), val);
}
}
aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &meshOffsets, glTF2::Ref<glTF2::Node> &ptr) {
Node &node = *ptr;
@ -863,6 +883,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
}
}
if (node.extensions) {
ainode->mMetaData = new aiMetadata;
ParseExtensions(ainode->mMetaData, node.extensions);
}
GetNodeTransform(ainode->mTransformation, node);
if (!node.meshes.empty()) {
@ -957,9 +982,14 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
//range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
//it is added to meta data of parent node, because there is no other place to put it
if (node.light->range.isPresent) {
if (!ainode->mMetaData) {
ainode->mMetaData = aiMetadata::Alloc(1);
ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value);
}
else {
ainode->mMetaData->Add("PBR_LightRange", node.light->range.value);
}
}
}
return ainode;

View File

@ -69,7 +69,8 @@ typedef enum aiMetadataType {
AI_DOUBLE = 4,
AI_AISTRING = 5,
AI_AIVECTOR3D = 6,
AI_META_MAX = 7,
AI_AIMETADATA = 7,
AI_META_MAX = 8,
#ifndef SWIG
FORCE_32BIT = INT_MAX
@ -100,6 +101,8 @@ struct aiMetadataEntry {
#include <string>
struct aiMetadata;
// -------------------------------------------------------------------------------
/**
* Helper functions to get the aiType enum entry for a type
@ -127,6 +130,9 @@ inline aiMetadataType GetAiType(const aiString &) {
inline aiMetadataType GetAiType(const aiVector3D &) {
return AI_AIVECTOR3D;
}
inline aiMetadataType GetAiType(const aiMetadata &) {
return AI_AIMETADATA;
}
#endif // __cplusplus
@ -204,6 +210,11 @@ struct aiMetadata {
rhs.Get<aiVector3D>(mKeys[i], v);
mValues[i].mData = new aiVector3D(v);
} break;
case AI_AIMETADATA: {
aiMetadata v;
rhs.Get<aiMetadata>(mKeys[i], v);
mValues[i].mData = new aiMetadata(v);
} break;
#ifndef SWIG
case FORCE_32BIT:
#endif
@ -213,6 +224,14 @@ struct aiMetadata {
}
}
aiMetadata &operator=(aiMetadata rhs) {
using std::swap;
swap(mNumProperties, rhs.mNumProperties);
swap(mKeys, rhs.mKeys);
swap(mValues, rhs.mValues);
return *this;
}
/**
* @brief The destructor.
*/
@ -245,6 +264,9 @@ struct aiMetadata {
case AI_AIVECTOR3D:
delete static_cast<aiVector3D *>(data);
break;
case AI_AIMETADATA:
delete static_cast<aiMetadata *>(data);
break;
#ifndef SWIG
case FORCE_32BIT:
#endif
@ -323,8 +345,10 @@ struct aiMetadata {
mValues[index].mType = GetAiType(value);
// Copy the given value to the dynamic storage
if (nullptr != mValues[index].mData) {
if (nullptr != mValues[index].mData && AI_AIMETADATA != mValues[index].mType) {
::memcpy(mValues[index].mData, &value, sizeof(T));
} else if (nullptr != mValues[index].mData && AI_AIMETADATA == mValues[index].mType) {
*static_cast<T *>(mValues[index].mData) = value;
} else {
mValues[index].mData = new T(value);
}
@ -418,6 +442,89 @@ struct aiMetadata {
return false;
}
friend bool CompareKeys(const aiMetadata &lhs, const aiMetadata &rhs) {
if (lhs.mNumProperties != rhs.mNumProperties) {
return false;
}
for (unsigned int i = 0; i < lhs.mNumProperties; ++i) {
if (lhs.mKeys[i] != rhs.mKeys[i]) {
return false;
}
}
return true;
}
friend bool CompareValues(const aiMetadata &lhs, const aiMetadata &rhs) {
if (lhs.mNumProperties != rhs.mNumProperties) {
return false;
}
for (unsigned int i = 0; i < lhs.mNumProperties; ++i) {
if (lhs.mValues[i].mType != rhs.mValues[i].mType) {
return false;
}
switch (lhs.mValues[i].mType) {
case AI_BOOL: {
if (*static_cast<bool *>(lhs.mValues[i].mData) != *static_cast<bool *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_INT32: {
if (*static_cast<int32_t *>(lhs.mValues[i].mData) != *static_cast<int32_t *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_UINT64: {
if (*static_cast<uint64_t *>(lhs.mValues[i].mData) != *static_cast<uint64_t *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_FLOAT: {
if (*static_cast<float *>(lhs.mValues[i].mData) != *static_cast<float *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_DOUBLE: {
if (*static_cast<double *>(lhs.mValues[i].mData) != *static_cast<double *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_AISTRING: {
if (*static_cast<aiString *>(lhs.mValues[i].mData) != *static_cast<aiString *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_AIVECTOR3D: {
if (*static_cast<aiVector3D *>(lhs.mValues[i].mData) != *static_cast<aiVector3D *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_AIMETADATA: {
if (*static_cast<aiMetadata *>(lhs.mValues[i].mData) != *static_cast<aiMetadata *>(rhs.mValues[i].mData)) {
return false;
}
} break;
#ifndef SWIG
case FORCE_32BIT:
#endif
default:
break;
}
}
return true;
}
friend bool operator==(const aiMetadata &lhs, const aiMetadata &rhs) {
return CompareKeys(lhs, rhs) && CompareValues(lhs, rhs);
}
friend bool operator!=(const aiMetadata &lhs, const aiMetadata &rhs) {
return !(lhs == rhs);
}
#endif // __cplusplus
};

View File

@ -197,9 +197,11 @@ TEST_F( utMetadata, copy_test ) {
m_data->Set( 5, "aiString", strVal );
aiVector3D vecVal( 1, 2, 3 );
m_data->Set( 6, "aiVector3D", vecVal );
aiMetadata metaVal;
m_data->Set( 7, "aiMetadata", metaVal );
aiMetadata copy( *m_data );
EXPECT_EQ( 7u, copy.mNumProperties );
EXPECT_EQ( 8u, copy.mNumProperties );
// bool test
{
@ -251,4 +253,11 @@ TEST_F( utMetadata, copy_test ) {
EXPECT_TRUE( copy.Get( "aiVector3D", v ) );
EXPECT_EQ( vecVal, v );
}
// metadata test
{
aiMetadata v;
EXPECT_TRUE( copy.Get( "aiMetadata", v ) );
EXPECT_EQ( metaVal, v );
}
}