mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-07-20 17:21:52 -05:00
Merge branch 'master' into customShaderImport
This commit is contained in:
commit
f69ebf823e
8
Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit.meta
Normal file
8
Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b09ae318bccbfce4993fafb418e1e8c7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
public static class Anglelimit
|
||||
{
|
||||
public static float3 Apply(
|
||||
in BlittableJointImmutable logic, in BlittableJointMutable joint,
|
||||
in quaternion parentRotation, in float3 head, in float3 nextTail)
|
||||
{
|
||||
switch (joint.anglelimitType)
|
||||
{
|
||||
case AnglelimitTypes.None:
|
||||
// do nothing
|
||||
return nextTail;
|
||||
|
||||
case AnglelimitTypes.Cone:
|
||||
{
|
||||
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
|
||||
var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalize(nextTail - head));
|
||||
tailDir = AnglelimitCone.Apply(tailDir, joint.anglelimit1);
|
||||
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
|
||||
}
|
||||
|
||||
case AnglelimitTypes.Hinge:
|
||||
{
|
||||
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
|
||||
var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalize(nextTail - head));
|
||||
tailDir = AnglelimitHinge.Apply(tailDir, joint.anglelimit1);
|
||||
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
|
||||
}
|
||||
|
||||
|
||||
case AnglelimitTypes.Spherical:
|
||||
{
|
||||
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
|
||||
var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalize(nextTail - head));
|
||||
tailDir = AnglelimitSpherical.Apply(tailDir, joint.anglelimit1, joint.anglelimit2);
|
||||
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new System.ArgumentException($"unknown joint.anglelimitType: {joint.anglelimitType}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="nextTail">nextTail(position vector in world space)</param>
|
||||
/// <returns>tailDir(directionay vector in angle space)</returns>
|
||||
/// <exception cref="System.NotImplementedException"></exception>
|
||||
public static quaternion anglelimitSpaceToWorld(in BlittableJointImmutable logic, in BlittableJointMutable joint,
|
||||
in quaternion parentRotation)
|
||||
{
|
||||
// Y+方向からjointのheadからtailに向かうベクトルへの最小回転
|
||||
var axisRotation = fromToQuaternion(new float3(0, 1, 0), logic.boneAxis);
|
||||
|
||||
// limitのローカル空間をワールド空間に写像する回転
|
||||
return
|
||||
math.mul(parentRotation,
|
||||
math.mul(logic.localRotation,
|
||||
math.mul(axisRotation,
|
||||
joint.anglelimitOffset)))
|
||||
;
|
||||
}
|
||||
|
||||
// https://discussions.unity.com/t/unity-mathematics-equivalent-to-quaternion-fromtorotation/237459
|
||||
public static quaternion fromToQuaternion(in float3 from, in float3 to)
|
||||
{
|
||||
var fromNorm = math.normalize(from);
|
||||
var toNorm = math.normalize(to);
|
||||
var dot = math.dot(fromNorm, toNorm);
|
||||
|
||||
// Handle the case where from and to are parallel but opposite
|
||||
if (math.abs(dot + 1f) < 1e-6f) // dot is approximately -1
|
||||
{
|
||||
// Find a perpendicular axis
|
||||
var perpAxis = math.abs(fromNorm.x) > math.abs(fromNorm.z)
|
||||
? new float3(-fromNorm.y, fromNorm.x, 0f)
|
||||
: new float3(0f, -fromNorm.z, fromNorm.y);
|
||||
return quaternion.AxisAngle(math.normalize(perpAxis), math.PI);
|
||||
}
|
||||
|
||||
// General case
|
||||
return quaternion.AxisAngle(
|
||||
angle: math.acos(math.clamp(dot, -1f, 1f)),
|
||||
axis: math.normalize(math.cross(fromNorm, toNorm))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3c2f98858052fbe4c89b445bad4c979b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
public static class AnglelimitCone
|
||||
{
|
||||
/// <param name="src">AngleLimit空間の方向ベクトル</param>
|
||||
/// <param name="angleLimit">radius</param>
|
||||
/// <returns>AngleLimit空間の方向ベクトル</returns>
|
||||
public static float3 Apply(in float3 src, float angleLimit)
|
||||
{
|
||||
// tailDirのy要素をjointに設定されたangleの余弦と比較する
|
||||
var cosAngle = math.cos(angleLimit);
|
||||
if (src.y >= cosAngle)
|
||||
{
|
||||
return src;
|
||||
}
|
||||
|
||||
var tailDir = src;
|
||||
{
|
||||
// x・z要素を、tailDirの正弦とjointに設定されたangleの正弦の比を用いてスケールする
|
||||
var ratio = math.sqrt((1.0f - cosAngle * cosAngle) / (1.0f - tailDir.y * tailDir.y));
|
||||
tailDir.x *= ratio;
|
||||
tailDir.z *= ratio;
|
||||
|
||||
// y要素を、jointに設定されたangleの余弦とする
|
||||
tailDir.y = cosAngle;
|
||||
}
|
||||
|
||||
return tailDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 780b79f298faea74ba4a123039a3faeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
public static class AnglelimitHinge
|
||||
{
|
||||
/// <param name="src">AngleLimit空間の方向ベクトル</param>
|
||||
/// <param name="angleLimit">radius</param>
|
||||
/// <returns>AngleLimit空間の方向ベクトル</returns>
|
||||
public static float3 Apply(in float3 src, float limitAngle)
|
||||
{
|
||||
// x要素を0にし、正規化する
|
||||
float3 tailDir = src;
|
||||
tailDir.x = 0.0f;
|
||||
tailDir = math.normalize(tailDir);
|
||||
|
||||
// tailDirのy要素をjointに設定されたangleの余弦と比較する
|
||||
var cosAngle = math.cos(limitAngle);
|
||||
if (tailDir.y < cosAngle)
|
||||
{
|
||||
// z要素を、tailDirの正弦とjointに設定されたangleの正弦の比を用いてスケールする
|
||||
var ratio = math.sqrt((1.0f - cosAngle * cosAngle) / (1.0f - tailDir.y * tailDir.y));
|
||||
tailDir.z *= ratio;
|
||||
|
||||
// y要素を、jointに設定されたangleの余弦とする
|
||||
tailDir.y = cosAngle;
|
||||
}
|
||||
|
||||
return tailDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb1e1bbfc1a339c40b5df4d846f09da4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
public static class AnglelimitSpherical
|
||||
{
|
||||
/// <param name="tailDir">AngleLimit空間の方向ベクトル</param>
|
||||
/// <param name="limitAnglePhi">radius</param>
|
||||
/// <param name="limitAngleTheta">radius</param>
|
||||
/// <returns>AngleLimit空間の方向ベクトル</returns>
|
||||
public static float3 Apply(in float3 tailDir, float limitAnglePhi, float limitAngleTheta)
|
||||
{
|
||||
// tailDirのphi・thetaを計算する
|
||||
var phi = math.atan2(tailDir.z, tailDir.y);
|
||||
var theta = math.asin(tailDir.x);
|
||||
|
||||
// phi・thetaをjointに設定されたphi・thetaを用いて制限する
|
||||
// var isLimited = false;
|
||||
if (math.abs(phi) > limitAnglePhi)
|
||||
{
|
||||
// isLimited = true;
|
||||
phi = limitAnglePhi * math.sign(phi);
|
||||
}
|
||||
|
||||
// thetaをjointに設定されたthetaを用いて制限する
|
||||
if (math.abs(theta) > limitAngleTheta)
|
||||
{
|
||||
// isLimited = true;
|
||||
theta = limitAngleTheta * math.sign(theta);
|
||||
}
|
||||
|
||||
// tailDirをphi・thetaを用いて再計算する
|
||||
var cos_theta = math.cos(theta);
|
||||
return new float3(math.sin(theta), cos_theta * math.cos(phi), cos_theta * math.sin(phi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cc767b94391a0c44ebd21390c57a869e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
public enum AnglelimitTypes
|
||||
{
|
||||
None,
|
||||
Cone,
|
||||
Hinge,
|
||||
Spherical,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 56836f5a87c46a641a0ffc048c10655f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
|
|
@ -7,15 +8,35 @@ namespace UniGLTF.SpringBoneJobs.Blittables
|
|||
/// Blittableなコライダ
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct BlittableCollider
|
||||
public readonly struct BlittableCollider
|
||||
{
|
||||
public BlittableColliderType colliderType;
|
||||
public Vector3 offset;
|
||||
public float radius;
|
||||
// capsule tail or plane normal
|
||||
public Vector3 tailOrNormal;
|
||||
public int transformIndex;
|
||||
private readonly float3x3 _data;
|
||||
|
||||
public BlittableColliderType colliderType => (BlittableColliderType)(int)_data.c2.y;
|
||||
public float3 offset => _data.c0;
|
||||
public float radius => _data.c2.x;
|
||||
// capsule tail or plane normal
|
||||
public float3 tailOrNormal => _data.c1;
|
||||
public int transformIndex => (int)_data.c2.z;
|
||||
|
||||
public BlittableCollider(
|
||||
float3 offset = default,
|
||||
float radius = 0,
|
||||
float3 tailOrNormal = default,
|
||||
BlittableColliderType colliderType = default,
|
||||
int colliderTransformIndex = 0)
|
||||
{
|
||||
var c0 = offset;
|
||||
var c1 = tailOrNormal;
|
||||
var c2 = new float3(radius,(int)colliderType, colliderTransformIndex);
|
||||
_data = new float3x3(c0, c1, c2);
|
||||
}
|
||||
|
||||
public BlittableCollider SetTransformIndex(int index)
|
||||
{
|
||||
return new BlittableCollider(offset, radius, tailOrNormal, colliderType, index);
|
||||
}
|
||||
|
||||
public void DrawGizmo(BlittableTransform t)
|
||||
{
|
||||
Gizmos.matrix = t.localToWorldMatrix;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
|
|
@ -9,15 +10,31 @@ namespace UniGLTF.SpringBoneJobs.Blittables
|
|||
/// 変わりにくいスコープ。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct BlittableJointImmutable
|
||||
public readonly struct BlittableJointImmutable
|
||||
{
|
||||
public int parentTransformIndex;
|
||||
public int headTransformIndex;
|
||||
public int tailTransformIndex;
|
||||
public float length;
|
||||
public Quaternion localRotation;
|
||||
public Vector3 boneAxis;
|
||||
private readonly float4x3 _data;
|
||||
|
||||
public int parentTransformIndex => (int)_data.c2.x;
|
||||
public int headTransformIndex => (int)_data.c2.y;
|
||||
public int tailTransformIndex => (int)_data.c2.z;
|
||||
public float length => _data.c2.w;
|
||||
public quaternion localRotation => _data.c0;
|
||||
public float3 boneAxis => _data.c1.xyz;
|
||||
|
||||
public BlittableJointImmutable(
|
||||
int parentTransformIndex = 0,
|
||||
int headTransformIndex = 0,
|
||||
int tailTransformIndex = 0,
|
||||
float length = 0,
|
||||
quaternion localRotation = default,
|
||||
float3 boneAxis = default)
|
||||
{
|
||||
var c0 = localRotation.value;
|
||||
var c1 = new float4(boneAxis, 0);
|
||||
var c2 = new float4(parentTransformIndex, headTransformIndex, tailTransformIndex, length);
|
||||
_data = new float4x3(c0, c1, c2);
|
||||
}
|
||||
|
||||
public void DrawGizmo(BlittableTransform t, BlittableJointMutable m)
|
||||
{
|
||||
Gizmos.matrix = t.localToWorldMatrix;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
|
|
@ -10,12 +10,50 @@ namespace UniGLTF.SpringBoneJobs.Blittables
|
|||
/// JointReconfigure を呼ばなければ以前と同じで不変となる。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct BlittableJointMutable
|
||||
public readonly struct BlittableJointMutable
|
||||
{
|
||||
public float stiffnessForce;
|
||||
public float gravityPower;
|
||||
public Vector3 gravityDir;
|
||||
public float dragForce;
|
||||
public float radius;
|
||||
/// <summary>
|
||||
/// |x |y |z |w |
|
||||
/// |--------|--------|--------|--------|
|
||||
/// |stiff |g-power |drag |radius |
|
||||
/// |g-dir.x |g-dir.y |g-dir.z | |
|
||||
/// |al.type |limit1 |limit2 |
|
||||
/// |offset.x|offset.y|offset.z|offset.w|
|
||||
///
|
||||
/// g-power = gravityPower
|
||||
/// g-dir = gravityDir
|
||||
/// al = anglelimit
|
||||
/// offset = anglelimitOffset
|
||||
/// </summary>
|
||||
private readonly float4x4 _data;
|
||||
|
||||
public float stiffnessForce => _data.c0.x;
|
||||
public float gravityPower => _data.c0.y;
|
||||
public float3 gravityDir => _data.c1.xyz;
|
||||
public float dragForce => _data.c0.z;
|
||||
public float radius => _data.c0.w;
|
||||
|
||||
public AnglelimitTypes anglelimitType => (AnglelimitTypes)_data.c2.x;
|
||||
public float anglelimit1 => _data.c2.y;
|
||||
public float anglelimit2 => _data.c2.z;
|
||||
public quaternion anglelimitOffset => _data.c3.xyzw;
|
||||
|
||||
public BlittableJointMutable(float stiffnessForce = 0,
|
||||
float gravityPower = 0,
|
||||
float3 gravityDir = default,
|
||||
float dragForce = 0,
|
||||
float radius = 0,
|
||||
// v0.129.4 anglelimit
|
||||
float angleLimitType = 0,
|
||||
float angleLimit1 = 0,
|
||||
float angleLimit2 = 0,
|
||||
quaternion angleLimitOffset = default)
|
||||
{
|
||||
var c0 = new float4(stiffnessForce, gravityPower, dragForce, radius);
|
||||
var c1 = new float4(gravityDir, 0);
|
||||
var c2 = new float4(angleLimitType, angleLimit1, angleLimit2, 0);
|
||||
var c3 = angleLimitOffset.value;
|
||||
_data = new float4x4(c0, c1, c2, c3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,33 @@
|
|||
using UnityEngine;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
public struct BlittableModelLevel
|
||||
public readonly struct BlittableModelLevel
|
||||
{
|
||||
private readonly float4 _data;
|
||||
|
||||
/// <summary>
|
||||
/// World 座標系の追加の力。風など。
|
||||
/// </summary>
|
||||
public Vector3 ExternalForce;
|
||||
public float3 ExternalForce => _data.xyz;
|
||||
|
||||
/// <summary>
|
||||
/// 処理結果の Transform への書き戻しを停止する。
|
||||
/// </summary>
|
||||
public bool StopSpringBoneWriteback;
|
||||
public bool StopSpringBoneWriteback => ((int)_data.w & 1) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// スケール値に連動して SpringBone のパラメータを自動調整する。
|
||||
/// (見た目の角速度が同じになるようにする)
|
||||
/// </summary>
|
||||
public bool SupportsScalingAtRuntime;
|
||||
public bool SupportsScalingAtRuntime => ((int)_data.w & 2) != 0;
|
||||
|
||||
public BlittableModelLevel(float3 externalForce = default,
|
||||
bool stopSpringBoneWriteback = false,
|
||||
bool supportsScalingAtRuntime = false)
|
||||
{
|
||||
var w = (stopSpringBoneWriteback ? 1 : 0) | ((supportsScalingAtRuntime ? 1 : 0) << 1);
|
||||
_data = new float4(externalForce, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,11 +3,20 @@ using System;
|
|||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
[Serializable]
|
||||
public struct BlittableSpan
|
||||
public readonly struct BlittableSpan
|
||||
{
|
||||
public int startIndex;
|
||||
public int count;
|
||||
private readonly int _startIndex;
|
||||
private readonly int _count;
|
||||
|
||||
public int startIndex => _startIndex;
|
||||
public int count => _count;
|
||||
|
||||
public int EndIndex => startIndex + count;
|
||||
|
||||
public BlittableSpan(int startIndex, int count)
|
||||
{
|
||||
_startIndex = startIndex;
|
||||
_count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
|
|
@ -7,12 +8,21 @@ namespace UniGLTF.SpringBoneJobs.Blittables
|
|||
/// FastSpringBoneではこれを起点として並列化し、処理を行う
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct BlittableSpring
|
||||
public readonly struct BlittableSpring
|
||||
{
|
||||
public BlittableSpan colliderSpan;
|
||||
public BlittableSpan logicSpan;
|
||||
public int centerTransformIndex;
|
||||
public int transformIndexOffset;
|
||||
public int modelIndex;
|
||||
private readonly int4x2 _data;
|
||||
|
||||
public BlittableSpan colliderSpan => new(_data.c0.x, _data.c0.y);
|
||||
public BlittableSpan logicSpan => new(_data.c0.z, _data.c0.w);
|
||||
public int centerTransformIndex => _data.c1.x;
|
||||
public int transformIndexOffset => _data.c1.y;
|
||||
public int modelIndex => _data.c1.z;
|
||||
|
||||
public BlittableSpring(BlittableSpan colliderSpan = default, BlittableSpan logicSpan = default, int centerTransformIndex = 0, int transformIndexOffset = 0, int modelIndex = 0)
|
||||
{
|
||||
var c0 = new int4(colliderSpan.startIndex, colliderSpan.count, logicSpan.startIndex, logicSpan.count);
|
||||
var c1 = new int4(centerTransformIndex, transformIndexOffset, modelIndex, 0);
|
||||
_data = new int4x2(c0, c1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine.Jobs;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.Blittables
|
||||
{
|
||||
|
|
@ -7,14 +9,147 @@ namespace UniGLTF.SpringBoneJobs.Blittables
|
|||
/// Transformの必要な機能だけを絞り、Blittableに対応させたクラス
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct BlittableTransform
|
||||
public readonly struct BlittableTransform
|
||||
{
|
||||
public Vector3 position;
|
||||
public Quaternion rotation;
|
||||
public Vector3 localPosition;
|
||||
public Quaternion localRotation;
|
||||
public Vector3 localScale;
|
||||
public Matrix4x4 localToWorldMatrix;
|
||||
public Matrix4x4 worldToLocalMatrix;
|
||||
private readonly float4x3 _localData;
|
||||
private readonly float4x4 _globalData;
|
||||
|
||||
public float3 position => GetPosition();
|
||||
public quaternion rotation => GetRotation();
|
||||
public float3 lossyScale => GetLossyScale();
|
||||
public float3 localPosition => _localData.c0.xyz;
|
||||
public quaternion localRotation => _localData.c1;
|
||||
public float3 localScale => _localData.c2.xyz;
|
||||
public float4x4 localToWorldMatrix => GetLocalToWorldMatrix();
|
||||
public float4x4 worldToLocalMatrix => math.inverse(localToWorldMatrix);
|
||||
|
||||
public static BlittableTransform FromTransformAccess(TransformAccess transform)
|
||||
{
|
||||
return new BlittableTransform(
|
||||
transform.rotation,
|
||||
transform.localPosition,
|
||||
transform.localRotation,
|
||||
transform.localScale,
|
||||
transform.localToWorldMatrix);
|
||||
}
|
||||
|
||||
private BlittableTransform(
|
||||
quaternion rotation,
|
||||
float3 localPosition,
|
||||
quaternion localRotation,
|
||||
float3 localScale,
|
||||
float4x4 localToWorldMatrix)
|
||||
{
|
||||
var c10 = new float4(localPosition, 0);
|
||||
var c11 = localRotation;
|
||||
var c12 = new float4(localScale, 0);
|
||||
_localData = new float4x3(c10, c11.value, c12);
|
||||
|
||||
var c20 = new float4(localToWorldMatrix.c0.xyz, rotation.value.x);
|
||||
var c21 = new float4(localToWorldMatrix.c1.xyz, rotation.value.y);
|
||||
var c22 = new float4(localToWorldMatrix.c2.xyz, rotation.value.z);
|
||||
var c23 = new float4(localToWorldMatrix.c3.xyz, rotation.value.w);
|
||||
_globalData = new float4x4(c20, c21, c22, c23);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private float4x4 GetLocalToWorldMatrix()
|
||||
{
|
||||
var c0 = new float4(_globalData.c0.xyz, 0);
|
||||
var c1 = new float4(_globalData.c1.xyz, 0);
|
||||
var c2 = new float4(_globalData.c2.xyz, 0);
|
||||
var c3 = new float4(_globalData.c3.xyz, 1);
|
||||
return new float4x4(c0, c1, c2, c3);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private float3 GetPosition()
|
||||
{
|
||||
return localToWorldMatrix.c3.xyz;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private quaternion GetRotation()
|
||||
{
|
||||
return new quaternion(_globalData.c0.w, _globalData.c1.w, _globalData.c2.w, _globalData.c3.w);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private float3 GetLossyScale()
|
||||
{
|
||||
float4x4 tr = float4x4.TRS(position, rotation, new float3(1.0f));
|
||||
float4x4 m = math.mul(math.inverse(tr), localToWorldMatrix);
|
||||
return new float3(m.c0.x, m.c1.y, m.c2.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 親Transformが移動や回転を行った際に、ローカル座標系の値をもとに新しい絶対座標系でのTransformを計算します。
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <returns></returns>
|
||||
public BlittableTransform UpdateParentMatrix(BlittableTransform parent)
|
||||
{
|
||||
quaternion newRotation = math.mul(parent.rotation, localRotation);
|
||||
float4x4 newLocalToWorldMatrix = math.mul(parent.localToWorldMatrix, float4x4.TRS(localPosition, localRotation, localScale));
|
||||
|
||||
return new BlittableTransform(newRotation, localPosition, localRotation, localScale, newLocalToWorldMatrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// グローバル座標系での位置を更新し、それに伴って連動する他の値も更新します。
|
||||
/// </summary>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="parent"></param>
|
||||
/// <returns></returns>
|
||||
public BlittableTransform UpdatePosition(float3 newValue, BlittableTransform? parent = null)
|
||||
{
|
||||
quaternion newRotation;
|
||||
float3 newLocalPosition;
|
||||
quaternion newLocalRotation;
|
||||
float4x4 newLocalToWorldMatrix;
|
||||
|
||||
if(parent.HasValue)
|
||||
{
|
||||
newLocalPosition = math.transform(parent.Value.worldToLocalMatrix, newValue);
|
||||
newLocalRotation = math.mul(math.inverse(parent.Value.rotation), rotation);
|
||||
newRotation = math.mul(parent.Value.rotation, newLocalRotation);
|
||||
newLocalToWorldMatrix = math.mul(parent.Value.localToWorldMatrix, float4x4.TRS(newLocalPosition, newLocalRotation, localScale));
|
||||
}
|
||||
else
|
||||
{
|
||||
newLocalPosition = newValue;
|
||||
newLocalRotation = rotation;
|
||||
newRotation = rotation;
|
||||
newLocalToWorldMatrix = float4x4.TRS(newValue, newRotation, localScale);
|
||||
}
|
||||
|
||||
return new BlittableTransform(newRotation, newLocalPosition, newLocalRotation, localScale, newLocalToWorldMatrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// グローバル座標系での回転を更新し、それに伴って連動する他の値も更新します。
|
||||
/// </summary>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="parent"></param>
|
||||
/// <returns></returns>
|
||||
public BlittableTransform UpdateRotation(quaternion newValue, BlittableTransform? parent = null)
|
||||
{
|
||||
quaternion newRotation = newValue;
|
||||
quaternion newLocalRotation;
|
||||
float4x4 newLocalToWorldMatrix;
|
||||
|
||||
if(parent.HasValue)
|
||||
{
|
||||
newLocalRotation = math.normalize(math.mul(math.inverse(parent.Value.rotation), newRotation));
|
||||
newLocalToWorldMatrix = math.mul(parent.Value.localToWorldMatrix, float4x4.TRS(localPosition, newLocalRotation, localScale));
|
||||
}
|
||||
else
|
||||
{
|
||||
newLocalRotation = newValue;
|
||||
newLocalToWorldMatrix = float4x4.TRS(position, newRotation, localScale);
|
||||
}
|
||||
|
||||
return new BlittableTransform(newRotation, localPosition, newLocalRotation, localScale, newLocalToWorldMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ using Unity.Burst;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UniGLTF.Runtime.Utils;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using UniGLTF.SpringBoneJobs.InputPorts;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Jobs;
|
||||
using UnityEngine.Profiling;
|
||||
|
|
@ -23,9 +25,9 @@ namespace UniGLTF.SpringBoneJobs
|
|||
// Joint Level
|
||||
private NativeArray<BlittableJointImmutable> _logics;
|
||||
private NativeArray<BlittableJointMutable> _joints;
|
||||
private NativeArray<Vector3> _prevTails;
|
||||
private NativeArray<Vector3> _currentTails;
|
||||
private NativeArray<Vector3> _nextTails;
|
||||
private NativeArray<float3> _prevTails;
|
||||
private NativeArray<float3> _currentTails;
|
||||
private NativeArray<float3> _nextTails;
|
||||
// Spring Level
|
||||
private NativeArray<BlittableSpring> _springs;
|
||||
// Moodel Level
|
||||
|
|
@ -39,9 +41,9 @@ namespace UniGLTF.SpringBoneJobs
|
|||
// 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;
|
||||
public NativeArray<float3> PrevTails => _prevTails;
|
||||
public NativeArray<float3> CurrentTails => _currentTails;
|
||||
public NativeArray<float3> NextTails => _nextTails;
|
||||
// accessor: Spring Level
|
||||
public NativeArray<BlittableSpring> Springs => _springs;
|
||||
// accessor: Model LEvel
|
||||
|
|
@ -64,9 +66,9 @@ namespace UniGLTF.SpringBoneJobs
|
|||
// 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);
|
||||
_prevTails = new NativeArray<float3>(logicsCount, Allocator.Persistent);
|
||||
_currentTails = new NativeArray<float3>(logicsCount, Allocator.Persistent);
|
||||
_nextTails = new NativeArray<float3>(logicsCount, Allocator.Persistent);
|
||||
// spring level
|
||||
_springs = new NativeArray<BlittableSpring>(springsCount, Allocator.Persistent);
|
||||
// model level
|
||||
|
|
@ -248,11 +250,12 @@ 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;
|
||||
DestSprings[index] = spring;
|
||||
DestSprings[index] = new BlittableSpring(
|
||||
modelIndex: ModelIndex,
|
||||
colliderSpan: new BlittableSpan(spring.colliderSpan.startIndex + CollidersOffset, spring.colliderSpan.count),
|
||||
logicSpan: new BlittableSpan(spring.logicSpan.startIndex + LogicsOffset, spring.logicSpan.count),
|
||||
transformIndexOffset: TransformOffset,
|
||||
centerTransformIndex: spring.centerTransformIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -296,9 +299,9 @@ namespace UniGLTF.SpringBoneJobs
|
|||
|
||||
[ReadOnly] public NativeArray<BlittableJointImmutable> Logics;
|
||||
[ReadOnly] public NativeArray<BlittableTransform> Transforms;
|
||||
[NativeDisableParallelForRestriction] public NativeSlice<Vector3> CurrentTails;
|
||||
[NativeDisableParallelForRestriction] public NativeSlice<Vector3> PrevTails;
|
||||
[NativeDisableParallelForRestriction] public NativeSlice<Vector3> NextTails;
|
||||
[NativeDisableParallelForRestriction] public NativeSlice<float3> CurrentTails;
|
||||
[NativeDisableParallelForRestriction] public NativeSlice<float3> PrevTails;
|
||||
[NativeDisableParallelForRestriction] public NativeSlice<float3> NextTails;
|
||||
|
||||
public void Execute(int springIndex)
|
||||
{
|
||||
|
|
@ -323,7 +326,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
}
|
||||
|
||||
var tail = Transforms[tailIndex];
|
||||
var tailPos = center.HasValue ? center.Value.worldToLocalMatrix.MultiplyPoint3x4(tail.position) : tail.position;
|
||||
var tailPos = center.HasValue ? MathHelper.MultiplyPoint3x4(center.Value.worldToLocalMatrix, tail.position) : tail.position;
|
||||
CurrentTails[jointIndex] = tailPos;
|
||||
PrevTails[jointIndex] = tailPos;
|
||||
NextTails[jointIndex] = tailPos;
|
||||
|
|
|
|||
|
|
@ -18,9 +18,13 @@ namespace UniGLTF.SpringBoneJobs
|
|||
_bufferCombiner.Dispose();
|
||||
}
|
||||
|
||||
public JobHandle Schedule(float deltaTime)
|
||||
public JobHandle Schedule(float deltaTime, JobHandle? dependency = null)
|
||||
{
|
||||
var handle = _bufferCombiner.ReconstructIfDirty(default);
|
||||
if(dependency.HasValue)
|
||||
{
|
||||
handle = JobHandle.CombineDependencies(handle, dependency.Value);
|
||||
}
|
||||
if (!_bufferCombiner.HasBuffer)
|
||||
{
|
||||
return handle;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs.InputPorts
|
||||
{
|
||||
|
|
@ -22,8 +23,8 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
public NativeArray<BlittableJointMutable> Joints { get; }
|
||||
public NativeArray<BlittableCollider> Colliders { get; }
|
||||
public NativeArray<BlittableJointImmutable> Logics { get; }
|
||||
private NativeArray<Vector3> _currentTailsBackup;
|
||||
private NativeArray<Vector3> _nextTailsBackup;
|
||||
private NativeArray<float3> _currentTailsBackup;
|
||||
private NativeArray<float3> _nextTailsBackup;
|
||||
public Transform[] Transforms { get; }
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -67,27 +68,17 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
List<BlittableJointImmutable> 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),
|
||||
};
|
||||
var blittableSpring = new BlittableSpring(
|
||||
centerTransformIndex: Array.IndexOf(Transforms, spring.center),
|
||||
colliderSpan: new BlittableSpan(blittableColliders.Count, spring.colliders.Length),
|
||||
logicSpan: new BlittableSpan(blittableJoints.Count, spring.joints.Length - 1));
|
||||
blittableSprings.Add(blittableSpring);
|
||||
|
||||
blittableColliders.AddRange(spring.colliders.Select(collider =>
|
||||
{
|
||||
var blittable = collider.Collider;
|
||||
blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform);
|
||||
return blittable;
|
||||
var transformIndex = Array.IndexOf(Transforms, collider.Transform);
|
||||
return blittable.SetTransformIndex(transformIndex);
|
||||
}));
|
||||
blittableJoints.AddRange(spring.joints
|
||||
.Take(spring.joints.Length - 1).Select(joint =>
|
||||
|
|
@ -123,25 +114,23 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
var localPosition = tailJoint.Transform.localPosition;
|
||||
|
||||
var scale = tailJoint.Transform.lossyScale;
|
||||
var localChildPosition = new Vector3(
|
||||
var localChildPosition = new float3(
|
||||
localPosition.x * scale.x,
|
||||
localPosition.y * scale.y,
|
||||
localPosition.z * scale.z
|
||||
);
|
||||
|
||||
yield return new BlittableJointImmutable
|
||||
{
|
||||
headTransformIndex = Array.IndexOf<Transform>(Transforms, joint.Transform),
|
||||
parentTransformIndex = Array.IndexOf<Transform>(Transforms, joint.Transform.parent),
|
||||
tailTransformIndex = Array.IndexOf<Transform>(Transforms, tailJoint.Transform),
|
||||
localRotation = joint.DefaultLocalRotation,
|
||||
boneAxis = localChildPosition.normalized,
|
||||
length = localChildPosition.magnitude
|
||||
};
|
||||
yield return new BlittableJointImmutable(
|
||||
headTransformIndex: Array.IndexOf<Transform>(Transforms, joint.Transform),
|
||||
parentTransformIndex: Array.IndexOf<Transform>(Transforms, joint.Transform.parent),
|
||||
tailTransformIndex: Array.IndexOf<Transform>(Transforms, tailJoint.Transform),
|
||||
localRotation: joint.DefaultLocalRotation,
|
||||
boneAxis: math.normalize(localChildPosition),
|
||||
length: math.length(localChildPosition));
|
||||
}
|
||||
}
|
||||
|
||||
public void BackupCurrentTails(NativeArray<Vector3> currentTails, NativeArray<Vector3> nextTails, int offset)
|
||||
public void BackupCurrentTails(NativeArray<float3> currentTails, NativeArray<float3> nextTails, int offset)
|
||||
{
|
||||
if (!Logics.IsCreated || Logics.Length == 0)
|
||||
{
|
||||
|
|
@ -155,16 +144,16 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
{
|
||||
_nextTailsBackup = new(Logics.Length, Allocator.Persistent);
|
||||
}
|
||||
NativeArray<Vector3>.Copy(currentTails, offset, _currentTailsBackup, 0, Logics.Length);
|
||||
NativeArray<Vector3>.Copy(nextTails, offset, _nextTailsBackup, 0, Logics.Length);
|
||||
NativeArray<float3>.Copy(currentTails, offset, _currentTailsBackup, 0, Logics.Length);
|
||||
NativeArray<float3>.Copy(nextTails, offset, _nextTailsBackup, 0, Logics.Length);
|
||||
}
|
||||
|
||||
public void RestoreCurrentTails(NativeArray<Vector3> currentTails, NativeArray<Vector3> nextTails, int offset)
|
||||
public void RestoreCurrentTails(NativeArray<float3> currentTails, NativeArray<float3> nextTails, int offset)
|
||||
{
|
||||
if (_currentTailsBackup.IsCreated)
|
||||
{
|
||||
NativeArray<Vector3>.Copy(_currentTailsBackup, 0, currentTails, offset, Logics.Length);
|
||||
NativeArray<Vector3>.Copy(_nextTailsBackup, 0, nextTails, offset, Logics.Length);
|
||||
NativeArray<float3>.Copy(_currentTailsBackup, 0, currentTails, offset, Logics.Length);
|
||||
NativeArray<float3>.Copy(_nextTailsBackup, 0, nextTails, offset, Logics.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -173,7 +162,7 @@ namespace UniGLTF.SpringBoneJobs.InputPorts
|
|||
{
|
||||
// mark velocity zero
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
currentTails.GetSubArray(offset, Logics.Length).AsSpan().Fill(new Vector3(float.NaN, float.NaN, float.NaN));
|
||||
currentTails.GetSubArray(offset, Logics.Length).AsSpan().Fill(new float3(float.NaN, float.NaN, float.NaN));
|
||||
#else
|
||||
var subArray = currentTails.GetSubArray(offset, Logics.Length);
|
||||
var value = new Vector3(float.NaN, float.NaN, float.NaN);
|
||||
|
|
|
|||
|
|
@ -17,16 +17,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
|
||||
public void Execute(int index, TransformAccess transform)
|
||||
{
|
||||
Transforms[index] = new BlittableTransform
|
||||
{
|
||||
position = transform.position,
|
||||
rotation = transform.rotation,
|
||||
localPosition = transform.localPosition,
|
||||
localRotation = transform.localRotation,
|
||||
localScale = transform.localScale,
|
||||
localToWorldMatrix = transform.localToWorldMatrix,
|
||||
worldToLocalMatrix = transform.worldToLocalMatrix
|
||||
};
|
||||
Transforms[index] = BlittableTransform.FromTransformAccess(transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
206
Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs
Normal file
206
Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
using UniGLTF.Runtime.Utils;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.SpringBoneJobs
|
||||
{
|
||||
public static class SpringBoneCollision
|
||||
{
|
||||
public static bool TryCollide(
|
||||
in BlittableJointImmutable logic, in BlittableJointMutable joint, in BlittableTransform headTransform,
|
||||
in BlittableCollider collider, in BlittableTransform colliderTransform, float maxColliderScale,
|
||||
in float3 colliderWorldTail, in float3 colliderWorldPosition,
|
||||
in float3 nextTail, out float3 newNextTail)
|
||||
{
|
||||
switch (collider.colliderType)
|
||||
{
|
||||
case BlittableColliderType.Sphere:
|
||||
return TryResolveSphereCollision(joint, collider, colliderWorldPosition, headTransform, maxColliderScale, logic, nextTail, out newNextTail);
|
||||
|
||||
case BlittableColliderType.Capsule:
|
||||
return TryResolveCapsuleCollision(colliderWorldTail, colliderWorldPosition, headTransform, joint, collider, maxColliderScale, logic, nextTail, out newNextTail);
|
||||
|
||||
case BlittableColliderType.Plane:
|
||||
return TryResolvePlaneCollision(joint, collider, colliderTransform, nextTail, out newNextTail);
|
||||
|
||||
case BlittableColliderType.SphereInside:
|
||||
return TryResolveSphereCollisionInside(joint, collider, colliderTransform, nextTail, out newNextTail);
|
||||
|
||||
case BlittableColliderType.CapsuleInside:
|
||||
return TryResolveCapsuleCollisionInside(joint, collider, colliderTransform, nextTail, out newNextTail);
|
||||
|
||||
default:
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryResolveSphereCollision(
|
||||
in BlittableJointMutable joint,
|
||||
in BlittableCollider collider,
|
||||
in float3 worldPosition,
|
||||
in BlittableTransform headTransform,
|
||||
in float maxColliderScale,
|
||||
in BlittableJointImmutable logic,
|
||||
in float3 nextTail, out float3 newNextTail)
|
||||
{
|
||||
var r = joint.radius + collider.radius * maxColliderScale;
|
||||
if (math.lengthsq(nextTail - worldPosition) <= (r * r))
|
||||
{
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
var normal = math.normalize(nextTail - worldPosition);
|
||||
var posFromCollider = worldPosition + normal * r;
|
||||
// 長さをboneLengthに強制
|
||||
newNextTail = headTransform.position + math.normalize(posFromCollider - headTransform.position) * logic.length;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNextTail = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryResolveCapsuleCollision(
|
||||
float3 worldTail,
|
||||
float3 worldPosition,
|
||||
BlittableTransform headTransform,
|
||||
BlittableJointMutable joint,
|
||||
BlittableCollider collider,
|
||||
float maxColliderScale,
|
||||
BlittableJointImmutable logic,
|
||||
in float3 nextTail, out float3 newNextTail)
|
||||
{
|
||||
var direction = worldTail - worldPosition;
|
||||
if (math.lengthsq(direction) == 0)
|
||||
{
|
||||
// head側半球の球判定
|
||||
return TryResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, nextTail, out newNextTail);
|
||||
}
|
||||
var P = math.normalize(direction);
|
||||
var Q = headTransform.position - worldPosition;
|
||||
var dot = math.dot(P, Q);
|
||||
if (dot <= 0)
|
||||
{
|
||||
// head側半球の球判定
|
||||
return TryResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, nextTail, out newNextTail);
|
||||
}
|
||||
if (dot >= math.length(direction))
|
||||
{
|
||||
// tail側半球の球判定
|
||||
return TryResolveSphereCollision(joint, collider, worldTail, headTransform, maxColliderScale, logic, nextTail, out newNextTail);
|
||||
}
|
||||
|
||||
// head-tail上の m_transform.position との最近点
|
||||
var p = worldPosition + P * dot;
|
||||
return TryResolveSphereCollision(joint, collider, p, headTransform, maxColliderScale, logic, nextTail, out newNextTail);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collision with SpringJoint and PlaneCollider.
|
||||
/// If collide update nextTail.
|
||||
/// </summary>
|
||||
/// <param name="joint">joint</param>
|
||||
/// <param name="collider">collider</param>
|
||||
/// <param name="colliderTransform">colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset);</param>
|
||||
/// <param name="nextTail">result of verlet integration</param>
|
||||
private static bool TryResolvePlaneCollision(
|
||||
in BlittableJointMutable joint,
|
||||
in BlittableCollider collider,
|
||||
in BlittableTransform colliderTransform,
|
||||
in float3 nextTail, out float3 newNextTail)
|
||||
{
|
||||
var transformedOffset = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.offset);
|
||||
var transformedNormal = math.normalize(MathHelper.MultiplyVector(colliderTransform.localToWorldMatrix, collider.tailOrNormal));
|
||||
var delta = nextTail - transformedOffset;
|
||||
|
||||
// ジョイントとコライダーの距離。負の値は衝突していることを示す
|
||||
var distance = math.dot(delta, transformedNormal) - joint.radius;
|
||||
|
||||
if (distance < 0)
|
||||
{
|
||||
// ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
|
||||
var direction = transformedNormal;
|
||||
newNextTail = nextTail - direction * distance;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNextTail = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryResolveSphereCollisionInside(
|
||||
in BlittableJointMutable joint,
|
||||
in BlittableCollider collider,
|
||||
in BlittableTransform colliderTransform,
|
||||
in float3 nextTail, out float3 newNextTail)
|
||||
{
|
||||
var transformedOffset = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.offset);
|
||||
var delta = nextTail - transformedOffset;
|
||||
|
||||
// ジョイントとコライダーの距離。負の値は衝突していることを示す
|
||||
var distance = collider.radius - joint.radius - math.length(delta);
|
||||
|
||||
// ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
|
||||
if (distance < 0)
|
||||
{
|
||||
var direction = -1 * math.normalize(delta);
|
||||
newNextTail = nextTail - direction * distance;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNextTail = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryResolveCapsuleCollisionInside(
|
||||
in BlittableJointMutable joint,
|
||||
in BlittableCollider collider,
|
||||
in BlittableTransform colliderTransform,
|
||||
in float3 nextTail, out float3 newNextTail)
|
||||
{
|
||||
var transformedOffset = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.offset);
|
||||
var transformedTail = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.tailOrNormal);
|
||||
var offsetToTail = transformedTail - transformedOffset;
|
||||
var lengthSqCapsule = math.lengthsq(offsetToTail);
|
||||
|
||||
var delta = nextTail - transformedOffset;
|
||||
var dot = math.dot(offsetToTail, delta);
|
||||
|
||||
if (dot < 0.0)
|
||||
{
|
||||
// ジョイントがカプセルの始点側にある場合
|
||||
// なにもしない
|
||||
}
|
||||
else if (dot > lengthSqCapsule)
|
||||
{
|
||||
// ジョイントがカプセルの終点側にある場合
|
||||
delta -= offsetToTail;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ジョイントがカプセルの始点と終点の間にある場合
|
||||
delta -= offsetToTail * (dot / lengthSqCapsule);
|
||||
}
|
||||
|
||||
// ジョイントとコライダーの距離。負の値は衝突していることを示す
|
||||
var distance = collider.radius - joint.radius - math.length(delta);
|
||||
|
||||
// ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
|
||||
if (distance < 0)
|
||||
{
|
||||
var direction = -1 * math.normalize(delta);
|
||||
newNextTail = nextTail - direction * distance;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNextTail = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 400f2bc818ed9ed44ac8b852cbd9dcc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -2,7 +2,10 @@
|
|||
"name": "SpringBoneJobs",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c"
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:2665a8d13d1b3f18800f46e256720795",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
@ -11,6 +14,12 @@
|
|||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.burst",
|
||||
"expression": "0.01",
|
||||
"define": "ENABLE_SPRINGBONE_BURST"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
using System;
|
||||
using UniGLTF.Runtime.Utils;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using Unity.Mathematics;
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
using Unity.Burst;
|
||||
#endif
|
||||
|
|
@ -26,10 +27,10 @@ namespace UniGLTF.SpringBoneJobs
|
|||
// 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;
|
||||
[ReadOnly] public NativeArray<float3> PrevTail;
|
||||
[ReadOnly] public NativeArray<float3> CurrentTail;
|
||||
// 処理後の tail 位置(ランダムアクセス)
|
||||
[NativeDisableParallelForRestriction] public NativeArray<Vector3> NextTail;
|
||||
[NativeDisableParallelForRestriction] public NativeArray<float3> NextTail;
|
||||
// Spring Level
|
||||
[ReadOnly] public NativeArray<BlittableSpring> Springs;
|
||||
// Model Level
|
||||
|
|
@ -67,105 +68,65 @@ namespace UniGLTF.SpringBoneJobs
|
|||
// 親があったら、親に依存するTransformを再計算
|
||||
if (parentTransform.HasValue)
|
||||
{
|
||||
headTransform.position =
|
||||
parentTransform.Value.localToWorldMatrix.MultiplyPoint3x4(headTransform.localPosition);
|
||||
headTransform.rotation = parentTransform.Value.rotation * headTransform.localRotation;
|
||||
headTransform = headTransform.UpdateParentMatrix(parentTransform.Value);
|
||||
}
|
||||
|
||||
var currentTail = centerTransform.HasValue
|
||||
? centerTransform.Value.localToWorldMatrix.MultiplyPoint3x4(CurrentTail[logicIndex])
|
||||
? MathHelper.MultiplyPoint3x4(centerTransform.Value.localToWorldMatrix, CurrentTail[logicIndex])
|
||||
: CurrentTail[logicIndex];
|
||||
var prevTail = centerTransform.HasValue
|
||||
? centerTransform.Value.localToWorldMatrix.MultiplyPoint3x4(PrevTail[logicIndex])
|
||||
? MathHelper.MultiplyPoint3x4(centerTransform.Value.localToWorldMatrix, PrevTail[logicIndex])
|
||||
: PrevTail[logicIndex];
|
||||
|
||||
var parentRotation = parentTransform?.rotation ?? Quaternion.identity;
|
||||
var parentRotation = parentTransform?.rotation ?? quaternion.identity;
|
||||
|
||||
// scaling 対応
|
||||
var scalingFactor = model.SupportsScalingAtRuntime ? TransformExtensions.AbsoluteMaxValue(headTransform.localToWorldMatrix.lossyScale) : 1.0f;
|
||||
var scalingFactor = model.SupportsScalingAtRuntime ? math.cmax(math.abs(headTransform.lossyScale)) : 1.0f;
|
||||
|
||||
// verlet積分で次の位置を計算
|
||||
var external = (joint.gravityDir * joint.gravityPower + model.ExternalForce) * DeltaTime;
|
||||
var nextTail = currentTail
|
||||
+ (currentTail - prevTail) * (1.0f - joint.dragForce) // 前フレームの移動を継続する(減衰もあるよ)
|
||||
+ parentRotation * logic.localRotation * logic.boneAxis *
|
||||
+ math.mul(math.mul(parentRotation, logic.localRotation), logic.boneAxis) *
|
||||
joint.stiffnessForce * DeltaTime * scalingFactor // 親の回転による子ボーンの移動目標
|
||||
+ external * scalingFactor; // 外力による移動量
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = headTransform.position + (nextTail - headTransform.position).normalized * logic.length;
|
||||
nextTail = headTransform.position + math.normalize(nextTail - headTransform.position) * logic.length;
|
||||
|
||||
nextTail = Anglelimit.Apply(logic, joint, parentRotation, head: headTransform.position, nextTail: nextTail);
|
||||
|
||||
// Collisionで移動
|
||||
for (var colliderIndex = colliderSpan.startIndex; colliderIndex < colliderSpan.startIndex + colliderSpan.count; ++colliderIndex)
|
||||
{
|
||||
var collider = Colliders[colliderIndex];
|
||||
var colliderTransform = Transforms[collider.transformIndex + transformIndexOffset];
|
||||
var colliderScale = colliderTransform.localToWorldMatrix.lossyScale;
|
||||
var maxColliderScale = Mathf.Max(Mathf.Max(Mathf.Abs(colliderScale.x), Mathf.Abs(colliderScale.y)), Mathf.Abs(colliderScale.z));
|
||||
var worldPosition = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset);
|
||||
var worldTail = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.tailOrNormal);
|
||||
var colliderScale = colliderTransform.lossyScale;
|
||||
var maxColliderScale = math.max(math.max(math.abs(colliderScale.x), math.abs(colliderScale.y)), math.abs(colliderScale.z));
|
||||
var worldPosition = MathHelper.MultiplyPoint3x4(colliderTransform.localToWorldMatrix, collider.offset);
|
||||
var worldTail = MathHelper.MultiplyPoint3x4(colliderTransform.localToWorldMatrix, collider.tailOrNormal);
|
||||
|
||||
switch (collider.colliderType)
|
||||
if (SpringBoneCollision.TryCollide(logic, joint,
|
||||
headTransform,
|
||||
collider, colliderTransform, maxColliderScale,
|
||||
colliderWorldTail: worldTail, colliderWorldPosition: worldPosition,
|
||||
nextTail: nextTail,
|
||||
out var newNextTail))
|
||||
{
|
||||
case BlittableColliderType.Sphere:
|
||||
ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail);
|
||||
break;
|
||||
|
||||
case BlittableColliderType.Capsule:
|
||||
ResolveCapsuleCollision(worldTail, worldPosition, headTransform, joint, collider, maxColliderScale, logic, ref nextTail);
|
||||
break;
|
||||
|
||||
case BlittableColliderType.Plane:
|
||||
ResolvePlaneCollision(joint, collider, colliderTransform, ref nextTail);
|
||||
break;
|
||||
|
||||
case BlittableColliderType.SphereInside:
|
||||
ResolveSphereCollisionInside(joint, collider, colliderTransform, ref nextTail);
|
||||
break;
|
||||
|
||||
case BlittableColliderType.CapsuleInside:
|
||||
ResolveCapsuleCollisionInside(joint, collider, colliderTransform, ref nextTail);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
// 衝突毎に nextTail を更新する。
|
||||
nextTail = Anglelimit.Apply(logic, joint, parentRotation, head: headTransform.position, nextTail: newNextTail);
|
||||
}
|
||||
}
|
||||
|
||||
NextTail[logicIndex] = centerTransform.HasValue
|
||||
? centerTransform.Value.worldToLocalMatrix.MultiplyPoint3x4(nextTail)
|
||||
? MathHelper.MultiplyPoint3x4(centerTransform.Value.worldToLocalMatrix, nextTail)
|
||||
: nextTail;
|
||||
|
||||
//回転を適用
|
||||
var rotation = parentRotation * logic.localRotation;
|
||||
headTransform.rotation = Quaternion.FromToRotation(rotation * logic.boneAxis,
|
||||
nextTail - headTransform.position) * rotation;
|
||||
|
||||
// Transformを更新
|
||||
if (parentTransform.HasValue)
|
||||
{
|
||||
var parentLocalToWorldMatrix = parentTransform.Value.localToWorldMatrix;
|
||||
headTransform.localRotation = Normalize(Quaternion.Inverse(parentTransform.Value.rotation) * headTransform.rotation);
|
||||
headTransform.localToWorldMatrix =
|
||||
parentLocalToWorldMatrix *
|
||||
Matrix4x4.TRS(
|
||||
headTransform.localPosition,
|
||||
headTransform.localRotation,
|
||||
headTransform.localScale
|
||||
);
|
||||
headTransform.worldToLocalMatrix = headTransform.localToWorldMatrix.inverse;
|
||||
}
|
||||
else
|
||||
{
|
||||
headTransform.localToWorldMatrix =
|
||||
Matrix4x4.TRS(
|
||||
headTransform.position,
|
||||
headTransform.rotation,
|
||||
headTransform.localScale
|
||||
);
|
||||
headTransform.worldToLocalMatrix = headTransform.localToWorldMatrix.inverse;
|
||||
headTransform.localRotation = headTransform.rotation;
|
||||
}
|
||||
var rotation = math.mul(parentRotation, logic.localRotation);
|
||||
headTransform = headTransform.UpdateRotation(
|
||||
math.mul(MathHelper.FromToRotation(math.mul(rotation, logic.boneAxis), nextTail - headTransform.position), rotation),
|
||||
parentTransform);
|
||||
|
||||
if (!model.StopSpringBoneWriteback)
|
||||
{
|
||||
|
|
@ -180,161 +141,5 @@ namespace UniGLTF.SpringBoneJobs
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BurstではMathfがエラーを吐くため、内部でMathfを呼ばないNormalizeを自前実装
|
||||
/// </summary>
|
||||
private static Quaternion Normalize(Quaternion q)
|
||||
{
|
||||
var num = (float)Math.Sqrt(Quaternion.Dot(q, q));
|
||||
return num < float.Epsilon ? Quaternion.identity : new Quaternion(q.x / num, q.y / num, q.z / num, q.w / num);
|
||||
}
|
||||
|
||||
private static void ResolveCapsuleCollision(
|
||||
Vector3 worldTail,
|
||||
Vector3 worldPosition,
|
||||
BlittableTransform headTransform,
|
||||
BlittableJointMutable joint,
|
||||
BlittableCollider collider,
|
||||
float maxColliderScale,
|
||||
BlittableJointImmutable logic,
|
||||
ref Vector3 nextTail)
|
||||
{
|
||||
var direction = worldTail - worldPosition;
|
||||
if (direction.sqrMagnitude == 0)
|
||||
{
|
||||
// head側半球の球判定
|
||||
ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail);
|
||||
return;
|
||||
}
|
||||
var P = direction.normalized;
|
||||
var Q = headTransform.position - worldPosition;
|
||||
var dot = Vector3.Dot(P, Q);
|
||||
if (dot <= 0)
|
||||
{
|
||||
// head側半球の球判定
|
||||
ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail);
|
||||
return;
|
||||
}
|
||||
if (dot >= direction.magnitude)
|
||||
{
|
||||
// tail側半球の球判定
|
||||
ResolveSphereCollision(joint, collider, worldTail, headTransform, maxColliderScale, logic, ref nextTail);
|
||||
return;
|
||||
}
|
||||
|
||||
// head-tail上の m_transform.position との最近点
|
||||
var p = worldPosition + P * dot;
|
||||
ResolveSphereCollision(joint, collider, p, headTransform, maxColliderScale, logic, ref nextTail);
|
||||
}
|
||||
|
||||
private static void ResolveSphereCollision(
|
||||
BlittableJointMutable joint,
|
||||
BlittableCollider collider,
|
||||
Vector3 worldPosition,
|
||||
BlittableTransform headTransform,
|
||||
float maxColliderScale,
|
||||
BlittableJointImmutable logic,
|
||||
ref Vector3 nextTail)
|
||||
{
|
||||
var r = joint.radius + collider.radius * maxColliderScale;
|
||||
if (Vector3.SqrMagnitude(nextTail - worldPosition) <= (r * r))
|
||||
{
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
var normal = (nextTail - worldPosition).normalized;
|
||||
var posFromCollider = worldPosition + normal * r;
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = headTransform.position + (posFromCollider - headTransform.position).normalized * logic.length;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResolveSphereCollisionInside(
|
||||
BlittableJointMutable joint,
|
||||
BlittableCollider collider,
|
||||
BlittableTransform colliderTransform,
|
||||
ref Vector3 nextTail)
|
||||
{
|
||||
var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset);
|
||||
var delta = nextTail - transformedOffset;
|
||||
|
||||
// ジョイントとコライダーの距離。負の値は衝突していることを示す
|
||||
var distance = collider.radius - joint.radius - delta.magnitude;
|
||||
|
||||
// ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
|
||||
if (distance < 0)
|
||||
{
|
||||
var direction = -delta.normalized;
|
||||
nextTail -= direction * distance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResolveCapsuleCollisionInside(
|
||||
BlittableJointMutable joint,
|
||||
BlittableCollider collider,
|
||||
BlittableTransform colliderTransform,
|
||||
ref Vector3 nextTail)
|
||||
{
|
||||
var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset);
|
||||
var transformedTail = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.tailOrNormal);
|
||||
var offsetToTail = transformedTail - transformedOffset;
|
||||
var lengthSqCapsule = offsetToTail.sqrMagnitude;
|
||||
|
||||
var delta = nextTail - transformedOffset;
|
||||
var dot = Vector3.Dot(offsetToTail, delta);
|
||||
|
||||
if (dot < 0.0)
|
||||
{
|
||||
// ジョイントがカプセルの始点側にある場合
|
||||
// なにもしない
|
||||
}
|
||||
else if (dot > lengthSqCapsule)
|
||||
{
|
||||
// ジョイントがカプセルの終点側にある場合
|
||||
delta -= offsetToTail;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ジョイントがカプセルの始点と終点の間にある場合
|
||||
delta -= offsetToTail * (dot / lengthSqCapsule);
|
||||
}
|
||||
|
||||
// ジョイントとコライダーの距離。負の値は衝突していることを示す
|
||||
var distance = collider.radius - joint.radius - delta.magnitude;
|
||||
|
||||
// ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
|
||||
if (distance < 0)
|
||||
{
|
||||
var direction = -delta.normalized;
|
||||
nextTail -= direction * distance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collision with SpringJoint and PlaneCollider.
|
||||
/// If collide update nextTail.
|
||||
/// </summary>
|
||||
/// <param name="joint">joint</param>
|
||||
/// <param name="collider">collier</param>
|
||||
/// <param name="colliderTransform">colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset);</param>
|
||||
/// <param name="nextTail">result of verlet integration</param>
|
||||
private static void ResolvePlaneCollision(
|
||||
BlittableJointMutable joint,
|
||||
BlittableCollider collider,
|
||||
BlittableTransform colliderTransform,
|
||||
ref Vector3 nextTail)
|
||||
{
|
||||
var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset);
|
||||
var transformedNormal = colliderTransform.localToWorldMatrix.MultiplyVector(collider.tailOrNormal).normalized;
|
||||
var delta = nextTail - transformedOffset;
|
||||
|
||||
// ジョイントとコライダーの距離。負の値は衝突していることを示す
|
||||
var distance = Vector3.Dot(delta, transformedNormal) - joint.radius;
|
||||
|
||||
if (distance < 0)
|
||||
{
|
||||
// ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す
|
||||
var direction = transformedNormal;
|
||||
nextTail -= direction * distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Assets/UniGLTF/Runtime/Utils/MathHelper.cs
Normal file
89
Assets/UniGLTF/Runtime/Utils/MathHelper.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UniGLTF.Runtime.Utils
|
||||
{
|
||||
public static class MathHelper
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float3 MultiplyPoint3x4(float4x4 matrix, float3 point)
|
||||
{
|
||||
return math.mul(matrix, new float4(point, 1)).xyz;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float3 MultiplyPoint(float4x4 matrix, float3 point)
|
||||
{
|
||||
var v = math.mul(matrix, new float4(point, 1.0f));
|
||||
return v.xyz / v.w;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float3 MultiplyVector(float4x4 matrix, float3 vector)
|
||||
{
|
||||
return math.mul(matrix, new float4(vector, 0)).xyz;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static quaternion FromToRotation(in float3 fromVector, in float3 toVector)
|
||||
{
|
||||
if (math.lengthsq(fromVector) == 0 || math.lengthsq(toVector) == 0)
|
||||
{
|
||||
return quaternion.identity;
|
||||
}
|
||||
|
||||
float3 from = math.normalize(fromVector);
|
||||
float3 to = math.normalize(toVector);
|
||||
|
||||
var dot = math.dot(from, to);
|
||||
switch(dot)
|
||||
{
|
||||
case >= 1.0f:
|
||||
return quaternion.identity;
|
||||
case <= -1.0f:
|
||||
{
|
||||
var axis = math.cross(from, new float3(1, 0, 0));
|
||||
if (math.lengthsq(axis) < 0.0001f)
|
||||
{
|
||||
axis = math.cross(from, new float3(0, 1, 0));
|
||||
}
|
||||
return quaternion.AxisAngle(math.normalize(axis), math.PI);
|
||||
}
|
||||
default:
|
||||
{
|
||||
var angle = math.acos(dot);
|
||||
var axis = math.cross(from, to);
|
||||
return quaternion.AxisAngle(math.normalize(axis), angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="UnityEngine.Mathf.Approximately"/> を Unity.Mathematics パッケージ向けに再実装した関数
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Approximately(float a, float b)
|
||||
{
|
||||
return math.abs(b - a) < math.max(1E-06f * math.max(math.abs(a), math.abs(b)), math.EPSILON * 8f);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathHelper.Approximately(float, float)"/>
|
||||
public static bool Approximately(float3 a, float3 b)
|
||||
{
|
||||
return Approximately(a.x, b.x) &&
|
||||
Approximately(a.y, b.y) &&
|
||||
Approximately(a.z, b.z);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathHelper.Approximately(float, float)"/>
|
||||
public static bool Approximately(quaternion a, quaternion b)
|
||||
{
|
||||
return Approximately(a.value.x, b.value.x) &&
|
||||
Approximately(a.value.y, b.value.y) &&
|
||||
Approximately(a.value.z, b.value.z) &&
|
||||
Approximately(a.value.w, b.value.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/UniGLTF/Runtime/Utils/MathHelper.cs.meta
Normal file
3
Assets/UniGLTF/Runtime/Utils/MathHelper.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50ff9ccb88bd4c208ab432127ec7b04d
|
||||
timeCreated: 1751330089
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"name": "UniGLTF.Utils",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"references": [
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"GUID:5f875fdc81c40184c8333b9d63c6ddd5",
|
||||
"GUID:27619889b8ba8c24980f49ee34dbb44a",
|
||||
"GUID:0acc523941302664db1f4e527237feb3",
|
||||
"GUID:1cd941934d098654fa21a13f28346412"
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
|
|
|
|||
49
Assets/UniGLTF/Tests/UniGLTF/MathTests.cs
Normal file
49
Assets/UniGLTF/Tests/UniGLTF/MathTests.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using NUnit.Framework;
|
||||
using UniGLTF.Runtime.Utils;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
namespace UniGLTF
|
||||
{
|
||||
public class MathTests
|
||||
{
|
||||
private readonly float4x4 _matrix = new float4x4(
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
13, 14, 15, 16);
|
||||
private readonly float3 _vector1 = new float3(1, 2, 3);
|
||||
private readonly float3 _vector2 = new float3(4, 5, 6);
|
||||
|
||||
[Test]
|
||||
public void MultiplyPoint3x4Test()
|
||||
{
|
||||
var result = MathHelper.MultiplyPoint3x4(_matrix, _vector1);
|
||||
var expected = ((Matrix4x4)_matrix).MultiplyPoint3x4(_vector1);
|
||||
Assert.That(MathHelper.Approximately(result, expected), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultiplyPointTest()
|
||||
{
|
||||
var result = MathHelper.MultiplyPoint(_matrix, _vector1);
|
||||
var expected = ((Matrix4x4)_matrix).MultiplyPoint(_vector1);
|
||||
Assert.That(MathHelper.Approximately(result, expected), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultiplyVectorTest()
|
||||
{
|
||||
var result = MathHelper.MultiplyVector(_matrix, _vector1);
|
||||
var expected = ((Matrix4x4)_matrix).MultiplyVector(_vector1);
|
||||
Assert.That(MathHelper.Approximately(result, expected), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FromToRotationTest()
|
||||
{
|
||||
var result = MathHelper.FromToRotation(_vector1, _vector2);
|
||||
var expected = Quaternion.FromToRotation(_vector1, _vector2);
|
||||
Assert.That(MathHelper.Approximately(result, expected), Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/UniGLTF/Tests/UniGLTF/MathTests.cs.meta
Normal file
3
Assets/UniGLTF/Tests/UniGLTF/MathTests.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4b920c4a4ea1401085ba8923e4ccaca2
|
||||
timeCreated: 1751329860
|
||||
|
|
@ -40,13 +40,10 @@ namespace VRM.SpringBoneJobs
|
|||
var c = new FastSpringBoneCollider
|
||||
{
|
||||
Transform = group.transform,
|
||||
Collider = new BlittableCollider
|
||||
{
|
||||
offset = collider.Offset,
|
||||
radius = collider.Radius,
|
||||
tailOrNormal = default,
|
||||
colliderType = BlittableColliderType.Sphere
|
||||
}
|
||||
Collider = new BlittableCollider(
|
||||
offset: collider.Offset,
|
||||
radius: collider.Radius,
|
||||
colliderType: BlittableColliderType.Sphere)
|
||||
};
|
||||
colliders.Add(c);
|
||||
}
|
||||
|
|
@ -85,14 +82,12 @@ namespace VRM.SpringBoneJobs
|
|||
joints.Add(new FastSpringBoneJoint
|
||||
{
|
||||
Transform = joint,
|
||||
Joint = new BlittableJointMutable
|
||||
{
|
||||
radius = spring.m_hitRadius,
|
||||
dragForce = spring.m_dragForce,
|
||||
gravityDir = spring.m_gravityDir,
|
||||
gravityPower = spring.m_gravityPower,
|
||||
stiffnessForce = spring.m_stiffnessForce
|
||||
},
|
||||
Joint = new BlittableJointMutable(
|
||||
radius: spring.m_hitRadius,
|
||||
dragForce: spring.m_dragForce,
|
||||
gravityDir: spring.m_gravityDir,
|
||||
gravityPower: spring.m_gravityPower,
|
||||
stiffnessForce: spring.m_stiffnessForce),
|
||||
DefaultLocalRotation = initMap[joint.transform].LocalRotation,
|
||||
});
|
||||
foreach (Transform child in joint)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
"GUID:a9bc101fb0471f94a8f99fd242fdd934",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:60c8346e00a8ddd4cafc5a02eceeec57",
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46"
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
|||
|
|
@ -8,11 +8,17 @@ namespace UniVRM10
|
|||
class VRM10SpringBoneJointEditor : Editor
|
||||
{
|
||||
private VRM10SpringBoneJoint m_target;
|
||||
|
||||
private SerializedProperty m_script;
|
||||
private SerializedProperty m_stiffnessForceProp;
|
||||
private SerializedProperty m_gravityPowerProp;
|
||||
private SerializedProperty m_gravityDirProp;
|
||||
private SerializedProperty m_dragForceProp;
|
||||
private SerializedProperty m_jointRadiusProp;
|
||||
private SerializedProperty m_angleLimitType;
|
||||
private SerializedProperty m_angleLimitRotation;
|
||||
private SerializedProperty m_angleLimitAngle1;
|
||||
private SerializedProperty m_angleLimitAngle2;
|
||||
|
||||
private Vrm10Instance m_root;
|
||||
|
||||
|
|
@ -24,11 +30,16 @@ namespace UniVRM10
|
|||
}
|
||||
m_target = (VRM10SpringBoneJoint)target;
|
||||
|
||||
m_script = serializedObject.FindProperty("m_Script");
|
||||
m_stiffnessForceProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_stiffnessForce));
|
||||
m_gravityPowerProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_gravityPower));
|
||||
m_gravityDirProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_gravityDir));
|
||||
m_dragForceProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_dragForce));
|
||||
m_jointRadiusProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_jointRadius));
|
||||
m_angleLimitType = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_anglelimitType));
|
||||
m_angleLimitRotation = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_angleLimitRotation));
|
||||
m_angleLimitAngle1 = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_angleLimitAngle1));
|
||||
m_angleLimitAngle2 = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_angleLimitAngle2));
|
||||
|
||||
m_root = m_target.GetComponentInParent<Vrm10Instance>();
|
||||
}
|
||||
|
|
@ -36,9 +47,15 @@ namespace UniVRM10
|
|||
static bool m_showJoints;
|
||||
static bool m_showColliders;
|
||||
static bool m_showJointSettings;
|
||||
static bool m_showAnglelimitSettings;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_script);
|
||||
}
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
///
|
||||
|
|
@ -67,6 +84,36 @@ namespace UniVRM10
|
|||
Vrm10EditorUtility.LimitBreakSlider(m_jointRadiusProp, 0.0f, 0.5f, 0.0f, Mathf.Infinity);
|
||||
}
|
||||
|
||||
//
|
||||
// angle limit
|
||||
//
|
||||
m_showAnglelimitSettings = EditorGUILayout.Foldout(m_showAnglelimitSettings, "AngleLimit Settings(dev)");
|
||||
if (m_showAnglelimitSettings)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_angleLimitType);
|
||||
switch ((UniGLTF.SpringBoneJobs.AnglelimitTypes)m_angleLimitType.enumValueIndex)
|
||||
{
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.None:
|
||||
break;
|
||||
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone:
|
||||
EditorGUILayout.PropertyField(m_angleLimitRotation);
|
||||
EditorGUILayout.PropertyField(m_angleLimitAngle1);
|
||||
break;
|
||||
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge:
|
||||
EditorGUILayout.PropertyField(m_angleLimitRotation);
|
||||
EditorGUILayout.PropertyField(m_angleLimitAngle1);
|
||||
break;
|
||||
|
||||
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical:
|
||||
EditorGUILayout.PropertyField(m_angleLimitRotation);
|
||||
EditorGUILayout.PropertyField(m_angleLimitAngle1);
|
||||
EditorGUILayout.PropertyField(m_angleLimitAngle2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties())
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
|
|
|
|||
|
|
@ -71,11 +71,6 @@ namespace UniVRM10
|
|||
m_materialValueBindingMerger.AccumulateValue(clip, value);
|
||||
}
|
||||
|
||||
public void RestoreMaterialInitialValues()
|
||||
{
|
||||
m_materialValueBindingMerger.RestoreMaterialInitialValues();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
m_materialValueBindingMerger.Dispose();
|
||||
|
|
|
|||
|
|
@ -138,17 +138,6 @@ namespace UniVRM10
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// m_materialMap に記録した値に Material を復旧する
|
||||
/// </summary>
|
||||
public void RestoreMaterialInitialValues()
|
||||
{
|
||||
foreach (var kv in m_materialMap)
|
||||
{
|
||||
kv.Value.Clear();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Accumulate
|
||||
|
|
|
|||
|
|
@ -26,14 +26,38 @@ namespace UniVRM10
|
|||
[SerializeField]
|
||||
public float m_jointRadius = 0.02f;
|
||||
|
||||
public BlittableJointMutable Blittable => new BlittableJointMutable
|
||||
[SerializeField]
|
||||
public UniGLTF.SpringBoneJobs.AnglelimitTypes m_anglelimitType;
|
||||
|
||||
[SerializeField]
|
||||
public Quaternion m_angleLimitRotation = Quaternion.identity;
|
||||
|
||||
[SerializeField, Range(0, Mathf.PI)]
|
||||
public float m_angleLimitAngle1 = Mathf.PI;
|
||||
|
||||
[SerializeField, Range(0, Mathf.PI)]
|
||||
public float m_angleLimitAngle2 = Mathf.PI;
|
||||
|
||||
public BlittableJointMutable Blittable => new BlittableJointMutable(
|
||||
stiffnessForce: m_stiffnessForce,
|
||||
gravityPower: m_gravityPower,
|
||||
gravityDir: m_gravityDir,
|
||||
dragForce: m_dragForce,
|
||||
radius: m_jointRadius,
|
||||
// v0.129.4
|
||||
angleLimitType: (float)m_anglelimitType,
|
||||
angleLimit1: m_angleLimitAngle1,
|
||||
angleLimit2: m_angleLimitAngle2,
|
||||
angleLimitOffset: m_angleLimitRotation
|
||||
);
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
stiffnessForce = m_stiffnessForce,
|
||||
dragForce = m_dragForce,
|
||||
gravityDir = m_gravityDir,
|
||||
gravityPower = m_gravityPower,
|
||||
radius = m_jointRadius,
|
||||
};
|
||||
if (m_angleLimitRotation == default)
|
||||
{
|
||||
m_angleLimitRotation = Quaternion.identity;
|
||||
}
|
||||
}
|
||||
|
||||
void AddJointRecursive(Transform t, VRM10SpringBoneJoint src)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d243bd3237701034a82757f58a0ec3da
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -49,26 +49,17 @@ namespace UniVRM10
|
|||
.Select(collider => new FastSpringBoneCollider
|
||||
{
|
||||
Transform = collider.transform,
|
||||
Collider = new BlittableCollider
|
||||
{
|
||||
offset = collider.Offset,
|
||||
radius = collider.Radius,
|
||||
tailOrNormal = collider.TailOrNormal,
|
||||
colliderType = TranslateColliderType(collider.ColliderType)
|
||||
}
|
||||
Collider = new BlittableCollider(
|
||||
offset: collider.Offset,
|
||||
radius: collider.Radius,
|
||||
tailOrNormal: collider.TailOrNormal,
|
||||
colliderType: TranslateColliderType(collider.ColliderType))
|
||||
}).ToArray(),
|
||||
joints = spring.Joints
|
||||
.Select(joint => new FastSpringBoneJoint
|
||||
{
|
||||
Transform = joint.transform,
|
||||
Joint = new BlittableJointMutable
|
||||
{
|
||||
radius = joint.m_jointRadius,
|
||||
dragForce = joint.m_dragForce,
|
||||
gravityDir = joint.m_gravityDir,
|
||||
gravityPower = joint.m_gravityPower,
|
||||
stiffnessForce = joint.m_stiffnessForce
|
||||
},
|
||||
Joint = joint.Blittable,
|
||||
DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation,
|
||||
}).ToArray(),
|
||||
}).ToArray();
|
||||
|
|
@ -43,7 +43,7 @@ namespace UniVRM10
|
|||
/// <summary>
|
||||
/// 毎フレーム Vrm10Runtime.Process から呼ばれる。
|
||||
/// </summary>
|
||||
public void Process();
|
||||
public void Process(float deltaTime);
|
||||
|
||||
/// <summary>
|
||||
/// from Vrm10Instance.OnDrawGizmosSelected
|
||||
|
|
@ -112,7 +112,7 @@ namespace UniVRM10
|
|||
m_fastSpringBoneService.BufferCombiner.InitializeJointsLocalRotation(m_fastSpringBoneBuffer);
|
||||
}
|
||||
|
||||
public void Process()
|
||||
public void Process(float deltaTime)
|
||||
{
|
||||
// FastSpringBoneService が実行するので何もしない
|
||||
}
|
||||
|
|
@ -118,9 +118,9 @@ namespace UniVRM10
|
|||
m_bufferCombiner.InitializeJointsLocalRotation(m_fastSpringBoneBuffer);
|
||||
}
|
||||
|
||||
public void Process()
|
||||
public void Process(float deltaTime)
|
||||
{
|
||||
m_fastSpringBoneScheduler.Schedule(Time.deltaTime).Complete();
|
||||
m_fastSpringBoneScheduler.Schedule(deltaTime).Complete();
|
||||
}
|
||||
|
||||
public void DrawGizmos()
|
||||
|
|
@ -20,7 +20,7 @@ namespace UniVRM10
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Process()
|
||||
public void Process(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ namespace UniVRM10
|
|||
Expression.Process(eyeDirection);
|
||||
|
||||
// 6. SpringBone
|
||||
SpringBone.Process();
|
||||
SpringBone.Process(Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,14 +51,11 @@ namespace UniVRM10
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_merger?.RestoreMaterialInitialValues();
|
||||
_merger?.Dispose();
|
||||
_merger = null;
|
||||
|
||||
_eyeDirectionApplicable?.Restore();
|
||||
_eyeDirectionApplicable = null;
|
||||
|
||||
_merger?.Dispose();
|
||||
_merger = null;
|
||||
}
|
||||
|
||||
internal void Process(LookAtEyeDirection inputEyeDirection)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using UniGLTF.SpringBoneJobs;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10.FastSpringBones
|
||||
|
|
@ -95,12 +96,17 @@ namespace UniVRM10.FastSpringBones
|
|||
}
|
||||
|
||||
public void ManualUpdate(float deltaTime)
|
||||
{
|
||||
ManualUpdate(deltaTime, null).Complete();
|
||||
}
|
||||
|
||||
public JobHandle ManualUpdate(in float deltaTime, in JobHandle? dependency = null)
|
||||
{
|
||||
if (UpdateType != UpdateTypes.Manual)
|
||||
{
|
||||
throw new global::System.ArgumentException("require UpdateTypes.Manual");
|
||||
}
|
||||
_fastSpringBoneScheduler.Schedule(deltaTime).Complete();
|
||||
return _fastSpringBoneScheduler.Schedule(deltaTime, dependency);
|
||||
}
|
||||
|
||||
public void OnDrawGizmosSelected()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"GUID:b7aa47b240b57de44a4b2021c143c9bf",
|
||||
"GUID:f2ca1407928ebdc4bbe7765cc278be44",
|
||||
"GUID:2665a8d13d1b3f18800f46e256720795",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46",
|
||||
"GUID:f06555f75b070af458a003d92f9efb00"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"GUID:e47c917724578cc43b5506c17a27e9a0",
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:5f875fdc81c40184c8333b9d63c6ddd5"
|
||||
"GUID:5f875fdc81c40184c8333b9d63c6ddd5",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
|||
|
|
@ -135,12 +135,7 @@ namespace UniVRM10.ClothWarp
|
|||
// }
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
Process(Time.deltaTime);
|
||||
}
|
||||
|
||||
void Process(float deltaTime)
|
||||
public void Process(float deltaTime)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -193,14 +193,12 @@ namespace UniVRM10.ClothWarp.Jobs
|
|||
var colliderTransformIndex = GetOrAddColliderTransform(collider.transform);
|
||||
|
||||
colliderRef.Add(colliderInfo.Count);
|
||||
colliderInfo.Add(new BlittableCollider
|
||||
{
|
||||
offset = collider.Offset,
|
||||
radius = collider.Radius,
|
||||
tailOrNormal = collider.TailOrNormal,
|
||||
colliderType = TranslateColliderType(collider.ColliderType),
|
||||
transformIndex = colliderTransformIndex,
|
||||
});
|
||||
colliderInfo.Add(new BlittableCollider(
|
||||
offset: collider.Offset,
|
||||
radius: collider.Radius,
|
||||
tailOrNormal: collider.TailOrNormal,
|
||||
colliderType: TranslateColliderType(collider.ColliderType),
|
||||
colliderTransformIndex: colliderTransformIndex));
|
||||
_colliders.Add(collider);
|
||||
}
|
||||
|
||||
|
|
@ -410,11 +408,6 @@ namespace UniVRM10.ClothWarp.Jobs
|
|||
}
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
Process(Time.deltaTime);
|
||||
}
|
||||
|
||||
public void Process(float deltaTime)
|
||||
{
|
||||
var frame = new FrameInfo(deltaTime, Vector3.zero);
|
||||
|
|
|
|||
|
|
@ -39,14 +39,12 @@ namespace UniVRM10.ClothWarp.Jobs
|
|||
|
||||
public BlittableJointMutable ToBlittableJointMutable()
|
||||
{
|
||||
return new BlittableJointMutable
|
||||
{
|
||||
stiffnessForce = Stiffness,
|
||||
gravityPower = 1.0f,
|
||||
gravityDir = Gravity,
|
||||
dragForce = Deceleration,
|
||||
radius = Radius,
|
||||
};
|
||||
return new BlittableJointMutable(
|
||||
stiffnessForce: Stiffness,
|
||||
gravityPower: 1.0f,
|
||||
gravityDir: Gravity,
|
||||
dragForce: Deceleration,
|
||||
radius: Radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -185,15 +185,14 @@ namespace UniVRM10.VRM10Viewer
|
|||
m_controller.ShowBoxMan(m_showBoxMan.value);
|
||||
if (m_controller.TryUpdate(
|
||||
m_motionMode.value == 0,
|
||||
new BlittableModelLevel
|
||||
{
|
||||
ExternalForce = new Vector3(
|
||||
new BlittableModelLevel(
|
||||
externalForce: new Vector3(
|
||||
m_springboneExternalX.value,
|
||||
m_springboneExternalY.value,
|
||||
m_springboneExternalZ.value),
|
||||
StopSpringBoneWriteback = m_useSpringbonePause.value,
|
||||
SupportsScalingAtRuntime = m_useSpringboneScaling.value,
|
||||
},
|
||||
stopSpringBoneWriteback: m_useSpringbonePause.value,
|
||||
supportsScalingAtRuntime: m_useSpringboneScaling.value
|
||||
),
|
||||
out var loaded
|
||||
))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
"GUID:e47c917724578cc43b5506c17a27e9a0",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46",
|
||||
"GUID:f06555f75b070af458a003d92f9efb00"
|
||||
"GUID:f06555f75b070af458a003d92f9efb00",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
|||
|
|
@ -226,12 +226,11 @@ namespace UniVRM10.VRM10Viewer
|
|||
m_controller.ShowBoxMan(m_showBoxMan.isOn);
|
||||
if (m_controller.TryUpdate(
|
||||
m_ui.IsTPose,
|
||||
new BlittableModelLevel
|
||||
{
|
||||
ExternalForce = new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value),
|
||||
StopSpringBoneWriteback = m_springbonePause.isOn,
|
||||
SupportsScalingAtRuntime = m_springboneScaling.isOn,
|
||||
},
|
||||
new BlittableModelLevel(
|
||||
externalForce: new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value),
|
||||
stopSpringBoneWriteback: m_springbonePause.isOn,
|
||||
supportsScalingAtRuntime: m_springboneScaling.isOn
|
||||
),
|
||||
out var loaded
|
||||
))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:b7aa47b240b57de44a4b2021c143c9bf",
|
||||
"GUID:05dd262a0c0a2f841b8252c8c3815582",
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46"
|
||||
"GUID:3e5d614bc16b50d41bd94c8d7444ca46",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
|||
|
|
@ -343,15 +343,15 @@ 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(
|
||||
(
|
||||
externalForce: new Vector3(
|
||||
m_springExternalX.value,
|
||||
m_springExternalY.value,
|
||||
m_springExternalZ.value
|
||||
),
|
||||
StopSpringBoneWriteback = m_springBonePause.isOn,
|
||||
SupportsScalingAtRuntime = m_springBoneScaling.isOn,
|
||||
});
|
||||
stopSpringBoneWriteback: m_springBonePause.isOn,
|
||||
supportsScalingAtRuntime: m_springBoneScaling.isOn
|
||||
));
|
||||
m_loaded.Update();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user