constrain method

  1. @override
void constrain(
  1. ActorNode node
)
override

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);
    }
  }
}