mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-30 23:01:24 -05:00
types
This commit is contained in:
@@ -16,164 +16,79 @@ namespace RotateParticle.Jobs
|
||||
public class RotateParticleJobSystem : IRotateParticleSystem
|
||||
{
|
||||
Vrm10Instance _vrm;
|
||||
TransformAccessArray _transformAccessArray;
|
||||
NativeArray<BlittableTransform> _transforms;
|
||||
|
||||
enum ParticleType
|
||||
{
|
||||
// kinematic. not verlet move
|
||||
Root,
|
||||
// particle. verlet move
|
||||
Verlet,
|
||||
// branch. move same as 1st branch sibling
|
||||
Branch,
|
||||
}
|
||||
|
||||
struct ParticleInfo
|
||||
{
|
||||
public ParticleType ParticleType;
|
||||
public int WarpIndex;
|
||||
public int ParentIndex;
|
||||
public float DistanceFromParent;
|
||||
public Quaternion InitRotation;
|
||||
public Vector3 InitTailLocalPosition;
|
||||
}
|
||||
|
||||
struct WarpInfo
|
||||
{
|
||||
public Vector3 Center;
|
||||
public float DragForce;
|
||||
public Quaternion ParentRotation;
|
||||
public int BranchRootIndex;
|
||||
public int Start;
|
||||
public int End;
|
||||
}
|
||||
NativeArray<WarpInfo> _warps;
|
||||
|
||||
TransformAccessArray _transformAccessArray;
|
||||
NativeArray<ParticleInfo> _particles;
|
||||
NativeArray<Vector3> _verletPrevOnCenter;
|
||||
NativeArray<Vector3> _verletCurrent;
|
||||
NativeArray<Vector3> _verletNext;
|
||||
|
||||
public IList<Warp> Warps => throw new NotImplementedException();
|
||||
|
||||
public IList<RectCloth> Cloths => throw new NotImplementedException();
|
||||
|
||||
struct VerletJob : IJobParallelFor
|
||||
{
|
||||
[ReadOnly] public FrameInfo Frame;
|
||||
|
||||
[ReadOnly] public NativeArray<WarpInfo> Warps;
|
||||
|
||||
|
||||
[ReadOnly] public NativeArray<ParticleInfo> Particles;
|
||||
[ReadOnly] public NativeArray<Vector3> PrevPositionsInCenter;
|
||||
[ReadOnly] public NativeArray<Vector3> CurrentPositions;
|
||||
[WriteOnly] public NativeArray<Vector3> NextPositions;
|
||||
public void Execute(int index)
|
||||
{
|
||||
var particle = Particles[index];
|
||||
if (particle.ParticleType == ParticleType.Root)
|
||||
{
|
||||
// kinematic. not move
|
||||
NextPositions[index] = CurrentPositions[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
var warp = Warps[particle.WarpIndex];
|
||||
var velocity = CurrentPositions[index] - warp.Center - PrevPositionsInCenter[index];
|
||||
velocity *= 1 - warp.DragForce;
|
||||
NextPositions[index] = CurrentPositions[index] +
|
||||
velocity + Frame.Force * Frame.SqDeltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Warp毎に verlet の結果を拘束する
|
||||
/// 1. 親子間の距離を一定に保つ
|
||||
/// 2. 移動を親の回転に変換する
|
||||
/// </summary>
|
||||
struct LocalRotationConstraintJob : IJobParallelFor
|
||||
{
|
||||
[ReadOnly] public NativeArray<WarpInfo> Warps;
|
||||
[ReadOnly] public NativeArray<ParticleInfo> Particles;
|
||||
[NativeDisableParallelForRestriction] public NativeArray<Vector3> Positions;
|
||||
[NativeDisableParallelForRestriction] public NativeArray<Quaternion> Rotations;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var warp = Warps[index];
|
||||
for (int i = warp.Start; i < warp.End; ++i)
|
||||
{
|
||||
var particle = Particles[i];
|
||||
switch (particle.ParticleType)
|
||||
{
|
||||
case ParticleType.Root:
|
||||
break;
|
||||
|
||||
case ParticleType.Verlet:
|
||||
if (i + 1 < warp.End)
|
||||
{
|
||||
var next = Particles[i + 1];
|
||||
if (next.ParentIndex == i)
|
||||
{
|
||||
/// 1. 親子間の距離を一定に保つ
|
||||
Positions[i + 1] = CalcPosition(Positions[i + 1],
|
||||
Positions[i], next.DistanceFromParent);
|
||||
// 2. 移動を親の回転に変換する
|
||||
var rest = Rotations[i] * next.InitRotation;
|
||||
Rotations[i] = rest * Quaternion.FromToRotation(
|
||||
// 初期状態
|
||||
rest * particle.InitTailLocalPosition,
|
||||
// 現状
|
||||
Positions[i + 1] - Positions[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ParticleType.Branch:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 CalcPosition(in Vector3 pos, in Vector3 parent, float distance)
|
||||
{
|
||||
return pos + (pos - parent).normalized * distance;
|
||||
}
|
||||
}
|
||||
NativeArray<Vector3> _prevPositionsOnCenter;
|
||||
NativeArray<Vector3> _currentPositions;
|
||||
NativeArray<Vector3> _nextPositions;
|
||||
NativeArray<Quaternion> _currentRotations;
|
||||
NativeArray<Quaternion> _nextRotations;
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (_transformAccessArray.isCreated) _transformAccessArray.Dispose();
|
||||
if (_warps.IsCreated) _warps.Dispose();
|
||||
if (_particles.IsCreated) _particles.Dispose();
|
||||
if (_prevPositionsOnCenter.IsCreated) _prevPositionsOnCenter.Dispose();
|
||||
if (_currentPositions.IsCreated) _currentPositions.Dispose();
|
||||
if (_nextPositions.IsCreated) _nextPositions.Dispose();
|
||||
}
|
||||
|
||||
class LocalRotaionConstraintJOb : IJob
|
||||
async Task IRotateParticleSystem.InitializeAsync(Vrm10Instance vrm, IAwaitCaller awaitCaller)
|
||||
{
|
||||
public void Execute()
|
||||
{
|
||||
_vrm = vrm;
|
||||
|
||||
List<Transform> transforms = new();
|
||||
var warps = vrm.GetComponentsInChildren<Warp>();
|
||||
foreach(var warp in warps)
|
||||
{
|
||||
|
||||
}
|
||||
await awaitCaller.NextFrame();
|
||||
}
|
||||
|
||||
JobHandle Schedule(
|
||||
in FrameInfo info,
|
||||
void IRotateParticleSystem.Process(float deltaTime)
|
||||
{
|
||||
Schedule(
|
||||
new FrameInfo(deltaTime, Vector3.zero),
|
||||
_transformAccessArray
|
||||
).Complete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// INIT PROCESS
|
||||
/// _transformAccessArray
|
||||
/// 👇
|
||||
/// _currentPositions
|
||||
/// _currentRotations
|
||||
/// </summary>
|
||||
private JobHandle Schedule(
|
||||
in FrameInfo frame,
|
||||
TransformAccessArray transformAccessArray
|
||||
)
|
||||
{
|
||||
JobHandle handle = default;
|
||||
|
||||
// load transform
|
||||
handle = new LoadTransformJob
|
||||
{
|
||||
CurrentPositions = _currentPositions,
|
||||
CurrentRotations = _currentRotations,
|
||||
}.Schedule(_transformAccessArray, handle);
|
||||
|
||||
// verlet
|
||||
handle = new VerletJob
|
||||
{
|
||||
}.Schedule(_verletCurrent.Length, 128, handle);
|
||||
Frame = frame,
|
||||
Warps = _warps,
|
||||
Particles = _particles,
|
||||
PrevPositionsOnCenter = _prevPositionsOnCenter,
|
||||
CurrentPositions = _currentPositions,
|
||||
NextPositions = _nextPositions,
|
||||
}.Schedule(_currentPositions.Length, 128, handle);
|
||||
|
||||
// local rotation constraint
|
||||
handle = new LocalRotationConstraintJob
|
||||
@@ -187,22 +102,6 @@ namespace RotateParticle.Jobs
|
||||
return handle;
|
||||
}
|
||||
|
||||
async Task IRotateParticleSystem.InitializeAsync(Vrm10Instance vrm, IAwaitCaller awaitCaller)
|
||||
{
|
||||
_vrm = vrm;
|
||||
var warps = vrm.GetComponentsInChildren<Warp>();
|
||||
await awaitCaller.NextFrame();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void IRotateParticleSystem.Process(float deltaTime)
|
||||
{
|
||||
Schedule(
|
||||
new FrameInfo(deltaTime, Vector3.zero),
|
||||
_transformAccessArray
|
||||
).Complete();
|
||||
}
|
||||
|
||||
void IRotateParticleSystem.ResetInitialRotation()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -210,7 +109,6 @@ namespace RotateParticle.Jobs
|
||||
|
||||
void IRotateParticleSystem.DrawGizmos()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Jobs;
|
||||
|
||||
|
||||
namespace RotateParticle.Jobs
|
||||
{
|
||||
public enum ParticleType
|
||||
{
|
||||
// kinematic. not verlet move
|
||||
Root,
|
||||
// particle. verlet move
|
||||
Verlet,
|
||||
// branch. move same as 1st branch sibling
|
||||
Branch,
|
||||
}
|
||||
|
||||
public struct ParticleInfo
|
||||
{
|
||||
public ParticleType ParticleType;
|
||||
public int WarpIndex;
|
||||
public int ParentIndex;
|
||||
public float DistanceFromParent;
|
||||
public Quaternion InitRotation;
|
||||
public Vector3 InitTailLocalPosition;
|
||||
}
|
||||
|
||||
public struct WarpInfo
|
||||
{
|
||||
public Vector3 Center;
|
||||
public float DragForce;
|
||||
public Quaternion ParentRotation;
|
||||
public int BranchRootIndex;
|
||||
public int Start;
|
||||
public int End;
|
||||
}
|
||||
|
||||
public struct LoadTransformJob : IJobParallelForTransform
|
||||
{
|
||||
// [ReadOnly] public NativeArray<ParticleInfo> Particles;
|
||||
[WriteOnly] public NativeArray<Vector3> CurrentPositions;
|
||||
[WriteOnly] public NativeArray<Quaternion> CurrentRotations;
|
||||
public void Execute(int index, TransformAccess transform)
|
||||
{
|
||||
// TODO: ModelSpace
|
||||
CurrentPositions[index] = transform.position;
|
||||
CurrentRotations[index] = transform.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
struct VerletJob : IJobParallelFor
|
||||
{
|
||||
[ReadOnly] public FrameInfo Frame;
|
||||
|
||||
[ReadOnly] public NativeArray<WarpInfo> Warps;
|
||||
|
||||
|
||||
[ReadOnly] public NativeArray<ParticleInfo> Particles;
|
||||
[ReadOnly] public NativeArray<Vector3> PrevPositionsOnCenter;
|
||||
[ReadOnly] public NativeArray<Vector3> CurrentPositions;
|
||||
[WriteOnly] public NativeArray<Vector3> NextPositions;
|
||||
public void Execute(int index)
|
||||
{
|
||||
var particle = Particles[index];
|
||||
if (particle.ParticleType == ParticleType.Root)
|
||||
{
|
||||
// kinematic. not move
|
||||
NextPositions[index] = CurrentPositions[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
var warp = Warps[particle.WarpIndex];
|
||||
var velocity = CurrentPositions[index] - warp.Center - PrevPositionsOnCenter[index];
|
||||
velocity *= 1 - warp.DragForce;
|
||||
NextPositions[index] = CurrentPositions[index] +
|
||||
velocity + Frame.Force * Frame.SqDeltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Warp毎に verlet の結果を拘束する
|
||||
/// 1. 親子間の距離を一定に保つ
|
||||
/// 2. 移動を親の回転に変換する
|
||||
/// </summary>
|
||||
struct LocalRotationConstraintJob : IJobParallelFor
|
||||
{
|
||||
[ReadOnly] public NativeArray<WarpInfo> Warps;
|
||||
[ReadOnly] public NativeArray<ParticleInfo> Particles;
|
||||
[NativeDisableParallelForRestriction] public NativeArray<Vector3> Positions;
|
||||
[NativeDisableParallelForRestriction] public NativeArray<Quaternion> Rotations;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var warp = Warps[index];
|
||||
for (int i = warp.Start; i < warp.End; ++i)
|
||||
{
|
||||
var particle = Particles[i];
|
||||
switch (particle.ParticleType)
|
||||
{
|
||||
case ParticleType.Root:
|
||||
break;
|
||||
|
||||
case ParticleType.Verlet:
|
||||
if (i + 1 < warp.End)
|
||||
{
|
||||
var next = Particles[i + 1];
|
||||
if (next.ParentIndex == i)
|
||||
{
|
||||
/// 1. 親子間の距離を一定に保つ
|
||||
Positions[i + 1] = CalcPosition(Positions[i + 1],
|
||||
Positions[i], next.DistanceFromParent);
|
||||
// 2. 移動を親の回転に変換する
|
||||
var rest = Rotations[i] * next.InitRotation;
|
||||
Rotations[i] = rest * Quaternion.FromToRotation(
|
||||
// 初期状態
|
||||
rest * particle.InitTailLocalPosition,
|
||||
// 現状
|
||||
Positions[i + 1] - Positions[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ParticleType.Branch:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 CalcPosition(in Vector3 pos, in Vector3 parent, float distance)
|
||||
{
|
||||
return pos + (pos - parent).normalized * distance;
|
||||
}
|
||||
}
|
||||
|
||||
class LocalRotaionConstraintJob : IJob
|
||||
{
|
||||
public void Execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 139cb8a384ad8c64abc4dcfab37bcaca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
// #define USE_ROTATEPARTICLE_JOB
|
||||
#define USE_ROTATEPARTICLE_JOB
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
@@ -11,10 +11,7 @@ namespace RotateParticle
|
||||
{
|
||||
public class RotateParticleSpringboneRuntime : IVrm10SpringBoneRuntime
|
||||
{
|
||||
Vrm10Instance _vrm;
|
||||
Action<Vrm10Instance> _onInit;
|
||||
|
||||
|
||||
IRotateParticleSystem _system;
|
||||
|
||||
public RotateParticleSpringboneRuntime(Action<Vrm10Instance> onInit = null)
|
||||
@@ -24,20 +21,20 @@ namespace RotateParticle
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_system != null)
|
||||
{
|
||||
_system.Dispose();
|
||||
_system = null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InitializeAsync(Vrm10Instance vrm, IAwaitCaller awaitCaller)
|
||||
{
|
||||
_vrm = vrm;
|
||||
if (_onInit != null)
|
||||
{
|
||||
_onInit(vrm);
|
||||
}
|
||||
|
||||
// var warps = vrm.GetComponentsInChildren<Warp>();
|
||||
// var cloths = vrm.GetComponentsInChildren<RectCloth>();
|
||||
// await awaitCaller.NextFrame();
|
||||
|
||||
#if USE_ROTATEPARTICLE_JOB
|
||||
_system = new Jobs.RotateParticleJobSystem();
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user