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. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs