mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-06-02 22:14:30 -05:00
Merge branch 'master' into fix/inputMaxValue
This commit is contained in:
commit
a3067ef7cc
21
Assets/UniGLTF/Runtime/Extensions/TransformExtensions.cs
Normal file
21
Assets/UniGLTF/Runtime/Extensions/TransformExtensions.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public static class TransformExtensions
|
||||
{
|
||||
public static float UniformedLossyScale(this Transform transform)
|
||||
{
|
||||
var s = transform.lossyScale;
|
||||
return AbsoluteMaxValue(s);
|
||||
}
|
||||
|
||||
public static float AbsoluteMaxValue(in Vector3 s)
|
||||
{
|
||||
var x = Mathf.Abs(s.x);
|
||||
var y = Mathf.Abs(s.y);
|
||||
var z = Mathf.Abs(s.z);
|
||||
return Mathf.Max(Mathf.Max(x, y), z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// 外力等の毎フレーム更新されうる外部から与えられる情報
|
||||
/// </summary>
|
||||
public struct BlittableExternalData
|
||||
{
|
||||
public Vector3 ExternalForce;
|
||||
|
||||
/// <summary>
|
||||
/// if false, spring bone is paused.
|
||||
/// </summary>
|
||||
public bool IsSpringBoneEnabled;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
public struct BlittableModelLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// World 座標系の追加の力。風など。
|
||||
/// </summary>
|
||||
public Vector3 ExternalForce;
|
||||
|
||||
/// <summary>
|
||||
/// 処理結果の Transform への書き戻しを停止する。
|
||||
/// </summary>
|
||||
public bool StopSpringBoneWriteback;
|
||||
|
||||
/// <summary>
|
||||
/// スケール値に連動して SpringBone のパラメータを自動調整する。
|
||||
/// (見た目の角速度が同じになるようにする)
|
||||
/// </summary>
|
||||
public bool SupportsScalingAtRuntime;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,6 @@ namespace UniGLTF.SpringBoneJobs.Blittables
|
|||
public BlittableSpan logicSpan;
|
||||
public int centerTransformIndex;
|
||||
public int transformIndexOffset;
|
||||
public unsafe BlittableExternalData* ExternalData;
|
||||
public int modelIndex;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using Unity.Jobs;
|
||||
using UnityEngine.Profiling;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,48 +20,58 @@ namespace UniGLTF.SpringBoneJobs
|
|||
/// </summary>
|
||||
public class FastSpringBoneCombinedBuffer : IDisposable
|
||||
{
|
||||
// 長さと index 同じ
|
||||
// Joint Level
|
||||
private NativeArray<BlittableJointImmutable> _logics;
|
||||
private NativeArray<BlittableJointMutable> _joints;
|
||||
private NativeArray<Vector3> _prevTails;
|
||||
private NativeArray<Vector3> _currentTails;
|
||||
private NativeArray<Vector3> _nextTails;
|
||||
|
||||
// Spring Level
|
||||
private NativeArray<BlittableSpring> _springs;
|
||||
// Moodel Level
|
||||
private NativeArray<BlittableModelLevel> _models;
|
||||
|
||||
// その他
|
||||
private NativeArray<BlittableCollider> _colliders;
|
||||
|
||||
private NativeArray<BlittableTransform> _transforms;
|
||||
private TransformAccessArray _transformAccessArray;
|
||||
|
||||
// accessor: Joint Level
|
||||
public NativeArray<BlittableJointImmutable> Logics => _logics;
|
||||
public NativeArray<BlittableJointMutable> Joints => _joints;
|
||||
public NativeArray<Vector3> PrevTails => _prevTails;
|
||||
public NativeArray<Vector3> CurrentTails => _currentTails;
|
||||
public NativeArray<Vector3> NextTails => _nextTails;
|
||||
|
||||
// accessor: Spring Level
|
||||
public NativeArray<BlittableSpring> Springs => _springs;
|
||||
|
||||
// accessor: Model LEvel
|
||||
public NativeArray<BlittableModelLevel> Models => _models;
|
||||
// accessor: Other
|
||||
public NativeArray<BlittableCollider> Colliders => _colliders;
|
||||
|
||||
public NativeArray<BlittableTransform> Transforms => _transforms;
|
||||
public TransformAccessArray TransformAccessArray => _transformAccessArray;
|
||||
|
||||
// 構築情報
|
||||
private FastSpringBoneBuffer[] _batchedBuffers;
|
||||
private int[] _batchedBufferLogicSizes;
|
||||
private Dictionary<Transform, int> _modelMap = new();
|
||||
private Dictionary<Transform, int> _jointMap = new();
|
||||
|
||||
private FastSpringBoneCombinedBuffer(int logicsCount, int springsCount, int collidersCount, int transformsCount,
|
||||
private FastSpringBoneCombinedBuffer(int logicsCount, int springsCount, int modelCount, int collidersCount, int transformsCount,
|
||||
FastSpringBoneBuffer[] batchedBuffers,
|
||||
int[] batchedBufferLogicSizes
|
||||
)
|
||||
{
|
||||
// joint level
|
||||
_logics = new NativeArray<BlittableJointImmutable>(logicsCount, Allocator.Persistent);
|
||||
_joints = new NativeArray<BlittableJointMutable>(logicsCount, Allocator.Persistent);
|
||||
_prevTails = new NativeArray<Vector3>(logicsCount, Allocator.Persistent);
|
||||
_currentTails = new NativeArray<Vector3>(logicsCount, Allocator.Persistent);
|
||||
_nextTails = new NativeArray<Vector3>(logicsCount, Allocator.Persistent);
|
||||
// spring level
|
||||
_springs = new NativeArray<BlittableSpring>(springsCount, Allocator.Persistent);
|
||||
// model level
|
||||
_models = new NativeArray<BlittableModelLevel>(modelCount, Allocator.Persistent);
|
||||
// others
|
||||
_colliders = new NativeArray<BlittableCollider>(collidersCount, Allocator.Persistent);
|
||||
_transforms = new NativeArray<BlittableTransform>(transformsCount, Allocator.Persistent);
|
||||
_batchedBuffers = batchedBuffers;
|
||||
|
|
@ -93,8 +103,8 @@ namespace UniGLTF.SpringBoneJobs
|
|||
|
||||
// バッファの構築
|
||||
Profiler.BeginSample("FastSpringBone.ReconstructBuffers.CreateBuffers");
|
||||
combined = new FastSpringBoneCombinedBuffer(logicsCount, springsCount, collidersCount, transformsCount,
|
||||
batchedBuffers, batchedBufferLogicSizes);
|
||||
combined = new FastSpringBoneCombinedBuffer(logicsCount, springsCount, _buffers.Count,
|
||||
collidersCount, transformsCount, batchedBuffers, batchedBufferLogicSizes);
|
||||
Profiler.EndSample();
|
||||
|
||||
return combined.Batching(handle);
|
||||
|
|
@ -110,6 +120,14 @@ namespace UniGLTF.SpringBoneJobs
|
|||
for (var i = 0; i < _batchedBuffers.Length; i++)
|
||||
{
|
||||
var buffer = _batchedBuffers[i];
|
||||
// 逆引き
|
||||
_modelMap.Add(buffer.Model, i);
|
||||
|
||||
for (var j = 0; j < _batchedBufferLogicSizes[i]; ++j)
|
||||
{
|
||||
var head = buffer.Logics[j].headTransformIndex;
|
||||
_jointMap.Add(buffer.Transforms[head], logicsOffset + j);
|
||||
}
|
||||
|
||||
// バッファの読み込みをスケジュール
|
||||
handle = new LoadTransformsJob
|
||||
|
|
@ -121,6 +139,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
|
||||
handle = new LoadSpringsJob
|
||||
{
|
||||
ModelIndex = i,
|
||||
SrcSprings = buffer.Springs,
|
||||
DestSprings = new NativeSlice<BlittableSpring>(_springs, springsOffset, buffer.Springs.Length),
|
||||
CollidersOffset = collidersOffset,
|
||||
|
|
@ -173,12 +192,17 @@ namespace UniGLTF.SpringBoneJobs
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
// joint
|
||||
if (_logics.IsCreated) _logics.Dispose();
|
||||
if (_joints.IsCreated) _joints.Dispose();
|
||||
if (_prevTails.IsCreated) _prevTails.Dispose();
|
||||
if (_currentTails.IsCreated) _currentTails.Dispose();
|
||||
if (_nextTails.IsCreated) _nextTails.Dispose();
|
||||
// spring
|
||||
if (_springs.IsCreated) _springs.Dispose();
|
||||
// model
|
||||
if (_models.IsCreated) _models.Dispose();
|
||||
// other
|
||||
if (_colliders.IsCreated) _colliders.Dispose();
|
||||
if (_transforms.IsCreated) _transforms.Dispose();
|
||||
if (_transformAccessArray.isCreated) _transformAccessArray.Dispose();
|
||||
|
|
@ -211,6 +235,22 @@ namespace UniGLTF.SpringBoneJobs
|
|||
_nextTails = tmp;
|
||||
}
|
||||
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings)
|
||||
{
|
||||
if (_jointMap.TryGetValue(joint, out var jointIndex))
|
||||
{
|
||||
_joints[jointIndex] = jointSettings;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetModelLevel(Transform model, BlittableModelLevel modelSetting)
|
||||
{
|
||||
if (_modelMap.TryGetValue(model, out var modelIndex))
|
||||
{
|
||||
_models[modelIndex] = modelSetting;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
[BurstCompile]
|
||||
#endif
|
||||
|
|
@ -236,6 +276,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
[ReadOnly] public NativeArray<BlittableSpring> SrcSprings;
|
||||
[WriteOnly] public NativeSlice<BlittableSpring> DestSprings;
|
||||
|
||||
public int ModelIndex;
|
||||
public int CollidersOffset;
|
||||
public int LogicsOffset;
|
||||
public int TransformOffset;
|
||||
|
|
@ -243,6 +284,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
public void Execute(int index)
|
||||
{
|
||||
var spring = SrcSprings[index];
|
||||
spring.modelIndex = ModelIndex;
|
||||
spring.colliderSpan.startIndex += CollidersOffset;
|
||||
spring.logicSpan.startIndex += LogicsOffset;
|
||||
spring.transformIndexOffset = TransformOffset;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
PrevTail = combined.PrevTails,
|
||||
NextTail = combined.NextTails,
|
||||
Springs = combined.Springs,
|
||||
Models = combined.Models,
|
||||
Colliders = combined.Colliders,
|
||||
Transforms = combined.Transforms,
|
||||
DeltaTime = deltaTime,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
|
|
@ -14,6 +13,10 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
/// </summary>
|
||||
public class FastSpringBoneBuffer : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// model root
|
||||
/// </summary>
|
||||
public Transform Model { get; }
|
||||
// NOTE: これらはFastSpringBoneBufferCombinerによってバッチングされる
|
||||
public NativeArray<BlittableSpring> Springs { get; }
|
||||
public NativeArray<BlittableJointMutable> Joints { get; }
|
||||
|
|
@ -23,34 +26,6 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
public Transform[] Transforms { get; }
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
// NOTE: これは更新頻度が高くバッチングが難しいため、ランダムアクセスを許容してメモリへ直接アクセスする
|
||||
// 生のヒープ領域は扱いにくいので長さ1のNativeArrayで代用
|
||||
private NativeArray<BlittableExternalData> _externalData;
|
||||
public Vector3 ExternalForce
|
||||
{
|
||||
get => _externalData[0].ExternalForce;
|
||||
set
|
||||
{
|
||||
_externalData[0] = new BlittableExternalData
|
||||
{
|
||||
ExternalForce = value,
|
||||
IsSpringBoneEnabled = _externalData[0].IsSpringBoneEnabled,
|
||||
};
|
||||
}
|
||||
}
|
||||
public bool IsSpringBoneEnabled
|
||||
{
|
||||
get => _externalData[0].IsSpringBoneEnabled;
|
||||
set
|
||||
{
|
||||
_externalData[0] = new BlittableExternalData
|
||||
{
|
||||
ExternalForce = _externalData[0].ExternalForce,
|
||||
IsSpringBoneEnabled = value,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Joint, Collider, Center の Transform のリスト
|
||||
/// - 重複を除去
|
||||
|
|
@ -79,18 +54,13 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
return Transforms;
|
||||
}
|
||||
|
||||
public unsafe FastSpringBoneBuffer(FastSpringBoneSpring[] springs)
|
||||
public FastSpringBoneBuffer(Transform model, FastSpringBoneSpring[] springs)
|
||||
{
|
||||
Model = model;
|
||||
|
||||
Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder");
|
||||
Transforms = MakeFlattenTransformList(springs);
|
||||
_externalData = new NativeArray<BlittableExternalData>(1, Allocator.Persistent);
|
||||
_externalData[0] = new BlittableExternalData
|
||||
{
|
||||
ExternalForce = Vector3.zero,
|
||||
IsSpringBoneEnabled = true,
|
||||
};
|
||||
|
||||
var externalDataPtr = (BlittableExternalData*)_externalData.GetUnsafePtr();
|
||||
List<BlittableSpring> blittableSprings = new();
|
||||
List<BlittableJointMutable> blittableJoints = new();
|
||||
List<BlittableCollider> blittableColliders = new();
|
||||
|
|
@ -110,7 +80,6 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
count = spring.joints.Length - 1,
|
||||
},
|
||||
centerTransformIndex = Array.IndexOf(Transforms, spring.center),
|
||||
ExternalData = externalDataPtr,
|
||||
};
|
||||
blittableSprings.Add(blittableSpring);
|
||||
|
||||
|
|
@ -134,7 +103,16 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
Joints = new NativeArray<BlittableJointMutable>(blittableJoints.ToArray(), Allocator.Persistent);
|
||||
Colliders = new NativeArray<BlittableCollider>(blittableColliders.ToArray(), Allocator.Persistent);
|
||||
Logics = new NativeArray<BlittableJointImmutable>(blittableLogics.ToArray(), Allocator.Persistent);
|
||||
BlittableTransforms = new NativeArray<BlittableTransform>(Transforms.Length, Allocator.Persistent);
|
||||
BlittableTransforms = new NativeArray<BlittableTransform>(Transforms.Select(transform => new BlittableTransform
|
||||
{
|
||||
position = transform.position,
|
||||
rotation = transform.rotation,
|
||||
localPosition = transform.localPosition,
|
||||
localRotation = transform.localRotation,
|
||||
localScale = transform.localScale,
|
||||
localToWorldMatrix = transform.localToWorldMatrix,
|
||||
worldToLocalMatrix = transform.worldToLocalMatrix
|
||||
}).ToArray(), Allocator.Persistent);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +160,6 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
BlittableTransforms.Dispose();
|
||||
Colliders.Dispose();
|
||||
Logics.Dispose();
|
||||
_externalData.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
{
|
||||
"name": "SpringBoneJobs",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"references": [
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
|
|
|
|||
|
|
@ -12,33 +12,44 @@ namespace UniGLTF.SpringBoneJobs
|
|||
#if ENABLE_SPRINGBONE_BURST
|
||||
[BurstCompile]
|
||||
#endif
|
||||
/// <summary>
|
||||
/// データの粒度
|
||||
/// - Joint Level: spring の節。Transform. stiffness など
|
||||
/// - Spring Level: spring の房。root から末端まで。この房 level で並列処理する
|
||||
/// - Model Level: 一人分。複数の房
|
||||
/// - System Level: すべての model。delta time とか
|
||||
/// </summary>
|
||||
public struct UpdateFastSpringBoneJob : IJobParallelFor
|
||||
{
|
||||
// Joint Level
|
||||
// すべての spring の joint を平坦に連結した配列
|
||||
// Joints, Logics, PrevTail, CurrentTail, NextTail は同じ index
|
||||
[ReadOnly] public NativeArray<BlittableJointMutable> Joints;
|
||||
[ReadOnly] public NativeArray<BlittableJointImmutable> Logics;
|
||||
[ReadOnly] public NativeArray<Vector3> PrevTail;
|
||||
[ReadOnly] public NativeArray<Vector3> CurrentTail;
|
||||
// ランダムアクセス
|
||||
// 処理後の tail 位置(ランダムアクセス)
|
||||
[NativeDisableParallelForRestriction] public NativeArray<Vector3> NextTail;
|
||||
|
||||
// Spring Level
|
||||
[ReadOnly] public NativeArray<BlittableSpring> Springs;
|
||||
// Model Level
|
||||
[ReadOnly] public NativeArray<BlittableModelLevel> Models;
|
||||
|
||||
[ReadOnly] public NativeArray<BlittableCollider> Colliders;
|
||||
|
||||
// FastSpringBoneBuffer.Transforms を連結したもの
|
||||
// ランダムアクセス
|
||||
// FastSpringBoneBuffer.Transforms を連結したもの(ランダムアクセス)
|
||||
[NativeDisableParallelForRestriction] public NativeArray<BlittableTransform> Transforms;
|
||||
|
||||
// System Level
|
||||
public float DeltaTime;
|
||||
|
||||
public unsafe void Execute(int index)
|
||||
/// <param name="index">房のindex</param>
|
||||
public void Execute(int index)
|
||||
{
|
||||
var spring = Springs[index];
|
||||
var transformIndexOffset = spring.transformIndexOffset;
|
||||
var colliderSpan = spring.colliderSpan;
|
||||
var logicSpan = spring.logicSpan;
|
||||
var model = Models[spring.modelIndex];
|
||||
|
||||
for (var logicIndex = logicSpan.startIndex; logicIndex < logicSpan.startIndex + logicSpan.count; ++logicIndex)
|
||||
{
|
||||
|
|
@ -70,13 +81,16 @@ namespace UniGLTF.SpringBoneJobs
|
|||
|
||||
var parentRotation = parentTransform?.rotation ?? Quaternion.identity;
|
||||
|
||||
// scaling 対応
|
||||
var scalingFactor = model.SupportsScalingAtRuntime ? TransformExtensions.AbsoluteMaxValue(headTransform.localToWorldMatrix.lossyScale) : 1.0f;
|
||||
|
||||
// verlet積分で次の位置を計算
|
||||
var external = (joint.gravityDir * joint.gravityPower + spring.ExternalData->ExternalForce) * DeltaTime;
|
||||
var external = (joint.gravityDir * joint.gravityPower + model.ExternalForce) * DeltaTime;
|
||||
var nextTail = currentTail
|
||||
+ (currentTail - prevTail) * (1.0f - joint.dragForce) // 前フレームの移動を継続する(減衰もあるよ)
|
||||
+ parentRotation * logic.localRotation * logic.boneAxis *
|
||||
joint.stiffnessForce * DeltaTime // 親の回転による子ボーンの移動目標
|
||||
+ external; // 外力による移動量
|
||||
joint.stiffnessForce * DeltaTime * scalingFactor // 親の回転による子ボーンの移動目標
|
||||
+ external * scalingFactor; // 外力による移動量
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = headTransform.position + (nextTail - headTransform.position).normalized * logic.length;
|
||||
|
|
@ -153,7 +167,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
headTransform.localRotation = headTransform.rotation;
|
||||
}
|
||||
|
||||
if (spring.ExternalData->IsSpringBoneEnabled)
|
||||
if (!model.StopSpringBoneWriteback)
|
||||
{
|
||||
// SpringBone の結果を Transform に反映する
|
||||
Transforms[logic.headTransformIndex + transformIndexOffset] = headTransform;
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
public static class TransformExtensions
|
||||
{
|
||||
public static float UniformedLossyScale(this Transform transform)
|
||||
{
|
||||
// Mathf.Max(a, b, c) は GC どうなんだろう
|
||||
var s = transform.lossyScale;
|
||||
var x = Mathf.Abs(s.x);
|
||||
var y = Mathf.Abs(s.y);
|
||||
var z = Mathf.Abs(s.z);
|
||||
if (x < y)
|
||||
{
|
||||
if (y < z)
|
||||
{
|
||||
return z;
|
||||
}
|
||||
else
|
||||
{
|
||||
return y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x < z)
|
||||
{
|
||||
return z;
|
||||
}
|
||||
else
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM
|
||||
|
|
@ -7,5 +8,27 @@ namespace VRM
|
|||
public interface IVrm0XSpringBoneRuntime
|
||||
{
|
||||
public Task InitializeAsync(GameObject vrm, IAwaitCaller awaitCaller);
|
||||
|
||||
/// <summary>
|
||||
/// SpringBone の構成変更を反映して再構築する。
|
||||
/// </summary>
|
||||
public void ReconstructSpringBone();
|
||||
|
||||
/// <summary>
|
||||
/// initialTransform 状態に復帰。verlet の速度 も 0 に。
|
||||
/// </summary>
|
||||
public void RestoreInitialTransform();
|
||||
|
||||
/// <summary>
|
||||
/// Joint レベルの可変情報をセットする
|
||||
/// stiffness,
|
||||
/// </summary>
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Model レベルの可変情報をセットする
|
||||
/// 風, pause, scaling
|
||||
/// </summary>
|
||||
public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,24 +5,17 @@ using UniGLTF.SpringBoneJobs.Blittables;
|
|||
using UniGLTF;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using UniGLTF.Utils;
|
||||
|
||||
|
||||
namespace VRM.SpringBoneJobs
|
||||
{
|
||||
public static class FastSpringBoneReplacer
|
||||
{
|
||||
/// <summary>
|
||||
/// - 指定された GameObject 内にある SpringBone を停止させる
|
||||
/// - FastSpringBoneBuffer に変換する
|
||||
/// </summary>
|
||||
public static async Task<FastSpringBoneBuffer> MakeBufferAsync(GameObject root, IAwaitCaller awaitCaller = null, CancellationToken token = default)
|
||||
{
|
||||
var components = root.GetComponentsInChildren<VRMSpringBone>();
|
||||
foreach (var sb in components)
|
||||
{
|
||||
// 停止させて FastSpringBoneService から実行させる
|
||||
sb.m_updateType = VRMSpringBone.SpringBoneUpdateType.Manual;
|
||||
}
|
||||
|
||||
var springs = new FastSpringBoneSpring[components.Length];
|
||||
for (int i = 0; i < components.Length; ++i)
|
||||
|
|
@ -57,6 +50,9 @@ namespace VRM.SpringBoneJobs
|
|||
}
|
||||
}
|
||||
|
||||
var runtime = root.GetComponent<RuntimeGltfInstance>();
|
||||
var initMap = runtime != null ? runtime.InitialTransformStates : root.GetComponentsInChildren<Transform>().ToDictionary(x => x, x => new TransformState(x));
|
||||
|
||||
var joints = new List<FastSpringBoneJoint>();
|
||||
foreach (var springRoot in component.RootBones)
|
||||
{
|
||||
|
|
@ -67,7 +63,7 @@ namespace VRM.SpringBoneJobs
|
|||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
Traverse(joints, component, springRoot);
|
||||
Traverse(joints, component, springRoot, initMap);
|
||||
}
|
||||
|
||||
var spring = new FastSpringBoneSpring
|
||||
|
|
@ -79,14 +75,14 @@ namespace VRM.SpringBoneJobs
|
|||
springs[i] = spring;
|
||||
}
|
||||
|
||||
return new FastSpringBoneBuffer(springs);
|
||||
return new FastSpringBoneBuffer(root.transform, springs);
|
||||
}
|
||||
|
||||
static void Traverse(List<FastSpringBoneJoint> joints, VRMSpringBone spring, Transform joint)
|
||||
static void Traverse(List<FastSpringBoneJoint> joints, VRMSpringBone spring, Transform joint, IReadOnlyDictionary<Transform, TransformState> initMap)
|
||||
{
|
||||
joints.Add(new FastSpringBoneJoint
|
||||
{
|
||||
Transform = joint.transform,
|
||||
Transform = joint,
|
||||
Joint = new BlittableJointMutable
|
||||
{
|
||||
radius = spring.m_hitRadius,
|
||||
|
|
@ -95,11 +91,11 @@ namespace VRM.SpringBoneJobs
|
|||
gravityPower = spring.m_gravityPower,
|
||||
stiffnessForce = spring.m_stiffnessForce
|
||||
},
|
||||
DefaultLocalRotation = joint.transform.localRotation,
|
||||
DefaultLocalRotation = initMap[joint.transform].LocalRotation,
|
||||
});
|
||||
foreach (Transform child in joint)
|
||||
{
|
||||
Traverse(joints, spring, child);
|
||||
Traverse(joints, spring, child, initMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM
|
||||
|
|
@ -16,26 +18,78 @@ namespace VRM
|
|||
/// </summary>
|
||||
public class Vrm0XFastSpringboneRuntime : IVrm0XSpringBoneRuntime
|
||||
{
|
||||
GameObject m_vrm;
|
||||
SpringBoneJobs.FastSpringBoneService m_service;
|
||||
FastSpringBoneBuffer m_buffer;
|
||||
|
||||
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>())
|
||||
{
|
||||
sb.m_updateType = VRMSpringBone.SpringBoneUpdateType.Manual;
|
||||
}
|
||||
|
||||
// create
|
||||
var buffer = await SpringBoneJobs.FastSpringBoneReplacer.MakeBufferAsync(vrm, awaitCaller);
|
||||
SpringBoneJobs.FastSpringBoneService.Instance.BufferCombiner.Register(buffer);
|
||||
|
||||
// disposer
|
||||
var disposer = vrm.AddComponent<FastSpringBoneDisposer>()
|
||||
var disposer = m_vrm.AddComponent<FastSpringBoneDisposer>()
|
||||
.AddAction(() =>
|
||||
{
|
||||
SpringBoneJobs.FastSpringBoneService.Instance.BufferCombiner.Unregister(buffer);
|
||||
buffer.Dispose();
|
||||
Unregister();
|
||||
})
|
||||
;
|
||||
|
||||
// create
|
||||
await RegisterAsync(awaitCaller);
|
||||
}
|
||||
|
||||
void Unregister()
|
||||
{
|
||||
Debug.Log("Vrm0XFastSpringboneRuntime.Unregister");
|
||||
if (m_buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_service.BufferCombiner.Unregister(m_buffer);
|
||||
m_buffer.Dispose();
|
||||
m_buffer = null;
|
||||
}
|
||||
|
||||
async Task RegisterAsync(IAwaitCaller awaitCaller)
|
||||
{
|
||||
Debug.Assert(m_buffer == null);
|
||||
var buffer = await SpringBoneJobs.FastSpringBoneReplacer.MakeBufferAsync(m_vrm, awaitCaller);
|
||||
m_buffer = buffer;
|
||||
SpringBoneJobs.FastSpringBoneService.Instance.BufferCombiner.Register(buffer);
|
||||
|
||||
}
|
||||
|
||||
public void ReconstructSpringBone()
|
||||
{
|
||||
var disposer = m_vrm.gameObject.GetComponent<FastSpringBoneDisposer>();
|
||||
Unregister();
|
||||
var task = RegisterAsync(new ImmediateCaller());
|
||||
}
|
||||
|
||||
public void RestoreInitialTransform()
|
||||
{
|
||||
if (m_buffer != null)
|
||||
{
|
||||
m_service.BufferCombiner.InitializeJointsLocalRotation(m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings)
|
||||
{
|
||||
m_service.BufferCombiner.Combined.SetJointLevel(joint, jointSettings);
|
||||
}
|
||||
|
||||
public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings)
|
||||
{
|
||||
m_service.BufferCombiner.Combined?.SetModelLevel(modelRoot, modelSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,11 +8,14 @@ namespace VRM.SpringBone
|
|||
public readonly IReadOnlyList<Transform> RootBones;
|
||||
public readonly Transform Center;
|
||||
public readonly VRMSpringBoneColliderGroup[] ColliderGroups;
|
||||
public readonly Vector3 ExternalForce;
|
||||
|
||||
public SceneInfo(
|
||||
IReadOnlyList<Transform> rootBones,
|
||||
Transform center,
|
||||
VRMSpringBoneColliderGroup[] colliderGroups) =>
|
||||
(RootBones, Center, ColliderGroups) = (rootBones, center, colliderGroups);
|
||||
VRMSpringBoneColliderGroup[] colliderGroups,
|
||||
Vector3 externalForce) =>
|
||||
(RootBones, Center, ColliderGroups, ExternalForce)
|
||||
= (rootBones, center, colliderGroups, externalForce);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM.SpringBone
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM.SpringBone
|
||||
|
|
@ -34,14 +35,14 @@ namespace VRM.SpringBone
|
|||
/// Verlet積分で次の位置を計算する
|
||||
/// </summary>
|
||||
public Vector3 VerletIntegration(float deltaTime, Transform center, Quaternion parentRotation,
|
||||
SpringBoneSettings settings, SpringBoneJointState _state, float scalingFactor)
|
||||
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 // 親の回転による子ボーンの移動目標
|
||||
+ settings.GravityDir * (settings.GravityPower * deltaTime) * scalingFactor; // 外力による移動量
|
||||
+ (settings.GravityDir * settings.GravityPower + externalForce) * deltaTime * scalingFactor; // 外力による移動量
|
||||
return nextTail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM.SpringBone
|
||||
|
|
@ -8,6 +9,7 @@ namespace VRM.SpringBone
|
|||
{
|
||||
Dictionary<Transform, Quaternion> m_initialLocalRotationMap;
|
||||
List<(Transform, SpringBoneJointInit, SpringBoneJointState)> m_joints = new();
|
||||
Dictionary<Transform, int> m_jointIndexMap = new();
|
||||
List<SphereCollider> m_colliders = new();
|
||||
|
||||
public void Setup(SceneInfo scene, bool force)
|
||||
|
|
@ -22,6 +24,7 @@ namespace VRM.SpringBone
|
|||
m_initialLocalRotationMap.Clear();
|
||||
}
|
||||
m_joints.Clear();
|
||||
m_jointIndexMap.Clear();
|
||||
|
||||
foreach (var go in scene.RootBones)
|
||||
{
|
||||
|
|
@ -32,6 +35,55 @@ namespace VRM.SpringBone
|
|||
SetupRecursive(scene.Center, go);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_joints.Count; ++i)
|
||||
{
|
||||
m_jointIndexMap.Add(m_joints[i].Item1, i);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReinitializeRotation(SceneInfo scene)
|
||||
{
|
||||
foreach (var go in scene.RootBones)
|
||||
{
|
||||
if (go != null)
|
||||
{
|
||||
ReinitializeRotationRecursive(scene.Center, go);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ReinitializeRotationRecursive(Transform center, Transform parent)
|
||||
{
|
||||
var index = m_jointIndexMap[parent];
|
||||
var (t, init, state) = m_joints[index];
|
||||
t.localRotation = m_initialLocalRotationMap[t];
|
||||
|
||||
Vector3 localPosition;
|
||||
Vector3 scale;
|
||||
if (parent.childCount == 0)
|
||||
{
|
||||
// 子ノードが無い。7cm 固定
|
||||
var delta = parent.position - parent.parent.position;
|
||||
var childPosition = parent.position + delta.normalized * 0.07f * parent.UniformedLossyScale();
|
||||
localPosition = parent.worldToLocalMatrix.MultiplyPoint(childPosition); // cancel scale
|
||||
scale = parent.lossyScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstChild = GetChildren(parent).First();
|
||||
localPosition = firstChild.localPosition;
|
||||
scale = firstChild.lossyScale;
|
||||
}
|
||||
var localChildPosition = new Vector3(
|
||||
localPosition.x * scale.x,
|
||||
localPosition.y * scale.y,
|
||||
localPosition.z * scale.z
|
||||
);
|
||||
|
||||
m_joints[index] = (t, init, new SpringBoneJointState(localChildPosition, localChildPosition));
|
||||
|
||||
foreach (Transform child in parent) SetupRecursive(center, child);
|
||||
}
|
||||
|
||||
private static IEnumerable<Transform> GetChildren(Transform parent)
|
||||
|
|
@ -114,7 +166,8 @@ namespace VRM.SpringBone
|
|||
// false の場合
|
||||
// 拡大すると移動速度はだいたい同じ => SpringBone の角速度が遅くなる
|
||||
var scalingFactor = settings.UseRuntimeScalingSupport ? transform.UniformedLossyScale() : 1.0f;
|
||||
var nextTail = init.VerletIntegration(deltaTime, scene.Center, parentRotation, settings, state, scalingFactor);
|
||||
var nextTail = init.VerletIntegration(deltaTime, scene.Center, parentRotation, settings, state,
|
||||
scalingFactor, scene.ExternalForce);
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = transform.position + (nextTail - transform.position).normalized * init.Length;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,14 @@ namespace VRM
|
|||
/// </summary>
|
||||
public bool UseRuntimeScalingSupport { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VRM-1.0 からのバックポート。
|
||||
/// - Runtime 制御用のパラメタである
|
||||
/// - シリアライズ対象でない
|
||||
/// - World座標系
|
||||
/// </summary>
|
||||
public Vector3 ExternalForce { get; set; }
|
||||
|
||||
public enum SpringBoneUpdateType
|
||||
{
|
||||
LateUpdate,
|
||||
|
|
@ -49,7 +57,9 @@ namespace VRM
|
|||
SpringBone.SceneInfo Scene => new(
|
||||
rootBones: RootBones,
|
||||
center: m_center,
|
||||
colliderGroups: ColliderGroups);
|
||||
colliderGroups: ColliderGroups,
|
||||
externalForce: ExternalForce);
|
||||
|
||||
SpringBone.SpringBoneSettings Settings => new
|
||||
(
|
||||
stiffnessForce: m_stiffnessForce,
|
||||
|
|
@ -68,6 +78,17 @@ namespace VRM
|
|||
}
|
||||
}
|
||||
|
||||
public void ReinitializeRotation()
|
||||
{
|
||||
m_system.ReinitializeRotation(Scene);
|
||||
}
|
||||
|
||||
public void SetModelLevel(UniGLTF.SpringBoneJobs.Blittables.BlittableModelLevel modelSettings)
|
||||
{
|
||||
UseRuntimeScalingSupport = modelSettings.SupportsScalingAtRuntime;
|
||||
ExternalForce = modelSettings.ExternalForce;
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (m_updateType == SpringBoneUpdateType.LateUpdate)
|
||||
|
|
@ -95,7 +116,7 @@ namespace VRM
|
|||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (Application.isPlaying && m_updateType!=SpringBoneUpdateType.Manual)
|
||||
if (Application.isPlaying && m_updateType != SpringBoneUpdateType.Manual)
|
||||
{
|
||||
m_system.PlayingGizmo(m_center, Settings, m_gizmoColor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM
|
||||
|
|
@ -13,13 +14,46 @@ namespace VRM
|
|||
/// </summary>
|
||||
public class Vrm0XSpringBoneDefaultRuntime : IVrm0XSpringBoneRuntime
|
||||
{
|
||||
GameObject m_vrm;
|
||||
public async Task InitializeAsync(GameObject vrm, IAwaitCaller awaitCaller)
|
||||
{
|
||||
m_vrm = vrm;
|
||||
|
||||
foreach (VRMSpringBone sb in vrm.GetComponentsInChildren<VRMSpringBone>())
|
||||
{
|
||||
sb.m_updateType = VRMSpringBone.SpringBoneUpdateType.LateUpdate;
|
||||
}
|
||||
await awaitCaller.NextFrame();
|
||||
}
|
||||
|
||||
public void ReconstructSpringBone()
|
||||
{
|
||||
foreach (VRMSpringBone sb in m_vrm.GetComponentsInChildren<VRMSpringBone>())
|
||||
{
|
||||
sb.Setup();
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreInitialTransform()
|
||||
{
|
||||
foreach (VRMSpringBone sb in m_vrm.GetComponentsInChildren<VRMSpringBone>())
|
||||
{
|
||||
sb.ReinitializeRotation();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings)
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings)
|
||||
{
|
||||
foreach (VRMSpringBone sb in m_vrm.GetComponentsInChildren<VRMSpringBone>())
|
||||
{
|
||||
sb.SetModelLevel(modelSettings);
|
||||
sb.m_updateType = modelSettings.StopSpringBoneWriteback ? VRMSpringBone.SpringBoneUpdateType.Manual : VRMSpringBone.SpringBoneUpdateType.LateUpdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,10 +74,9 @@ namespace UniVRM10
|
|||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// UniGLTF.UniGLTFLogger.Log("invaliate");
|
||||
if(m_root!=null)
|
||||
if (m_root != null)
|
||||
{
|
||||
m_root.Runtime.SpringBone.ReconstructSpringBone();
|
||||
m_root.Runtime.SpringBone.SetJointLevel(m_target.transform, m_target.Blittable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@
|
|||
"GUID:2ef84b520212e174a94668c7a0862d3b",
|
||||
"GUID:5f875fdc81c40184c8333b9d63c6ddd5",
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c",
|
||||
"GUID:da3e51d19d51a544fa14d43fee843098",
|
||||
"GUID:7da8a75dcade2144aab699032d7d7987",
|
||||
"GUID:b7aa47b240b57de44a4b2021c143c9bf",
|
||||
"GUID:1cd941934d098654fa21a13f28346412"
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
|
|
@ -28,6 +29,15 @@ namespace UniVRM10
|
|||
[SerializeField]
|
||||
public bool m_drawCollider = false;
|
||||
|
||||
public BlittableJointMutable Blittable => new BlittableJointMutable
|
||||
{
|
||||
stiffnessForce = m_stiffnessForce,
|
||||
dragForce = m_dragForce,
|
||||
gravityDir = m_gravityDir,
|
||||
gravityPower = m_dragForce,
|
||||
radius = m_jointRadius,
|
||||
};
|
||||
|
||||
void AddJointRecursive(Transform t, VRM10SpringBoneJoint src)
|
||||
{
|
||||
var joint = t.gameObject.GetOrAddComponent<VRM10SpringBoneJoint>();
|
||||
|
|
|
|||
|
|
@ -119,15 +119,24 @@ namespace UniVRM10
|
|||
{
|
||||
if (m_springBoneRuntime == null)
|
||||
{
|
||||
// シーン配置モデルが play された
|
||||
var provider = GetComponent<IVrm10SpringBoneRuntimeProvider>();
|
||||
if (provider != null)
|
||||
{
|
||||
// 明示的カスタマイズ
|
||||
m_springBoneRuntime = provider.CreateSpringBoneRuntime();
|
||||
}
|
||||
else
|
||||
{
|
||||
// deafult に fallback
|
||||
m_springBoneRuntime = new Vrm10FastSpringboneRuntime();
|
||||
if (Application.isEditor)
|
||||
{
|
||||
m_springBoneRuntime = new Vrm10FastSpringboneRuntimeStandalone();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_springBoneRuntime = new Vrm10FastSpringboneRuntime();
|
||||
}
|
||||
}
|
||||
m_springBoneRuntime.InitializeAsync(this, new ImmediateCaller());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace UniVRM10
|
|||
|
||||
// create(Spring情報の再収集。設定変更の反映)
|
||||
var springs = vrm.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
|
||||
{
|
||||
{
|
||||
center = spring.Center,
|
||||
colliders = spring.ColliderGroups
|
||||
.SelectMany(group => group.Colliders)
|
||||
|
|
@ -74,7 +74,7 @@ namespace UniVRM10
|
|||
|
||||
await awaitCaller.NextFrame();
|
||||
|
||||
fastSpringBoneBuffer = new FastSpringBoneBuffer(springs);
|
||||
fastSpringBoneBuffer = new FastSpringBoneBuffer(vrm.transform, springs);
|
||||
return fastSpringBoneBuffer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ using UniGLTF;
|
|||
using UnityEngine;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniGLTF.SpringBoneJobs;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
|
|
@ -17,18 +19,21 @@ namespace UniVRM10
|
|||
private FastSpringBones.FastSpringBoneService m_fastSpringBoneService;
|
||||
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
|
||||
|
||||
public Vector3 ExternalForce
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings)
|
||||
{
|
||||
get => m_fastSpringBoneBuffer.ExternalForce;
|
||||
set => m_fastSpringBoneBuffer.ExternalForce = value;
|
||||
}
|
||||
public bool IsSpringBoneEnabled
|
||||
{
|
||||
get => m_fastSpringBoneBuffer.IsSpringBoneEnabled;
|
||||
set => m_fastSpringBoneBuffer.IsSpringBoneEnabled = value;
|
||||
if (m_fastSpringBoneService.BufferCombiner.Combined is FastSpringBoneCombinedBuffer combined)
|
||||
{
|
||||
combined.SetJointLevel(joint, jointSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public float DeltaTime => throw new NotImplementedException();
|
||||
public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings)
|
||||
{
|
||||
if (m_fastSpringBoneService.BufferCombiner.Combined is FastSpringBoneCombinedBuffer combined)
|
||||
{
|
||||
combined.SetModelLevel(modelRoot, modelSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using UnityEngine;
|
|||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using UniGLTF.SpringBoneJobs;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
|
|
@ -19,18 +20,21 @@ namespace UniVRM10
|
|||
public FastSpringBoneBufferCombiner m_bufferCombiner = new();
|
||||
private FastSpringBoneScheduler m_fastSpringBoneScheduler;
|
||||
|
||||
public Vector3 ExternalForce
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings)
|
||||
{
|
||||
get => m_fastSpringBoneBuffer.ExternalForce;
|
||||
set => m_fastSpringBoneBuffer.ExternalForce = value;
|
||||
}
|
||||
public bool IsSpringBoneEnabled
|
||||
{
|
||||
get => m_fastSpringBoneBuffer.IsSpringBoneEnabled;
|
||||
set => m_fastSpringBoneBuffer.IsSpringBoneEnabled = value;
|
||||
if (m_bufferCombiner.Combined is FastSpringBoneCombinedBuffer combined)
|
||||
{
|
||||
combined.SetJointLevel(joint, jointSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public float DeltaTime => Time.deltaTime;
|
||||
public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings)
|
||||
{
|
||||
if (m_bufferCombiner.Combined is FastSpringBoneCombinedBuffer combined)
|
||||
{
|
||||
combined.SetModelLevel(modelRoot, modelSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public Vrm10FastSpringboneRuntimeStandalone()
|
||||
{
|
||||
|
|
@ -115,7 +119,7 @@ namespace UniVRM10
|
|||
|
||||
public void Process()
|
||||
{
|
||||
m_fastSpringBoneScheduler.Schedule(DeltaTime).Complete();
|
||||
m_fastSpringBoneScheduler.Schedule(Time.deltaTime).Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,11 +30,19 @@ namespace UniVRM10
|
|||
public IVrm10SpringBoneRuntime SpringBone { get; }
|
||||
public IVrm10Animation VrmAnimation { get; set; }
|
||||
|
||||
[Obsolete("use Vrm10Runtime.SpringBone.ExternalForce")]
|
||||
[Obsolete("use Vrm10Runtime.SpringBone.SetModelLevel")]
|
||||
public Vector3 ExternalForce
|
||||
{
|
||||
get { return SpringBone.ExternalForce; }
|
||||
set { SpringBone.ExternalForce = value; }
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// return SpringBone.ExternalForce;
|
||||
}
|
||||
set
|
||||
{
|
||||
// SpringBone.SetModelLevel = value;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public Vrm10Runtime(Vrm10Instance instance, bool useControlRig, IVrm10SpringBoneRuntime springBoneRuntime)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public interface IVrm10SpringBoneRuntime : IDisposable
|
||||
|
|
@ -20,20 +22,23 @@ namespace UniVRM10
|
|||
public void RestoreInitialTransform();
|
||||
|
||||
/// <summary>
|
||||
/// Joint レベルの可変情報をセットする
|
||||
/// stiffness,
|
||||
/// </summary>
|
||||
public void SetJointLevel(Transform joint, BlittableJointMutable jointSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Model レベルの可変情報をセットする
|
||||
/// 風, pause, scaling
|
||||
/// </summary>
|
||||
public void SetModelLevel(Transform modelRoot, BlittableModelLevel modelSettings);
|
||||
|
||||
/// <summary>
|
||||
/// System レベルの可変情報
|
||||
/// TODO: デザイン検討中。
|
||||
/// deltaTime のカスタマイズポイント。通常は Time.dletaTime
|
||||
/// </summary>
|
||||
public float DeltaTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 風などの追加の外力を設定する
|
||||
/// </summary>
|
||||
public Vector3 ExternalForce { get; set; }
|
||||
|
||||
/// <summary>
|
||||
// SpringBone のランタイムの動作状態を設定する。
|
||||
// SpringBone の動きを一時停止したいときは false にする。
|
||||
/// </summary>
|
||||
public bool IsSpringBoneEnabled { get; set; }
|
||||
// public float DeltaTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 毎フレーム Vrm10Runtime.Process から呼ばれる。
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:b7aa47b240b57de44a4b2021c143c9bf",
|
||||
"GUID:da3e51d19d51a544fa14d43fee843098",
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c",
|
||||
"GUID:e47c917724578cc43b5506c17a27e9a0",
|
||||
"GUID:1cd941934d098654fa21a13f28346412"
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace UniVRM10.VRM10Viewer
|
|||
{
|
||||
RuntimeGltfInstance m_instance;
|
||||
Vrm10Instance m_controller;
|
||||
public Vrm10Instance Instance => m_controller;
|
||||
public Vrm10RuntimeControlRig ControlRig => m_controller.Runtime.ControlRig;
|
||||
public Vrm10Runtime Runtime => m_controller.Runtime;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -3,6 +3,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
|
|
@ -26,12 +27,6 @@ namespace UniVRM10.VRM10Viewer
|
|||
[SerializeField]
|
||||
Toggle m_showBoxMan = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_pauseSpringBone = default;
|
||||
|
||||
[SerializeField]
|
||||
Button m_resetSpringBone = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_enableLipSync = default;
|
||||
|
||||
|
|
@ -44,15 +39,34 @@ namespace UniVRM10.VRM10Viewer
|
|||
[SerializeField]
|
||||
Toggle m_useAsync = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_useSingelton = default;
|
||||
|
||||
[SerializeField]
|
||||
GameObject m_target = default;
|
||||
|
||||
[SerializeField]
|
||||
TextAsset m_motion;
|
||||
|
||||
// springbone
|
||||
[SerializeField]
|
||||
Toggle m_useSpringboneSingelton = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_springbonePause = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_springboneScaling = default;
|
||||
|
||||
[SerializeField]
|
||||
Slider m_springboneExternalX = default;
|
||||
[SerializeField]
|
||||
Slider m_springboneExternalY = default;
|
||||
[SerializeField]
|
||||
Slider m_springboneExternalZ = default;
|
||||
|
||||
[SerializeField]
|
||||
Button m_resetSpringBone = default;
|
||||
[SerializeField]
|
||||
Button m_reconstructSpringBone = default;
|
||||
|
||||
GameObject Root = default;
|
||||
|
||||
IVrm10Animation m_src = default;
|
||||
|
|
@ -257,7 +271,6 @@ 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<Toggle>(FindObjectsSortMode.InstanceID);
|
||||
|
|
@ -265,12 +278,15 @@ namespace UniVRM10.VRM10Viewer
|
|||
var toggles = GameObject.FindObjectsOfType<Toggle>();
|
||||
#endif
|
||||
m_showBoxMan = toggles.First(x => x.name == "ShowBoxMan");
|
||||
m_pauseSpringBone = toggles.First(x => x.name == "PauseSpringBone");
|
||||
m_enableLipSync = toggles.First(x => x.name == "EnableLipSync");
|
||||
m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink");
|
||||
m_enableAutoExpression = toggles.First(x => x.name == "EnableAutoExpression");
|
||||
m_useAsync = toggles.First(x => x.name == "UseAsync");
|
||||
m_useSingelton = toggles.First(x => x.name == "UseSingleton");
|
||||
|
||||
m_useSpringboneSingelton = toggles.First(x => x.name == "UseSingleton");
|
||||
m_springbonePause = toggles.First(x => x.name == "PauseSpringBone");
|
||||
m_resetSpringBone = buttons.First(x => x.name == "ResetSpringBone");
|
||||
|
||||
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
var texts = GameObject.FindObjectsByType<Text>(FindObjectsSortMode.InstanceID);
|
||||
|
|
@ -355,6 +371,7 @@ namespace UniVRM10.VRM10Viewer
|
|||
m_openMotion.onClick.AddListener(OnOpenMotionClicked);
|
||||
m_pastePose.onClick.AddListener(OnPastePoseClicked);
|
||||
m_resetSpringBone.onClick.AddListener(OnResetSpringBoneClicked);
|
||||
m_reconstructSpringBone.onClick.AddListener(OnReconstructSpringBoneClicked);
|
||||
|
||||
// load initial bvh
|
||||
if (m_motion != null)
|
||||
|
|
@ -414,7 +431,12 @@ namespace UniVRM10.VRM10Viewer
|
|||
m_loaded.Runtime.VrmAnimation = Motion;
|
||||
}
|
||||
|
||||
m_loaded.Runtime.SpringBone.IsSpringBoneEnabled = !m_pauseSpringBone.isOn;
|
||||
m_loaded.Runtime.SpringBone.SetModelLevel(m_loaded.Instance.transform, new BlittableModelLevel
|
||||
{
|
||||
ExternalForce = new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value),
|
||||
StopSpringBoneWriteback = m_springbonePause.isOn,
|
||||
SupportsScalingAtRuntime = m_springboneScaling.isOn,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -505,6 +527,17 @@ namespace UniVRM10.VRM10Viewer
|
|||
}
|
||||
}
|
||||
|
||||
void OnReconstructSpringBoneClicked()
|
||||
{
|
||||
if (m_loaded != null)
|
||||
{
|
||||
if (m_loaded.Runtime != null)
|
||||
{
|
||||
m_loaded.Runtime.SpringBone.ReconstructSpringBone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IMaterialDescriptorGenerator GetVrmMaterialDescriptorGenerator(bool useUrp)
|
||||
{
|
||||
if (useUrp)
|
||||
|
|
@ -547,7 +580,7 @@ namespace UniVRM10.VRM10Viewer
|
|||
awaitCaller: m_useAsync.enabled ? new RuntimeOnlyAwaitCaller() : new ImmediateCaller(),
|
||||
vrmMetaInformationCallback: m_texts.UpdateMeta,
|
||||
ct: cancellationToken,
|
||||
springboneRuntime: m_useSingelton.isOn ? new Vrm10FastSpringboneRuntime() : new Vrm10FastSpringboneRuntimeStandalone());
|
||||
springboneRuntime: m_useSpringboneSingelton.isOn ? new Vrm10FastSpringboneRuntime() : new Vrm10FastSpringboneRuntimeStandalone());
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
UnityObjectDestroyer.DestroyRuntimeOrEditor(vrm10Instance.gameObject);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using UniGLTF;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniHumanoid;
|
||||
using UnityEngine;
|
||||
|
||||
|
|
@ -40,9 +41,12 @@ namespace VRM.SimpleViewer
|
|||
}
|
||||
}
|
||||
|
||||
public Loaded(RuntimeGltfInstance instance, HumanPoseTransfer src, Transform lookAtTarget)
|
||||
IVrm0XSpringBoneRuntime _springbone;
|
||||
|
||||
public Loaded(RuntimeGltfInstance instance, HumanPoseTransfer src, Transform lookAtTarget, IVrm0XSpringBoneRuntime springbone)
|
||||
{
|
||||
_instance = instance;
|
||||
_springbone = springbone;
|
||||
|
||||
var lookAt = instance.GetComponent<VRMLookAtHead>();
|
||||
if (lookAt != null)
|
||||
|
|
@ -104,15 +108,19 @@ namespace VRM.SimpleViewer
|
|||
}
|
||||
}
|
||||
|
||||
public void ResetSpring()
|
||||
public void ResetSpringbone()
|
||||
{
|
||||
if (_pose != null)
|
||||
{
|
||||
foreach (var spring in _pose.GetComponentsInChildren<VRMSpringBone>())
|
||||
{
|
||||
spring.Setup();
|
||||
}
|
||||
}
|
||||
_springbone.RestoreInitialTransform();
|
||||
}
|
||||
|
||||
public void ReconstructSpringbone()
|
||||
{
|
||||
_springbone.ReconstructSpringBone();
|
||||
}
|
||||
|
||||
public void SetSpringboneModelLevel(BlittableModelLevel modelSettings)
|
||||
{
|
||||
_springbone.SetModelLevel(_instance.transform, modelSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -39,8 +39,28 @@ namespace VRM.SimpleViewer
|
|||
[SerializeField]
|
||||
Toggle m_loadAnimation = default;
|
||||
|
||||
// SpringBone
|
||||
[SerializeField]
|
||||
Toggle m_useFastSpringBone = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_springBonePause = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_springBoneScaling = default;
|
||||
|
||||
[SerializeField]
|
||||
Slider m_springExternalX = default;
|
||||
[SerializeField]
|
||||
Slider m_springExternalY = default;
|
||||
[SerializeField]
|
||||
Slider m_springExternalZ = default;
|
||||
|
||||
[SerializeField]
|
||||
Button m_reset = default;
|
||||
|
||||
[SerializeField]
|
||||
Button m_reconstruct = default;
|
||||
#endregion
|
||||
|
||||
[SerializeField]
|
||||
|
|
@ -52,9 +72,6 @@ namespace VRM.SimpleViewer
|
|||
[SerializeField]
|
||||
GameObject Root = default;
|
||||
|
||||
[SerializeField]
|
||||
Button m_reset = default;
|
||||
|
||||
[SerializeField]
|
||||
TextAsset m_motion;
|
||||
|
||||
|
|
@ -280,10 +297,9 @@ namespace VRM.SimpleViewer
|
|||
m_version.text = string.Format("VRMViewer {0}.{1}",
|
||||
PackageVersion.MAJOR, PackageVersion.MINOR);
|
||||
m_open.onClick.AddListener(OnOpenClicked);
|
||||
m_useFastSpringBone.onValueChanged.AddListener(OnUseFastSpringBoneValueChanged);
|
||||
OnUseFastSpringBoneValueChanged(m_useFastSpringBone.isOn);
|
||||
|
||||
m_reset.onClick.AddListener(() => m_loaded?.ResetSpring());
|
||||
m_reset.onClick.AddListener(() => m_loaded?.ResetSpringbone());
|
||||
m_reconstruct.onClick.AddListener(() => m_loaded?.ReconstructSpringbone());
|
||||
|
||||
// load initial bvh
|
||||
if (m_motion != null)
|
||||
|
|
@ -327,6 +343,16 @@ namespace VRM.SimpleViewer
|
|||
{
|
||||
m_loaded.EnableLipSyncValue = m_enableLipSync.isOn;
|
||||
m_loaded.EnableBlinkValue = m_enableAutoBlink.isOn;
|
||||
m_loaded.SetSpringboneModelLevel(new UniGLTF.SpringBoneJobs.Blittables.BlittableModelLevel
|
||||
{
|
||||
ExternalForce = new Vector3(
|
||||
m_springExternalX.value,
|
||||
m_springExternalY.value,
|
||||
m_springExternalZ.value
|
||||
),
|
||||
StopSpringBoneWriteback = m_springBonePause.isOn,
|
||||
SupportsScalingAtRuntime = m_springBoneScaling.isOn,
|
||||
});
|
||||
m_loaded.Update();
|
||||
}
|
||||
}
|
||||
|
|
@ -392,21 +418,17 @@ namespace VRM.SimpleViewer
|
|||
// vrm
|
||||
VrmUtility.MaterialGeneratorCallback materialCallback = (glTF_VRM_extensions vrm) => GetVrmMaterialGenerator(m_useUrpMaterial.isOn, vrm);
|
||||
VrmUtility.MetaCallback metaCallback = m_texts.UpdateMeta;
|
||||
IVrm0XSpringBoneRuntime springboneRuntime = m_useFastSpringBone.isOn ? new Vrm0XFastSpringboneRuntime() : new Vrm0XSpringBoneDefaultRuntime();
|
||||
var instance = await VrmUtility.LoadBytesAsync(path, bytes, GetIAwaitCaller(m_useAsync.isOn),
|
||||
materialCallback, metaCallback,
|
||||
loadAnimation: m_loadAnimation.isOn,
|
||||
springboneRuntime: m_useFastSpringBone.isOn ? new Vrm0XFastSpringboneRuntime() : new Vrm0XSpringBoneDefaultRuntime()
|
||||
springboneRuntime: springboneRuntime
|
||||
);
|
||||
|
||||
instance.EnableUpdateWhenOffscreen();
|
||||
instance.ShowMeshes();
|
||||
|
||||
m_loaded = new Loaded(instance, m_src, m_target.transform);
|
||||
}
|
||||
|
||||
void OnUseFastSpringBoneValueChanged(bool flag)
|
||||
{
|
||||
m_reset.gameObject.SetActive(!flag);
|
||||
m_loaded = new Loaded(instance, m_src, m_target.transform, springboneRuntime);
|
||||
}
|
||||
|
||||
static IMaterialDescriptorGenerator GetGltfMaterialGenerator(bool useUrp)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user