mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-22 06:57:25 -05:00
Merge pull request #953 from ousttrue/feature10/aim_object_space
[1.0] aim constraint の up vector の目標空間 model/local を実装
This commit is contained in:
commit
bc1cd34114
|
|
@ -54,35 +54,34 @@ namespace UniVRM10
|
|||
|
||||
var pos = m_target.transform.position;
|
||||
|
||||
var pr = m_target.ParentRotation;
|
||||
var pr = TR.FromParent(m_target.transform);
|
||||
|
||||
if (m_target.Logic == null)
|
||||
if (m_target.m_src == null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
TR.FromWorld(m_target.transform).Draw(0.2f);
|
||||
|
||||
Handles.matrix = Matrix4x4.identity;
|
||||
var rot = Handles.RotationHandle(pr * m_target.DestinationOffset, pos);
|
||||
var rot = Handles.RotationHandle(pr.Rotation * m_target.DestinationOffset, pos);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_target, "Rotated RotateAt Point");
|
||||
m_target.DestinationOffset = Quaternion.Inverse(pr) * rot;
|
||||
m_target.DestinationOffset = Quaternion.Inverse(pr.Rotation) * rot;
|
||||
}
|
||||
|
||||
DrawAimUp(rot, pos, Color.yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
var init = m_target.ParentRotation * m_target.Logic.InitialLocalRotation;
|
||||
var init = pr.Rotation * m_target.m_src.LocalInitial.Rotation;
|
||||
DrawAimUp(init * m_target.DestinationOffset, m_target.transform.position, Color.yellow);
|
||||
new TR(init, m_target.transform.position).Draw(0.2f);
|
||||
DrawAimUp(init * m_target.DestinationOffset * m_target.Delta, m_target.transform.position, Color.magenta);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"yaw: {m_target.Yaw:0.}");
|
||||
sb.AppendLine($"pitch: {m_target.Pitch:0.}");
|
||||
Handles.Label(m_target.transform.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
// Target UPVector
|
||||
Handles.color = Color.green;
|
||||
Handles.DrawLine(m_target.transform.position, m_target.transform.position + m_target.UpVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace UniVRM10
|
|||
|
||||
public void OnSceneGUI()
|
||||
{
|
||||
if (m_target.GetSource() == null)
|
||||
if (m_target.Source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ namespace UniVRM10
|
|||
if (!Application.isPlaying)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Quaternion offset = Handles.RotationHandle(m_target.SourceOffset, m_target.GetSource().position);
|
||||
Quaternion offset = Handles.RotationHandle(m_target.SourceOffset, m_target.Source.position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_target.GetComponent(), "source offset");
|
||||
|
|
@ -78,7 +78,7 @@ namespace UniVRM10
|
|||
|
||||
// this to target line
|
||||
Handles.color = Color.yellow;
|
||||
Handles.DrawLine(m_target.GetSource().position, m_target.GetComponent().transform.position);
|
||||
Handles.DrawLine(m_target.Source.position, m_target.GetComponent().transform.position);
|
||||
|
||||
var delta = Clamp180(m_target.Delta);
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ namespace UniVRM10
|
|||
sb.AppendLine($"{delta.x:0.00}");
|
||||
sb.AppendLine($"{delta.y:0.00}");
|
||||
sb.Append($"{delta.z:0.00}");
|
||||
Handles.Label(m_target.GetSource().position, sb.ToString(), Style);
|
||||
Handles.Label(m_target.Source.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
// show dst
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace UniVRM10
|
|||
{
|
||||
// case SourceCoordinates.World: return m_transform.rotation * Quaternion.Inverse(m_initial.Rotation);
|
||||
case ObjectSpace.local: return TR.FromLocal(Source) * (LocalInitial * new TR(sourceRotationOffset)).Inverse();
|
||||
case ObjectSpace.model: return TR.FromWorld(Source) * (TR.FromWorld(ModelRoot) * ModelInitial * new TR(sourceRotationOffset)).Inverse();
|
||||
case ObjectSpace.model: return TR.FromWorld(Source) * (TR.FromParent(ModelRoot) * ModelInitial * new TR(sourceRotationOffset)).Inverse();
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +1,65 @@
|
|||
using System;
|
||||
using UniGLTF.Extensions.VRMC_node_constraint;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
/// <summary>
|
||||
/// WIP
|
||||
///
|
||||
/// Slerp(thisRot * offsetRot(Aim x Up), sourceRot, weight)
|
||||
///
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class VRM10AimConstraint : VRM10Constraint
|
||||
{
|
||||
[Header("Source")]
|
||||
[SerializeField]
|
||||
public Transform Source = default;
|
||||
Transform m_source = default;
|
||||
public override Transform Source
|
||||
{
|
||||
get => m_source;
|
||||
set => m_source = value;
|
||||
}
|
||||
|
||||
[Header("Destination")]
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
public Quaternion ParentRotation => transform.parent == null ? Quaternion.identity : transform.parent.rotation;
|
||||
ObjectSpace m_destinationCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
public Quaternion DestinationOffset = Quaternion.identity;
|
||||
|
||||
public class AimLogic
|
||||
{
|
||||
public readonly Quaternion InitialLocalRotation;
|
||||
public AimLogic(Quaternion initialLocalRotation)
|
||||
{
|
||||
InitialLocalRotation = initialLocalRotation;
|
||||
}
|
||||
}
|
||||
public AimLogic Logic { get; private set; }
|
||||
Quaternion m_delta;
|
||||
public Quaternion Delta => m_delta;
|
||||
|
||||
void Start()
|
||||
public Vector3 UpVector
|
||||
{
|
||||
if (Source == null)
|
||||
get
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
switch (m_destinationCoordinate)
|
||||
{
|
||||
case ObjectSpace.model: return ModelRoot.up;
|
||||
|
||||
if (Logic == null)
|
||||
{
|
||||
Logic = new AimLogic(transform.localRotation);
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return transform.up;
|
||||
}
|
||||
|
||||
return (TR.FromParent(transform).Rotation * m_dst.LocalInitial.Rotation) * Vector3.up;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TargetのUpdateよりも先か後かはその時による。
|
||||
/// 厳密に制御するのは無理。
|
||||
/// </summary>
|
||||
public override void Process()
|
||||
public override void OnProcess()
|
||||
{
|
||||
if (Logic == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var zAxis = (Source.position - transform.position).normalized;
|
||||
var xAxis = Vector3.Cross(Vector3.up, zAxis);
|
||||
var xAxis = Vector3.Cross(UpVector, zAxis);
|
||||
var yAxis = Vector3.Cross(zAxis, xAxis);
|
||||
var m = new Matrix4x4(xAxis, yAxis, zAxis, new Vector4(0, 0, 0, 1));
|
||||
Delta = Quaternion.Inverse(ParentRotation * Logic.InitialLocalRotation * DestinationOffset) * m.rotation;
|
||||
transform.rotation = ParentRotation * Logic.InitialLocalRotation * Delta;
|
||||
var parent = TR.FromParent(transform);
|
||||
m_delta = Quaternion.Inverse(parent.Rotation * m_src.LocalInitial.Rotation * DestinationOffset) * m.rotation;
|
||||
transform.rotation = parent.Rotation * m_src.LocalInitial.Rotation * Delta;
|
||||
}
|
||||
|
||||
public float Yaw;
|
||||
public float Pitch;
|
||||
public Quaternion Delta;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,131 @@
|
|||
using System;
|
||||
using UniGLTF.Extensions.VRMC_node_constraint;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public abstract class VRM10Constraint : MonoBehaviour
|
||||
{
|
||||
public abstract void Process();
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[SerializeField]
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
protected virtual void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (true)
|
||||
{
|
||||
current = current.parent;
|
||||
if (current.parent == null)
|
||||
{
|
||||
// root
|
||||
break;
|
||||
}
|
||||
if (current.GetComponent<VRM10Controller>() != null)
|
||||
{
|
||||
// model root
|
||||
break;
|
||||
}
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
#region Source
|
||||
public abstract Transform Source { get; set; }
|
||||
|
||||
public ConstraintSource m_src;
|
||||
|
||||
|
||||
protected TR SourceInitialCoords(ObjectSpace space)
|
||||
{
|
||||
switch (space)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
if (m_src == null)
|
||||
{
|
||||
return new TR(ModelRoot.rotation, Source.position);
|
||||
}
|
||||
else
|
||||
{
|
||||
var r = (TR.FromParent(ModelRoot) * m_src.ModelInitial).Rotation;
|
||||
var t = (TR.FromParent(Source) * m_src.LocalInitial).Translation;
|
||||
return new TR(r, t);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
if (m_src == null)
|
||||
{
|
||||
return TR.FromWorld(Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TR.FromParent(Source) * m_src.LocalInitial;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Destination
|
||||
protected ConstraintDestination m_dst;
|
||||
|
||||
protected TR DestinationInitialCoords(ObjectSpace space)
|
||||
{
|
||||
switch (space)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
if (m_dst == null)
|
||||
{
|
||||
return new TR(ModelRoot.rotation, transform.position);
|
||||
}
|
||||
else
|
||||
{
|
||||
var r = (TR.FromParent(ModelRoot) * m_dst.ModelInitial).Rotation;
|
||||
var t = (TR.FromParent(transform) * m_dst.LocalInitial).Translation;
|
||||
return new TR(r, t);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
if (m_dst == null)
|
||||
{
|
||||
return TR.FromWorld(transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TR.FromParent(transform) * m_dst.LocalInitial;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Process()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_src == null)
|
||||
{
|
||||
m_src = new ConstraintSource(Source, ModelRoot);
|
||||
}
|
||||
if (m_dst == null)
|
||||
{
|
||||
m_dst = new ConstraintDestination(transform, ModelRoot);
|
||||
}
|
||||
|
||||
OnProcess();
|
||||
}
|
||||
|
||||
public abstract void OnProcess();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ namespace UniVRM10
|
|||
switch (DestinationCoordinate)
|
||||
{
|
||||
case ObjectSpace.local:
|
||||
m_dst.ApplyLocal(m_dst.LocalInitial * new TR(DestinationOffset) * new TR(Delta));
|
||||
m_dst.ApplyLocal(DestinationInitialCoords(ObjectSpace.local) * new TR(DestinationOffset) * new TR(Delta));
|
||||
break;
|
||||
|
||||
case ObjectSpace.model:
|
||||
m_dst.ApplyModel(DestinationInitialCoords * new TR(DestinationOffset) * new TR(Delta));
|
||||
m_dst.ApplyModel(DestinationInitialCoords(ObjectSpace.model) * new TR(DestinationOffset) * new TR(Delta));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace UniVRM10
|
|||
break;
|
||||
|
||||
case ObjectSpace.model:
|
||||
m_dst.ApplyModel(DestinationInitialCoords * new TR(DestinationOffset) * new TR(Quaternion.Euler(Delta)));
|
||||
m_dst.ApplyModel(DestinationInitialCoords(ObjectSpace.model) * new TR(DestinationOffset) * new TR(Quaternion.Euler(Delta)));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -15,19 +15,15 @@ namespace UniVRM10
|
|||
set => m_freezeAxes = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[SerializeField]
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
#region Source
|
||||
[Header("Source")]
|
||||
[SerializeField]
|
||||
public Transform Source = default;
|
||||
|
||||
public Transform GetSource() => Source;
|
||||
Transform m_source = default;
|
||||
public override Transform Source
|
||||
{
|
||||
get => m_source;
|
||||
set => m_source = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
ObjectSpace m_sourceCoordinate = default;
|
||||
|
|
@ -68,38 +64,6 @@ namespace UniVRM10
|
|||
}
|
||||
#endregion
|
||||
|
||||
protected ConstraintSource m_src;
|
||||
|
||||
TR SourceModelCoords
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return TR.FromWorld(ModelRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TR.FromParent(ModelRoot) * m_src.ModelInitial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TR SourceInitialCoords
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return TR.FromWorld(Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TR.FromParent(Source) * m_src.LocalInitial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TR GetSourceCoords()
|
||||
{
|
||||
if (Source == null)
|
||||
|
|
@ -115,12 +79,14 @@ namespace UniVRM10
|
|||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(SourceModelCoords.Rotation * SourceOffset, SourceInitialCoords.Translation);
|
||||
var init = SourceInitialCoords(ObjectSpace.model);
|
||||
return new TR(init.Rotation * SourceOffset, init.Translation);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
return new TR(SourceInitialCoords.Rotation * SourceOffset, SourceInitialCoords.Translation);
|
||||
var init = SourceInitialCoords(ObjectSpace.local);
|
||||
return new TR(init.Rotation * SourceOffset, init.Translation);
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -130,38 +96,6 @@ namespace UniVRM10
|
|||
|
||||
public abstract TR GetSourceCurrent();
|
||||
|
||||
protected ConstraintDestination m_dst;
|
||||
|
||||
TR DestinationModelCoords
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_dst == null)
|
||||
{
|
||||
return TR.FromWorld(ModelRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TR.FromParent(ModelRoot) * m_dst.ModelInitial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TR DestinationInitialCoords
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_dst == null)
|
||||
{
|
||||
return TR.FromWorld(transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TR.FromParent(transform) * m_dst.LocalInitial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TR GetDstCoords()
|
||||
{
|
||||
switch (DestinationCoordinate)
|
||||
|
|
@ -172,12 +106,14 @@ namespace UniVRM10
|
|||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(DestinationModelCoords.Rotation * DestinationOffset, DestinationInitialCoords.Translation);
|
||||
var init = DestinationInitialCoords(ObjectSpace.model);
|
||||
return new TR(init.Rotation * DestinationOffset, init.Translation);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
return new TR(DestinationInitialCoords.Rotation * DestinationOffset, DestinationInitialCoords.Translation);
|
||||
var init = DestinationInitialCoords(ObjectSpace.local);
|
||||
return new TR(init.Rotation * DestinationOffset, init.Translation);
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -187,7 +123,6 @@ namespace UniVRM10
|
|||
|
||||
public abstract TR GetDstCurrent();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Editorで設定値の変更を反映するために、クリアする
|
||||
/// </summary>
|
||||
|
|
@ -204,16 +139,6 @@ namespace UniVRM10
|
|||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (current.parent != null)
|
||||
{
|
||||
current = current.parent;
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
public Component GetComponent()
|
||||
{
|
||||
return this;
|
||||
|
|
@ -224,23 +149,8 @@ namespace UniVRM10
|
|||
|
||||
protected abstract void ApplyDelta();
|
||||
|
||||
public override void Process()
|
||||
public override void OnProcess()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_src == null)
|
||||
{
|
||||
m_src = new ConstraintSource(Source, ModelRoot);
|
||||
}
|
||||
if (m_dst == null)
|
||||
{
|
||||
m_dst = new ConstraintDestination(transform, ModelRoot);
|
||||
}
|
||||
|
||||
m_delta = m_src.Delta(SourceCoordinate, SourceOffset);
|
||||
ApplyDelta();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user