Pārlūkot izejas kodu

Added support for heterogenous metadata on the aiNodes.

Frederik Aalund 11 gadi atpakaļ
vecāks
revīzija
a8401ba377
3 mainītis faili ar 175 papildinājumiem un 56 dzēšanām
  1. 13 28
      code/FBXConverter.cpp
  2. 6 10
      code/IFCLoader.cpp
  3. 156 18
      include/assimp/metadata.h

+ 13 - 28
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<std::string>(props, "UDP3DSMAX", ""));
-		++index;
-
+		data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(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<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >())
-				ss << interpreted->Value();
-			else if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >())
-				ss << interpreted->Value();
+			if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >())
+				data->Set(index++, prop.first, interpreted->Value());
 			else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >())
-				ss << interpreted->Value();
+				data->Set(index++, prop.first, interpreted->Value());
 			else if (const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >())
-				ss << interpreted->Value();
+				data->Set(index++, prop.first, interpreted->Value());
 			else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >())
-				ss << interpreted->Value();
+				data->Set(index++, prop.first, interpreted->Value());
+			else if (const TypedProperty<aiString>* interpreted = prop.second->As<TypedProperty<aiString> >())
+				data->Set(index++, prop.first, interpreted->Value());
 			else if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >())
-			{
-				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);
 		}
 	}
 

+ 6 - 10
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]();
-
-			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;
-			}
+			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));
+
 			nd->mMetaData = data;
 		}
 	}

+ 156 - 18
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 <stdint.h>
+
+
+
+// -------------------------------------------------------------------------------
+/**
+  * 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<typename callable>
+inline void transform( aiType type, void* data, callable c )
+{
+	switch (type) 
+	{
+	case aiType::AI_BOOL:
+		callable(static_cast<bool*>(data));
+		break;
+	case aiType::AI_INT:
+		callable(static_cast<int*>(data));
+		break;
+	case aiType::AI_UINT64:
+		callable(static_cast<uint64_t*>(data));
+		break;
+	case aiType::AI_FLOAT:
+		callable(static_cast<float*>(data));
+		break;
+	case aiType::AI_AISTRING:
+		callable(static_cast<aiString*>(data));
+		break;
+	case aiType::AI_AIVECTOR3D:
+		callable(static_cast<aiVector3D*>(data));
+		break;
+	default:
+		assert(false);
+		break;
+	}
+}
+
+// -------------------------------------------------------------------------------
+/**
+  * Transform. 
+  * 
+  * This is a convenience overload for aiMetaDataEntry's.
+  */
+ // -------------------------------------------------------------------------------
+template<typename callable>
+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<mNumProperties; ++i)
+				transform(mValues[i], (void (*)(void*))(operator delete));
+			// Delete the metadata array
 			delete [] mValues;
+		}
+		
 	}
 
 
-	inline bool Get(const aiString& key, aiString& value)
+
+	template<typename T>
+	inline void Set( unsigned index, const std::string& key, const T& value )
 	{
-		for (unsigned i=0; i<mNumProperties; ++i) {
-			if (mKeys[i]==key) {
-				value=mValues[i];
-				return true;
-			}
-		}
+		// In range assertion
+		assert(index < mNumProperties);
+
+		// Set metadata key
+		mKeys[index] = key;
+
+		// Set metadata type
+		mValues[index].type = GetAiType(value);
+		// Copy the given value to the dynamic storage
+		mValues[index].data = new T(value);
+	}
+
+	template<typename T>
+	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<T*>(mValues[index].data);
+		return true;
+	}
+
+	template<typename T>
+	inline bool Get( const aiString& key, T& value )
+	{
+		// Search for the given key
+		for (unsigned i=0; i<mNumProperties; ++i)
+			if (mKeys[i]==key)
+				return Get(i, value);
 		return false;
 	}
+
 #endif // __cplusplus
 };
 
-#ifdef __cplusplus
-} //extern "C" {
-#endif
-
 #endif // __AI_METADATA_H_INC__