Skip to content

Commit

Permalink
BlittableExternalData to BlittableModelLevel
Browse files Browse the repository at this point in the history
  • Loading branch information
ousttrue committed Oct 3, 2024
1 parent 521cfa0 commit f643f2b
Show file tree
Hide file tree
Showing 19 changed files with 164 additions and 109 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public struct BlittableSpring
public BlittableSpan logicSpan;
public int centerTransformIndex;
public int transformIndexOffset;
public unsafe BlittableExternalData* ExternalData;
public int modelIndex;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Unity.Jobs;
using UnityEngine.Profiling;
using UniGLTF.SpringBoneJobs.InputPorts;
using UnityEngine;

namespace UniGLTF.SpringBoneJobs
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -93,8 +103,8 @@ internal static JobHandle Create(JobHandle handle,

// バッファの構築
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);
Expand All @@ -110,6 +120,14 @@ private JobHandle Batching(JobHandle handle)
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
Expand All @@ -121,6 +139,7 @@ private JobHandle Batching(JobHandle handle)

handle = new LoadSpringsJob
{
ModelIndex = i,
SrcSprings = buffer.Springs,
DestSprings = new NativeSlice<BlittableSpring>(_springs, springsOffset, buffer.Springs.Length),
CollidersOffset = collidersOffset,
Expand Down Expand Up @@ -173,12 +192,17 @@ private JobHandle Batching(JobHandle handle)

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();
Expand Down Expand Up @@ -211,6 +235,22 @@ public void FlipBuffer()
_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
Expand All @@ -236,13 +276,15 @@ private struct LoadSpringsJob : IJobParallelFor
[ReadOnly] public NativeArray<BlittableSpring> SrcSprings;
[WriteOnly] public NativeSlice<BlittableSpring> DestSprings;

public int ModelIndex;
public int CollidersOffset;
public int LogicsOffset;
public int TransformOffset;

public void Execute(int index)
{
var spring = SrcSprings[index];
spring.modelIndex = ModelIndex;
spring.colliderSpan.startIndex += CollidersOffset;
spring.logicSpan.startIndex += LogicsOffset;
spring.transformIndexOffset = TransformOffset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public JobHandle Schedule(float deltaTime)
PrevTail = combined.PrevTails,
NextTail = combined.NextTails,
Springs = combined.Springs,
Models = combined.Models,
Colliders = combined.Colliders,
Transforms = combined.Transforms,
DeltaTime = deltaTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.Profiling;
using UniGLTF.SpringBoneJobs.Blittables;
Expand All @@ -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; }
Expand All @@ -23,34 +26,6 @@ public class FastSpringBoneBuffer : IDisposable
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 のリスト
/// - 重複を除去
Expand Down Expand Up @@ -79,18 +54,13 @@ static Transform[] MakeFlattenTransformList(FastSpringBoneSpring[] springs)
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();
Expand All @@ -110,7 +80,6 @@ public unsafe FastSpringBoneBuffer(FastSpringBoneSpring[] springs)
count = spring.joints.Length - 1,
},
centerTransformIndex = Array.IndexOf(Transforms, spring.center),
ExternalData = externalDataPtr,
};
blittableSprings.Add(blittableSpring);

Expand Down Expand Up @@ -182,7 +151,6 @@ public void Dispose()
BlittableTransforms.Dispose();
Colliders.Dispose();
Logics.Dispose();
_externalData.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
Expand Down
27 changes: 19 additions & 8 deletions Assets/UniGLTF/Runtime/SpringBoneJobs/UpdateFastSpringBoneJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -71,7 +82,7 @@ public unsafe void Execute(int index)
var parentRotation = parentTransform?.rotation ?? Quaternion.identity;

// 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 *
Expand Down Expand Up @@ -153,7 +164,7 @@ public unsafe void Execute(int index)
headTransform.localRotation = headTransform.rotation;
}

if (spring.ExternalData->IsSpringBoneEnabled)
if (!model.StopSpringBoneWriteback)
{
// SpringBone の結果を Transform に反映する
Transforms[logic.headTransformIndex + transformIndexOffset] = headTransform;
Expand Down
Loading

0 comments on commit f643f2b

Please sign in to comment.