diff --git a/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs b/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs
index f22a16105..184132e93 100644
--- a/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs
+++ b/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs
@@ -79,6 +79,12 @@ namespace UniVRM10
$"{SPEC_DIR}/VRMC_vrm_animation-1.0/schema/VRMC_vrm_animation.schema.json",
"Assets/VRM10/Runtime/Format/Animation"
),
+
+ // VRMC_animation
+ new GenerateInfo(
+ $"{SPEC_DIR}/VRMC_springBone_extended_collider-1.0/schema/VRMC_springBone_extended_collider.schema.json",
+ "Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider"
+ ),
};
foreach (var arg in args)
diff --git a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs
index 60e3c45de..6c29a1270 100644
--- a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs
+++ b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs
@@ -7,6 +7,9 @@ namespace UniVRM10
{
Sphere,
Capsule,
+ Plane,
+ SphereInside,
+ CapsuleInside,
}
[Serializable]
@@ -23,6 +26,10 @@ namespace UniVRM10
/// bone local position
public Vector3 Tail;
+ public Vector3 Normal = Vector3.up;
+
+ public Vector3 TailOrNormal => ColliderType == VRM10SpringBoneColliderTypes.Plane ? Normal : Tail;
+
public static int SelectedGuid;
public bool IsSelected => GetInstanceID() == SelectedGuid;
@@ -38,11 +45,107 @@ namespace UniVRM10
break;
case VRM10SpringBoneColliderTypes.Capsule:
- Gizmos.color = new Color(1.0f, 0.1f, 0.1f);
- Gizmos.DrawWireSphere(Offset, Radius);
- Gizmos.DrawWireSphere(Tail, Radius);
- Gizmos.DrawLine(Offset, Tail);
+ Gizmos.color = Color.magenta;
+ DrawCapsuleGizmo(transform.localToWorldMatrix.MultiplyPoint(Offset), transform.localToWorldMatrix.MultiplyPoint(Tail), Radius);
break;
+
+ case VRM10SpringBoneColliderTypes.Plane:
+ Gizmos.color = new Color(1.0f, 0.5f, 0.0f);
+ DrawPlane(transform.localToWorldMatrix, Offset, Normal, Radius);
+ break;
+
+ case VRM10SpringBoneColliderTypes.SphereInside:
+ Gizmos.color = new Color(0.5f, 0, 1.0f);
+ Gizmos.DrawWireSphere(Offset, Radius);
+ break;
+
+ case VRM10SpringBoneColliderTypes.CapsuleInside:
+ Gizmos.color = new Color(0.5f, 0, 1.0f);
+ DrawCapsuleGizmo(transform.localToWorldMatrix.MultiplyPoint(Offset), transform.localToWorldMatrix.MultiplyPoint(Tail), Radius);
+ break;
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+
+ public static void DrawCapsuleGizmo(Vector3 start, Vector3 end, float radius)
+ {
+ var tail = end - start;
+ var distance = (end - start).magnitude;
+ Gizmos.matrix = Matrix4x4.TRS(start, Quaternion.FromToRotation(Vector3.forward, tail), Vector3.one);
+ Gizmos.DrawWireSphere(Vector3.zero, radius);
+ Gizmos.DrawWireSphere(Vector3.forward * distance, radius);
+ var capsuleEnd = Vector3.forward * distance;
+ var offsets = new Vector3[] { new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, -1.0f, 0.0f) };
+ for (int i = 0; i < offsets.Length; i++)
+ {
+ Gizmos.DrawLine(offsets[i] * radius, capsuleEnd + offsets[i] * radius);
+ }
+ Gizmos.matrix = Matrix4x4.identity;
+ }
+
+ public static void DrawPlane(in Matrix4x4 m, in Vector3 offset, in Vector3 _n, float radius)
+ {
+ var n = _n.normalized;
+ Gizmos.matrix = m;
+ Gizmos.DrawLine(offset, offset + n * radius);
+
+ // N Y-Axis として
+ // XZ 平面を描画する。
+ var z = Vector3.Cross(Vector3.right, n);
+ if (z.magnitude > 1e-4)
+ {
+ var zr = z * radius;
+ var x = Vector3.Cross(n, z);
+ var xr = x * radius;
+ Gizmos.DrawLine(-xr, xr);
+ {
+ var o = offset + zr;
+ Gizmos.DrawLine(o - xr, o + xr);
+ }
+ {
+ var o = offset - zr;
+ Gizmos.DrawLine(o - xr, o + xr);
+ }
+
+ Gizmos.DrawLine(-zr, zr);
+ {
+ var o = offset + xr;
+ Gizmos.DrawLine(o - zr, o + zr);
+ }
+ {
+ var o = offset - xr;
+ Gizmos.DrawLine(o - zr, o + zr);
+ }
+ }
+ else
+ {
+ // N と ローカル X-Axis が重なっていた場合
+ var x = Vector3.Cross(n, Vector3.forward);
+ var xr = x * radius;
+ var _z = Vector3.Cross(x, n);
+ var zr = _z * radius;
+
+ Gizmos.DrawLine(-xr, xr);
+ {
+ var o = offset + zr;
+ Gizmos.DrawLine(o - xr, o + xr);
+ }
+ {
+ var o = offset - zr;
+ Gizmos.DrawLine(o - xr, o + xr);
+ }
+
+ Gizmos.DrawLine(-zr, zr);
+ {
+ var o = offset + xr;
+ Gizmos.DrawLine(o - zr, o + zr);
+ }
+ {
+ var o = offset - xr;
+ Gizmos.DrawLine(o - zr, o + zr);
+ }
}
}
diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
index 8a40ad9e5..52eccc274 100644
--- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
+++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs
@@ -131,7 +131,7 @@ namespace UniVRM10
{
offset = collider.Offset,
radius = collider.Radius,
- tail = collider.Tail,
+ tailOrNormal = collider.TailOrNormal,
colliderType = TranslateColliderType(collider.ColliderType)
}
}).ToArray(),
@@ -172,6 +172,12 @@ namespace UniVRM10
return BlittableColliderType.Sphere;
case VRM10SpringBoneColliderTypes.Capsule:
return BlittableColliderType.Capsule;
+ case VRM10SpringBoneColliderTypes.Plane:
+ return BlittableColliderType.Plane;
+ case VRM10SpringBoneColliderTypes.SphereInside:
+ return BlittableColliderType.SphereInside;
+ case VRM10SpringBoneColliderTypes.CapsuleInside:
+ return BlittableColliderType.CapsuleInside;
default:
throw new ArgumentOutOfRangeException();
}
diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs
index 334887503..1f88e7fee 100644
--- a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs
+++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs
@@ -9,11 +9,12 @@ namespace UniVRM10.FastSpringBones.Blittables
///
[Serializable]
public struct BlittableCollider
- {
+ {
public BlittableColliderType colliderType;
public Vector3 offset;
public float radius;
- public Vector3 tail;
+ // capsule tail or plane normal
+ public Vector3 tailOrNormal;
public int transformIndex;
}
}
\ No newline at end of file
diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs
index 04f0b9f25..69ea0f91d 100644
--- a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs
+++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs
@@ -4,5 +4,8 @@ namespace UniVRM10.FastSpringBones.Blittables
{
Sphere,
Capsule,
+ Plane,
+ SphereInside,
+ CapsuleInside,
}
}
\ No newline at end of file
diff --git a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs
index 87e5e16d4..4c7009d09 100644
--- a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs
+++ b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs
@@ -22,7 +22,7 @@ namespace UniVRM10.FastSpringBones.System
[NativeDisableParallelForRestriction] public NativeArray Transforms;
public float DeltaTime;
-
+
public unsafe void Execute(int index)
{
var spring = Springs[index];
@@ -79,16 +79,32 @@ namespace UniVRM10.FastSpringBones.System
var colliderScale = colliderTransform.localToWorldMatrix.lossyScale;
var maxColliderScale = Mathf.Max(Mathf.Max(Mathf.Abs(colliderScale.x), Mathf.Abs(colliderScale.y)), Mathf.Abs(colliderScale.z));
var worldPosition = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset);
- var worldTail = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.tail);
-
+ var worldTail = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.tailOrNormal);
+
switch (collider.colliderType)
{
case BlittableColliderType.Sphere:
- ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail);
+ ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail);
break;
+
case BlittableColliderType.Capsule:
ResolveCapsuleCollision(worldTail, worldPosition, headTransform, joint, collider, maxColliderScale, logic, ref nextTail);
break;
+
+ case BlittableColliderType.Plane:
+ ResolvePlaneCollision(joint, collider, colliderTransform, ref nextTail);
+ break;
+
+ case BlittableColliderType.SphereInside:
+ ResolveSphereCollisionInside(joint, collider, colliderTransform, ref nextTail);
+ break;
+
+ case BlittableColliderType.CapsuleInside:
+ ResolveCapsuleCollisionInside(joint, collider, colliderTransform, ref nextTail);
+ break;
+
+ default:
+ throw new NotImplementedException();
}
}
@@ -203,5 +219,95 @@ namespace UniVRM10.FastSpringBones.System
nextTail = headTransform.position + (posFromCollider - headTransform.position).normalized * logic.length;
}
}
+
+ private static void ResolveSphereCollisionInside(
+ BlittableJoint joint,
+ BlittableCollider collider,
+ BlittableTransform colliderTransform,
+ ref Vector3 nextTail)
+ {
+ var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset);
+ var delta = nextTail - transformedOffset;
+
+ // ジョイントとコライダーの距離。負の値は衝突していることを示す
+ var distance = collider.radius - joint.radius - delta.magnitude;
+
+ // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
+ if (distance < 0)
+ {
+ var direction = -delta.normalized;
+ nextTail -= direction * distance;
+ }
+ }
+
+ private static void ResolveCapsuleCollisionInside(
+ BlittableJoint joint,
+ BlittableCollider collider,
+ BlittableTransform colliderTransform,
+ ref Vector3 nextTail)
+ {
+ var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset);
+ var transformedTail = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.tailOrNormal);
+ var offsetToTail = transformedTail - transformedOffset;
+ var lengthSqCapsule = offsetToTail.sqrMagnitude;
+
+ var delta = nextTail - transformedOffset;
+ var dot = Vector3.Dot(offsetToTail, delta);
+
+ if (dot < 0.0)
+ {
+ // ジョイントがカプセルの始点側にある場合
+ // なにもしない
+ }
+ else if (dot > lengthSqCapsule)
+ {
+ // ジョイントがカプセルの終点側にある場合
+ delta -= offsetToTail;
+ }
+ else
+ {
+ // ジョイントがカプセルの始点と終点の間にある場合
+ delta -= offsetToTail * (dot / lengthSqCapsule);
+ }
+
+ // ジョイントとコライダーの距離。負の値は衝突していることを示す
+ var distance = collider.radius - joint.radius - delta.magnitude;
+
+ // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
+ if (distance < 0)
+ {
+ var direction = -delta.normalized;
+ nextTail -= direction * distance;
+ }
+ }
+
+ ///
+ /// Collision with SpringJoint and PlaneCollider.
+ /// If collide update nextTail.
+ ///
+ /// joint
+ /// collier
+ /// colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset);
+ /// result of verlet integration
+ private static void ResolvePlaneCollision(
+ BlittableJoint joint,
+ BlittableCollider collider,
+ BlittableTransform colliderTransform,
+ ref Vector3 nextTail)
+ {
+ var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset);
+ var transformedNormal = colliderTransform.localToWorldMatrix.MultiplyVector(collider.tailOrNormal).normalized;
+ var delta = nextTail - transformedOffset;
+
+ // ジョイントとコライダーの距離。負の値は衝突していることを示す
+ var distance = Vector3.Dot(delta, transformedNormal) - joint.radius;
+
+ if (distance < 0)
+ {
+ // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
+ var direction = transformedNormal;
+ nextTail -= direction * distance;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Assets/VRM10/Runtime/Format/Animation/Deserializer.g.cs b/Assets/VRM10/Runtime/Format/Animation/Deserializer.g.cs
index d74221b5b..7b8660150 100644
--- a/Assets/VRM10/Runtime/Format/Animation/Deserializer.g.cs
+++ b/Assets/VRM10/Runtime/Format/Animation/Deserializer.g.cs
@@ -1921,26 +1921,6 @@ public static Preset __expressions_Deserialize_Preset(JsonNode parsed)
continue;
}
- if(key=="lookUp"){
- value.LookUp = __expressions__preset_Deserialize_LookUp(kv.Value);
- continue;
- }
-
- if(key=="lookDown"){
- value.LookDown = __expressions__preset_Deserialize_LookDown(kv.Value);
- continue;
- }
-
- if(key=="lookLeft"){
- value.LookLeft = __expressions__preset_Deserialize_LookLeft(kv.Value);
- continue;
- }
-
- if(key=="lookRight"){
- value.LookRight = __expressions__preset_Deserialize_LookRight(kv.Value);
- continue;
- }
-
if(key=="neutral"){
value.Neutral = __expressions__preset_Deserialize_Neutral(kv.Value);
continue;
@@ -2301,114 +2281,6 @@ public static Expression __expressions__preset_Deserialize_BlinkRight(JsonNode p
return value;
}
-public static Expression __expressions__preset_Deserialize_LookUp(JsonNode parsed)
-{
- var value = new Expression();
-
- foreach(var kv in parsed.ObjectItems())
- {
- var key = kv.Key.GetString();
-
- if(key=="extensions"){
- value.Extensions = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="extras"){
- value.Extras = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="node"){
- value.Node = kv.Value.GetInt32();
- continue;
- }
-
- }
- return value;
-}
-
-public static Expression __expressions__preset_Deserialize_LookDown(JsonNode parsed)
-{
- var value = new Expression();
-
- foreach(var kv in parsed.ObjectItems())
- {
- var key = kv.Key.GetString();
-
- if(key=="extensions"){
- value.Extensions = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="extras"){
- value.Extras = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="node"){
- value.Node = kv.Value.GetInt32();
- continue;
- }
-
- }
- return value;
-}
-
-public static Expression __expressions__preset_Deserialize_LookLeft(JsonNode parsed)
-{
- var value = new Expression();
-
- foreach(var kv in parsed.ObjectItems())
- {
- var key = kv.Key.GetString();
-
- if(key=="extensions"){
- value.Extensions = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="extras"){
- value.Extras = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="node"){
- value.Node = kv.Value.GetInt32();
- continue;
- }
-
- }
- return value;
-}
-
-public static Expression __expressions__preset_Deserialize_LookRight(JsonNode parsed)
-{
- var value = new Expression();
-
- foreach(var kv in parsed.ObjectItems())
- {
- var key = kv.Key.GetString();
-
- if(key=="extensions"){
- value.Extensions = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="extras"){
- value.Extras = new glTFExtensionImport(kv.Value);
- continue;
- }
-
- if(key=="node"){
- value.Node = kv.Value.GetInt32();
- continue;
- }
-
- }
- return value;
-}
-
public static Expression __expressions__preset_Deserialize_Neutral(JsonNode parsed)
{
var value = new Expression();
@@ -2496,9 +2368,25 @@ public static LookAt Deserialize_LookAt(JsonNode parsed)
continue;
}
+ if(key=="offsetFromHeadBone"){
+ value.OffsetFromHeadBone = __lookAt_Deserialize_OffsetFromHeadBone(kv.Value);
+ continue;
+ }
+
}
return value;
}
+public static float[] __lookAt_Deserialize_OffsetFromHeadBone(JsonNode parsed)
+{
+ var value = new float[parsed.GetArrayCount()];
+ int i=0;
+ foreach(var x in parsed.ArrayItems())
+ {
+ value[i++] = x.GetSingle();
+ }
+ return value;
+}
+
} // GltfDeserializer
} // UniGLTF
diff --git a/Assets/VRM10/Runtime/Format/Animation/Format.g.cs b/Assets/VRM10/Runtime/Format/Animation/Format.g.cs
index df697d818..f7a1d5f03 100644
--- a/Assets/VRM10/Runtime/Format/Animation/Format.g.cs
+++ b/Assets/VRM10/Runtime/Format/Animation/Format.g.cs
@@ -251,18 +251,6 @@ namespace UniGLTF.Extensions.VRMC_vrm_animation
// Represents a single expression.
public Expression BlinkRight;
- // Represents a single expression.
- public Expression LookUp;
-
- // Represents a single expression.
- public Expression LookDown;
-
- // Represents a single expression.
- public Expression LookLeft;
-
- // Represents a single expression.
- public Expression LookRight;
-
// Represents a single expression.
public Expression Neutral;
}
@@ -292,6 +280,9 @@ namespace UniGLTF.Extensions.VRMC_vrm_animation
// Represents a single glTF node represents the eye gaze point.
public int? Node;
+
+ // The position offset of the origin of the LookAt from the humanoid head bone
+ public float[] OffsetFromHeadBone;
}
public class VRMC_vrm_animation
diff --git a/Assets/VRM10/Runtime/Format/Animation/Serializer.g.cs b/Assets/VRM10/Runtime/Format/Animation/Serializer.g.cs
index d27bd05a6..996c1ccb5 100644
--- a/Assets/VRM10/Runtime/Format/Animation/Serializer.g.cs
+++ b/Assets/VRM10/Runtime/Format/Animation/Serializer.g.cs
@@ -1689,26 +1689,6 @@ public static void __expressions_Serialize_Preset(JsonFormatter f, Preset value)
__expressions__preset_Serialize_BlinkRight(f, value.BlinkRight);
}
- if(value.LookUp!=null){
- f.Key("lookUp");
- __expressions__preset_Serialize_LookUp(f, value.LookUp);
- }
-
- if(value.LookDown!=null){
- f.Key("lookDown");
- __expressions__preset_Serialize_LookDown(f, value.LookDown);
- }
-
- if(value.LookLeft!=null){
- f.Key("lookLeft");
- __expressions__preset_Serialize_LookLeft(f, value.LookLeft);
- }
-
- if(value.LookRight!=null){
- f.Key("lookRight");
- __expressions__preset_Serialize_LookRight(f, value.LookRight);
- }
-
if(value.Neutral!=null){
f.Key("neutral");
__expressions__preset_Serialize_Neutral(f, value.Neutral);
@@ -2016,98 +1996,6 @@ public static void __expressions__preset_Serialize_BlinkRight(JsonFormatter f, E
f.EndMap();
}
-public static void __expressions__preset_Serialize_LookUp(JsonFormatter f, Expression value)
-{
- f.BeginMap();
-
-
- if(value.Extensions!=null){
- f.Key("extensions");
- (value.Extensions as glTFExtension).Serialize(f);
- }
-
- if(value.Extras!=null){
- f.Key("extras");
- (value.Extras as glTFExtension).Serialize(f);
- }
-
- if(value.Node.HasValue){
- f.Key("node");
- f.Value(value.Node.GetValueOrDefault());
- }
-
- f.EndMap();
-}
-
-public static void __expressions__preset_Serialize_LookDown(JsonFormatter f, Expression value)
-{
- f.BeginMap();
-
-
- if(value.Extensions!=null){
- f.Key("extensions");
- (value.Extensions as glTFExtension).Serialize(f);
- }
-
- if(value.Extras!=null){
- f.Key("extras");
- (value.Extras as glTFExtension).Serialize(f);
- }
-
- if(value.Node.HasValue){
- f.Key("node");
- f.Value(value.Node.GetValueOrDefault());
- }
-
- f.EndMap();
-}
-
-public static void __expressions__preset_Serialize_LookLeft(JsonFormatter f, Expression value)
-{
- f.BeginMap();
-
-
- if(value.Extensions!=null){
- f.Key("extensions");
- (value.Extensions as glTFExtension).Serialize(f);
- }
-
- if(value.Extras!=null){
- f.Key("extras");
- (value.Extras as glTFExtension).Serialize(f);
- }
-
- if(value.Node.HasValue){
- f.Key("node");
- f.Value(value.Node.GetValueOrDefault());
- }
-
- f.EndMap();
-}
-
-public static void __expressions__preset_Serialize_LookRight(JsonFormatter f, Expression value)
-{
- f.BeginMap();
-
-
- if(value.Extensions!=null){
- f.Key("extensions");
- (value.Extensions as glTFExtension).Serialize(f);
- }
-
- if(value.Extras!=null){
- f.Key("extras");
- (value.Extras as glTFExtension).Serialize(f);
- }
-
- if(value.Node.HasValue){
- f.Key("node");
- f.Value(value.Node.GetValueOrDefault());
- }
-
- f.EndMap();
-}
-
public static void __expressions__preset_Serialize_Neutral(JsonFormatter f, Expression value)
{
f.BeginMap();
@@ -2187,8 +2075,25 @@ public static void Serialize_LookAt(JsonFormatter f, LookAt value)
f.Value(value.Node.GetValueOrDefault());
}
+ if(value.OffsetFromHeadBone!=null&&value.OffsetFromHeadBone.Count()>=3){
+ f.Key("offsetFromHeadBone");
+ __lookAt_Serialize_OffsetFromHeadBone(f, value.OffsetFromHeadBone);
+ }
+
f.EndMap();
}
+public static void __lookAt_Serialize_OffsetFromHeadBone(JsonFormatter f, float[] value)
+{
+ f.BeginList();
+
+ foreach(var item in value)
+ {
+ f.Value(item);
+
+ }
+ f.EndList();
+}
+
} // class
} // namespace
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider.meta b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider.meta
new file mode 100644
index 000000000..6ea3f5ae0
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4feacc5eab0e46e4b900d239ff3c6485
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Deserializer.g.cs b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Deserializer.g.cs
new file mode 100644
index 000000000..2630d2a80
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Deserializer.g.cs
@@ -0,0 +1,238 @@
+// This file is generated from JsonSchema. Don't modify this source code.
+using UniJSON;
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace UniGLTF.Extensions.VRMC_springBone_extended_collider {
+
+public static class GltfDeserializer
+{
+ public static readonly Utf8String ExtensionNameUtf8 = Utf8String.From(VRMC_springBone_extended_collider.ExtensionName);
+
+public static bool TryGet(UniGLTF.glTFExtension src, out VRMC_springBone_extended_collider extension)
+{
+ if(src is UniGLTF.glTFExtensionImport extensions)
+ {
+ foreach(var kv in extensions.ObjectItems())
+ {
+ if(kv.Key.GetUtf8String() == ExtensionNameUtf8)
+ {
+ extension = Deserialize(kv.Value);
+ return true;
+ }
+ }
+ }
+
+ extension = default;
+ return false;
+}
+
+
+public static VRMC_springBone_extended_collider Deserialize(JsonNode parsed)
+{
+ var value = new VRMC_springBone_extended_collider();
+
+ foreach(var kv in parsed.ObjectItems())
+ {
+ var key = kv.Key.GetString();
+
+ if(key=="extensions"){
+ value.Extensions = new glTFExtensionImport(kv.Value);
+ continue;
+ }
+
+ if(key=="extras"){
+ value.Extras = new glTFExtensionImport(kv.Value);
+ continue;
+ }
+
+ if(key=="specVersion"){
+ value.SpecVersion = kv.Value.GetString();
+ continue;
+ }
+
+ if(key=="shape"){
+ value.Shape = Deserialize_Shape(kv.Value);
+ continue;
+ }
+
+ }
+ return value;
+}
+
+public static ExtendedColliderShape Deserialize_Shape(JsonNode parsed)
+{
+ var value = new ExtendedColliderShape();
+
+ foreach(var kv in parsed.ObjectItems())
+ {
+ var key = kv.Key.GetString();
+
+ if(key=="extensions"){
+ value.Extensions = new glTFExtensionImport(kv.Value);
+ continue;
+ }
+
+ if(key=="extras"){
+ value.Extras = new glTFExtensionImport(kv.Value);
+ continue;
+ }
+
+ if(key=="sphere"){
+ value.Sphere = __shape_Deserialize_Sphere(kv.Value);
+ continue;
+ }
+
+ if(key=="capsule"){
+ value.Capsule = __shape_Deserialize_Capsule(kv.Value);
+ continue;
+ }
+
+ if(key=="plane"){
+ value.Plane = __shape_Deserialize_Plane(kv.Value);
+ continue;
+ }
+
+ }
+ return value;
+}
+
+public static ExtendedColliderShapeSphere __shape_Deserialize_Sphere(JsonNode parsed)
+{
+ var value = new ExtendedColliderShapeSphere();
+
+ foreach(var kv in parsed.ObjectItems())
+ {
+ var key = kv.Key.GetString();
+
+ if(key=="offset"){
+ value.Offset = __shape__sphere_Deserialize_Offset(kv.Value);
+ continue;
+ }
+
+ if(key=="radius"){
+ value.Radius = kv.Value.GetSingle();
+ continue;
+ }
+
+ if(key=="inside"){
+ value.Inside = kv.Value.GetBoolean();
+ continue;
+ }
+
+ }
+ return value;
+}
+
+public static float[] __shape__sphere_Deserialize_Offset(JsonNode parsed)
+{
+ var value = new float[parsed.GetArrayCount()];
+ int i=0;
+ foreach(var x in parsed.ArrayItems())
+ {
+ value[i++] = x.GetSingle();
+ }
+ return value;
+}
+
+public static ExtendedColliderShapeCapsule __shape_Deserialize_Capsule(JsonNode parsed)
+{
+ var value = new ExtendedColliderShapeCapsule();
+
+ foreach(var kv in parsed.ObjectItems())
+ {
+ var key = kv.Key.GetString();
+
+ if(key=="offset"){
+ value.Offset = __shape__capsule_Deserialize_Offset(kv.Value);
+ continue;
+ }
+
+ if(key=="radius"){
+ value.Radius = kv.Value.GetSingle();
+ continue;
+ }
+
+ if(key=="tail"){
+ value.Tail = __shape__capsule_Deserialize_Tail(kv.Value);
+ continue;
+ }
+
+ if(key=="inside"){
+ value.Inside = kv.Value.GetBoolean();
+ continue;
+ }
+
+ }
+ return value;
+}
+
+public static float[] __shape__capsule_Deserialize_Offset(JsonNode parsed)
+{
+ var value = new float[parsed.GetArrayCount()];
+ int i=0;
+ foreach(var x in parsed.ArrayItems())
+ {
+ value[i++] = x.GetSingle();
+ }
+ return value;
+}
+
+public static float[] __shape__capsule_Deserialize_Tail(JsonNode parsed)
+{
+ var value = new float[parsed.GetArrayCount()];
+ int i=0;
+ foreach(var x in parsed.ArrayItems())
+ {
+ value[i++] = x.GetSingle();
+ }
+ return value;
+}
+
+public static ExtendedColliderShapePlane __shape_Deserialize_Plane(JsonNode parsed)
+{
+ var value = new ExtendedColliderShapePlane();
+
+ foreach(var kv in parsed.ObjectItems())
+ {
+ var key = kv.Key.GetString();
+
+ if(key=="offset"){
+ value.Offset = __shape__plane_Deserialize_Offset(kv.Value);
+ continue;
+ }
+
+ if(key=="normal"){
+ value.Normal = __shape__plane_Deserialize_Normal(kv.Value);
+ continue;
+ }
+
+ }
+ return value;
+}
+
+public static float[] __shape__plane_Deserialize_Offset(JsonNode parsed)
+{
+ var value = new float[parsed.GetArrayCount()];
+ int i=0;
+ foreach(var x in parsed.ArrayItems())
+ {
+ value[i++] = x.GetSingle();
+ }
+ return value;
+}
+
+public static float[] __shape__plane_Deserialize_Normal(JsonNode parsed)
+{
+ var value = new float[parsed.GetArrayCount()];
+ int i=0;
+ foreach(var x in parsed.ArrayItems())
+ {
+ value[i++] = x.GetSingle();
+ }
+ return value;
+}
+
+} // GltfDeserializer
+} // UniGLTF
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Deserializer.g.cs.meta b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Deserializer.g.cs.meta
new file mode 100644
index 000000000..fdf943ac1
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Deserializer.g.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 03ad1a44a20bbc94db18a7ee01cd6d3e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Format.g.cs b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Format.g.cs
new file mode 100644
index 000000000..8ce05a98f
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Format.g.cs
@@ -0,0 +1,76 @@
+// This file is generated from JsonSchema. Don't modify this source code.
+using System;
+using System.Collections.Generic;
+
+
+namespace UniGLTF.Extensions.VRMC_springBone_extended_collider
+{
+
+ public class ExtendedColliderShapeSphere
+ {
+ // The offset of the sphere from the origin in the local space.
+ public float[] Offset;
+
+ // The radius of the sphere.
+ public float? Radius;
+
+ // If true, the collider prevents spring bones from going outside of the sphere instead.
+ public bool? Inside;
+ }
+
+ public class ExtendedColliderShapeCapsule
+ {
+ // The offset of the capsule head from the origin in the local space.
+ public float[] Offset;
+
+ // The radius of the capsule.
+ public float? Radius;
+
+ // The offset of the capsule tail from the origin in the local space.
+ public float[] Tail;
+
+ // If true, the collider prevents spring bones from going outside of the capsule instead.
+ public bool? Inside;
+ }
+
+ public class ExtendedColliderShapePlane
+ {
+ // The offset of the plane from the origin in the local space.
+ public float[] Offset;
+
+ // The normal of the plane in the local space. Must be normalized.
+ public float[] Normal;
+ }
+
+ public class ExtendedColliderShape
+ {
+ // Dictionary object with extension-specific objects.
+ public object Extensions;
+
+ // Application-specific data.
+ public object Extras;
+
+ public ExtendedColliderShapeSphere Sphere;
+
+ public ExtendedColliderShapeCapsule Capsule;
+
+ public ExtendedColliderShapePlane Plane;
+ }
+
+ public class VRMC_springBone_extended_collider
+ {
+ public const string ExtensionName = "VRMC_springBone_extended_collider";
+
+ // Dictionary object with extension-specific objects.
+ public object Extensions;
+
+ // Application-specific data.
+ public object Extras;
+
+ // Specification version of VRMC_springBone_extended_collider.
+ public string SpecVersion;
+
+ // The shape of the collider.
+ public ExtendedColliderShape Shape;
+ }
+}
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Format.g.cs.meta b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Format.g.cs.meta
new file mode 100644
index 000000000..960a93d31
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Format.g.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: afa332976c5ea28468f9a63b0b3ad344
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Serializer.g.cs b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Serializer.g.cs
new file mode 100644
index 000000000..bfc86ffdd
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Serializer.g.cs
@@ -0,0 +1,222 @@
+// This file is generated from JsonSchema. Don't modify this source code.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UniJSON;
+
+namespace UniGLTF.Extensions.VRMC_springBone_extended_collider {
+
+ static public class GltfSerializer
+ {
+
+ public static void SerializeTo(ref UniGLTF.glTFExtension dst, VRMC_springBone_extended_collider extension)
+ {
+ if (dst is glTFExtensionImport)
+ {
+ throw new NotImplementedException();
+ }
+
+ if (!(dst is glTFExtensionExport extensions))
+ {
+ extensions = new glTFExtensionExport();
+ dst = extensions;
+ }
+
+ var f = new JsonFormatter();
+ Serialize(f, extension);
+ extensions.Add(VRMC_springBone_extended_collider.ExtensionName, f.GetStoreBytes());
+ }
+
+
+public static void Serialize(JsonFormatter f, VRMC_springBone_extended_collider value)
+{
+ f.BeginMap();
+
+
+ if(value.Extensions!=null){
+ f.Key("extensions");
+ (value.Extensions as glTFExtension).Serialize(f);
+ }
+
+ if(value.Extras!=null){
+ f.Key("extras");
+ (value.Extras as glTFExtension).Serialize(f);
+ }
+
+ if(!string.IsNullOrEmpty(value.SpecVersion)){
+ f.Key("specVersion");
+ f.Value(value.SpecVersion);
+ }
+
+ if(value.Shape!=null){
+ f.Key("shape");
+ Serialize_Shape(f, value.Shape);
+ }
+
+ f.EndMap();
+}
+
+public static void Serialize_Shape(JsonFormatter f, ExtendedColliderShape value)
+{
+ f.BeginMap();
+
+
+ if(value.Extensions!=null){
+ f.Key("extensions");
+ (value.Extensions as glTFExtension).Serialize(f);
+ }
+
+ if(value.Extras!=null){
+ f.Key("extras");
+ (value.Extras as glTFExtension).Serialize(f);
+ }
+
+ if(value.Sphere!=null){
+ f.Key("sphere");
+ __shape_Serialize_Sphere(f, value.Sphere);
+ }
+
+ if(value.Capsule!=null){
+ f.Key("capsule");
+ __shape_Serialize_Capsule(f, value.Capsule);
+ }
+
+ if(value.Plane!=null){
+ f.Key("plane");
+ __shape_Serialize_Plane(f, value.Plane);
+ }
+
+ f.EndMap();
+}
+
+public static void __shape_Serialize_Sphere(JsonFormatter f, ExtendedColliderShapeSphere value)
+{
+ f.BeginMap();
+
+
+ if(value.Offset!=null&&value.Offset.Count()>=3){
+ f.Key("offset");
+ __shape__sphere_Serialize_Offset(f, value.Offset);
+ }
+
+ if(value.Radius.HasValue){
+ f.Key("radius");
+ f.Value(value.Radius.GetValueOrDefault());
+ }
+
+ if(value.Inside.HasValue){
+ f.Key("inside");
+ f.Value(value.Inside.GetValueOrDefault());
+ }
+
+ f.EndMap();
+}
+
+public static void __shape__sphere_Serialize_Offset(JsonFormatter f, float[] value)
+{
+ f.BeginList();
+
+ foreach(var item in value)
+ {
+ f.Value(item);
+
+ }
+ f.EndList();
+}
+
+public static void __shape_Serialize_Capsule(JsonFormatter f, ExtendedColliderShapeCapsule value)
+{
+ f.BeginMap();
+
+
+ if(value.Offset!=null&&value.Offset.Count()>=3){
+ f.Key("offset");
+ __shape__capsule_Serialize_Offset(f, value.Offset);
+ }
+
+ if(value.Radius.HasValue){
+ f.Key("radius");
+ f.Value(value.Radius.GetValueOrDefault());
+ }
+
+ if(value.Tail!=null&&value.Tail.Count()>=3){
+ f.Key("tail");
+ __shape__capsule_Serialize_Tail(f, value.Tail);
+ }
+
+ if(value.Inside.HasValue){
+ f.Key("inside");
+ f.Value(value.Inside.GetValueOrDefault());
+ }
+
+ f.EndMap();
+}
+
+public static void __shape__capsule_Serialize_Offset(JsonFormatter f, float[] value)
+{
+ f.BeginList();
+
+ foreach(var item in value)
+ {
+ f.Value(item);
+
+ }
+ f.EndList();
+}
+
+public static void __shape__capsule_Serialize_Tail(JsonFormatter f, float[] value)
+{
+ f.BeginList();
+
+ foreach(var item in value)
+ {
+ f.Value(item);
+
+ }
+ f.EndList();
+}
+
+public static void __shape_Serialize_Plane(JsonFormatter f, ExtendedColliderShapePlane value)
+{
+ f.BeginMap();
+
+
+ if(value.Offset!=null&&value.Offset.Count()>=3){
+ f.Key("offset");
+ __shape__plane_Serialize_Offset(f, value.Offset);
+ }
+
+ if(value.Normal!=null&&value.Normal.Count()>=3){
+ f.Key("normal");
+ __shape__plane_Serialize_Normal(f, value.Normal);
+ }
+
+ f.EndMap();
+}
+
+public static void __shape__plane_Serialize_Offset(JsonFormatter f, float[] value)
+{
+ f.BeginList();
+
+ foreach(var item in value)
+ {
+ f.Value(item);
+
+ }
+ f.EndList();
+}
+
+public static void __shape__plane_Serialize_Normal(JsonFormatter f, float[] value)
+{
+ f.BeginList();
+
+ foreach(var item in value)
+ {
+ f.Value(item);
+
+ }
+ f.EndList();
+}
+
+ } // class
+} // namespace
diff --git a/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Serializer.g.cs.meta b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Serializer.g.cs.meta
new file mode 100644
index 000000000..43d7c548c
--- /dev/null
+++ b/Assets/VRM10/Runtime/Format/SpringBoneExtendedCollider/Serializer.g.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a96731f2fb44d4d43a94e9c52d4361b5
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs
index 62144854f..7a26cd8d5 100644
--- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs
+++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs
@@ -324,6 +324,68 @@ namespace UniVRM10
return shape;
}
+ static UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShape ExportShapeExtended(VRM10SpringBoneCollider z)
+ {
+ var shape = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShape();
+ switch (z.ColliderType)
+ {
+ case VRM10SpringBoneColliderTypes.Sphere:
+ {
+ shape.Sphere = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeSphere
+ {
+ Radius = z.Radius,
+ Offset = ReverseX(z.Offset),
+ };
+ break;
+ }
+
+ case VRM10SpringBoneColliderTypes.Capsule:
+ {
+ shape.Capsule = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeCapsule
+ {
+ Radius = z.Radius,
+ Offset = ReverseX(z.Offset),
+ Tail = ReverseX(z.Tail),
+ };
+ break;
+ }
+
+ case VRM10SpringBoneColliderTypes.SphereInside:
+ {
+ shape.Sphere = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeSphere
+ {
+ Radius = z.Radius,
+ Offset = ReverseX(z.Offset),
+ Inside = true,
+ };
+ break;
+ }
+
+ case VRM10SpringBoneColliderTypes.CapsuleInside:
+ {
+ shape.Capsule = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeCapsule
+ {
+ Radius = z.Radius,
+ Offset = ReverseX(z.Offset),
+ Tail = ReverseX(z.Tail),
+ };
+ break;
+ }
+
+ case VRM10SpringBoneColliderTypes.Plane:
+ {
+ shape.Plane = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapePlane
+ {
+ Offset = ReverseX(z.Offset),
+ Normal = ReverseX(z.Normal),
+ };
+ break;
+ }
+ break;
+ }
+ return shape;
+ }
+
static UniGLTF.Extensions.VRMC_springBone.SpringBoneJoint ExportJoint(VRM10SpringBoneJoint y, Func getIndexFromTransform)
{
var joint = new UniGLTF.Extensions.VRMC_springBone.SpringBoneJoint
@@ -369,11 +431,22 @@ namespace UniVRM10
foreach (var c in colliders)
{
- springBone.Colliders.Add(new UniGLTF.Extensions.VRMC_springBone.Collider
+ var exportCollider = new UniGLTF.Extensions.VRMC_springBone.Collider
{
Node = getNodeIndexFromTransform(c.transform),
Shape = ExportShape(c),
- });
+ };
+ if (c.ColliderType == VRM10SpringBoneColliderTypes.SphereInside
+ || c.ColliderType == VRM10SpringBoneColliderTypes.CapsuleInside
+ || c.ColliderType == VRM10SpringBoneColliderTypes.Plane
+ )
+ {
+ exportCollider.Extensions = new UniGLTF.Extensions.VRMC_springBone_extended_collider.VRMC_springBone_extended_collider
+ {
+ Shape = ExportShapeExtended(c),
+ };
+ }
+ springBone.Colliders.Add(exportCollider);
}
// colliderGroups
diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs
index 65b201ae4..98d7ac94b 100644
--- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs
+++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs
@@ -538,6 +538,41 @@ namespace UniVRM10
{
throw new Vrm10Exception("unknown shape");
}
+
+ // https://github.com/vrm-c/vrm-specification/tree/master/specification/VRMC_springBone_extended_collider-1.0
+ // VRMC_springBone_extended_collider
+ if (UniGLTF.Extensions.VRMC_springBone_extended_collider.GltfDeserializer.TryGet(c.Extensions as glTFExtension,
+ out UniGLTF.Extensions.VRMC_springBone_extended_collider.VRMC_springBone_extended_collider exCollider))
+ {
+ if (exCollider.Shape.Sphere is UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeSphere exSphere)
+ {
+ collider.ColliderType = exSphere.Inside.GetValueOrDefault() ? VRM10SpringBoneColliderTypes.SphereInside : VRM10SpringBoneColliderTypes.Sphere;
+ collider.Offset = Vector3InvertX(exSphere.Offset);
+ collider.Radius = exSphere.Radius.Value;
+ if (exSphere.Inside.HasValue && exSphere.Inside.Value)
+ {
+ collider.ColliderType = VRM10SpringBoneColliderTypes.SphereInside;
+ }
+ }
+ else if (exCollider.Shape.Capsule is UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeCapsule exCapsule)
+ {
+ collider.ColliderType = exCapsule.Inside.GetValueOrDefault() ? VRM10SpringBoneColliderTypes.CapsuleInside : VRM10SpringBoneColliderTypes.Capsule;
+ collider.Offset = Vector3InvertX(exCapsule.Offset);
+ collider.Tail = Vector3InvertX(exCapsule.Tail);
+ collider.Radius = exCapsule.Radius.Value;
+ }
+ else if (exCollider.Shape.Plane is UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapePlane exPlane)
+ {
+ collider.ColliderType = VRM10SpringBoneColliderTypes.Plane;
+ collider.Offset = Vector3InvertX(exPlane.Offset);
+ collider.Normal = Vector3InvertX(exPlane.Normal);
+ collider.Radius = 0.1f; // gizmo visualize. 10cm
+ }
+ else
+ {
+ throw new Vrm10Exception("VRMC_springBone_extended_collider: unknown shape");
+ }
+ }
}
}
diff --git a/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs
index e52a898dc..7150476bf 100644
--- a/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs
+++ b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs
@@ -181,10 +181,6 @@ namespace UniVRM10
{ if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.blink), nameof(Vrm10AnimationInstance.preset_blink), preset.Blink) is ExpressionInfo info) yield return info; }
{ if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.blinkLeft), nameof(Vrm10AnimationInstance.preset_blinkleft), preset.BlinkLeft) is ExpressionInfo info) yield return info; }
{ if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.blinkRight), nameof(Vrm10AnimationInstance.preset_blinkright), preset.BlinkRight) is ExpressionInfo info) yield return info; }
- { if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.lookUp), "preset_lookup", preset.LookUp) is ExpressionInfo info) yield return info; }
- { if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.lookDown), "preset_lookdown", preset.LookDown) is ExpressionInfo info) yield return info; }
- { if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.lookLeft), "preset_lookleft", preset.LookLeft) is ExpressionInfo info) yield return info; }
- { if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.lookRight), "preset_lookright", preset.LookRight) is ExpressionInfo info) yield return info; }
{ if (GetExpression(gltfAnimation, ExpressionKey.CreateFromPreset(ExpressionPreset.neutral), nameof(Vrm10AnimationInstance.preset_neutral), preset.Neutral) is ExpressionInfo info) yield return info; }
}
if (animation.Expressions.Custom != null)
diff --git a/vrm-specification b/vrm-specification
index 0bcc3d4c5..7f5252a94 160000
--- a/vrm-specification
+++ b/vrm-specification
@@ -1 +1 @@
-Subproject commit 0bcc3d4c56311ea36905049b10908a4eb60aa327
+Subproject commit 7f5252a94208fc127b59eb4ce2fd699e6ae3ca6e