123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.FinalIK {
- /// <summary>
- /// Maps a 3-segmented bone hierarchy to a node chain of an %IK Solver
- /// </summary>
- [System.Serializable]
- public class IKMappingLimb: IKMapping {
-
- #region Main Interface
- /// <summary>
- /// Limb Bone Map type
- /// </summary>
- [System.Serializable]
- public enum BoneMapType {
- Parent,
- Bone1,
- Bone2,
- Bone3
- }
- /// <summary>
- /// The optional parent bone (clavicle).
- /// </summary>
- public Transform parentBone;
- /// <summary>
- /// The first bone (upper arm or thigh).
- /// </summary>
- public Transform bone1;
- /// <summary>
- /// The second bone (forearm or calf).
- /// </summary>
- public Transform bone2;
- /// <summary>
- /// The third bone (hand or foot).
- /// </summary>
- public Transform bone3;
- /// <summary>
- /// The weight of maintaining the third bone's rotation as it was in the animation
- /// </summary>
- [Range(0f, 1f)]
- public float maintainRotationWeight;
- /// <summary>
- /// The weight of mapping the limb to it's IK pose. This can be useful if you want to disable the effect of IK for the limb.
- /// </summary>
- [Range(0f, 1f)]
- public float weight = 1f; // Added in 0.2
- /// <summary>
- /// Disable this to maintain original sampled rotations of the limb bones relative to each other.
- /// </summary>
- [System.NonSerializedAttribute] public bool updatePlaneRotations = true;
- /// <summary>
- /// Determines whether this IKMappingLimb is valid
- /// </summary>
- public override bool IsValid(IKSolver solver, ref string message) {
- if (!base.IsValid(solver, ref message)) return false;
-
- if (!BoneIsValid(bone1, solver, ref message)) return false;
- if (!BoneIsValid(bone2, solver, ref message)) return false;
- if (!BoneIsValid(bone3, solver, ref message)) return false;
-
- return true;
- }
- /// <summary>
- /// Gets the bone map of the specified bone.
- /// </summary>
- public BoneMap GetBoneMap(BoneMapType boneMap) {
- switch(boneMap) {
- case BoneMapType.Parent:
- if (parentBone == null) Warning.Log("This limb does not have a parent (shoulder) bone", bone1);
- return boneMapParent;
- case BoneMapType.Bone1: return boneMap1;
- case BoneMapType.Bone2: return boneMap2;
- default: return boneMap3;
- }
- }
- /// <summary>
- /// Makes the limb mapped to the specific local directions of the bones. Added in 0.3
- /// </summary>
- public void SetLimbOrientation(Vector3 upper, Vector3 lower) {
- boneMap1.defaultLocalTargetRotation = Quaternion.Inverse(Quaternion.Inverse(bone1.rotation) * Quaternion.LookRotation(bone2.position - bone1.position, bone1.rotation * -upper));
- boneMap2.defaultLocalTargetRotation = Quaternion.Inverse(Quaternion.Inverse(bone2.rotation) * Quaternion.LookRotation(bone3.position - bone2.position, bone2.rotation * -lower));
- }
-
- #endregion Main Interface
-
- private BoneMap boneMapParent = new BoneMap(), boneMap1 = new BoneMap(), boneMap2 = new BoneMap(), boneMap3 = new BoneMap();
-
- public IKMappingLimb() {}
-
- public IKMappingLimb(Transform bone1, Transform bone2, Transform bone3, Transform parentBone = null) {
- SetBones(bone1, bone2, bone3, parentBone);
- }
-
- public void SetBones(Transform bone1, Transform bone2, Transform bone3, Transform parentBone = null) {
- this.bone1 = bone1;
- this.bone2 = bone2;
- this.bone3 = bone3;
- this.parentBone = parentBone;
- }
-
- public void StoreDefaultLocalState() {
- if (parentBone != null) boneMapParent.StoreDefaultLocalState();
- boneMap1.StoreDefaultLocalState();
- boneMap2.StoreDefaultLocalState();
- boneMap3.StoreDefaultLocalState();
- }
-
- public void FixTransforms() {
- if (parentBone != null) boneMapParent.FixTransform(false);
- boneMap1.FixTransform(true);
- boneMap2.FixTransform(false);
- boneMap3.FixTransform(false);
- }
-
- /*
- * Initiating and setting defaults
- * */
- public override void Initiate(IKSolverFullBody solver) {
- if (boneMapParent == null) boneMapParent = new BoneMap();
- if (boneMap1 == null) boneMap1 = new BoneMap();
- if (boneMap2 == null) boneMap2 = new BoneMap();
- if (boneMap3 == null) boneMap3 = new BoneMap();
- // Finding the nodes
- if (parentBone != null) boneMapParent.Initiate(parentBone, solver);
- boneMap1.Initiate(bone1, solver);
- boneMap2.Initiate(bone2, solver);
- boneMap3.Initiate(bone3, solver);
- // Define plane points for the bone maps
- boneMap1.SetPlane(solver, boneMap1.transform, boneMap2.transform, boneMap3.transform);
- boneMap2.SetPlane(solver, boneMap2.transform, boneMap3.transform, boneMap1.transform);
- // Find the swing axis for the parent bone
- if (parentBone != null) boneMapParent.SetLocalSwingAxis(boneMap1);
- }
-
- /*
- * Presolving the bones and maintaining rotation
- * */
- public void ReadPose() {
- boneMap1.UpdatePlane(updatePlaneRotations, true);
- boneMap2.UpdatePlane(updatePlaneRotations, false);
- // Clamping weights
- weight = Mathf.Clamp(weight, 0f, 1f);
- // Define plane points for the bone maps
- boneMap3.MaintainRotation();
- }
- 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);
- }
- }
- }
|