Added unparsed FBX properties to the aiNode's metadata. This allows the

user to extract extra/custom/user attributes/properties from the scene
graph. E.g., extracting attributes set under "extra attributes" in Maya.
pull/231/head
Frederik Aalund 2014-03-09 16:18:05 +01:00
parent 84b66092d7
commit 9eb8677aba
3 changed files with 73 additions and 15 deletions

View File

@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include <iterator> #include <iterator>
#include <sstream>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include "FBXParser.h" #include "FBXParser.h"
@ -94,14 +95,6 @@ public:
TransformationComp_MAXIMUM TransformationComp_MAXIMUM
}; };
enum MetadataKeys
{
MetadataKeys_UserProperties = 0,
MetadataKeys_IsNull,
MetadataKeys_MAXIMUM
};
public: public:
Converter(aiScene* out, const Document& doc) Converter(aiScene* out, const Document& doc)
@ -760,21 +753,56 @@ private:
void SetupNodeMetadata(const Model& model, aiNode& nd) void SetupNodeMetadata(const Model& model, aiNode& nd)
{ {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
//create metadata on node // create metadata on node
std::size_t numStaticMetaData = 2;
aiMetadata* data = new aiMetadata(); aiMetadata* data = new aiMetadata();
data->mNumProperties = MetadataKeys_MAXIMUM; data->mNumProperties = unparsedProperties.size() + numStaticMetaData;
data->mKeys = new aiString[data->mNumProperties](); data->mKeys = new aiString[data->mNumProperties]();
data->mValues = new aiString[data->mNumProperties](); data->mValues = new aiString[data->mNumProperties]();
nd.mMetaData = data; nd.mMetaData = data;
int index = 0;
// find user defined properties // find user defined properties (3ds Max)
data->mKeys[MetadataKeys_UserProperties].Set("UserProperties"); data->mKeys[index].Set("UserProperties");
data->mValues[MetadataKeys_UserProperties].Set(PropertyGet<std::string>(props, "UDP3DSMAX", "")); data->mValues[index].Set(PropertyGet<std::string>(props, "UDP3DSMAX", ""));
++index;
// preserve the info that a node was marked as Null node in the original file. // preserve the info that a node was marked as Null node in the original file.
data->mKeys[MetadataKeys_IsNull].Set("IsNull"); data->mKeys[index].Set("IsNull");
data->mValues[MetadataKeys_IsNull].Set(model.IsNull() ? "true" : "false"); data->mValues[index].Set(model.IsNull() ? "true" : "false");
++index;
// 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();
else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int>>())
ss << interpreted->Value();
else if (const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t>>())
ss << interpreted->Value();
else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float>>())
ss << 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;
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -201,6 +201,33 @@ const Property* PropertyTable::Get(const std::string& name) const
return (*it).second; return (*it).second;
} }
DirectPropertyMap PropertyTable::GetUnparsedProperties() const
{
DirectPropertyMap result;
// Loop through all the lazy properties (which is all the properties)
BOOST_FOREACH(const LazyPropertyMap::value_type& element, lazyProps) {
// Skip parsed properties
if (props.end() != props.find(element.first)) continue;
// Read the element's value.
// Wrap the naked pointer (since the call site is required to acquire ownership)
// std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
boost::shared_ptr<Property> prop = boost::shared_ptr<Property>(ReadTypedProperty(*element.second));
// Element could not be read. Skip it.
if (!prop) continue;
// Add to result
result[element.first] = prop;
}
return result;
}
} //! FBX } //! FBX
} //! Assimp } //! Assimp

View File

@ -101,6 +101,7 @@ private:
}; };
typedef std::fbx_unordered_map<std::string,boost::shared_ptr<Property>> DirectPropertyMap;
typedef std::fbx_unordered_map<std::string,const Property*> PropertyMap; typedef std::fbx_unordered_map<std::string,const Property*> PropertyMap;
typedef std::fbx_unordered_map<std::string,const Element*> LazyPropertyMap; typedef std::fbx_unordered_map<std::string,const Element*> LazyPropertyMap;
@ -128,6 +129,8 @@ public:
return templateProps.get(); return templateProps.get();
} }
DirectPropertyMap GetUnparsedProperties() const;
private: private:
LazyPropertyMap lazyProps; LazyPropertyMap lazyProps;