140 lines
5.5 KiB
C#
140 lines
5.5 KiB
C#
/* InstantVR Movements
|
|
* author: Pascal Serrarnes
|
|
* email: support@passervr.com
|
|
* version: 3.0.8
|
|
* date: June 26, 2015
|
|
*
|
|
*/
|
|
|
|
using UnityEngine;
|
|
|
|
namespace Passer.Humanoid {
|
|
|
|
public abstract class Movements {
|
|
public Movements() { }
|
|
|
|
public virtual void Start(HumanoidControl _humanoid, HumanoidTarget _target) {
|
|
}
|
|
|
|
private static float maxAngularSpeed = 360;
|
|
|
|
protected Quaternion LimitRotationSpeed(Quaternion oldRotation, Quaternion newRotation, float thisMaxAngularSpeed) {
|
|
newRotation = Quaternion.RotateTowards(oldRotation, newRotation, maxAngularSpeed * Time.deltaTime);
|
|
return newRotation;
|
|
}
|
|
|
|
//float last;
|
|
protected Quaternion MeasureRotationSpeed(Quaternion oldRotation, Quaternion newRotation) {
|
|
//Debug.Log(maxAngularSpeed * Time.deltaTime + ": "+ Quaternion.Angle(oldRotation, newRotation) + " T " + newRotation.eulerAngles);
|
|
//last = Time.time;
|
|
return newRotation;
|
|
}
|
|
protected static Quaternion LimitRotationSpeed(Quaternion oldRotation, Quaternion newRotation) {
|
|
newRotation = Quaternion.RotateTowards(oldRotation, newRotation, maxAngularSpeed * Time.deltaTime);
|
|
return newRotation;
|
|
}
|
|
|
|
protected static Quaternion LimitAngle(HumanoidTarget.TargetedBone targetedBone, ref Quaternion lastLocalBoneRotation, Quaternion boneRotation) {
|
|
if (targetedBone.parent == null || targetedBone.parent.bone.transform == null)
|
|
return boneRotation;
|
|
|
|
Quaternion parentRotation = targetedBone.parent.bone.targetRotation;
|
|
Quaternion localRotation = Quaternion.Inverse(parentRotation) * boneRotation;
|
|
|
|
float lastAngle = Quaternion.Angle(Quaternion.identity, lastLocalBoneRotation);
|
|
float angle = Quaternion.Angle(parentRotation, boneRotation);
|
|
if (angle < lastAngle) {
|
|
// Decreasing angle
|
|
|
|
// No damping or limit
|
|
|
|
lastLocalBoneRotation = localRotation;
|
|
return boneRotation;
|
|
|
|
} else {
|
|
// Increasing angle
|
|
Quaternion deltaLocalRotation = Quaternion.Inverse(lastLocalBoneRotation) * localRotation;
|
|
|
|
// Damping tension based limit
|
|
float tension = targetedBone.GetTension();
|
|
float f = Mathf.Clamp01(1 - tension * tension);
|
|
deltaLocalRotation = Quaternion.Slerp(Quaternion.identity, deltaLocalRotation, f);
|
|
lastLocalBoneRotation = lastLocalBoneRotation * deltaLocalRotation;
|
|
|
|
// Hard limit
|
|
lastLocalBoneRotation = Quaternion.RotateTowards(Quaternion.identity, lastLocalBoneRotation, targetedBone.bone.maxAngle);
|
|
|
|
return parentRotation * lastLocalBoneRotation;
|
|
}
|
|
}
|
|
protected Vector3 LimitAngles(HumanoidTarget.TargetedBone bone, Vector3 angles) {
|
|
angles = UnityAngles.Clamp(angles, bone.bone.minAngles, bone.bone.maxAngles);
|
|
return angles;
|
|
}
|
|
|
|
public static void ClampRotation(Transform bone, Quaternion referenceRotation, Vector3 ROMnegative, Vector3 ROMpositive) {
|
|
Quaternion localRotation = Quaternion.Inverse(referenceRotation) * bone.rotation;
|
|
Vector3 localEuler = localRotation.eulerAngles;
|
|
|
|
localRotation = Quaternion.Euler(
|
|
Mathf.Clamp(Angle180(localEuler.x), ROMnegative.x, ROMpositive.x),
|
|
Mathf.Clamp(Angle180(localEuler.y), ROMnegative.y, ROMpositive.y),
|
|
Mathf.Clamp(Angle180(localEuler.z), ROMnegative.z, ROMpositive.z));
|
|
|
|
bone.rotation = referenceRotation * localRotation;
|
|
}
|
|
|
|
public static Vector3 MuscleTension(Transform bone, Quaternion referenceRotation, Vector3 ROMnegative, Vector3 ROMpositive) {
|
|
Quaternion localRotation = Quaternion.Inverse(referenceRotation) * bone.rotation;
|
|
Vector3 localEuler = localRotation.eulerAngles;
|
|
|
|
Vector3 tension = new Vector3(
|
|
AxisTension(Angle180(localEuler.x), ROMnegative.x, ROMpositive.x),
|
|
AxisTension(Angle180(localEuler.y), ROMnegative.y, ROMpositive.y),
|
|
AxisTension(Angle180(localEuler.z), ROMnegative.z, ROMpositive.z));
|
|
|
|
return tension;
|
|
}
|
|
|
|
private static float AxisTension(float angle, float ROMnegative, float ROMpositive) {
|
|
return AxisTension(angle, ROMnegative, ROMpositive, 1);
|
|
}
|
|
|
|
private static float AxisTension(float angle, float ROMnegative, float ROMpositive, float MaxTension) {
|
|
float f;
|
|
if (angle < 0)
|
|
f = angle / ROMnegative;
|
|
else {
|
|
f = angle / ROMpositive;
|
|
}
|
|
|
|
return (f * f) * MaxTension;
|
|
}
|
|
|
|
public static Vector3 Euler180(Vector3 eulerAngles) {
|
|
return new Vector3(
|
|
Angle180(eulerAngles.x),
|
|
Angle180(eulerAngles.y),
|
|
Angle180(eulerAngles.z));
|
|
}
|
|
|
|
public static float Angle180(float _angle) {
|
|
float angle = _angle;
|
|
while (angle > 180)
|
|
angle -= 360;
|
|
while (angle < -180)
|
|
angle += 360;
|
|
return angle;
|
|
}
|
|
|
|
public static float AngleDifference(float a, float b) {
|
|
float r = b - a;
|
|
while (r < -180)
|
|
r += 360;
|
|
while (r > 180)
|
|
r -= 360;
|
|
return r;
|
|
}
|
|
|
|
}
|
|
} |