IK
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 1 Nov 2007 12:40:46 +0000 (12:40 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 1 Nov 2007 12:40:46 +0000 (12:40 +0000)
==

Solving is now done independent of scale, by scaling the chain to have a
size of about 1.0. This solves some issues with small or big chains, and
also makes the IK stretch setting independent of scale. The latter breaks
backwards compatibility somewhat, but is an improvement over what it did
before.

intern/iksolver/intern/IK_QJacobianSolver.cpp
intern/iksolver/intern/IK_QJacobianSolver.h
intern/iksolver/intern/IK_QSegment.cpp
intern/iksolver/intern/IK_QSegment.h
intern/iksolver/intern/IK_QTask.h
intern/iksolver/intern/IK_Solver.cpp
source/blender/blenkernel/intern/armature.c

index f19b2a162fa224ce43b8ee1de94a4ef8be69aace..17750a7195fe9e90e53190ca58193f17e3f351f3 100644 (file)
@@ -42,6 +42,36 @@ IK_QJacobianSolver::IK_QJacobianSolver()
        m_rootmatrix.setIdentity();
 }
 
+MT_Scalar IK_QJacobianSolver::ComputeScale()
+{
+       std::vector<IK_QSegment*>::iterator seg;
+       float length = 0.0f;
+
+       for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
+               length += (*seg)->MaxExtension();
+       
+       if(length == 0.0f)
+               return 1.0f;
+       else
+               return 1.0f/length;
+}
+
+void IK_QJacobianSolver::Scale(float scale, std::list<IK_QTask*>& tasks)
+{
+       std::list<IK_QTask*>::iterator task;
+       std::vector<IK_QSegment*>::iterator seg;
+
+       for (task = tasks.begin(); task != tasks.end(); task++)
+               (*task)->Scale(scale);
+
+       for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
+               (*seg)->Scale(scale);
+       
+       m_rootmatrix.getOrigin() *= scale;
+       m_goal *= scale;
+       m_polegoal *= scale;
+}
+
 void IK_QJacobianSolver::AddSegmentList(IK_QSegment *seg)
 {
        m_segments.push_back(seg);
@@ -293,9 +323,12 @@ bool IK_QJacobianSolver::Solve(
        const int max_iterations
 )
 {
+       float scale = ComputeScale();
        bool solved = false;
        //double dt = analyze_time();
 
+       Scale(scale, tasks);
+
        ConstrainPoleVector(root, tasks);
 
        root->UpdateTransform(m_rootmatrix);
@@ -346,15 +379,14 @@ bool IK_QJacobianSolver::Solve(
                if (norm < 1e-3) {
                        solved = true;
                        break;
-                       //analyze_add_run(iterations, analyze_time()-dt);
-
-                       return true;
                }
        }
 
        if(m_poleconstraint)
                root->PrependBasis(m_rootmatrix.getBasis());
 
+       Scale(1.0f/scale, tasks);
+
        //analyze_add_run(max_iterations, analyze_time()-dt);
 
        return solved;
index bc3d1686b59870c597325b566f0daff1f7e95500..9ad46cd0aa604b2d6bcde630236574b9c1428a63 100644 (file)
@@ -75,6 +75,9 @@ private:
        bool UpdateAngles(MT_Scalar& norm);
        void ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask*>& tasks);
 
+       MT_Scalar ComputeScale();
+       void Scale(float scale, std::list<IK_QTask*>& tasks);
+
 private:
 
        IK_QJacobian m_jacobian;
index 1855c1e3db3b626812607f2f7f79953408495aae..a5217ed91d63567d34153831d2ace421bd8444b3 100644 (file)
@@ -343,6 +343,16 @@ void IK_QSegment::PrependBasis(const MT_Matrix3x3& mat)
        m_basis = m_rest_basis.inverse() * mat * m_rest_basis * m_basis;
 }
 
+void IK_QSegment::Scale(float scale)
+{
+       m_start *= scale;
+       m_translation *= scale;
+       m_orig_translation *= scale;
+       m_global_start *= scale;
+       m_global_transform.getOrigin() *= scale;
+       m_max_extension *= scale;
+}
+
 // IK_QSphericalSegment
 
 IK_QSphericalSegment::IK_QSphericalSegment()
@@ -1026,3 +1036,17 @@ void IK_QTranslateSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
        m_limit[axis]= true;
 }
 
+void IK_QTranslateSegment::Scale(float scale)
+{
+       int i;
+
+       IK_QSegment::Scale(scale);
+
+       for (i = 0; i < 3; i++) {
+               m_min[0] *= scale;
+               m_max[1] *= scale;
+       }
+
+       m_new_translation *= scale;
+}
+
index ca0abafb06adc8df8397332645fa30a32942024e..3c5df463468e5a8a4cfac3de84e99febce9f761b 100644 (file)
@@ -169,6 +169,9 @@ public:
        void PrependBasis(const MT_Matrix3x3& mat);
        void Reset();
 
+       // scale
+       virtual void Scale(float scale);
+
 protected:
 
        // num_DoF: number of degrees of freedom
@@ -335,6 +338,8 @@ public:
        void SetWeight(int axis, MT_Scalar weight);
        void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
 
+       void Scale(float scale);
+
 private:
        int m_axis[3];
        bool m_axis_enabled[3], m_limit[3];
index 26beaa386229e310f465ab4319e3c9ada0672aff..f2fd34119a1e19658a3b87065b99768af7f3b0ed 100644 (file)
@@ -77,6 +77,8 @@ public:
 
        virtual bool PositionTask() const { return false; }
 
+       virtual void Scale(float scale) {}
+
 protected:
        int m_id;
        int m_size;
@@ -100,6 +102,7 @@ public:
        MT_Scalar Distance() const;
 
        bool PositionTask() const { return true; }
+       void Scale(float scale) { m_goal *= scale; m_clamp_length *= scale; }
 
 private:
        MT_Vector3 m_goal;
@@ -137,6 +140,8 @@ public:
 
        MT_Scalar Distance() const;
 
+       void Scale(float scale) { m_goal_center *= scale; m_distance *= scale; }
+
 private:
        MT_Scalar ComputeTotalMass(const IK_QSegment *segment);
        MT_Vector3 ComputeCenter(const IK_QSegment *segment);
index b2d75d783c6016be5383e03ad7bac9ee6993ac34..140c35c8c46c28e6ceb0bdeb31f8e8d9132ae081 100644 (file)
@@ -41,7 +41,7 @@ using namespace std;
 
 class IK_QSolver {
 public:
-       IK_QSolver() {};
+       IK_QSolver() : root(NULL) {};
 
        IK_QJacobianSolver solver;
        IK_QSegment *root;
@@ -197,13 +197,12 @@ void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
        if (stiffness < 0.0)
                return;
        
-       if (stiffness > 0.99)
-               stiffness = 0.99;
+       if (stiffness > 0.999)
+               stiffness = 0.999;
 
        IK_QSegment *qseg = (IK_QSegment*)seg;
        MT_Scalar weight = 1.0-stiffness;
 
-
        if (axis >= IK_TRANS_X) {
                if(!qseg->Translational())
                        if(qseg->Composite() && qseg->Composite()->Translational())
index a282fd24509700bb1b9ad5f69673cb11ef9f496d..d5eb43fa12e3af3874be85641a64632e577743a9 100644 (file)
@@ -1598,7 +1598,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
 
                if(tree->stretch && (pchan->ikstretch > 0.0)) {
                        float ikstretch = pchan->ikstretch*pchan->ikstretch;
-                       IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.99));
+                       IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.999));
                        IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10);
                }
        }