示例#1
0
        /*
         * Gets the starting position of the iteration
         * */
        private Vector3 GetPosition(IKSolverFullBody solver, out Quaternion planeRotationOffset)
        {
            planeRotationOffset = Quaternion.identity;
            if (!isEndEffector)
            {
                return(solver.GetNode(chainIndex, nodeIndex).solverPosition);                            // non end-effectors are always free
            }
            if (maintainRelativePositionWeight <= 0f)
            {
                return(animatedPosition);
            }

            // Maintain relative position
            Vector3 p   = bone.position;
            Vector3 dir = p - planeBone1.position;

            planeRotationOffset = GetPlaneRotation(solver) * Quaternion.Inverse(animatedPlaneRotation);

            p = solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition + planeRotationOffset * dir;

            // Interpolate the rotation offset
            planeRotationOffset = Quaternion.Lerp(Quaternion.identity, planeRotationOffset, maintainRelativePositionWeight);

            return(Vector3.Lerp(animatedPosition, p + solver.GetNode(chainIndex, nodeIndex).offset, maintainRelativePositionWeight));
        }
        /*
         * Positioning and rotating the spine bones to match the solver positions
         * */
        private void MapToSolverPositions(IKSolverFullBody solver)
        {
            // Translating the first bone
            // Note: spine here also includes the pelvis
            spine[0].SetToIKPosition();
            spine[0].RotateToPlane(solver, 1f);

            // Translating all the bones between the first and the last
            for (int i = 1; i < spine.Length - 1; i++)
            {
                spine[i].Swing(spine[i + 1].ikPosition, 1f);

                if (twistWeight > 0)
                {
                    float bWeight = (float)i / ((float)spine.Length - 2);

                    Vector3 s1 = solver.GetNode(leftUpperArm.chainIndex, leftUpperArm.nodeIndex).solverPosition;
                    Vector3 s2 = solver.GetNode(rightUpperArm.chainIndex, rightUpperArm.nodeIndex).solverPosition;
                    spine[i].Twist(s1 - s2, spine[i + 1].ikPosition - spine[i].transform.position, bWeight * twistWeight);
                }
            }

            // Translating the last bone
            spine[spine.Length - 1].SetToIKPosition();
            spine[spine.Length - 1].RotateToPlane(solver, 1f);
        }
示例#3
0
		/*
		 * Clear node offset
		 * */
		public void ResetOffset(IKSolverFullBody solver) {
			solver.GetNode(chainIndex, nodeIndex).offset = Vector3.zero;

			for (int i = 0; i < childChainIndexes.Length; i++) {
				solver.GetNode(childChainIndexes[i], childNodeIndexes[i]).offset = Vector3.zero;
			}
		}
示例#4
0
            private Quaternion GetTargetRotation(IKSolverFullBody solver)
            {
                Vector3 solverPosition  = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition;
                Vector3 solverPosition2 = solver.GetNode(this.plane2ChainIndex, this.plane2NodeIndex).solverPosition;
                Vector3 solverPosition3 = solver.GetNode(this.plane3ChainIndex, this.plane3NodeIndex).solverPosition;

                if (solverPosition == solverPosition3)
                {
                    return(Quaternion.identity);
                }
                return(Quaternion.LookRotation(solverPosition2 - solverPosition, solverPosition3 - solverPosition));
            }
示例#5
0
		/*
		* Rotation of plane nodes in the solver
		* */
		private Quaternion GetPlaneRotation(IKSolverFullBody solver) {
			Vector3 p1 = solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition;
			Vector3 p2 = solver.GetNode(plane2ChainIndex, plane2NodeIndex).solverPosition;
			Vector3 p3 = solver.GetNode(plane3ChainIndex, plane3NodeIndex).solverPosition;

			Vector3 viewingVector = p2 - p1;
			Vector3 upVector = p3 - p1;

			if (viewingVector == Vector3.zero) {
				Warning.Log("Make sure you are not placing 2 or more FBBIK effectors of the same chain to exactly the same position.", bone);
				return Quaternion.identity;
			}
			
			return Quaternion.LookRotation(viewingVector, upVector);
		}
示例#6
0
        private Quaternion GetPlaneRotation(IKSolverFullBody solver)
        {
            Vector3 solverPosition  = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition;
            Vector3 solverPosition2 = solver.GetNode(this.plane2ChainIndex, this.plane2NodeIndex).solverPosition;
            Vector3 solverPosition3 = solver.GetNode(this.plane3ChainIndex, this.plane3NodeIndex).solverPosition;
            Vector3 vector          = solverPosition2 - solverPosition;
            Vector3 upwards         = solverPosition3 - solverPosition;

            if (vector == Vector3.zero)
            {
                Warning.Log("Make sure you are not placing 2 or more FBBIK effectors of the same chain to exactly the same position.", this.bone, false);
                return(Quaternion.identity);
            }
            return(Quaternion.LookRotation(vector, upwards));
        }
示例#7
0
		/*
		 * Manipulating node solverPosition
		 * */
		public void Update(IKSolverFullBody solver) {
			if (firstUpdate) {
				animatedPosition = bone.position + solver.GetNode(chainIndex, nodeIndex).offset;
				firstUpdate = false;
			}

			solver.GetNode(chainIndex, nodeIndex).solverPosition = Vector3.Lerp(GetPosition(solver, out planeRotationOffset), position, posW);

			// Child nodes
			if (!effectChildNodes) return;

			for (int i = 0; i < childBones.Length; i++) {
				solver.GetNode(childChainIndexes[i], childNodeIndexes[i]).solverPosition = Vector3.Lerp(solver.GetNode(childChainIndexes[i], childNodeIndexes[i]).solverPosition, solver.GetNode(chainIndex, nodeIndex).solverPosition + localPositions[i], posW);
			}
		}
示例#8
0
            /*
             * Rotation of plane nodes in the solver
             * */
            private Quaternion GetTargetRotation(IKSolverFullBody solver)
            {
                Vector3 p1 = solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition;
                Vector3 p2 = solver.GetNode(plane2ChainIndex, plane2NodeIndex).solverPosition;
                Vector3 p3 = solver.GetNode(plane3ChainIndex, plane3NodeIndex).solverPosition;

                if (p1 == p3)
                {
                    return(Quaternion.identity);
                }
                return(Quaternion.LookRotation(p2 - p1, p3 - p1));

                //if (planeNode1.solverPosition == planeNode3.solverPosition) return Quaternion.identity;
                //return Quaternion.LookRotation(planeNode2.solverPosition - planeNode1.solverPosition, planeNode3.solverPosition - planeNode1.solverPosition);
            }
示例#9
0
		/*
		 * Presolving, applying offset
		 * */
		public void OnPreSolve(IKSolverFullBody solver) {
			positionWeight = Mathf.Clamp(positionWeight, 0f, 1f);
			rotationWeight = Mathf.Clamp(rotationWeight, 0f, 1f);
			maintainRelativePositionWeight = Mathf.Clamp(maintainRelativePositionWeight, 0f, 1f);

			// Calculating weights
			posW = positionWeight * solver.IKPositionWeight;
			rotW = rotationWeight * solver.IKPositionWeight;

			solver.GetNode(chainIndex, nodeIndex).effectorPositionWeight = posW;
			solver.GetNode(chainIndex, nodeIndex).effectorRotationWeight = rotW;

			solver.GetNode(chainIndex, nodeIndex).solverRotation = rotation;

			if (float.IsInfinity(positionOffset.x) ||
				float.IsInfinity(positionOffset.y) ||
				float.IsInfinity(positionOffset.z)
			    ) Debug.LogError("Invalid IKEffector.positionOffset (contains Infinity)! Please make sure not to set IKEffector.positionOffset to infinite values.", bone);

			if (float.IsNaN(positionOffset.x) ||
			    float.IsNaN(positionOffset.y) ||
			    float.IsNaN(positionOffset.z)
			    ) Debug.LogError("Invalid IKEffector.positionOffset (contains NaN)! Please make sure not to set IKEffector.positionOffset to NaN values.", bone);

			if (positionOffset.sqrMagnitude > 10000000000f) Debug.LogError("Additive effector positionOffset detected in Full Body IK (extremely large value). Make sure you are not circularily adding to effector positionOffset each frame.", bone);

			if (float.IsInfinity(position.x) ||
			    float.IsInfinity(position.y) ||
			    float.IsInfinity(position.z)
			    ) Debug.LogError("Invalid IKEffector.position (contains Infinity)!");

			solver.GetNode(chainIndex, nodeIndex).offset += positionOffset * solver.IKPositionWeight;

			if (effectChildNodes && solver.iterations > 0) {
				for (int i = 0; i < childBones.Length; i++) {
					localPositions[i] = childBones[i].transform.position - bone.transform.position;

					solver.GetNode(childChainIndexes[i], childNodeIndexes[i]).offset += positionOffset * solver.IKPositionWeight;
				}
			}

			// Relative to Plane
			if (usePlaneNodes && maintainRelativePositionWeight > 0f) {
				animatedPlaneRotation = Quaternion.LookRotation(planeBone2.position - planeBone1.position, planeBone3.position - planeBone1.position);;
			}

			firstUpdate = true;
		}
示例#10
0
        private Vector3 OrthoToBone1(IKSolverFullBody solver, Vector3 tangent)
        {
            Vector3 vector = solver.GetNode(this.chainIndex2, this.nodeIndex2).solverPosition - solver.GetNode(this.chainIndex1, this.nodeIndex1).solverPosition;

            Vector3.OrthoNormalize(ref vector, ref tangent);
            return(tangent);
        }
示例#11
0
        public void WritePose(IKSolverFullBody solver, bool fullBody)
        {
            if (weight <= 0f)
            {
                return;
            }

            // Swing the parent bone to look at the first node's position
            if (fullBody)
            {
                if (parentBone != null)
                {
                    boneMapParent.Swing(solver.GetNode(boneMap1.chainIndex, boneMap1.nodeIndex).solverPosition, weight);
                    //boneMapParent.Swing(boneMap1.node.solverPosition, weight);
                }

                // Fix the first bone to it's node
                boneMap1.FixToNode(solver, weight);
            }

            // Rotate the 2 first bones to the plane points
            boneMap1.RotateToPlane(solver, weight);
            boneMap2.RotateToPlane(solver, weight);

            // Rotate the third bone to the rotation it had before solving
            boneMap3.RotateToMaintain(maintainRotationWeight * weight * solver.IKPositionWeight);

            // Rotate the third bone to the effector rotation
            boneMap3.RotateToEffector(solver, weight);
        }
示例#12
0
 public void Update(IKSolverFullBody solver)
 {
     if (this.firstUpdate)
     {
         this.animatedPosition = this.bone.position + solver.GetNode(this.chainIndex, this.nodeIndex).offset;
         this.firstUpdate      = false;
     }
     solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition = Vector3.Lerp(this.GetPosition(solver, out this.planeRotationOffset), this.position, this.posW);
     if (!this.effectChildNodes)
     {
         return;
     }
     for (int i = 0; i < this.childBones.Length; i++)
     {
         solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).solverPosition = Vector3.Lerp(solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).solverPosition, solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition + this.localPositions[i], this.posW);
     }
 }
示例#13
0
            public void RotateToEffector(IKSolverFullBody solver, float weight)
            {
                if (!this.isNodeBone)
                {
                    return;
                }
                float num = weight * solver.GetNode(this.chainIndex, this.nodeIndex).effectorRotationWeight;

                if (num <= 0f)
                {
                    return;
                }
                if (num >= 1f)
                {
                    this.transform.rotation = solver.GetNode(this.chainIndex, this.nodeIndex).solverRotation;
                    return;
                }
                this.transform.rotation = Quaternion.Lerp(this.transform.rotation, solver.GetNode(this.chainIndex, this.nodeIndex).solverRotation, num);
            }
示例#14
0
        private Vector3 GetPosition(IKSolverFullBody solver, out Quaternion planeRotationOffset)
        {
            planeRotationOffset = Quaternion.identity;
            if (!this.isEndEffector)
            {
                return(solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition);
            }
            if (this.maintainRelativePositionWeight <= 0f)
            {
                return(this.animatedPosition);
            }
            Vector3 a     = this.bone.position;
            Vector3 point = a - this.planeBone1.position;

            planeRotationOffset = this.GetPlaneRotation(solver) * Quaternion.Inverse(this.animatedPlaneRotation);
            a = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition + planeRotationOffset * point;
            planeRotationOffset = Quaternion.Lerp(Quaternion.identity, planeRotationOffset, this.maintainRelativePositionWeight);
            return(Vector3.Lerp(this.animatedPosition, a + solver.GetNode(this.chainIndex, this.nodeIndex).offset, this.maintainRelativePositionWeight));
        }
示例#15
0
 public void OnPreSolve(IKSolverFullBody solver)
 {
     this.positionWeight = Mathf.Clamp(this.positionWeight, 0f, 1f);
     this.rotationWeight = Mathf.Clamp(this.rotationWeight, 0f, 1f);
     this.maintainRelativePositionWeight = Mathf.Clamp(this.maintainRelativePositionWeight, 0f, 1f);
     this.posW = this.positionWeight * solver.IKPositionWeight;
     this.rotW = this.rotationWeight * solver.IKPositionWeight;
     solver.GetNode(this.chainIndex, this.nodeIndex).effectorPositionWeight = this.posW;
     solver.GetNode(this.chainIndex, this.nodeIndex).effectorRotationWeight = this.rotW;
     solver.GetNode(this.chainIndex, this.nodeIndex).solverRotation         = this.rotation;
     if (float.IsInfinity(this.positionOffset.x) || float.IsInfinity(this.positionOffset.y) || float.IsInfinity(this.positionOffset.z))
     {
         Debug.LogError("Invalid IKEffector.positionOffset (contains Infinity)! Please make sure not to set IKEffector.positionOffset to infinite values.", this.bone);
     }
     if (float.IsNaN(this.positionOffset.x) || float.IsNaN(this.positionOffset.y) || float.IsNaN(this.positionOffset.z))
     {
         Debug.LogError("Invalid IKEffector.positionOffset (contains NaN)! Please make sure not to set IKEffector.positionOffset to NaN values.", this.bone);
     }
     if (this.positionOffset.sqrMagnitude > 1E+10f)
     {
         Debug.LogError("Additive effector positionOffset detected in Full Body IK (extremely large value). Make sure you are not circularily adding to effector positionOffset each frame.", this.bone);
     }
     if (float.IsInfinity(this.position.x) || float.IsInfinity(this.position.y) || float.IsInfinity(this.position.z))
     {
         Debug.LogError("Invalid IKEffector.position (contains Infinity)!");
     }
     solver.GetNode(this.chainIndex, this.nodeIndex).offset += this.positionOffset * solver.IKPositionWeight;
     if (this.effectChildNodes && solver.iterations > 0)
     {
         for (int i = 0; i < this.childBones.Length; i++)
         {
             this.localPositions[i] = this.childBones[i].transform.position - this.bone.transform.position;
             solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).offset += this.positionOffset * solver.IKPositionWeight;
         }
     }
     if (this.usePlaneNodes && this.maintainRelativePositionWeight > 0f)
     {
         this.animatedPlaneRotation = Quaternion.LookRotation(this.planeBone2.position - this.planeBone1.position, this.planeBone3.position - this.planeBone1.position);
     }
     this.firstUpdate = true;
 }
示例#16
0
            /*
             * Rotates to match the effector rotation
             * */
            public void RotateToEffector(IKSolverFullBody solver, float weight)
            {
                if (!isNodeBone)
                {
                    return;
                }
                float w = weight * solver.GetNode(chainIndex, nodeIndex).effectorRotationWeight;

                if (w <= 0f)
                {
                    return;
                }

                if (w >= 1f)
                {
                    transform.rotation = solver.GetNode(chainIndex, nodeIndex).solverRotation;
                    return;
                }

                transform.rotation = Quaternion.Lerp(transform.rotation, solver.GetNode(chainIndex, nodeIndex).solverRotation, w);
            }
示例#17
0
        public Vector3 GetDir(IKSolverFullBody solver)
        {
            if (!this.initiated)
            {
                return(Vector3.zero);
            }
            float num = this.weight * solver.IKPositionWeight;

            if (this.bendGoal != null)
            {
                Vector3 lhs = this.bendGoal.position - solver.GetNode(this.chainIndex1, this.nodeIndex1).solverPosition;
                if (lhs != Vector3.zero)
                {
                    this.direction = lhs;
                }
            }
            if (num >= 1f)
            {
                return(this.direction.normalized);
            }
            Vector3    vector   = solver.GetNode(this.chainIndex3, this.nodeIndex3).solverPosition - solver.GetNode(this.chainIndex1, this.nodeIndex1).solverPosition;
            Quaternion rotation = Quaternion.FromToRotation(this.bone3.position - this.bone1.position, vector);
            Vector3    vector2  = rotation * (this.bone2.position - this.bone1.position);

            if (solver.GetNode(this.chainIndex3, this.nodeIndex3).effectorRotationWeight > 0f)
            {
                Vector3 b = -Vector3.Cross(vector, solver.GetNode(this.chainIndex3, this.nodeIndex3).solverRotation *this.defaultChildDirection);
                vector2 = Vector3.Lerp(vector2, b, solver.GetNode(this.chainIndex3, this.nodeIndex3).effectorRotationWeight);
            }
            if (this.rotationOffset != Quaternion.identity)
            {
                Quaternion lhs2 = Quaternion.FromToRotation(this.rotationOffset * vector, vector);
                vector2 = lhs2 * this.rotationOffset * vector2;
            }
            if (num <= 0f)
            {
                return(vector2);
            }
            return(Vector3.Lerp(vector2, this.direction.normalized, num));
        }
示例#18
0
 public void FixToNode(IKSolverFullBody solver, float weight, IKSolver.Node fixNode = null)
 {
     if (fixNode == null)
     {
         fixNode = solver.GetNode(this.chainIndex, this.nodeIndex);
     }
     if (weight >= 1f)
     {
         this.transform.position = fixNode.solverPosition;
         return;
     }
     this.transform.position = Vector3.Lerp(this.transform.position, fixNode.solverPosition, weight);
 }
        /*
         * Mapping the spine to the hip and chest planes
         * */
        public void WritePose(IKSolverFullBody solver)
        {
            Vector3 firstPosition = spine[0].GetPlanePosition(solver);
            Vector3 rootPosition  = solver.GetNode(spine[rootNodeIndex].chainIndex, spine[rootNodeIndex].nodeIndex).solverPosition;
            Vector3 lastPosition  = spine[spine.Length - 1].GetPlanePosition(solver);

            // If we have more than 3 bones, use the FABRIK algorithm
            if (useFABRIK)
            {
                Vector3 offset = solver.GetNode(spine[rootNodeIndex].chainIndex, spine[rootNodeIndex].nodeIndex).solverPosition - spine[rootNodeIndex].transform.position;

                for (int i = 0; i < spine.Length; i++)
                {
                    spine[i].ikPosition = spine[i].transform.position + offset;
                }

                // Iterating the FABRIK algorithm
                for (int i = 0; i < iterations; i++)
                {
                    ForwardReach(lastPosition);
                    BackwardReach(firstPosition);
                    spine[rootNodeIndex].ikPosition = rootPosition;
                }
            }
            else
            {
                // When we have just 3 bones, we know their positions already
                spine[0].ikPosition             = firstPosition;
                spine[rootNodeIndex].ikPosition = rootPosition;
            }

            spine[spine.Length - 1].ikPosition = lastPosition;

            // Mapping the spine bones to the solver
            MapToSolverPositions(solver);
        }
示例#20
0
 public void WritePose(IKSolverFullBody solver, bool fullBody)
 {
     if (this.weight <= 0f)
     {
         return;
     }
     if (fullBody)
     {
         if (this.parentBone != null)
         {
             this.boneMapParent.Swing(solver.GetNode(this.boneMap1.chainIndex, this.boneMap1.nodeIndex).solverPosition, this.weight);
         }
         this.boneMap1.FixToNode(solver, this.weight, null);
     }
     this.boneMap1.RotateToPlane(solver, this.weight);
     this.boneMap2.RotateToPlane(solver, this.weight);
     this.boneMap3.RotateToMaintain(this.maintainRotationWeight * this.weight * solver.IKPositionWeight);
     this.boneMap3.RotateToEffector(solver, this.weight);
 }
示例#21
0
			/*
			 * Rotates to match the effector rotation
			 * */
			public void RotateToEffector(IKSolverFullBody solver, float weight) {
				if (!isNodeBone) return;
				float w = weight * solver.GetNode(chainIndex, nodeIndex).effectorRotationWeight;
				if (w <= 0f) return;

				if (w >= 1f) {
					transform.rotation = solver.GetNode(chainIndex, nodeIndex).solverRotation;
					return;
				}

				transform.rotation = Quaternion.Lerp(transform.rotation, solver.GetNode(chainIndex, nodeIndex).solverRotation, w);
			}
示例#22
0
			/*
			 * Moves the bone to the solver position of it's node
			 * */
			public void FixToNode(IKSolverFullBody solver, float weight, IKSolver.Node fixNode = null) {
				if (fixNode == null) fixNode = solver.GetNode(chainIndex, nodeIndex);

				if (weight >= 1f) {
					transform.position = fixNode.solverPosition;
					return;
				}

				transform.position = Vector3.Lerp(transform.position, fixNode.solverPosition, weight);
			}
示例#23
0
		/*
		 * Mapping the spine to the hip and chest planes
		 * */
		public void WritePose(IKSolverFullBody solver) {
			Vector3 firstPosition = spine[0].GetPlanePosition(solver);
			Vector3 rootPosition = solver.GetNode(spine[rootNodeIndex].chainIndex, spine[rootNodeIndex].nodeIndex).solverPosition;
			Vector3 lastPosition = spine[spine.Length - 1].GetPlanePosition(solver);

			// If we have more than 3 bones, use the FABRIK algorithm
			if (useFABRIK) {
				Vector3 offset = solver.GetNode(spine[rootNodeIndex].chainIndex, spine[rootNodeIndex].nodeIndex).solverPosition - spine[rootNodeIndex].transform.position;
					
				for (int i = 0; i < spine.Length; i++) {
					spine[i].ikPosition = spine[i].transform.position + offset;
				}
					
				// Iterating the FABRIK algorithm
				for (int i = 0; i < iterations; i++) {
					ForwardReach(lastPosition);
					BackwardReach(firstPosition);
					spine[rootNodeIndex].ikPosition = rootPosition;
				}
			} else {
				// When we have just 3 bones, we know their positions already
				spine[0].ikPosition = firstPosition;
				spine[rootNodeIndex].ikPosition = rootPosition;
			}

			spine[spine.Length - 1].ikPosition = lastPosition;

			// Mapping the spine bones to the solver
			MapToSolverPositions(solver);
		}
示例#24
0
			/*
			 * Rotation of plane nodes in the solver
			 * */
			private Quaternion GetTargetRotation(IKSolverFullBody solver) {
				Vector3 p1 = solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition;
				Vector3 p2 = solver.GetNode(plane2ChainIndex, plane2NodeIndex).solverPosition;
				Vector3 p3 = solver.GetNode(plane3ChainIndex, plane3NodeIndex).solverPosition;

				if (p1 == p3) return Quaternion.identity;
				return Quaternion.LookRotation(p2 - p1, p3 - p1);

				//if (planeNode1.solverPosition == planeNode3.solverPosition) return Quaternion.identity;
				//return Quaternion.LookRotation(planeNode2.solverPosition - planeNode1.solverPosition, planeNode3.solverPosition - planeNode1.solverPosition);
			}
示例#25
0
 /*
  * Gets the bone's position relative to its 3 plane nodes
  * */
 public Vector3 GetPlanePosition(IKSolverFullBody solver)
 {
     return(solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition + (GetTargetRotation(solver) * planePosition));
     //return planeNode1.solverPosition + (targetRotation * planePosition);
 }
示例#26
0
		/*
		 * Positioning and rotating the spine bones to match the solver positions
		 * */
		private void MapToSolverPositions(IKSolverFullBody solver) {
			// Translating the first bone
			// Note: spine here also includes the pelvis
			spine[0].SetToIKPosition();
			spine[0].RotateToPlane(solver, 1f);

			// Translating all the bones between the first and the last
			for (int i = 1; i < spine.Length - 1; i++) {
				spine[i].Swing(spine[i + 1].ikPosition, 1f);

				if (twistWeight > 0) {
					float bWeight = (float)i / ((float)spine.Length - 2);

					Vector3 s1 = solver.GetNode(leftUpperArm.chainIndex, leftUpperArm.nodeIndex).solverPosition;
					Vector3 s2 = solver.GetNode(rightUpperArm.chainIndex, rightUpperArm.nodeIndex).solverPosition;
					spine[i].Twist(s1 - s2, spine[i + 1].ikPosition - spine[i].transform.position, bWeight * twistWeight);
				}
			}
			
			// Translating the last bone
			spine[spine.Length - 1].SetToIKPosition();
			spine[spine.Length - 1].RotateToPlane(solver, 1f);
		}
		/*
		 * Computes the direction from the first node to the second node
		 * */
		public Vector3 GetDir(IKSolverFullBody solver) {
			if (!initiated) return Vector3.zero;

			float w = weight * solver.IKPositionWeight;

			// Apply the bend goal
			if (bendGoal != null) {
				Vector3 b = bendGoal.position - solver.GetNode(chainIndex1, nodeIndex1).solverPosition;
				if (b != Vector3.zero) direction = b;
			}

			if (w >= 1f) return direction.normalized;

			Vector3 solverDirection = solver.GetNode(chainIndex3, nodeIndex3).solverPosition - solver.GetNode(chainIndex1, nodeIndex1).solverPosition;

			// Get rotation from animated limb direction to solver limb direction
			Quaternion f = Quaternion.FromToRotation(bone3.position - bone1.position, solverDirection);

			// Rotate the default bend direction by f
			Vector3 dir = f * (bone2.position - bone1.position);

			// Effector rotation
			if (solver.GetNode(chainIndex3, nodeIndex3).effectorRotationWeight > 0f) {
				// Bend direction according to the effector rotation
				Vector3 effectorDirection = -Vector3.Cross(solverDirection, solver.GetNode(chainIndex3, nodeIndex3).solverRotation * defaultChildDirection);
				dir = Vector3.Lerp(dir, effectorDirection, solver.GetNode(chainIndex3, nodeIndex3).effectorRotationWeight);
			}

			// Rotation Offset
			if (rotationOffset != Quaternion.identity) {
				Quaternion toOrtho = Quaternion.FromToRotation(rotationOffset * solverDirection, solverDirection);
				dir = toOrtho * rotationOffset * dir;
			}

			if (w <= 0f) return dir;
			return Vector3.Lerp(dir, direction.normalized, w); 
		}
		/*
		 * Ortho-Normalize a vector to the first bone direction
		 * */
		private Vector3 OrthoToBone1(IKSolverFullBody solver, Vector3 tangent) {
			Vector3 normal = solver.GetNode(chainIndex2, nodeIndex2).solverPosition - solver.GetNode(chainIndex1, nodeIndex1).solverPosition;
			Vector3.OrthoNormalize(ref normal, ref tangent);
			return tangent;
		}
示例#29
0
		public void WritePose(IKSolverFullBody solver, bool fullBody) {
			if (weight <= 0f) return;

			// Swing the parent bone to look at the first node's position
			if (fullBody) {
				if (parentBone != null) {
					boneMapParent.Swing(solver.GetNode(boneMap1.chainIndex, boneMap1.nodeIndex).solverPosition, weight);
					//boneMapParent.Swing(boneMap1.node.solverPosition, weight);
				}
				
				// Fix the first bone to it's node
				//boneMap1.FixToNode(weight);
			}

			// Rotate the 2 first bones to the plane points
			boneMap1.RotateToPlane(solver, weight);
			boneMap2.RotateToPlane(solver, weight);

			// Rotate the third bone to the rotation it had before solving
			boneMap3.RotateToMaintain(maintainRotationWeight * weight * solver.IKPositionWeight);
			
			// Rotate the third bone to the effector rotation
			boneMap3.RotateToEffector(solver, weight);
		}
示例#30
0
 /*
  * Gets the bone's position relative to it's 3 plane nodes
  * 限制骨骼在平面节点之间
  * */
 public Vector3 GetPlanePosition(IKSolverFullBody solver)
 {
     //计算 当前节点在相对于平面节点的方向需要做的位移偏移量 然后叠加到 solverPosition中
     return(solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition + (GetTargetRotation(solver) * planePosition));
     //return planeNode1.solverPosition + (targetRotation * planePosition);
 }
示例#31
0
 public Vector3 GetPlanePosition(IKSolverFullBody solver)
 {
     return(solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition + this.GetTargetRotation(solver) * this.planePosition);
 }
示例#32
0
			/*
			 * Gets the bone's position relative to it's 3 plane nodes
			 * */
			public Vector3 GetPlanePosition(IKSolverFullBody solver) {
				return solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition + (GetTargetRotation(solver) * planePosition);
				//return planeNode1.solverPosition + (targetRotation * planePosition);
			}
示例#33
0
		/*
		 * Gets the starting position of the iteration
		 * */
		private Vector3 GetPosition(IKSolverFullBody solver, out Quaternion planeRotationOffset) {
			planeRotationOffset = Quaternion.identity;
			if (!isEndEffector) return solver.GetNode(chainIndex, nodeIndex).solverPosition; // non end-effectors are always free

			if (maintainRelativePositionWeight <= 0f) return animatedPosition;

			// Maintain relative position
			Vector3 p = bone.position;
			Vector3 dir = p - planeBone1.position;
				
			planeRotationOffset = GetPlaneRotation(solver) * Quaternion.Inverse(animatedPlaneRotation);

			p = solver.GetNode(plane1ChainIndex, plane1NodeIndex).solverPosition + planeRotationOffset * dir;

			// Interpolate the rotation offset
			planeRotationOffset = Quaternion.Lerp(Quaternion.identity, planeRotationOffset, maintainRelativePositionWeight);

			return Vector3.Lerp(animatedPosition, p + solver.GetNode(chainIndex, nodeIndex).offset, maintainRelativePositionWeight);
		}