Blender  V2.93
IK_QTask.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include "IK_QTask.h"
25 
26 // IK_QTask
27 
28 IK_QTask::IK_QTask(int size, bool primary, bool active, const IK_QSegment *segment)
29  : m_size(size), m_primary(primary), m_active(active), m_segment(segment), m_weight(1.0)
30 {
31 }
32 
33 // IK_QPositionTask
34 
35 IK_QPositionTask::IK_QPositionTask(bool primary, const IK_QSegment *segment, const Vector3d &goal)
36  : IK_QTask(3, primary, true, segment), m_goal(goal)
37 {
38  // computing clamping length
39  int num;
40  const IK_QSegment *seg;
41 
42  m_clamp_length = 0.0;
43  num = 0;
44 
45  for (seg = m_segment; seg; seg = seg->Parent()) {
46  m_clamp_length += seg->MaxExtension();
47  num++;
48  }
49 
50  m_clamp_length /= 2 * num;
51 }
52 
54 {
55  // compute beta
56  const Vector3d &pos = m_segment->GlobalEnd();
57 
58  Vector3d d_pos = m_goal - pos;
59  double length = d_pos.norm();
60 
61  if (length > m_clamp_length)
62  d_pos = (m_clamp_length / length) * d_pos;
63 
64  jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
65 
66  // compute derivatives
67  int i;
68  const IK_QSegment *seg;
69 
70  for (seg = m_segment; seg; seg = seg->Parent()) {
71  Vector3d p = seg->GlobalStart() - pos;
72 
73  for (i = 0; i < seg->NumberOfDoF(); i++) {
74  Vector3d axis = seg->Axis(i) * m_weight;
75 
76  if (seg->Translational())
77  jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e2);
78  else {
79  Vector3d pa = p.cross(axis);
80  jacobian.SetDerivatives(m_id, seg->DoFId() + i, pa, 1e0);
81  }
82  }
83  }
84 }
85 
87 {
88  const Vector3d &pos = m_segment->GlobalEnd();
89  Vector3d d_pos = m_goal - pos;
90  return d_pos.norm();
91 }
92 
93 // IK_QOrientationTask
94 
96  const IK_QSegment *segment,
97  const Matrix3d &goal)
98  : IK_QTask(3, primary, true, segment), m_goal(goal), m_distance(0.0)
99 {
100 }
101 
103 {
104  // compute betas
105  const Matrix3d &rot = m_segment->GlobalTransform().linear();
106 
107  Matrix3d d_rotm = (m_goal * rot.transpose()).transpose();
108 
109  Vector3d d_rot;
110  d_rot = -0.5 * Vector3d(d_rotm(2, 1) - d_rotm(1, 2),
111  d_rotm(0, 2) - d_rotm(2, 0),
112  d_rotm(1, 0) - d_rotm(0, 1));
113 
114  m_distance = d_rot.norm();
115 
116  jacobian.SetBetas(m_id, m_size, m_weight * d_rot);
117 
118  // compute derivatives
119  int i;
120  const IK_QSegment *seg;
121 
122  for (seg = m_segment; seg; seg = seg->Parent())
123  for (i = 0; i < seg->NumberOfDoF(); i++) {
124 
125  if (seg->Translational())
126  jacobian.SetDerivatives(m_id, seg->DoFId() + i, Vector3d(0, 0, 0), 1e2);
127  else {
128  Vector3d axis = seg->Axis(i) * m_weight;
129  jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e0);
130  }
131  }
132 }
133 
134 // IK_QCenterOfMassTask
135 // Note: implementation not finished!
136 
138  const IK_QSegment *segment,
139  const Vector3d &goal_center)
140  : IK_QTask(3, primary, true, segment), m_goal_center(goal_center)
141 {
142  m_total_mass_inv = ComputeTotalMass(m_segment);
143  if (!FuzzyZero(m_total_mass_inv))
144  m_total_mass_inv = 1.0 / m_total_mass_inv;
145 }
146 
147 double IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
148 {
149  double mass = /*seg->Mass()*/ 1.0;
150 
151  const IK_QSegment *seg;
152  for (seg = segment->Child(); seg; seg = seg->Sibling())
153  mass += ComputeTotalMass(seg);
154 
155  return mass;
156 }
157 
158 Vector3d IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
159 {
160  Vector3d center = /*seg->Mass()**/ segment->GlobalStart();
161 
162  const IK_QSegment *seg;
163  for (seg = segment->Child(); seg; seg = seg->Sibling())
164  center += ComputeCenter(seg);
165 
166  return center;
167 }
168 
169 void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian &jacobian,
170  Vector3d &center,
171  const IK_QSegment *segment)
172 {
173  int i;
174  Vector3d p = center - segment->GlobalStart();
175 
176  for (i = 0; i < segment->NumberOfDoF(); i++) {
177  Vector3d axis = segment->Axis(i) * m_weight;
178  axis *= /*segment->Mass()**/ m_total_mass_inv;
179 
180  if (segment->Translational())
181  jacobian.SetDerivatives(m_id, segment->DoFId() + i, axis, 1e2);
182  else {
183  Vector3d pa = axis.cross(p);
184  jacobian.SetDerivatives(m_id, segment->DoFId() + i, pa, 1e0);
185  }
186  }
187 
188  const IK_QSegment *seg;
189  for (seg = segment->Child(); seg; seg = seg->Sibling())
190  JacobianSegment(jacobian, center, seg);
191 }
192 
194 {
195  Vector3d center = ComputeCenter(m_segment) * m_total_mass_inv;
196 
197  // compute beta
198  Vector3d d_pos = m_goal_center - center;
199 
200  m_distance = d_pos.norm();
201 
202 #if 0
203  if (m_distance > m_clamp_length)
204  d_pos = (m_clamp_length / m_distance) * d_pos;
205 #endif
206 
207  jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
208 
209  // compute derivatives
210  JacobianSegment(jacobian, center, m_segment);
211 }
212 
214 {
215  return m_distance;
216 }
NSNotificationCenter * center
static bool FuzzyZero(double x)
Definition: IK_Math.h:36
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btMatrix3x3 transpose() const
Return the transpose of the matrix.
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
void ComputeJacobian(IK_QJacobian &jacobian)
Definition: IK_QTask.cpp:193
IK_QCenterOfMassTask(bool primary, const IK_QSegment *segment, const Vector3d &center)
Definition: IK_QTask.cpp:137
double Distance() const
Definition: IK_QTask.cpp:213
void SetDerivatives(int id, int dof_id, const Vector3d &v, double norm_weight)
void SetBetas(int id, int size, const Vector3d &v)
IK_QOrientationTask(bool primary, const IK_QSegment *segment, const Matrix3d &goal)
Definition: IK_QTask.cpp:95
void ComputeJacobian(IK_QJacobian &jacobian)
Definition: IK_QTask.cpp:102
void ComputeJacobian(IK_QJacobian &jacobian)
Definition: IK_QTask.cpp:53
double Distance() const
Definition: IK_QTask.cpp:86
IK_QPositionTask(bool primary, const IK_QSegment *segment, const Vector3d &goal)
Definition: IK_QTask.cpp:35
int NumberOfDoF() const
Definition: IK_QSegment.h:94
int DoFId() const
Definition: IK_QSegment.h:100
const Vector3d GlobalStart() const
Definition: IK_QSegment.h:121
const Affine3d & GlobalTransform() const
Definition: IK_QSegment.h:132
const Vector3d GlobalEnd() const
Definition: IK_QSegment.h:126
IK_QSegment * Sibling() const
Definition: IK_QSegment.h:75
bool Translational() const
Definition: IK_QSegment.h:138
const double MaxExtension() const
Definition: IK_QSegment.h:111
virtual Vector3d Axis(int dof) const =0
IK_QSegment * Parent() const
Definition: IK_QSegment.h:80
const IK_QSegment * m_segment
Definition: IK_QTask.h:91
double m_weight
Definition: IK_QTask.h:92
int m_size
Definition: IK_QTask.h:88
int m_id
Definition: IK_QTask.h:87
IK_QTask(int size, bool primary, bool active, const IK_QSegment *segment)
Definition: IK_QTask.cpp:28
#define rot(x, k)
uint pos
Segment< FEdge *, Vec3r > segment
bool active
all scheduled work for the GPU.