상속: UnityEngine.Point
		/*
		 * Draws the scene view helpers for IKSolverHeuristic
		 * */
		public static void AddScene(IKSolverHeuristic solver, Color color, bool modifiable) {
			// Protect from null reference errors
			if (Application.isPlaying && !solver.initiated) return;
			if (!Application.isPlaying && !solver.IsValid()) return;

			Handles.color = color;
			GUI.color = color;
			
			// Display the bones
			for (int i = 0; i < solver.bones.Length; i++) {
				IKSolver.Bone bone = solver.bones[i];

				if (i < solver.bones.Length - 1) Handles.DrawLine(bone.transform.position, solver.bones[i + 1].transform.position);
				Inspector.SphereCap(0, solver.bones[i].transform.position, Quaternion.identity, GetHandleSize(solver.bones[i].transform.position));
			}
			
			// Selecting joint and manipulating IKPosition
			if (Application.isPlaying && solver.IKPositionWeight > 0) {
				if (modifiable) {
					Inspector.CubeCap(0, solver.IKPosition, solver.GetRoot().rotation, GetHandleSize(solver.IKPosition));
						
					// Manipulating position
					if (solver.target == null) solver.IKPosition = Handles.PositionHandle(solver.IKPosition, Quaternion.identity);
				}
				
				// Draw a transparent line from last bone to IKPosition
				Handles.color = new Color(color.r, color.g, color.b, color.a * solver.IKPositionWeight);
				Handles.DrawLine(solver.bones[solver.bones.Length - 1].transform.position, solver.IKPosition);
			}
			
			Handles.color = Color.white;
			GUI.color = Color.white;
		}
예제 #2
0
        /*
         * Rotating bone to get transform aim closer to target
         * */
        private void RotateToTarget(Vector3 targetPosition, IKSolver.Bone bone, float weight)
        {
            // Swing
            if (weight >= 0f)
            {
                Quaternion rotationOffset = Quaternion.FromToRotation(transformAxis, targetPosition - transform.position);
                bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, rotationOffset, weight) * bone.transform.rotation;
            }

            // Pole
            if (poleWeight > 0f)
            {
                Vector3 poleDirection = polePosition - transform.position;

                // Ortho-normalize to transform axis to make this a twisting only operation
                Vector3 poleDirOrtho = poleDirection;
                Vector3 normal       = transformAxis;
                Vector3.OrthoNormalize(ref normal, ref poleDirOrtho);

                Quaternion toPole = Quaternion.FromToRotation(transformPoleAxis, poleDirOrtho);
                bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, toPole, weight * poleWeight) * bone.transform.rotation;
            }

            if (useRotationLimits && bone.rotationLimit != null)
            {
                bone.rotationLimit.Apply();
            }
        }
예제 #3
0
        /// <summary>
        /// Solve the bone chain virtually using solverPositions only. SolverRotations will not be changed.
        /// </summary>
        public static void SolveVirtualPositions(IKSolver.Bone bone1, IKSolver.Bone bone2, IKSolver.Bone bone3, Vector3 targetPosition, Vector3 bendNormal, float weight)
        {
            // Direction of the limb in solver
            targetPosition = Vector3.Lerp(bone3.solverPosition, targetPosition, weight);

            Vector3 dir = targetPosition - bone1.solverPosition;

            // Distance between the first and the last node solver positions
            float sqrMag = dir.sqrMagnitude;

            if (sqrMag == 0f)
            {
                return;
            }
            float length = Mathf.Sqrt(sqrMag);

            float sqrMag1 = (bone2.solverPosition - bone1.solverPosition).sqrMagnitude;
            float sqrMag2 = (bone3.solverPosition - bone2.solverPosition).sqrMagnitude;

            // Get the general world space bending direction
            Vector3 bendDir = Vector3.Cross(dir, bendNormal);

            // Get the direction to the trigonometrically solved position of the second node
            Vector3 toBendPoint = GetDirectionToBendPoint(dir, length, bendDir, sqrMag1, sqrMag2);

            //bone2.solverPosition = bone1.solverPosition + toBendPoint;
            bone2.solverPosition = bone1.solverPosition + toBendPoint.normalized * Mathf.Sqrt(sqrMag1);
            bone3.solverPosition = sqrMag < sqrMag1 + sqrMag2? targetPosition: bone2.solverPosition + (targetPosition - bone2.solverPosition).normalized * Mathf.Sqrt(sqrMag2);
        }
예제 #4
0
        /// <summary>
        /// Draws the scene view helpers for IKSolverAim
        /// </summary>
        public static void AddScene(IKSolverAim solver, Color color, bool modifiable)
        {
            // Protect from null reference errors
            if (!solver.IsValid(false))
            {
                return;
            }
            if (solver.transform == null)
            {
                return;
            }
            if (Application.isPlaying && !solver.initiated)
            {
                return;
            }

            Handles.color = color;
            GUI.color     = color;

            // Display the bones
            for (int i = 0; i < solver.bones.Length; i++)
            {
                IKSolver.Bone bone = solver.bones[i];

                if (i < solver.bones.Length - 1)
                {
                    Handles.DrawLine(bone.transform.position, solver.bones[i + 1].transform.position);
                }
                Handles.SphereCap(0, solver.bones[i].transform.position, Quaternion.identity, jointSize);
            }

            if (solver.axis != Vector3.zero)
            {
                Handles.ConeCap(0, solver.transform.position, Quaternion.LookRotation(solver.transform.rotation * solver.axis), jointSize * 2f);
            }

            // Selecting joint and manipulating IKPosition
            if (Application.isPlaying && solver.IKPositionWeight > 0)
            {
                if (modifiable)
                {
                    Handles.SphereCap(0, solver.IKPosition, Quaternion.identity, selectedSize);

                    // Manipulating position
                    solver.IKPosition = Handles.PositionHandle(solver.IKPosition, Quaternion.identity);
                }

                // Draw a transparent line from transform to IKPosition
                Handles.color = new Color(color.r, color.g, color.b, color.a * solver.IKPositionWeight);
                Handles.DrawLine(solver.bones[solver.bones.Length - 1].transform.position, solver.transform.position);
                Handles.DrawLine(solver.transform.position, solver.IKPosition);
            }

            Handles.color = Color.white;
            GUI.color     = Color.white;
        }
예제 #5
0
		/// <summary>
		/// Rebuild the bone hierarcy and reinitiate the solver.
		/// </summary>
		/// <returns>
		/// Returns true if the new chain is valid.
		/// </returns>
		public bool SetChain(Transform[] hierarchy, Transform root) {
			if (bones == null || bones.Length != hierarchy.Length) bones = new Bone[hierarchy.Length];
			for (int i = 0; i < hierarchy.Length; i++) {
				if (bones[i] == null) bones[i] = new IKSolver.Bone();
				bones[i].transform = hierarchy[i];
			}
			
			Initiate(root);
			return initiated;
		}
예제 #6
0
        /*
         * Rotating bone to get transform aim closer to target
         * */
        private void RotateToTarget(Vector3 targetPosition, IKSolver.Bone bone, float weight)
        {
            Quaternion rotationOffset = Quaternion.FromToRotation(transformAxis, targetPosition - transform.position);

            bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, rotationOffset, weight) * bone.transform.rotation;

            if (useRotationLimits && bone.rotationLimit != null)
            {
                bone.rotationLimit.Apply();
            }
        }
예제 #7
0
        /*
         * Rotating bone to get transform aim closer to target
         * */
        private void RotateToTarget(Vector3 targetPosition, IKSolver.Bone bone, float weight)
        {
            // Swing
            if (XY)
            {
                if (weight >= 0f)
                {
                    Vector3 dir       = transformAxis;
                    Vector3 targetDir = targetPosition - transform.position;

                    float angleDir    = Mathf.Atan2(dir.x, dir.y) * Mathf.Rad2Deg;
                    float angleTarget = Mathf.Atan2(targetDir.x, targetDir.y) * Mathf.Rad2Deg;

                    bone.transform.rotation = Quaternion.AngleAxis(Mathf.DeltaAngle(angleDir, angleTarget), Vector3.back) * bone.transform.rotation;
                }
            }
            else
            {
                if (weight >= 0f)
                {
                    Quaternion rotationOffset = Quaternion.FromToRotation(transformAxis, targetPosition - transform.position);

                    if (weight >= 1f)
                    {
                        bone.transform.rotation = rotationOffset * bone.transform.rotation;
                    }
                    else
                    {
                        bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, rotationOffset, weight) * bone.transform.rotation;
                    }
                }

                // Pole
                if (poleWeight > 0f)
                {
                    Vector3 poleDirection = polePosition - transform.position;

                    // Ortho-normalize to transform axis to make this a twisting only operation
                    Vector3 poleDirOrtho = poleDirection;
                    Vector3 normal       = transformAxis;
                    Vector3.OrthoNormalize(ref normal, ref poleDirOrtho);

                    Quaternion toPole = Quaternion.FromToRotation(transformPoleAxis, poleDirOrtho);
                    bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, toPole, weight * poleWeight) * bone.transform.rotation;
                }
            }

            if (useRotationLimits && bone.rotationLimit != null)
            {
                bone.rotationLimit.Apply();
            }
        }
예제 #8
0
        /// <summary>
        /// Rebuild the bone hierarcy and reinitiate the solver.
        /// </summary>
        /// <returns>
        /// Returns true if the new chain is valid.
        /// </returns>
        public bool SetChain(Transform[] hierarchy, Transform root)
        {
            if (bones == null || bones.Length != hierarchy.Length)
            {
                bones = new Bone[hierarchy.Length];
            }
            for (int i = 0; i < hierarchy.Length; i++)
            {
                if (bones[i] == null)
                {
                    bones[i] = new IKSolver.Bone();
                }
                bones[i].transform = hierarchy[i];
            }

            Initiate(root);
            return(initiated);
        }
예제 #9
0
 private void RotateToTarget(Vector3 targetPosition, IKSolver.Bone bone, float weight)
 {
     if (this.XY)
     {
         if (weight >= 0f)
         {
             Vector3 transformAxis = this.transformAxis;
             Vector3 vector        = targetPosition - this.transform.position;
             float   current       = Mathf.Atan2(transformAxis.x, transformAxis.y) * 57.29578f;
             float   target        = Mathf.Atan2(vector.x, vector.y) * 57.29578f;
             bone.transform.rotation = Quaternion.AngleAxis(Mathf.DeltaAngle(current, target), Vector3.back) * bone.transform.rotation;
         }
     }
     else
     {
         if (weight >= 0f)
         {
             Quaternion quaternion = Quaternion.FromToRotation(this.transformAxis, targetPosition - this.transform.position);
             if (weight >= 1f)
             {
                 bone.transform.rotation = quaternion * bone.transform.rotation;
             }
             else
             {
                 bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, quaternion, weight) * bone.transform.rotation;
             }
         }
         if (this.poleWeight > 0f)
         {
             Vector3 vector2        = this.polePosition - this.transform.position;
             Vector3 toDirection    = vector2;
             Vector3 transformAxis2 = this.transformAxis;
             Vector3.OrthoNormalize(ref transformAxis2, ref toDirection);
             Quaternion b = Quaternion.FromToRotation(this.transformPoleAxis, toDirection);
             bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, b, weight * this.poleWeight) * bone.transform.rotation;
         }
     }
     if (this.useRotationLimits && bone.rotationLimit != null)
     {
         bone.rotationLimit.Apply();
     }
 }
예제 #10
0
 private void RotateToTarget(Vector3 targetPosition, IKSolver.Bone bone, float weight)
 {
     if (weight >= 0f)
     {
         Quaternion b = Quaternion.FromToRotation(this.transformAxis, targetPosition - this.transform.position);
         bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, b, weight) * bone.transform.rotation;
     }
     if (this.poleWeight > 0f)
     {
         Vector3 vector        = this.polePosition - this.transform.position;
         Vector3 toDirection   = vector;
         Vector3 transformAxis = this.transformAxis;
         Vector3.OrthoNormalize(ref transformAxis, ref toDirection);
         Quaternion b2 = Quaternion.FromToRotation(this.transformPoleAxis, toDirection);
         bone.transform.rotation = Quaternion.Lerp(Quaternion.identity, b2, weight * this.poleWeight) * bone.transform.rotation;
     }
     if (this.useRotationLimits && bone.rotationLimit != null)
     {
         bone.rotationLimit.Apply();
     }
 }
예제 #11
0
        public override bool IsValid(bool log)
        {
            if (this.bones.Length == 0)
            {
                if (log)
                {
                    base.LogWarning("IK chain has no bones. Can not initiate solver.");
                }
                return(false);
            }
            if (this.bones.Length < this.minBones)
            {
                if (log)
                {
                    base.LogWarning("IK chain has less than " + this.minBones + " bones. Can not initiate solver.");
                }
                return(false);
            }
            IKSolver.Bone[] array = this.bones;
            for (int i = 0; i < array.Length; i++)
            {
                IKSolver.Bone bone = array[i];
                if (bone.transform == null)
                {
                    if (log)
                    {
                        base.LogWarning("Bone transform is null in IK chain. Can not initiate solver.");
                    }
                    return(false);
                }
            }
            if (!this.allowCommonParent && !IKSolver.HierarchyIsValid(this.bones))
            {
                if (log)
                {
                    base.LogWarning("IK requires for it's bones to be parented to each other. Invalid bone hierarchy detected.");
                }
                return(false);
            }
            Transform transform = IKSolver.ContainsDuplicateBone(this.bones);

            if (transform != null)
            {
                if (log)
                {
                    base.LogWarning(transform.name + " is represented multiple times in a single IK chain. Can nott initiate solver.");
                }
                return(false);
            }
            if (!this.boneLengthCanBeZero)
            {
                for (int j = 0; j < this.bones.Length - 1; j++)
                {
                    float magnitude = (this.bones[j].transform.position - this.bones[j + 1].transform.position).magnitude;
                    if (magnitude == 0f)
                    {
                        if (log)
                        {
                            base.LogWarning("Bone " + j + " length is zero. Can nott initiate solver.");
                        }
                        return(false);
                    }
                }
            }
            return(true);
        }