constrain method
Implementation
@override
void constrain(ActorNode node) {
ActorNode? target = this.target as ActorNode?;
if (target == null) {
return;
}
Vec2D worldTargetTranslation = Vec2D();
target.getWorldTranslation(worldTargetTranslation);
if (_influencedBones!.isEmpty) {
return;
}
// Decompose the chain.
for (final BoneChain item in _fkChain) {
ActorBone bone = item.bone;
Mat2D parentWorld = bone.parent!.worldTransform;
Mat2D.invert(item.parentWorldInverse, parentWorld);
Mat2D.multiply(
bone.transform, item.parentWorldInverse, bone.worldTransform);
Mat2D.decompose(bone.transform, item.transformComponents);
}
int count = _boneData.length;
if (count == 1) {
solve1(_boneData[0], worldTargetTranslation);
} else if (count == 2) {
solve2(_boneData[0], _boneData[1], worldTargetTranslation);
} else {
BoneChain tip = _boneData[count - 1];
for (int i = 0; i < count - 1; i++) {
BoneChain item = _boneData[i];
solve2(item, tip, worldTargetTranslation);
for (int j = item.index + 1; j < _fkChain.length - 1; j++) {
BoneChain fk = _fkChain[j];
Mat2D.invert(fk.parentWorldInverse, fk.bone.parent!.worldTransform);
}
}
}
// At the end, mix the FK angle with the IK angle by strength
if (strength != 1.0) {
for (final BoneChain fk in _fkChain) {
if (!fk.included) {
ActorBone bone = fk.bone;
Mat2D.multiply(
bone.worldTransform, bone.parent!.worldTransform, bone.transform);
continue;
}
double fromAngle = fk.transformComponents.rotation % pi2;
double toAngle = fk.angle % pi2;
double diff = toAngle - fromAngle;
if (diff > pi) {
diff -= pi2;
} else if (diff < -pi) {
diff += pi2;
}
double angle = fromAngle + diff * strength;
constrainRotation(fk, angle);
}
}
}