[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