新仕様に合わせて旧コンポーネントを整理。Vrm10AimConstraint, Vrm10RollConstraint, VRM10RotationConstraint のコンポーネント(placeholder), Import, Export を実装

This commit is contained in:
ousttrue
2022-04-12 13:44:23 +09:00
parent 54998b3a3e
commit 325fe98980
17 changed files with 140 additions and 444 deletions

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 7b369ee7eb21d1047bb03e139faa7eda
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,32 +0,0 @@
using UnityEditor;
using UnityEngine;
namespace UniVRM10
{
public static class TRExtensions
{
public static void Draw(this TR tr, float size)
{
Handles.matrix = tr.TRS(size);
// Handles.CubeHandleCap(0, Vector3.zero, Quaternion.identity, size, EventType.Repaint);
Handles.color = Color.red;
Handles.DrawLine(Vector3.zero, Vector3.right);
Handles.color = Color.green;
Handles.DrawLine(Vector3.zero, Vector3.up);
Handles.color = Color.blue;
Handles.DrawLine(Vector3.zero, Vector3.forward);
Handles.color = Color.white;
// xy
Handles.DrawLine(Vector3.right + Vector3.up, Vector3.right);
Handles.DrawLine(Vector3.right + Vector3.up, Vector3.up);
// yz
Handles.DrawLine(Vector3.up + Vector3.forward, Vector3.forward);
Handles.DrawLine(Vector3.up + Vector3.forward, Vector3.up);
// zx
Handles.DrawLine(Vector3.forward + Vector3.right, Vector3.forward);
Handles.DrawLine(Vector3.forward + Vector3.right, Vector3.right);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f2d422c6e760aca49841f8acf44c0434
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,122 +0,0 @@
using System.Text;
using UnityEditor;
using UnityEngine;
namespace UniVRM10
{
public abstract class VRM10PositionRotationConstraintEditorBase : Editor
{
VRM10RotationPositionConstraintBase m_target;
void OnEnable()
{
m_target = (VRM10RotationPositionConstraintBase)target;
}
static GUIStyle s_style;
static GUIStyle Style
{
get
{
if (s_style == null)
{
s_style = new GUIStyle("box");
}
return s_style;
}
}
/// <summary>
/// Euler各を +- 180 にクランプする
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
static Vector3 Clamp180(Vector3 v)
{
var x = v.x;
while (x < -180) x += 360;
while (x > 180) x -= 360;
var y = v.y;
while (y < -180) y += 360;
while (y > 180) y -= 360;
var z = v.z;
while (z < -180) z += 360;
while (z > 180) z -= 360;
return new Vector3(x, y, z);
}
public void OnSceneGUI()
{
if (m_target.Source == null)
{
return;
}
// source offset
if (!Application.isPlaying)
{
EditorGUI.BeginChangeCheck();
Quaternion offset = Handles.RotationHandle(m_target.SourceOffset, m_target.Source.position);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(m_target.GetComponent(), "source offset");
m_target.SourceOffset = offset;
}
}
// dest offset
if (!Application.isPlaying)
{
EditorGUI.BeginChangeCheck();
Quaternion offset = Handles.RotationHandle(m_target.DestinationOffset, m_target.GetComponent().transform.position);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(m_target.GetComponent(), "dest offset");
m_target.DestinationOffset = offset;
}
}
// this to target line
Handles.color = Color.yellow;
Handles.DrawLine(m_target.Source.position, m_target.GetComponent().transform.position);
var delta = Clamp180(m_target.Delta);
// show source
{
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine();
sb.AppendLine($"{delta.x:0.00}");
sb.AppendLine($"{delta.y:0.00}");
sb.Append($"{delta.z:0.00}");
Handles.Label(m_target.Source.position, sb.ToString(), Style);
}
// show dst
{
var sb = new StringBuilder();
sb.AppendLine(m_target.Axes.HasFlag(AxisMask.X) ? $"{delta.x:0.00}" : "----");
sb.AppendLine(m_target.Axes.HasFlag(AxisMask.Y) ? $"{delta.y:0.00}" : "----");
sb.Append(m_target.Axes.HasFlag(AxisMask.Z) ? $"{delta.z:0.00}" : "----");
Handles.Label(m_target.GetComponent().transform.position, sb.ToString(), Style);
}
m_target.GetSourceCoords().Draw(0.2f);
if (Application.isPlaying)
{
Handles.matrix = m_target.GetSourceCurrent().TRS(0.05f);
Handles.color = Color.yellow;
Handles.DrawWireCube(Vector3.zero, Vector3.one);
}
m_target.GetDstCoords().Draw(0.2f);
if (Application.isPlaying)
{
Handles.matrix = m_target.GetDstCurrent().TRS(0.05f);
Handles.color = Color.yellow;
Handles.DrawWireCube(Vector3.zero, Vector3.one);
}
}
}
}

View File

@@ -1,9 +0,0 @@
using UnityEditor;
namespace UniVRM10
{
[CustomEditor(typeof(VRM10RotationConstraint))]
public class VRM10RotationConstraintEditor : VRM10PositionRotationConstraintEditorBase
{
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: cd4ca141215a42c45a0036791f2f8a4d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -71,7 +71,7 @@ namespace UniVRM10
Transform m_head;
public VRM10Constraint[] m_constraints;
public Vrm10Constraint[] m_constraints;
ScrollView m_scrollView = new ScrollView();
@@ -177,7 +177,7 @@ namespace UniVRM10
{
if (m_constraints == null)
{
m_constraints = Root.GetComponentsInChildren<VRM10Constraint>();
m_constraints = Root.GetComponentsInChildren<Vrm10Constraint>();
}
}
@@ -187,7 +187,7 @@ namespace UniVRM10
{
foreach (var c in m_constraints)
{
EditorGUILayout.ObjectField(c, typeof(VRM10Constraint), true);
EditorGUILayout.ObjectField(c, typeof(Vrm10Constraint), true);
}
}
}

View File

@@ -1,92 +1,9 @@
using System;
using UniGLTF.Extensions.VRMC_node_constraint;
using UnityEngine;
namespace UniVRM10
{
public abstract class VRM10Constraint : MonoBehaviour
public abstract class Vrm10Constraint : MonoBehaviour
{
[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<Vrm10Instance>() != null)
{
// model root
break;
}
}
ModelRoot = current;
}
#region Source
public abstract Transform Source { get; set; }
public ConstraintSource m_src;
protected TR SourceInitialCoords()
{
if (m_src == null)
{
return TR.FromWorld(Source);
}
else
{
return TR.FromParent(Source) * m_src.LocalInitial;
}
}
#endregion
#region Destination
protected ConstraintDestination m_dst;
protected TR DestinationInitialCoords()
{
if (m_dst == null)
{
return TR.FromWorld(transform);
}
else
{
return TR.FromParent(transform) * m_dst.LocalInitial;
}
}
#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();
public abstract void Process();
}
}

View File

@@ -1,40 +1,23 @@
using System;
using UniGLTF.Extensions.VRMC_node_constraint;
using UnityEngine;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// 対象の初期回転と現在回転の差分(delta)を、自身の初期回転と自身の初期回転にdeltaを乗算したものに対してWeightでSlerpする。
/// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_draft/schema/VRMC_node_constraint.rotationConstraint.schema.json
/// </summary>
[DisallowMultipleComponent]
public class VRM10RotationConstraint : VRM10RotationPositionConstraintBase
public class Vrm10RotationConstraint : Vrm10Constraint
{
public override Vector3 Delta => Axes.Mask(Quaternion.Slerp(Quaternion.identity, m_delta.Rotation, Weight).eulerAngles);
[SerializeField]
public Transform Source = default;
public override TR GetSourceCurrent()
{
var coords = GetSourceCoords();
if (m_src == null)
{
return coords;
}
return coords * new TR(m_delta.Rotation);
}
[SerializeField]
[Range(0, 10.0f)]
public float Weight = 1.0f;
public override TR GetDstCurrent()
public override void Process()
{
var coords = GetDstCoords();
if (m_src == null)
{
return coords;
}
return coords * new TR(m_delta.Rotation);
}
protected override void ApplyDelta()
{
m_dst.ApplyLocal(m_dst.LocalInitial * new TR(DestinationOffset) * new TR(Quaternion.Euler(Delta)));
throw new System.NotImplementedException();
}
}
}

View File

@@ -1,105 +0,0 @@
using System;
using UniGLTF.Extensions.VRMC_node_constraint;
using UnityEngine;
namespace UniVRM10
{
public abstract class VRM10RotationPositionConstraintBase : VRM10Constraint
{
[SerializeField]
[EnumFlags]
AxisMask m_axes = AxisMask.X | AxisMask.Y | AxisMask.Z;
public AxisMask Axes
{
get => m_axes;
set => m_axes = value;
}
#region Source
[Header("Source")]
[SerializeField]
Transform m_source = default;
public override Transform Source
{
get => m_source;
set => m_source = value;
}
[SerializeField]
VRM10RotationOffset m_sourceOffset = VRM10RotationOffset.Identity;
public Quaternion SourceOffset
{
get => m_sourceOffset.Rotation;
set => m_sourceOffset.Rotation = value;
}
#endregion
#region Destination
[Header("Destination")]
[SerializeField]
public VRM10RotationOffset m_destinationOffset = VRM10RotationOffset.Identity;
public Quaternion DestinationOffset
{
get => m_destinationOffset.Rotation;
set => m_destinationOffset.Rotation = value;
}
#endregion
public TR GetSourceCoords()
{
if (Source == null)
{
throw new ConstraintException(ConstraintException.ExceptionTypes.NoSource);
}
var init = SourceInitialCoords();
return new TR(init.Rotation * SourceOffset, init.Translation);
}
public abstract TR GetSourceCurrent();
public TR GetDstCoords()
{
var init = DestinationInitialCoords();
return new TR(init.Rotation * DestinationOffset, init.Translation);
}
public abstract TR GetDstCurrent();
/// <summary>
/// Editorで設定値の変更を反映するために、クリアする
/// </summary>
void OnValidate()
{
// Debug.Log("Validate");
if (m_src != null && m_src.ModelRoot != ModelRoot)
{
m_src = null;
}
if (m_dst != null && m_dst.ModelRoot != ModelRoot)
{
m_dst = null;
}
}
public Component GetComponent()
{
return this;
}
protected TR m_delta;
public abstract Vector3 Delta { get; }
protected abstract void ApplyDelta();
public override void OnProcess()
{
m_delta = m_src.Delta(SourceOffset);
ApplyDelta();
}
}
}

View File

@@ -0,0 +1,26 @@
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 : Vrm10Constraint
{
[SerializeField]
public Transform Source = default;
[SerializeField]
[Range(0, 10.0f)]
public float Weight = 1.0f;
[SerializeField]
public UniGLTF.Extensions.VRMC_node_constraint.AimAxis AimAxis;
public override void Process()
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 07919df684c7a4c47a9492a2de417f66
guid: 37b0507e4ae49724898ca17cc3db6f1a
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,26 @@
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.rollConstraint.schema.json
/// </summary>
[DisallowMultipleComponent]
public class Vrm10RollConstraint : Vrm10Constraint
{
[SerializeField]
public Transform Source = default;
[SerializeField]
[Range(0, 10.0f)]
public float Weight = 1.0f;
[SerializeField]
public UniGLTF.Extensions.VRMC_node_constraint.RollAxis RollAxis;
public override void Process()
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 46c1f13688fee134aa37a39a72433217
guid: 1e864293edac89b40b9f79c23e7aa547
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -12,7 +12,7 @@ namespace UniVRM10
public class Vrm10Runtime : IDisposable
{
private readonly Vrm10Instance m_target;
private readonly VRM10Constraint[] m_constraints;
private readonly Vrm10Constraint[] m_constraints;
private readonly Transform m_head;
private readonly FastSpringBoneService m_fastSpringBoneService;
@@ -39,7 +39,7 @@ namespace UniVRM10
if (m_constraints == null)
{
m_constraints = target.GetComponentsInChildren<VRM10Constraint>();
m_constraints = target.GetComponentsInChildren<Vrm10Constraint>();
}
if (!Application.isPlaying)

View File

@@ -401,14 +401,43 @@ namespace UniVRM10
static void ExportConstraints(Vrm10Instance vrmController, Model model, ModelExporter converter, List<glTFNode> nodes)
{
var constraints = vrmController.GetComponentsInChildren<VRM10Constraint>();
var constraints = vrmController.GetComponentsInChildren<Vrm10Constraint>();
foreach (var constraint in constraints)
{
UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint vrmConstraint = default;
var vrmConstraint = new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
{
SpecVersion = NODE_CONSTRAINT_SPEC_VERSION,
Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint
{
},
};
switch (constraint)
{
case VRM10RotationConstraint rotationConstraint:
vrmConstraint = ExportRotationConstraint(rotationConstraint, model, converter);
case Vrm10AimConstraint aimConstraint:
vrmConstraint.Constraint.Aim = new UniGLTF.Extensions.VRMC_node_constraint.AimConstraint
{
Source = model.Nodes.IndexOf(converter.Nodes[aimConstraint.Source.gameObject]),
Weight = aimConstraint.Weight,
AimAxis = aimConstraint.AimAxis,
};
break;
case Vrm10RollConstraint rollConstraint:
vrmConstraint.Constraint.Roll = new UniGLTF.Extensions.VRMC_node_constraint.RollConstraint
{
Source = model.Nodes.IndexOf(converter.Nodes[rollConstraint.Source.gameObject]),
Weight = rollConstraint.Weight,
RollAxis = rollConstraint.RollAxis,
};
break;
case Vrm10RotationConstraint rotationConstraint:
vrmConstraint.Constraint.Rotation = new UniGLTF.Extensions.VRMC_node_constraint.RotationConstraint
{
Source = model.Nodes.IndexOf(converter.Nodes[rotationConstraint.Source.gameObject]),
Weight = rotationConstraint.Weight,
};
break;
default:
@@ -433,22 +462,6 @@ namespace UniVRM10
};
}
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportRotationConstraint(VRM10RotationConstraint c, Model model, ModelExporter converter)
{
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
{
SpecVersion = NODE_CONSTRAINT_SPEC_VERSION,
Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint
{
Rotation = new UniGLTF.Extensions.VRMC_node_constraint.RotationConstraint
{
Source = model.Nodes.IndexOf(converter.Nodes[c.Source.gameObject]),
// Axes = ToArray(c.Axes),
Weight = c.Weight,
},
},
};
}
static UniGLTF.Extensions.VRMC_vrm.MeshAnnotation ExportMeshAnnotation(RendererFirstPersonFlags flags, Transform root, Func<Renderer, int> getIndex)
{

View File

@@ -652,6 +652,17 @@ namespace UniVRM10
return v;
}
/// <summary>
/// https://github.com/vrm-c/vrm-specification/tree/master/specification/VRMC_node_constraint-1.0_draft
///
/// * roll
/// * aim
/// * rotaton
///
/// </summary>
/// <param name="awaitCaller"></param>
/// <param name="controller"></param>
/// <returns></returns>
async Task LoadConstraintAsync(IAwaitCaller awaitCaller, Vrm10Instance controller)
{
for (int i = 0; i < Data.GLTF.nodes.Count; ++i)
@@ -661,14 +672,32 @@ namespace UniVRM10
{
var constraint = ext.Constraint;
var node = Nodes[i];
if (constraint.Rotation != null)
if (constraint.Roll != null)
{
var r = constraint.Rotation;
var rotationConstraint = node.gameObject.AddComponent<VRM10RotationConstraint>();
rotationConstraint.Source = Nodes[r.Source.Value];
// rotationConstraint.Axes = ConstraintAxes(r.Axes);
rotationConstraint.Weight = r.Weight.Value;
rotationConstraint.ModelRoot = Root.transform;
var roll = constraint.Roll;
var component = node.gameObject.AddComponent<Vrm10RollConstraint>();
component.Source = Nodes[roll.Source.Value];
component.Weight = roll.Weight.Value;
component.RollAxis = roll.RollAxis;
}
else if (constraint.Aim != null)
{
var aim = constraint.Aim;
var component = node.gameObject.AddComponent<Vrm10AimConstraint>();
component.Source = Nodes[aim.Source.Value];
component.Weight = aim.Weight.Value;
component.AimAxis = aim.AimAxis;
}
else if (constraint.Rotation != null)
{
var rotation = constraint.Rotation;
var component = node.gameObject.AddComponent<Vrm10RotationConstraint>();
component.Source = Nodes[rotation.Source.Value];
component.Weight = rotation.Weight.Value;
}
else
{
throw new NotImplementedException();
}
}
}