mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-28 05:44:48 -05:00
implement Constraint
This commit is contained in:
@@ -7,7 +7,7 @@ namespace UniVRM10
|
||||
/// FreezeAxesで使う。bitマスク
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum AxesMask
|
||||
public enum AxisMask
|
||||
{
|
||||
X = 1,
|
||||
Y = 2,
|
||||
@@ -16,17 +16,17 @@ namespace UniVRM10
|
||||
|
||||
public static class AxesMaskExtensions
|
||||
{
|
||||
public static Vector3 Freeze(this AxesMask mask, Vector3 src)
|
||||
public static Vector3 Freeze(this AxisMask mask, Vector3 src)
|
||||
{
|
||||
if (mask.HasFlag(AxesMask.X))
|
||||
if (mask.HasFlag(AxisMask.X))
|
||||
{
|
||||
src.x = 0;
|
||||
}
|
||||
if (mask.HasFlag(AxesMask.Y))
|
||||
if (mask.HasFlag(AxisMask.Y))
|
||||
{
|
||||
src.y = 0;
|
||||
}
|
||||
if (mask.HasFlag(AxesMask.Z))
|
||||
if (mask.HasFlag(AxisMask.Z))
|
||||
{
|
||||
src.z = 0;
|
||||
}
|
||||
|
||||
@@ -1,33 +1,28 @@
|
||||
using System;
|
||||
using UniGLTF.Extensions.VRMC_constraints;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public enum DestinationCoordinates
|
||||
{
|
||||
World,
|
||||
Local,
|
||||
}
|
||||
|
||||
class ConstraintDestination
|
||||
{
|
||||
readonly Transform m_transform;
|
||||
readonly DestinationCoordinates m_coords;
|
||||
readonly ObjectSpace m_coords;
|
||||
|
||||
readonly TRS m_initial;
|
||||
|
||||
public ConstraintDestination(Transform t, DestinationCoordinates coords)
|
||||
public ConstraintDestination(Transform t, ObjectSpace coords)
|
||||
{
|
||||
m_transform = t;
|
||||
m_coords = coords;
|
||||
|
||||
switch (m_coords)
|
||||
{
|
||||
case DestinationCoordinates.World:
|
||||
m_initial = TRS.GetWorld(t);
|
||||
break;
|
||||
// case ObjectSpace.World:
|
||||
// m_initial = TRS.GetWorld(t);
|
||||
// break;
|
||||
|
||||
case DestinationCoordinates.Local:
|
||||
case ObjectSpace.local:
|
||||
m_initial = TRS.GetLocal(t);
|
||||
break;
|
||||
|
||||
@@ -41,11 +36,11 @@ namespace UniVRM10
|
||||
var value = m_initial.Translation + delta * weight;
|
||||
switch (m_coords)
|
||||
{
|
||||
case DestinationCoordinates.World:
|
||||
m_transform.position = value;
|
||||
break;
|
||||
// case DestinationCoordinates.World:
|
||||
// m_transform.position = value;
|
||||
// break;
|
||||
|
||||
case DestinationCoordinates.Local:
|
||||
case ObjectSpace.local:
|
||||
m_transform.localPosition = value;
|
||||
break;
|
||||
|
||||
@@ -60,11 +55,11 @@ namespace UniVRM10
|
||||
var value = Quaternion.LerpUnclamped(Quaternion.identity, delta, weight) * m_initial.Rotation;
|
||||
switch (m_coords)
|
||||
{
|
||||
case DestinationCoordinates.World:
|
||||
m_transform.rotation = value;
|
||||
break;
|
||||
// case DestinationCoordinates.World:
|
||||
// m_transform.rotation = value;
|
||||
// break;
|
||||
|
||||
case DestinationCoordinates.Local:
|
||||
case ObjectSpace.local:
|
||||
m_transform.localRotation = value;
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,33 +1,16 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using UniGLTF.Extensions.VRMC_constraints;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public enum SourceCoordinates
|
||||
{
|
||||
/// <summary>
|
||||
/// ワールド座標
|
||||
/// </summary>
|
||||
World,
|
||||
|
||||
/// <summary>
|
||||
/// モデルルート(指定のTransform)ローカル座標
|
||||
/// </summary>
|
||||
Model,
|
||||
|
||||
/// <summary>
|
||||
/// m_transform ローカル座標
|
||||
/// </summary>
|
||||
Local,
|
||||
}
|
||||
|
||||
class ConstraintSource
|
||||
{
|
||||
readonly Transform m_modelRoot;
|
||||
|
||||
readonly Transform m_transform;
|
||||
|
||||
readonly SourceCoordinates m_coords;
|
||||
readonly ObjectSpace m_coords;
|
||||
|
||||
readonly TRS m_initial;
|
||||
|
||||
@@ -37,9 +20,9 @@ namespace UniVRM10
|
||||
{
|
||||
switch (m_coords)
|
||||
{
|
||||
case SourceCoordinates.World: return m_transform.position - m_initial.Translation;
|
||||
case SourceCoordinates.Local: return m_transform.localPosition - m_initial.Translation;
|
||||
case SourceCoordinates.Model: return m_modelRoot.worldToLocalMatrix.MultiplyPoint(m_transform.position) - m_initial.Translation;
|
||||
// case ObjectSpace.World: return m_transform.position - m_initial.Translation;
|
||||
case ObjectSpace.local: return m_transform.localPosition - m_initial.Translation;
|
||||
case ObjectSpace.model: return m_modelRoot.worldToLocalMatrix.MultiplyPoint(m_transform.position) - m_initial.Translation;
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -52,30 +35,30 @@ namespace UniVRM10
|
||||
switch (m_coords)
|
||||
{
|
||||
// 右からかけるか、左からかけるか、それが問題なのだ
|
||||
case SourceCoordinates.World: return m_transform.rotation * Quaternion.Inverse(m_initial.Rotation);
|
||||
case SourceCoordinates.Local: return m_transform.localRotation * Quaternion.Inverse(m_initial.Rotation);
|
||||
case SourceCoordinates.Model: return m_transform.rotation * Quaternion.Inverse(m_modelRoot.rotation) * Quaternion.Inverse(m_initial.Rotation);
|
||||
// case SourceCoordinates.World: return m_transform.rotation * Quaternion.Inverse(m_initial.Rotation);
|
||||
case ObjectSpace.local: return m_transform.localRotation * Quaternion.Inverse(m_initial.Rotation);
|
||||
case ObjectSpace.model: return m_transform.rotation * Quaternion.Inverse(m_modelRoot.rotation) * Quaternion.Inverse(m_initial.Rotation);
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConstraintSource(Transform t, SourceCoordinates coords, Transform modelRoot = null)
|
||||
public ConstraintSource(Transform t, ObjectSpace coords, Transform modelRoot = null)
|
||||
{
|
||||
m_transform = t;
|
||||
m_coords = coords;
|
||||
|
||||
switch (coords)
|
||||
{
|
||||
case SourceCoordinates.World:
|
||||
m_initial = TRS.GetWorld(t);
|
||||
break;
|
||||
// case SourceCoordinates.World:
|
||||
// m_initial = TRS.GetWorld(t);
|
||||
// break;
|
||||
|
||||
case SourceCoordinates.Local:
|
||||
case ObjectSpace.local:
|
||||
m_initial = TRS.GetLocal(t);
|
||||
break;
|
||||
|
||||
case SourceCoordinates.Model:
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
var world = TRS.GetWorld(t);
|
||||
m_modelRoot = modelRoot;
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace UniVRM10
|
||||
///
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class VRMAimConstraint : VRMConstraint
|
||||
public class VRM10AimConstraint : VRM10Constraint
|
||||
{
|
||||
[SerializeField]
|
||||
Transform Source = default;
|
||||
public Transform Source = default;
|
||||
|
||||
// [SerializeField]
|
||||
// [Range(0, 10.0f)]
|
||||
@@ -24,12 +24,13 @@ namespace UniVRM10
|
||||
/// Forward
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
Vector3 AimVector = Vector3.forward;
|
||||
public Vector3 AimVector = Vector3.forward;
|
||||
|
||||
[SerializeField]
|
||||
Vector3 UpVector = Vector3.up;
|
||||
public Vector3 UpVector = Vector3.up;
|
||||
|
||||
Vector3 RightVector;
|
||||
[SerializeField]
|
||||
public Vector3 RightVector;
|
||||
|
||||
Quaternion m_selfInitial;
|
||||
Matrix4x4 m_coords;
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f104dcf447611a4ca99f4ac41e806e8
|
||||
guid: e1e8c3a00191fbd4db98fb47ddb80e8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -2,7 +2,7 @@ using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public abstract class VRMConstraint : MonoBehaviour
|
||||
public abstract class VRM10Constraint : MonoBehaviour
|
||||
{
|
||||
public virtual void Process()
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8f13bc2bb7b6734e92bba2b204e2e49
|
||||
guid: ded8c4db12c688b46814cf0bf925cacf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using UniGLTF.Extensions.VRMC_constraints;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
@@ -6,26 +7,26 @@ namespace UniVRM10
|
||||
/// 対象の初期位置と現在位置の差分(delta)を、自身の初期位置に対してWeightを乗算して加算する。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class VRMPositionConstraint : VRMConstraint
|
||||
public class VRM10PositionConstraint : VRM10Constraint
|
||||
{
|
||||
[SerializeField]
|
||||
Transform Source = default;
|
||||
public Transform Source = default;
|
||||
|
||||
[SerializeField]
|
||||
SourceCoordinates SourceCoordinate = default;
|
||||
public ObjectSpace SourceCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
DestinationCoordinates DestinationCoordinate = default;
|
||||
public ObjectSpace DestinationCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
AxesMask FreezeAxes = default;
|
||||
public AxisMask FreezeAxes = default;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
float Weight = 1.0f;
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[SerializeField]
|
||||
Transform ModelRoot = default;
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
ConstraintSource m_src;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7e95091802973e488fdcc4b3840cdc5
|
||||
guid: 6fec0847a81b2124c9f67575d247b1f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using UniGLTF.Extensions.VRMC_constraints;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -7,26 +8,26 @@ namespace UniVRM10
|
||||
/// 対象の初期回転と現在回転の差分(delta)を、自身の初期回転と自身の初期回転にdeltaを乗算したものに対してWeightでSlerpする。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class VRMRotationConstraint : VRMConstraint
|
||||
public class VRM10RotationConstraint : VRM10Constraint
|
||||
{
|
||||
[SerializeField]
|
||||
Transform Source = default;
|
||||
public Transform Source = default;
|
||||
|
||||
[SerializeField]
|
||||
SourceCoordinates SourceCoordinate = default;
|
||||
public ObjectSpace SourceCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
DestinationCoordinates DestinationCoordinate = default;
|
||||
public ObjectSpace DestinationCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
AxesMask FreezeAxes = default;
|
||||
public AxisMask FreezeAxes = default;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
float Weight = 1.0f;
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[SerializeField]
|
||||
Transform ModelRoot = default;
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
ConstraintSource m_src;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e017e9a63d31c4e4cbcc905a0caf0605
|
||||
guid: 7a07fbecedce41b4396f286fd7634e1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -55,7 +55,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
VRMConstraint[] m_constraints;
|
||||
VRM10Constraint[] m_constraints;
|
||||
|
||||
Transform m_head;
|
||||
public Transform Head
|
||||
@@ -113,7 +113,7 @@ namespace UniVRM10
|
||||
//
|
||||
if (m_constraints == null)
|
||||
{
|
||||
m_constraints = GetComponentsInChildren<VRMConstraint>();
|
||||
m_constraints = GetComponentsInChildren<VRM10Constraint>();
|
||||
}
|
||||
foreach (var constraint in m_constraints)
|
||||
{
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace UniVRM10
|
||||
var joint = new VRM10SpringJoint(Nodes[gltfJoint.Node.Value]);
|
||||
joint.m_jointRadius = gltfJoint.HitRadius.Value;
|
||||
joint.m_dragForce = gltfJoint.DragForce.Value;
|
||||
joint.m_gravityDir = new Vector3(gltfJoint.GravityDir[0], gltfJoint.GravityDir[1], gltfJoint.GravityDir[2]);
|
||||
joint.m_gravityDir = Vector3(gltfJoint.GravityDir);
|
||||
joint.m_gravityPower = gltfJoint.GravityPower.Value;
|
||||
joint.m_stiffnessForce = gltfJoint.Stiffness.Value;
|
||||
// joint.m_exclude = gltfJoint.Exclude.GetValueOrDefault();
|
||||
@@ -368,7 +368,7 @@ namespace UniVRM10
|
||||
return new VRM10SpringBoneCollider
|
||||
{
|
||||
ColliderType = VRM10SpringBoneColliderTypes.Sphere,
|
||||
Offset = new Vector3(x.Sphere.Offset[0], x.Sphere.Offset[1], x.Sphere.Offset[2]),
|
||||
Offset = Vector3(x.Sphere.Offset),
|
||||
Radius = x.Sphere.Radius.Value,
|
||||
};
|
||||
}
|
||||
@@ -377,9 +377,9 @@ namespace UniVRM10
|
||||
return new VRM10SpringBoneCollider
|
||||
{
|
||||
ColliderType = VRM10SpringBoneColliderTypes.Capsule,
|
||||
Offset = new Vector3(x.Capsule.Offset[0], x.Capsule.Offset[1], x.Capsule.Offset[2]),
|
||||
Offset = Vector3(x.Capsule.Offset),
|
||||
Radius = x.Capsule.Radius.Value,
|
||||
Tail = new Vector3(x.Capsule.Tail[0], x.Capsule.Tail[1], x.Capsule.Tail[2]),
|
||||
Tail = Vector3(x.Capsule.Tail),
|
||||
};
|
||||
}
|
||||
else
|
||||
@@ -400,8 +400,71 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
static AxisMask FreezeAxis(bool[] flags)
|
||||
{
|
||||
var mask = default(AxisMask);
|
||||
if (flags != null && flags.Length == 3)
|
||||
{
|
||||
if (flags[0]) mask |= AxisMask.X;
|
||||
if (flags[1]) mask |= AxisMask.Y;
|
||||
if (flags[2]) mask |= AxisMask.Z;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
static Vector3 Vector3(float[] f)
|
||||
{
|
||||
var v = default(Vector3);
|
||||
if (f != null && f.Length == 3)
|
||||
{
|
||||
v.x = f[0];
|
||||
v.y = f[1];
|
||||
v.z = f[2];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
async Task LoadConstraintAsync(IAwaitCaller awaitCaller, VRM10Controller controller)
|
||||
{
|
||||
for (int i = 0; i < Parser.GLTF.nodes.Count; ++i)
|
||||
{
|
||||
var gltfNode = Parser.GLTF.nodes[i];
|
||||
if (UniGLTF.Extensions.VRMC_constraints.GltfDeserializer.TryGet(gltfNode.extensions, out UniGLTF.Extensions.VRMC_constraints.VRMC_constraints constraint))
|
||||
{
|
||||
var node = Nodes[i];
|
||||
if (constraint.Position != null)
|
||||
{
|
||||
var p = constraint.Position;
|
||||
var positionConstraint = node.gameObject.AddComponent<VRM10PositionConstraint>();
|
||||
positionConstraint.SourceCoordinate = p.SourceSpace;
|
||||
positionConstraint.Source = Nodes[p.Source.Value];
|
||||
positionConstraint.DestinationCoordinate = p.DestinationSpace;
|
||||
positionConstraint.FreezeAxes = FreezeAxis(p.FreezeAxes);
|
||||
positionConstraint.Weight = p.Weight.Value;
|
||||
positionConstraint.ModelRoot = Root.transform;
|
||||
}
|
||||
else if (constraint.Rotation != null)
|
||||
{
|
||||
var r = constraint.Rotation;
|
||||
var rotationConstraint = node.gameObject.AddComponent<VRM10RotationConstraint>();
|
||||
rotationConstraint.SourceCoordinate = r.SourceSpace;
|
||||
rotationConstraint.Source = Nodes[r.Source.Value];
|
||||
rotationConstraint.DestinationCoordinate = r.DestinationSpace;
|
||||
rotationConstraint.FreezeAxes = FreezeAxis(r.FreezeAxes);
|
||||
rotationConstraint.Weight = r.Weight.Value;
|
||||
rotationConstraint.ModelRoot = Root.transform;
|
||||
}
|
||||
else if (constraint.Aim != null)
|
||||
{
|
||||
var a = constraint.Aim;
|
||||
var aimConstraint = node.gameObject.AddComponent<VRM10AimConstraint>();
|
||||
aimConstraint.Source = Nodes[a.Source.Value];
|
||||
aimConstraint.AimVector = Vector3(a.AimVector);
|
||||
aimConstraint.UpVector = Vector3(a.UpVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await awaitCaller.NextFrame();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user