Edited at

# 任意の回転から振り(Swing)と捻り(Twist)を取り出す

DecomposeSwingTwist.cs

```//------------------------------------------------------------
/// <summary>
/// QuaternionからTwistとSwingを取り出す
/// </summary>
/// <param name="q">与える回転(Local)</param>
/// <param name="twistAxis">捻りを取り出すための基準軸(Local)</param>
/// <param name="swing">分解したSwing回転(Local)</param>
/// <param name="twist">分解したTwist回転(Local)</param>
/// <seealso cref="http://www.euclideanspace.com/maths/geometry/rotations/for/decomposition/" />
/// <seealso cref="http://allenchou.net/2018/05/game-math-swing-twist-interpolation-sterp/" />
//------------------------------------------------------------
public static void DecomposeSwingTwist(Quaternion q, Vector3
twistAxis, out Quaternion swing, out Quaternion twist) {
// (rotation axis) * cos(angle / 2)
Vector3 r = new Vector3(q.x, q.y, q.z);

// singularity: rotation by 180 degree
if (r.sqrMagnitude < Mathf.Epsilon) {
Vector3 rotatedTwistAxis = q * twistAxis;
Vector3 swingAxis = Vector3.Cross(twistAxis, rotatedTwistAxis);

if (swingAxis.sqrMagnitude > Mathf.Epsilon) {
float swingAngle = Vector3.Angle(twistAxis,
rotatedTwistAxis);
swing = Quaternion.AngleAxis(swingAngle, swingAxis);
} else {
// more singularity: rotation axis parallel to twist axis
swing = Quaternion.identity;    // no swing
}

// always twist 180 degree on singularity
twist = Quaternion.AngleAxis(180.0f, twistAxis);
} else {
// formula & proof:
// http://www.euclideanspace.com/maths/geometry/rotations/for/decomposition/
Vector3 p = Vector3.Project(r, twistAxis);
twist = new Quaternion(p.x, p.y, p.z, q.w);
twist = Quaternion.Normalize(twist);
swing = q * Quaternion.Inverse(twist);
}
}
```