2
0
Эх сурвалжийг харах

- fbx: pre-filter animated property we don't support as early as possible.

Alexander Gessler 13 жил өмнө
parent
commit
5bc573edb8

+ 87 - 38
code/FBXAnimation.cpp

@@ -98,41 +98,14 @@ AnimationCurve::~AnimationCurve()
 
 
 // ------------------------------------------------------------------------------------------------
-AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, 
+	const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/)
 : Object(id, element, name)
 , target()
+, doc(doc)
 {
 	const Scope& sc = GetRequiredScope(element);
-	props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
-
-	{
-	// resolve attached animation curves
-	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
-
-	BOOST_FOREACH(const Connection* con, conns) {
-
-		// link should go for a property
-		if (!con->PropertyName().length()) {
-			continue;
-		}
-
-		const Object* const ob = con->SourceObject();
-		if(!ob) {
-			DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
-			continue;
-		}
-
-		const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
-		if(!anim) {
-			DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
-			continue;
-		}
-		
-		curves[con->PropertyName()] = anim;
-	}
-
-	}{
-
+	
 	// find target node
 	const char* whitelist[] = {"Model","NodeAttribute"};
 	const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
@@ -144,6 +117,21 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
 			continue;
 		}
 
+		if(target_prop_whitelist) {
+			const char* const s = con->PropertyName().c_str();
+			bool ok = false;
+			for (size_t i = 0; i < whitelist_size; ++i) {
+				if (!strcmp(s, target_prop_whitelist[i])) {
+					ok = true;
+					break;
+				}
+			}
+
+			if (!ok) {
+				throw std::range_error("AnimationCurveNode target property is not in whitelist");
+			}
+		}
+
 		const Object* const ob = con->DestinationObject();
 		if(!ob) {
 			DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
@@ -160,10 +148,12 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
 		prop = con->PropertyName();
 		break;
 	}
-	}
+
 	if(!target) {
 		DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
 	}
+
+	props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
 }
 
 
@@ -174,14 +164,64 @@ AnimationCurveNode::~AnimationCurveNode()
 }
 
 
+// ------------------------------------------------------------------------------------------------
+const AnimationCurveMap& AnimationCurveNode::Curves() const
+{
+	if(curves.empty()) {
+		// resolve attached animation curves
+		const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
+
+		BOOST_FOREACH(const Connection* con, conns) {
+
+			// link should go for a property
+			if (!con->PropertyName().length()) {
+				continue;
+			}
+
+			const Object* const ob = con->SourceObject();
+			if(!ob) {
+				DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
+				continue;
+			}
+
+			const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
+			if(!anim) {
+				DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
+				continue;
+			}
+
+			curves[con->PropertyName()] = anim;
+		}
+	}
+
+	return curves;
+}
+
+
 // ------------------------------------------------------------------------------------------------
 AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 : Object(id, element, name)
+, doc(doc)
 {
 	const Scope& sc = GetRequiredScope(element);
 
 	// note: the props table here bears little importance and is usually absent
 	props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+AnimationLayer::~AnimationLayer()
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, 
+	size_t whitelist_size /*= 0*/) const
+{
+	AnimationCurveNodeList nodes;
 
 	// resolve attached animation nodes
 	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
@@ -205,15 +245,24 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
 			DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
 			continue;
 		}
+
+		if(target_prop_whitelist) {
+			const char* s = anim->TargetProperty().c_str();
+			bool ok = false;
+			for (size_t i = 0; i < whitelist_size; ++i) {
+				if (!strcmp(s, target_prop_whitelist[i])) {
+					ok = true;
+					break;
+				}
+			}
+			if(!ok) {
+				continue;
+			}
+		}
 		nodes.push_back(anim);
 	}
-}
-
-
-// ------------------------------------------------------------------------------------------------
-AnimationLayer::~AnimationLayer()
-{
 
+	return nodes; // pray for NRVO
 }
 
 // ------------------------------------------------------------------------------------------------

+ 7 - 1
code/FBXConverter.cpp

@@ -1745,11 +1745,17 @@ private:
 		// reverse mapping from curves to layers, much faster than querying 
 		// the FBX DOM for it.
 		LayerMap layer_map;
+
+		const char* prop_whitelist[] = {
+			"Lcl Scaling",
+			"Lcl Rotation",
+			"Lcl Translation"
+		};
 		
 		BOOST_FOREACH(const AnimationLayer* layer, layers) {
 			ai_assert(layer);
 
-			const AnimationCurveNodeList& nodes = layer->Nodes();
+			const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 3);
 			BOOST_FOREACH(const AnimationCurveNode* node, nodes) {
 				ai_assert(node);
 

+ 15 - 9
code/FBXDocument.h

@@ -845,7 +845,12 @@ class AnimationCurveNode : public Object
 {
 public:
 
-	AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+	/* the optional whitelist specifies a list of property names for which the caller
+	wants animations for. If the curve node does not match one of these, std::range_error
+	will be thrown. */
+	AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
+		const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0);
+
 	~AnimationCurveNode();
 
 public:
@@ -856,9 +861,7 @@ public:
 	}
 
 
-	const AnimationCurveMap Curves() const {
-		return curves;
-	}
+	const AnimationCurveMap& Curves() const;
 
 	/** Object the curve is assigned to, this can be NULL if the
 	 *  target object has no DOM representation or could not
@@ -884,9 +887,10 @@ private:
 
 	const Object* target;
 	boost::shared_ptr<const PropertyTable> props;
-	AnimationCurveMap curves;
+	mutable AnimationCurveMap curves;
 
 	std::string prop;
+	const Document& doc;
 };
 
 typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
@@ -897,6 +901,7 @@ class AnimationLayer : public Object
 {
 public:
 
+	
 	AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
 	~AnimationLayer();
 
@@ -907,14 +912,15 @@ public:
 		return *props.get();
 	}
 
-	const AnimationCurveNodeList& Nodes() const {
-		return nodes;
-	}
+	/* the optional whitelist specifies a list of property names for which the caller
+	wants animations for. Curves not matching this list will not be added to the
+	animation layer. */
+	AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0) const;
 
 private:
 
 	boost::shared_ptr<const PropertyTable> props;
-	AnimationCurveNodeList nodes;
+	const Document& doc;
 };