Skip to content

Commit

Permalink
Merge branch 'master' into fix/expression_override
Browse files Browse the repository at this point in the history
  • Loading branch information
ousttrue authored Oct 23, 2024
2 parents 8f3cb87 + 675bb7b commit 333ae76
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 50 deletions.
7 changes: 5 additions & 2 deletions Assets/VRM/Editor/Format/VRMEditorExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,11 @@ private static byte[] Export(

if (settings.PoseFreeze)
{
// 正規化
VRMBoneNormalizer.Execute(target, settings.ForceTPose, settings.FreezeMeshUseCurrentBlendShapeWeight);
using (var backup = new VrmGeometryBackup(target))
{
// 正規化
VRMBoneNormalizer.Execute(target, settings.ForceTPose, settings.FreezeMeshUseCurrentBlendShapeWeight);
}
}

// 元のBlendShapeClipに変更を加えないように複製
Expand Down
92 changes: 92 additions & 0 deletions Assets/VRM/Runtime/IO/VrmGeometryBackup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UniGLTF;

namespace VRM
{
/// <summary>
/// SpringBone, LookAt の座標を記録しておき、Dispose で復帰する。
/// </summary>
public class VrmGeometryBackup : IDisposable
{
struct VrmSpringBoneColliderBackup
{
struct Collider
{
Vector3 _offsetInWorld;
float _radiusMultLossyScale;

public Collider(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider)
{
_offsetInWorld = transform.TransformPoint(collider.Offset);
_radiusMultLossyScale = transform.UniformedLossyScale() * collider.Radius;
}

public void Restore(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider)
{
collider.Offset = transform.worldToLocalMatrix.MultiplyPoint(_offsetInWorld);
collider.Radius = _radiusMultLossyScale / transform.UniformedLossyScale();
}
}
Collider[] _colliers;

public VrmSpringBoneColliderBackup(VRMSpringBoneColliderGroup colliderGroup)
{
_colliers = colliderGroup.Colliders.Select(x => new Collider(colliderGroup.transform, x)).ToArray();
}

public void Restore(VRMSpringBoneColliderGroup colliderGroup)
{
for (int i = 0; i < colliderGroup.Colliders.Length; ++i)
{
_colliers[i].Restore(colliderGroup.transform, colliderGroup.Colliders[i]);
}
}
}

struct VrmSpringBoneBackup
{
Vector3 _gravityDirInWorld;
float _radiusMultLossyScale;

public VrmSpringBoneBackup(VRMSpringBone springBone)
{
_gravityDirInWorld = springBone.transform.TransformDirection(springBone.m_gravityDir);
_radiusMultLossyScale = springBone.transform.UniformedLossyScale() * springBone.m_hitRadius;
}
public void Restore(VRMSpringBone springBone)
{
springBone.m_gravityDir = springBone.transform.worldToLocalMatrix.MultiplyVector(_gravityDirInWorld);
springBone.m_hitRadius = _radiusMultLossyScale / springBone.transform.UniformedLossyScale();
}
}

Dictionary<VRMSpringBoneColliderGroup, VrmSpringBoneColliderBackup> _springBoneColliders;
Dictionary<VRMSpringBone, VrmSpringBoneBackup> _springBones;
VRMFirstPerson _firstPerson;
Vector3 _firstPersonOffsetInWorld;

public VrmGeometryBackup(GameObject root)
{
_springBoneColliders = root.GetComponentsInChildren<VRMSpringBoneColliderGroup>().ToDictionary(x => x, x => new VrmSpringBoneColliderBackup(x));
_springBones = root.GetComponentsInChildren<VRMSpringBone>().ToDictionary(x => x, x => new VrmSpringBoneBackup(x));
_firstPerson = root.GetComponent<VRMFirstPerson>();
_firstPersonOffsetInWorld = _firstPerson.transform.TransformPoint(_firstPerson.FirstPersonOffset);
}

public void Dispose()
{
foreach (var (k, v) in _springBoneColliders)
{
v.Restore(k);
}
foreach (var (k, v) in _springBones)
{
v.Restore(k);
}
_firstPerson.FirstPersonOffset = _firstPerson.transform.worldToLocalMatrix.MultiplyPoint(_firstPersonOffsetInWorld);
}
}
}
11 changes: 11 additions & 0 deletions Assets/VRM/Runtime/IO/VrmGeometryBackup.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 23 additions & 20 deletions Assets/VRM/Runtime/SpringBone/Jobs/FastSpringBoneReplacer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,34 @@ public static async Task<FastSpringBoneBuffer> MakeBufferAsync(GameObject root,
{
var component = components[i];
var colliders = new List<FastSpringBoneCollider>();
foreach (var group in component.ColliderGroups)
if (component.ColliderGroups != null)
{
if (group == null) continue;
if (awaitCaller != null)
{
await awaitCaller.NextFrame();
token.ThrowIfCancellationRequested();
}

foreach (var collider in group.Colliders)
foreach (var group in component.ColliderGroups)
{
if (collider == null) continue;
if (group == null) continue;
if (awaitCaller != null)
{
await awaitCaller.NextFrame();
token.ThrowIfCancellationRequested();
}

var c = new FastSpringBoneCollider
foreach (var collider in group.Colliders)
{
Transform = group.transform,
Collider = new BlittableCollider
if (collider == null) continue;

var c = new FastSpringBoneCollider
{
offset = collider.Offset,
radius = collider.Radius,
tailOrNormal = default,
colliderType = BlittableColliderType.Sphere
}
};
colliders.Add(c);
Transform = group.transform,
Collider = new BlittableCollider
{
offset = collider.Offset,
radius = collider.Radius,
tailOrNormal = default,
colliderType = BlittableColliderType.Sphere
}
};
colliders.Add(c);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ public class Vrm0XFastSpringboneRuntime : IVrm0XSpringBoneRuntime
SpringBoneJobs.FastSpringBoneService m_service;
FastSpringBoneBuffer m_buffer;

public Vrm0XFastSpringboneRuntime()
{
m_service = SpringBoneJobs.FastSpringBoneService.Instance;
}

public async Task InitializeAsync(GameObject vrm, IAwaitCaller awaitCaller)
{
m_vrm = vrm;
m_service = SpringBoneJobs.FastSpringBoneService.Instance;

// default update の停止
foreach (VRMSpringBone sb in vrm.GetComponentsInChildren<VRMSpringBone>())
Expand Down Expand Up @@ -69,9 +73,8 @@ async Task RegisterAsync(IAwaitCaller awaitCaller)

public void ReconstructSpringBone()
{
var disposer = m_vrm.gameObject.GetComponent<FastSpringBoneDisposer>();
Unregister();
var task = RegisterAsync(new ImmediateCaller());
var _ = RegisterAsync(new ImmediateCaller());
}

public void RestoreInitialTransform()
Expand Down
6 changes: 2 additions & 4 deletions Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ public Quaternion WorldRotationFromTailPosition(Transform m_transform, Vector3 n
/// <summary>
/// Verlet積分で次の位置を計算する
/// </summary>
public Vector3 VerletIntegration(float deltaTime, Transform center, Quaternion parentRotation,
SpringBoneSettings settings, SpringBoneJointState _state, float scalingFactor, Vector3 externalForce)
public Vector3 VerletIntegration(float deltaTime, Quaternion parentRotation,
SpringBoneSettings settings, SpringBoneJointState state, float scalingFactor, Vector3 externalForce)
{
var state = _state.ToWorld(center);

var nextTail = state.CurrentTail
+ (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ)
+ parentRotation * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime * scalingFactor // 親の回転による子ボーンの移動目標
Expand Down
5 changes: 3 additions & 2 deletions Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ SpringBoneSettings settings

for (int i = 0; i < m_joints.Count; ++i)
{
var (transform, init, state) = m_joints[i];
var (transform, init, _state) = m_joints[i];
var state = _state.ToWorld(scene.Center);

// Spring処理
var parentRotation = transform.parent != null ? transform.parent.rotation : Quaternion.identity;
Expand All @@ -166,7 +167,7 @@ SpringBoneSettings settings
// false の場合
// 拡大すると移動速度はだいたい同じ => SpringBone の角速度が遅くなる
var scalingFactor = settings.UseRuntimeScalingSupport ? transform.UniformedLossyScale() : 1.0f;
var nextTail = init.VerletIntegration(deltaTime, scene.Center, parentRotation, settings, state,
var nextTail = init.VerletIntegration(deltaTime, parentRotation, settings, state,
scalingFactor, scene.ExternalForce);

// 長さをboneLengthに強制
Expand Down
21 changes: 12 additions & 9 deletions Assets/VRM10/Editor/Vrm10ExportDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,18 @@ protected override void ExportPath(string path)
disposer.Push(copy);
root = copy;

// Transform の回転とスケールを Mesh に適用します。
// - BlendShape は現状がbakeされます
// - 回転とスケールが反映された新しい Mesh が作成されます
// - Transform の回転とスケールはクリアされます。world position を維持します
var newMeshMap = BoneNormalizer.NormalizeHierarchyFreezeMesh(root, m_settings.FreezeMeshUseCurrentBlendShapeWeight);

// SkinnedMeshRenderer.sharedMesh と MeshFilter.sharedMesh を新しいMeshで置き換える
BoneNormalizer.Replace(root, newMeshMap, m_settings.FreezeMeshKeepRotation);
}
using (var backup = new Vrm10GeometryBackup(root))
{
// Transform の回転とスケールを Mesh に適用します。
// - BlendShape は現状がbakeされます
// - 回転とスケールが反映された新しい Mesh が作成されます
// - Transform の回転とスケールはクリアされます。world position を維持します
var newMeshMap = BoneNormalizer.NormalizeHierarchyFreezeMesh(root, m_settings.FreezeMeshUseCurrentBlendShapeWeight);

// SkinnedMeshRenderer.sharedMesh と MeshFilter.sharedMesh を新しいMeshで置き換える
BoneNormalizer.Replace(root, newMeshMap, m_settings.FreezeMeshKeepRotation);
}
}

var converter = new UniVRM10.ModelExporter();
var model = converter.Export(arrayManager, root);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public class Vrm10FastSpringboneRuntime : IVrm10SpringBoneRuntime
private FastSpringBones.FastSpringBoneService m_fastSpringBoneService;
private FastSpringBoneBuffer m_fastSpringBoneBuffer;

public Vrm10FastSpringboneRuntime()
{
m_fastSpringBoneService = FastSpringBones.FastSpringBoneService.Instance;
}

public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings)
{
if (m_fastSpringBoneService.BufferCombiner.Combined is FastSpringBoneCombinedBuffer combined)
Expand All @@ -37,7 +42,6 @@ public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings

public async Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller)
{
m_fastSpringBoneService = FastSpringBones.FastSpringBoneService.Instance;
m_instance = instance;

// NOTE: FastSpringBoneService は UnitTest などでは動作しない
Expand All @@ -49,8 +53,11 @@ public async Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCall

public void Dispose()
{
m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer);
m_fastSpringBoneBuffer.Dispose();
if (m_fastSpringBoneBuffer != null)
{
m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer);
m_fastSpringBoneBuffer.Dispose();
}
}

/// <summary>
Expand Down
75 changes: 75 additions & 0 deletions Assets/VRM10/Runtime/IO/Vrm10GeometryBackup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UniGLTF;

namespace UniVRM10
{
/// <summary>
/// SpringBone, LookAt の座標を記録しておき、Dispose で復帰する。
/// </summary>
public class Vrm10GeometryBackup : IDisposable
{
struct Vrm10SpringBoneColliderBackup
{
Vector3 _offsetInWorld;
float _radiusMultLossyScale;

public Vrm10SpringBoneColliderBackup(VRM10SpringBoneCollider collider)
{
_offsetInWorld = collider.transform.TransformPoint(collider.Offset);
_radiusMultLossyScale = collider.transform.UniformedLossyScale() * collider.Radius;
}

public void Restore(VRM10SpringBoneCollider collider)
{
collider.Offset = collider.transform.worldToLocalMatrix.MultiplyPoint(_offsetInWorld);
collider.Radius = _radiusMultLossyScale / collider.transform.UniformedLossyScale();
}
}

struct Vrm10SpringBoneJointBackup
{
Vector3 _gravityDirInWorld;
float _radiusMultLossyScale;

public Vrm10SpringBoneJointBackup(VRM10SpringBoneJoint joint)
{
_gravityDirInWorld = joint.transform.TransformDirection(joint.m_gravityDir);
_radiusMultLossyScale = joint.transform.UniformedLossyScale() * joint.m_jointRadius;
}
public void Restore(VRM10SpringBoneJoint joint)
{
joint.m_gravityDir = joint.transform.worldToLocalMatrix.MultiplyVector(_gravityDirInWorld);
joint.m_jointRadius = _radiusMultLossyScale / joint.transform.UniformedLossyScale();
}
}

Dictionary<VRM10SpringBoneCollider, Vrm10SpringBoneColliderBackup> _springBoneColliders;
Dictionary<VRM10SpringBoneJoint, Vrm10SpringBoneJointBackup> _springBoneJoints;
Vrm10Instance _vrm;
Vector3 _lookAtOffsetInWorld;

public Vrm10GeometryBackup(GameObject root)
{
_springBoneColliders = root.GetComponentsInChildren<VRM10SpringBoneCollider>().ToDictionary(x => x, x => new Vrm10SpringBoneColliderBackup(x));
_springBoneJoints = root.GetComponentsInChildren<VRM10SpringBoneJoint>().ToDictionary(x => x, x => new Vrm10SpringBoneJointBackup(x));
_vrm = root.GetComponent<Vrm10Instance>();
_lookAtOffsetInWorld = _vrm.transform.TransformPoint(_vrm.Vrm.LookAt.OffsetFromHead);
}

public void Dispose()
{
foreach (var (k, v) in _springBoneColliders)
{
v.Restore(k);
}
foreach (var (k, v) in _springBoneJoints)
{
v.Restore(k);
}
_vrm.Vrm.LookAt.OffsetFromHead = _vrm.transform.worldToLocalMatrix.MultiplyPoint(_lookAtOffsetInWorld);
}
}
}
11 changes: 11 additions & 0 deletions Assets/VRM10/Runtime/IO/Vrm10GeometryBackup.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 333ae76

Please sign in to comment.