Blender V2.61 - r43446

IK_QSegment.h

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Original author: Laurence
00024  * Contributor(s): Brecht
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #ifndef NAN_INCLUDED_IK_QSegment_h
00035 #define NAN_INCLUDED_IK_QSegment_h
00036 
00037 #include "MT_Vector3.h"
00038 #include "MT_Transform.h"
00039 #include "MT_Matrix4x4.h"
00040 #include "IK_QJacobian.h"
00041 
00042 #include <vector>
00043 
00065 class IK_QSegment
00066 {
00067 public:
00068     virtual ~IK_QSegment();
00069 
00070     // start: a user defined translation
00071     // rest_basis: a user defined rotation
00072     // basis: a user defined rotation
00073     // length: length of this segment
00074 
00075     void SetTransform(
00076         const MT_Vector3& start,
00077         const MT_Matrix3x3& rest_basis,
00078         const MT_Matrix3x3& basis,
00079         const MT_Scalar length
00080     );
00081 
00082     // tree structure access
00083     void SetParent(IK_QSegment *parent);
00084 
00085     IK_QSegment *Child() const
00086     { return m_child; }
00087 
00088     IK_QSegment *Sibling() const
00089     { return m_sibling; }
00090 
00091     IK_QSegment *Parent() const
00092     { return m_parent; }
00093 
00094     // for combining two joints into one from the interface
00095     void SetComposite(IK_QSegment *seg);
00096     
00097     IK_QSegment *Composite() const
00098     { return m_composite; }
00099 
00100     // number of degrees of freedom
00101     int NumberOfDoF() const
00102     { return m_num_DoF; }
00103 
00104     // unique id for this segment, for identification in the jacobian
00105     int DoFId() const
00106     { return m_DoF_id; }
00107 
00108     void SetDoFId(int dof_id)
00109     { m_DoF_id = dof_id; }
00110 
00111     // the max distance of the end of this bone from the local origin.
00112     const MT_Scalar MaxExtension() const
00113     { return m_max_extension; }
00114 
00115     // the change in rotation and translation w.r.t. the rest pose
00116     MT_Matrix3x3 BasisChange() const;
00117     MT_Vector3 TranslationChange() const;
00118 
00119     // the start and end of the segment
00120     const MT_Point3 &GlobalStart() const
00121     { return m_global_start; }
00122 
00123     const MT_Point3 &GlobalEnd() const
00124     { return m_global_transform.getOrigin(); }
00125 
00126     // the global transformation at the end of the segment
00127     const MT_Transform &GlobalTransform() const
00128     { return m_global_transform; }
00129 
00130     // is a translational segment?
00131     bool Translational() const
00132     { return m_translational; }
00133 
00134     // locking (during inner clamping loop)
00135     bool Locked(int dof) const
00136     { return m_locked[dof]; }
00137 
00138     void UnLock()
00139     { m_locked[0] = m_locked[1] = m_locked[2] = false; }
00140 
00141     // per dof joint weighting
00142     MT_Scalar Weight(int dof) const
00143     { return m_weight[dof]; }
00144 
00145     void ScaleWeight(int dof, MT_Scalar scale)
00146     { m_weight[dof] *= scale; }
00147 
00148     // recursively update the global coordinates of this segment, 'global'
00149     // is the global transformation from the parent segment
00150     void UpdateTransform(const MT_Transform &global);
00151 
00152     // get axis from rotation matrix for derivative computation
00153     virtual MT_Vector3 Axis(int dof) const=0;
00154 
00155     // update the angles using the dTheta's computed using the jacobian matrix
00156     virtual bool UpdateAngle(const IK_QJacobian&, MT_Vector3&, bool*)=0;
00157     virtual void Lock(int, IK_QJacobian&, MT_Vector3&) {}
00158     virtual void UpdateAngleApply()=0;
00159 
00160     // set joint limits
00161     virtual void SetLimit(int, MT_Scalar, MT_Scalar) {};
00162 
00163     // set joint weights (per axis)
00164     virtual void SetWeight(int, MT_Scalar) {};
00165 
00166     virtual void SetBasis(const MT_Matrix3x3& basis) { m_basis = basis; }
00167 
00168     // functions needed for pole vector constraint
00169     void PrependBasis(const MT_Matrix3x3& mat);
00170     void Reset();
00171 
00172     // scale
00173     virtual void Scale(float scale);
00174 
00175 protected:
00176 
00177     // num_DoF: number of degrees of freedom
00178     IK_QSegment(int num_DoF, bool translational);
00179 
00180     // remove child as a child of this segment
00181     void RemoveChild(IK_QSegment *child);
00182 
00183     // tree structure variables
00184     IK_QSegment *m_parent;
00185     IK_QSegment *m_child;
00186     IK_QSegment *m_sibling;
00187     IK_QSegment *m_composite;
00188 
00189     // full transform = 
00190     // start * rest_basis * basis * translation
00191     MT_Vector3 m_start;
00192     MT_Matrix3x3 m_rest_basis;
00193     MT_Matrix3x3 m_basis;
00194     MT_Vector3 m_translation;
00195 
00196     // original basis
00197     MT_Matrix3x3 m_orig_basis;
00198     MT_Vector3 m_orig_translation;
00199 
00200     // maximum extension of this segment
00201     MT_Scalar m_max_extension;
00202 
00203     // accumulated transformations starting from root
00204     MT_Point3 m_global_start;
00205     MT_Transform m_global_transform;
00206 
00207     // number degrees of freedom, (first) id of this segments DOF's
00208     int m_num_DoF, m_DoF_id;
00209 
00210     bool m_locked[3];
00211     bool m_translational;
00212     MT_Scalar m_weight[3];
00213 };
00214 
00215 class IK_QSphericalSegment : public IK_QSegment
00216 {
00217 public:
00218     IK_QSphericalSegment();
00219 
00220     MT_Vector3 Axis(int dof) const;
00221 
00222     bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
00223     void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
00224     void UpdateAngleApply();
00225 
00226     bool ComputeClampRotation(MT_Vector3& clamp);
00227 
00228     void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
00229     void SetWeight(int axis, MT_Scalar weight);
00230 
00231 private:
00232     MT_Matrix3x3 m_new_basis;
00233     bool m_limit_x, m_limit_y, m_limit_z;
00234     MT_Scalar m_min[2], m_max[2];
00235     MT_Scalar m_min_y, m_max_y, m_max_x, m_max_z, m_offset_x, m_offset_z;
00236     MT_Scalar m_locked_ax, m_locked_ay, m_locked_az;
00237 };
00238 
00239 class IK_QNullSegment : public IK_QSegment
00240 {
00241 public:
00242     IK_QNullSegment();
00243 
00244     bool UpdateAngle(const IK_QJacobian&, MT_Vector3&, bool*) { return false; }
00245     void UpdateAngleApply() {}
00246 
00247     MT_Vector3 Axis(int) const { return MT_Vector3(0, 0, 0); }
00248     void SetBasis(const MT_Matrix3x3&) { m_basis.setIdentity(); }
00249 };
00250 
00251 class IK_QRevoluteSegment : public IK_QSegment
00252 {
00253 public:
00254     // axis: the axis of the DoF, in range 0..2
00255     IK_QRevoluteSegment(int axis);
00256 
00257     MT_Vector3 Axis(int dof) const;
00258 
00259     bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
00260     void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
00261     void UpdateAngleApply();
00262 
00263     void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
00264     void SetWeight(int axis, MT_Scalar weight);
00265     void SetBasis(const MT_Matrix3x3& basis);
00266 
00267 private:
00268     int m_axis;
00269     MT_Scalar m_angle, m_new_angle;
00270     bool m_limit;
00271     MT_Scalar m_min, m_max;
00272 };
00273 
00274 class IK_QSwingSegment : public IK_QSegment
00275 {
00276 public:
00277     // XZ DOF, uses one direct rotation
00278     IK_QSwingSegment();
00279 
00280     MT_Vector3 Axis(int dof) const;
00281 
00282     bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
00283     void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
00284     void UpdateAngleApply();
00285 
00286     void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
00287     void SetWeight(int axis, MT_Scalar weight);
00288     void SetBasis(const MT_Matrix3x3& basis);
00289 
00290 private:
00291     MT_Matrix3x3 m_new_basis;
00292     bool m_limit_x, m_limit_z;
00293     MT_Scalar m_min[2], m_max[2];
00294     MT_Scalar m_max_x, m_max_z, m_offset_x, m_offset_z;
00295 };
00296 
00297 class IK_QElbowSegment : public IK_QSegment
00298 {
00299 public:
00300     // XY or ZY DOF, uses two sequential rotations: first rotate around
00301     // X or Z, then rotate around Y (twist)
00302     IK_QElbowSegment(int axis);
00303 
00304     MT_Vector3 Axis(int dof) const;
00305 
00306     bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
00307     void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
00308     void UpdateAngleApply();
00309 
00310     void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
00311     void SetWeight(int axis, MT_Scalar weight);
00312     void SetBasis(const MT_Matrix3x3& basis);
00313 
00314 private:
00315     int m_axis;
00316 
00317     MT_Scalar m_twist, m_angle, m_new_twist, m_new_angle;
00318     MT_Scalar m_cos_twist, m_sin_twist;
00319 
00320     bool m_limit, m_limit_twist;
00321     MT_Scalar m_min, m_max, m_min_twist, m_max_twist;
00322 };
00323 
00324 class IK_QTranslateSegment : public IK_QSegment
00325 {
00326 public:
00327     // 1DOF, 2DOF or 3DOF translational segments
00328     IK_QTranslateSegment(int axis1);
00329     IK_QTranslateSegment(int axis1, int axis2);
00330     IK_QTranslateSegment();
00331 
00332     MT_Vector3 Axis(int dof) const;
00333 
00334     bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
00335     void Lock(int, IK_QJacobian&, MT_Vector3&);
00336     void UpdateAngleApply();
00337 
00338     void SetWeight(int axis, MT_Scalar weight);
00339     void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
00340 
00341     void Scale(float scale);
00342 
00343 private:
00344     int m_axis[3];
00345     bool m_axis_enabled[3], m_limit[3];
00346     MT_Vector3 m_new_translation;
00347     MT_Scalar m_min[3], m_max[3];
00348 };
00349 
00350 #endif
00351