16 m_poleconstraint =
false;
17 m_getpoleangle =
false;
18 m_rootmatrix.setIdentity();
21double IK_QJacobianSolver::ComputeScale()
23 std::vector<IK_QSegment *>::iterator seg;
26 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
27 length += (*seg)->MaxExtension();
38void IK_QJacobianSolver::Scale(
double scale, std::list<IK_QTask *> &tasks)
40 std::list<IK_QTask *>::iterator
task;
41 std::vector<IK_QSegment *>::iterator seg;
43 for (task = tasks.begin();
task != tasks.end();
task++) {
44 (*task)->Scale(scale);
47 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
51 m_rootmatrix.translation() *= scale;
56void IK_QJacobianSolver::AddSegmentList(
IK_QSegment *seg)
58 m_segments.push_back(seg);
61 for (child = seg->
Child(); child; child = child->
Sibling()) {
62 AddSegmentList(child);
72 std::vector<IK_QSegment *>::iterator seg;
75 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
77 num_dof += (*seg)->NumberOfDoF();
86 int secondary_size = 0, secondary = 0;
87 double primary_weight = 0.0, secondary_weight = 0.0;
88 std::list<IK_QTask *>::iterator task;
90 for (task = tasks.begin(); task != tasks.end(); task++) {
94 qtask->
SetId(primary_size);
95 primary_size += qtask->
Size();
96 primary_weight += qtask->
Weight();
99 qtask->
SetId(secondary_size);
100 secondary_size += qtask->
Size();
101 secondary_weight += qtask->
Weight();
106 if (primary_size == 0 ||
FuzzyZero(primary_weight)) {
110 m_secondary_enabled = (secondary > 0);
113 double primary_rescale = 1.0 / primary_weight;
114 double secondary_rescale;
116 secondary_rescale = 0.0;
119 secondary_rescale = 1.0 / secondary_weight;
122 for (task = tasks.begin(); task != tasks.end(); task++) {
136 m_jacobian_sub.
ArmMatrices(num_dof, secondary_size);
142 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
143 for (i = 0; i < (*seg)->NumberOfDoF(); i++) {
144 m_jacobian.
SetDoFWeight((*seg)->DoFId() + i, (*seg)->Weight(i));
152 IK_QSegment *tip, Vector3d &goal, Vector3d &polegoal,
float poleangle,
bool getangle)
154 m_poleconstraint =
true;
157 m_polegoal = polegoal;
158 m_poleangle = (getangle) ? 0.0f : poleangle;
159 m_getpoleangle = getangle;
162void IK_QJacobianSolver::ConstrainPoleVector(
IK_QSegment *root, std::list<IK_QTask *> &tasks)
168 if (!m_poleconstraint) {
173 std::list<IK_QTask *>::iterator
task;
174 int positiontasks = 0;
176 for (task = tasks.begin();
task != tasks.end();
task++) {
177 if ((*task)->PositionTask()) {
182 if (positiontasks >= 2) {
183 m_poleconstraint =
false;
191 const Vector3d endpos = m_poletip->
GlobalEnd();
197 Vector3d dir =
normalize(endpos - rootpos);
198 Vector3d rootx = rootbasis.col(0);
199 Vector3d rootz = rootbasis.col(2);
200 Vector3d up = rootx *
cos(m_poleangle) + rootz *
sin(m_poleangle);
203 Vector3d poledir = (m_getpoleangle) ? dir :
normalize(m_goal - rootpos);
204 Vector3d poleup =
normalize(m_polegoal - rootpos);
206 Matrix3d mat, polemat;
209 mat.row(1) = mat.row(0).cross(dir);
212 polemat.row(0) =
normalize(poledir.cross(poleup));
213 polemat.row(1) = polemat.row(0).cross(poledir);
214 polemat.row(2) = -poledir;
216 if (m_getpoleangle) {
218 m_poleangle =
angle(mat.row(1), polemat.row(1));
220 double dt = rootz.dot(mat.row(1) *
cos(m_poleangle) + mat.row(0) *
sin(m_poleangle));
222 m_poleangle = -m_poleangle;
226 m_getpoleangle =
false;
227 ConstrainPoleVector(root, tasks);
235 trans.linear() = polemat.transpose() * mat;
236 trans.translation() = Vector3d(0, 0, 0);
237 m_rootmatrix = trans * m_rootmatrix;
241bool IK_QJacobianSolver::UpdateAngles(
double &
norm)
244 std::vector<IK_QSegment *>::iterator seg;
246 double minabsdelta = 1e10, absdelta;
247 Vector3d delta, mindelta;
248 bool locked =
false, clamp[3];
254 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
258 if (clamp[i] && !qseg->
Locked(i)) {
259 absdelta =
fabs(delta[i]);
262 qseg->
Lock(i, m_jacobian, delta);
265 else if (absdelta < minabsdelta) {
266 minabsdelta = absdelta;
278 minseg->
Lock(mindof, m_jacobian, mindelta);
281 if (minabsdelta >
norm) {
286 if (locked ==
false) {
288 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
290 (*seg)->UpdateAngleApply();
299 std::list<IK_QTask *> tasks,
301 const int max_iterations)
303 float scale = ComputeScale();
309 ConstrainPoleVector(root, tasks);
314 for (
int iterations = 0; iterations < max_iterations; iterations++) {
318 std::list<IK_QTask *>::iterator task;
321 for (task = tasks.begin(); task != tasks.end(); task++) {
322 if ((*task)->Primary()) {
323 (*task)->ComputeJacobian(m_jacobian);
326 (*task)->ComputeJacobian(m_jacobian_sub);
336 if (m_secondary_enabled) {
337 m_jacobian.
SubTask(m_jacobian_sub);
341 fprintf(stderr,
"IK Exception\n");
346 }
while (UpdateAngles(
norm));
349 std::vector<IK_QSegment *>::iterator seg;
350 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
356 if (maxnorm >
norm) {
367 if (m_poleconstraint) {
371 Scale(1.0f / scale, tasks);
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
static const double IK_EPSILON
static bool FuzzyZero(double x)
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
SIMD_FORCE_INLINE btScalar length() const
Return the length of the 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
bool Locked(int dof) const
void UpdateTransform(const Affine3d &global)
void PrependBasis(const Matrix3d &mat)
void SetDoFId(int dof_id)
IK_QSegment * Child() const
IK_QSegment * Sibling() const
void SetWeight(double weight)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float3 cos(float3 v)
struct blender::compositor::@172::@174 task
T sin(const AngleRadianBase< T > &a)