float CalculateAngle(BendingSegment seg, float angle) { // Handle threshold angle difference, bending multiplier, // and max angle difference here float hAngleThr = Mathf.Max( 0, Mathf.Abs(angle) - seg.thresholdAngleDifference) * Mathf.Sign(angle); angle = Mathf.Max( Mathf.Abs(hAngleThr) * Mathf.Abs(seg.bendingMultiplier), Mathf.Abs(angle) - seg.maxAngleDifference) * Mathf.Sign(angle) * Mathf.Sign(seg.bendingMultiplier); // If we're in restricted mode float maxBendingAngle = seg.maxBendingAngle; if (this.Restricted == true) { maxBendingAngle = seg.restrictedBendingAngle; } // Handle max bending angle here angle = Mathf.Clamp( angle, -maxBendingAngle, maxBendingAngle); return(angle); }
private void Start() { if (this.rootNode == null) { this.rootNode = base.transform; } BendingSegment[] array = this.segments; for (int i = 0; i < array.Length; i++) { BendingSegment bendingSegment = array[i]; Quaternion rotation = bendingSegment.firstTransform.parent.rotation; Quaternion lhs = Quaternion.Inverse(rotation); bendingSegment.referenceLookDir = lhs * this.rootNode.rotation * this.headLookVector.normalized; bendingSegment.referenceUpDir = lhs * this.rootNode.rotation * this.headUpVector.normalized; bendingSegment.angleH = 0f; bendingSegment.angleV = 0f; bendingSegment.dirUp = bendingSegment.referenceUpDir; bendingSegment.chainLength = 1; Transform transform = bendingSegment.lastTransform; while (transform != bendingSegment.firstTransform && transform != transform.root) { bendingSegment.chainLength++; transform = transform.parent; } bendingSegment.origRotations = new Quaternion[bendingSegment.chainLength]; transform = bendingSegment.lastTransform; for (int j = bendingSegment.chainLength - 1; j >= 0; j--) { bendingSegment.origRotations[j] = transform.localRotation; transform = transform.parent; } } }
public void AddSegment(BendingSegment Segment) { if (this.segments == null) { this.segments = new List <BendingSegment>(); } this.segments.Add(Segment); }
public BendingSegment(BendingSegment other) { this.firstTransform = other.firstTransform; this.lastTransform = other.lastTransform; this.bodyPart = other.bodyPart; this.thresholdAngleDifference = other.thresholdAngleDifference; this.bendingMultiplier = other.bendingMultiplier; this.maxAngleDifference = other.maxAngleDifference; this.maxBendingAngle = other.maxBendingAngle; this.responsiveness = other.responsiveness; this.angleH = other.angleH; this.angleV = other.angleV; this.dirUp = other.dirUp; this.referenceLookDir = other.referenceLookDir; this.referenceUpDir = other.referenceUpDir; this.chainLength = other.chainLength; this.origRotations = new Quaternion[other.origRotations.Length]; for (int i = 0; i < this.origRotations.Length; ++i) { this.origRotations[i] = other.origRotations[i]; } }
public void AutoPopulateSegments() { segments = new BendingSegment[5]; nonAffectedJoints = new Impulsion.NonAffectedJoints[2]; for (int i = 0; i < 5; i++) segments[i] = new BendingSegment(); for (int i = 0; i < 2; i++) nonAffectedJoints[i] = new Impulsion.NonAffectedJoints(); nonAffectedJoints[0].joint = _abf.findBone("LeftArm"); nonAffectedJoints[0].effect = 0.4f; nonAffectedJoints[1].joint = _abf.findBone("RightArm"); nonAffectedJoints[1].effect = 0.4f; segments[0].firstTransform = _abf.findBone("Spine"); segments[0].lastTransform = _abf.findBone("Spine1"); segments[0].thresholdAngleDifference = 45f; segments[0].bendingMultiplier = 0.6f; segments[0].maxAngleDifference = 30f; segments[0].maxBendingAngle = 10f; segments[0].responsiveness = 0.5f; segments[0].leanEffect = 0.5f; segments[1].firstTransform = segments[0].lastTransform; segments[1].lastTransform = _abf.findBone("Spine2"); segments[1].thresholdAngleDifference = 30f; segments[1].bendingMultiplier = 0.6f; segments[1].maxAngleDifference = 90f; segments[1].maxBendingAngle = 20f; segments[1].responsiveness = 0.5f; segments[1].leanEffect = 0.5f; segments[2].firstTransform = _abf.findBone("Neck"); segments[2].lastTransform = _abf.findBone("Head"); segments[2].isHead = true; segments[2].thresholdAngleDifference = 15f; segments[2].bendingMultiplier = 0.7f; segments[2].maxAngleDifference = 75f; segments[2].maxBendingAngle = 65f; segments[2].responsiveness = 2f; segments[2].leanEffect = 0f; segments[3].firstTransform = _abf.findBone("LeftEye"); segments[3].lastTransform = segments[3].firstTransform; segments[3].isEye = true; segments[3].thresholdAngleDifference = 0f; segments[3].bendingMultiplier = 1f; segments[3].maxAngleDifference = 0f; segments[3].maxBendingAngle = 15f; segments[3].responsiveness = 20f; segments[3].leanEffect = 0f; segments[4].firstTransform = _abf.findBone("RightEye"); segments[4].lastTransform = segments[4].firstTransform; segments[4].isEye = true; segments[4].thresholdAngleDifference = 0f; segments[4].bendingMultiplier = 1f; segments[4].maxAngleDifference = 0f; segments[4].maxBendingAngle = 15f; segments[4].responsiveness = 20f; segments[4].leanEffect = 0f; }
private void LateUpdate() { if (Time.deltaTime == 0f) { return; } Vector3[] array = new Vector3[this.nonAffectedJoints.Length]; for (int i = 0; i < this.nonAffectedJoints.Length; i++) { IEnumerator enumerator = this.nonAffectedJoints[i].joint.GetEnumerator(); try { if (enumerator.MoveNext()) { Transform transform = (Transform)enumerator.Current; array[i] = transform.position - this.nonAffectedJoints[i].joint.position; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } } BendingSegment[] array2 = this.segments; for (int j = 0; j < array2.Length; j++) { BendingSegment bendingSegment = array2[j]; Transform transform2 = bendingSegment.lastTransform; if (this.overrideAnimation) { for (int k = bendingSegment.chainLength - 1; k >= 0; k--) { transform2.localRotation = bendingSegment.origRotations[k]; transform2 = transform2.parent; } } Quaternion rotation = bendingSegment.firstTransform.parent.rotation; Quaternion rotation2 = Quaternion.Inverse(rotation); Vector3 normalized = (this.target - bendingSegment.lastTransform.position).normalized; Vector3 vector = rotation2 * normalized; float num = HeadLookController.AngleAroundAxis(bendingSegment.referenceLookDir, vector, bendingSegment.referenceUpDir); Vector3 axis = Vector3.Cross(bendingSegment.referenceUpDir, vector); Vector3 dirA = vector - Vector3.Project(vector, bendingSegment.referenceUpDir); float num2 = HeadLookController.AngleAroundAxis(dirA, vector, axis); float f = Mathf.Max(0f, Mathf.Abs(num) - bendingSegment.thresholdAngleDifference) * Mathf.Sign(num); float f2 = Mathf.Max(0f, Mathf.Abs(num2) - bendingSegment.thresholdAngleDifference) * Mathf.Sign(num2); num = Mathf.Max(Mathf.Abs(f) * Mathf.Abs(bendingSegment.bendingMultiplier), Mathf.Abs(num) - bendingSegment.maxAngleDifference) * Mathf.Sign(num) * Mathf.Sign(bendingSegment.bendingMultiplier); num2 = Mathf.Max(Mathf.Abs(f2) * Mathf.Abs(bendingSegment.bendingMultiplier), Mathf.Abs(num2) - bendingSegment.maxAngleDifference) * Mathf.Sign(num2) * Mathf.Sign(bendingSegment.bendingMultiplier); num = Mathf.Clamp(num, -bendingSegment.maxBendingAngle, bendingSegment.maxBendingAngle); num2 = Mathf.Clamp(num2, -bendingSegment.maxBendingAngle, bendingSegment.maxBendingAngle); Vector3 axis2 = Vector3.Cross(bendingSegment.referenceUpDir, bendingSegment.referenceLookDir); bendingSegment.angleH = Mathf.Lerp(bendingSegment.angleH, num, Time.deltaTime * bendingSegment.responsiveness); bendingSegment.angleV = Mathf.Lerp(bendingSegment.angleV, num2, Time.deltaTime * bendingSegment.responsiveness); vector = Quaternion.AngleAxis(bendingSegment.angleH, bendingSegment.referenceUpDir) * Quaternion.AngleAxis(bendingSegment.angleV, axis2) * bendingSegment.referenceLookDir; Vector3 referenceUpDir = bendingSegment.referenceUpDir; Vector3.OrthoNormalize(ref vector, ref referenceUpDir); Vector3 forward = vector; bendingSegment.dirUp = Vector3.Slerp(bendingSegment.dirUp, referenceUpDir, Time.deltaTime * 5f); Vector3.OrthoNormalize(ref forward, ref bendingSegment.dirUp); Quaternion to = rotation * Quaternion.LookRotation(forward, bendingSegment.dirUp) * Quaternion.Inverse(rotation * Quaternion.LookRotation(bendingSegment.referenceLookDir, bendingSegment.referenceUpDir)); Quaternion lhs = Quaternion.Slerp(Quaternion.identity, to, this.effect / (float)bendingSegment.chainLength); transform2 = bendingSegment.lastTransform; for (int l = 0; l < bendingSegment.chainLength; l++) { transform2.rotation = lhs * transform2.rotation; transform2 = transform2.parent; } } for (int m = 0; m < this.nonAffectedJoints.Length; m++) { Vector3 vector2 = Vector3.zero; IEnumerator enumerator2 = this.nonAffectedJoints[m].joint.GetEnumerator(); try { if (enumerator2.MoveNext()) { Transform transform3 = (Transform)enumerator2.Current; vector2 = transform3.position - this.nonAffectedJoints[m].joint.position; } } finally { IDisposable disposable2 = enumerator2 as IDisposable; if (disposable2 != null) { disposable2.Dispose(); } } Vector3 toDirection = Vector3.Slerp(array[m], vector2, this.nonAffectedJoints[m].effect); this.nonAffectedJoints[m].joint.rotation = Quaternion.FromToRotation(vector2, toDirection) * this.nonAffectedJoints[m].joint.rotation; } }
public void OnStart(CBody oBody) { _oBody = oBody; //###MOD: Init segment from code as our component is added at runtime now BendingSegment oSeg = new BendingSegment(); oSeg.firstTransform = _oBody._oBodyBase.FindBone("chest/neck"); //###IMPROVE? Can spine be added (or would interfere with our anim too much?) oSeg.lastTransform = _oBody._oBodyBase.FindBone("chest/neck/head"); oSeg.thresholdAngleDifference = 0; //###??? oSeg.bendingMultiplier = 1.0f; //###IMPROVE!!!: Add 'eyes' and get them to move part of the way oSeg.maxAngleDifference = 90; oSeg.maxBendingAngle = 40; //###IMPROVE: Reduce angle for head up / down and wider for head left/right oSeg.responsiveness = 3.0f; //###TUNE!!! segments[0] = oSeg; if (rootNode == null) rootNode = transform; // Setup segments foreach (BendingSegment segment in segments) { Quaternion parentRot = segment.firstTransform.parent.rotation; Quaternion parentRotInv = Quaternion.Inverse(parentRot); segment.referenceLookDir = parentRotInv * rootNode.rotation * headLookVector.normalized; segment.referenceUpDir = parentRotInv * rootNode.rotation * headUpVector.normalized; segment.angleH = 0; segment.angleV = 0; segment.dirUp = segment.referenceUpDir; segment.chainLength = 1; Transform t = segment.lastTransform; while (t != segment.firstTransform && t != t.root) { segment.chainLength++; t = t.parent; } segment.origRotations = new Quaternion[segment.chainLength]; t = segment.lastTransform; for (int i=segment.chainLength - 1; i >= 0; i--) { segment.origRotations[i] = t.localRotation; t = t.parent; } } }
float CalculateAngle(BendingSegment seg, float angle) { // Handle threshold angle difference, bending multiplier, // and max angle difference here float hAngleThr = Mathf.Max( 0, Mathf.Abs(angle) - seg.thresholdAngleDifference) * Mathf.Sign(angle); angle = Mathf.Max( Mathf.Abs(hAngleThr) * Mathf.Abs(seg.bendingMultiplier), Mathf.Abs(angle) - seg.maxAngleDifference) * Mathf.Sign(angle) * Mathf.Sign(seg.bendingMultiplier); // If we're in restricted mode float maxBendingAngle = seg.maxBendingAngle; if (this.Restricted == true) maxBendingAngle = seg.restrictedBendingAngle; // Handle max bending angle here angle = Mathf.Clamp( angle, -maxBendingAngle, maxBendingAngle); return angle; }