190 lines
4.3 KiB
C#
190 lines
4.3 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
namespace RootMotion.FinalIK
|
|
{
|
|
[Serializable]
|
|
public class IKMappingLimb : IKMapping
|
|
{
|
|
[Serializable]
|
|
public enum BoneMapType
|
|
{
|
|
Parent = 0,
|
|
Bone1 = 1,
|
|
Bone2 = 2,
|
|
Bone3 = 3
|
|
}
|
|
|
|
public Transform parentBone;
|
|
|
|
public Transform bone1;
|
|
|
|
public Transform bone2;
|
|
|
|
public Transform bone3;
|
|
|
|
[Range(0f, 1f)]
|
|
public float maintainRotationWeight;
|
|
|
|
[Range(0f, 1f)]
|
|
public float weight = 1f;
|
|
|
|
[NonSerialized]
|
|
public bool updatePlaneRotations = true;
|
|
|
|
private BoneMap boneMapParent = new BoneMap();
|
|
|
|
private BoneMap boneMap1 = new BoneMap();
|
|
|
|
private BoneMap boneMap2 = new BoneMap();
|
|
|
|
private BoneMap boneMap3 = new BoneMap();
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
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(position: false);
|
|
}
|
|
boneMap1.FixTransform(position: true);
|
|
boneMap2.FixTransform(position: false);
|
|
boneMap3.FixTransform(position: false);
|
|
}
|
|
|
|
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();
|
|
}
|
|
if (parentBone != null)
|
|
{
|
|
boneMapParent.Initiate(parentBone, solver);
|
|
}
|
|
boneMap1.Initiate(bone1, solver);
|
|
boneMap2.Initiate(bone2, solver);
|
|
boneMap3.Initiate(bone3, solver);
|
|
boneMap1.SetPlane(solver, boneMap1.transform, boneMap2.transform, boneMap3.transform);
|
|
boneMap2.SetPlane(solver, boneMap2.transform, boneMap3.transform, boneMap1.transform);
|
|
if (parentBone != null)
|
|
{
|
|
boneMapParent.SetLocalSwingAxis(boneMap1);
|
|
}
|
|
}
|
|
|
|
public void ReadPose()
|
|
{
|
|
boneMap1.UpdatePlane(updatePlaneRotations, position: true);
|
|
boneMap2.UpdatePlane(updatePlaneRotations, position: false);
|
|
weight = Mathf.Clamp(weight, 0f, 1f);
|
|
boneMap3.MaintainRotation();
|
|
}
|
|
|
|
public void WritePose(IKSolverFullBody solver, bool fullBody)
|
|
{
|
|
if (weight <= 0f)
|
|
{
|
|
return;
|
|
}
|
|
if (fullBody)
|
|
{
|
|
if (parentBone != null)
|
|
{
|
|
boneMapParent.Swing(solver.GetNode(boneMap1.chainIndex, boneMap1.nodeIndex).solverPosition, weight);
|
|
}
|
|
boneMap1.FixToNode(solver, weight);
|
|
}
|
|
boneMap1.RotateToPlane(solver, weight);
|
|
boneMap2.RotateToPlane(solver, weight);
|
|
boneMap3.RotateToMaintain(maintainRotationWeight * weight * solver.IKPositionWeight);
|
|
boneMap3.RotateToEffector(solver, weight);
|
|
}
|
|
}
|
|
}
|