VRM10SpringBoneManager.cs

This commit is contained in:
ousttrue
2021-01-19 19:28:55 +09:00
parent e05daa1524
commit 0484f02198
13 changed files with 285 additions and 411 deletions

View File

@@ -39,15 +39,15 @@ namespace UniVRM10
EditorUtility.SetDirty(m_target);
}
}
[MenuItem("CONTEXT/VRM10SpringBoneColliderGroup/X Mirror")]
private static void InvertOffsetX(MenuCommand command)
{
var target = command.context as VRM10SpringBoneColliderGroup;
if (target == null) return;
Undo.RecordObject(target, "X Mirror");
foreach (var sphereCollider in target.Colliders)
{
var offset = sphereCollider.Offset;
@@ -55,27 +55,27 @@ namespace UniVRM10
sphereCollider.Offset = offset;
}
}
[MenuItem("CONTEXT/VRM10SpringBoneColliderGroup/Sort Colliders by Radius")]
private static void SortByRadius(MenuCommand command)
{
var target = command.context as VRM10SpringBoneColliderGroup;
if (target == null) return;
Undo.RecordObject(target, "Sort Colliders by Radius");
target.Colliders = target.Colliders.OrderBy(x => -x.Radius).ToArray();
target.Colliders = target.Colliders.OrderBy(x => -x.Radius).ToList();
}
[MenuItem("CONTEXT/VRM10SpringBoneColliderGroup/Sort Colliders by Offset Y")]
private static void SortByOffsetY(MenuCommand command)
{
var target = command.context as VRM10SpringBoneColliderGroup;
if (target == null) return;
Undo.RecordObject(target, "Sort Colliders by Offset Y");
target.Colliders = target.Colliders.OrderBy(x => -x.Offset.y).ToArray();
target.Colliders = target.Colliders.OrderBy(x => -x.Offset.y).ToList();
}
}
}

View File

@@ -1,56 +0,0 @@
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
namespace UniVRM10
{
class VRM10SpringBoneTreeView : TreeView
{
VRM10Controller m_root;
Dictionary<int, VRM10SpringBone> m_boneMap = new Dictionary<int, VRM10SpringBone>();
public bool TryGetSpringBone(int id, out VRM10SpringBone bone)
{
return m_boneMap.TryGetValue(id, out bone);
}
public VRM10SpringBoneTreeView(TreeViewState treeViewState, VRM10Controller root)
: base(treeViewState)
{
m_root = root;
Reload();
}
protected override bool CanMultiSelect(TreeViewItem item)
{
return false;
}
protected override TreeViewItem BuildRoot()
{
m_boneMap.Clear();
var root = new TreeViewItem { id = 0, depth = -1, displayName = m_root.name };
var allItems = new List<TreeViewItem>();
var bones = m_root.GetComponentsInChildren<VRM10SpringBone>();
var id = 1;
for (int i = 0; i < bones.Length; ++i, ++id)
{
var bone = bones[i];
m_boneMap.Add(id, bone);
allItems.Add(new TreeViewItem
{
id = id,
displayName = bone.name,
});
}
// Utility method that initializes the TreeViewItem.children and -parent for all items.
SetupParentsAndChildrenFromDepths(root, allItems);
// Return root of the tree
return root;
}
}
}

View File

@@ -1,111 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace UniVRM10
{
public class VRM10SpringBoneWindow : EditorWindow
{
[MenuItem(VRMVersion.MENU + "/VRMSpringBoneWindow")]
public static void ShowEditorWindow()
{
var wnd = GetWindow<VRM10SpringBoneWindow>();
wnd.titleContent = new GUIContent("VRMSpringBoneWindow");
}
void OnEnable()
{
minSize = new Vector2(100, 100);
maxSize = new Vector2(4000, 4000);
Selection.selectionChanged += OnSelectionChanged;
}
void OnDisable()
{
Selection.selectionChanged -= OnSelectionChanged;
}
VRM10Controller m_currentRoot;
[SerializeField]
TreeViewState m_treeViewState;
VRM10SpringBoneTreeView m_treeView;
Rect m_treeRect;
Rect m_inspectorRect;
Vector2 m_inspectorScrollPos;
void OnGUI()
{
if (m_treeView is null)
{
return;
}
// bone selector
Rect fullRect = GUILayoutUtility.GetRect(0, 100000, 0, 10000);
var treeRect = new Rect(fullRect.x, fullRect.y, fullRect.width, EditorGUIUtility.singleLineHeight * 3);
var inspectorRect = new Rect(fullRect.x, treeRect.y + treeRect.height, fullRect.width, fullRect.height - treeRect.height);
if (Event.current.type == EventType.Repaint)
{
m_treeRect = treeRect;
m_inspectorRect = inspectorRect;
// Debug.Log($"{m_treeRect}, {m_inspectorRect}");
}
m_treeView.OnGUI(m_treeRect);
GUILayout.BeginArea(m_inspectorRect);
m_inspectorScrollPos = GUILayout.BeginScrollView(m_inspectorScrollPos, GUI.skin.box);
if (m_treeViewState.selectedIDs.Any())
{
// selected な SpringBone の Inspector を描画する
if (m_treeView.TryGetSpringBone(m_treeViewState.selectedIDs[0], out VRM10SpringBone bone))
{
// Debug.Log(bone);
using (var inspector = new CustomInspector(new SerializedObject(bone)))
{
inspector.OnInspectorGUI();
}
}
}
GUILayout.EndScrollView();
GUILayout.EndArea();
}
void OnSelectionChanged()
{
var go = Selection.activeObject as GameObject;
if (go is null)
{
return;
}
var meta = go.GetComponentInParent<VRM10Controller>();
if (meta == m_currentRoot)
{
return;
}
m_currentRoot = meta;
if (m_currentRoot is null)
{
m_treeViewState = null;
m_treeView = null;
}
else
{
// update treeview
Debug.Log(m_currentRoot);
m_treeViewState = new TreeViewState();
m_treeView = new VRM10SpringBoneTreeView(m_treeViewState, m_currentRoot);
}
Repaint();
}
}
}

View File

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

View File

@@ -53,11 +53,12 @@ namespace UniVRM10
{
m_metaEditor = Editor.CreateEditor(m_target.Meta);
}
m_controller = serializedObject.FindProperty(nameof(m_target.Controller));
m_expression = serializedObject.FindProperty(nameof(m_target.Expression));
m_lookAt = serializedObject.FindProperty(nameof(m_target.LookAt));
m_firstPerson = serializedObject.FindProperty(nameof(m_target.FirstPerson));
m_asset = serializedObject.FindProperty(nameof(m_target.ModelAsset));
m_controller = PropGui.FromObject(serializedObject, nameof(m_target.Controller));
m_expression = PropGui.FromObject(serializedObject, nameof(m_target.Expression));
m_lookAt = PropGui.FromObject(serializedObject, nameof(m_target.LookAt));
m_firstPerson = PropGui.FromObject(serializedObject, nameof(m_target.FirstPerson));
m_springBone = PropGui.FromObject(serializedObject, nameof(m_target.SpringBone));
m_asset = PropGui.FromObject(serializedObject, nameof(m_target.ModelAsset));
}
void OnDisable()
@@ -76,16 +77,51 @@ namespace UniVRM10
Expression,
LookAt,
FirstPerson,
SpringBone,
Assets,
}
Tabs _tab;
Editor m_metaEditor;
SerializedProperty m_controller;
SerializedProperty m_expression;
SerializedProperty m_lookAt;
SerializedProperty m_firstPerson;
SerializedProperty m_asset;
class PropGui
{
SerializedProperty m_prop;
PropGui(SerializedProperty property)
{
m_prop = property;
}
public static PropGui FromObject(SerializedObject serializedObject, string name)
{
var prop = serializedObject.FindProperty(name);
return new PropGui(prop);
}
public void RecursiveProperty()
{
var depth = m_prop.depth;
var iterator = m_prop.Copy();
for (var enterChildren = true; iterator.NextVisible(enterChildren); enterChildren = false)
{
if (iterator.depth < depth)
return;
depth = iterator.depth;
using (new EditorGUI.DisabledScope("m_Script" == iterator.propertyPath))
EditorGUILayout.PropertyField(iterator, true);
}
}
}
PropGui m_controller;
PropGui m_expression;
PropGui m_lookAt;
PropGui m_firstPerson;
PropGui m_springBone;
PropGui m_asset;
public override void OnInspectorGUI()
{
@@ -109,24 +145,28 @@ namespace UniVRM10
break;
case Tabs.Controller:
RecursiveProperty(m_controller);
m_controller.RecursiveProperty();
break;
case Tabs.Expression:
ExpressionGUI();
RecursiveProperty(m_expression);
m_expression.RecursiveProperty();
break;
case Tabs.LookAt:
RecursiveProperty(m_lookAt);
m_lookAt.RecursiveProperty();
break;
case Tabs.FirstPerson:
RecursiveProperty(m_firstPerson);
m_firstPerson.RecursiveProperty();
break;
case Tabs.SpringBone:
m_springBone.RecursiveProperty();
break;
case Tabs.Assets:
RecursiveProperty(m_asset);
m_asset.RecursiveProperty();
break;
}
@@ -164,22 +204,6 @@ namespace UniVRM10
}
}
static void RecursiveProperty(SerializedProperty property)
{
var depth = property.depth;
var iterator = property.Copy();
for (var enterChildren = true; iterator.NextVisible(enterChildren); enterChildren = false)
{
if (iterator.depth < depth)
return;
depth = iterator.depth;
using (new EditorGUI.DisabledScope("m_Script" == iterator.propertyPath))
EditorGUILayout.PropertyField(iterator, true);
}
}
void OnSceneGUI()
{
OnSceneGUIOffset();

View File

@@ -8,11 +8,8 @@ namespace UniVRM10
/// The base algorithm is http://rocketjump.skr.jp/unity3d/109/ of @ricopin416
/// DefaultExecutionOrder(11000) means calculate springbone after FinalIK( VRIK )
/// </summary>
[AddComponentMenu("VRM10/VRM10SpringBone")]
#if UNITY_5_5_OR_NEWER
[DefaultExecutionOrder(11000)]
#endif
public class VRM10SpringBone : MonoBehaviour
[Serializable]
public class VRM10SpringBone
{
[SerializeField]
public string m_comment;
@@ -49,7 +46,7 @@ namespace UniVRM10
public List<VRM10SpringJoint> Joints = new List<VRM10SpringJoint>();
[SerializeField]
public VRM10SpringBoneColliderGroup[] ColliderGroups;
public List<VRM10SpringBoneColliderGroup> ColliderGroups = new List<VRM10SpringBoneColliderGroup>();
SpringBoneProcessor m_processor = new SpringBoneProcessor();

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using UnityEngine;
@@ -10,14 +11,18 @@ namespace UniVRM10
[AddComponentMenu("VRM10/VRM10SpringBoneColliderGroup")]
public class VRM10SpringBoneColliderGroup : MonoBehaviour
{
[SerializeField]
public VRM10SpringBoneCollider[] Colliders = new VRM10SpringBoneCollider[]{
new VRM10SpringBoneCollider
void Reset()
{
// default shape
Colliders.Add(new VRM10SpringBoneCollider
{
ColliderType = VRM10SpringBoneColliderTypes.Capsule,
Radius=0.1f
}
};
Radius = 0.1f
});
}
[SerializeField]
public List<VRM10SpringBoneCollider> Colliders = new List<VRM10SpringBoneCollider>();
public static void DrawWireCapsule(Vector3 headPos, Vector3 tailPos, float radius)
{

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// すべての SpringBone を管理する。
/// Humanoid 一体につきひとつだけ存在する。
/// </summary>
[Serializable]
public class VRM10SpringBoneManager
{
[SerializeField]
public List<VRM10SpringBone> Springs = new List<VRM10SpringBone>();
/// <summary>
/// 1フレームに一回呼び出す(VRM10Controllerの仕事)
/// </summary>
public void Process()
{
foreach (var spring in Springs)
{
spring.Process();
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c012308d77f262b4789f2fee6cdb7105
guid: d09e28f7198c42d42bb31fd40e164b2d
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -15,16 +15,16 @@ namespace UniVRM10
[DisallowMultipleComponent]
public class VRM10Controller : MonoBehaviour
{
public enum UpdateTypes
{
None,
Update,
LateUpdate,
}
[Serializable]
public class VRM10ControllerImpl
{
public enum UpdateTypes
{
None,
Update,
LateUpdate,
}
[SerializeField, Header("UpdateSetting")]
public UpdateTypes UpdateType = UpdateTypes.LateUpdate;
}
@@ -44,6 +44,9 @@ namespace UniVRM10
[SerializeField]
public VRM10ControllerFirstPerson FirstPerson = new VRM10ControllerFirstPerson();
[SerializeField]
public VRM10SpringBoneManager SpringBone = new VRM10SpringBoneManager();
[SerializeField]
public ModelAsset ModelAsset;
@@ -62,7 +65,6 @@ namespace UniVRM10
}
VRMConstraint[] m_constraints;
VRM10SpringBone[] m_springs;
Transform m_head;
public Transform Head
@@ -133,14 +135,7 @@ namespace UniVRM10
//
// spring
//
if (m_springs == null)
{
m_springs = GetComponentsInChildren<VRM10SpringBone>();
}
foreach (var spring in m_springs)
{
spring.Process();
}
SpringBone.Process();
//
// expression
@@ -160,7 +155,7 @@ namespace UniVRM10
private void Update()
{
if (Controller.UpdateType == UpdateTypes.Update)
if (Controller.UpdateType == VRM10ControllerImpl.UpdateTypes.Update)
{
Apply();
}
@@ -168,7 +163,7 @@ namespace UniVRM10
private void LateUpdate()
{
if (Controller.UpdateType == UpdateTypes.LateUpdate)
if (Controller.UpdateType == VRM10ControllerImpl.UpdateTypes.LateUpdate)
{
Apply();
}

View File

@@ -232,67 +232,67 @@ namespace UniVRM10
// springBone
{
var colliders = new Dictionary<VrmLib.SpringBoneColliderGroup, UniVRM10.VRM10SpringBoneColliderGroup>();
if (model.Vrm.SpringBone != null)
{
foreach (var colliderGroup in model.Vrm.SpringBone.Springs.SelectMany(x => x.Colliders))
{
var go = asset.Map.Nodes[colliderGroup.Node];
var springBoneColliderGroup = go.AddComponent<UniVRM10.VRM10SpringBoneColliderGroup>();
springBoneColliderGroup.Colliders = colliderGroup.Colliders.Select(x =>
{
switch (x.ColliderType)
{
case VrmLib.VrmSpringBoneColliderTypes.Sphere:
return new UniVRM10.VRM10SpringBoneCollider()
{
ColliderType = VRM10SpringBoneColliderTypes.Sphere,
Offset = x.Offset.ToUnityVector3(),
Radius = x.Radius
};
case VrmLib.VrmSpringBoneColliderTypes.Capsule:
return new UniVRM10.VRM10SpringBoneCollider()
{
ColliderType = VRM10SpringBoneColliderTypes.Capsule,
Offset = x.Offset.ToUnityVector3(),
Radius = x.Radius,
Tail = x.CapsuleTail.ToUnityVector3(),
};
default:
throw new NotImplementedException();
}
}).ToArray(); ;
colliders.Add(colliderGroup, springBoneColliderGroup);
}
}
GameObject springBoneObject = null;
var springBoneTransform = asset.Root.transform.GetChildren().FirstOrDefault(x => x.name == "SpringBone");
if (springBoneTransform == null)
{
springBoneObject = new GameObject("SpringBone");
}
else
{
springBoneObject = springBoneTransform.gameObject;
}
springBoneObject.transform.SetParent(asset.Root.transform);
if (model.Vrm.SpringBone != null)
{
foreach (var vrmSpring in model.Vrm.SpringBone.Springs)
{
var springBone = springBoneObject.AddComponent<UniVRM10.VRM10SpringBone>();
// create a spring
var springBone = new UniVRM10.VRM10SpringBone();
springBone.m_comment = vrmSpring.Comment;
if (vrmSpring.Origin != null && asset.Map.Nodes.TryGetValue(vrmSpring.Origin, out GameObject origin))
{
springBone.m_center = origin.transform;
}
controller.SpringBone.Springs.Add(springBone);
// create colliders for the spring
foreach (var vrmSpringBoneCollider in vrmSpring.Colliders)
{
var go = asset.Map.Nodes[vrmSpringBoneCollider.Node];
var springBoneColliderGroup = go.GetComponent<UniVRM10.VRM10SpringBoneColliderGroup>();
if (springBoneColliderGroup != null)
{
// already setup
}
else
{
// new collider
springBoneColliderGroup = go.AddComponent<UniVRM10.VRM10SpringBoneColliderGroup>();
// add collider shapes
springBoneColliderGroup.Colliders.Clear();
foreach (var x in vrmSpringBoneCollider.Colliders)
{
switch (x.ColliderType)
{
case VrmLib.VrmSpringBoneColliderTypes.Sphere:
springBoneColliderGroup.Colliders.Add(new UniVRM10.VRM10SpringBoneCollider()
{
ColliderType = VRM10SpringBoneColliderTypes.Sphere,
Offset = x.Offset.ToUnityVector3(),
Radius = x.Radius
});
break;
case VrmLib.VrmSpringBoneColliderTypes.Capsule:
springBoneColliderGroup.Colliders.Add(new UniVRM10.VRM10SpringBoneCollider()
{
ColliderType = VRM10SpringBoneColliderTypes.Capsule,
Offset = x.Offset.ToUnityVector3(),
Radius = x.Radius,
Tail = x.CapsuleTail.ToUnityVector3(),
});
break;
default:
throw new NotImplementedException();
}
}
}
springBone.ColliderGroups.Add(springBoneColliderGroup);
}
// create joint for the spring
foreach (var vrmJoint in vrmSpring.Joints)
{
var joint = new VRM10SpringBone.VRM10SpringJoint();
@@ -305,8 +305,6 @@ namespace UniVRM10
springBone.Joints.Add(joint);
}
springBone.ColliderGroups = vrmSpring.Colliders.Select(x => colliders[x]).ToArray();
}
}
}

View File

@@ -258,133 +258,136 @@ namespace UniVRM10
// blendShape
var controller = root.GetComponent<UniVRM10.VRM10Controller>();
if (controller != null)
{
Model.Vrm.ExpressionManager = new VrmLib.ExpressionManager();
if (controller != null)
{
foreach (var clip in controller.Expression.ExpressionAvatar.Clips)
Model.Vrm.ExpressionManager = new VrmLib.ExpressionManager();
if (controller != null)
{
var expression = ToVrmLib(clip, root);
if (expression != null)
foreach (var clip in controller.Expression.ExpressionAvatar.Clips)
{
Model.Vrm.ExpressionManager.ExpressionList.Add(expression);
var expression = ToVrmLib(clip, root);
if (expression != null)
{
Model.Vrm.ExpressionManager.ExpressionList.Add(expression);
}
}
}
}
}
// firstPerson
{
var firstPerson = new VrmLib.FirstPerson();
if (controller != null)
// firstPerson
{
foreach (var annotation in controller.FirstPerson.Renderers)
var firstPerson = new VrmLib.FirstPerson();
if (controller != null)
{
firstPerson.Annotations.Add(
new VrmLib.FirstPersonMeshAnnotation(Nodes[annotation.Renderer.gameObject],
annotation.FirstPersonFlag)
);
foreach (var annotation in controller.FirstPerson.Renderers)
{
firstPerson.Annotations.Add(
new VrmLib.FirstPersonMeshAnnotation(Nodes[annotation.Renderer.gameObject],
annotation.FirstPersonFlag)
);
}
Model.Vrm.FirstPerson = firstPerson;
}
Model.Vrm.FirstPerson = firstPerson;
}
}
// lookAt
{
var lookAt = new VrmLib.LookAt();
if (controller != null)
// lookAt
{
if (controller.LookAt.LookAtType == VRM10ControllerLookAt.LookAtTypes.Expression)
var lookAt = new VrmLib.LookAt();
if (controller != null)
{
lookAt.HorizontalInner = new VrmLib.LookAtRangeMap();
lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
if (controller.LookAt.LookAtType == VRM10ControllerLookAt.LookAtTypes.Expression)
{
InputMaxValue = controller.LookAt.HorizontalOuter.CurveXRangeDegree,
OutputScaling = controller.LookAt.HorizontalOuter.CurveYRangeDegree
};
lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalUp.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalUp.CurveYRangeDegree,
};
lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalDown.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalDown.CurveYRangeDegree,
};
}
else if (controller.LookAt.LookAtType == VRM10ControllerLookAt.LookAtTypes.Bone)
{
lookAt.HorizontalInner = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.HorizontalInner.CurveXRangeDegree,
OutputScaling = controller.LookAt.HorizontalInner.CurveYRangeDegree
};
lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.HorizontalOuter.CurveXRangeDegree,
OutputScaling = controller.LookAt.HorizontalOuter.CurveYRangeDegree
};
lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalUp.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalUp.CurveYRangeDegree,
};
lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalDown.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalDown.CurveYRangeDegree,
};
}
lookAt.OffsetFromHeadBone = controller.LookAt.OffsetFromHead.ToNumericsVector3();
}
Model.Vrm.LookAt = lookAt;
}
// springBone
{
var springBones = root.GetComponentsInChildren<UniVRM10.VRM10SpringBone>();
foreach (var springBone in springBones)
{
var vrmSpringBone = new VrmLib.SpringBone()
{
Comment = springBone.m_comment,
Origin = (springBone.m_center != null) ? Nodes[springBone.m_center.gameObject] : null,
};
foreach (var joint in springBone.Joints)
{
vrmSpringBone.Joints.Add(new VrmLib.SpringJoint
{
Stiffness = joint.m_stiffnessForce,
GravityPower = joint.m_gravityPower,
GravityDir = joint.m_gravityDir.ToNumericsVector3(),
DragForce = joint.m_dragForce,
HitRadius = joint.m_hitRadius,
});
}
foreach (var colliderGroup in springBone.ColliderGroups)
{
var colliderGroups = colliderGroup.Colliders.Select(x =>
{
switch (x.ColliderType)
lookAt.HorizontalInner = new VrmLib.LookAtRangeMap();
lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
{
case VRM10SpringBoneColliderTypes.Sphere:
return VrmLib.VrmSpringBoneCollider.CreateSphere(x.Offset.ToNumericsVector3(), x.Radius);
case VRM10SpringBoneColliderTypes.Capsule:
return VrmLib.VrmSpringBoneCollider.CreateCapsule(x.Offset.ToNumericsVector3(), x.Radius, x.Tail.ToNumericsVector3());
default:
throw new NotImplementedException();
}
});
var vrmColliderGroup = new VrmLib.SpringBoneColliderGroup(Nodes[colliderGroup.gameObject], colliderGroups);
vrmSpringBone.Colliders.Add(vrmColliderGroup);
InputMaxValue = controller.LookAt.HorizontalOuter.CurveXRangeDegree,
OutputScaling = controller.LookAt.HorizontalOuter.CurveYRangeDegree
};
lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalUp.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalUp.CurveYRangeDegree,
};
lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalDown.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalDown.CurveYRangeDegree,
};
}
else if (controller.LookAt.LookAtType == VRM10ControllerLookAt.LookAtTypes.Bone)
{
lookAt.HorizontalInner = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.HorizontalInner.CurveXRangeDegree,
OutputScaling = controller.LookAt.HorizontalInner.CurveYRangeDegree
};
lookAt.HorizontalOuter = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.HorizontalOuter.CurveXRangeDegree,
OutputScaling = controller.LookAt.HorizontalOuter.CurveYRangeDegree
};
lookAt.VerticalUp = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalUp.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalUp.CurveYRangeDegree,
};
lookAt.VerticalDown = new VrmLib.LookAtRangeMap()
{
InputMaxValue = controller.LookAt.VerticalDown.CurveXRangeDegree,
OutputScaling = controller.LookAt.VerticalDown.CurveYRangeDegree,
};
}
lookAt.OffsetFromHeadBone = controller.LookAt.OffsetFromHead.ToNumericsVector3();
}
Model.Vrm.LookAt = lookAt;
}
Model.Vrm.SpringBone.Springs.Add(vrmSpringBone);
// springBone
{
var springBoneManager = controller.SpringBone;
foreach (var springBone in springBoneManager.Springs)
{
var vrmSpringBone = new VrmLib.SpringBone()
{
Comment = springBone.m_comment,
Origin = (springBone.m_center != null) ? Nodes[springBone.m_center.gameObject] : null,
};
foreach (var joint in springBone.Joints)
{
vrmSpringBone.Joints.Add(new VrmLib.SpringJoint
{
Stiffness = joint.m_stiffnessForce,
GravityPower = joint.m_gravityPower,
GravityDir = joint.m_gravityDir.ToNumericsVector3(),
DragForce = joint.m_dragForce,
HitRadius = joint.m_hitRadius,
});
}
foreach (var colliderGroup in springBone.ColliderGroups)
{
var colliderGroups = colliderGroup.Colliders.Select(x =>
{
switch (x.ColliderType)
{
case VRM10SpringBoneColliderTypes.Sphere:
return VrmLib.VrmSpringBoneCollider.CreateSphere(x.Offset.ToNumericsVector3(), x.Radius);
case VRM10SpringBoneColliderTypes.Capsule:
return VrmLib.VrmSpringBoneCollider.CreateCapsule(x.Offset.ToNumericsVector3(), x.Radius, x.Tail.ToNumericsVector3());
default:
throw new NotImplementedException();
}
});
var vrmColliderGroup = new VrmLib.SpringBoneColliderGroup(Nodes[colliderGroup.gameObject], colliderGroups);
vrmSpringBone.Colliders.Add(vrmColliderGroup);
}
Model.Vrm.SpringBone.Springs.Add(vrmSpringBone);
}
}
}

View File

@@ -97,7 +97,9 @@ namespace VrmLib
return false;
}
var Vrm = new Vrm(storage.CreateVrmMeta(model.Textures), storage.VrmExporterVersion, storage.VrmSpecVersion);
var meta = storage.CreateVrmMeta(model.Textures);
var Vrm = new Vrm(meta, storage.VrmExporterVersion, storage.VrmSpecVersion);
model.Vrm = Vrm;
storage.LoadVrmHumanoid(model.Nodes);