initial upload
This commit is contained in:
@ -0,0 +1,149 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace RootMotion.FinalIK {
|
||||
|
||||
/// <summary>
|
||||
/// Posing the children of a Transform to match the children of another Transform
|
||||
/// </summary>
|
||||
public class GenericPoser : Poser {
|
||||
|
||||
/// <summary>
|
||||
/// Mapping a bone to its target
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class Map {
|
||||
public Transform bone;
|
||||
public Transform target;
|
||||
|
||||
private Vector3 defaultLocalPosition;
|
||||
private Quaternion defaultLocalRotation;
|
||||
|
||||
private Vector3 lerpLocalPosition;
|
||||
private Quaternion lerpLocalRotation;
|
||||
|
||||
// Custom constructor
|
||||
public Map(Transform bone, Transform target) {
|
||||
this.bone = bone;
|
||||
this.target = target;
|
||||
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
public void StoreDefaultState() {
|
||||
defaultLocalPosition = bone.localPosition;
|
||||
defaultLocalRotation = bone.localRotation;
|
||||
}
|
||||
|
||||
public void StoreCurrentPose()
|
||||
{
|
||||
lerpLocalPosition = bone.localPosition;
|
||||
lerpLocalRotation = bone.localRotation;
|
||||
}
|
||||
|
||||
public void FixTransform() {
|
||||
bone.localPosition = defaultLocalPosition;
|
||||
bone.localRotation = defaultLocalRotation;
|
||||
}
|
||||
|
||||
// Update mapping
|
||||
public void Update(float localRotationWeight, float localPositionWeight) {
|
||||
bone.localRotation = Quaternion.Lerp(bone.localRotation, target.localRotation, localRotationWeight);
|
||||
bone.localPosition = Vector3.Lerp(bone.localPosition, target.localPosition, localPositionWeight);
|
||||
}
|
||||
|
||||
public void BlendFromLastPose(float lerpTimer)
|
||||
{
|
||||
bone.localPosition = Vector3.Lerp(lerpLocalPosition, bone.localPosition, lerpTimer);
|
||||
bone.localRotation = Quaternion.Lerp(lerpLocalRotation, bone.localRotation, lerpTimer);
|
||||
}
|
||||
}
|
||||
|
||||
public Map[] maps;
|
||||
|
||||
/// <summary>
|
||||
/// Finds mapping automatically. This requires for all children of the transform to have unique names. This method is not very memory efficient so try to avoid using it in play mode.
|
||||
/// </summary>
|
||||
[ContextMenu("Auto-Mapping")]
|
||||
public override void AutoMapping() {
|
||||
if (poseRoot == null) {
|
||||
maps = new Map[0];
|
||||
return;
|
||||
}
|
||||
|
||||
maps = new Map[0];
|
||||
|
||||
Transform[] children = (Transform[])transform.GetComponentsInChildren<Transform>();
|
||||
Transform[] poseChildren = (Transform[])poseRoot.GetComponentsInChildren<Transform>();
|
||||
Transform target;
|
||||
|
||||
// Find all the bone to target matches
|
||||
for (int i = 1; i < children.Length; i++) {
|
||||
target = GetTargetNamed(children[i].name, poseChildren);
|
||||
if (target != null) {
|
||||
Array.Resize(ref maps, maps.Length + 1);
|
||||
maps[maps.Length - 1] = new Map(children[i], target);
|
||||
}
|
||||
}
|
||||
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
protected override void InitiatePoser() {
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
protected override void UpdatePoser() {
|
||||
if (weight <= 0f) return;
|
||||
if (localPositionWeight <= 0f && localRotationWeight <= 0f) return;
|
||||
if (poseRoot == null) return;
|
||||
|
||||
// Calculate weights
|
||||
float rW = localRotationWeight * weight;
|
||||
float pW = localPositionWeight * weight;
|
||||
|
||||
// Lerping the localRotation and the localPosition
|
||||
for (int i = 0; i < maps.Length; i++) maps[i].Update(rW, pW);
|
||||
}
|
||||
|
||||
protected override void StoreCurrentPose()
|
||||
{
|
||||
for (int i = 0; i < maps.Length; i++)
|
||||
{
|
||||
maps[i].StoreCurrentPose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BlendFromLastPose(float lerpTimer)
|
||||
{
|
||||
for (int i = 0; i < maps.Length; i++)
|
||||
{
|
||||
maps[i].BlendFromLastPose(lerpTimer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void FixPoserTransforms() {
|
||||
for (int i = 0; i < maps.Length; i++) {
|
||||
maps[i].FixTransform();
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreDefaultState() {
|
||||
for (int i = 0; i < maps.Length; i++) {
|
||||
maps[i].StoreDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a Transform from the array that has the specified name
|
||||
private Transform GetTargetNamed(string tName, Transform[] array) {
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
if (array[i].name == tName) return array[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd754e329e5ea4f139b08b9271641e12
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,100 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace RootMotion.FinalIK {
|
||||
|
||||
/// <summary>
|
||||
/// Posing the children of a Transform to match the children of another Transform
|
||||
/// </summary>
|
||||
public class HandPoser : Poser {
|
||||
|
||||
public override void AutoMapping() {
|
||||
if (poseRoot == null) poseChildren = new Transform[0];
|
||||
else poseChildren = (Transform[])poseRoot.GetComponentsInChildren<Transform>();
|
||||
|
||||
_poseRoot = poseRoot;
|
||||
}
|
||||
|
||||
protected override void InitiatePoser() {
|
||||
// Find the children
|
||||
children = (Transform[])GetComponentsInChildren<Transform>();
|
||||
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
protected override void FixPoserTransforms() {
|
||||
for (int i = 0; i < children.Length; i++) {
|
||||
children[i].localPosition = defaultLocalPositions[i];
|
||||
children[i].localRotation = defaultLocalRotations[i];
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdatePoser() {
|
||||
if (weight <= 0f) return;
|
||||
if (localPositionWeight <= 0f && localRotationWeight <= 0f) return;
|
||||
|
||||
// Get the children, if we don't have them already
|
||||
if (_poseRoot != poseRoot) AutoMapping();
|
||||
|
||||
if (poseRoot == null) return;
|
||||
|
||||
// Something went wrong
|
||||
if (children.Length != poseChildren.Length) {
|
||||
Warning.Log("Number of children does not match with the pose", transform);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate weights
|
||||
float rW = localRotationWeight * weight;
|
||||
float pW = localPositionWeight * weight;
|
||||
|
||||
// Lerping the localRotation and the localPosition
|
||||
for (int i = 0; i < children.Length; i++) {
|
||||
if (children[i] != transform) {
|
||||
children[i].localRotation = Quaternion.Lerp(children[i].localRotation, poseChildren[i].localRotation, rW);
|
||||
children[i].localPosition = Vector3.Lerp(children[i].localPosition, poseChildren[i].localPosition, pW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void StoreCurrentPose()
|
||||
{
|
||||
lerpLocalPositions = new Vector3[children.Length];
|
||||
lerpLocalRotations = new Quaternion[children.Length];
|
||||
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
{
|
||||
lerpLocalPositions[i] = children[i].localPosition;
|
||||
lerpLocalRotations[i] = children[i].localRotation;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BlendFromLastPose(float lerpTimer)
|
||||
{
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
{
|
||||
children[i].localPosition = Vector3.Lerp(lerpLocalPositions[i], children[i].localPosition, lerpTimer);
|
||||
children[i].localRotation = Quaternion.Lerp(lerpLocalRotations[i], children[i].localRotation, lerpTimer);
|
||||
}
|
||||
}
|
||||
|
||||
protected Transform[] children;
|
||||
|
||||
private Transform _poseRoot;
|
||||
private Transform[] poseChildren;
|
||||
private Vector3[] defaultLocalPositions;
|
||||
private Quaternion[] defaultLocalRotations;
|
||||
private Vector3[] lerpLocalPositions;
|
||||
private Quaternion[] lerpLocalRotations;
|
||||
|
||||
protected void StoreDefaultState() {
|
||||
defaultLocalPositions = new Vector3[children.Length];
|
||||
defaultLocalRotations = new Quaternion[children.Length];
|
||||
|
||||
for (int i = 0; i < children.Length; i++) {
|
||||
defaultLocalPositions[i] = children[i].localPosition;
|
||||
defaultLocalRotations[i] = children[i].localRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a98c3501ec8dc43c8a64321bd55c3f63
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
127
Unity-Master/Assets/Plugins/RootMotion/FinalIK/Posers/Poser.cs
Normal file
127
Unity-Master/Assets/Plugins/RootMotion/FinalIK/Posers/Poser.cs
Normal file
@ -0,0 +1,127 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace RootMotion.FinalIK {
|
||||
|
||||
/// <summary>
|
||||
/// The base abstract class for all class that are translating a hierarchy of bones to match the translation of bones in another hierarchy.
|
||||
/// </summary>
|
||||
public abstract class Poser: SolverManager {
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the other Transform (should be identical to this one)
|
||||
/// </summary>
|
||||
public Transform poseRoot;
|
||||
/// <summary>
|
||||
/// The master weight.
|
||||
/// </summary>
|
||||
[Range(0f, 1f)] public float weight = 1f;
|
||||
/// <summary>
|
||||
/// Weight of localRotation matching
|
||||
/// </summary>
|
||||
[Range(0f, 1f)] public float localRotationWeight = 1f;
|
||||
/// <summary>
|
||||
/// Weight of localPosition matching
|
||||
/// </summary>
|
||||
[Range(0f, 1f)] public float localPositionWeight;
|
||||
|
||||
/// <summary>
|
||||
/// Map this instance to the poseRoot.
|
||||
/// </summary>
|
||||
public abstract void AutoMapping();
|
||||
public virtual void AutoMapping(Transform[] bones) { }
|
||||
|
||||
/// <summary>
|
||||
/// For manual update of the poser.
|
||||
/// </summary>
|
||||
public void UpdateManual(float deltaTime) {
|
||||
|
||||
UpdatePoser();
|
||||
UpdateLerping(deltaTime);
|
||||
if (storeCurrentPoseFlag) OnStoreCurrentPoseFlag();
|
||||
}
|
||||
|
||||
public void SetPoseRoot(Transform newPoseRoot, Transform[] autoMappingBones, float blendSpeed)
|
||||
{
|
||||
this.blendSpeed = blendSpeed;
|
||||
|
||||
if (newPoseRoot != null && poseRoot != null && weight > 0f)
|
||||
{
|
||||
nextPoseRoot = newPoseRoot;
|
||||
this.autoMappingBones = autoMappingBones;
|
||||
storeCurrentPoseFlag = true;
|
||||
} else
|
||||
{
|
||||
poseRoot = newPoseRoot;
|
||||
AutoMapping(autoMappingBones);
|
||||
storeCurrentPoseFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool initiated;
|
||||
protected abstract void InitiatePoser();
|
||||
protected abstract void UpdatePoser();
|
||||
protected abstract void StoreCurrentPose();
|
||||
protected abstract void BlendFromLastPose(float lerpTimer);
|
||||
protected abstract void FixPoserTransforms();
|
||||
|
||||
protected Transform nextPoseRoot;
|
||||
protected bool storeCurrentPoseFlag;
|
||||
private bool isLerping;
|
||||
private float lerpTimer;
|
||||
private Transform[] autoMappingBones = new Transform[0];
|
||||
private float blendSpeed;
|
||||
|
||||
private void UpdateLerping(float deltaTime)
|
||||
{
|
||||
if (!isLerping) return;
|
||||
|
||||
lerpTimer = Mathf.MoveTowards(lerpTimer, 1f, deltaTime * blendSpeed);
|
||||
BlendFromLastPose(lerpTimer);
|
||||
|
||||
if (lerpTimer >= 1f)
|
||||
{
|
||||
isLerping = false;
|
||||
lerpTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the solver. If you need full control of the execution order of your IK solvers, disable this script and call UpdateSolver() instead.
|
||||
* */
|
||||
protected override void UpdateSolver() {
|
||||
if (!initiated) InitiateSolver();
|
||||
if (!initiated) return;
|
||||
|
||||
UpdatePoser();
|
||||
UpdateLerping(Time.deltaTime);
|
||||
if (storeCurrentPoseFlag) OnStoreCurrentPoseFlag();
|
||||
}
|
||||
|
||||
private void OnStoreCurrentPoseFlag()
|
||||
{
|
||||
StoreCurrentPose();
|
||||
isLerping = true;
|
||||
lerpTimer = 0f;
|
||||
poseRoot = nextPoseRoot;
|
||||
AutoMapping(autoMappingBones);
|
||||
nextPoseRoot = null;
|
||||
|
||||
storeCurrentPoseFlag = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiates the %IK solver
|
||||
* */
|
||||
protected override void InitiateSolver() {
|
||||
if (initiated) return;
|
||||
InitiatePoser();
|
||||
initiated = true;
|
||||
}
|
||||
|
||||
protected override void FixTransforms() {
|
||||
if (!initiated) return;
|
||||
FixPoserTransforms();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c8218556cda043adb17da42f8151df0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,175 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace RootMotion.FinalIK
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Posing the children of a Transform to match the children of another Transform that has different bone orientations.
|
||||
/// </summary>
|
||||
public class UniversalPoser : Poser
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Mapping a bone to its target
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class Map
|
||||
{
|
||||
public Transform bone;
|
||||
[HideInInspector]
|
||||
public Transform target;
|
||||
|
||||
private Vector3 defaultLocalPosition;
|
||||
private Quaternion defaultLocalRotation;
|
||||
|
||||
private Vector3 lerpLocalPosition;
|
||||
private Quaternion lerpLocalRotation;
|
||||
|
||||
|
||||
// Custom constructor
|
||||
public Map(Transform bone, Transform target)
|
||||
{
|
||||
this.bone = bone;
|
||||
this.target = target;
|
||||
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
public void StoreDefaultState()
|
||||
{
|
||||
defaultLocalPosition = bone.localPosition;
|
||||
defaultLocalRotation = bone.localRotation;
|
||||
}
|
||||
|
||||
public void StoreCurrentPose()
|
||||
{
|
||||
lerpLocalPosition = bone.localPosition;
|
||||
lerpLocalRotation = bone.localRotation;
|
||||
}
|
||||
|
||||
|
||||
public void FixTransform()
|
||||
{
|
||||
bone.localPosition = defaultLocalPosition;
|
||||
bone.localRotation = defaultLocalRotation;
|
||||
}
|
||||
|
||||
// Update mapping
|
||||
public void Update(float localRotationWeight, float localPositionWeight, Vector3 targetAxis1, Vector3 targetAxis2, Vector3 axis1, Vector3 axis2)
|
||||
{
|
||||
if (targetAxis1 == axis1 && targetAxis2 == axis2)
|
||||
{
|
||||
bone.localRotation = Quaternion.Lerp(bone.localRotation, target.localRotation, localRotationWeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
Quaternion r = Quaternion.Lerp(bone.localRotation, QuaTools.MatchRotation(target.localRotation, targetAxis1, targetAxis2, axis1, axis2), localRotationWeight);
|
||||
Quaternion c = QuaTools.MatchRotation(Quaternion.identity, targetAxis1, targetAxis2, axis1, axis2);
|
||||
bone.localRotation = c * r;
|
||||
}
|
||||
|
||||
//bone.localPosition = Vector3.Lerp(bone.localPosition, target.localPosition, localPositionWeight); //TODO
|
||||
}
|
||||
|
||||
public void BlendFromLastPose(float lerpTimer)
|
||||
{
|
||||
bone.localPosition = Vector3.Lerp(lerpLocalPosition, bone.localPosition, lerpTimer);
|
||||
bone.localRotation = Quaternion.Lerp(lerpLocalRotation, bone.localRotation, lerpTimer);
|
||||
}
|
||||
}
|
||||
|
||||
[Tooltip("Choose 2 axes of a finger bone. For example 1 pointing towards the next finger and 2 pointing up. Select a finger bone in the InteractionTarget hierarchy and see which local axis points towards the next bone and which local axis points up and set targetAxis1 and targetAxis2 accordingly. Then select a finger in this poser's hierarchy and do the same for axis1 and axis2.")]
|
||||
public Vector3 targetAxis1 = Vector3.forward, targetAxis2 = Vector3.up, axis1 = Vector3.forward, axis2 = Vector3.up;
|
||||
[Tooltip("List of bones must match InteractionTarget's list of bones in both array size and hierarchy.")]
|
||||
public Map[] bones;
|
||||
|
||||
public override void AutoMapping() {}
|
||||
|
||||
public override void AutoMapping(Transform[] bones)
|
||||
{
|
||||
if (bones.Length != this.bones.Length)
|
||||
{
|
||||
Debug.LogError("Trying to use UniversalPoser with an InteractionTarget that has a different number of bones. Bones must match with UniversalPoser bones in both array size and hierarchy", transform);
|
||||
Debug.LogError("InterqactionTarget.bones: " + bones.Length);
|
||||
for (int i = 0; i < bones.Length; i++)
|
||||
{
|
||||
Debug.LogError(" " + i + ": " + bones[i].name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.bones.Length; i++)
|
||||
{
|
||||
this.bones[i].target = bones[i];
|
||||
}
|
||||
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
protected override void InitiatePoser()
|
||||
{
|
||||
StoreDefaultState();
|
||||
}
|
||||
|
||||
protected override void UpdatePoser()
|
||||
{
|
||||
if (weight <= 0f) return;
|
||||
if (localPositionWeight <= 0f && localRotationWeight <= 0f) return;
|
||||
if (poseRoot == null) return;
|
||||
|
||||
// Calculate weights
|
||||
float rW = localRotationWeight * weight;
|
||||
float pW = localPositionWeight * weight;
|
||||
|
||||
// Lerping the localRotation and the localPosition
|
||||
for (int i = 0; i < bones.Length; i++) bones[i].Update(rW, pW, targetAxis1, targetAxis2, axis1, axis2);
|
||||
}
|
||||
|
||||
protected override void StoreCurrentPose()
|
||||
{
|
||||
for (int i = 0; i < bones.Length; i++)
|
||||
{
|
||||
bones[i].StoreCurrentPose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BlendFromLastPose(float lerpTimer)
|
||||
{
|
||||
for (int i = 0; i < bones.Length; i++)
|
||||
{
|
||||
bones[i].BlendFromLastPose(lerpTimer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void FixPoserTransforms()
|
||||
{
|
||||
for (int i = 0; i < bones.Length; i++)
|
||||
{
|
||||
bones[i].FixTransform();
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreDefaultState()
|
||||
{
|
||||
for (int i = 0; i < bones.Length; i++)
|
||||
{
|
||||
bones[i].StoreDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a Transform from the array that has the specified name
|
||||
private Transform GetTargetNamed(string tName, Transform[] array)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i].name == tName) return array[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c38faaae4d939647ae12f04b96e8ef3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user