mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-23 19:15:07 -05:00
Merge pull request #906 from ousttrue/feature10/constraint_read_write
Feature10/constraint read write
This commit is contained in:
@@ -54,9 +54,10 @@ namespace UniVRM10
|
||||
}
|
||||
m_root = value;
|
||||
|
||||
m_boneMap = null;
|
||||
m_springs = null;
|
||||
m_colliderGroups = null;
|
||||
m_boneMap = null;
|
||||
m_constraints = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +71,9 @@ namespace UniVRM10
|
||||
static bool s_foldColliders = true;
|
||||
public VRM10SpringBoneColliderGroup[] m_colliderGroups;
|
||||
|
||||
static bool s_foldConstraints = true;
|
||||
public VRM10Constraint[] m_constraints;
|
||||
|
||||
void Reload()
|
||||
{
|
||||
var backup = Root;
|
||||
@@ -83,13 +87,14 @@ namespace UniVRM10
|
||||
{
|
||||
Root = (Transform)EditorGUILayout.ObjectField("vrm1 root", m_root, typeof(Transform), true);
|
||||
|
||||
if (m_springs != null && m_springs.Length > 0 && m_springs[0] == null)
|
||||
if (m_springs != null && m_springs.Length > 0 && m_springs.Any(x => x == null))
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
|
||||
m_scrollPosition = EditorGUILayout.BeginScrollView(m_scrollPosition);
|
||||
|
||||
// mouse wheel scroll part 1
|
||||
var isScroll = Event.current.isScrollWheel;
|
||||
if (isScroll)
|
||||
{
|
||||
@@ -99,7 +104,10 @@ namespace UniVRM10
|
||||
m_scrollPosition = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
DrawContent();
|
||||
|
||||
// mouse wheel scroll part 2
|
||||
var bottom = EditorGUILayout.GetControlRect();
|
||||
if (isScroll)
|
||||
{
|
||||
@@ -111,6 +119,7 @@ namespace UniVRM10
|
||||
}
|
||||
Repaint();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
@@ -155,10 +164,14 @@ namespace UniVRM10
|
||||
{
|
||||
m_colliderGroups = m_root.GetComponentsInChildren<VRM10SpringBoneColliderGroup>();
|
||||
}
|
||||
if (m_constraints == null)
|
||||
{
|
||||
m_constraints = m_root.GetComponentsInChildren<VRM10Constraint>();
|
||||
}
|
||||
}
|
||||
|
||||
GUI.enabled = false;
|
||||
s_foldHumanoidBones = EditorGUILayout.Foldout(s_foldHumanoidBones, "human bones");
|
||||
s_foldHumanoidBones = EditorGUILayout.Foldout(s_foldHumanoidBones, "humanoid bones");
|
||||
if (s_foldHumanoidBones)
|
||||
{
|
||||
if (m_boneMap != null)
|
||||
@@ -197,6 +210,18 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_foldConstraints = EditorGUILayout.Foldout(s_foldConstraints, "constraints");
|
||||
if (s_foldConstraints)
|
||||
{
|
||||
if (m_constraints != null)
|
||||
{
|
||||
foreach (var c in m_constraints)
|
||||
{
|
||||
EditorGUILayout.ObjectField(c, typeof(VRM10Constraint), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace UniVRM10
|
||||
|
||||
readonly TRS m_initial;
|
||||
|
||||
public ConstraintDestination(Transform t, ObjectSpace coords)
|
||||
public ConstraintDestination(Transform t, ObjectSpace coords, Transform modelRoot = null)
|
||||
{
|
||||
m_transform = t;
|
||||
m_coords = coords;
|
||||
@@ -26,12 +26,16 @@ namespace UniVRM10
|
||||
m_initial = TRS.GetLocal(t);
|
||||
break;
|
||||
|
||||
case ObjectSpace.model:
|
||||
m_initial = TRS.GetRelative(t, modelRoot.worldToLocalMatrix);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyTranslation(Vector3 delta, float weight)
|
||||
public void ApplyTranslation(Vector3 delta, float weight, Transform modelRoot = null)
|
||||
{
|
||||
var value = m_initial.Translation + delta * weight;
|
||||
switch (m_coords)
|
||||
@@ -44,12 +48,16 @@ namespace UniVRM10
|
||||
m_transform.localPosition = value;
|
||||
break;
|
||||
|
||||
case ObjectSpace.model:
|
||||
m_transform.position = modelRoot.localToWorldMatrix.MultiplyPoint(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyRotation(Quaternion delta, float weight)
|
||||
public void ApplyRotation(Quaternion delta, float weight, Transform modelRoot = null)
|
||||
{
|
||||
// 0~1 で clamp しない slerp
|
||||
var value = Quaternion.LerpUnclamped(Quaternion.identity, delta, weight) * m_initial.Rotation;
|
||||
@@ -63,6 +71,10 @@ namespace UniVRM10
|
||||
m_transform.localRotation = value;
|
||||
break;
|
||||
|
||||
case ObjectSpace.model:
|
||||
m_transform.rotation = modelRoot.rotation * value;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -27,5 +27,15 @@ namespace UniVRM10
|
||||
Scale = t.localScale,
|
||||
};
|
||||
}
|
||||
|
||||
public static TRS GetRelative(Transform t, Matrix4x4 toRelative)
|
||||
{
|
||||
return new TRS
|
||||
{
|
||||
Translation = toRelative.MultiplyPoint(t.position),
|
||||
Rotation = toRelative.rotation * t.rotation,
|
||||
Scale = toRelative.MultiplyVector(t.lossyScale),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace UniVRM10
|
||||
[SerializeField]
|
||||
public Transform Source = default;
|
||||
|
||||
// [SerializeField]
|
||||
// [Range(0, 10.0f)]
|
||||
// float Weight = 1.0f;
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Forward
|
||||
|
||||
@@ -42,6 +42,16 @@ namespace UniVRM10
|
||||
m_dst = null;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (current.parent != null)
|
||||
{
|
||||
current = current.parent;
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
if (Source == null)
|
||||
@@ -56,11 +66,11 @@ namespace UniVRM10
|
||||
}
|
||||
if (m_dst == null)
|
||||
{
|
||||
m_dst = new ConstraintDestination(transform, DestinationCoordinate);
|
||||
m_dst = new ConstraintDestination(transform, DestinationCoordinate, ModelRoot);
|
||||
}
|
||||
|
||||
var delta = FreezeAxes.Freeze(m_src.TranslationDelta);
|
||||
m_dst.ApplyTranslation(delta, Weight);
|
||||
m_dst.ApplyTranslation(delta, Weight, ModelRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,16 @@ namespace UniVRM10
|
||||
m_dst = null;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (current.parent != null)
|
||||
{
|
||||
current = current.parent;
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SourceのUpdateよりも先か後かはその時による。
|
||||
/// 厳密に制御するのは無理。
|
||||
@@ -61,7 +71,7 @@ namespace UniVRM10
|
||||
}
|
||||
if (m_dst == null)
|
||||
{
|
||||
m_dst = new ConstraintDestination(transform, DestinationCoordinate);
|
||||
m_dst = new ConstraintDestination(transform, DestinationCoordinate, ModelRoot);
|
||||
}
|
||||
|
||||
// 軸制限をしたオイラー角
|
||||
@@ -70,7 +80,7 @@ namespace UniVRM10
|
||||
var rotation = Quaternion.Euler(fleezed);
|
||||
// Debug.Log($"{delta} => {rotation}");
|
||||
// オイラー角を再度Quaternionへ。weight を加味してSlerpする
|
||||
m_dst.ApplyRotation(rotation, Weight);
|
||||
m_dst.ApplyRotation(rotation, Weight, ModelRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,10 @@ namespace UniVRM10
|
||||
var mesh = CreateMesh(filter.sharedMesh, meshRenderer, Materials);
|
||||
Model.MeshGroups.Add(mesh);
|
||||
Nodes[renderer.gameObject].MeshGroup = mesh;
|
||||
Meshes.Add(filter.sharedMesh, mesh);
|
||||
if (!Meshes.ContainsKey(filter.sharedMesh))
|
||||
{
|
||||
Meshes.Add(filter.sharedMesh, mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,20 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone, int? thumbnailIndex) ExportVrm(GameObject root, Model model, RuntimeVrmConverter converter, VRM10MetaObject meta)
|
||||
/// <summary>
|
||||
/// VRMコンポーネントのエクスポート
|
||||
/// </summary>
|
||||
/// <param name="vrm"></param>
|
||||
/// <param name="springBone"></param>
|
||||
/// <param name="constraint"></param>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="converter"></param>
|
||||
/// <param name="meta"></param>
|
||||
/// <returns></returns>
|
||||
(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm,
|
||||
UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone,
|
||||
int? thumbnailIndex) ExportVrm(GameObject root, Model model, RuntimeVrmConverter converter, VRM10MetaObject meta)
|
||||
{
|
||||
var vrmController = root?.GetComponent<VRM10Controller>();
|
||||
|
||||
@@ -245,6 +258,7 @@ namespace UniVRM10
|
||||
ExportFirstPerson(vrm, vrmController, model, converter);
|
||||
|
||||
vrmSpringBone = ExportSpringBone(vrmController, model, converter);
|
||||
ExportConstraints(vrmController, model, converter);
|
||||
}
|
||||
|
||||
return (vrm, vrmSpringBone, thumbnailTextureIndex);
|
||||
@@ -339,6 +353,101 @@ namespace UniVRM10
|
||||
return springBone;
|
||||
}
|
||||
|
||||
void ExportConstraints(VRM10Controller vrmController, Model model, RuntimeVrmConverter converter)
|
||||
{
|
||||
var constraints = vrmController.GetComponentsInChildren<VRM10Constraint>();
|
||||
foreach (var constraint in constraints)
|
||||
{
|
||||
UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint vrmConstraint = default;
|
||||
switch (constraint)
|
||||
{
|
||||
case VRM10PositionConstraint positionConstraint:
|
||||
vrmConstraint = ExportPostionConstraint(positionConstraint, model, converter);
|
||||
break;
|
||||
|
||||
case VRM10RotationConstraint rotationConstraint:
|
||||
vrmConstraint = ExportRotationConstraint(rotationConstraint, model, converter);
|
||||
break;
|
||||
|
||||
case VRM10AimConstraint aimConstraint:
|
||||
vrmConstraint = ExportAimConstraint(aimConstraint, model, converter);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// serialize to gltfNode
|
||||
var node = converter.Nodes[constraint.gameObject];
|
||||
var nodeIndex = model.Nodes.IndexOf(node);
|
||||
var gltfNode = Storage.Gltf.nodes[nodeIndex];
|
||||
UniGLTF.Extensions.VRMC_node_constraint.GltfSerializer.SerializeTo(ref gltfNode.extensions, vrmConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
static bool[] ToArray(AxisMask mask)
|
||||
{
|
||||
return new bool[]
|
||||
{
|
||||
mask.HasFlag(AxisMask.X),
|
||||
mask.HasFlag(AxisMask.Y),
|
||||
mask.HasFlag(AxisMask.Z),
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportPostionConstraint(VRM10PositionConstraint c, Model model, RuntimeVrmConverter converter)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
|
||||
{
|
||||
Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint
|
||||
{
|
||||
Position = new UniGLTF.Extensions.VRMC_node_constraint.PositionConstraint
|
||||
{
|
||||
Source = model.Nodes.IndexOf(converter.Nodes[c.Source.gameObject]),
|
||||
SourceSpace = c.SourceCoordinate,
|
||||
DestinationSpace = c.DestinationCoordinate,
|
||||
FreezeAxes = ToArray(c.FreezeAxes),
|
||||
Weight = c.Weight,
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportRotationConstraint(VRM10RotationConstraint c, Model model, RuntimeVrmConverter converter)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
|
||||
{
|
||||
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]),
|
||||
SourceSpace = c.SourceCoordinate,
|
||||
DestinationSpace = c.DestinationCoordinate,
|
||||
FreezeAxes = ToArray(c.FreezeAxes),
|
||||
Weight = c.Weight,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportAimConstraint(VRM10AimConstraint c, Model model, RuntimeVrmConverter converter)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
|
||||
{
|
||||
Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint
|
||||
{
|
||||
Aim = new UniGLTF.Extensions.VRMC_node_constraint.AimConstraint
|
||||
{
|
||||
Source = model.Nodes.IndexOf(converter.Nodes[c.Source.gameObject]),
|
||||
AimVector = ReverseX(c.AimVector),
|
||||
UpVector = ReverseX(c.UpVector),
|
||||
Weight = c.Weight,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_vrm.MeshAnnotation ExportMeshAnnotation(RendererFirstPersonFlags flags, Func<Renderer, int> getIndex)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_vrm.MeshAnnotation
|
||||
|
||||
Reference in New Issue
Block a user