diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs index f3a47dcad..06863b2fc 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs @@ -139,5 +139,24 @@ namespace UniVRM10 throw new ArgumentOutOfRangeException(); } } + + public void RestoreInitialTransform() + { + // Spring の joint に対応する transform の回転を初期状態 + foreach (var (k, v) in m_initialData.TransformIndexMap) + { + k.localRotation = v.InitialLocalRotation; + } + + // 初期状態にしたtransformを使って spring logic を構築 + m_initialData.BlittableLogics.Clear(); + foreach (var spring in m_initialData.Springs) + { + m_initialData.AddLogic(spring); + } + + // DOTS バッファーを更新 + m_initialData.SyncAndZeroVelocity(m_fastSpringBoneBuffer.Logics); + } } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs index 64e47fbdd..1e0c01ead 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/InputPorts/FastSpringBoneBufferBuilder.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Unity.Collections; using UnityEngine; using UnityEngine.Profiling; using UniVRM10.FastSpringBones.Blittables; @@ -13,9 +14,17 @@ namespace UniVRM10.FastSpringBones.System public readonly List BlittableColliders = new(); public readonly List BlittableLogics = new(); public readonly Transform[] Transforms; - - public FastSpringBoneBufferBuilder(IReadOnlyList springs, bool simulateLastBone = false) + public struct TransformInfo { + public int Index; + public Quaternion InitialLocalRotation; + } + public readonly IDictionary TransformIndexMap; + public readonly FastSpringBoneSpring[] Springs; + + public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs, bool simulateLastBone = false) + { + Springs = springs; Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder"); var transformHashSet = new HashSet(); foreach (var spring in springs) @@ -34,8 +43,12 @@ namespace UniVRM10.FastSpringBones.System if (spring.center != null) transformHashSet.Add(spring.center); } Transforms = transformHashSet.ToArray(); - var transformIndexDictionary = Transforms.Select((trs, index) => (trs, index)) - .ToDictionary(tuple => tuple.trs, tuple => tuple.index); + TransformIndexMap = Transforms.Select((trs, index) => (trs, index)) + .ToDictionary(tuple => tuple.trs, tuple => new TransformInfo + { + Index = tuple.index, + InitialLocalRotation = tuple.trs.localRotation, + }); foreach (var spring in springs) { @@ -51,14 +64,14 @@ namespace UniVRM10.FastSpringBones.System startIndex = BlittableJoints.Count, count = simulateLastBone ? spring.joints.Length : spring.joints.Length - 1, }, - centerTransformIndex = spring.center ? transformIndexDictionary[spring.center] : -1, + centerTransformIndex = spring.center ? TransformIndexMap[spring.center].Index : -1, }; BlittableSprings.Add(blittableSpring); BlittableColliders.AddRange(spring.colliders.Select(collider => { var blittable = collider.Collider; - blittable.transformIndex = transformIndexDictionary[collider.Transform]; + blittable.transformIndex = TransformIndexMap[collider.Transform].Index; return blittable; })); BlittableJoints.AddRange(spring.joints @@ -68,56 +81,62 @@ namespace UniVRM10.FastSpringBones.System return blittable; })); - for (var i = 0; i < (simulateLastBone ? spring.joints.Length : spring.joints.Length - 1); ++i) + AddLogic(spring, simulateLastBone); + + } + Profiler.EndSample(); + } + + public void AddLogic(FastSpringBoneSpring spring, bool simulateLastBone = false) + { + for (var i = 0; i < (simulateLastBone ? spring.joints.Length : spring.joints.Length - 1); ++i) + { + var joint = spring.joints[i]; + var tailJoint = i + 1 < spring.joints.Length ? spring.joints[i + 1] : (FastSpringBoneJoint?)null; + var parentJoint = i - 1 >= 0 ? spring.joints[i - 1] : (FastSpringBoneJoint?)null; + var localPosition = Vector3.zero; + if (tailJoint.HasValue) { - var joint = spring.joints[i]; - var tailJoint = i + 1 < spring.joints.Length ? spring.joints[i + 1] : (FastSpringBoneJoint?)null; - var parentJoint = i - 1 >= 0 ? spring.joints[i - 1] : (FastSpringBoneJoint?)null; - var localPosition = Vector3.zero; - if (tailJoint.HasValue) + localPosition = tailJoint.Value.Transform.localPosition; + } + else + { + if (parentJoint.HasValue) { - localPosition = tailJoint.Value.Transform.localPosition; + var delta = joint.Transform.position - parentJoint.Value.Transform.position; + localPosition = + joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta); } else { - if (parentJoint.HasValue) - { - var delta = joint.Transform.position - parentJoint.Value.Transform.position; - localPosition = - joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta); - } - else - { - localPosition = Vector3.down; - } + localPosition = Vector3.down; } - - var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale; - var localChildPosition = - new Vector3( - localPosition.x * scale.x, - localPosition.y * scale.y, - localPosition.z * scale.z - ); - - var worldChildPosition = joint.Transform.TransformPoint(localChildPosition); - var currentTail = spring.center != null - ? spring.center.InverseTransformPoint(worldChildPosition) - : worldChildPosition; - var parent = joint.Transform.parent; - BlittableLogics.Add(new BlittableLogic - { - headTransformIndex = transformIndexDictionary[joint.Transform], - parentTransformIndex = parent != null ? transformIndexDictionary[parent] : -1, - currentTail = currentTail, - prevTail = currentTail, - localRotation = joint.DefaultLocalRotation, - boneAxis = localChildPosition.normalized, - length = localChildPosition.magnitude - }); } + + var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale; + var localChildPosition = + new Vector3( + localPosition.x * scale.x, + localPosition.y * scale.y, + localPosition.z * scale.z + ); + + var worldChildPosition = joint.Transform.TransformPoint(localChildPosition); + var currentTail = spring.center != null + ? spring.center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + var parent = joint.Transform.parent; + BlittableLogics.Add(new BlittableLogic + { + headTransformIndex = TransformIndexMap[joint.Transform].Index, + parentTransformIndex = parent != null ? TransformIndexMap[parent].Index : -1, + currentTail = currentTail, + prevTail = currentTail, + localRotation = joint.DefaultLocalRotation, + boneAxis = localChildPosition.normalized, + length = localChildPosition.magnitude + }); } - Profiler.EndSample(); } public unsafe void SetExternalDataPtr(BlittableExternalData* externalData) @@ -129,14 +148,18 @@ namespace UniVRM10.FastSpringBones.System // ExternalData = externalData, // }; var b = BlittableSprings[i]; - BlittableSprings[i] = new BlittableSpring - { - centerTransformIndex = b.centerTransformIndex, - colliderSpan = b.colliderSpan, - logicSpan = b.logicSpan, - transformIndexOffset = b.transformIndexOffset, - ExternalData = externalData, - }; + b.ExternalData = externalData; + BlittableSprings[i] = b; + } + } + + public unsafe void SyncAndZeroVelocity(NativeArray logics) + { + for (int i = 0; i < BlittableLogics.Count; ++i) + { + var l = BlittableLogics[i]; + l.prevTail = l.currentTail; + logics[i] = BlittableLogics[i]; } } } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity index 77c4b9464..54855ea3b 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Viewer.unity @@ -232,7 +232,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 15 + m_RootOrder: 16 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -773,7 +773,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1236,14 +1236,15 @@ RectTransform: - {fileID: 1621794411} - {fileID: 2009818432} - {fileID: 168425995} - - {fileID: 1307084561} - {fileID: 224350191} - {fileID: 1791103379} - {fileID: 1311520909} + - {fileID: 1307084561} - {fileID: 974864191} - {fileID: 1767706907} - {fileID: 1557052150} - {fileID: 1728528388} + - {fileID: 704896193} - {fileID: 597950322} - {fileID: 935566651} - {fileID: 634488421} @@ -1823,7 +1824,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 339774397} - m_RootOrder: 11 + m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1904,7 +1905,7 @@ RectTransform: - {fileID: 154330168} - {fileID: 1954133885} m_Father: {fileID: 339774397} - m_RootOrder: 17 + m_RootOrder: 18 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1991,7 +1992,7 @@ RectTransform: - {fileID: 2010083454} - {fileID: 1081455630} m_Father: {fileID: 339774397} - m_RootOrder: 13 + m_RootOrder: 14 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2247,6 +2248,128 @@ MonoBehaviour: m_ChildScaleWidth: 0 m_ChildScaleHeight: 0 m_ReverseArrangement: 0 +--- !u!1 &704896192 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 704896193} + - component: {fileID: 704896196} + - component: {fileID: 704896195} + - component: {fileID: 704896194} + m_Layer: 5 + m_Name: ResetSpringBone + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &704896193 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 983782643} + m_Father: {fileID: 339774397} + m_RootOrder: 11 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 162, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &704896194 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 704896195} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &704896195 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &704896196 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704896192} + m_CullTransparentMesh: 0 --- !u!1 &773923918 GameObject: m_ObjectHideFlags: 0 @@ -3398,7 +3521,7 @@ RectTransform: - {fileID: 175751363} - {fileID: 1904789319} m_Father: {fileID: 339774397} - m_RootOrder: 12 + m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -3485,6 +3608,88 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 974864190} m_CullTransparentMesh: 0 +--- !u!1 &983782642 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 983782643} + - component: {fileID: 983782645} + - component: {fileID: 983782644} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &983782643 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 983782642} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 704896193} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &983782644 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 983782642} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ResetSpring + +' +--- !u!222 &983782645 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 983782642} + m_CullTransparentMesh: 0 --- !u!1 &1007924635 GameObject: m_ObjectHideFlags: 0 @@ -4950,7 +5155,7 @@ RectTransform: m_Children: - {fileID: 910859648} m_Father: {fileID: 339774397} - m_RootOrder: 3 + m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5147,7 +5352,7 @@ RectTransform: - {fileID: 1866921958} - {fileID: 1767669911} m_Father: {fileID: 339774397} - m_RootOrder: 6 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5444,7 +5649,7 @@ RectTransform: - {fileID: 452923209} - {fileID: 2090837017} m_Father: {fileID: 339774397} - m_RootOrder: 16 + m_RootOrder: 17 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -6444,7 +6649,7 @@ RectTransform: - {fileID: 62367395} - {fileID: 1037763549} m_Father: {fileID: 339774397} - m_RootOrder: 14 + m_RootOrder: 15 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -6619,6 +6824,7 @@ MonoBehaviour: m_pastePose: {fileID: 1307084564} m_showBoxMan: {fileID: 1767706908} m_pauseSpringBone: {fileID: 1728528389} + m_resetSpringBone: {fileID: 704896194} m_enableLipSync: {fileID: 935566650} m_enableAutoBlink: {fileID: 634488422} m_enableAutoExpression: {fileID: 1767738855} @@ -6677,7 +6883,7 @@ RectTransform: - {fileID: 1166391799} - {fileID: 1140410864} m_Father: {fileID: 339774397} - m_RootOrder: 5 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index c3ba3c2ec..f0f842ae2 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -30,6 +30,9 @@ namespace UniVRM10.VRM10Viewer [SerializeField] Toggle m_pauseSpringBone = default; + [SerializeField] + Button m_resetSpringBone = default; + [SerializeField] Toggle m_enableLipSync = default; @@ -255,6 +258,7 @@ namespace UniVRM10.VRM10Viewer m_openModel = buttons.First(x => x.name == "OpenModel"); m_openMotion = buttons.First(x => x.name == "OpenMotion"); m_pastePose = buttons.First(x => x.name == "PastePose"); + m_resetSpringBone = buttons.First(x => x.name == "ResetSpringBone"); #if UNITY_2022_3_OR_NEWER var toggles = GameObject.FindObjectsByType(FindObjectsSortMode.InstanceID); @@ -351,6 +355,7 @@ namespace UniVRM10.VRM10Viewer m_openModel.onClick.AddListener(OnOpenModelClicked); m_openMotion.onClick.AddListener(OnOpenMotionClicked); m_pastePose.onClick.AddListener(OnPastePoseClicked); + m_resetSpringBone.onClick.AddListener(OnResetSpringBoneClicked); // load initial bvh if (m_motion != null) @@ -490,6 +495,17 @@ namespace UniVRM10.VRM10Viewer } } + void OnResetSpringBoneClicked() + { + if (m_loaded != null) + { + if (m_loaded.Runtime != null) + { + m_loaded.Runtime.SpringBone.RestoreInitialTransform(); + } + } + } + static IMaterialDescriptorGenerator GetVrmMaterialDescriptorGenerator(bool useUrp) { if (useUrp)