Merge pull request #2454 from ousttrue/fix/springbone_model_level

[1.0][SpringBone] ModelLevel 追加
This commit is contained in:
ousttrue 2024-10-08 13:05:14 +09:00 committed by GitHub
commit 3a492d79c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 2019 additions and 222 deletions

View 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);
}
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,23 @@
using UnityEngine;
namespace UniGLTF.SpringBoneJobs.Blittables
{
public struct BlittableModelLevel
{
/// <summary>
/// 風など。
/// </summary>
public Vector3 ExternalForce;
/// <summary>
/// 処理結果の Transform への書き戻しを停止する。
/// </summary>
public bool StopSpringBoneWriteback;
/// <summary>
/// スケール値に連動して SpringBone のパラメータを自動調整する。
/// (見た目の角速度が同じになるようにする)
/// </summary>
public bool SupportsScalingAtRuntime;
}
}

View File

@ -13,6 +13,6 @@ namespace UniGLTF.SpringBoneJobs.Blittables
public BlittableSpan logicSpan;
public int centerTransformIndex;
public int transformIndexOffset;
public unsafe BlittableExternalData* ExternalData;
public int modelIndex;
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using Unity.Jobs;
using UnityEngine.Profiling;
using UniGLTF.SpringBoneJobs.InputPorts;
using UnityEngine;
namespace UniGLTF.SpringBoneJobs
{

View File

@ -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;

View File

@ -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,

View File

@ -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);
@ -182,7 +151,6 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
BlittableTransforms.Dispose();
Colliders.Dispose();
Logics.Dispose();
_externalData.Dispose();
}
}
}

View File

@ -1,10 +1,12 @@
{
"name": "SpringBoneJobs",
"rootNamespace": "",
"references": [],
"references": [
"GUID:8d76e605759c3f64a957d63ef96ada7c"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,

View File

@ -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;

View File

@ -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;
}
}
}
}
}

View File

@ -79,7 +79,7 @@ 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)

View File

@ -1,3 +1,4 @@
using UniGLTF;
using UnityEngine;
namespace VRM.SpringBone

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using UniGLTF;
using UnityEngine;
namespace VRM.SpringBone

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UnityEngine;
namespace VRM.SpringBone

View File

@ -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);
}
}
}

View File

@ -6,10 +6,9 @@
"GUID:2ef84b520212e174a94668c7a0862d3b",
"GUID:5f875fdc81c40184c8333b9d63c6ddd5",
"GUID:8d76e605759c3f64a957d63ef96ada7c",
"GUID:da3e51d19d51a544fa14d43fee843098",
"GUID:7da8a75dcade2144aab699032d7d7987",
"GUID:b7aa47b240b57de44a4b2021c143c9bf",
"GUID:1cd941934d098654fa21a13f28346412"
"GUID:1cd941934d098654fa21a13f28346412",
"GUID:3e5d614bc16b50d41bd94c8d7444ca46"
],
"includePlatforms": [
"Editor"

View File

@ -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>();

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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();
}
}
}

View File

@ -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)

View File

@ -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 から呼ばれる。

View File

@ -3,10 +3,10 @@
"rootNamespace": "",
"references": [
"GUID:b7aa47b240b57de44a4b2021c143c9bf",
"GUID:da3e51d19d51a544fa14d43fee843098",
"GUID:8d76e605759c3f64a957d63ef96ada7c",
"GUID:e47c917724578cc43b5506c17a27e9a0",
"GUID:1cd941934d098654fa21a13f28346412"
"GUID:1cd941934d098654fa21a13f28346412",
"GUID:3e5d614bc16b50d41bd94c8d7444ca46"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@ -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

View File

@ -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);