From f0cd4039c08ab350d4b4cb074865aa2d742e7449 Mon Sep 17 00:00:00 2001 From: AoiKamishiro Date: Wed, 13 Aug 2025 16:59:05 +0900 Subject: [PATCH 1/9] =?UTF-8?q?chor:=20URP=E7=89=88=E3=82=B7=E3=82=A7?= =?UTF-8?q?=E3=83=BC=E3=83=80=E3=83=BC=E3=81=AB=20ApplicationSpaceWarp?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM10/MToon10/Editor/MToonInspector.cs | 1 + .../UnityShaderLab/Properties/MToon10Prop.cs | 3 ++ .../Properties/MToon10Properties.cs | 2 ++ .../Shaders/vrmc_materials_mtoon_urp.shader | 31 ++++++++++++++++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Assets/VRM10/MToon10/Editor/MToonInspector.cs b/Assets/VRM10/MToon10/Editor/MToonInspector.cs index 0c8a3a05d..488234c5e 100644 --- a/Assets/VRM10/MToon10/Editor/MToonInspector.cs +++ b/Assets/VRM10/MToon10/Editor/MToonInspector.cs @@ -249,6 +249,7 @@ namespace VRM10.MToon10.Editor EditorGUILayout.LabelField("DstBlend", ((BlendMode)props[MToon10Prop.UnityDstBlend].floatValue).ToString()); EditorGUILayout.LabelField("ZWrite", ((UnityZWriteMode)props[MToon10Prop.UnityZWrite].floatValue).ToString()); EditorGUILayout.LabelField("AlphaToMask", ((UnityAlphaToMaskMode)props[MToon10Prop.UnityAlphaToMask].floatValue).ToString()); + EditorGUILayout.LabelField("XR Motion Vectors Pass (Space Warp)", (props[MToon10Prop.MotionVector].floatValue) > 0.5f ? "Enabled" : "Disabled"); EditorGUILayout.LabelField("Enabled Keywords", string.Join("\n", mat.shaderKeywords), EditorStyles.textArea); } } diff --git a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs index f3e896097..b9078c6a1 100644 --- a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs +++ b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs @@ -56,6 +56,9 @@ UnityDstBlend, UnityZWrite, UnityAlphaToMask, + + // Motion Vector + MotionVector, // for Editor EditorEditMode, diff --git a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs index fa9904d85..a467fba78 100644 --- a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs +++ b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs @@ -53,6 +53,8 @@ namespace VRM10.MToon10 [MToon10Prop.UnityZWrite] = "_M_ZWrite", [MToon10Prop.UnityAlphaToMask] = "_M_AlphaToMask", + [MToon10Prop.MotionVector] = "_XRMotionVectorsPass", + [MToon10Prop.EditorEditMode] = "_M_EditMode", }; diff --git a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader index 881ea9aa0..224001b0c 100644 --- a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader +++ b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader @@ -57,11 +57,14 @@ Shader "VRM10/Universal Render Pipeline/MToon10" _M_ZWrite ("_ZWrite", Float) = 1.0 _M_AlphaToMask ("_AlphaToMask", Float) = 0.0 + // Motion Vector + _XRMotionVectorsPass("_XRMotionVectorsPass", Float) = 1.0 + // etc _M_DebugMode ("_DebugMode", Float) = 0.0 // for Editor - _M_EditMode ("_EditMode", Float) = 0.0 + _M_EditMode ("_EditMode", Float) = 0.0 } // Shader Model 3.0 @@ -81,6 +84,32 @@ Shader "VRM10/Universal Render Pipeline/MToon10" "IgnoreProjector" = "True" } + Pass + { + Name "XRMotionVectors" + Tags { "LightMode" = "XRMotionVectors" } + ColorMask RGBA + + // Stencil write for obj motion pixels + Stencil + { + WriteMask 1 + Ref 1 + Comp Always + Pass Replace + } + + HLSLPROGRAM + #pragma shader_feature_local _ALPHATEST_ON + #pragma multi_compile _ LOD_FADE_CROSSFADE + #pragma shader_feature_local_vertex _ADD_PRECOMPUTED_VELOCITY + #define APPLICATION_SPACE_WARP_MOTION 1 + + #include "Packages/com.unity.render-pipelines.universal/Shaders/BakedLitInput.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ObjectMotionVectors.hlsl" + ENDHLSL + } + // Universal Forward Pass Pass { From 870d540de6226bb43c128322cf98534886f8aec9 Mon Sep 17 00:00:00 2001 From: Aoi Kamishiro Date: Fri, 15 Aug 2025 10:19:28 +0900 Subject: [PATCH 2/9] =?UTF-8?q?=E4=B8=8D=E5=BF=85=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E5=B7=AE=E5=88=86=E3=81=8C=E7=99=BA=E7=94=9F=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader index 224001b0c..e2fe7f6e2 100644 --- a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader +++ b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader @@ -64,7 +64,7 @@ Shader "VRM10/Universal Render Pipeline/MToon10" _M_DebugMode ("_DebugMode", Float) = 0.0 // for Editor - _M_EditMode ("_EditMode", Float) = 0.0 + _M_EditMode ("_EditMode", Float) = 0.0 } // Shader Model 3.0 From 05ad6b8aa1c66035ea720cbe019211cbf08044ab Mon Sep 17 00:00:00 2001 From: AoiKamishiro Date: Mon, 8 Sep 2025 10:38:49 +0900 Subject: [PATCH 3/9] =?UTF-8?q?Revert=20"=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E3=81=AA=E5=B7=AE=E5=88=86=E3=81=8C=E7=99=BA=E7=94=9F=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 870d540de6226bb43c128322cf98534886f8aec9. --- Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader index e2fe7f6e2..224001b0c 100644 --- a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader +++ b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader @@ -64,7 +64,7 @@ Shader "VRM10/Universal Render Pipeline/MToon10" _M_DebugMode ("_DebugMode", Float) = 0.0 // for Editor - _M_EditMode ("_EditMode", Float) = 0.0 + _M_EditMode ("_EditMode", Float) = 0.0 } // Shader Model 3.0 From e63b1802c0e3aed3710a75417fbe1a02b4e924b4 Mon Sep 17 00:00:00 2001 From: AoiKamishiro Date: Mon, 8 Sep 2025 10:38:55 +0900 Subject: [PATCH 4/9] =?UTF-8?q?Revert=20"chor:=20URP=E7=89=88=E3=82=B7?= =?UTF-8?q?=E3=82=A7=E3=83=BC=E3=83=80=E3=83=BC=E3=81=AB=20ApplicationSpac?= =?UTF-8?q?eWarp=E5=AF=BE=E5=BF=9C=E3=82=92=E8=BF=BD=E5=8A=A0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f0cd4039c08ab350d4b4cb074865aa2d742e7449. --- Assets/VRM10/MToon10/Editor/MToonInspector.cs | 1 - .../UnityShaderLab/Properties/MToon10Prop.cs | 3 -- .../Properties/MToon10Properties.cs | 2 -- .../Shaders/vrmc_materials_mtoon_urp.shader | 31 +------------------ 4 files changed, 1 insertion(+), 36 deletions(-) diff --git a/Assets/VRM10/MToon10/Editor/MToonInspector.cs b/Assets/VRM10/MToon10/Editor/MToonInspector.cs index 488234c5e..0c8a3a05d 100644 --- a/Assets/VRM10/MToon10/Editor/MToonInspector.cs +++ b/Assets/VRM10/MToon10/Editor/MToonInspector.cs @@ -249,7 +249,6 @@ namespace VRM10.MToon10.Editor EditorGUILayout.LabelField("DstBlend", ((BlendMode)props[MToon10Prop.UnityDstBlend].floatValue).ToString()); EditorGUILayout.LabelField("ZWrite", ((UnityZWriteMode)props[MToon10Prop.UnityZWrite].floatValue).ToString()); EditorGUILayout.LabelField("AlphaToMask", ((UnityAlphaToMaskMode)props[MToon10Prop.UnityAlphaToMask].floatValue).ToString()); - EditorGUILayout.LabelField("XR Motion Vectors Pass (Space Warp)", (props[MToon10Prop.MotionVector].floatValue) > 0.5f ? "Enabled" : "Disabled"); EditorGUILayout.LabelField("Enabled Keywords", string.Join("\n", mat.shaderKeywords), EditorStyles.textArea); } } diff --git a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs index b9078c6a1..f3e896097 100644 --- a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs +++ b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Prop.cs @@ -56,9 +56,6 @@ UnityDstBlend, UnityZWrite, UnityAlphaToMask, - - // Motion Vector - MotionVector, // for Editor EditorEditMode, diff --git a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs index a467fba78..fa9904d85 100644 --- a/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs +++ b/Assets/VRM10/MToon10/Runtime/UnityShaderLab/Properties/MToon10Properties.cs @@ -53,8 +53,6 @@ namespace VRM10.MToon10 [MToon10Prop.UnityZWrite] = "_M_ZWrite", [MToon10Prop.UnityAlphaToMask] = "_M_AlphaToMask", - [MToon10Prop.MotionVector] = "_XRMotionVectorsPass", - [MToon10Prop.EditorEditMode] = "_M_EditMode", }; diff --git a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader index 224001b0c..881ea9aa0 100644 --- a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader +++ b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader @@ -57,14 +57,11 @@ Shader "VRM10/Universal Render Pipeline/MToon10" _M_ZWrite ("_ZWrite", Float) = 1.0 _M_AlphaToMask ("_AlphaToMask", Float) = 0.0 - // Motion Vector - _XRMotionVectorsPass("_XRMotionVectorsPass", Float) = 1.0 - // etc _M_DebugMode ("_DebugMode", Float) = 0.0 // for Editor - _M_EditMode ("_EditMode", Float) = 0.0 + _M_EditMode ("_EditMode", Float) = 0.0 } // Shader Model 3.0 @@ -84,32 +81,6 @@ Shader "VRM10/Universal Render Pipeline/MToon10" "IgnoreProjector" = "True" } - Pass - { - Name "XRMotionVectors" - Tags { "LightMode" = "XRMotionVectors" } - ColorMask RGBA - - // Stencil write for obj motion pixels - Stencil - { - WriteMask 1 - Ref 1 - Comp Always - Pass Replace - } - - HLSLPROGRAM - #pragma shader_feature_local _ALPHATEST_ON - #pragma multi_compile _ LOD_FADE_CROSSFADE - #pragma shader_feature_local_vertex _ADD_PRECOMPUTED_VELOCITY - #define APPLICATION_SPACE_WARP_MOTION 1 - - #include "Packages/com.unity.render-pipelines.universal/Shaders/BakedLitInput.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ObjectMotionVectors.hlsl" - ENDHLSL - } - // Universal Forward Pass Pass { From 5321414a72465af0536ae51e334c8d6edfca4366 Mon Sep 17 00:00:00 2001 From: AoiKamishiro Date: Mon, 8 Sep 2025 10:39:34 +0900 Subject: [PATCH 5/9] =?UTF-8?q?chor:=20AppSW=E7=94=A8XRMotionVector?= =?UTF-8?q?=E3=83=91=E3=82=B9=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Shaders/vrmc_materials_mtoon_urp.shader | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader index 881ea9aa0..74a890cdf 100644 --- a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader +++ b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader @@ -251,6 +251,32 @@ Shader "VRM10/Universal Render Pipeline/MToon10" #include "./vrmc_materials_mtoon_shadowcaster_fragment.hlsl" ENDHLSL } + + Pass + { + Name "XRMotionVectors" + Tags { "LightMode" = "XRMotionVectors" } + ColorMask RGBA + + // Stencil write for obj motion pixels + Stencil + { + WriteMask 1 + Ref 1 + Comp Always + Pass Replace + } + + HLSLPROGRAM + #pragma shader_feature_local _ALPHATEST_ON + #pragma multi_compile _ LOD_FADE_CROSSFADE + #pragma shader_feature_local_vertex _ADD_PRECOMPUTED_VELOCITY + #define APPLICATION_SPACE_WARP_MOTION 1 + + #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ObjectMotionVectors.hlsl" + ENDHLSL + } } FallBack "Hidden/Universal Render Pipeline/FallbackError" From d986dadee0bf150f4aa6d9955eb9cf3b3b584182 Mon Sep 17 00:00:00 2001 From: AoiKamishiro Date: Mon, 8 Sep 2025 10:41:37 +0900 Subject: [PATCH 6/9] =?UTF-8?q?chor:=20PackageRequirements=20=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Shaders/vrmc_materials_mtoon_urp.shader | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader index 74a890cdf..1916bec17 100644 --- a/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader +++ b/Assets/VRM10/MToon10/Shaders/vrmc_materials_mtoon_urp.shader @@ -67,12 +67,6 @@ Shader "VRM10/Universal Render Pipeline/MToon10" // Shader Model 3.0 SubShader { - PackageRequirements - { - "unity": "2021.3" - "com.unity.render-pipelines.universal": "12.0.0" - } - Tags { "RenderType" = "Opaque" @@ -84,6 +78,12 @@ Shader "VRM10/Universal Render Pipeline/MToon10" // Universal Forward Pass Pass { + PackageRequirements + { + "unity": "2021.3" + "com.unity.render-pipelines.universal": "12.0.0" + } + Name "UniversalForward" Tags { "LightMode" = "UniversalForward" } @@ -132,6 +132,12 @@ Shader "VRM10/Universal Render Pipeline/MToon10" // MToon Outline Pass Pass { + PackageRequirements + { + "unity": "2021.3" + "com.unity.render-pipelines.universal": "12.0.0" + } + Name "MToonOutline" Tags { "LightMode" = "MToonOutline" } @@ -171,6 +177,12 @@ Shader "VRM10/Universal Render Pipeline/MToon10" // Depth Only Pass Pass { + PackageRequirements + { + "unity": "2021.3" + "com.unity.render-pipelines.universal": "12.0.0" + } + Name "DepthOnly" Tags { "LightMode" = "DepthOnly" } @@ -199,6 +211,12 @@ Shader "VRM10/Universal Render Pipeline/MToon10" // Depth Normals Pass Pass { + PackageRequirements + { + "unity": "2021.3" + "com.unity.render-pipelines.universal": "12.0.0" + } + Name "DepthNormals" Tags { "LightMode" = "DepthNormals" } @@ -227,6 +245,12 @@ Shader "VRM10/Universal Render Pipeline/MToon10" // Shadow Caster Pass Pass { + PackageRequirements + { + "unity": "2021.3" + "com.unity.render-pipelines.universal": "12.0.0" + } + Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } @@ -254,6 +278,12 @@ Shader "VRM10/Universal Render Pipeline/MToon10" Pass { + PackageRequirements + { + "unity": "6000.0" + "com.unity.render-pipelines.universal": "17.0.0" + } + Name "XRMotionVectors" Tags { "LightMode" = "XRMotionVectors" } ColorMask RGBA From a9e9ec7b3b26944973b348f9ee0d8bd202f5202e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 9 Sep 2025 15:01:21 +0900 Subject: [PATCH 7/9] generate --- .../VRM10/Editor/Vrm10SerializerGenerator.cs | 8 + .../VRM10/Runtime/Format/SpringBoneLimit.meta | 8 + .../Format/SpringBoneLimit/Deserializer.g.cs | 236 ++++++++++++++++++ .../SpringBoneLimit/Deserializer.g.cs.meta | 11 + .../Format/SpringBoneLimit/Format.g.cs | 91 +++++++ .../Format/SpringBoneLimit/Format.g.cs.meta | 11 + .../Format/SpringBoneLimit/Serializer.g.cs | 218 ++++++++++++++++ .../SpringBoneLimit/Serializer.g.cs.meta | 11 + 8 files changed, 594 insertions(+) create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit.meta create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs.meta create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs.meta create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs create mode 100644 Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs.meta diff --git a/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs b/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs index 0229699b6..5cb7d8a34 100644 --- a/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs +++ b/Assets/VRM10/Editor/Vrm10SerializerGenerator.cs @@ -86,6 +86,14 @@ namespace UniVRM10 $"{Vrm10SpecDir}/VRMC_springBone_extended_collider-1.0/schema/VRMC_springBone_extended_collider.schema.json", $"{Vrm10FormatGeneratedDir}/SpringBoneExtendedCollider" ), + + // VRMC_springBone_limit-1.0 + // (experimental) + // https://github.com/0b5vr/vrm-specification/tree/springBone-limit + new GenerateInfo( + $"{Vrm10SpecDir}/VRMC_springBone_limit-1.0/schema/VRMC_springBone_limit.schema.json", + $"{Vrm10FormatGeneratedDir}/SpringBoneLimit" + ), }; foreach (var arg in args) diff --git a/Assets/VRM10/Runtime/Format/SpringBoneLimit.meta b/Assets/VRM10/Runtime/Format/SpringBoneLimit.meta new file mode 100644 index 000000000..8b9e26e5e --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6b6c07a37ce7d2348beb488d3c2fad01 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs new file mode 100644 index 000000000..16fb7981a --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs @@ -0,0 +1,236 @@ +// 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_limit { + +public static class GltfDeserializer +{ + public static readonly Utf8String ExtensionNameUtf8 = Utf8String.From(VRMC_springBone_limit.ExtensionName); + +public static bool TryGet(UniGLTF.glTFExtension src, out VRMC_springBone_limit 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_limit Deserialize(JsonNode parsed) +{ + var value = new VRMC_springBone_limit(); + + 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=="limit"){ + value.Limit = Deserialize_Limit(kv.Value); + continue; + } + + } + return value; +} + +public static Limit Deserialize_Limit(JsonNode parsed) +{ + var value = new Limit(); + + 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=="cone"){ + value.Cone = __limit_Deserialize_Cone(kv.Value); + continue; + } + + if(key=="hinge"){ + value.Hinge = __limit_Deserialize_Hinge(kv.Value); + continue; + } + + if(key=="spherical"){ + value.Spherical = __limit_Deserialize_Spherical(kv.Value); + continue; + } + + } + return value; +} + +public static ConeLimit __limit_Deserialize_Cone(JsonNode parsed) +{ + var value = new ConeLimit(); + + 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=="angle"){ + value.Angle = kv.Value.GetSingle(); + continue; + } + + if(key=="rotation"){ + value.Rotation = __limit__cone_Deserialize_Rotation(kv.Value); + continue; + } + + } + return value; +} + +public static float[] __limit__cone_Deserialize_Rotation(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 HingeLimit __limit_Deserialize_Hinge(JsonNode parsed) +{ + var value = new HingeLimit(); + + 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=="angle"){ + value.Angle = kv.Value.GetSingle(); + continue; + } + + if(key=="rotation"){ + value.Rotation = __limit__hinge_Deserialize_Rotation(kv.Value); + continue; + } + + } + return value; +} + +public static float[] __limit__hinge_Deserialize_Rotation(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 SphericalLimit __limit_Deserialize_Spherical(JsonNode parsed) +{ + var value = new SphericalLimit(); + + 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=="phi"){ + value.Phi = kv.Value.GetSingle(); + continue; + } + + if(key=="theta"){ + value.Theta = kv.Value.GetSingle(); + continue; + } + + if(key=="rotation"){ + value.Rotation = __limit__spherical_Deserialize_Rotation(kv.Value); + continue; + } + + } + return value; +} + +public static float[] __limit__spherical_Deserialize_Rotation(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/SpringBoneLimit/Deserializer.g.cs.meta b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs.meta new file mode 100644 index 000000000..ce3c9d1bd --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Deserializer.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91feea663efc32c40bc07c67bdc8b868 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs new file mode 100644 index 000000000..069ed2edd --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs @@ -0,0 +1,91 @@ +// This file is generated from JsonSchema. Don't modify this source code. +using System; +using System.Collections.Generic; + + +namespace UniGLTF.Extensions.VRMC_springBone_limit +{ + + public class ConeLimit + { + // Dictionary object with extension-specific objects. + public object Extensions; + + // Application-specific data. + public object Extras; + + // The angle of the cone limit in radians. If the angle is set to π or greater, the angle will be interpreted as π by the implementation. When the angle is set to π, the cone shape becomes a sphere. + public float? Angle; + + // The rotation from the default orientation of the cone limit. The rotation is represented as a quaternion (x, y, z, w), where w is the scalar. + public float[] Rotation; + } + + public class HingeLimit + { + // Dictionary object with extension-specific objects. + public object Extensions; + + // Application-specific data. + public object Extras; + + // The angle of the hinge limit in radians. If the angle is set to π or greater, the angle will be interpreted as π by the implementation. When the angle is set to π, the hinge shape becomes a full disc. + public float? Angle; + + // The rotation from the default orientation of the hinge limit. The rotation is represented as a quaternion (x, y, z, w), where w is the scalar. + public float[] Rotation; + } + + public class SphericalLimit + { + // Dictionary object with extension-specific objects. + public object Extensions; + + // Application-specific data. + public object Extras; + + // The phi angle of the spherical limit in radians. If the phi angle is set to π or greater, the angle will be interpreted as π by the implementation. + public float? Phi; + + // The theta angle of the spherical limit in radians. If the theta angle is set to π/2 or greater, the angle will be interpreted as π/2 by the implementation. + public float? Theta; + + // The rotation from the default orientation of the spherical limit. The rotation is represented as a quaternion (x, y, z, w), where w is the scalar. + public float[] Rotation; + } + + public class Limit + { + // Dictionary object with extension-specific objects. + public object Extensions; + + // Application-specific data. + public object Extras; + + // A limit that restricts the orientation of the spring in a cone shape. + public ConeLimit Cone; + + // A limit that restricts the orientation of the spring in a hinge shape. + public HingeLimit Hinge; + + // A limit that restricts the orientation of the spring in a spherical coordinate shape. + public SphericalLimit Spherical; + } + + public class VRMC_springBone_limit + { + public const string ExtensionName = "VRMC_springBone_limit"; + + // Dictionary object with extension-specific objects. + public object Extensions; + + // Application-specific data. + public object Extras; + + // Specification version of VRMC_springBone_limit. + public string SpecVersion; + + // Describes a limit apply to the spring. Either cone, hinge, or spherical must be present. + public Limit Limit; + } +} diff --git a/Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs.meta b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs.meta new file mode 100644 index 000000000..524099a2a --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Format.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40be47ec456e1cb46a3ce8a3ecb70910 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs new file mode 100644 index 000000000..1056a8989 --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs @@ -0,0 +1,218 @@ +// 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_limit { + + static public class GltfSerializer + { + + public static void SerializeTo(ref UniGLTF.glTFExtension dst, VRMC_springBone_limit 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_limit.ExtensionName, f.GetStoreBytes()); + } + + +public static void Serialize(JsonFormatter f, VRMC_springBone_limit 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.Limit!=null){ + f.Key("limit"); + Serialize_Limit(f, value.Limit); + } + + f.EndMap(); +} + +public static void Serialize_Limit(JsonFormatter f, Limit 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.Cone!=null){ + f.Key("cone"); + __limit_Serialize_Cone(f, value.Cone); + } + + if(value.Hinge!=null){ + f.Key("hinge"); + __limit_Serialize_Hinge(f, value.Hinge); + } + + if(value.Spherical!=null){ + f.Key("spherical"); + __limit_Serialize_Spherical(f, value.Spherical); + } + + f.EndMap(); +} + +public static void __limit_Serialize_Cone(JsonFormatter f, ConeLimit 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.Angle.HasValue){ + f.Key("angle"); + f.Value(value.Angle.GetValueOrDefault()); + } + + if(value.Rotation!=null&&value.Rotation.Count()>=4){ + f.Key("rotation"); + __limit__cone_Serialize_Rotation(f, value.Rotation); + } + + f.EndMap(); +} + +public static void __limit__cone_Serialize_Rotation(JsonFormatter f, float[] value) +{ + f.BeginList(); + + foreach(var item in value) + { + f.Value(item); + + } + f.EndList(); +} + +public static void __limit_Serialize_Hinge(JsonFormatter f, HingeLimit 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.Angle.HasValue){ + f.Key("angle"); + f.Value(value.Angle.GetValueOrDefault()); + } + + if(value.Rotation!=null&&value.Rotation.Count()>=4){ + f.Key("rotation"); + __limit__hinge_Serialize_Rotation(f, value.Rotation); + } + + f.EndMap(); +} + +public static void __limit__hinge_Serialize_Rotation(JsonFormatter f, float[] value) +{ + f.BeginList(); + + foreach(var item in value) + { + f.Value(item); + + } + f.EndList(); +} + +public static void __limit_Serialize_Spherical(JsonFormatter f, SphericalLimit 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.Phi.HasValue){ + f.Key("phi"); + f.Value(value.Phi.GetValueOrDefault()); + } + + if(value.Theta.HasValue){ + f.Key("theta"); + f.Value(value.Theta.GetValueOrDefault()); + } + + if(value.Rotation!=null&&value.Rotation.Count()>=4){ + f.Key("rotation"); + __limit__spherical_Serialize_Rotation(f, value.Rotation); + } + + f.EndMap(); +} + +public static void __limit__spherical_Serialize_Rotation(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/SpringBoneLimit/Serializer.g.cs.meta b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs.meta new file mode 100644 index 000000000..1ed147337 --- /dev/null +++ b/Assets/VRM10/Runtime/Format/SpringBoneLimit/Serializer.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02602b2f45f722f47a872ca0d1d8262d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 6c5b02fb15473f3d46e0660fc5ee175c42f6e45e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 9 Sep 2025 15:42:29 +0900 Subject: [PATCH 8/9] importer --- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index af6bdc9c1..2c285f069 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Threading.Tasks; using UniGLTF; +using UniGLTF.Extensions.VRMC_springBone_limit; using UniGLTF.Utils; using UnityEngine; @@ -626,6 +628,31 @@ namespace UniVRM10 joint.m_gravityDir = gltfJoint.GravityDir != null ? Vector3InvertX(gltfJoint.GravityDir) : Vector3.down; joint.m_gravityPower = gltfJoint.GravityPower.GetValueOrDefault(0.0f); joint.m_stiffnessForce = gltfJoint.Stiffness.GetValueOrDefault(1.0f); + + if (UniGLTF.Extensions.VRMC_springBone_limit.GltfDeserializer.TryGet(gltfJoint.Extensions as glTFExtension, + out var extensionSpringBoneLimit)) + { + if (extensionSpringBoneLimit.Limit.Cone is UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit cone) + { + joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone; + joint.m_angleLimitRotation = QuaternionFromFloat4(cone.Rotation); + joint.m_angleLimitAngle1 = cone.Angle.GetValueOrDefault(Mathf.PI * 0.5f); + } + else if (extensionSpringBoneLimit.Limit.Hinge is UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit hinge) + { + joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge; + joint.m_angleLimitRotation = QuaternionFromFloat4(hinge.Rotation); + joint.m_angleLimitAngle1 = hinge.Angle.GetValueOrDefault(Mathf.PI * 0.5f); + } + else if (extensionSpringBoneLimit.Limit.Spherical is UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit spherical) + { + joint.m_anglelimitType = UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical; + joint.m_angleLimitRotation = QuaternionFromFloat4(spherical.Rotation); + joint.m_angleLimitAngle1 = spherical.Theta.GetValueOrDefault(Mathf.PI * 0.5f); + joint.m_angleLimitAngle2 = spherical.Phi.GetValueOrDefault(Mathf.PI * 0.5f); + } + } + spring.Joints.Add(joint); } } @@ -633,6 +660,16 @@ namespace UniVRM10 } } + private static Quaternion QuaternionFromFloat4(float[] xyzw) + { + var q = (xyzw != null && xyzw.Length == 4) + ? new Quaternion(xyzw[0], xyzw[1], xyzw[2], xyzw[3]) + : Quaternion.identity + ; + // vrm-1.0 is x inverted + return Axes.X.Create().InvertQuaternion(q); + } + static AxisMask ConstraintAxes(bool[] flags) { var mask = default(AxisMask); From c14b32645f043149ac67344ccd7fe3f5006cf244 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 9 Sep 2025 16:34:48 +0900 Subject: [PATCH 9/9] exporter --- Assets/VRM10/Runtime/IO/Vrm10Exporter.cs | 65 ++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 34b51f3ca..1cad2eb9b 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -140,6 +140,12 @@ namespace UniVRM10 return new float[] { -v.x, v.y, v.z }; } + static float[] ReverseX(Quaternion q) + { + q = UniGLTF.Axes.X.Create().InvertQuaternion(q); + return new float[] { q.x, q.y, q.z, q.w }; + } + /// /// 必要な容量を計算 /// (sparseは考慮してないので大きめ) @@ -444,6 +450,65 @@ namespace UniVRM10 GravityDir = ReverseX(y.m_gravityDir), GravityPower = y.m_gravityPower, }; + + switch (y.m_anglelimitType) + { + case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone: + { + var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit + { + Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit + { + Cone = new UniGLTF.Extensions.VRMC_springBone_limit.ConeLimit + { + Rotation = ReverseX(y.m_angleLimitRotation), + Angle = y.m_angleLimitAngle1, + } + } + }; + glTFExtension extensions = default; + UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit); + joint.Extensions = extensions; + break; + } + case UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge: + { + var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit + { + Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit + { + Hinge = new UniGLTF.Extensions.VRMC_springBone_limit.HingeLimit + { + Rotation = ReverseX(y.m_angleLimitRotation), + Angle = y.m_angleLimitAngle1, + } + } + }; + glTFExtension extensions = default; + UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit); + joint.Extensions = extensions; + break; + } + case UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical: + { + var limit = new UniGLTF.Extensions.VRMC_springBone_limit.VRMC_springBone_limit + { + Limit = new UniGLTF.Extensions.VRMC_springBone_limit.Limit + { + Spherical = new UniGLTF.Extensions.VRMC_springBone_limit.SphericalLimit + { + Rotation = ReverseX(y.m_angleLimitRotation), + Theta = y.m_angleLimitAngle1, + Phi = y.m_angleLimitAngle2, + } + } + }; + glTFExtension extensions = default; + UniGLTF.Extensions.VRMC_springBone_limit.GltfSerializer.SerializeTo(ref extensions, limit); + joint.Extensions = extensions; + break; + } + } return joint; }