Fix too much memory usage for Cycles attribute map.
[blender.git] / intern / iksolver / intern / IK_QSegment.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Original author: Laurence
24  * Contributor(s): Brecht
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file iksolver/intern/IK_QSegment.h
30  *  \ingroup iksolver
31  */
32
33 #pragma once
34
35 #include "IK_Math.h"
36 #include "IK_QJacobian.h"
37
38 #include <vector>
39
40 /**
41  * An IK_Qsegment encodes information about a segments
42  * local coordinate system.
43  * 
44  * These segments always point along the y-axis.
45  * 
46  * Here we define the local coordinates of a joint as
47  * local_transform = 
48  * translate(tr1) * rotation(A) * rotation(q) * translate(0,length,0)
49  * You can read this as:
50  * - first translate by (0,length,0)
51  * - multiply by the rotation matrix derived from the current
52  * angle parameterization q.
53  * - multiply by the user defined matrix representing the rest
54  * position of the bone.
55  * - translate by the used defined translation (tr1)
56  * The ordering of these transformations is vital, you must
57  * use exactly the same transformations when displaying the segments
58  */
59
60 class IK_QSegment
61 {
62 public:
63         EIGEN_MAKE_ALIGNED_OPERATOR_NEW
64         virtual ~IK_QSegment();
65
66         // start: a user defined translation
67         // rest_basis: a user defined rotation
68         // basis: a user defined rotation
69         // length: length of this segment
70
71         void SetTransform(
72                 const Vector3d& start,
73                 const Matrix3d& rest_basis,
74                 const Matrix3d& basis,
75                 const double length
76         );
77
78         // tree structure access
79         void SetParent(IK_QSegment *parent);
80
81         IK_QSegment *Child() const
82         { return m_child; }
83
84         IK_QSegment *Sibling() const
85         { return m_sibling; }
86
87         IK_QSegment *Parent() const
88         { return m_parent; }
89
90         // for combining two joints into one from the interface
91         void SetComposite(IK_QSegment *seg);
92         
93         IK_QSegment *Composite() const
94         { return m_composite; }
95
96         // number of degrees of freedom
97         int NumberOfDoF() const
98         { return m_num_DoF; }
99
100         // unique id for this segment, for identification in the jacobian
101         int DoFId() const
102         { return m_DoF_id; }
103
104         void SetDoFId(int dof_id)
105         { m_DoF_id = dof_id; }
106
107         // the max distance of the end of this bone from the local origin.
108         const double MaxExtension() const
109         { return m_max_extension; }
110
111         // the change in rotation and translation w.r.t. the rest pose
112         Matrix3d BasisChange() const;
113         Vector3d TranslationChange() const;
114
115         // the start and end of the segment
116         const Vector3d GlobalStart() const
117         { return m_global_start; }
118
119         const Vector3d GlobalEnd() const
120         { return m_global_transform.translation(); }
121
122         // the global transformation at the end of the segment
123         const Affine3d &GlobalTransform() const
124         { return m_global_transform; }
125
126         // is a translational segment?
127         bool Translational() const
128         { return m_translational; }
129
130         // locking (during inner clamping loop)
131         bool Locked(int dof) const
132         { return m_locked[dof]; }
133
134         void UnLock()
135         { m_locked[0] = m_locked[1] = m_locked[2] = false; }
136
137         // per dof joint weighting
138         double Weight(int dof) const
139         { return m_weight[dof]; }
140
141         void ScaleWeight(int dof, double scale)
142         { m_weight[dof] *= scale; }
143
144         // recursively update the global coordinates of this segment, 'global'
145         // is the global transformation from the parent segment
146         void UpdateTransform(const Affine3d &global);
147
148         // get axis from rotation matrix for derivative computation
149         virtual Vector3d Axis(int dof) const=0;
150
151         // update the angles using the dTheta's computed using the jacobian matrix
152         virtual bool UpdateAngle(const IK_QJacobian&, Vector3d&, bool*)=0;
153         virtual void Lock(int, IK_QJacobian&, Vector3d&) {}
154         virtual void UpdateAngleApply()=0;
155
156         // set joint limits
157         virtual void SetLimit(int, double, double) {}
158
159         // set joint weights (per axis)
160         virtual void SetWeight(int, double) {}
161
162         virtual void SetBasis(const Matrix3d& basis) { m_basis = basis; }
163
164         // functions needed for pole vector constraint
165         void PrependBasis(const Matrix3d& mat);
166         void Reset();
167
168         // scale
169         virtual void Scale(double scale);
170
171 protected:
172
173         // num_DoF: number of degrees of freedom
174         IK_QSegment(int num_DoF, bool translational);
175
176         // remove child as a child of this segment
177         void RemoveChild(IK_QSegment *child);
178
179         // tree structure variables
180         IK_QSegment *m_parent;
181         IK_QSegment *m_child;
182         IK_QSegment *m_sibling;
183         IK_QSegment *m_composite;
184
185         // full transform = 
186         // start * rest_basis * basis * translation
187         Vector3d m_start;
188         Matrix3d m_rest_basis;
189         Matrix3d m_basis;
190         Vector3d m_translation;
191
192         // original basis
193         Matrix3d m_orig_basis;
194         Vector3d m_orig_translation;
195
196         // maximum extension of this segment
197         double m_max_extension;
198
199         // accumulated transformations starting from root
200         Vector3d m_global_start;
201         Affine3d m_global_transform;
202
203         // number degrees of freedom, (first) id of this segments DOF's
204         int m_num_DoF, m_DoF_id;
205
206         bool m_locked[3];
207         bool m_translational;
208         double m_weight[3];
209 };
210
211 class IK_QSphericalSegment : public IK_QSegment
212 {
213 public:
214         IK_QSphericalSegment();
215
216         Vector3d Axis(int dof) const;
217
218         bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
219         void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
220         void UpdateAngleApply();
221
222         bool ComputeClampRotation(Vector3d& clamp);
223
224         void SetLimit(int axis, double lmin, double lmax);
225         void SetWeight(int axis, double weight);
226
227 private:
228         Matrix3d m_new_basis;
229         bool m_limit_x, m_limit_y, m_limit_z;
230         double m_min[2], m_max[2];
231         double m_min_y, m_max_y, m_max_x, m_max_z, m_offset_x, m_offset_z;
232         double m_locked_ax, m_locked_ay, m_locked_az;
233 };
234
235 class IK_QNullSegment : public IK_QSegment
236 {
237 public:
238         IK_QNullSegment();
239
240         bool UpdateAngle(const IK_QJacobian&, Vector3d&, bool*) { return false; }
241         void UpdateAngleApply() {}
242
243         Vector3d Axis(int) const { return Vector3d(0, 0, 0); }
244         void SetBasis(const Matrix3d&) { m_basis.setIdentity(); }
245 };
246
247 class IK_QRevoluteSegment : public IK_QSegment
248 {
249 public:
250         // axis: the axis of the DoF, in range 0..2
251         IK_QRevoluteSegment(int axis);
252
253         Vector3d Axis(int dof) const;
254
255         bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
256         void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
257         void UpdateAngleApply();
258
259         void SetLimit(int axis, double lmin, double lmax);
260         void SetWeight(int axis, double weight);
261         void SetBasis(const Matrix3d& basis);
262
263 private:
264         int m_axis;
265         double m_angle, m_new_angle;
266         bool m_limit;
267         double m_min, m_max;
268 };
269
270 class IK_QSwingSegment : public IK_QSegment
271 {
272 public:
273         // XZ DOF, uses one direct rotation
274         IK_QSwingSegment();
275
276         Vector3d Axis(int dof) const;
277
278         bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
279         void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
280         void UpdateAngleApply();
281
282         void SetLimit(int axis, double lmin, double lmax);
283         void SetWeight(int axis, double weight);
284         void SetBasis(const Matrix3d& basis);
285
286 private:
287         Matrix3d m_new_basis;
288         bool m_limit_x, m_limit_z;
289         double m_min[2], m_max[2];
290         double m_max_x, m_max_z, m_offset_x, m_offset_z;
291 };
292
293 class IK_QElbowSegment : public IK_QSegment
294 {
295 public:
296         // XY or ZY DOF, uses two sequential rotations: first rotate around
297         // X or Z, then rotate around Y (twist)
298         IK_QElbowSegment(int axis);
299
300         Vector3d Axis(int dof) const;
301
302         bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
303         void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
304         void UpdateAngleApply();
305
306         void SetLimit(int axis, double lmin, double lmax);
307         void SetWeight(int axis, double weight);
308         void SetBasis(const Matrix3d& basis);
309
310 private:
311         int m_axis;
312
313         double m_twist, m_angle, m_new_twist, m_new_angle;
314         double m_cos_twist, m_sin_twist;
315
316         bool m_limit, m_limit_twist;
317         double m_min, m_max, m_min_twist, m_max_twist;
318 };
319
320 class IK_QTranslateSegment : public IK_QSegment
321 {
322 public:
323         // 1DOF, 2DOF or 3DOF translational segments
324         IK_QTranslateSegment(int axis1);
325         IK_QTranslateSegment(int axis1, int axis2);
326         IK_QTranslateSegment();
327
328         Vector3d Axis(int dof) const;
329
330         bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
331         void Lock(int, IK_QJacobian&, Vector3d&);
332         void UpdateAngleApply();
333
334         void SetWeight(int axis, double weight);
335         void SetLimit(int axis, double lmin, double lmax);
336
337         void Scale(double scale);
338
339 private:
340         int m_axis[3];
341         bool m_axis_enabled[3], m_limit[3];
342         Vector3d m_new_translation;
343         double m_min[3], m_max[3];
344 };
345