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