[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20456] branches/ge_dev: iTaSC: first working version in Blender.

Benoit Bolsee benoit.bolsee at online.be
Wed May 27 20:43:10 CEST 2009


Revision: 20456
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20456
Author:   ben2610
Date:     2009-05-27 20:43:09 +0200 (Wed, 27 May 2009)

Log Message:
-----------
iTaSC: first working version in Blender. It's far from being finished but the performance target is reached: the solver usually iterates only once between the frame.

Modified Paths:
--------------
    branches/ge_dev/intern/itasc/Armature.cpp
    branches/ge_dev/intern/itasc/Armature.hpp
    branches/ge_dev/intern/itasc/Cache.cpp
    branches/ge_dev/intern/itasc/Cache.hpp
    branches/ge_dev/intern/itasc/MovingFrame.cpp
    branches/ge_dev/source/blender/ikplugin/intern/itasc_plugin.cpp

Modified: branches/ge_dev/intern/itasc/Armature.cpp
===================================================================
--- branches/ge_dev/intern/itasc/Armature.cpp	2009-05-27 17:18:14 UTC (rev 20455)
+++ branches/ge_dev/intern/itasc/Armature.cpp	2009-05-27 18:43:09 UTC (rev 20456)
@@ -14,6 +14,7 @@
 
 // a joint constraint is characterized by 5 values: tolerance, K, alpha, yd, yddot
 static const unsigned int constraintCacheSize = sizeof(double)*5;
+std::string Armature::m_root = "root";
 
 Armature::Armature():
 	ControlledObject(),
@@ -150,6 +151,33 @@
 	return true;
 }
 
+bool Armature::getSegment(const std::string& name, const Joint* &p_joint, double &q_rest, double &q, const Frame* &p_tip)
+{
+	SegmentMap::const_iterator sit = m_tree.getSegment(name);
+	if (sit == m_tree.getSegments().end())
+		return false;
+	p_joint = &sit->second.segment.getJoint();
+	p_tip = &sit->second.segment.getFrameToTip();
+	if (p_joint->getType() != Joint::None) {
+		q_rest = m_joints[sit->second.q_nr];
+		q = m_qKdl(sit->second.q_nr);
+	}
+	return true;
+}
+
+double Armature::getMaxJointChange(double timestep)
+{
+	if (!m_finalized)
+		return 0.0;
+	double maxJoint = 0.0;
+	for (unsigned int i=0; i<m_njoint; i++) {
+		double joint = fabs(m_qdot(i)*timestep);
+		if (maxJoint < joint)
+			maxJoint = joint;
+	}
+	return maxJoint;
+}
+
 int Armature::addConstraint(const std::string& segment_name, ConstraintCallback _function, void* _param, bool _freeParam, bool _substep)
 {
 	SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
@@ -310,7 +338,7 @@
 {
     //calculate pose and jacobian
 	for (unsigned int ee=0; ee<m_nee; ee++) {
-		m_fksolver->JntToCart(m_qKdl,m_effectors[ee].pose,m_effectors[ee].name);
+		m_fksolver->JntToCart(m_qKdl,m_effectors[ee].pose,m_effectors[ee].name,m_root);
 		m_jacsolver->JntToJac(m_qKdl,*m_jac,m_effectors[ee].name);
 		// get the jacobian for the base point, to prepare transformation to world reference
 		changeRefPoint(*m_jac,-m_effectors[ee].pose.p,*m_jac);
@@ -330,6 +358,13 @@
 	return (ee >= m_nee) ? F_identity : m_effectors[ee].pose;
 }
 
+bool Armature::getRelativeFrame(Frame& result, const std::string& segment_name, const std::string& base_name)
+{
+	if (!m_finalized)
+		return false;
+	return (m_fksolver->JntToCart(m_qKdl,result,segment_name,base_name) < 0) ? false : true;
+}
+
 double Armature::getJoint(unsigned int joint)
 {
 	if (m_finalized && joint < m_njoint)

Modified: branches/ge_dev/intern/itasc/Armature.hpp
===================================================================
--- branches/ge_dev/intern/itasc/Armature.hpp	2009-05-27 17:18:14 UTC (rev 20455)
+++ branches/ge_dev/intern/itasc/Armature.hpp	2009-05-27 18:43:09 UTC (rev 20456)
@@ -27,6 +27,9 @@
 	// specific limit constraint on joint
 	int addLimitConstraint(const std::string& segment_name, double _min, double _max, double _threshold, double _maxWeight=1000.0, double _slope=1.0);
 	double getJoint(unsigned int joint);
+	double getMaxJointChange(double timestep);
+	bool getSegment(const std::string& segment_name, const Joint* &p_joint, double &q_rest, double &q, const Frame* &p_tip);
+	bool getRelativeFrame(Frame& result, const std::string& segment_name, const std::string& base_name=m_root);
 
 	virtual void finalize();
 
@@ -83,6 +86,7 @@
     virtual void updateJacobian();
 
 private:
+	static std::string m_root;
     Tree m_tree;
 	unsigned int m_njoint;
 	unsigned int m_nconstraint;

Modified: branches/ge_dev/intern/itasc/Cache.cpp
===================================================================
--- branches/ge_dev/intern/itasc/Cache.cpp	2009-05-27 17:18:14 UTC (rev 20455)
+++ branches/ge_dev/intern/itasc/Cache.cpp	2009-05-27 18:43:09 UTC (rev 20456)
@@ -432,12 +432,17 @@
 
 const void *Cache::getPreviousCacheItem(const void *device, int id, unsigned int *timestamp)
 {
-	CacheMap::iterator it = m_cache.find(device);
+	CacheMap::iterator it;
 	CacheEntry *entry;
 	CacheChannel *channel;
 	CacheBuffer *buffer;
 	CacheItem *item;
 
+	if (device) {
+		it = m_cache.find(device);	
+	} else {
+		it = m_cache.begin();
+	}
 	if (it == m_cache.end()) {
 		// device does not exist
 		return NULL;

Modified: branches/ge_dev/intern/itasc/Cache.hpp
===================================================================
--- branches/ge_dev/intern/itasc/Cache.hpp	2009-05-27 17:18:14 UTC (rev 20455)
+++ branches/ge_dev/intern/itasc/Cache.hpp	2009-05-27 18:43:09 UTC (rev 20456)
@@ -107,7 +107,9 @@
 	   returns the data pointer or NULL if there is no cache item before timestamp.
 	   On return, timestamp is updated with the actual timestamp of the item being returned.
 	   Note that the length of the item is not returned, it is up to the device to organize
-	   the data so that length can be retrieved from the data if needed. */
+	   the data so that length can be retrieved from the data if needed.
+	   Device can NULL, it will then just look the first channel available, useful to 
+	   test the status of the cache. */
 	const void *getPreviousCacheItem(const void *device, int channel, CacheTS *timestamp);
 
 	/* returns the cache item with the timestamp that is exactly equal to the given timestamp

Modified: branches/ge_dev/intern/itasc/MovingFrame.cpp
===================================================================
--- branches/ge_dev/intern/itasc/MovingFrame.cpp	2009-05-27 17:18:14 UTC (rev 20455)
+++ branches/ge_dev/intern/itasc/MovingFrame.cpp	2009-05-27 18:43:09 UTC (rev 20456)
@@ -94,10 +94,11 @@
 	// don't compute the velocity during substepping, it is assumed constant.
 	if (!timestamp.substep) {
 		bool cacheAvail = true;
-		if (!timestamp.reiterate)
+		if (!timestamp.reiterate) {
 			cacheAvail = popInternalFrame(timestamp.cacheTimestamp);
-		if (m_function)
-			(*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
+			if (m_function)
+				(*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
+		}
 		// only compute velocity if we have a previous pose
 		if (cacheAvail) {
 			unsigned int iXu;

Modified: branches/ge_dev/source/blender/ikplugin/intern/itasc_plugin.cpp
===================================================================
--- branches/ge_dev/source/blender/ikplugin/intern/itasc_plugin.cpp	2009-05-27 17:18:14 UTC (rev 20455)
+++ branches/ge_dev/source/blender/ikplugin/intern/itasc_plugin.cpp	2009-05-27 18:43:09 UTC (rev 20456)
@@ -31,29 +31,34 @@
 #include <string.h>
 #include <vector>
 
+// iTaSC headers
+#include "Armature.hpp"
+#include "MovingFrame.hpp"
+#include "CopyPose.hpp"
+#include "WSDLSSolver.hpp"
+#include "Scene.hpp"
+#include "Cache.hpp"
+
 #include "MEM_guardedalloc.h"
 
+extern "C" {
 #include "BIK_api.h"
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
+#include "BKE_global.h"
 #include "BKE_armature.h"
 #include "BKE_utildefines.h"
+#include "BKE_constraint.h"
 #include "DNA_object_types.h"
 #include "DNA_action_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_armature_types.h"
+#include "DNA_scene_types.h"
+};
 
 #include "itasc_plugin.h"
 
-// iTaSC headers
-#include "Armature.hpp"
-#include "MovingFrame.hpp"
-#include "CopyPose.hpp"
-#include "WSDLSSolver.hpp"
-#include "Scene.hpp"
-#include "Cache.hpp"
-
 // Structure pointed by bArmature.ikdata
 // It contains everything needed to simulate the armatures
 // There can be several simulation islands independent to each other
@@ -63,7 +68,6 @@
 };
 
 typedef float Vector3[3];
-typedef float Vector4[4];
 
 // one structure for each target in the scene
 struct IK_Target
@@ -71,6 +75,7 @@
 	iTaSC::MovingFrame*		target;
 	iTaSC::ConstraintSet*	constraint;
 	struct bConstraint*		blenderConstraint;
+	Object*					owner;			//for auto IK
 	std::string				targetName;
 	std::string				constraintName;
 	int						ee;				//end effector number
@@ -80,6 +85,7 @@
 		target = NULL;
 		constraint = NULL;
 		blenderConstraint = NULL;
+		owner = NULL;
 		ee = 0;
 		targetName.reserve(32);
 		constraintName.reserve(32);
@@ -92,39 +98,54 @@
 	}
 };
 
+struct IK_Channel {
+	bPoseChannel*	pchan;		// channel where we must copy matrix back
+	int				parent;		// index in this array of the parent channel
+	KDL::Frame		frame;		// frame of the bone relative to object base, not armature base
+	std::string		bone;		// segment name of the joint from which we get the bone tail and head
+
+	IK_Channel() {
+		pchan = NULL;
+		parent = -1;
+	}
+};
+
 struct IK_Scene
 {
 	IK_Scene*			next;
 	int					numchan;	// number of channel in pchan
-	bPoseChannel**		pchan;		// list of pose in tree, same index as bones and parents
+	// array of bone information, one per channel in the tree
+	IK_Channel*			channels;
 	iTaSC::Armature*	armature;
 	iTaSC::Cache*		cache;
 	iTaSC::Scene*		scene;
-	iTaSC::MovingFrame* base;
+	iTaSC::MovingFrame* base;		// armature base object
+	KDL::Frame			baseFrame;	// frame of armature base relative to blArmature
 	iTaSC::WSDLSSolver* solver;
+	Object*				blArmature;
 	
-	std::vector<std::string>	bones;		// bones[i] = segment name of the joint from which we get the bone i tail and head
 	std::vector<IK_Target*>		targets;
 
 	IK_Scene() {
 		next = NULL;
-		pchan = NULL;
+		channels = NULL;
 		armature = NULL;
 		cache = NULL;
 		scene = NULL;
 		base = NULL;
 		solver = NULL;
+		blArmature = NULL;
 	}
 
 	~IK_Scene() {
-		if (pchan)
-			MEM_freeN(pchan);
 		// delete scene first
 		if (scene)
 			delete scene;
 		for(std::vector<IK_Target*>::iterator it = targets.begin();	it != targets.end(); ++it)
 			delete (*it);
 		targets.clear();
+		if (channels)
+			delete [] channels;
 		if (solver)
 			delete solver;
 		if (armature)
@@ -360,7 +381,17 @@
 	IK_Target* target = (IK_Target*)param;
 	// compute next target position
 	// get target matrix from constraint.
-	return false;
+	bKinematicConstraint* data;
+	float rootmat[4][4];
+
+	data = (bKinematicConstraint*)target->blenderConstraint->data;
+
+	get_constraint_target_matrix(target->blenderConstraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, rootmat, 1.0);
+
+	// rootmat contains the target pose in world coordinate, just put in next pose
+	// TBD: blending, pole target
+	next.setValue(&rootmat[0][0]);
+	return true;
 }
 
 static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
@@ -371,7 +402,24 @@
 	// ikscene->pchan[0] is the root channel of the tree
 	// if it has a parent, get the pose matrix from it and replace [3] by parent pchan->tail
 	// then multiply by the armature matrix to get ikscene->armature base position

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list