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

Reply via email to