31 m_poleconstraint =
false;
32 m_getpoleangle =
false;
33 m_rootmatrix.setIdentity();
36 double IK_QJacobianSolver::ComputeScale()
38 std::vector<IK_QSegment *>::iterator seg;
41 for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
42 length += (*seg)->MaxExtension();
50 void IK_QJacobianSolver::Scale(
double scale, std::list<IK_QTask *> &tasks)
52 std::list<IK_QTask *>::iterator
task;
53 std::vector<IK_QSegment *>::iterator seg;
56 (*task)->Scale(scale);
58 for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
61 m_rootmatrix.translation() *= scale;
66 void IK_QJacobianSolver::AddSegmentList(
IK_QSegment *seg)
68 m_segments.push_back(seg);
71 for (child = seg->
Child(); child; child = child->
Sibling())
72 AddSegmentList(child);
81 std::vector<IK_QSegment *>::iterator seg;
84 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
86 num_dof += (*seg)->NumberOfDoF();
93 int primary_size = 0, primary = 0;
94 int secondary_size = 0, secondary = 0;
95 double primary_weight = 0.0, secondary_weight = 0.0;
96 std::list<IK_QTask *>::iterator
task;
98 for (
task = tasks.begin();
task != tasks.end();
task++) {
102 qtask->
SetId(primary_size);
103 primary_size += qtask->
Size();
104 primary_weight += qtask->
Weight();
108 qtask->
SetId(secondary_size);
109 secondary_size += qtask->
Size();
110 secondary_weight += qtask->
Weight();
115 if (primary_size == 0 ||
FuzzyZero(primary_weight))
118 m_secondary_enabled = (secondary > 0);
121 double primary_rescale = 1.0 / primary_weight;
122 double secondary_rescale;
124 secondary_rescale = 0.0;
126 secondary_rescale = 1.0 / secondary_weight;
128 for (
task = tasks.begin();
task != tasks.end();
task++) {
140 m_jacobian_sub.
ArmMatrices(num_dof, secondary_size);
145 for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
146 for (i = 0; i < (*seg)->NumberOfDoF(); i++)
147 m_jacobian.
SetDoFWeight((*seg)->DoFId() + i, (*seg)->Weight(i));
153 IK_QSegment *tip, Vector3d &goal, Vector3d &polegoal,
float poleangle,
bool getangle)
155 m_poleconstraint =
true;
158 m_polegoal = polegoal;
159 m_poleangle = (getangle) ? 0.0f : poleangle;
160 m_getpoleangle = getangle;
163 void IK_QJacobianSolver::ConstrainPoleVector(
IK_QSegment *root, std::list<IK_QTask *> &tasks)
169 if (!m_poleconstraint)
173 std::list<IK_QTask *>::iterator
task;
174 int positiontasks = 0;
177 if ((*task)->PositionTask())
180 if (positiontasks >= 2) {
181 m_poleconstraint =
false;
189 const Vector3d endpos = m_poletip->
GlobalEnd();
195 Vector3d dir =
normalize(endpos - rootpos);
196 Vector3d rootx = rootbasis.col(0);
197 Vector3d rootz = rootbasis.col(2);
198 Vector3d up = rootx *
cos(m_poleangle) + rootz *
sin(m_poleangle);
201 Vector3d poledir = (m_getpoleangle) ? dir :
normalize(m_goal - rootpos);
202 Vector3d poleup =
normalize(m_polegoal - rootpos);
204 Matrix3d mat, polemat;
207 mat.row(1) = mat.row(0).cross(dir);
210 polemat.row(0) =
normalize(poledir.cross(poleup));
211 polemat.row(1) = polemat.row(0).cross(poledir);
212 polemat.row(2) = -poledir;
214 if (m_getpoleangle) {
216 m_poleangle =
angle(mat.row(1), polemat.row(1));
218 double dt = rootz.dot(mat.row(1) *
cos(m_poleangle) + mat.row(0) *
sin(m_poleangle));
220 m_poleangle = -m_poleangle;
223 m_getpoleangle =
false;
224 ConstrainPoleVector(root, tasks);
232 trans.linear() = polemat.transpose() * mat;
233 trans.translation() = Vector3d(0, 0, 0);
234 m_rootmatrix = trans * m_rootmatrix;
238 bool IK_QJacobianSolver::UpdateAngles(
double &
norm)
241 std::vector<IK_QSegment *>::iterator seg;
243 double minabsdelta = 1e10, absdelta;
244 Vector3d delta, mindelta;
245 bool locked =
false,
clamp[3];
251 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
256 absdelta =
fabs(delta[i]);
259 qseg->
Lock(i, m_jacobian, delta);
262 else if (absdelta < minabsdelta) {
263 minabsdelta = absdelta;
275 minseg->
Lock(mindof, m_jacobian, mindelta);
278 if (minabsdelta >
norm)
284 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
286 (*seg)->UpdateAngleApply();
294 std::list<IK_QTask *> tasks,
296 const int max_iterations)
298 float scale = ComputeScale();
304 ConstrainPoleVector(root, tasks);
309 for (
int iterations = 0; iterations < max_iterations; iterations++) {
313 std::list<IK_QTask *>::iterator
task;
316 for (
task = tasks.begin();
task != tasks.end();
task++) {
317 if ((*task)->Primary())
318 (*task)->ComputeJacobian(m_jacobian);
320 (*task)->ComputeJacobian(m_jacobian_sub);
329 if (m_secondary_enabled)
330 m_jacobian.
SubTask(m_jacobian_sub);
333 fprintf(stderr,
"IK Exception\n");
338 }
while (UpdateAngles(
norm));
341 std::vector<IK_QSegment *>::iterator seg;
342 for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
351 if (norm < 1e-3 && iterations > 10) {
357 if (m_poleconstraint)
360 Scale(1.0f / scale, tasks);
static const double IK_EPSILON
static bool FuzzyZero(double x)
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
void SetPoleVectorConstraint(IK_QSegment *tip, Vector3d &goal, Vector3d &polegoal, float poleangle, bool getangle)
bool Solve(IK_QSegment *root, std::list< IK_QTask * > tasks, const double tolerance, const int max_iterations)
bool Setup(IK_QSegment *root, std::list< IK_QTask * > &tasks)
void SetDoFWeight(int dof, double weight)
void SubTask(IK_QJacobian &jacobian)
double AngleUpdateNorm() const
void ArmMatrices(int dof, int task_size)
const Vector3d GlobalStart() const
const Affine3d & GlobalTransform() const
const Vector3d GlobalEnd() const
virtual void Lock(int, IK_QJacobian &, Vector3d &)
virtual bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *)=0
IK_QSegment * Child() const
IK_QSegment * Sibling() const
bool Locked(int dof) const
void UpdateTransform(const Affine3d &global)
void PrependBasis(const Matrix3d &mat)
void SetDoFId(int dof_id)
void SetWeight(double weight)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
struct blender::compositor::@172::@174 task
ccl_device_inline int clamp(int a, int mn, int mx)
ccl_device_inline float2 normalize(const float2 &a)
ccl_device_inline float2 fabs(const float2 &a)