private void Gizmos_DrawArrowGuide() { if (BaseTransform == null) { return; } if (LeadBone == null) { return; } if (_editor_arrowsAlpha > 0f) { float d = Vector3.Distance(LeadBone.position, BaseTransform.position); Vector3 arrowStart = Vector3.Lerp(BaseTransform.position, LeadBone.position, 0.7f); Handles.color = new Color(0.05f, 0.225f, 1f, 0.9f * _editor_arrowsAlpha); FGUI_Handles.DrawArrow(BaseTransform.TransformDirection(ModelForwardAxis) * d * .22f + arrowStart, Quaternion.LookRotation(BaseTransform.TransformDirection(ModelForwardAxis), BaseTransform.TransformDirection(ModelUpAxis)), d * 0.2f); Handles.color = new Color(0.05f, 0.8f, 0.05f, 0.75f * _editor_arrowsAlpha); arrowStart = LeadBone.position + BaseTransform.TransformDirection(ModelUpAxis) * d * .285f; FGUI_Handles.DrawArrow(arrowStart, Quaternion.LookRotation(BaseTransform.TransformDirection(ModelUpAxis), BaseTransform.TransformDirection(ModelForwardAxis)), d * 0.15f, 4f, 0.5f); } if (_editor_arrowsAlpha > -0.1f) { _editor_arrowsAlpha -= 0.0125f; } }
/// <summary> /// Main head look rotation calculations logics execution /// </summary> private void CalculateLookAnimation() { // Begin check for stop lokoing _stopLooking = false; // Stopping looking when object to follow is null if (FollowMode != EFFollowMode.FollowJustPosition) { if (ObjectToFollow == null) { if (MomentLookTransform == null) { _stopLooking = true; } } } Vector3 lookRotation; LookPositionUpdate(); LookWhenAboveGoBackCalculations(); // When stopping look, we don't want head to goo too fast onto forward look pose if (_stopLooking) { finalLookPosition = transform.TransformPoint(lookFreezeFocusPoint); } else { if (!BirdMode) { finalLookPosition = smoothLookPosition; } else { finalLookPosition = BirdTargetPosition; } } if (FixingPreset != EFAxisFixOrder.Parental) { #region Calculating target rotation and angles // If our target is out of max distance let's look at default direction if (LookState == EFHeadLookState.OutOfMaxDistance) { targetLookAngles = Vector3.MoveTowards(targetLookAngles, Vector3.zero, 1f + RotationSpeed); } else { // Direction towards target in different spaces Vector3 worldDirectionAndTargetAngles = (finalLookPosition - GetLookStartMeasurePosition()).normalized; // Supporting different axis orientation using matrix if (usingAxisCorrection) { worldDirectionAndTargetAngles = axisCorrectionMatrix.inverse.MultiplyVector(worldDirectionAndTargetAngles).normalized; worldDirectionAndTargetAngles = WrapVector(Quaternion.LookRotation(worldDirectionAndTargetAngles, axisCorrectionMatrix.MultiplyVector(ModelUpAxis).normalized).eulerAngles); } else // Easier calculations when using standard z - forward - y up { worldDirectionAndTargetAngles = BaseTransform.InverseTransformDirection(worldDirectionAndTargetAngles); worldDirectionAndTargetAngles = WrapVector(Quaternion.LookRotation(worldDirectionAndTargetAngles, BaseTransform.TransformDirection(ModelUpAxis)).eulerAngles); } targetLookAngles = worldDirectionAndTargetAngles; } Vector2 angles = targetLookAngles; angles = LimitAnglesCalculations(angles); AnimateAnglesTowards(angles); #endregion // Character rotation offset if (usingAxisCorrection) { Quaternion fromto = Quaternion.FromToRotation(Vector3.right, Vector3.Cross(Vector3.up, ModelForwardAxis)); fromto = Quaternion.Euler(finalLookAngles) * fromto * BaseTransform.rotation; lookRotation = fromto.eulerAngles; } else { lookRotation = finalLookAngles + BaseTransform.eulerAngles; } // Additional operations lookRotation += RotationOffset; lookRotation = ConvertFlippedAxes(lookRotation); } else // Universal correction method { lookRotation = LookRotationParental((finalLookPosition - GetLookStartMeasurePosition()).normalized).eulerAngles; lookRotation += RotationOffset; } if (!_stopLooking) { lookFreezeFocusPoint = BaseTransform.InverseTransformPoint(finalLookPosition); } targetLookRotation = Quaternion.Euler(lookRotation); SetTargetBonesRotations(); }
/// <summary> /// Correction matrix for axis correction calculations /// </summary> private void UpdateCorrectionMatrix() { // Supporting different axis orientation using matrix if (ModelUpAxis != Vector3.up || ModelForwardAxis != Vector3.forward) { usingAxisCorrection = true; axisCorrectionMatrix = Matrix4x4.TRS(BaseTransform.position, Quaternion.LookRotation(BaseTransform.TransformDirection(ModelForwardAxis), BaseTransform.TransformDirection(ModelUpAxis)), BaseTransform.lossyScale); } else // Easier calculations when using standard z - forward - y up { usingAxisCorrection = false; } }
/// <summary> /// Getting position in front of head bone /// </summary> public Vector3 GetForwardPosition() { return(LeadBone.position + BaseTransform.TransformDirection(ModelForwardAxis)); }
private void Gizmos_DrawBones() { if (LeadBone == null) { return; } Color c = Handles.color; Color boneColor = new Color(0.075f, .85f, 0.3f, gizmosAlpha * 0.7f); Handles.color = boneColor; Vector3 f = BaseTransform.TransformDirection(ModelForwardAxis); if (LeadBone.childCount > 0) { FGUI_Handles.DrawBoneHandle(LeadBone.position, LeadBone.position + BaseTransform.TransformDirection(ModelUpAxis) * Vector3.Distance(LeadBone.position, LeadBone.parent.position) / 2f, f); } if (LookBones.Count > 0) { // Drawing back-bones for (int i = 1; i < LookBones.Count; i++) { if (LookBones[i].Transform != null) { if (LookBones[i] == null) { continue; } FGUI_Handles.DrawBoneHandle(LookBones[i].Transform.position, LookBones[i - 1].Transform.position, f); } } if (LookBones.Count > 1) { FGUI_Handles.DrawBoneHandle(LookBones[1].Transform.position, LeadBone.position, f); } } Handles.SphereHandleCap(0, LeadBone.position, Quaternion.identity, _gizmosDist * 0.025f, EventType.Repaint); for (int i = 0; i < LeadBone.childCount; i++) { Handles.color = new Color(0.8f, .8f, 0.8f, gizmosAlpha * 0.25f); Handles.DrawDottedLine(LeadBone.position, LeadBone.GetChild(i).position, 2.5f); Handles.color = new Color(0.8f, .8f, 0.8f, gizmosAlpha * 0.1f); Handles.SphereHandleCap(0, LeadBone.GetChild(i).position, Quaternion.identity, _gizmosDist * 0.01f, EventType.Repaint); } if (LookBones.Count > 1) { if (LookBones[LookBones.Count - 1].Transform.parent) { Handles.color = new Color(0.8f, .8f, 0.8f, gizmosAlpha * 0.25f); Handles.DrawDottedLine(LookBones[LookBones.Count - 1].Transform.position, LookBones[LookBones.Count - 1].Transform.parent.position, 3f); Handles.color = new Color(0.8f, .8f, 0.8f, gizmosAlpha * 0.1f); Handles.SphereHandleCap(0, LookBones[LookBones.Count - 1].Transform.parent.position, Quaternion.identity, _gizmosDist * 0.01f, EventType.Repaint); } } Handles.color = c; }
//Vector3 firstBoneOff = Vector3.zero; public void Init() { if (SpineBones.Count == 0) { if (SpineTransforms.Count > 2) { CreateSpineChain(SpineTransforms[0], SpineTransforms[SpineTransforms.Count - 1]); Debug.Log("[SPINE ANIMATOR] Auto Bone Conversion from old version of Spine Animator! Please select your objects with Spine Animator to pre-convert it instead of automatically doing it when game Starts! (" + name + ")"); } else { Debug.Log("[SPINE ANIMATOR] could not initialize Spine Animator inside '" + name + "' because there are no bones to animate!"); return; } } if (initialized) { Debug.Log("[Spine Animator] " + name + " is already initialized!"); return; } if (BaseTransform == null) { BaseTransform = FindBaseTransform(); } // Checking bones for zero-distance ones for (int i = 0; i < SpineBones.Count; i++) { Vector3 childPos; if (i == SpineBones.Count - 1) { childPos = SpineBones[i - 1].transform.position + (SpineBones[i - 1].transform.position - SpineBones[i].transform.position); } else { childPos = SpineBones[i + 1].transform.position; } float dist = Vector3.Distance(SpineBones[i].transform.position, childPos); if (dist < 0.01f) { float refDistance = (SpineBones[SpineBones.Count - 1].transform.position - SpineBones[SpineBones.Count - 2].transform.parent.position).magnitude; Vector3 forw = SpineBones[i].transform.position - BaseTransform.position; Vector3 loc = BaseTransform.InverseTransformDirection(forw); loc.y = 0f; loc.Normalize(); SpineBones[i + 1].DefaultForward = loc; // firstBoneOff SpineBones[i + 1].transform.position = SpineBones[i + 1].transform.position + BaseTransform.TransformDirection(loc) * refDistance * -0.125f; } } referenceDistance = 0f; // Preparing bones for (int i = 0; i < SpineBones.Count; i++) { SpineBones[i].PrepareBone(BaseTransform, SpineBones, i); referenceDistance += SpineBones[i].BoneLength; } referenceDistance /= (float)(SpineBones.Count); frontHead = new HeadBone(SpineBones[0].transform); frontHead.PrepareBone(BaseTransform, SpineBones, 0); backHead = new HeadBone(SpineBones[SpineBones.Count - 1].transform); backHead.PrepareBone(BaseTransform, SpineBones, SpineBones.Count - 1); // Collision calculations helper list CollidersDataToCheck = new List <FImp_ColliderData_Base>(); // Straightening spine pose to desired positions and rotations on init chainReverseFlag = !LastBoneLeading; UpdateChainIndexHelperVariables(); ReposeSpine(); //SpineMotion(); initialized = true; }
/// <summary> /// Computing look angles needed to look at target world position from this character /// </summary> public Vector2 ComputeAnglesTowards(Vector3 worldPosition) { // Direction towards target in different spaces Vector3 worldDirectionAndTargetAngles = (worldPosition - GetLookStartMeasurePosition()).normalized; // Supporting different axis orientation using matrix if (usingAxisCorrection) { worldDirectionAndTargetAngles = axisCorrectionMatrix.inverse.MultiplyVector(worldDirectionAndTargetAngles).normalized; worldDirectionAndTargetAngles = WrapVector(Quaternion.LookRotation(worldDirectionAndTargetAngles, axisCorrectionMatrix.MultiplyVector(ModelUpAxis).normalized).eulerAngles); } else // Easier calculations when using standard z - forward - y up { worldDirectionAndTargetAngles = BaseTransform.InverseTransformDirection(worldDirectionAndTargetAngles); worldDirectionAndTargetAngles = WrapVector(Quaternion.LookRotation(worldDirectionAndTargetAngles, BaseTransform.TransformDirection(ModelUpAxis)).eulerAngles); } return(worldDirectionAndTargetAngles); }
/// <summary> /// Computing variables making Quaternion.Look universal for different skeletonal setups /// </summary> private void ComputeBonesRotationsFixVariables() { if (BaseTransform != null) { Quaternion preRot = BaseTransform.rotation; BaseTransform.rotation = Quaternion.identity; FromAuto = LeadBone.rotation * -Vector3.forward; float angl = Quaternion.Angle(Quaternion.identity, LeadBone.rotation); Quaternion rotateAxis = (LeadBone.rotation * Quaternion.Inverse(Quaternion.FromToRotation(FromAuto, ModelForwardAxis))); OffsetAuto = Quaternion.AngleAxis(angl, rotateAxis.eulerAngles.normalized).eulerAngles; BaseTransform.rotation = preRot; parentalReferenceLookForward = Quaternion.Inverse(LeadBone.parent.rotation) * BaseTransform.rotation * ModelForwardAxis.normalized; parentalReferenceUp = Quaternion.Inverse(LeadBone.parent.rotation) * BaseTransform.rotation * ModelUpAxis.normalized; headForward = Quaternion.FromToRotation(LeadBone.InverseTransformDirection(BaseTransform.TransformDirection(ModelForwardAxis.normalized)), Vector3.forward) * Vector3.forward; } else { Debug.LogWarning("Base Transform isn't defined, so we can't use auto correction!"); } }
private void _Debug_Rays() { if (!DebugRays) { return; } Debug.DrawRay(GetLookStartMeasurePosition() + Vector3.up * 0.01f, Quaternion.Euler(finalLookAngles) * BaseTransform.TransformDirection(ModelForwardAxis), Color.cyan); //Vector3 startLook = GetLookStartMeasurePosition(); //Debug.DrawRay(startLook + Vector3.up * 0.25f, axisCorrectionMatrix.MultiplyVector(Vector3.forward), Color.blue); //Debug.DrawRay(startLook + Vector3.up * 0.25f, axisCorrectionMatrix.MultiplyVector(Vector3.up), Color.green); //Debug.DrawRay(GetLookStartMeasurePosition() + Vector3.up * 0.9f, Quaternion.Euler(finalLookAngles) * Vector3.forward, Color.magenta); //Debug.DrawRay(GetLookStartMeasurePosition() + Vector3.up, Quaternion.Euler(finalLookAngles) * ModelForwardAxis, Color.cyan); //Quaternion fromto = Quaternion.FromToRotation(Vector3.forward, ModelForwardAxis) * Quaternion.FromToRotation(Vector3.up, ModelUpAxis); //Quaternion rot = Quaternion.Euler(finalLookAngles) * fromto * BaseTransform.rotation; //Debug.DrawRay(GetLookStartMeasurePosition() + Vector3.up * 1.1f, rot * Vector3.forward, Color.yellow); //fromto = Quaternion.FromToRotation(Vector3.right, Vector3.Cross(Vector3.up, ModelForwardAxis)); //rot = fromto * Quaternion.Euler(finalLookAngles) * BaseTransform.rotation; //Debug.DrawRay(GetLookStartMeasurePosition() + Vector3.up * 1.2f, rot * Vector3.forward, Color.red); }