UniVRM/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs
0b5vr 610048cdcf change (1.0, constraint): Change max range of weights to 1.0
現状、仕様ではweightの最大値は1.0となっているので、UI上もこれに従うのが良いと思います。
2022-04-21 12:18:18 +09:00

81 lines
2.7 KiB
C#

using System;
using UniGLTF.Extensions.VRMC_node_constraint;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_draft/schema/VRMC_node_constraint.aimConstraint.schema.json
/// </summary>
[DisallowMultipleComponent]
public class Vrm10AimConstraint : MonoBehaviour, IVrm10Constraint
{
public GameObject GameObject => gameObject;
[SerializeField]
public Transform Source = default;
[SerializeField]
[Range(0, 1.0f)]
public float Weight = 1.0f;
[SerializeField]
public AimAxis AimAxis;
Vector3 GetAxisVector()
{
switch (AimAxis)
{
case AimAxis.PositiveX: return Vector3.right;
case AimAxis.NegativeX: return Vector3.left;
case AimAxis.PositiveY: return Vector3.up;
case AimAxis.NegativeY: return Vector3.down;
case AimAxis.PositiveZ: return Vector3.forward;
case AimAxis.NegativeZ: return Vector3.back;
default: throw new NotImplementedException();
}
}
Quaternion _dstRestLocalQuat;
void Awake()
{
if (Source == null)
{
this.enabled = false;
return;
}
_dstRestLocalQuat = transform.localRotation;
}
/// <summary>
/// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_draft/README.ja.md#example-of-implementation-1
///
/// fromVec = aimAxis.applyQuaternion( dstParentWorldQuat * dstRestQuat )
/// toVec = ( srcWorldPos - dstWorldPos ).normalized
/// fromToQuat = Quaternion.fromToRotation( fromVec, toVec )
/// targetQuat = Quaternion.slerp(
/// dstRestQuat,
/// dstParentWorldQuat.inverse * fromToQuat * dstParentWorldQuat * dstRestQuat,
/// weight
/// )
/// </summary>
public void Process()
{
if (Source == null) return;
// world coords
var dstParentWorldQuat = transform.parent != null ? transform.parent.rotation : Quaternion.identity;
var fromVec = (dstParentWorldQuat * _dstRestLocalQuat) * GetAxisVector();
var toVec = (Source.position - transform.position).normalized;
var fromToQuat = Quaternion.FromToRotation(fromVec, toVec);
transform.rotation = Quaternion.SlerpUnclamped(
_dstRestLocalQuat,
Quaternion.Inverse(dstParentWorldQuat) * fromToQuat * dstParentWorldQuat * _dstRestLocalQuat,
Weight
);
}
}
}