11 public Transform target;
12 public Transform start, joint, end;
13 public Transform poleVector, upVector;
15 public float blendPct = 1.0f;
18 public Transform startXform, jointXform, endXform;
22 const float epsilon = 0.001f;
23 if (blendPct < epsilon)
26 var preUp = upVector ? upVector.up : Vector3.Cross(end.position - start.position, joint.position - start.position).normalized;
28 var targetPosition = target.position;
29 var targetRotation = target.rotation;
31 Vector3 forward, up, result = joint.position;
32 Solve(start.position, targetPosition, poleVector.position,
33 (joint.position - start.position).magnitude,
34 (end.position - joint.position).magnitude,
35 ref result, out forward, out up);
37 if (up == Vector3.zero)
40 var startPosition = start.position;
41 var jointPosition = joint.position;
42 var endPosition = end.position;
44 var startRotationLocal = start.localRotation;
45 var jointRotationLocal = joint.localRotation;
46 var endRotationLocal = end.localRotation;
48 var startParent = start.parent;
49 var jointParent = joint.parent;
50 var endParent = end.parent;
52 var startScale = start.localScale;
53 var jointScale = joint.localScale;
54 var endScale = end.localScale;
56 if (startXform == null)
58 startXform =
new GameObject(
"startXform").transform;
59 startXform.parent = transform;
62 startXform.position = startPosition;
63 startXform.LookAt(joint, preUp);
64 start.parent = startXform;
66 if (jointXform == null)
68 jointXform =
new GameObject(
"jointXform").transform;
69 jointXform.parent = startXform;
72 jointXform.position = jointPosition;
73 jointXform.LookAt(end, preUp);
74 joint.parent = jointXform;
78 endXform =
new GameObject(
"endXform").transform;
79 endXform.parent = jointXform;
82 endXform.position = endPosition;
83 end.parent = endXform;
85 startXform.LookAt(result, up);
86 jointXform.LookAt(targetPosition, up);
87 endXform.rotation = targetRotation;
89 start.parent = startParent;
90 joint.parent = jointParent;
91 end.parent = endParent;
93 end.rotation = targetRotation;
98 start.localRotation = Quaternion.Slerp(startRotationLocal, start.localRotation, blendPct);
99 joint.localRotation = Quaternion.Slerp(jointRotationLocal, joint.localRotation, blendPct);
100 end.localRotation = Quaternion.Slerp(endRotationLocal, end.localRotation, blendPct);
104 start.localScale = startScale;
105 joint.localScale = jointScale;
106 end.localScale = endScale;
109 public static bool Solve(
116 out Vector3 forward, out Vector3 up)
118 var totalDist = jointDist + targetDist;
119 var start2end = end - start;
120 var poleVectorDir = (poleVector - start).normalized;
121 var baseDist = start2end.magnitude;
125 const float epsilon = 0.001f;
126 if (baseDist < epsilon)
129 result += poleVectorDir * jointDist;
131 forward = Vector3.Cross(poleVectorDir, Vector3.up);
132 up = Vector3.Cross(forward, poleVectorDir).normalized;
136 forward = start2end * (1.0f / baseDist);
137 up = Vector3.Cross(forward, poleVectorDir).normalized;
139 if (baseDist + epsilon < totalDist)
142 var p = (totalDist + baseDist) * 0.5f;
143 if (p > jointDist + epsilon && p > targetDist + epsilon)
145 var A = Mathf.Sqrt(p * (p - jointDist) * (p - targetDist) * (p - baseDist));
146 var height = 2.0f * A / baseDist;
148 var dist = Mathf.Sqrt((jointDist * jointDist) - (height * height));
149 var right = Vector3.Cross(up, forward);
151 result += (forward * dist) + (right * height);
157 result += poleVectorDir * jointDist;
163 result += forward * jointDist;