| 11 | } |
| 12 | |
| 13 | void InverseKinematics::SolveTwoBoneIK(Transform& rootTransform, Transform& midJointTransform, Transform& endEffectorTransform, const Vector3& targetPosition, const Vector3& poleVector, bool allowStretching, float maxStretchScale) |
| 14 | { |
| 15 | // Calculate limb segment lengths |
| 16 | Real lowerLimbLength = (endEffectorTransform.Translation - midJointTransform.Translation).Length(); |
| 17 | Real upperLimbLength = (midJointTransform.Translation - rootTransform.Translation).Length(); |
| 18 | Vector3 midJointPos = midJointTransform.Translation; |
| 19 | |
| 20 | // Calculate the direction and length towards the target |
| 21 | Vector3 toTargetVector = targetPosition - rootTransform.Translation; |
| 22 | Real toTargetLength = toTargetVector.Length(); |
| 23 | Real totalLimbLength = lowerLimbLength + upperLimbLength; |
| 24 | |
| 25 | // Normalize the direction vector or set a default direction if too small |
| 26 | Vector3 toTargetDir; |
| 27 | if (toTargetLength < ZeroTolerance) |
| 28 | { |
| 29 | toTargetLength = ZeroTolerance; |
| 30 | toTargetDir = Vector3(1, 0, 0); |
| 31 | } |
| 32 | else |
| 33 | { |
| 34 | toTargetDir = toTargetVector.GetNormalized(); |
| 35 | } |
| 36 | |
| 37 | // Calculate the pole vector direction |
| 38 | Vector3 poleVectorDelta = poleVector - rootTransform.Translation; |
| 39 | const Real poleVectorLengthSqr = poleVectorDelta.LengthSquared(); |
| 40 | |
| 41 | Vector3 jointPlaneNormal, bendDirection; |
| 42 | if (poleVectorLengthSqr < ZeroTolerance * ZeroTolerance) |
| 43 | { |
| 44 | bendDirection = Vector3::Forward; |
| 45 | jointPlaneNormal = Vector3::Up; |
| 46 | } |
| 47 | else |
| 48 | { |
| 49 | jointPlaneNormal = toTargetDir ^ poleVectorDelta; |
| 50 | if (jointPlaneNormal.LengthSquared() < ZeroTolerance * ZeroTolerance) |
| 51 | { |
| 52 | toTargetDir.FindBestAxisVectors(jointPlaneNormal, bendDirection); |
| 53 | } |
| 54 | else |
| 55 | { |
| 56 | jointPlaneNormal.Normalize(); |
| 57 | bendDirection = poleVectorDelta - (poleVectorDelta | toTargetDir) * toTargetDir; |
| 58 | bendDirection.Normalize(); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | // Handle limb stretching if allowed |
| 63 | if (allowStretching) |
| 64 | { |
| 65 | const Real initialStretchRatio = 1.0f; |
| 66 | const Real stretchRange = maxStretchScale - initialStretchRatio; |
| 67 | if (stretchRange > ZeroTolerance && totalLimbLength > ZeroTolerance) |
| 68 | { |
| 69 | const Real reachRatio = toTargetLength / totalLimbLength; |
| 70 | const Real scalingFactor = (maxStretchScale - 1.0f) * Math::Saturate((reachRatio - initialStretchRatio) / stretchRange); |
nothing calls this directly
no test coverage detected