mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-13 22:09:53 -05:00
FastSpringBoneBufferBuilder を FastSpringBoneBuffer.FastSpringBoneBuffer に合体
This commit is contained in:
parent
80c2bb921c
commit
7f089f1dd8
|
|
@ -14,8 +14,8 @@ namespace UniVRM10
|
|||
private readonly Vrm10Instance m_instance;
|
||||
private readonly IReadOnlyDictionary<Transform, TransformState> m_defaultTransformStates;
|
||||
private readonly FastSpringBoneService m_fastSpringBoneService;
|
||||
|
||||
private FastSpringBoneBufferBuilder m_initialData;
|
||||
private FastSpringBoneSpring[] m_springs;
|
||||
private Quaternion[] m_initialLocalRotations;
|
||||
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
|
||||
public Vector3 ExternalForce
|
||||
{
|
||||
|
|
@ -73,7 +73,7 @@ namespace UniVRM10
|
|||
}
|
||||
|
||||
// create
|
||||
var springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
|
||||
m_springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
|
||||
{
|
||||
center = spring.Center,
|
||||
colliders = spring.ColliderGroups
|
||||
|
|
@ -105,9 +105,9 @@ namespace UniVRM10
|
|||
}).ToArray(),
|
||||
}).ToArray();
|
||||
|
||||
m_initialData = new FastSpringBoneBufferBuilder(springs);
|
||||
m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_initialData);
|
||||
m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_springs);
|
||||
m_fastSpringBoneService.BufferCombiner.Register(m_fastSpringBoneBuffer);
|
||||
m_initialLocalRotations = m_fastSpringBoneBuffer.Transforms.Select(x => x.localRotation).ToArray();
|
||||
}
|
||||
|
||||
private TransformState GetOrAddDefaultTransformState(Transform tf)
|
||||
|
|
@ -143,21 +143,21 @@ namespace UniVRM10
|
|||
public void RestoreInitialTransform()
|
||||
{
|
||||
// Spring の joint に対応する transform の回転を初期状態
|
||||
for (int i = 0; i < m_initialData.Transforms.Length; ++i)
|
||||
for (int i = 0; i < m_fastSpringBoneBuffer.Transforms.Length; ++i)
|
||||
{
|
||||
var transform = m_initialData.Transforms[i];
|
||||
transform.localRotation = m_initialData.InitialLocalRotations[i];
|
||||
var transform = m_fastSpringBoneBuffer.Transforms[i];
|
||||
transform.localRotation = m_initialLocalRotations[i];
|
||||
}
|
||||
|
||||
// 初期状態にしたtransformを使って spring logic を構築
|
||||
m_initialData.BlittableLogics.Clear();
|
||||
foreach (var spring in m_initialData.Springs)
|
||||
List<BlittableLogic> blittableLogics = new();
|
||||
foreach (var spring in m_springs)
|
||||
{
|
||||
m_initialData.AddLogic(spring);
|
||||
FastSpringBoneBuffer.AddLogic(m_fastSpringBoneBuffer.Transforms, blittableLogics, spring);
|
||||
}
|
||||
|
||||
// DOTS バッファーを更新
|
||||
m_initialData.SyncAndZeroVelocity(m_fastSpringBoneBuffer.Logics);
|
||||
m_fastSpringBoneBuffer.SyncAndZeroVelocity(blittableLogics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
|
|
@ -47,28 +49,148 @@ namespace UniVRM10.FastSpringBones.System
|
|||
IsSpringBoneEnabled = value,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public unsafe FastSpringBoneBuffer(FastSpringBoneBufferBuilder b)
|
||||
/// <summary>
|
||||
/// Joint, Collider, Center の Transform のリスト
|
||||
/// - 重複を除去
|
||||
/// </summary>
|
||||
/// <param name="springs"></param>
|
||||
/// <returns></returns>
|
||||
static Transform[] MakeFlattenTransformList(FastSpringBoneSpring[] springs)
|
||||
{
|
||||
Profiler.BeginSample("FastSpringBone.ConstructBuffers.ConstructNativeArrays");
|
||||
var transformHashSet = new HashSet<Transform>();
|
||||
foreach (var spring in springs)
|
||||
{
|
||||
foreach (var joint in spring.joints)
|
||||
{
|
||||
transformHashSet.Add(joint.Transform);
|
||||
if (joint.Transform.parent != null) transformHashSet.Add(joint.Transform.parent);
|
||||
}
|
||||
|
||||
foreach (var collider in spring.colliders)
|
||||
{
|
||||
transformHashSet.Add(collider.Transform);
|
||||
}
|
||||
|
||||
if (spring.center != null) transformHashSet.Add(spring.center);
|
||||
}
|
||||
var Transforms = transformHashSet.ToArray();
|
||||
return Transforms;
|
||||
}
|
||||
|
||||
public unsafe FastSpringBoneBuffer(FastSpringBoneSpring[] springs)
|
||||
{
|
||||
Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder");
|
||||
Transforms = MakeFlattenTransformList(springs);
|
||||
_externalData = new NativeArray<BlittableExternalData>(1, Allocator.Persistent);
|
||||
_externalData[0] = new BlittableExternalData
|
||||
{
|
||||
ExternalForce = Vector3.zero,
|
||||
IsSpringBoneEnabled = true,
|
||||
};
|
||||
b.SetExternalDataPtr((BlittableExternalData*)_externalData.GetUnsafePtr());
|
||||
Springs = new NativeArray<BlittableSpring>(b.BlittableSprings.ToArray(), Allocator.Persistent);
|
||||
Joints = new NativeArray<BlittableJoint>(b.BlittableJoints.ToArray(), Allocator.Persistent);
|
||||
Colliders = new NativeArray<BlittableCollider>(b.BlittableColliders.ToArray(), Allocator.Persistent);
|
||||
Logics = new NativeArray<BlittableLogic>(b.BlittableLogics.ToArray(), Allocator.Persistent);
|
||||
BlittableTransforms = new NativeArray<BlittableTransform>(b.Transforms.Length, Allocator.Persistent);
|
||||
Transforms = b.Transforms;
|
||||
|
||||
var externalDataPtr = (BlittableExternalData*)_externalData.GetUnsafePtr();
|
||||
List<BlittableSpring> blittableSprings = new();
|
||||
List<BlittableJoint> blittableJoints = new();
|
||||
List<BlittableCollider> blittableColliders = new();
|
||||
List<BlittableLogic> blittableLogics = new();
|
||||
foreach (var spring in springs)
|
||||
{
|
||||
var blittableSpring = new BlittableSpring
|
||||
{
|
||||
colliderSpan = new BlittableSpan
|
||||
{
|
||||
startIndex = blittableColliders.Count,
|
||||
count = spring.colliders.Length,
|
||||
},
|
||||
logicSpan = new BlittableSpan
|
||||
{
|
||||
startIndex = blittableJoints.Count,
|
||||
count = spring.joints.Length - 1,
|
||||
},
|
||||
centerTransformIndex = Array.IndexOf(Transforms, spring.center),
|
||||
ExternalData = externalDataPtr,
|
||||
};
|
||||
blittableSprings.Add(blittableSpring);
|
||||
|
||||
blittableColliders.AddRange(spring.colliders.Select(collider =>
|
||||
{
|
||||
var blittable = collider.Collider;
|
||||
blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform);
|
||||
return blittable;
|
||||
}));
|
||||
blittableJoints.AddRange(spring.joints
|
||||
.Take(spring.joints.Length - 1).Select(joint =>
|
||||
{
|
||||
var blittable = joint.Joint;
|
||||
return blittable;
|
||||
}));
|
||||
|
||||
AddLogic(Transforms, blittableLogics, spring);
|
||||
}
|
||||
|
||||
Springs = new NativeArray<BlittableSpring>(blittableSprings.ToArray(), Allocator.Persistent);
|
||||
Joints = new NativeArray<BlittableJoint>(blittableJoints.ToArray(), Allocator.Persistent);
|
||||
Colliders = new NativeArray<BlittableCollider>(blittableColliders.ToArray(), Allocator.Persistent);
|
||||
Logics = new NativeArray<BlittableLogic>(blittableLogics.ToArray(), Allocator.Persistent);
|
||||
BlittableTransforms = new NativeArray<BlittableTransform>(Transforms.Length, Allocator.Persistent);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
static public void AddLogic(Transform[] Transforms, List<BlittableLogic> BlittableLogics, FastSpringBoneSpring spring)
|
||||
{
|
||||
for (var i = 0; i < spring.joints.Length - 1; ++i)
|
||||
{
|
||||
var joint = spring.joints[i];
|
||||
var tailJoint = i + 1 < spring.joints.Length ? spring.joints[i + 1] : (FastSpringBoneJoint?)null;
|
||||
var parentJoint = i - 1 >= 0 ? spring.joints[i - 1] : (FastSpringBoneJoint?)null;
|
||||
var localPosition = Vector3.zero;
|
||||
if (tailJoint.HasValue)
|
||||
{
|
||||
localPosition = tailJoint.Value.Transform.localPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parentJoint.HasValue)
|
||||
{
|
||||
var delta = joint.Transform.position - parentJoint.Value.Transform.position;
|
||||
localPosition =
|
||||
joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
localPosition = Vector3.down;
|
||||
}
|
||||
}
|
||||
|
||||
var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale;
|
||||
var localChildPosition = new Vector3(
|
||||
localPosition.x * scale.x,
|
||||
localPosition.y * scale.y,
|
||||
localPosition.z * scale.z
|
||||
);
|
||||
|
||||
var worldChildPosition = joint.Transform.TransformPoint(localChildPosition);
|
||||
var currentTail = spring.center != null
|
||||
? spring.center.InverseTransformPoint(worldChildPosition)
|
||||
: worldChildPosition;
|
||||
var parent = joint.Transform.parent;
|
||||
|
||||
|
||||
BlittableLogics.Add(new BlittableLogic
|
||||
{
|
||||
headTransformIndex = Array.IndexOf(Transforms, joint.Transform),
|
||||
parentTransformIndex = Array.IndexOf(Transforms, parent),
|
||||
currentTail = currentTail,
|
||||
prevTail = currentTail,
|
||||
localRotation = joint.DefaultLocalRotation,
|
||||
boneAxis = localChildPosition.normalized,
|
||||
length = localChildPosition.magnitude
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed) return;
|
||||
|
|
@ -80,5 +202,16 @@ namespace UniVRM10.FastSpringBones.System
|
|||
Logics.Dispose();
|
||||
_externalData.Dispose();
|
||||
}
|
||||
|
||||
public unsafe void SyncAndZeroVelocity(IReadOnlyList<BlittableLogic> logics)
|
||||
{
|
||||
var dst = Logics;
|
||||
for (int i = 0; i < logics.Count; ++i)
|
||||
{
|
||||
var l = logics[i];
|
||||
l.prevTail = l.currentTail;
|
||||
dst[i] = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UniVRM10.FastSpringBones.Blittables;
|
||||
|
||||
namespace UniVRM10.FastSpringBones.System
|
||||
{
|
||||
public class FastSpringBoneBufferBuilder
|
||||
{
|
||||
public readonly List<BlittableSpring> BlittableSprings = new();
|
||||
public readonly List<BlittableJoint> BlittableJoints = new();
|
||||
public readonly List<BlittableCollider> BlittableColliders = new();
|
||||
public readonly List<BlittableLogic> BlittableLogics = new();
|
||||
public readonly Transform[] Transforms;
|
||||
public readonly Quaternion[] InitialLocalRotations;
|
||||
public struct TransformInfo
|
||||
{
|
||||
public int Index;
|
||||
public Quaternion InitialLocalRotation;
|
||||
}
|
||||
public readonly FastSpringBoneSpring[] Springs;
|
||||
|
||||
public FastSpringBoneBufferBuilder(FastSpringBoneSpring[] springs)
|
||||
{
|
||||
Springs = springs;
|
||||
Profiler.BeginSample("FastSpringBone.ConstructBuffers.BufferBuilder");
|
||||
var transformHashSet = new HashSet<Transform>();
|
||||
foreach (var spring in springs)
|
||||
{
|
||||
foreach (var joint in spring.joints)
|
||||
{
|
||||
transformHashSet.Add(joint.Transform);
|
||||
if (joint.Transform.parent != null) transformHashSet.Add(joint.Transform.parent);
|
||||
}
|
||||
|
||||
foreach (var collider in spring.colliders)
|
||||
{
|
||||
transformHashSet.Add(collider.Transform);
|
||||
}
|
||||
|
||||
if (spring.center != null) transformHashSet.Add(spring.center);
|
||||
}
|
||||
Transforms = transformHashSet.ToArray();
|
||||
InitialLocalRotations = Transforms.Select(x => x.localRotation).ToArray();
|
||||
|
||||
foreach (var spring in springs)
|
||||
{
|
||||
var blittableSpring = new BlittableSpring
|
||||
{
|
||||
colliderSpan = new BlittableSpan
|
||||
{
|
||||
startIndex = BlittableColliders.Count,
|
||||
count = spring.colliders.Length,
|
||||
},
|
||||
logicSpan = new BlittableSpan
|
||||
{
|
||||
startIndex = BlittableJoints.Count,
|
||||
count = spring.joints.Length - 1,
|
||||
},
|
||||
centerTransformIndex = Array.IndexOf(Transforms, spring.center),
|
||||
};
|
||||
BlittableSprings.Add(blittableSpring);
|
||||
|
||||
BlittableColliders.AddRange(spring.colliders.Select(collider =>
|
||||
{
|
||||
var blittable = collider.Collider;
|
||||
blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform);
|
||||
return blittable;
|
||||
}));
|
||||
BlittableJoints.AddRange(spring.joints
|
||||
.Take(spring.joints.Length - 1).Select(joint =>
|
||||
{
|
||||
var blittable = joint.Joint;
|
||||
return blittable;
|
||||
}));
|
||||
|
||||
AddLogic(spring);
|
||||
|
||||
}
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
public void AddLogic(FastSpringBoneSpring spring)
|
||||
{
|
||||
for (var i = 0; i < spring.joints.Length - 1; ++i)
|
||||
{
|
||||
var joint = spring.joints[i];
|
||||
var tailJoint = i + 1 < spring.joints.Length ? spring.joints[i + 1] : (FastSpringBoneJoint?)null;
|
||||
var parentJoint = i - 1 >= 0 ? spring.joints[i - 1] : (FastSpringBoneJoint?)null;
|
||||
var localPosition = Vector3.zero;
|
||||
if (tailJoint.HasValue)
|
||||
{
|
||||
localPosition = tailJoint.Value.Transform.localPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parentJoint.HasValue)
|
||||
{
|
||||
var delta = joint.Transform.position - parentJoint.Value.Transform.position;
|
||||
localPosition =
|
||||
joint.Transform.worldToLocalMatrix.MultiplyPoint(joint.Transform.position + delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
localPosition = Vector3.down;
|
||||
}
|
||||
}
|
||||
|
||||
var scale = tailJoint.HasValue ? tailJoint.Value.Transform.lossyScale : joint.Transform.lossyScale;
|
||||
var localChildPosition = new Vector3(
|
||||
localPosition.x * scale.x,
|
||||
localPosition.y * scale.y,
|
||||
localPosition.z * scale.z
|
||||
);
|
||||
|
||||
var worldChildPosition = joint.Transform.TransformPoint(localChildPosition);
|
||||
var currentTail = spring.center != null
|
||||
? spring.center.InverseTransformPoint(worldChildPosition)
|
||||
: worldChildPosition;
|
||||
var parent = joint.Transform.parent;
|
||||
BlittableLogics.Add(new BlittableLogic
|
||||
{
|
||||
headTransformIndex = Array.IndexOf(Transforms, joint.Transform),
|
||||
parentTransformIndex = Array.IndexOf(Transforms, parent),
|
||||
currentTail = currentTail,
|
||||
prevTail = currentTail,
|
||||
localRotation = joint.DefaultLocalRotation,
|
||||
boneAxis = localChildPosition.normalized,
|
||||
length = localChildPosition.magnitude
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void SetExternalDataPtr(BlittableExternalData* externalData)
|
||||
{
|
||||
for (int i = 0; i < BlittableSprings.Count; ++i)
|
||||
{
|
||||
// blittableSprings[i] = blittableSprings[i] with
|
||||
// {
|
||||
// ExternalData = externalData,
|
||||
// };
|
||||
var b = BlittableSprings[i];
|
||||
b.ExternalData = externalData;
|
||||
BlittableSprings[i] = b;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void SyncAndZeroVelocity(NativeArray<BlittableLogic> logics)
|
||||
{
|
||||
for (int i = 0; i < BlittableLogics.Count; ++i)
|
||||
{
|
||||
var l = BlittableLogics[i];
|
||||
l.prevTail = l.currentTail;
|
||||
logics[i] = BlittableLogics[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 82dbc85cfa7168546b209a51f6342d84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in New Issue
Block a user