// Move and rotate the pelvis private void TranslatePelvis(Leg[] legs, Vector3 deltaPosition, Quaternion deltaRotation, float w) { // Rotation Vector3 p = head.solverPosition; deltaRotation = QuaTools.ClampRotation(deltaRotation, chestClampWeight, 2); Quaternion f = w >= 1f? pelvisRotationOffset: Quaternion.Slerp(Quaternion.identity, pelvisRotationOffset, w); VirtualBone.RotateAroundPoint(bones, 0, pelvis.solverPosition, f * Quaternion.Slerp(Quaternion.identity, deltaRotation, w * bodyRotStiffness)); deltaPosition -= head.solverPosition - p; // Position // Move the body back when head is moving down Vector3 m = anchorRotation * Vector3.forward; m.y = 0f; float backOffset = deltaPosition.y * 0.35f * headHeight; deltaPosition += m * backOffset; /* * if (backOffset < 0f) { * foreach (Leg leg in legs) leg.heelPositionOffset += Vector3.up * backOffset * backOffset; // TODO Ignoring root rotation * } */ MovePosition(LimitPelvisPosition(legs, pelvis.solverPosition + deltaPosition * w * bodyPosStiffness, false)); }
// Bending the spine to the head effector private void Bend(VirtualBone[] bones, int firstIndex, int lastIndex, Quaternion targetRotation, float clampWeight, bool uniformWeight, float w) { if (w <= 0f) { return; } if (bones.Length == 0) { return; } int bonesCount = (lastIndex + 1) - firstIndex; if (bonesCount < 1) { return; } Quaternion r = QuaTools.FromToRotation(bones[lastIndex].solverRotation, targetRotation); r = QuaTools.ClampRotation(r, clampWeight, 2); float step = uniformWeight? 1f / bonesCount: 0f; for (int i = firstIndex; i < lastIndex + 1; i++) { if (!uniformWeight) { step = Mathf.Clamp(((i - firstIndex) + 1) / bonesCount, 0, 1f); } VirtualBone.RotateAroundPoint(bones, i, bones[i].solverPosition, Quaternion.Slerp(Quaternion.identity, r, step * w)); } }
// Called by the FBBIK each time it is finished updating private void OnPostUpdate() { if (!enabled) { return; } if (!ik.enabled) { return; } if (!gameObject.activeInHierarchy) { return; } // Stretching the spine and neck PostStretching(); // Rotate the head bone Quaternion headRotation = QuaTools.FromToRotation(ik.references.head.rotation, transform.rotation); headRotation = QuaTools.ClampRotation(headRotation, headClampWeight, 2); ik.references.head.rotation = Quaternion.Lerp(Quaternion.identity, headRotation, rotationWeight * ik.solver.IKPositionWeight) * ik.references.head.rotation; }
// Bending the spine to the head effector private void SpineBend() { float w = bendWeight * ik.solver.IKPositionWeight; if (w <= 0f) { return; } if (bendBones.Length == 0) { return; } Quaternion rotation = transform.rotation * Quaternion.Inverse(ik.references.root.rotation * headRotationRelativeToRoot); rotation = QuaTools.ClampRotation(rotation, bodyClampWeight, 2); float step = 1f / bendBones.Length; for (int i = 0; i < bendBones.Length; i++) { if (bendBones[i].transform != null) { bendBones[i].transform.rotation = Quaternion.Lerp(Quaternion.identity, rotation, step * bendBones[i].weight * w) * bendBones[i].transform.rotation; } } }
// Move and rotate the pelvis private void TranslatePelvis(Leg[] legs, Vector3 deltaPosition, Quaternion deltaRotation, float scale) { // Rotation Vector3 p = head.solverPosition; deltaRotation = QuaTools.ClampRotation(deltaRotation, chestClampWeight, 2); Quaternion r = Quaternion.Slerp(Quaternion.identity, deltaRotation, bodyRotStiffness * rotationWeight); r = Quaternion.Slerp(r, QuaTools.FromToRotation(pelvis.solverRotation, IKRotationPelvis), pelvisRotationWeight); VirtualBone.RotateAroundPoint(bones, 0, pelvis.solverPosition, pelvisRotationOffset * r); deltaPosition -= head.solverPosition - p; // Position // Move the body back when head is moving down Vector3 m = rootRotation * Vector3.forward; float deltaY = V3Tools.ExtractVertical(deltaPosition, rootRotation * Vector3.up, 1f).magnitude; if (scale > 0f) { deltaY /= scale; } float backOffset = deltaY * -moveBodyBackWhenCrouching * headHeight; deltaPosition += m * backOffset; MovePosition(LimitPelvisPosition(legs, pelvis.solverPosition + deltaPosition * bodyPosStiffness * positionWeight, false)); }
private void SpineBend() { float num = this.bendWeight * this.ik.solver.IKPositionWeight; if (num <= 0f) { return; } if (this.bendBones.Length == 0) { return; } Quaternion quaternion = base.transform.rotation * Quaternion.Inverse(this.ik.references.root.rotation * this.headRotationRelativeToRoot); quaternion = QuaTools.ClampRotation(quaternion, this.bodyClampWeight, 2); float num2 = 1f / (float)this.bendBones.Length; for (int i = 0; i < this.bendBones.Length; i++) { if (this.bendBones[i].transform != null) { this.bendBones[i].transform.rotation = Quaternion.Lerp(Quaternion.identity, quaternion, num2 * this.bendBones[i].weight * num) * this.bendBones[i].transform.rotation; } } }
private void OnPostUpdate() { if (!base.enabled) { return; } if (!this.ik.enabled) { return; } if (!base.gameObject.activeInHierarchy) { return; } this.PostStretching(); Quaternion quaternion = QuaTools.FromToRotation(this.ik.references.head.rotation, base.transform.rotation); quaternion = QuaTools.ClampRotation(quaternion, this.headClampWeight, 2); this.ik.references.head.rotation = Quaternion.Lerp(Quaternion.identity, quaternion, this.rotationWeight * this.ik.solver.IKPositionWeight) * this.ik.references.head.rotation; }