Преглед изворни кода

- fbx: resolve target node for node animations.

Alexander Gessler пре 13 година
родитељ
комит
378bc93593
3 измењених фајлова са 83 додато и 5 уклоњено
  1. 42 1
      code/FBXAnimation.cpp
  2. 27 1
      code/FBXDocument.cpp
  3. 14 3
      code/FBXDocument.h

+ 42 - 1
code/FBXAnimation.cpp

@@ -98,6 +98,7 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
 : Object(id, element, name)
 , target()
 {
+	{
 	// resolve attached animation curves
 	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
 
@@ -119,9 +120,49 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
 			DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
 			continue;
 		}
+		
+		curves[con->PropertyName()] = anim;
+	}
+
+	}{
+
+	// find target node
+	const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID());
+
+	BOOST_FOREACH(const Connection* con, conns) {
+
+		// link should go for a property
+		if (con->PropertyName().length()) {
+			continue;
+		}
+
+		// note: the implicit rule in all DOM classes is to always resolve
+		// from destination to source (since the FBX object hierarchy is,
+		// with very few exceptions, a DAG, this avoids cycles). Since
+		// it goes the other way round, we have to cope with the case
+		// that the destination is not fully constructed yet.
+		LazyObject& lob = con->LazyDestinationObject();
+		if(lob.IsBeingConstructed()) {
+			continue;
+		}
+
+		const Object* ob = lob.Get();
+		if(!ob) {
+			DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
+			continue;
+		}
+
+		target = dynamic_cast<const Model*>(ob);
+		if(!target) {
+			continue;
+		}
 
 		prop = con->PropertyName();
-		curves[prop] = anim;
+		break;
+	}
+	}
+	if(!target) {
+		DOMError("failed to resolve target model for animation node",&element);
 	}
 }
 

+ 27 - 1
code/FBXDocument.cpp

@@ -390,6 +390,7 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
 : doc(doc)
 , element(element)
 , id(id)
+, being_constructed()
 {
 
 }
@@ -425,7 +426,8 @@ const Object* LazyObject::Get()
 		DOMError(err,&element);
 	} 
 
-	// XXX prevent recursive calls
+	// prevent recursive calls
+	being_constructed = true;
 
 	// this needs to be relatively fast since it happens a lot,
 	// so avoid constructing strings all the time.
@@ -462,6 +464,7 @@ const Object* LazyObject::Get()
 		//DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
 	}
 
+	being_constructed = false;
 	return object.get();
 }
 
@@ -697,6 +700,7 @@ void Document::ReadConnections()
 	}
 }
 
+
 // ------------------------------------------------------------------------------------------------
 const std::vector<const AnimationStack*>& Document::AnimationStacks() const
 {
@@ -718,6 +722,7 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
 	return animationStacksResolved;
 }
 
+
 // ------------------------------------------------------------------------------------------------
 LazyObject* Document::GetObject(uint64_t id) const
 {
@@ -725,6 +730,7 @@ LazyObject* Document::GetObject(uint64_t id) const
 	return it == objects.end() ? NULL : (*it).second;
 }
 
+
 // ------------------------------------------------------------------------------------------------
 std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
 {
@@ -762,6 +768,7 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
 	return temp; // NRVO should handle this
 }
 
+
 // ------------------------------------------------------------------------------------------------
 Connection::Connection(uint64_t insertionOrder,  uint64_t src, uint64_t dest, const std::string& prop, const Document& doc)
 : insertionOrder(insertionOrder)
@@ -783,6 +790,24 @@ Connection::~Connection()
 }
 
 
+// ------------------------------------------------------------------------------------------------
+LazyObject& Connection::LazySourceObject() const
+{
+	LazyObject* const lazy = doc.GetObject(src);
+	ai_assert(lazy);
+	return *lazy;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+LazyObject& Connection::LazyDestinationObject() const
+{
+	LazyObject* const lazy = doc.GetObject(dest);
+	ai_assert(lazy);
+	return *lazy;
+}
+
+
 // ------------------------------------------------------------------------------------------------
 const Object* Connection::SourceObject() const
 {
@@ -791,6 +816,7 @@ const Object* Connection::SourceObject() const
 	return lazy->Get();
 }
 
+
 // ------------------------------------------------------------------------------------------------
 const Object* Connection::DestinationObject() const
 {

+ 14 - 3
code/FBXDocument.h

@@ -85,6 +85,10 @@ public:
 		return id;
 	}
 
+	bool IsBeingConstructed() const {
+		return being_constructed;
+	}
+
 private:
 
 	const Document& doc;
@@ -92,6 +96,7 @@ private:
 	boost::scoped_ptr<const Object> object;
 
 	const uint64_t id;
+	bool being_constructed;
 };
 
 
@@ -469,11 +474,12 @@ public:
 		return curves;
 	}
 
-
+	/** Model instance the curve is assigned to, this is always non-NULL */
 	const Model* TargetNode() const {
 		return target;
 	}
 
+	/** Property of TargetNode() that is being animated*/
 	const std::string& TargetProperty() const {
 		return prop;
 	}
@@ -562,8 +568,13 @@ public:
 	const Object* SourceObject() const;
 	const Object* DestinationObject() const;
 
-	// return the name of the property the connection is attached to.
-	// this is an empty string for object to object (OO) connections.
+	// these, however, are always guaranteed to be valid
+	LazyObject& LazySourceObject() const;
+	LazyObject& LazyDestinationObject() const;
+
+
+	/** return the name of the property the connection is attached to.
+	  * this is an empty string for object to object (OO) connections. */
 	const std::string& PropertyName() const {
 		return prop;
 	}