diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 1ac05aa17..b0f4bf823 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -760,48 +760,33 @@ private: aiMetadata* data = new aiMetadata(); data->mNumProperties = unparsedProperties.size() + numStaticMetaData; data->mKeys = new aiString[data->mNumProperties](); - data->mValues = new aiString[data->mNumProperties](); + data->mValues = new aiMetaDataEntry[data->mNumProperties](); nd.mMetaData = data; int index = 0; // find user defined properties (3ds Max) - data->mKeys[index].Set("UserProperties"); - data->mValues[index].Set(PropertyGet(props, "UDP3DSMAX", "")); - ++index; - + data->Set(index++, "UserProperties", aiString(PropertyGet(props, "UDP3DSMAX", ""))); // preserve the info that a node was marked as Null node in the original file. - data->mKeys[index].Set("IsNull"); - data->mValues[index].Set(model.IsNull() ? "true" : "false"); - ++index; + data->Set(index++, "IsNull", model.IsNull() ? true : false); // add unparsed properties to the node's metadata BOOST_FOREACH(const DirectPropertyMap::value_type& prop, unparsedProperties) { - // all values are converted to strings using the following stringstream - std::stringstream ss; - bool parse_succeeded = false; - // Interpret the property as a concrete type - if (const TypedProperty* interpreted = prop.second->As >()) - ss << interpreted->Value(); - else if (const TypedProperty* interpreted = prop.second->As >()) - ss << interpreted->Value(); + if (const TypedProperty* interpreted = prop.second->As >()) + data->Set(index++, prop.first, interpreted->Value()); else if (const TypedProperty* interpreted = prop.second->As >()) - ss << interpreted->Value(); + data->Set(index++, prop.first, interpreted->Value()); else if (const TypedProperty* interpreted = prop.second->As >()) - ss << interpreted->Value(); + data->Set(index++, prop.first, interpreted->Value()); else if (const TypedProperty* interpreted = prop.second->As >()) - ss << interpreted->Value(); + data->Set(index++, prop.first, interpreted->Value()); + else if (const TypedProperty* interpreted = prop.second->As >()) + data->Set(index++, prop.first, interpreted->Value()); else if (const TypedProperty* interpreted = prop.second->As >()) - { - aiVector3D v = interpreted->Value(); - ss << v.x << ";" << v.y << ";" << v.z; - } - - // add property to meta data - data->mKeys[index].Set(prop.first); - data->mValues[index].Set(ss.str()); - ++index; + data->Set(index++, prop.first, interpreted->Value()); + else + assert(false); } } diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 4c8feeab1..a00f2c9e7 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -726,16 +726,12 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion aiMetadata* data = new aiMetadata(); data->mNumProperties = properties.size(); data->mKeys = new aiString[data->mNumProperties](); - data->mValues = new aiString[data->mNumProperties](); + data->mValues = new aiMetaDataEntry[data->mNumProperties](); + + unsigned int index = 0; + BOOST_FOREACH(const Metadata::value_type& kv, properties) + data->Set(index++, kv.first, aiString(kv.second)); - unsigned int i = 0; - BOOST_FOREACH(const Metadata::value_type& kv, properties) { - data->mKeys[i].Set(kv.first); - if (kv.second.length() > 0) { - data->mValues[i].Set(kv.second); - } - ++i; - } nd->mMetaData = data; } } diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 942029ae6..6d52f59dd 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -45,10 +45,116 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef __AI_METADATA_H_INC__ #define __AI_METADATA_H_INC__ +#include + + + +// ------------------------------------------------------------------------------- +/** + * Enum used to distinguish data types + */ + // ------------------------------------------------------------------------------- +enum aiType +{ + AI_BOOL = 0, + AI_INT = 1, + AI_UINT64 = 2, + AI_FLOAT = 3, + AI_AISTRING = 4, + AI_AIVECTOR3D = 5, + + FORCE_32BIT = INT_MAX +}; + + + +// ------------------------------------------------------------------------------- +/** + * Metadata entry + * + * The type field uniquely identifies the underlying type of the data field + */ + // ------------------------------------------------------------------------------- +struct aiMetaDataEntry +{ + aiType type; + void* data; +}; + + + #ifdef __cplusplus -extern "C" { + +// ------------------------------------------------------------------------------- +/** + * Helper functions to get the aiType enum entry for a type + */ + // ------------------------------------------------------------------------------- +inline aiType GetAiType( bool ) { return aiType::AI_BOOL; } +inline aiType GetAiType( int ) { return aiType::AI_INT; } +inline aiType GetAiType( uint64_t ) { return aiType::AI_UINT64; } +inline aiType GetAiType( float ) { return aiType::AI_FLOAT; } +inline aiType GetAiType( aiString ) { return aiType::AI_AISTRING; } +inline aiType GetAiType( aiVector3D ) { return aiType::AI_AIVECTOR3D; } + + + +// ------------------------------------------------------------------------------- +/** + * Transform + * + * Applies the callable, c, to the given data of the given type. + * The callable, c, is expected to have the following interface + * + * c( T* data ) + * + * where T can be any type with a corresponding entry in the aiType enum. + */ + // ------------------------------------------------------------------------------- +template +inline void transform( aiType type, void* data, callable c ) +{ + switch (type) + { + case aiType::AI_BOOL: + callable(static_cast(data)); + break; + case aiType::AI_INT: + callable(static_cast(data)); + break; + case aiType::AI_UINT64: + callable(static_cast(data)); + break; + case aiType::AI_FLOAT: + callable(static_cast(data)); + break; + case aiType::AI_AISTRING: + callable(static_cast(data)); + break; + case aiType::AI_AIVECTOR3D: + callable(static_cast(data)); + break; + default: + assert(false); + break; + } +} + +// ------------------------------------------------------------------------------- +/** + * Transform. + * + * This is a convenience overload for aiMetaDataEntry's. + */ + // ------------------------------------------------------------------------------- +template +inline void transform( aiMetaDataEntry entry, callable c ) +{ transform(entry.type, entry.data, c); } + #endif + + // ------------------------------------------------------------------------------- /** * Container for holding metadata. @@ -66,18 +172,17 @@ struct aiMetadata /** Arrays of values, may not be NULL. Entries in this array may be NULL if the * corresponding property key has no assigned value. */ - C_STRUCT aiString* mValues; + C_STRUCT aiMetaDataEntry* mValues; #ifdef __cplusplus /** Constructor */ aiMetadata() - { // set all members to zero by default - mKeys = NULL; - mValues = NULL; - mNumProperties = 0; - } + : mKeys(NULL) + , mValues(NULL) + , mNumProperties(0) + {} /** Destructor */ @@ -86,27 +191,60 @@ struct aiMetadata if (mKeys) delete [] mKeys; if (mValues) + { + // Delete each metadata entry + for (unsigned i=0; i + inline void Set( unsigned index, const std::string& key, const T& value ) { - for (unsigned i=0; i + inline bool Get( unsigned index, T& value ) + { + // Return false if the output data type does + // not match the found value's data type + if (GetAiType(value) != mValues[index].type) + return false; + + // Otherwise, output the found value and + // return true + value = *static_cast(mValues[index].data); + return true; + } + + template + inline bool Get( const aiString& key, T& value ) + { + // Search for the given key + for (unsigned i=0; i