Modify: 매지카클로스2 스크립트 최신화
This commit is contained in:
parent
60f8e6dc25
commit
3f3d799879
@ -1,6 +1,6 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!114 &-4012764583101539669
|
--- !u!114 &-3443301767334639713
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
|||||||
@ -9,6 +9,13 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
public Vector3 eulers = new Vector3(0, 90, 0);
|
public Vector3 eulers = new Vector3(0, 90, 0);
|
||||||
public Space space = Space.World;
|
public Space space = Space.World;
|
||||||
|
public enum UpdateMode
|
||||||
|
{
|
||||||
|
Update,
|
||||||
|
FixedUpdate,
|
||||||
|
}
|
||||||
|
[SerializeField]
|
||||||
|
private UpdateMode updateMode = UpdateMode.Update;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Range(0.1f, 5.0f)]
|
[Range(0.1f, 5.0f)]
|
||||||
@ -19,11 +26,23 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
private float time = 0;
|
private float time = 0;
|
||||||
|
|
||||||
|
private void FixedUpdate()
|
||||||
|
{
|
||||||
|
if (updateMode == UpdateMode.FixedUpdate)
|
||||||
|
UpdatePosition(Time.fixedDeltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
|
{
|
||||||
|
if (updateMode == UpdateMode.Update)
|
||||||
|
UpdatePosition(Time.deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatePosition(float dtime)
|
||||||
{
|
{
|
||||||
if (useSin)
|
if (useSin)
|
||||||
{
|
{
|
||||||
time += Time.deltaTime;
|
time += dtime;
|
||||||
float ang = (time % interval) / interval * Mathf.PI * 2.0f;
|
float ang = (time % interval) / interval * Mathf.PI * 2.0f;
|
||||||
var t = Mathf.Sin(ang);
|
var t = Mathf.Sin(ang);
|
||||||
if (space == Space.World)
|
if (space == Space.World)
|
||||||
@ -33,7 +52,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
transform.Rotate(eulers * Time.deltaTime, space);
|
transform.Rotate(eulers * dtime, space);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -124,10 +124,7 @@ namespace MagicaCloth2
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// カメラターゲットポジション
|
// カメラターゲットポジション
|
||||||
if (cameraTarget)
|
cameraTargetPos = cameraTarget ? cameraTarget.position : transform.position;
|
||||||
{
|
|
||||||
cameraTargetPos = cameraTarget.position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 補間
|
// 補間
|
||||||
cameraDist = Mathf.SmoothDamp(cameraDist, setCameraDist, ref cameraDistVelocity, cameraDistHokanTime);
|
cameraDist = Mathf.SmoothDamp(cameraDist, setCameraDist, ref cameraDistVelocity, cameraDistHokanTime);
|
||||||
@ -147,13 +144,13 @@ namespace MagicaCloth2
|
|||||||
Vector3 pos = q * v;
|
Vector3 pos = q * v;
|
||||||
|
|
||||||
// ターゲットポジション
|
// ターゲットポジション
|
||||||
Vector3 tarpos = cameraTargetPos + cameraTargetOffset;
|
Vector3 tarpos = cameraTargetPos + transform.TransformVector(cameraTargetOffset);
|
||||||
Vector3 fixpos = tarpos + pos;
|
Vector3 fixpos = tarpos + pos;
|
||||||
cameraTransform.localPosition = fixpos;
|
cameraTransform.position = fixpos;
|
||||||
|
|
||||||
// 回転確定
|
// 回転確定
|
||||||
Vector3 relativePos = tarpos - cameraTransform.position;
|
Vector3 relativePos = tarpos - cameraTransform.position;
|
||||||
Quaternion rot = Quaternion.LookRotation(relativePos);
|
Quaternion rot = Quaternion.LookRotation(relativePos, transform.up);
|
||||||
cameraTransform.rotation = rot;
|
cameraTransform.rotation = rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,8 +179,8 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
else if (moveMode == MoveMode.Free)
|
else if (moveMode == MoveMode.Free)
|
||||||
{
|
{
|
||||||
Vector3 offset = cameraTransform.up * -speed.y * moveSpeed;
|
Vector3 offset = transform.InverseTransformDirection(cameraTransform.up) * -speed.y * moveSpeed;
|
||||||
offset += cameraTransform.right * -speed.x * moveSpeed;
|
offset += transform.InverseTransformDirection(cameraTransform.right) * -speed.x * moveSpeed;
|
||||||
|
|
||||||
cameraTargetOffset += offset;
|
cameraTargetOffset += offset;
|
||||||
}
|
}
|
||||||
@ -207,7 +204,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="screenVelocity"></param>
|
/// <param name="screenVelocity"></param>
|
||||||
private void OnTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity)
|
private void OnTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity)
|
||||||
{
|
{
|
||||||
screenVelocity *= Time.deltaTime * 60.0f;
|
screenVelocity *= SpeedAdjustment();
|
||||||
|
|
||||||
if (fid == 2)
|
if (fid == 2)
|
||||||
{
|
{
|
||||||
@ -225,6 +222,8 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
private void OnDoubleTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity)
|
private void OnDoubleTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity)
|
||||||
{
|
{
|
||||||
|
screenVelocity *= SpeedAdjustment();
|
||||||
|
|
||||||
if (SimpleInputManager.Instance.GetTouchCount() >= 3)
|
if (SimpleInputManager.Instance.GetTouchCount() >= 3)
|
||||||
updateOffset(screenVelocity);
|
updateOffset(screenVelocity);
|
||||||
}
|
}
|
||||||
@ -236,9 +235,15 @@ namespace MagicaCloth2
|
|||||||
/// <param name="speedcm"></param>
|
/// <param name="speedcm"></param>
|
||||||
private void OnTouchPinch(float speedscr, float speedcm)
|
private void OnTouchPinch(float speedscr, float speedcm)
|
||||||
{
|
{
|
||||||
//if (Mathf.Abs(speedcm) > 1.0f)
|
speedcm *= SpeedAdjustment();
|
||||||
|
|
||||||
if (SimpleInputManager.Instance.GetTouchCount() < 3)
|
if (SimpleInputManager.Instance.GetTouchCount() < 3)
|
||||||
updateZoom(speedcm);
|
updateZoom(speedcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float SpeedAdjustment()
|
||||||
|
{
|
||||||
|
return Time.deltaTime * 60.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -233,6 +233,7 @@ namespace MagicaCloth2
|
|||||||
sdata.colliderCollisionConstraint.mode = ColliderCollisionConstraint.Mode.Point;
|
sdata.colliderCollisionConstraint.mode = ColliderCollisionConstraint.Mode.Point;
|
||||||
|
|
||||||
// setup collider
|
// setup collider
|
||||||
|
// UpperLeg L
|
||||||
var lobj = new GameObject("CapsuleCollider_L");
|
var lobj = new GameObject("CapsuleCollider_L");
|
||||||
lobj.transform.SetParent(gameObjectContainer.GetGameObject("Character1_LeftUpLeg").transform);
|
lobj.transform.SetParent(gameObjectContainer.GetGameObject("Character1_LeftUpLeg").transform);
|
||||||
lobj.transform.localPosition = new Vector3(0.0049f, 0.0f, -0.0832f);
|
lobj.transform.localPosition = new Vector3(0.0049f, 0.0f, -0.0832f);
|
||||||
@ -240,17 +241,10 @@ namespace MagicaCloth2
|
|||||||
var colliderL = lobj.AddComponent<MagicaCapsuleCollider>();
|
var colliderL = lobj.AddComponent<MagicaCapsuleCollider>();
|
||||||
colliderL.direction = MagicaCapsuleCollider.Direction.Z;
|
colliderL.direction = MagicaCapsuleCollider.Direction.Z;
|
||||||
colliderL.SetSize(0.082f, 0.094f, 0.3f);
|
colliderL.SetSize(0.082f, 0.094f, 0.3f);
|
||||||
|
// UpperLeg R (Symmetry)
|
||||||
var robj = new GameObject("CapsuleCollider_R");
|
colliderL.symmetryMode = ColliderSymmetryMode.AutomaticHumanBody;
|
||||||
robj.transform.SetParent(gameObjectContainer.GetGameObject("Character1_RightUpLeg").transform);
|
colliderL.UpdateParameters(); // Required when changing parameters.
|
||||||
robj.transform.localPosition = new Vector3(-0.0049f, 0.0f, -0.0832f);
|
|
||||||
robj.transform.localEulerAngles = new Vector3(0.23f, -16.376f, -0.028f);
|
|
||||||
var colliderR = robj.AddComponent<MagicaCapsuleCollider>();
|
|
||||||
colliderR.direction = MagicaCapsuleCollider.Direction.Z;
|
|
||||||
colliderR.SetSize(0.082f, 0.094f, 0.3f);
|
|
||||||
|
|
||||||
sdata.colliderCollisionConstraint.colliderList.Add(colliderL);
|
sdata.colliderCollisionConstraint.colliderList.Add(colliderL);
|
||||||
sdata.colliderCollisionConstraint.colliderList.Add(colliderR);
|
|
||||||
|
|
||||||
// start build
|
// start build
|
||||||
cloth.BuildAndRun();
|
cloth.BuildAndRun();
|
||||||
|
|||||||
@ -105,6 +105,8 @@ namespace MagicaCloth2
|
|||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
protected override void InitSingleton()
|
protected override void InitSingleton()
|
||||||
{
|
{
|
||||||
|
SimpleInput.Init();
|
||||||
|
|
||||||
// スクリーン情報
|
// スクリーン情報
|
||||||
CalcScreenDpi();
|
CalcScreenDpi();
|
||||||
|
|
||||||
@ -188,7 +190,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public int GetTouchCount()
|
public int GetTouchCount()
|
||||||
{
|
{
|
||||||
return Input.touchCount;
|
return SimpleInput.touchCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsUI()
|
public bool IsUI()
|
||||||
@ -199,7 +201,7 @@ namespace MagicaCloth2
|
|||||||
if (mobilePlatform)
|
if (mobilePlatform)
|
||||||
{
|
{
|
||||||
// モバイル用タッチ入力
|
// モバイル用タッチ入力
|
||||||
return EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId);
|
return EventSystem.current.IsPointerOverGameObject(SimpleInput.GetTouch(0).fingerId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -214,7 +216,7 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateMobile()
|
private void UpdateMobile()
|
||||||
{
|
{
|
||||||
int count = Input.touchCount;
|
int count = SimpleInput.touchCount;
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
@ -223,7 +225,7 @@ namespace MagicaCloth2
|
|||||||
// バックボタン
|
// バックボタン
|
||||||
if (Application.platform == RuntimePlatform.Android)
|
if (Application.platform == RuntimePlatform.Android)
|
||||||
{
|
{
|
||||||
if (Input.GetKey(KeyCode.Escape) && lastTime + 0.2f < Time.time)
|
if (SimpleInput.GetKey(KeyCode.Escape) && lastTime + 0.2f < Time.time)
|
||||||
{
|
{
|
||||||
lastTime = Time.time;
|
lastTime = Time.time;
|
||||||
if (OnBackButton != null)
|
if (OnBackButton != null)
|
||||||
@ -239,7 +241,7 @@ namespace MagicaCloth2
|
|||||||
// メイン
|
// メイン
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Touch touch = Input.GetTouch(i);
|
Touch touch = SimpleInput.GetTouch(i);
|
||||||
int fid = touch.fingerId;
|
int fid = touch.fingerId;
|
||||||
|
|
||||||
// フィンガーIDが0と1以外は無視する
|
// フィンガーIDが0と1以外は無視する
|
||||||
@ -289,7 +291,7 @@ namespace MagicaCloth2
|
|||||||
int setcnt = 0;
|
int setcnt = 0;
|
||||||
for (int j = 0; j < count; j++)
|
for (int j = 0; j < count; j++)
|
||||||
{
|
{
|
||||||
Touch t = Input.GetTouch(j);
|
Touch t = SimpleInput.GetTouch(j);
|
||||||
if (mainFingerId == t.fingerId)
|
if (mainFingerId == t.fingerId)
|
||||||
{
|
{
|
||||||
t1pos = t.position;
|
t1pos = t.position;
|
||||||
@ -497,7 +499,7 @@ namespace MagicaCloth2
|
|||||||
private void UpdateMouse()
|
private void UpdateMouse()
|
||||||
{
|
{
|
||||||
// BackSpace を Android 端末のバックボタンに割り当てる
|
// BackSpace を Android 端末のバックボタンに割り当てる
|
||||||
if (Input.GetKeyDown(KeyCode.Backspace))
|
if (SimpleInput.GetKeyDown(KeyCode.Backspace))
|
||||||
{
|
{
|
||||||
if (OnBackButton != null)
|
if (OnBackButton != null)
|
||||||
OnBackButton();
|
OnBackButton();
|
||||||
@ -507,7 +509,7 @@ namespace MagicaCloth2
|
|||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
// マウスボタンダウン
|
// マウスボタンダウン
|
||||||
if (Input.GetMouseButtonDown(i))
|
if (SimpleInput.GetMouseButtonDown(i))
|
||||||
{
|
{
|
||||||
if (IsUI())
|
if (IsUI())
|
||||||
continue;
|
continue;
|
||||||
@ -519,46 +521,46 @@ namespace MagicaCloth2
|
|||||||
mouseDown[i] = true;
|
mouseDown[i] = true;
|
||||||
|
|
||||||
// 入力位置を記録
|
// 入力位置を記録
|
||||||
downPos[i] = Input.mousePosition;
|
downPos[i] = SimpleInput.mousePosition;
|
||||||
mouseOldMovePos[i] = Input.mousePosition;
|
mouseOldMovePos[i] = SimpleInput.mousePosition;
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
flickDownPos[i] = Input.mousePosition;
|
flickDownPos[i] = SimpleInput.mousePosition;
|
||||||
|
|
||||||
// タッチダウンイベント発行
|
// タッチダウンイベント発行
|
||||||
if (OnTouchDown != null)
|
if (OnTouchDown != null)
|
||||||
OnTouchDown(i, Input.mousePosition);
|
OnTouchDown(i, SimpleInput.mousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// マウスボタンアップ
|
// マウスボタンアップ
|
||||||
if (Input.GetMouseButtonUp(i) && mouseDown[i])
|
if (SimpleInput.GetMouseButtonUp(i) && mouseDown[i])
|
||||||
{
|
{
|
||||||
mouseDown[i] = false;
|
mouseDown[i] = false;
|
||||||
|
|
||||||
// フリック判定
|
// フリック判定
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
CheckFlic(i, mouseOldMovePos[i], Input.mousePosition, flickDownPos[i], flickDownTime[i]);
|
CheckFlic(i, mouseOldMovePos[i], SimpleInput.mousePosition, flickDownPos[i], flickDownTime[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseOldMovePos[i] = Vector2.zero;
|
mouseOldMovePos[i] = Vector2.zero;
|
||||||
|
|
||||||
// タッチアップイベント
|
// タッチアップイベント
|
||||||
if (OnTouchUp != null)
|
if (OnTouchUp != null)
|
||||||
OnTouchUp(i, Input.mousePosition);
|
OnTouchUp(i, SimpleInput.mousePosition);
|
||||||
|
|
||||||
// タップ判定
|
// タップ判定
|
||||||
float distcm = Vector2.Distance(downPos[0], Input.mousePosition) / screenDpc;
|
float distcm = Vector2.Distance(downPos[0], SimpleInput.mousePosition) / screenDpc;
|
||||||
if (distcm <= tapRadiusCm)
|
if (distcm <= tapRadiusCm)
|
||||||
{
|
{
|
||||||
if (OnTouchTap != null)
|
if (OnTouchTap != null)
|
||||||
OnTouchTap(i, Input.mousePosition);
|
OnTouchTap(i, SimpleInput.mousePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移動
|
// 移動
|
||||||
if (mouseDown[i])
|
if (mouseDown[i])
|
||||||
{
|
{
|
||||||
Vector2 spos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
|
Vector2 spos = new Vector2(SimpleInput.mousePosition.x, SimpleInput.mousePosition.y);
|
||||||
Vector2 delta = spos - mouseOldMovePos[i];
|
Vector2 delta = spos - mouseOldMovePos[i];
|
||||||
|
|
||||||
if (spos != mouseOldMovePos[i])
|
if (spos != mouseOldMovePos[i])
|
||||||
@ -569,10 +571,10 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 移動通知(現在スクリーン座標、速度(スクリーン比率/s)、速度(cm/s))
|
// 移動通知(現在スクリーン座標、速度(スクリーン比率/s)、速度(cm/s))
|
||||||
if (OnTouchMove != null)
|
if (OnTouchMove != null)
|
||||||
OnTouchMove(i, Input.mousePosition, CalcScreenRatioVector(delta) / Time.deltaTime, speedcm);
|
OnTouchMove(i, SimpleInput.mousePosition, CalcScreenRatioVector(delta) / Time.deltaTime, speedcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseOldMovePos[i] = Input.mousePosition;
|
mouseOldMovePos[i] = SimpleInput.mousePosition;
|
||||||
|
|
||||||
// フリックダウン位置更新
|
// フリックダウン位置更新
|
||||||
flickDownPos[i] = (flickDownPos[i] + spos) * 0.5f;
|
flickDownPos[i] = (flickDownPos[i] + spos) * 0.5f;
|
||||||
@ -582,7 +584,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ピンチイン/アウト
|
// ピンチイン/アウト
|
||||||
float w = Input.GetAxis("Mouse ScrollWheel");
|
float w = SimpleInput.GetMouseScrollWheel();
|
||||||
if (Mathf.Abs(w) > 0.01f)
|
if (Mathf.Abs(w) > 0.01f)
|
||||||
{
|
{
|
||||||
// モバイル入力とスケール感を合わせるために係数を掛ける
|
// モバイル入力とスケール感を合わせるために係数を掛ける
|
||||||
|
|||||||
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/DemoScenes/CoreRP/UnityChanKAGURA_CoreRP.unity
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,5 +1,18 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &-8535022332011870411
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
version: 7
|
||||||
--- !u!114 &-5755898939291106094
|
--- !u!114 &-5755898939291106094
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
@ -116,16 +129,3 @@ Material:
|
|||||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
- _Tiling: {r: 1, g: 1, b: 0, a: 0}
|
- _Tiling: {r: 1, g: 1, b: 0, a: 0}
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
--- !u!114 &3484866536248413851
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 11
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
version: 7
|
|
||||||
|
|||||||
@ -1,5 +1,18 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &-2691252781391532706
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
version: 7
|
||||||
--- !u!21 &2100000
|
--- !u!21 &2100000
|
||||||
Material:
|
Material:
|
||||||
serializedVersion: 8
|
serializedVersion: 8
|
||||||
@ -116,16 +129,3 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
version: 0
|
version: 0
|
||||||
--- !u!114 &8408605057506184450
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 11
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
version: 7
|
|
||||||
|
|||||||
@ -1,5 +1,18 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &-7295792319158048354
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
version: 7
|
||||||
--- !u!114 &-4086932747498456647
|
--- !u!114 &-4086932747498456647
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
@ -13,19 +26,6 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
version: 0
|
version: 0
|
||||||
--- !u!114 &-164983938586400980
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 11
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
version: 7
|
|
||||||
--- !u!21 &2100000
|
--- !u!21 &2100000
|
||||||
Material:
|
Material:
|
||||||
serializedVersion: 8
|
serializedVersion: 8
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!114 &-4330475528230009683
|
--- !u!114 &-3407187510348448959
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
|||||||
@ -13,19 +13,6 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
version: 0
|
version: 0
|
||||||
--- !u!114 &-1058601315364651215
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 11
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
version: 7
|
|
||||||
--- !u!21 &2100000
|
--- !u!21 &2100000
|
||||||
Material:
|
Material:
|
||||||
serializedVersion: 8
|
serializedVersion: 8
|
||||||
@ -129,3 +116,16 @@ Material:
|
|||||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
- _Tiling: {r: 1, g: 1, b: 0, a: 0}
|
- _Tiling: {r: 1, g: 1, b: 0, a: 0}
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
|
--- !u!114 &5988508712152931550
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
version: 7
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!114 &-8786398318607239453
|
--- !u!114 &-178249263625412926
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
|||||||
@ -1,18 +1,5 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!114 &-6925851060112298428
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 11
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
version: 7
|
|
||||||
--- !u!21 &2100000
|
--- !u!21 &2100000
|
||||||
Material:
|
Material:
|
||||||
serializedVersion: 8
|
serializedVersion: 8
|
||||||
@ -116,6 +103,19 @@ Material:
|
|||||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
- _Tiling: {r: 1, g: 1, b: 0, a: 0}
|
- _Tiling: {r: 1, g: 1, b: 0, a: 0}
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
|
--- !u!114 &1491462379427701739
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
version: 7
|
||||||
--- !u!114 &6265247899772061283
|
--- !u!114 &6265247899772061283
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
|
|||||||
@ -116,7 +116,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
version: 0
|
version: 0
|
||||||
--- !u!114 &9070933888469703597
|
--- !u!114 &7169070195589252005
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 11
|
m_ObjectHideFlags: 11
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
|||||||
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Body).prefab
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/SD_Kohaku_chanz/Utc_sum_humanoid (Hair).prefab
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Example (Can be deleted)/UnityChan/UnityChanKAGURA/UnityCHanKAGURA_MC2.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Accessory.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Cape.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_FrontHair.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_HardSpring.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_LongHair.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_MiddleSpring.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_ShortHair.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Skirt.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_SoftSpring.json
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json
(Stored with Git LFS)
vendored
BIN
Assets/External/MagicaCloth2/Res/Preset/MC2_Preset_Tail.json
(Stored with Git LFS)
vendored
Binary file not shown.
@ -19,5 +19,11 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gizmo display state.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsGizmoVisible { get; set; }
|
||||||
|
protected virtual void OnDrawGizmos() => IsGizmoVisible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 重力方向(ワールド空間)
|
/// 重力方向(ワールド空間)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 gravityDirection;
|
public float3 worldGravityDirection;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初期姿勢での重力の減衰率(0.0 ~ 1.0)
|
/// 初期姿勢での重力の減衰率(0.0 ~ 1.0)
|
||||||
@ -63,6 +63,9 @@ namespace MagicaCloth2
|
|||||||
public float rotationalInterpolation;
|
public float rotationalInterpolation;
|
||||||
public float rootRotation;
|
public float rootRotation;
|
||||||
|
|
||||||
|
// カリング(Culling)
|
||||||
|
public CullingSettings.CullingParams culling;
|
||||||
|
|
||||||
// 慣性制約(Inertia)
|
// 慣性制約(Inertia)
|
||||||
public InertiaConstraint.InertiaConstraintParams inertiaConstraint;
|
public InertiaConstraint.InertiaConstraintParams inertiaConstraint;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
@ -16,20 +17,31 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
public MagicaCloth cloth { get; internal set; }
|
public MagicaCloth cloth { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同期中の参照クロス。これは同期階層の最上位のクロスを指す
|
||||||
|
/// </summary>
|
||||||
|
public MagicaCloth SyncTopCloth { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 状態フラグ(0 ~ 31)
|
/// 状態フラグ(0 ~ 31)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int State_Valid = 0;
|
public const int State_Valid = 0;
|
||||||
public const int State_Enable = 1;
|
public const int State_Enable = 1;
|
||||||
public const int State_ParameterDirty = 2;
|
//public const int State_ParameterDirty = 2;
|
||||||
public const int State_InitComplete = 3;
|
public const int State_InitSuccess = 3;
|
||||||
public const int State_Build = 4;
|
public const int State_InitComplete = 4;
|
||||||
public const int State_Running = 5;
|
public const int State_Build = 5;
|
||||||
public const int State_DisableAutoBuild = 6;
|
public const int State_Running = 6;
|
||||||
public const int State_CullingInvisible = 7; // チームデータの同フラグのコピー
|
public const int State_DisableAutoBuild = 7;
|
||||||
public const int State_CullingKeep = 8; // チームデータの同フラグのコピー
|
public const int State_CameraCullingInvisible = 8; // チームデータの同フラグのコピー
|
||||||
public const int State_SkipWriting = 9; // 書き込み停止(ストップモーション用)
|
public const int State_CameraCullingKeep = 9; // チームデータの同フラグのコピー
|
||||||
public const int State_SkipWritingDirty = 10; // 書き込み停止フラグ更新サイン
|
public const int State_SkipWriting = 10; // 書き込み停止(ストップモーション用)
|
||||||
|
//public const int State_SkipWritingDirty = 11; // 書き込み停止フラグ更新サイン
|
||||||
|
public const int State_UsePreBuild = 12; // PreBuildを利用
|
||||||
|
public const int State_DistanceCullingInvisible = 13; // チームデータの同フラグのコピー
|
||||||
|
public const int State_UpdateTangent = 14; // 接線の更新
|
||||||
|
public const int State_Component = 15; // コンポーネントの有効状態
|
||||||
|
public const int State_Verification = 16; // 検証結果による有効状態
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 現在の状態
|
/// 現在の状態
|
||||||
@ -45,7 +57,7 @@ namespace MagicaCloth2
|
|||||||
/// レンダー情報へのハンドル
|
/// レンダー情報へのハンドル
|
||||||
/// (レンダラーのセットアップデータ)
|
/// (レンダラーのセットアップデータ)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<int> renderHandleList = new List<int>();
|
internal List<int> renderHandleList = new List<int>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// BoneClothのセットアップデータ
|
/// BoneClothのセットアップデータ
|
||||||
@ -58,8 +70,11 @@ namespace MagicaCloth2
|
|||||||
public class RenderMeshInfo
|
public class RenderMeshInfo
|
||||||
{
|
{
|
||||||
public int renderHandle;
|
public int renderHandle;
|
||||||
public VirtualMesh renderMesh;
|
public VirtualMeshContainer renderMeshContainer;
|
||||||
public DataChunk mappingChunk;
|
public DataChunk mappingChunk;
|
||||||
|
//public DataChunk renderMeshPositionAndNormalChunk;
|
||||||
|
//public DataChunk renderMeshTangentChunk;
|
||||||
|
public int renderDataWorkIndex;
|
||||||
}
|
}
|
||||||
internal List<RenderMeshInfo> renderMeshInfoList = new List<RenderMeshInfo>();
|
internal List<RenderMeshInfo> renderMeshInfoList = new List<RenderMeshInfo>();
|
||||||
|
|
||||||
@ -96,6 +111,11 @@ namespace MagicaCloth2
|
|||||||
internal ResultCode result;
|
internal ResultCode result;
|
||||||
public ResultCode Result => result;
|
public ResultCode Result => result;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初期化データ参照結果
|
||||||
|
/// </summary>
|
||||||
|
public ResultCode InitDataResult { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cloth Type
|
/// Cloth Type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -120,18 +140,15 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// プロキシメッシュ
|
/// プロキシメッシュ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VirtualMesh ProxyMesh { get; private set; } = null;
|
public VirtualMeshContainer ProxyMeshContainer { get; private set; } = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// コライダーリスト
|
/// 登録中のコライダー
|
||||||
/// コライダーが格納されるインデックスは他のデータのインデックスと一致している
|
/// int2 (メインコライダー・ローカルインデックス, シンメトリーコライダー・ローカルインデックス)
|
||||||
|
/// メインコライダーのインデックス0はあり得る
|
||||||
|
/// シンメトリーコライダーのインデックス0はシンメトリーが存在しないことを示す
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal List<ColliderComponent> colliderList = new List<ColliderComponent>();
|
internal Dictionary<ColliderComponent, int2> colliderDict = new Dictionary<ColliderComponent, int2>();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// コライダー配列数
|
|
||||||
/// </summary>
|
|
||||||
internal int ColliderCapacity => colliderList.Count;
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -156,14 +173,37 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// カリング用対象アニメーター
|
/// 連動アニメーター
|
||||||
|
/// ・カリング
|
||||||
|
/// ・更新モード
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal Animator cullingAnimator = null;
|
internal Animator interlockingAnimator = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// カリング用アニメーター配下のレンダラーリスト
|
/// カリング用アニメーター配下のレンダラーリスト
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal List<Renderer> cullingAnimatorRenderers = new List<Renderer>();
|
internal List<Renderer> interlockingAnimatorRenderers = new List<Renderer>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在アンカーとして設定されているTransformのインスタンスID
|
||||||
|
/// </summary>
|
||||||
|
internal int anchorTransformId = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在距離カリングの参照として設定されているオブジェクトのインスタンスID
|
||||||
|
/// </summary>
|
||||||
|
internal int distanceReferenceObjectId = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// コンポーネントの登録TransformIndex
|
||||||
|
/// tdata.componentTransformIndexのコピー
|
||||||
|
/// </summary>
|
||||||
|
//internal int componentTransformIndex = 0;
|
||||||
|
|
||||||
|
internal Animator cameraCullingAnimator = null;
|
||||||
|
internal List<Renderer> cameraCullingRenderers = null;
|
||||||
|
internal CullingSettings.CameraCullingMode cameraCullingMode;
|
||||||
|
internal bool cameraCullingOldInvisible = false;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -171,12 +211,12 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
volatile object lockObject = new object();
|
volatile object lockObject = new object();
|
||||||
volatile object lockState = new object();
|
//volatile object lockState = new object();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初期化待機カウンター
|
/// 初期化待機カウンター
|
||||||
/// </summary>
|
/// </summary>
|
||||||
volatile int suspendCounter = 0;
|
//volatile int suspendCounter = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 破棄フラグ
|
/// 破棄フラグ
|
||||||
@ -195,7 +235,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public BitField32 GetStateFlag()
|
public BitField32 GetStateFlag()
|
||||||
{
|
{
|
||||||
lock (lockState)
|
//lock (lockState)
|
||||||
{
|
{
|
||||||
// copy
|
// copy
|
||||||
var state = stateFlag;
|
var state = stateFlag;
|
||||||
@ -205,7 +245,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public bool IsState(int state)
|
public bool IsState(int state)
|
||||||
{
|
{
|
||||||
lock (lockState)
|
//lock (lockState)
|
||||||
{
|
{
|
||||||
return stateFlag.IsSet(state);
|
return stateFlag.IsSet(state);
|
||||||
}
|
}
|
||||||
@ -213,16 +253,19 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void SetState(int state, bool sw)
|
public void SetState(int state, bool sw)
|
||||||
{
|
{
|
||||||
lock (lockState)
|
//lock (lockState)
|
||||||
{
|
{
|
||||||
stateFlag.SetBits(state, sw);
|
stateFlag.SetBits(state, sw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsValid() => IsState(State_Valid);
|
public bool IsValid() => IsState(State_Valid);
|
||||||
public bool IsCullingInvisible() => IsState(State_CullingInvisible);
|
public bool IsRunning() => IsState(State_Running);
|
||||||
public bool IsCullingKeep() => IsState(State_CullingKeep);
|
public bool IsCameraCullingInvisible() => IsState(State_CameraCullingInvisible);
|
||||||
|
public bool IsCameraCullingKeep() => IsState(State_CameraCullingKeep);
|
||||||
|
public bool IsDistanceCullingInvisible() => IsState(State_DistanceCullingInvisible);
|
||||||
public bool IsSkipWriting() => IsState(State_SkipWriting);
|
public bool IsSkipWriting() => IsState(State_SkipWriting);
|
||||||
|
public bool IsUpdateTangent() => IsState(State_UpdateTangent);
|
||||||
|
|
||||||
public bool IsEnable
|
public bool IsEnable
|
||||||
{
|
{
|
||||||
@ -240,7 +283,7 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
if (IsValid() == false || TeamId == 0)
|
if (IsValid() == false || TeamId == 0)
|
||||||
return false;
|
return false;
|
||||||
return ProxyMesh?.IsSuccess ?? false;
|
return ProxyMeshContainer?.shareVirtualMesh?.IsSuccess ?? false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +335,7 @@ namespace MagicaCloth2
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 仮想メッシュ破棄
|
// 仮想メッシュ破棄
|
||||||
info.renderMesh?.Dispose();
|
info.renderMeshContainer?.Dispose();
|
||||||
}
|
}
|
||||||
renderMeshInfoList.Clear();
|
renderMeshInfoList.Clear();
|
||||||
renderMeshInfoList = null;
|
renderMeshInfoList = null;
|
||||||
@ -310,13 +353,24 @@ namespace MagicaCloth2
|
|||||||
boneClothSetupData = null;
|
boneClothSetupData = null;
|
||||||
|
|
||||||
// プロキシメッシュ破棄
|
// プロキシメッシュ破棄
|
||||||
ProxyMesh?.Dispose();
|
ProxyMeshContainer?.Dispose();
|
||||||
ProxyMesh = null;
|
ProxyMeshContainer = null;
|
||||||
|
|
||||||
colliderList.Clear();
|
colliderDict.Clear();
|
||||||
|
|
||||||
cullingAnimator = null;
|
interlockingAnimator = null;
|
||||||
cullingAnimatorRenderers.Clear();
|
interlockingAnimatorRenderers.Clear();
|
||||||
|
|
||||||
|
// PreBuildデータ解除
|
||||||
|
MagicaManager.PreBuild?.UnregisterPreBuildData(cloth?.GetSerializeData2()?.preBuildData.GetSharePreBuildData());
|
||||||
|
|
||||||
|
// 作業バッファ破棄
|
||||||
|
SyncTopCloth = null;
|
||||||
|
int compId = cloth.GetInstanceID();
|
||||||
|
MagicaManager.Team.comp2SuspendCounterMap.Remove(compId);
|
||||||
|
MagicaManager.Team.comp2TeamIdMap.Remove(compId);
|
||||||
|
MagicaManager.Team.comp2SyncPartnerCompMap.Remove(compId);
|
||||||
|
MagicaManager.Team.comp2SyncTopCompMap.Remove(compId);
|
||||||
|
|
||||||
// 完全破棄フラグ
|
// 完全破棄フラグ
|
||||||
isDestoryInternal = true;
|
isDestoryInternal = true;
|
||||||
@ -329,23 +383,44 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
internal void IncrementSuspendCounter()
|
internal void IncrementSuspendCounter()
|
||||||
{
|
{
|
||||||
lock (lockObject)
|
//suspendCounter++;
|
||||||
|
var tm = MagicaManager.Team;
|
||||||
|
int compId = cloth.GetInstanceID();
|
||||||
|
if (tm.comp2SuspendCounterMap.TryGetValue(compId, out int cnt))
|
||||||
{
|
{
|
||||||
suspendCounter++;
|
cnt++;
|
||||||
|
//tm.comp2SuspendCounterMap.Add(compId, cnt);
|
||||||
|
tm.comp2SuspendCounterMap[compId] = cnt;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
tm.comp2SuspendCounterMap.Add(compId, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void DecrementSuspendCounter()
|
internal void DecrementSuspendCounter()
|
||||||
{
|
{
|
||||||
lock (lockObject)
|
//suspendCounter--;
|
||||||
|
var tm = MagicaManager.Team;
|
||||||
|
int compId = cloth.GetInstanceID();
|
||||||
|
if (tm.comp2SuspendCounterMap.TryGetValue(compId, out int cnt))
|
||||||
{
|
{
|
||||||
suspendCounter--;
|
cnt--;
|
||||||
|
if (cnt > 0)
|
||||||
|
//tm.comp2SuspendCounterMap.Add(compId, cnt);
|
||||||
|
tm.comp2SuspendCounterMap[compId] = cnt;
|
||||||
|
else
|
||||||
|
tm.comp2SuspendCounterMap.Remove(compId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int GetSuspendCounter()
|
internal int GetSuspendCounter()
|
||||||
{
|
{
|
||||||
return suspendCounter;
|
//return suspendCounter;
|
||||||
|
var tm = MagicaManager.Team;
|
||||||
|
int compId = cloth.GetInstanceID();
|
||||||
|
if (tm.comp2SuspendCounterMap.TryGetValue(compId, out int cnt))
|
||||||
|
return cnt;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderMeshInfo GetRenderMeshInfo(int index)
|
public RenderMeshInfo GetRenderMeshInfo(int index)
|
||||||
@ -364,16 +439,22 @@ namespace MagicaCloth2
|
|||||||
public void GetUsedTransform(HashSet<Transform> transformSet)
|
public void GetUsedTransform(HashSet<Transform> transformSet)
|
||||||
{
|
{
|
||||||
cloth.SerializeData.GetUsedTransform(transformSet);
|
cloth.SerializeData.GetUsedTransform(transformSet);
|
||||||
|
cloth.serializeData2.GetUsedTransform(transformSet);
|
||||||
clothTransformRecord?.GetUsedTransform(transformSet);
|
clothTransformRecord?.GetUsedTransform(transformSet);
|
||||||
boneClothSetupData?.GetUsedTransform(transformSet);
|
boneClothSetupData?.GetUsedTransform(transformSet);
|
||||||
renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).GetUsedTransform(transformSet));
|
renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).GetUsedTransform(transformSet));
|
||||||
customSkinningBoneRecords.ForEach(rd => rd.GetUsedTransform(transformSet));
|
customSkinningBoneRecords.ForEach(rd => rd.GetUsedTransform(transformSet));
|
||||||
normalAdjustmentTransformRecord?.GetUsedTransform(transformSet);
|
normalAdjustmentTransformRecord?.GetUsedTransform(transformSet);
|
||||||
|
|
||||||
|
// nullを除外する
|
||||||
|
if (transformSet.Contains(null))
|
||||||
|
transformSet.Remove(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
||||||
{
|
{
|
||||||
cloth.SerializeData.ReplaceTransform(replaceDict);
|
cloth.SerializeData.ReplaceTransform(replaceDict);
|
||||||
|
cloth.serializeData2.ReplaceTransform(replaceDict);
|
||||||
clothTransformRecord?.ReplaceTransform(replaceDict);
|
clothTransformRecord?.ReplaceTransform(replaceDict);
|
||||||
boneClothSetupData?.ReplaceTransform(replaceDict);
|
boneClothSetupData?.ReplaceTransform(replaceDict);
|
||||||
renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).ReplaceTransform(replaceDict));
|
renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).ReplaceTransform(replaceDict));
|
||||||
@ -386,7 +467,44 @@ namespace MagicaCloth2
|
|||||||
// ここではフラグのみ更新する
|
// ここではフラグのみ更新する
|
||||||
// 実際の更新はチームのAlwaysTeamUpdate()で行われる
|
// 実際の更新はチームのAlwaysTeamUpdate()で行われる
|
||||||
SetState(State_SkipWriting, sw);
|
SetState(State_SkipWriting, sw);
|
||||||
SetState(State_SkipWritingDirty, true);
|
//SetState(State_SkipWritingDirty, true);
|
||||||
|
MagicaManager.Team.skipWritingDirtyList.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ClothUpdateMode GetClothUpdateMode()
|
||||||
|
{
|
||||||
|
switch (cloth.SerializeData.updateMode)
|
||||||
|
{
|
||||||
|
case ClothUpdateMode.Normal:
|
||||||
|
case ClothUpdateMode.UnityPhysics:
|
||||||
|
case ClothUpdateMode.Unscaled:
|
||||||
|
return cloth.SerializeData.updateMode;
|
||||||
|
case ClothUpdateMode.AnimatorLinkage:
|
||||||
|
if (interlockingAnimator)
|
||||||
|
{
|
||||||
|
switch (interlockingAnimator.updateMode)
|
||||||
|
{
|
||||||
|
case AnimatorUpdateMode.Normal:
|
||||||
|
return ClothUpdateMode.Normal;
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
case AnimatorUpdateMode.Fixed:
|
||||||
|
return ClothUpdateMode.UnityPhysics;
|
||||||
|
#else
|
||||||
|
case AnimatorUpdateMode.AnimatePhysics:
|
||||||
|
return ClothUpdateMode.UnityPhysics;
|
||||||
|
#endif
|
||||||
|
case AnimatorUpdateMode.UnscaledTime:
|
||||||
|
return ClothUpdateMode.Unscaled;
|
||||||
|
default:
|
||||||
|
Develop.DebugLogWarning($"[{cloth.name}] Unknown Animator UpdateMode:{interlockingAnimator.updateMode}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ClothUpdateMode.Normal;
|
||||||
|
default:
|
||||||
|
Develop.LogError($"[{cloth.name}] Unknown Cloth Update Mode:{cloth.SerializeData.updateMode}");
|
||||||
|
return ClothUpdateMode.Normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,56 @@
|
|||||||
// Magica Cloth 2.
|
// Magica Cloth 2.
|
||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
{
|
{
|
||||||
public partial class ClothProcess
|
public partial class ClothProcess
|
||||||
{
|
{
|
||||||
|
public ResultCode GenerateStatusCheck()
|
||||||
|
{
|
||||||
|
ResultCode result = new ResultCode();
|
||||||
|
|
||||||
|
// スケール値チェック
|
||||||
|
var scl = cloth.transform.lossyScale;
|
||||||
|
if (Mathf.Approximately(scl.x, 0.0f) || Mathf.Approximately(scl.y, 0.0f) || Mathf.Approximately(scl.z, 0.0f))
|
||||||
|
{
|
||||||
|
// スケール値がゼロ
|
||||||
|
result.SetError(Define.Result.Init_ScaleIsZero);
|
||||||
|
}
|
||||||
|
else if (scl.x < 0.0f || scl.y < 0.0f || scl.z < 0.0f)
|
||||||
|
{
|
||||||
|
// 負のスケール
|
||||||
|
// 負のスケールでの初期化は、事前構築もしくは初期化データありの場合許可する
|
||||||
|
var sdata2 = cloth.GetSerializeData2();
|
||||||
|
if (sdata2.preBuildData.UsePreBuild() || (sdata2.initData?.HasData() ?? false))
|
||||||
|
{
|
||||||
|
// ただし許可されるのは一軸フリップのみ
|
||||||
|
int flipCount = (scl.x < 0.0f ? 1 : 0) + (scl.y < 0.0f ? 1 : 0) + (scl.z < 0.0f ? 1 : 0);
|
||||||
|
if (flipCount != 1)
|
||||||
|
{
|
||||||
|
result.SetError(Define.Result.Init_NegativeScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result.SetError(Define.Result.Init_NegativeScale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float diff1 = Mathf.Abs(1.0f - scl.x / scl.y);
|
||||||
|
float diff2 = Mathf.Abs(1.0f - scl.x / scl.z);
|
||||||
|
const float diffTolerance = 0.01f; // 誤差(1%)
|
||||||
|
if (diff1 > diffTolerance || diff2 > diffTolerance)
|
||||||
|
{
|
||||||
|
// 一様スケールではない
|
||||||
|
result.SetWarning(Define.Result.Init_NonUniformScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
internal bool GenerateInitialization()
|
internal bool GenerateInitialization()
|
||||||
{
|
{
|
||||||
result.SetProcess();
|
result.SetProcess();
|
||||||
|
|||||||
@ -29,6 +29,13 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Renderer> sourceRenderers = new List<Renderer>();
|
public List<Renderer> sourceRenderers = new List<Renderer>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write target to mesh in MeshCloth.
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
public ClothMeshWriteMode meshWriteMode = ClothMeshWriteMode.PositionAndNormal;
|
||||||
|
|
||||||
public enum PaintMode
|
public enum PaintMode
|
||||||
{
|
{
|
||||||
Manual = 0,
|
Manual = 0,
|
||||||
@ -55,6 +62,14 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Texture2D> paintMaps = new List<Texture2D>();
|
public List<Texture2D> paintMaps = new List<Texture2D>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The UV channel that references the paint map.
|
||||||
|
/// [NG] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
[Range(0, 7)]
|
||||||
|
public int paintMapUvChannel = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Root bone list used in BoneCloth.
|
/// Root bone list used in BoneCloth.
|
||||||
/// [NG] Runtime changes.
|
/// [NG] Runtime changes.
|
||||||
@ -92,7 +107,7 @@ namespace MagicaCloth2
|
|||||||
/// [OK] Runtime changes.
|
/// [OK] Runtime changes.
|
||||||
/// [NG] Export/Import with Presets
|
/// [NG] Export/Import with Presets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ClothUpdateMode updateMode = ClothUpdateMode.Normal;
|
public ClothUpdateMode updateMode = ClothUpdateMode.AnimatorLinkage;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Blend ratio between initial pose and animation pose.
|
/// Blend ratio between initial pose and animation pose.
|
||||||
@ -180,7 +195,7 @@ namespace MagicaCloth2
|
|||||||
/// [OK] Runtime changes.
|
/// [OK] Runtime changes.
|
||||||
/// [NG] Export/Import with Presets
|
/// [NG] Export/Import with Presets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[System.NonSerialized]
|
[Range(0.0f, 1.0f)]
|
||||||
public float blendWeight = 1.0f;
|
public float blendWeight = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -11,8 +11,14 @@ namespace MagicaCloth2
|
|||||||
/// Parts that cannot be exported externally.
|
/// Parts that cannot be exported externally.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class ClothSerializeData2 : IDataValidate, IValid
|
public class ClothSerializeData2 : IDataValidate, IValid, ITransform
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initialization Data.
|
||||||
|
/// </summary>
|
||||||
|
[SerializeField]
|
||||||
|
public ClothInitSerializeData initData = new ClothInitSerializeData();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 頂点ペイントデータ
|
/// 頂点ペイントデータ
|
||||||
/// vertex paint data.
|
/// vertex paint data.
|
||||||
@ -26,8 +32,23 @@ namespace MagicaCloth2
|
|||||||
/// Transform and vertex attribute dictionary data.
|
/// Transform and vertex attribute dictionary data.
|
||||||
/// When creating BoneCloth/BoneSpring at runtime, you can store Transform and vertex attribute pairs in this dictionary and use it instead of vertex paint data.
|
/// When creating BoneCloth/BoneSpring at runtime, you can store Transform and vertex attribute pairs in this dictionary and use it instead of vertex paint data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[System.NonSerialized]
|
||||||
public Dictionary<Transform, VertexAttribute> boneAttributeDict = new Dictionary<Transform, VertexAttribute>();
|
public Dictionary<Transform, VertexAttribute> boneAttributeDict = new Dictionary<Transform, VertexAttribute>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rendererに対応する頂点属性データ
|
||||||
|
/// 実行時にMeshClothを構築する場合に、このリストにレンダラーごとのメッシュ頂点数分の頂点属性を格納することでセレクションデータの代わりにすることができます
|
||||||
|
/// Vertex attribute data corresponding to the Renderer.
|
||||||
|
/// When constructing MeshCloth at runtime, you can substitute selection data by storing vertex attributes in this list for the number of mesh vertices per renderer.
|
||||||
|
/// </summary>
|
||||||
|
[System.NonSerialized]
|
||||||
|
public List<VertexAttribute[]> vertexAttributeList = new List<VertexAttribute[]>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PreBuild Data.
|
||||||
|
/// </summary>
|
||||||
|
public PreBuildSerializeData preBuildData = new PreBuildSerializeData();
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public ClothSerializeData2()
|
public ClothSerializeData2()
|
||||||
{
|
{
|
||||||
@ -57,5 +78,17 @@ namespace MagicaCloth2
|
|||||||
int hash = 0;
|
int hash = 0;
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetUsedTransform(HashSet<Transform> transformSet)
|
||||||
|
{
|
||||||
|
initData.GetUsedTransform(transformSet);
|
||||||
|
preBuildData.GetUsedTransform(transformSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
||||||
|
{
|
||||||
|
initData.ReplaceTransform(replaceDict);
|
||||||
|
preBuildData.ReplaceTransform(replaceDict);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,11 @@ namespace MagicaCloth2
|
|||||||
return false;
|
return false;
|
||||||
if (rootBones.Count(x => x != null) == 0)
|
if (rootBones.Count(x => x != null) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
if (rootBones.Distinct().Count() != rootBones.Count)
|
||||||
|
{
|
||||||
|
verificationResult.SetError(Define.Result.SerializeData_DuplicateRootBone);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ClothProcess.ClothType.MeshCloth:
|
case ClothProcess.ClothType.MeshCloth:
|
||||||
if (sourceRenderers == null || sourceRenderers.Count == 0)
|
if (sourceRenderers == null || sourceRenderers.Count == 0)
|
||||||
@ -57,6 +62,11 @@ namespace MagicaCloth2
|
|||||||
verificationResult.SetError(Define.Result.SerializeData_Over31Renderers);
|
verificationResult.SetError(Define.Result.SerializeData_Over31Renderers);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (sourceRenderers.Distinct().Count() != sourceRenderers.Count)
|
||||||
|
{
|
||||||
|
verificationResult.SetError(Define.Result.SerializeData_DuplicateRenderer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -107,10 +117,12 @@ namespace MagicaCloth2
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
|
const int NullHash = -3910836;
|
||||||
|
|
||||||
int hash = 0;
|
int hash = 0;
|
||||||
hash += (int)clothType;
|
hash += (int)clothType;
|
||||||
foreach (var ren in sourceRenderers)
|
foreach (var ren in sourceRenderers)
|
||||||
hash += ren?.GetInstanceID() ?? 0;
|
hash += ren?.GetInstanceID() ?? NullHash;
|
||||||
foreach (var t in rootBones)
|
foreach (var t in rootBones)
|
||||||
{
|
{
|
||||||
var stack = new Stack<Transform>(30);
|
var stack = new Stack<Transform>(30);
|
||||||
@ -119,7 +131,10 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
var t2 = stack.Pop();
|
var t2 = stack.Pop();
|
||||||
if (t2 == null)
|
if (t2 == null)
|
||||||
|
{
|
||||||
|
hash += NullHash;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
hash += t2.GetInstanceID();
|
hash += t2.GetInstanceID();
|
||||||
hash += t2.localPosition.GetHashCode();
|
hash += t2.localPosition.GetHashCode();
|
||||||
hash += t2.localRotation.GetHashCode();
|
hash += t2.localRotation.GetHashCode();
|
||||||
@ -142,6 +157,7 @@ namespace MagicaCloth2
|
|||||||
hash += map.isReadable ? 1 : 0;
|
hash += map.isReadable ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hash += paintMapUvChannel * 123;
|
||||||
hash += colliderCollisionConstraint.GetHashCode();
|
hash += colliderCollisionConstraint.GetHashCode();
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
@ -158,7 +174,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
//cparams.solverFrequency = Define.System.SolverFrequency;
|
//cparams.solverFrequency = Define.System.SolverFrequency;
|
||||||
cparams.gravity = clothType == ClothProcess.ClothType.BoneSpring ? 0.0f : gravity; // BoneSpring has no gravity.
|
cparams.gravity = clothType == ClothProcess.ClothType.BoneSpring ? 0.0f : gravity; // BoneSpring has no gravity.
|
||||||
cparams.gravityDirection = gravityDirection;
|
cparams.worldGravityDirection = gravityDirection;
|
||||||
cparams.gravityFalloff = gravityFalloff;
|
cparams.gravityFalloff = gravityFalloff;
|
||||||
cparams.stablizationTimeAfterReset = stablizationTimeAfterReset;
|
cparams.stablizationTimeAfterReset = stablizationTimeAfterReset;
|
||||||
cparams.blendWeight = blendWeight;
|
cparams.blendWeight = blendWeight;
|
||||||
@ -169,6 +185,7 @@ namespace MagicaCloth2
|
|||||||
cparams.rotationalInterpolation = rotationalInterpolation;
|
cparams.rotationalInterpolation = rotationalInterpolation;
|
||||||
cparams.rootRotation = rootRotation;
|
cparams.rootRotation = rootRotation;
|
||||||
|
|
||||||
|
cparams.culling.Convert(cullingSettings);
|
||||||
cparams.inertiaConstraint.Convert(inertiaConstraint);
|
cparams.inertiaConstraint.Convert(inertiaConstraint);
|
||||||
cparams.tetherConstraint.Convert(tetherConstraint, clothType);
|
cparams.tetherConstraint.Convert(tetherConstraint, clothType);
|
||||||
cparams.distanceConstraint.Convert(distanceConstraint, clothType);
|
cparams.distanceConstraint.Convert(distanceConstraint, clothType);
|
||||||
@ -187,8 +204,10 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
ClothProcess.ClothType clothType;
|
ClothProcess.ClothType clothType;
|
||||||
List<Renderer> sourceRenderers;
|
List<Renderer> sourceRenderers;
|
||||||
|
ClothMeshWriteMode meshWriteMode;
|
||||||
PaintMode paintMode;
|
PaintMode paintMode;
|
||||||
List<Texture2D> paintMaps;
|
List<Texture2D> paintMaps;
|
||||||
|
int paintMapUvChannel;
|
||||||
List<Transform> rootBones;
|
List<Transform> rootBones;
|
||||||
RenderSetupData.BoneConnectionMode connectionMode;
|
RenderSetupData.BoneConnectionMode connectionMode;
|
||||||
float rotationalInterpolation;
|
float rotationalInterpolation;
|
||||||
@ -204,9 +223,9 @@ namespace MagicaCloth2
|
|||||||
MagicaCloth synchronization;
|
MagicaCloth synchronization;
|
||||||
float stablizationTimeAfterReset;
|
float stablizationTimeAfterReset;
|
||||||
float blendWeight;
|
float blendWeight;
|
||||||
CullingSettings.CameraCullingMode cullingMode;
|
CullingSettings cullingSetting;
|
||||||
CullingSettings.CameraCullingMethod cullingMethod;
|
Transform anchor;
|
||||||
List<Renderer> cullingRenderers;
|
float anchorInertia;
|
||||||
|
|
||||||
internal TempBuffer(ClothSerializeData sdata)
|
internal TempBuffer(ClothSerializeData sdata)
|
||||||
{
|
{
|
||||||
@ -217,8 +236,10 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
clothType = sdata.clothType;
|
clothType = sdata.clothType;
|
||||||
sourceRenderers = new List<Renderer>(sdata.sourceRenderers);
|
sourceRenderers = new List<Renderer>(sdata.sourceRenderers);
|
||||||
|
meshWriteMode = sdata.meshWriteMode;
|
||||||
paintMode = sdata.paintMode;
|
paintMode = sdata.paintMode;
|
||||||
paintMaps = new List<Texture2D>(sdata.paintMaps);
|
paintMaps = new List<Texture2D>(sdata.paintMaps);
|
||||||
|
paintMapUvChannel = sdata.paintMapUvChannel;
|
||||||
rootBones = new List<Transform>(sdata.rootBones);
|
rootBones = new List<Transform>(sdata.rootBones);
|
||||||
connectionMode = sdata.connectionMode;
|
connectionMode = sdata.connectionMode;
|
||||||
rotationalInterpolation = sdata.rotationalInterpolation;
|
rotationalInterpolation = sdata.rotationalInterpolation;
|
||||||
@ -234,17 +255,19 @@ namespace MagicaCloth2
|
|||||||
synchronization = sdata.selfCollisionConstraint.syncPartner;
|
synchronization = sdata.selfCollisionConstraint.syncPartner;
|
||||||
stablizationTimeAfterReset = sdata.stablizationTimeAfterReset;
|
stablizationTimeAfterReset = sdata.stablizationTimeAfterReset;
|
||||||
blendWeight = sdata.blendWeight;
|
blendWeight = sdata.blendWeight;
|
||||||
cullingMode = sdata.cullingSettings.cameraCullingMode;
|
cullingSetting = sdata.cullingSettings.Clone();
|
||||||
cullingMethod = sdata.cullingSettings.cameraCullingMethod;
|
anchor = sdata.inertiaConstraint.anchor;
|
||||||
cullingRenderers = new List<Renderer>(sdata.cullingSettings.cameraCullingRenderers);
|
anchorInertia = sdata.inertiaConstraint.anchorInertia;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Pop(ClothSerializeData sdata)
|
internal void Pop(ClothSerializeData sdata)
|
||||||
{
|
{
|
||||||
sdata.clothType = clothType;
|
sdata.clothType = clothType;
|
||||||
sdata.sourceRenderers = sourceRenderers;
|
sdata.sourceRenderers = sourceRenderers;
|
||||||
|
sdata.meshWriteMode = meshWriteMode;
|
||||||
sdata.paintMode = paintMode;
|
sdata.paintMode = paintMode;
|
||||||
sdata.paintMaps = paintMaps;
|
sdata.paintMaps = paintMaps;
|
||||||
|
sdata.paintMapUvChannel = paintMapUvChannel;
|
||||||
sdata.rootBones = rootBones;
|
sdata.rootBones = rootBones;
|
||||||
sdata.connectionMode = connectionMode;
|
sdata.connectionMode = connectionMode;
|
||||||
sdata.rotationalInterpolation = rotationalInterpolation;
|
sdata.rotationalInterpolation = rotationalInterpolation;
|
||||||
@ -260,9 +283,9 @@ namespace MagicaCloth2
|
|||||||
sdata.selfCollisionConstraint.syncPartner = synchronization;
|
sdata.selfCollisionConstraint.syncPartner = synchronization;
|
||||||
sdata.stablizationTimeAfterReset = stablizationTimeAfterReset;
|
sdata.stablizationTimeAfterReset = stablizationTimeAfterReset;
|
||||||
sdata.blendWeight = blendWeight;
|
sdata.blendWeight = blendWeight;
|
||||||
sdata.cullingSettings.cameraCullingMode = cullingMode;
|
sdata.cullingSettings = cullingSetting;
|
||||||
sdata.cullingSettings.cameraCullingMethod = cullingMethod;
|
sdata.inertiaConstraint.anchor = anchor;
|
||||||
sdata.cullingSettings.cameraCullingRenderers = cullingRenderers;
|
sdata.inertiaConstraint.anchorInertia = anchorInertia;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,6 +348,7 @@ namespace MagicaCloth2
|
|||||||
sourceRenderers = new List<Renderer>(sdata.sourceRenderers);
|
sourceRenderers = new List<Renderer>(sdata.sourceRenderers);
|
||||||
paintMode = sdata.paintMode;
|
paintMode = sdata.paintMode;
|
||||||
paintMaps = new List<Texture2D>(sdata.paintMaps);
|
paintMaps = new List<Texture2D>(sdata.paintMaps);
|
||||||
|
paintMapUvChannel = sdata.paintMapUvChannel;
|
||||||
rootBones = new List<Transform>(sdata.rootBones);
|
rootBones = new List<Transform>(sdata.rootBones);
|
||||||
connectionMode = sdata.connectionMode;
|
connectionMode = sdata.connectionMode;
|
||||||
rotationalInterpolation = sdata.rotationalInterpolation;
|
rotationalInterpolation = sdata.rotationalInterpolation;
|
||||||
@ -404,5 +428,17 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool IsBoneSpring() => clothType == ClothProcess.ClothType.BoneSpring;
|
public bool IsBoneSpring() => clothType == ClothProcess.ClothType.BoneSpring;
|
||||||
|
|
||||||
|
public int GetUvChannel()
|
||||||
|
{
|
||||||
|
switch (paintMode)
|
||||||
|
{
|
||||||
|
case PaintMode.Texture_Fixed_Move:
|
||||||
|
case PaintMode.Texture_Fixed_Move_Limit:
|
||||||
|
return paintMapUvChannel;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,5 +23,14 @@ namespace MagicaCloth2
|
|||||||
/// Updates are independent of Unity's Time.timeScale.
|
/// Updates are independent of Unity's Time.timeScale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Unscaled = 2,
|
Unscaled = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Automatically set from linked animator.
|
||||||
|
/// 連動アニメーターから自動設定する
|
||||||
|
/// - Animator.UpdateMode.Normal -> Normal
|
||||||
|
/// - Animator.UpdateMode.AnimatePhysics -> UnityPhysics
|
||||||
|
/// - Animator.UpdateMode.UnscaledTime -> Unscaled
|
||||||
|
/// </summary>
|
||||||
|
AnimatorLinkage = 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,12 @@
|
|||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
{
|
{
|
||||||
public abstract class ColliderComponent : ClothBehaviour, IDataValidate
|
public abstract class ColliderComponent : ClothBehaviour, IDataValidate, ITransform
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// トランスフォームからの中心ローカルオフセット
|
/// トランスフォームからの中心ローカルオフセット
|
||||||
@ -23,6 +24,17 @@ namespace MagicaCloth2
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
protected Vector3 size;
|
protected Vector3 size;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// シンメトリーモード
|
||||||
|
/// Symmetry mode.
|
||||||
|
/// </summary>
|
||||||
|
public ColliderSymmetryMode symmetryMode = ColliderSymmetryMode.None;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// シンメトリーの接続対象
|
||||||
|
/// Symmetry connection target.
|
||||||
|
/// </summary>
|
||||||
|
public Transform symmetryTarget = null;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -42,6 +54,16 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private HashSet<int> teamIdSet = new HashSet<int>();
|
private HashSet<int> teamIdSet = new HashSet<int>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在登録中のシンメトリーモード
|
||||||
|
/// </summary>
|
||||||
|
public ColliderSymmetryMode? ActiveSymmetryMode { get; private set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在登録中のシンメトリーターゲット
|
||||||
|
/// </summary>
|
||||||
|
public Transform ActiveSymmetryTarget { get; private set; }
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get collider size.
|
/// Get collider size.
|
||||||
@ -52,26 +74,30 @@ namespace MagicaCloth2
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual Vector3 GetSize()
|
public virtual Vector3 GetSize() => size;
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetSize(Vector3 size)
|
public void SetSize(Vector3 size) => this.size = size;
|
||||||
{
|
|
||||||
this.size = size;
|
public void SetSizeX(float size) => this.size.x = size;
|
||||||
}
|
public void SetSizeY(float size) => this.size.y = size;
|
||||||
|
public void SetSizeZ(float size) => this.size.z = size;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// スケール値を取得
|
/// スケール値を取得
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public float GetScale()
|
public virtual float GetScale()
|
||||||
{
|
{
|
||||||
// X軸のみを見る
|
// X軸のみを見る
|
||||||
return transform.lossyScale.x;
|
return transform.lossyScale.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 方向の逆転(基本的にカプセルコライダー用)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual bool IsReverseDirection() => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// チームへのコライダー登録通知
|
/// チームへのコライダー登録通知
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -85,9 +111,11 @@ namespace MagicaCloth2
|
|||||||
/// チームからのコライダー解除通知
|
/// チームからのコライダー解除通知
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="teamId"></param>
|
/// <param name="teamId"></param>
|
||||||
internal void Exit(int teamId)
|
/// <returns>利用者0ならtrue</returns>
|
||||||
|
internal bool Exit(int teamId)
|
||||||
{
|
{
|
||||||
teamIdSet.Remove(teamId);
|
teamIdSet.Remove(teamId);
|
||||||
|
return teamIdSet.Count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -101,15 +129,269 @@ namespace MagicaCloth2
|
|||||||
// パラメータの検証
|
// パラメータの検証
|
||||||
DataValidate();
|
DataValidate();
|
||||||
|
|
||||||
|
// Symmetry更新
|
||||||
|
// シンメトリーは削除もしくは追加がある。またTransformが変更される場合もある
|
||||||
|
var oldActiveSymmetryMode = ActiveSymmetryMode;
|
||||||
|
var oldActiveSymmetryTarget = ActiveSymmetryTarget;
|
||||||
|
SetActiveSymmetryMode(firstOnly: false); // 最新の状態に更新
|
||||||
|
bool changeSymmetry = oldActiveSymmetryMode != ActiveSymmetryMode || oldActiveSymmetryTarget != ActiveSymmetryTarget;
|
||||||
|
|
||||||
|
// 反映
|
||||||
foreach (int teamId in teamIdSet)
|
foreach (int teamId in teamIdSet)
|
||||||
{
|
{
|
||||||
MagicaManager.Collider.UpdateParameters(this, teamId);
|
MagicaManager.Collider.UpdateParameters(this, teamId, changeSymmetry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在の状態から適切なシンメトリーモードとそのターゲットTransformを計算して返す
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ColliderSymmetryMode CalcSymmetryMode(out Transform symmetryParent)
|
||||||
|
{
|
||||||
|
symmetryParent = symmetryTarget;
|
||||||
|
|
||||||
|
// 親
|
||||||
|
var parent = transform.parent;
|
||||||
|
if (parent == null)
|
||||||
|
return ColliderSymmetryMode.None;
|
||||||
|
|
||||||
|
switch (symmetryMode)
|
||||||
|
{
|
||||||
|
case ColliderSymmetryMode.None:
|
||||||
|
return ColliderSymmetryMode.None;
|
||||||
|
case ColliderSymmetryMode.AutomaticHumanBody:
|
||||||
|
case ColliderSymmetryMode.AutomaticTarget:
|
||||||
|
break;
|
||||||
|
case ColliderSymmetryMode.X_Symmetry:
|
||||||
|
case ColliderSymmetryMode.Y_Symmetry:
|
||||||
|
case ColliderSymmetryMode.Z_Symmetry:
|
||||||
|
case ColliderSymmetryMode.XYZ_Symmetry:
|
||||||
|
// ターゲットnullの場合は親
|
||||||
|
if (symmetryParent == null)
|
||||||
|
symmetryParent = parent;
|
||||||
|
return symmetryMode;
|
||||||
|
default:
|
||||||
|
Develop.LogError("Unknown symmetry mode.");
|
||||||
|
return ColliderSymmetryMode.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatic
|
||||||
|
Animator ani = symmetryMode == ColliderSymmetryMode.AutomaticHumanBody ? gameObject.GetComponentInParent<Animator>(true) : null;
|
||||||
|
|
||||||
|
// 対象Transform
|
||||||
|
// AutomaticではSymmetryTargetは無視される
|
||||||
|
var target = symmetryMode == ColliderSymmetryMode.AutomaticTarget ? symmetryTarget : null;
|
||||||
|
if (target == null && ani)
|
||||||
|
{
|
||||||
|
// 自動判定
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Hips, HumanBodyBones.Hips);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftUpperLeg, HumanBodyBones.RightUpperLeg);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightUpperLeg, HumanBodyBones.LeftUpperLeg);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftLowerLeg, HumanBodyBones.RightLowerLeg);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightLowerLeg, HumanBodyBones.LeftLowerLeg);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftFoot, HumanBodyBones.RightFoot);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightFoot, HumanBodyBones.LeftFoot);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Spine, HumanBodyBones.Spine);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Chest, HumanBodyBones.Chest);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Neck, HumanBodyBones.Neck);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Head, HumanBodyBones.Head);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftShoulder, HumanBodyBones.RightShoulder);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightShoulder, HumanBodyBones.LeftShoulder);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftUpperArm, HumanBodyBones.RightUpperArm);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightUpperArm, HumanBodyBones.LeftUpperArm);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftLowerArm, HumanBodyBones.RightLowerArm);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightLowerArm, HumanBodyBones.LeftLowerArm);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftHand, HumanBodyBones.RightHand);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightHand, HumanBodyBones.LeftHand);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.LeftToes, HumanBodyBones.RightToes);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.RightToes, HumanBodyBones.LeftToes);
|
||||||
|
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.Jaw, HumanBodyBones.Jaw);
|
||||||
|
GetHumanoidSymmetryBone(ref target, parent, ani, HumanBodyBones.UpperChest, HumanBodyBones.UpperChest);
|
||||||
|
}
|
||||||
|
if (target == null)
|
||||||
|
target = parent;
|
||||||
|
symmetryParent = target;
|
||||||
|
|
||||||
|
// 親が同一かどうか
|
||||||
|
bool sameParent = target == parent;
|
||||||
|
|
||||||
|
// 各軸
|
||||||
|
var x = parent.right;
|
||||||
|
var y = parent.up;
|
||||||
|
var z = parent.forward;
|
||||||
|
var sx = target.right;
|
||||||
|
var sy = target.up;
|
||||||
|
var sz = target.forward;
|
||||||
|
|
||||||
|
// ベクトルの方向性情報
|
||||||
|
// Animatorがある場合はAnimatorから、ない場合は共通の親Transformから、それでも無い場合はワールドX軸
|
||||||
|
Vector3 H = Vector3.right;
|
||||||
|
if (ani)
|
||||||
|
H = ani.transform.right;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var commonParent = FindCommonParent(transform, symmetryParent);
|
||||||
|
if (commonParent)
|
||||||
|
{
|
||||||
|
//Debug.Log($"Find common parent:{commonParent.name}");
|
||||||
|
H = commonParent.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float xdot = Mathf.Abs(Vector3.Dot(H, x));
|
||||||
|
float ydot = Mathf.Abs(Vector3.Dot(H, y));
|
||||||
|
float zdot = Mathf.Abs(Vector3.Dot(H, z));
|
||||||
|
|
||||||
|
bool xsign = Vector3.Dot(x, sx) >= 0.0f;
|
||||||
|
bool ysign = Vector3.Dot(y, sy) >= 0.0f;
|
||||||
|
bool zsign = Vector3.Dot(z, sz) >= 0.0f;
|
||||||
|
|
||||||
|
if (xdot > ydot && xdot > zdot)
|
||||||
|
{
|
||||||
|
// (X)
|
||||||
|
if (sameParent)
|
||||||
|
return ColliderSymmetryMode.X_Symmetry;
|
||||||
|
if (Vector3.Dot(H, x) * Vector3.Dot(H, sx) > 0.0f)
|
||||||
|
{
|
||||||
|
if (ysign == false && zsign == false)
|
||||||
|
return ColliderSymmetryMode.XYZ_Symmetry;
|
||||||
|
else
|
||||||
|
return ColliderSymmetryMode.X_Symmetry;
|
||||||
|
}
|
||||||
|
else if (zsign)
|
||||||
|
return ColliderSymmetryMode.Y_Symmetry;
|
||||||
|
else
|
||||||
|
return ColliderSymmetryMode.Z_Symmetry;
|
||||||
|
}
|
||||||
|
else if (ydot > xdot && ydot > zdot)
|
||||||
|
{
|
||||||
|
// (Y)
|
||||||
|
if (sameParent)
|
||||||
|
return ColliderSymmetryMode.Y_Symmetry;
|
||||||
|
if (Vector3.Dot(H, y) * Vector3.Dot(H, sy) > 0.0f)
|
||||||
|
{
|
||||||
|
if (xsign == false && zsign == false)
|
||||||
|
return ColliderSymmetryMode.XYZ_Symmetry;
|
||||||
|
else
|
||||||
|
return ColliderSymmetryMode.Y_Symmetry;
|
||||||
|
}
|
||||||
|
else if (zsign)
|
||||||
|
return ColliderSymmetryMode.X_Symmetry;
|
||||||
|
else
|
||||||
|
return ColliderSymmetryMode.Z_Symmetry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// (Z)
|
||||||
|
if (sameParent)
|
||||||
|
return ColliderSymmetryMode.Z_Symmetry;
|
||||||
|
if (Vector3.Dot(H, z) * Vector3.Dot(H, sz) > 0.0f)
|
||||||
|
{
|
||||||
|
if (xsign == false && ysign == false)
|
||||||
|
return ColliderSymmetryMode.XYZ_Symmetry;
|
||||||
|
else
|
||||||
|
return ColliderSymmetryMode.Z_Symmetry;
|
||||||
|
}
|
||||||
|
else if (xsign)
|
||||||
|
return ColliderSymmetryMode.Y_Symmetry;
|
||||||
|
else
|
||||||
|
return ColliderSymmetryMode.X_Symmetry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetHumanoidSymmetryBone(ref Transform target, Transform parent, Animator ani, HumanBodyBones src, HumanBodyBones dst)
|
||||||
|
{
|
||||||
|
var bone = ani.GetBoneTransform(src);
|
||||||
|
if (bone && parent == bone)
|
||||||
|
{
|
||||||
|
var bone2 = ani.GetBoneTransform(dst);
|
||||||
|
if (bone2)
|
||||||
|
{
|
||||||
|
target = bone2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// at/btの共通の親を返す。無い場合はnull。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="at"></param>
|
||||||
|
/// <param name="bt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Transform FindCommonParent(Transform at, Transform bt)
|
||||||
|
{
|
||||||
|
if (at == null || bt == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// ハッシュセットでatの親を格納
|
||||||
|
var atParents = new HashSet<Transform>(16);
|
||||||
|
Transform current = at;
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
atParents.Add(current);
|
||||||
|
current = current.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// btの親をチェック
|
||||||
|
current = bt;
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
if (atParents.Contains(current))
|
||||||
|
return current;
|
||||||
|
current = current.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在のシンメトリー設定に基づいて、シンメトリーのモードと対象を決定する
|
||||||
|
/// </summary>
|
||||||
|
internal void SetActiveSymmetryMode(bool firstOnly)
|
||||||
|
{
|
||||||
|
if (ActiveSymmetryMode.HasValue == false || firstOnly == false)
|
||||||
|
{
|
||||||
|
ActiveSymmetryMode = CalcSymmetryMode(out var target);
|
||||||
|
ActiveSymmetryTarget = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int UseTeamCount => teamIdSet.Count;
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
public void GetUsedTransform(HashSet<Transform> transformSet)
|
||||||
|
{
|
||||||
|
if (symmetryTarget)
|
||||||
|
transformSet.Add(symmetryTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
||||||
|
{
|
||||||
|
if (symmetryTarget)
|
||||||
|
{
|
||||||
|
int id = symmetryTarget.GetInstanceID();
|
||||||
|
if (id != 0 && replaceDict.ContainsKey(id))
|
||||||
|
symmetryTarget = replaceDict[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
protected virtual void Start()
|
protected virtual void Start()
|
||||||
{
|
{
|
||||||
|
SetActiveSymmetryMode(firstOnly: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnValidate()
|
protected virtual void OnValidate()
|
||||||
@ -138,7 +420,10 @@ namespace MagicaCloth2
|
|||||||
protected virtual void OnDestroy()
|
protected virtual void OnDestroy()
|
||||||
{
|
{
|
||||||
// コライダーを削除する
|
// コライダーを削除する
|
||||||
foreach (int teamId in teamIdSet)
|
if (teamIdSet.Count > 0)
|
||||||
|
{
|
||||||
|
var teamList = teamIdSet.ToList();
|
||||||
|
foreach (int teamId in teamList)
|
||||||
{
|
{
|
||||||
MagicaManager.Collider.RemoveCollider(this, teamId);
|
MagicaManager.Collider.RemoveCollider(this, teamId);
|
||||||
}
|
}
|
||||||
@ -146,3 +431,4 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -29,6 +29,12 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Direction direction = Direction.X;
|
public Direction direction = Direction.X;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reverse direction.
|
||||||
|
/// 方向を逆転させる
|
||||||
|
/// </summary>
|
||||||
|
public bool reverseDirection = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 半径をStart/End別々に設定
|
/// 半径をStart/End別々に設定
|
||||||
/// Set radius separately for Start/End.
|
/// Set radius separately for Start/End.
|
||||||
@ -86,12 +92,14 @@ namespace MagicaCloth2
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Vector3 GetLocalDir()
|
public Vector3 GetLocalDir()
|
||||||
{
|
{
|
||||||
|
float rev = reverseDirection ? -1 : 1;
|
||||||
|
|
||||||
if (direction == Direction.X)
|
if (direction == Direction.X)
|
||||||
return Vector3.right;
|
return Vector3.right * rev;
|
||||||
else if (direction == Direction.Y)
|
else if (direction == Direction.Y)
|
||||||
return Vector3.up;
|
return Vector3.up * rev;
|
||||||
else
|
else
|
||||||
return Vector3.forward;
|
return Vector3.forward * rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -108,6 +116,12 @@ namespace MagicaCloth2
|
|||||||
return Vector3.up;
|
return Vector3.up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 方向の逆転(基本的にカプセルコライダー用)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool IsReverseDirection() => reverseDirection;
|
||||||
|
|
||||||
public override void DataValidate()
|
public override void DataValidate()
|
||||||
{
|
{
|
||||||
size.x = Mathf.Max(size.x, 0.001f);
|
size.x = Mathf.Max(size.x, 0.001f);
|
||||||
|
|||||||
@ -3,9 +3,7 @@
|
|||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -188,14 +186,6 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
|
||||||
NativeArray<float> lengthBuffer;
|
|
||||||
NativeArray<float3> localPosBuffer;
|
|
||||||
NativeArray<quaternion> localRotBuffer;
|
|
||||||
NativeArray<quaternion> rotationBuffer;
|
|
||||||
NativeArray<float3> restorationVectorBuffer;
|
|
||||||
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public AngleConstraint()
|
public AngleConstraint()
|
||||||
{
|
{
|
||||||
@ -203,149 +193,46 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
lengthBuffer.DisposeSafe();
|
|
||||||
localPosBuffer.DisposeSafe();
|
|
||||||
localRotBuffer.DisposeSafe();
|
|
||||||
rotationBuffer.DisposeSafe();
|
|
||||||
restorationVectorBuffer.DisposeSafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void WorkBufferUpdate()
|
|
||||||
{
|
|
||||||
int pcnt = MagicaManager.Simulation.ParticleCount;
|
|
||||||
lengthBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory);
|
|
||||||
localPosBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory);
|
|
||||||
localRotBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory);
|
|
||||||
rotationBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory);
|
|
||||||
restorationVectorBuffer.Resize(pcnt, options: NativeArrayOptions.UninitializedMemory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.AppendLine($"[AngleConstraint]");
|
sb.AppendLine($"[AngleConstraint]");
|
||||||
sb.AppendLine($" -lengthBuffer:{(lengthBuffer.IsCreated ? lengthBuffer.Length : 0)}");
|
|
||||||
sb.AppendLine($" -localPosBuffer:{(localPosBuffer.IsCreated ? localPosBuffer.Length : 0)}");
|
|
||||||
sb.AppendLine($" -localRotBuffer:{(localRotBuffer.IsCreated ? localRotBuffer.Length : 0)}");
|
|
||||||
sb.AppendLine($" -rotationBuffer:{(rotationBuffer.IsCreated ? rotationBuffer.Length : 0)}");
|
|
||||||
sb.AppendLine($" -restorationVectorBuffer:{(restorationVectorBuffer.IsCreated ? restorationVectorBuffer.Length : 0)}");
|
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Solver
|
||||||
/// 制約の解決
|
//=========================================================================================
|
||||||
/// </summary>
|
internal static void SolverConstraint(
|
||||||
/// <param name="clothBase"></param>
|
DataChunk chunk,
|
||||||
/// <param name="jobHandle"></param>
|
in float4 simulationPower,
|
||||||
/// <returns></returns>
|
|
||||||
internal unsafe JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
|
|
||||||
// 角度復元と角度制限を1つに統合したもの
|
|
||||||
// 復元/制限ともにほぼMC1の移植。
|
|
||||||
// 他のアルゴリズムを散々テストした結果、MC1の動きが一番映えるという結論に至る。
|
|
||||||
// 微調整および堅牢性を上げるために反復回数を増やしている。
|
|
||||||
var job = new AngleConstraintJob()
|
|
||||||
{
|
|
||||||
simulationPower = MagicaManager.Time.SimulationPower,
|
|
||||||
|
|
||||||
stepBaseLineIndexArray = sm.processingStepBaseLine.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
vertexDepths = vm.vertexDepths.GetNativeArray(),
|
|
||||||
vertexParentIndices = vm.vertexParentIndices.GetNativeArray(),
|
|
||||||
baseLineStartDataIndices = vm.baseLineStartDataIndices.GetNativeArray(),
|
|
||||||
baseLineDataCounts = vm.baseLineDataCounts.GetNativeArray(),
|
|
||||||
baseLineData = vm.baseLineData.GetNativeArray(),
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
|
|
||||||
stepBasicPositionBuffer = sm.stepBasicPositionBuffer,
|
|
||||||
stepBasicRotationBuffer = sm.stepBasicRotationBuffer,
|
|
||||||
|
|
||||||
lengthBufferArray = lengthBuffer,
|
|
||||||
localPosBufferArray = localPosBuffer,
|
|
||||||
localRotBufferArray = localRotBuffer,
|
|
||||||
rotationBufferArray = rotationBuffer,
|
|
||||||
restorationVectorBufferArray = restorationVectorBuffer,
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(sm.processingStepBaseLine.GetJobSchedulePtr(), 2, jobHandle);
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct AngleConstraintJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
public float4 simulationPower;
|
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepBaseLineIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> vertexDepths,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<int> vertexParentIndices,
|
||||||
public NativeArray<float> vertexDepths;
|
ref NativeArray<ushort> baseLineStartDataIndices,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<ushort> baseLineDataCounts,
|
||||||
public NativeArray<int> vertexParentIndices;
|
ref NativeArray<ushort> baseLineData,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ushort> baseLineStartDataIndices;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ushort> baseLineDataCounts;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ushort> baseLineData;
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<float3> nextPosArray;
|
ref NativeArray<float3> velocityPosArray,
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float> frictionArray,
|
||||||
public NativeArray<float3> velocityPosArray;
|
// buffer
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> stepBasicPositionBuffer,
|
||||||
public NativeArray<float> frictionArray;
|
ref NativeArray<quaternion> stepBasicRotationBuffer,
|
||||||
|
// buffer2
|
||||||
// temp
|
ref NativeArray<float> lengthBufferArray,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> localPosBufferArray,
|
||||||
public NativeArray<float3> stepBasicPositionBuffer;
|
ref NativeArray<quaternion> localRotBufferArray,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<quaternion> rotationBufferArray,
|
||||||
public NativeArray<quaternion> stepBasicRotationBuffer;
|
ref NativeArray<float3> restorationVectorBufferArray
|
||||||
[NativeDisableParallelForRestriction]
|
)
|
||||||
public NativeArray<float> lengthBufferArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> localPosBufferArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<quaternion> localRotBufferArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<quaternion> rotationBufferArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> restorationVectorBufferArray;
|
|
||||||
|
|
||||||
// ベースラインごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
uint pack = (uint)stepBaseLineIndexArray[index];
|
|
||||||
int teamId = DataUtility.Unpack32Hi(pack);
|
|
||||||
int bindex = DataUtility.Unpack32Low(pack);
|
|
||||||
|
|
||||||
// チームは有効であることが保証されている
|
|
||||||
var tdata = teamDataArray[teamId];
|
|
||||||
var param = parameterArray[teamId];
|
|
||||||
var angleParam = param.angleConstraint;
|
var angleParam = param.angleConstraint;
|
||||||
if (angleParam.useAngleLimit == false && angleParam.useAngleRestoration == false)
|
if (angleParam.useAngleLimit == false && angleParam.useAngleRestoration == false)
|
||||||
return;
|
return;
|
||||||
@ -354,9 +241,6 @@ namespace MagicaCloth2
|
|||||||
int p_start = tdata.particleChunk.startIndex;
|
int p_start = tdata.particleChunk.startIndex;
|
||||||
int v_start = tdata.proxyCommonChunk.startIndex;
|
int v_start = tdata.proxyCommonChunk.startIndex;
|
||||||
|
|
||||||
int start = baseLineStartDataIndices[bindex];
|
|
||||||
int dcnt = baseLineDataCounts[bindex];
|
|
||||||
|
|
||||||
bool useAngleLimit = angleParam.useAngleLimit;
|
bool useAngleLimit = angleParam.useAngleLimit;
|
||||||
bool useAngleRestoration = angleParam.useAngleRestoration;
|
bool useAngleRestoration = angleParam.useAngleRestoration;
|
||||||
|
|
||||||
@ -371,6 +255,15 @@ namespace MagicaCloth2
|
|||||||
//float gravity = param.gravity;
|
//float gravity = param.gravity;
|
||||||
//float3 gravityVector = gravity > Define.System.Epsilon ? param.gravityDirection : 0;
|
//float3 gravityVector = gravity > Define.System.Epsilon ? param.gravityDirection : 0;
|
||||||
|
|
||||||
|
// ベースラインごと
|
||||||
|
//int bindex = tdata.baseLineChunk.startIndex;
|
||||||
|
int bindex = tdata.baseLineChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int a = 0; a < tdata.baseLineChunk.dataLength; a++, bindex++)
|
||||||
|
for (int a = 0; a < chunk.dataLength; a++, bindex++)
|
||||||
|
{
|
||||||
|
int start = baseLineStartDataIndices[bindex];
|
||||||
|
int dcnt = baseLineDataCounts[bindex];
|
||||||
|
|
||||||
// バッファリング
|
// バッファリング
|
||||||
int dataIndex = start + d_start;
|
int dataIndex = start + d_start;
|
||||||
for (int i = 0; i < dcnt; i++, dataIndex++)
|
for (int i = 0; i < dcnt; i++, dataIndex++)
|
||||||
@ -402,8 +295,21 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 親からの基本姿勢
|
// 親からの基本姿勢
|
||||||
var bv = bpos - pbpos;
|
var bv = bpos - pbpos;
|
||||||
Develop.Assert(math.length(bv) > 0.0f);
|
float bvlen = math.length(bv);
|
||||||
var v = math.normalize(bv);
|
if (vlen < Define.System.Epsilon || bvlen < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
// length=0
|
||||||
|
//Debug.Log($"NG1");
|
||||||
|
//エッジ長0対処
|
||||||
|
lengthBufferArray[pindex] = 0;
|
||||||
|
localPosBufferArray[pindex] = 0;
|
||||||
|
localRotBufferArray[pindex] = quaternion.identity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Develop.Assert(math.length(bv) > 0.0f);
|
||||||
|
//var v = math.normalize(bv);
|
||||||
|
var v = bv / bvlen;
|
||||||
var ipq = math.inverse(pbrot);
|
var ipq = math.inverse(pbrot);
|
||||||
float3 localPos = math.mul(ipq, v);
|
float3 localPos = math.mul(ipq, v);
|
||||||
quaternion localRot = math.mul(ipq, brot);
|
quaternion localRot = math.mul(ipq, brot);
|
||||||
@ -412,12 +318,14 @@ namespace MagicaCloth2
|
|||||||
localPosBufferArray[pindex] = localPos;
|
localPosBufferArray[pindex] = localPos;
|
||||||
localRotBufferArray[pindex] = localRot;
|
localRotBufferArray[pindex] = localRot;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (useAngleRestoration)
|
if (useAngleRestoration)
|
||||||
{
|
{
|
||||||
// 復元ベクトル
|
// 復元ベクトル
|
||||||
float3 rv = bpos - pbpos;
|
float3 rv = bpos - pbpos;
|
||||||
restorationVectorBufferArray[pindex] = rv;
|
restorationVectorBufferArray[pindex] = rv;
|
||||||
|
//Debug.Log($"[{pindex}] rv:{rv}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -478,19 +386,46 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 現在のベクトル
|
// 現在のベクトル
|
||||||
float3 v = cpos - ppos;
|
float3 v = cpos - ppos;
|
||||||
|
float vlen = math.length(v);
|
||||||
|
if (vlen < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
//エッジ長0対処
|
||||||
|
//Debug.Log($"NG2");
|
||||||
|
goto EndAngleLimit;
|
||||||
|
}
|
||||||
|
|
||||||
// 復元すべきベクトル
|
// 復元すべきベクトル
|
||||||
float3 tv = math.mul(prot, localPos);
|
float3 tv = math.mul(prot, localPos);
|
||||||
|
float tvlen = math.length(tv);
|
||||||
|
if (tvlen < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
//エッジ長0対処
|
||||||
|
//Debug.Log($"NG3");
|
||||||
|
float3 add = ppos - cpos;
|
||||||
|
nextPosArray[pindex] = ppos;
|
||||||
|
velocityPosArray[pindex] = velocityPosArray[pindex] + add;
|
||||||
|
rotationBufferArray[pindex] = math.mul(prot, localRot);
|
||||||
|
goto EndAngleLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
v /= vlen;
|
||||||
|
tv /= tvlen;
|
||||||
|
|
||||||
// ベクトル長修正
|
// ベクトル長修正
|
||||||
float vlen = math.length(v);
|
|
||||||
float blen = lengthBufferArray[pindex];
|
float blen = lengthBufferArray[pindex];
|
||||||
vlen = math.lerp(vlen, blen, 0.5f); // 計算前の距離に徐々に近づける
|
vlen = math.lerp(vlen, blen, 0.5f); // 計算前の距離に徐々に近づける
|
||||||
Develop.Assert(vlen > 0.0f);
|
if (blen < Define.System.Epsilon || vlen < Define.System.Epsilon)
|
||||||
v = math.normalize(v) * vlen;
|
{
|
||||||
|
//エッジ長0対処
|
||||||
|
//Debug.Log($"NG4");
|
||||||
|
goto EndAngleLimit;
|
||||||
|
}
|
||||||
|
//Develop.Assert(vlen > 0.0f);
|
||||||
|
//v = math.normalize(v) * vlen;
|
||||||
|
v = v * vlen;
|
||||||
|
|
||||||
// ベクトル角度クランプ
|
// ベクトル角度クランプ
|
||||||
float maxAngleDeg = angleParam.limitCurveData.EvaluateCurve(cdepth);
|
float maxAngleDeg = angleParam.limitCurveData.MC2EvaluateCurve(cdepth);
|
||||||
float maxAngleRad = math.radians(maxAngleDeg);
|
float maxAngleRad = math.radians(maxAngleDeg);
|
||||||
float angle = MathUtility.Angle(v, tv);
|
float angle = MathUtility.Angle(v, tv);
|
||||||
float3 rv = v;
|
float3 rv = v;
|
||||||
@ -537,12 +472,23 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 回転補正
|
// 回転補正
|
||||||
v = cpos - ppos;
|
v = cpos - ppos;
|
||||||
|
vlen = math.length(v);
|
||||||
|
if (vlen < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
//エッジ長0対処
|
||||||
|
//Debug.Log($"NG5");
|
||||||
|
goto EndAngleLimit;
|
||||||
|
}
|
||||||
|
v /= vlen;
|
||||||
var nrot = math.mul(prot, localRot);
|
var nrot = math.mul(prot, localRot);
|
||||||
var q = MathUtility.FromToRotation(tv, v);
|
//var q = MathUtility.FromToRotation(tv, v);
|
||||||
|
var q = MathUtility.FromToRotationWithoutNormalize(tv, v);
|
||||||
nrot = math.mul(q, nrot);
|
nrot = math.mul(q, nrot);
|
||||||
rotationBufferArray[pindex] = nrot;
|
rotationBufferArray[pindex] = nrot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EndAngleLimit:
|
||||||
|
|
||||||
//=====================================================
|
//=====================================================
|
||||||
// Angle Restoration
|
// Angle Restoration
|
||||||
//=====================================================
|
//=====================================================
|
||||||
@ -550,14 +496,31 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
//Debug.Log($"pindex:{pindex}, p_pindex:{p_pindex}");
|
//Debug.Log($"pindex:{pindex}, p_pindex:{p_pindex}");
|
||||||
|
|
||||||
// 現在のベクトル
|
|
||||||
float3 v = cpos - ppos;
|
|
||||||
|
|
||||||
// 復元すべきベクトル
|
// 復元すべきベクトル
|
||||||
float3 tv = restorationVectorBufferArray[pindex];
|
float3 tv = restorationVectorBufferArray[pindex];
|
||||||
|
float tvlen = math.length(tv);
|
||||||
|
if (tvlen < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
//エッジ長0対処
|
||||||
|
//Debug.Log($"NG6");
|
||||||
|
float3 add = ppos - cpos;
|
||||||
|
nextPosArray[pindex] = ppos;
|
||||||
|
velocityPosArray[pindex] = velocityPosArray[pindex] + add;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 現在のベクトル
|
||||||
|
float3 v = cpos - ppos;
|
||||||
|
float vlen = math.length(v);
|
||||||
|
if (vlen < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
//エッジ長0対処
|
||||||
|
//Debug.Log($"NG7");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 復元力
|
// 復元力
|
||||||
float restorationStiffness = angleParam.restorationStiffness.EvaluateCurveClamp01(cdepth);
|
float restorationStiffness = angleParam.restorationStiffness.MC2EvaluateCurveClamp01(cdepth);
|
||||||
restorationStiffness = math.saturate(restorationStiffness * simulationPower.w);
|
restorationStiffness = math.saturate(restorationStiffness * simulationPower.w);
|
||||||
|
|
||||||
//int _pindex = indexBuffer[i] + p_start;
|
//int _pindex = indexBuffer[i] + p_start;
|
||||||
@ -567,7 +530,7 @@ namespace MagicaCloth2
|
|||||||
restorationStiffness *= gravityFalloff;
|
restorationStiffness *= gravityFalloff;
|
||||||
|
|
||||||
// 球面線形補間
|
// 球面線形補間
|
||||||
var q = MathUtility.FromToRotation(v, tv, restorationStiffness);
|
var q = MathUtility.FromToRotationWithoutNormalize(v / vlen, tv / tvlen, restorationStiffness);
|
||||||
float3 rv = math.mul(q, v);
|
float3 rv = math.mul(q, v);
|
||||||
|
|
||||||
// 回転中心割合
|
// 回転中心割合
|
||||||
@ -607,6 +570,25 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// バッファクリア
|
||||||
|
bindex = tdata.baseLineChunk.startIndex + chunk.startIndex;
|
||||||
|
for (int a = 0; a < chunk.dataLength; a++, bindex++)
|
||||||
|
{
|
||||||
|
int start = baseLineStartDataIndices[bindex];
|
||||||
|
int dcnt = baseLineDataCounts[bindex];
|
||||||
|
|
||||||
|
int dataIndex = start + d_start;
|
||||||
|
for (int i = 0; i < dcnt; i++, dataIndex++)
|
||||||
|
{
|
||||||
|
int l_index = baseLineData[dataIndex];
|
||||||
|
int pindex = p_start + l_index;
|
||||||
|
|
||||||
|
lengthBufferArray[pindex] = 0;
|
||||||
|
localPosBufferArray[pindex] = 0;
|
||||||
|
restorationVectorBufferArray[pindex] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Collections.LowLevel.Unsafe;
|
using Unity.Collections.LowLevel.Unsafe;
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -113,6 +111,11 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void GetUsedTransform(HashSet<Transform> transformSet)
|
public void GetUsedTransform(HashSet<Transform> transformSet)
|
||||||
{
|
{
|
||||||
|
colliderList.ForEach(x =>
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
x.GetUsedTransform(transformSet);
|
||||||
|
});
|
||||||
foreach (var t in collisionBones)
|
foreach (var t in collisionBones)
|
||||||
{
|
{
|
||||||
if (t)
|
if (t)
|
||||||
@ -122,6 +125,11 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
||||||
{
|
{
|
||||||
|
colliderList.ForEach(x =>
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
x.ReplaceTransform(replaceDict);
|
||||||
|
});
|
||||||
for (int i = 0; i < collisionBones.Count; i++)
|
for (int i = 0; i < collisionBones.Count; i++)
|
||||||
{
|
{
|
||||||
var t = collisionBones[i];
|
var t = collisionBones[i];
|
||||||
@ -184,9 +192,6 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeArray<int> tempFrictionArray;
|
|
||||||
NativeArray<int> tempNormalArray;
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public ColliderCollisionConstraint()
|
public ColliderCollisionConstraint()
|
||||||
{
|
{
|
||||||
@ -195,211 +200,69 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
tempFrictionArray.DisposeSafe();
|
|
||||||
tempNormalArray.DisposeSafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 作業バッファ更新
|
|
||||||
/// </summary>
|
|
||||||
internal void WorkBufferUpdate()
|
|
||||||
{
|
|
||||||
int cnt = MagicaManager.Team.edgeColliderCollisionCount;
|
|
||||||
if (cnt == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int pcnt = MagicaManager.Simulation.ParticleCount;
|
|
||||||
tempFrictionArray.Resize(pcnt);
|
|
||||||
tempNormalArray.Resize(pcnt * 3);
|
|
||||||
//if (tempFrictionArray.IsCreated == false || tempFrictionArray.Length < pcnt)
|
|
||||||
//{
|
|
||||||
// if (tempFrictionArray.IsCreated)
|
|
||||||
// tempFrictionArray.Dispose();
|
|
||||||
// tempFrictionArray = new NativeArray<int>(pcnt, Allocator.Persistent);
|
|
||||||
//}
|
|
||||||
//if (tempNormalArray.IsCreated == false || tempNormalArray.Length < pcnt * 3)
|
|
||||||
//{
|
|
||||||
// if (tempNormalArray.IsCreated)
|
|
||||||
// tempNormalArray.Dispose();
|
|
||||||
// tempNormalArray = new NativeArray<int>(pcnt * 3, Allocator.Persistent);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.AppendLine($"[ColliderCollisionConstraint]");
|
sb.AppendLine($"[ColliderCollisionConstraint]");
|
||||||
sb.AppendLine($" -tempFrictionArray:{(tempFrictionArray.IsCreated ? tempFrictionArray.Length : 0)}");
|
|
||||||
sb.AppendLine($" -tempNormalArray:{(tempNormalArray.IsCreated ? tempNormalArray.Length : 0)}");
|
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Point Solver
|
||||||
/// 制約の解決
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="clothBase"></param>
|
|
||||||
/// <param name="jobHandle"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
unsafe internal JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
var cm = MagicaManager.Collider;
|
|
||||||
|
|
||||||
// Point
|
|
||||||
var job = new PointColliderCollisionConstraintJob()
|
|
||||||
{
|
|
||||||
stepParticleIndexArray = sm.processingStepParticle.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
vertexDepths = vm.vertexDepths.GetNativeArray(),
|
|
||||||
|
|
||||||
teamIdArray = sm.teamIdArray.GetNativeArray(),
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
collisionNormalArray = sm.collisionNormalArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
basePosArray = sm.basePosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
colliderFlagArray = cm.flagArray.GetNativeArray(),
|
|
||||||
colliderWorkDataArray = cm.workDataArray.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle);
|
|
||||||
|
|
||||||
// Edge
|
|
||||||
if (tm.edgeColliderCollisionCount > 0)
|
|
||||||
{
|
|
||||||
var job2 = new EdgeColliderCollisionConstraintJob()
|
|
||||||
{
|
|
||||||
stepEdgeCollisionIndexArray = sm.processingStepEdgeCollision.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
vertexDepths = vm.vertexDepths.GetNativeArray(),
|
|
||||||
edgeTeamIdArray = vm.edgeTeamIdArray.GetNativeArray(),
|
|
||||||
edges = vm.edges.GetNativeArray(),
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
collisionNormalArray = sm.collisionNormalArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
colliderFlagArray = cm.flagArray.GetNativeArray(),
|
|
||||||
colliderWorkDataArray = cm.workDataArray.GetNativeArray(),
|
|
||||||
|
|
||||||
countArray = sm.countArray,
|
|
||||||
sumArray = sm.sumArray,
|
|
||||||
tempFrictionArray = tempFrictionArray,
|
|
||||||
tempNormalArray = tempNormalArray,
|
|
||||||
};
|
|
||||||
jobHandle = job2.Schedule(sm.processingStepEdgeCollision.GetJobSchedulePtr(), 32, jobHandle);
|
|
||||||
|
|
||||||
// 集計
|
|
||||||
var job3 = new SolveEdgeBufferAndClearJob()
|
|
||||||
{
|
|
||||||
jobParticleIndexList = sm.processingStepParticle.Buffer,
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
collisionNormalArray = sm.collisionNormalArray.GetNativeArray(),
|
|
||||||
|
|
||||||
countArray = sm.countArray,
|
|
||||||
sumArray = sm.sumArray,
|
|
||||||
tempFrictionArray = tempFrictionArray,
|
|
||||||
tempNormalArray = tempNormalArray,
|
|
||||||
};
|
|
||||||
jobHandle = job3.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
internal static void SolverPointConstraint(
|
||||||
/// Pointコライダー衝突判定
|
DataChunk chunk,
|
||||||
/// </summary>
|
|
||||||
[BurstCompile]
|
|
||||||
struct PointColliderCollisionConstraintJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepParticleIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> vertexDepths,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> vertexDepths;
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<short> teamIdArray;
|
ref NativeArray<float> frictionArray,
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float3> collisionNormalArray,
|
||||||
public NativeArray<float3> nextPosArray;
|
ref NativeArray<float3> velocityPosArray,
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float3> basePosArray,
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> collisionNormalArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> basePosArray;
|
|
||||||
|
|
||||||
// collider
|
// collider
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<ExBitFlag16> colliderFlagArray,
|
||||||
public NativeArray<ExBitFlag8> colliderFlagArray;
|
ref NativeArray<ColliderManager.WorkData> colliderWorkDataArray
|
||||||
[Unity.Collections.ReadOnly]
|
)
|
||||||
public NativeArray<ColliderManager.WorkData> colliderWorkDataArray;
|
|
||||||
|
|
||||||
// ステップ実行パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
// このパーティクルは有効であることが保証されている
|
if (tdata.UseColliderCount == 0)
|
||||||
int pindex = stepParticleIndexArray[index];
|
return;
|
||||||
int teamId = teamIdArray[pindex];
|
if (param.colliderCollisionConstraint.mode != Mode.Point)
|
||||||
var tdata = teamDataArray[teamId];
|
return;
|
||||||
if (tdata.colliderCount == 0)
|
if (chunk.IsValid == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// パラメータ
|
bool isSpring = tdata.IsSpring;
|
||||||
var param = parameterArray[teamId];
|
|
||||||
|
|
||||||
// モード判定
|
|
||||||
var mode = param.colliderCollisionConstraint.mode;
|
|
||||||
if (mode != Mode.Point)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
// ■Point
|
||||||
|
// パーティクルごと
|
||||||
|
//int pindex = tdata.particleChunk.startIndex;
|
||||||
|
//int vindex = tdata.proxyCommonChunk.startIndex;
|
||||||
|
int pindex = tdata.particleChunk.startIndex + chunk.startIndex;
|
||||||
|
int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
{
|
||||||
// パーティクル情報
|
// パーティクル情報
|
||||||
var nextPos = nextPosArray[pindex];
|
var nextPos = nextPosArray[pindex];
|
||||||
int l_index = pindex - tdata.particleChunk.startIndex;
|
|
||||||
int vindex = tdata.proxyCommonChunk.startIndex + l_index;
|
|
||||||
var attr = attributes[vindex];
|
var attr = attributes[vindex];
|
||||||
if (attr.IsInvalid() || attr.IsDisableCollision())
|
if (attr.IsInvalid() || attr.IsDisableCollision())
|
||||||
return;
|
continue;
|
||||||
if (attr.IsMove() == false && tdata.IsSpring == false) // スプリング利用時は固定頂点も通す
|
if (attr.IsMove() == false && tdata.IsSpring == false) // スプリング利用時は固定頂点も通す
|
||||||
return;
|
continue;
|
||||||
float depth = vertexDepths[vindex];
|
float depth = vertexDepths[vindex];
|
||||||
|
|
||||||
// BoneSpringでは自動的にソフトコライダーとなる
|
// BoneSpringでは自動的にソフトコライダーとなる
|
||||||
bool isSpring = tdata.IsSpring;
|
|
||||||
var basePos = isSpring ? basePosArray[pindex] : float3.zero; // ソフトコライダーのみbasePosが必要
|
var basePos = isSpring ? basePosArray[pindex] : float3.zero; // ソフトコライダーのみbasePosが必要
|
||||||
|
|
||||||
// パーティクル半径
|
// パーティクル半径
|
||||||
float radius = math.max(param.radiusCurveData.EvaluateCurve(depth), 0.0001f); // safe;
|
float radius = math.max(param.radiusCurveData.MC2EvaluateCurve(depth), 0.0001f); // safe;
|
||||||
|
|
||||||
// チームスケール倍率
|
// チームスケール倍率
|
||||||
radius *= tdata.scaleRatio;
|
radius *= tdata.scaleRatio;
|
||||||
@ -426,7 +289,7 @@ namespace MagicaCloth2
|
|||||||
aabb.Expand(cfr);
|
aabb.Expand(cfr);
|
||||||
|
|
||||||
// BoneSpringでの最大押し出し距離
|
// BoneSpringでの最大押し出し距離
|
||||||
float maxLength = isSpring ? math.max(param.colliderCollisionConstraint.limitDistance.EvaluateCurve(depth), 0.0001f) * tdata.scaleRatio : -1; // チームスケール倍率
|
float maxLength = isSpring ? math.max(param.colliderCollisionConstraint.limitDistance.MC2EvaluateCurve(depth), 0.0001f) * tdata.scaleRatio : -1; // チームスケール倍率
|
||||||
|
|
||||||
// チーム内のコライダーをループ
|
// チーム内のコライダーをループ
|
||||||
int cindex = tdata.colliderChunk.startIndex;
|
int cindex = tdata.colliderChunk.startIndex;
|
||||||
@ -447,7 +310,6 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
case ColliderManager.ColliderType.Sphere:
|
case ColliderManager.ColliderType.Sphere:
|
||||||
// ソフトコライダーはSphereのみ
|
// ソフトコライダーはSphereのみ
|
||||||
//dist = PointSphereColliderDetection(ref _nextPos, basePos, radius, aabb, cwork, maxLength, out n);
|
|
||||||
dist = PointSphereColliderDetection(ref _nextPos, basePos, radius, aabb, cwork, isSpring, maxLength, out n);
|
dist = PointSphereColliderDetection(ref _nextPos, basePos, radius, aabb, cwork, isSpring, maxLength, out n);
|
||||||
break;
|
break;
|
||||||
case ColliderManager.ColliderType.CapsuleX_Center:
|
case ColliderManager.ColliderType.CapsuleX_Center:
|
||||||
@ -473,6 +335,7 @@ namespace MagicaCloth2
|
|||||||
addPos += (_nextPos - nextPos);
|
addPos += (_nextPos - nextPos);
|
||||||
addN += n;
|
addN += n;
|
||||||
addCnt++;
|
addCnt++;
|
||||||
|
//Debug.Log($"Collision!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// コライダーに一定距離近づいている場合(動摩擦/静止摩擦が影響する)
|
// コライダーに一定距離近づいている場合(動摩擦/静止摩擦が影響する)
|
||||||
@ -531,17 +394,18 @@ namespace MagicaCloth2
|
|||||||
velocityPosArray[pindex] = velocityPosArray[pindex] + addPos;
|
velocityPosArray[pindex] = velocityPosArray[pindex] + addPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
static float PointSphereColliderDetection(
|
||||||
/// Point球衝突判定
|
ref float3 nextpos,
|
||||||
/// </summary>
|
in float3 basePos,
|
||||||
/// <param name="nextpos"></param>
|
float radius,
|
||||||
/// <param name="pos"></param>
|
in AABB aabb,
|
||||||
/// <param name="radius"></param>
|
in ColliderManager.WorkData cwork,
|
||||||
/// <param name="cindex"></param>
|
bool isSpring,
|
||||||
/// <param name="friction"></param>
|
float maxLength,
|
||||||
/// <returns></returns>
|
out float3 normal
|
||||||
float PointSphereColliderDetection(ref float3 nextpos, in float3 basePos, float radius, in AABB aabb, in ColliderManager.WorkData cwork, bool isSpring, float maxLength, out float3 normal)
|
)
|
||||||
{
|
{
|
||||||
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
||||||
normal = 0;
|
normal = 0;
|
||||||
@ -599,15 +463,12 @@ namespace MagicaCloth2
|
|||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
static float PointPlaneColliderDetction(
|
||||||
/// Point平面衝突判定(無限平面)
|
ref float3 nextpos,
|
||||||
/// </summary>
|
float radius,
|
||||||
/// <param name="nextpos"></param>
|
in ColliderManager.WorkData cwork,
|
||||||
/// <param name="radius"></param>
|
out float3 normal
|
||||||
/// <param name="cindex"></param>
|
)
|
||||||
/// <param name="normal"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
float PointPlaneColliderDetction(ref float3 nextpos, float radius, in ColliderManager.WorkData cwork, out float3 normal)
|
|
||||||
{
|
{
|
||||||
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
||||||
|
|
||||||
@ -625,17 +486,13 @@ namespace MagicaCloth2
|
|||||||
return MathUtility.IntersectPointPlaneDist(cpos + n * radius, n, nextpos, out nextpos);
|
return MathUtility.IntersectPointPlaneDist(cpos + n * radius, n, nextpos, out nextpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
static float PointCapsuleColliderDetection(
|
||||||
/// Pointカプセル衝突判定
|
ref float3 nextpos,
|
||||||
/// </summary>
|
float radius,
|
||||||
/// <param name="nextpos"></param>
|
in AABB aabb,
|
||||||
/// <param name="pos"></param>
|
in ColliderManager.WorkData cwork,
|
||||||
/// <param name="radius"></param>
|
out float3 normal
|
||||||
/// <param name="cindex"></param>
|
)
|
||||||
/// <param name="dir"></param>
|
|
||||||
/// <param name="friction"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
float PointCapsuleColliderDetection(ref float3 nextpos, float radius, in AABB aabb, in ColliderManager.WorkData cwork, out float3 normal)
|
|
||||||
{
|
{
|
||||||
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
||||||
normal = 0;
|
normal = 0;
|
||||||
@ -681,92 +538,65 @@ namespace MagicaCloth2
|
|||||||
// 平面衝突判定と押し出し
|
// 平面衝突判定と押し出し
|
||||||
return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos);
|
return MathUtility.IntersectPointPlaneDist(c, n, nextpos, out nextpos);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Edge Solver
|
||||||
/// Edgeコライダー衝突判定
|
//=========================================================================================
|
||||||
/// </summary>
|
internal unsafe static void SolverEdgeConstraint(
|
||||||
[BurstCompile]
|
DataChunk chunk,
|
||||||
unsafe struct EdgeColliderCollisionConstraintJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepEdgeCollisionIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> vertexDepths,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<int2> edges,
|
||||||
public NativeArray<float> vertexDepths;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<short> edgeTeamIdArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int2> edges;
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> collisionNormalArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
|
|
||||||
// collider
|
// collider
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<ExBitFlag16> colliderFlagArray,
|
||||||
public NativeArray<ExBitFlag8> colliderFlagArray;
|
ref NativeArray<ColliderManager.WorkData> colliderWorkDataArray,
|
||||||
[Unity.Collections.ReadOnly]
|
// buffer2
|
||||||
public NativeArray<ColliderManager.WorkData> colliderWorkDataArray;
|
ref NativeArray<float3> tempVectorBufferA,
|
||||||
|
ref NativeArray<float3> tempVectorBufferB,
|
||||||
// output
|
ref NativeArray<int> tempCountBuffer,
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float> tempFloatBufferA
|
||||||
public NativeArray<int> countArray;
|
)
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> sumArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> tempFrictionArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> tempNormalArray;
|
|
||||||
|
|
||||||
// ステップ実行エッジごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
// このエッジは有効であることが保証されている
|
if (tdata.UseColliderCount == 0)
|
||||||
int eindex = stepEdgeCollisionIndexArray[index];
|
return;
|
||||||
int teamId = edgeTeamIdArray[eindex];
|
if (param.colliderCollisionConstraint.mode != Mode.Edge)
|
||||||
var tdata = teamDataArray[teamId];
|
return;
|
||||||
if (tdata.colliderCount == 0)
|
if (chunk.IsValid == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// パラメータ
|
// ■Edge
|
||||||
var param = parameterArray[teamId];
|
int* vecAPt = (int*)tempVectorBufferA.GetUnsafePtr();
|
||||||
|
int* vecBPt = (int*)tempVectorBufferB.GetUnsafePtr();
|
||||||
|
int* cntPt = (int*)tempCountBuffer.GetUnsafePtr();
|
||||||
|
int* floatPt = (int*)tempFloatBufferA.GetUnsafePtr();
|
||||||
|
|
||||||
// モード判定
|
// ■計算
|
||||||
var mode = param.colliderCollisionConstraint.mode;
|
// エッジごと
|
||||||
if (mode != Mode.Edge)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// エッジ情報
|
|
||||||
int vstart = tdata.proxyCommonChunk.startIndex;
|
int vstart = tdata.proxyCommonChunk.startIndex;
|
||||||
|
//int eindex = tdata.proxyEdgeChunk.startIndex;
|
||||||
|
int eindex = tdata.proxyEdgeChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.proxyEdgeChunk.dataLength; k++, eindex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, eindex++)
|
||||||
|
{
|
||||||
|
// エッジ情報
|
||||||
int2 edge = edges[eindex];
|
int2 edge = edges[eindex];
|
||||||
int2 vE = edge + vstart;
|
int2 vE = edge + vstart;
|
||||||
var attrE0 = attributes[vE.x];
|
var attrE0 = attributes[vE.x];
|
||||||
var attrE1 = attributes[vE.y];
|
var attrE1 = attributes[vE.y];
|
||||||
// 両方とも固定なら不要
|
// 両方とも固定なら不要
|
||||||
if (attrE0.IsMove() == false && attrE1.IsMove() == false)
|
if (attrE0.IsMove() == false && attrE1.IsMove() == false)
|
||||||
return;
|
continue;
|
||||||
int pstart = tdata.particleChunk.startIndex;
|
int pstart = tdata.particleChunk.startIndex;
|
||||||
int2 pE = edge + pstart;
|
int2 pE = edge + pstart;
|
||||||
float3x2 nextPosE = new float3x2(nextPosArray[pE.x], nextPosArray[pE.y]);
|
float3x2 nextPosE = new float3x2(nextPosArray[pE.x], nextPosArray[pE.y]);
|
||||||
float2 depthE = new float2(vertexDepths[vE.x], vertexDepths[vE.y]);
|
float2 depthE = new float2(vertexDepths[vE.x], vertexDepths[vE.y]);
|
||||||
float2 radiusE = new float2(param.radiusCurveData.EvaluateCurve(depthE.x), param.radiusCurveData.EvaluateCurve(depthE.y));
|
float2 radiusE = new float2(param.radiusCurveData.MC2EvaluateCurve(depthE.x), param.radiusCurveData.MC2EvaluateCurve(depthE.y));
|
||||||
|
|
||||||
// チームスケール倍率
|
// チームスケール倍率
|
||||||
radiusE *= tdata.scaleRatio;
|
radiusE *= tdata.scaleRatio;
|
||||||
@ -781,12 +611,6 @@ namespace MagicaCloth2
|
|||||||
float3 collisionNormal = 0;
|
float3 collisionNormal = 0;
|
||||||
float3 n = 0;
|
float3 n = 0;
|
||||||
|
|
||||||
// 書き込みポインタ
|
|
||||||
int* cntPt = (int*)countArray.GetUnsafePtr();
|
|
||||||
int* sumPt = (int*)sumArray.GetUnsafePtr();
|
|
||||||
int* frictionPt = (int*)tempFrictionArray.GetUnsafePtr();
|
|
||||||
int* normalPt = (int*)tempNormalArray.GetUnsafePtr();
|
|
||||||
|
|
||||||
// エッジAABB
|
// エッジAABB
|
||||||
var aabbE = new AABB(nextPosE.c0 - radiusE.x, nextPosE.c0 + radiusE.x);
|
var aabbE = new AABB(nextPosE.c0 - radiusE.x, nextPosE.c0 + radiusE.x);
|
||||||
var aabbE1 = new AABB(nextPosE.c1 - radiusE.y, nextPosE.c1 + radiusE.y);
|
var aabbE1 = new AABB(nextPosE.c1 - radiusE.y, nextPosE.c1 + radiusE.y);
|
||||||
@ -868,8 +692,8 @@ namespace MagicaCloth2
|
|||||||
addPos *= t;
|
addPos *= t;
|
||||||
|
|
||||||
// 書き戻し
|
// 書き戻し
|
||||||
InterlockUtility.AddFloat3(pE.x, addPos.c0, cntPt, sumPt);
|
InterlockUtility.AddFloat3(pE.x, addPos.c0, cntPt, vecAPt);
|
||||||
InterlockUtility.AddFloat3(pE.y, addPos.c1, cntPt, sumPt);
|
InterlockUtility.AddFloat3(pE.y, addPos.c1, cntPt, vecAPt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,20 +705,99 @@ namespace MagicaCloth2
|
|||||||
var friction = 1.0f - math.saturate(mindist / cfr);
|
var friction = 1.0f - math.saturate(mindist / cfr);
|
||||||
|
|
||||||
// 大きい場合のみ上書き
|
// 大きい場合のみ上書き
|
||||||
InterlockUtility.Max(pE.x, friction, frictionPt);
|
InterlockUtility.Max(pE.x, friction, floatPt);
|
||||||
InterlockUtility.Max(pE.y, friction, frictionPt);
|
InterlockUtility.Max(pE.y, friction, floatPt);
|
||||||
|
|
||||||
// 摩擦用接触法線平均化
|
// 摩擦用接触法線平均化
|
||||||
//Develop.Assert(math.length(collisionNormal) > 0.0f);
|
//Develop.Assert(math.length(collisionNormal) > 0.0f);
|
||||||
collisionNormal = math.normalize(collisionNormal);
|
collisionNormal = math.normalize(collisionNormal);
|
||||||
|
|
||||||
// 接触法線集計(すべて加算する)
|
// 接触法線集計(すべて加算する)
|
||||||
InterlockUtility.AddFloat3(pE.x, collisionNormal, normalPt);
|
InterlockUtility.AddFloat3(pE.x, collisionNormal, vecBPt);
|
||||||
InterlockUtility.AddFloat3(pE.y, collisionNormal, normalPt);
|
InterlockUtility.AddFloat3(pE.y, collisionNormal, vecBPt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float EdgeSphereColliderDetection(ref float3x2 nextPosE, in float2 radiusE, in AABB aabbE, float cfr, in ColliderManager.WorkData cwork, out float3 normal)
|
internal unsafe static void SumEdgeConstraint(
|
||||||
|
DataChunk chunk,
|
||||||
|
// team
|
||||||
|
ref TeamManager.TeamData tdata,
|
||||||
|
ref ClothParameters param,
|
||||||
|
// particle
|
||||||
|
ref NativeArray<float3> nextPosArray,
|
||||||
|
ref NativeArray<float> frictionArray,
|
||||||
|
ref NativeArray<float3> collisionNormalArray,
|
||||||
|
// buffer2
|
||||||
|
ref NativeArray<float3> tempVectorBufferA,
|
||||||
|
ref NativeArray<float3> tempVectorBufferB,
|
||||||
|
ref NativeArray<int> tempCountBuffer,
|
||||||
|
ref NativeArray<float> tempFloatBufferA
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tdata.UseColliderCount == 0)
|
||||||
|
return;
|
||||||
|
if (param.colliderCollisionConstraint.mode != Mode.Edge)
|
||||||
|
return;
|
||||||
|
if (chunk.IsValid == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ■Edge
|
||||||
|
int* vecAPt = (int*)tempVectorBufferA.GetUnsafePtr();
|
||||||
|
int* vecBPt = (int*)tempVectorBufferB.GetUnsafePtr();
|
||||||
|
int* cntPt = (int*)tempCountBuffer.GetUnsafePtr();
|
||||||
|
int* floatPt = (int*)tempFloatBufferA.GetUnsafePtr();
|
||||||
|
|
||||||
|
// ■集計
|
||||||
|
// パーティクルごと
|
||||||
|
//int pindex = tdata.particleChunk.startIndex;
|
||||||
|
//int vindex = tdata.proxyCommonChunk.startIndex;
|
||||||
|
int pindex = tdata.particleChunk.startIndex + chunk.startIndex;
|
||||||
|
int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
{
|
||||||
|
// nextpos
|
||||||
|
int count = tempCountBuffer[pindex];
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
float3 add = InterlockUtility.ReadAverageFloat3(pindex, cntPt, vecAPt);
|
||||||
|
|
||||||
|
// 書き出し
|
||||||
|
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
||||||
|
}
|
||||||
|
|
||||||
|
// friction
|
||||||
|
float f = InterlockUtility.ReadFloat(pindex, floatPt);
|
||||||
|
if (f > 0.0f && f > frictionArray[pindex])
|
||||||
|
{
|
||||||
|
frictionArray[pindex] = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collision normal
|
||||||
|
float3 n = InterlockUtility.ReadFloat3(pindex, vecBPt);
|
||||||
|
if (math.lengthsq(n) > 0.0f)
|
||||||
|
{
|
||||||
|
n = math.normalize(n);
|
||||||
|
collisionNormalArray[pindex] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// バッファクリア
|
||||||
|
tempVectorBufferA[pindex] = 0;
|
||||||
|
tempVectorBufferB[pindex] = 0;
|
||||||
|
tempCountBuffer[pindex] = 0;
|
||||||
|
tempFloatBufferA[pindex] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float EdgeSphereColliderDetection(
|
||||||
|
ref float3x2 nextPosE,
|
||||||
|
in float2 radiusE,
|
||||||
|
in AABB aabbE,
|
||||||
|
float cfr,
|
||||||
|
in ColliderManager.WorkData cwork,
|
||||||
|
out float3 normal
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
||||||
normal = 0;
|
normal = 0;
|
||||||
@ -989,7 +892,14 @@ namespace MagicaCloth2
|
|||||||
return -C;
|
return -C;
|
||||||
}
|
}
|
||||||
|
|
||||||
float EdgeCapsuleColliderDetection(ref float3x2 nextPosE, in float2 radiusE, in AABB aabbE, float cfr, in ColliderManager.WorkData cwork, out float3 normal)
|
static float EdgeCapsuleColliderDetection(
|
||||||
|
ref float3x2 nextPosE,
|
||||||
|
in float2 radiusE,
|
||||||
|
in AABB aabbE,
|
||||||
|
float cfr,
|
||||||
|
in ColliderManager.WorkData cwork,
|
||||||
|
out float3 normal
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
||||||
normal = 0;
|
normal = 0;
|
||||||
@ -1021,10 +931,37 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 押出法線
|
// 押出法線
|
||||||
var v = cA - cB;
|
var v = cA - cB;
|
||||||
Develop.Assert(math.length(v) > 0.0f);
|
float3 n = v / clen;
|
||||||
float3 n = math.normalize(v);
|
|
||||||
normal = n;
|
normal = n;
|
||||||
|
|
||||||
|
#if !MC2_DISABLE_EDGE_COLLISION_EXTENSION
|
||||||
|
// ★カプセル半径を考慮した補正
|
||||||
|
// これまでのエッジ-カプセル判定はカプセルの半径が始点と終点で同じであることが前提となっていた
|
||||||
|
// そのためカプセルの始点と終点の半径が異なると間違った衝突判定が行われてしまい、それが原因で大きな振動が発生していた
|
||||||
|
// (これはBoneClothのようにカプセルエッジよりメッシュエッジのほうが長い場合に顕著になる)
|
||||||
|
// そこで始点と終点の半径が異なる場合は、最初の計算の最近接点方向からカプセルエッジを半径分シフトし、
|
||||||
|
// それをもとに再度エッジ-エッジ判定を行うように修正した
|
||||||
|
// これは完璧ではないがおおよそ理想的な判定を行うようになり、また振動の問題も大幅に解決できる
|
||||||
|
// (ただし小刻みな振動はまだ発生することがある)
|
||||||
|
if (sr != er)
|
||||||
|
{
|
||||||
|
// 押し出し法線方向にカプセル半径を考慮してカプセルの中心線をシフトさせる
|
||||||
|
float3 soldpos2 = soldpos + n * sr;
|
||||||
|
float3 eoldpos2 = eoldpos + n * er;
|
||||||
|
|
||||||
|
// この線分で再び最近接点(s/t)を計算する
|
||||||
|
MathUtility.ClosestPtSegmentSegment2(nextPosE.c0, nextPosE.c1, soldpos2, eoldpos2, out s, out t);
|
||||||
|
|
||||||
|
// 最終的にはこのシフト後のsとtを利用するように結果を書き換える
|
||||||
|
cA = math.lerp(nextPosE.c0, nextPosE.c1, s);
|
||||||
|
cB = math.lerp(soldpos, eoldpos, t);
|
||||||
|
v = cA - cB;
|
||||||
|
clen = math.length(v);
|
||||||
|
n = v / clen;
|
||||||
|
normal = n;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 変位
|
// 変位
|
||||||
float3 dB0 = spos - soldpos;
|
float3 dB0 = spos - soldpos;
|
||||||
float3 dB1 = epos - eoldpos;
|
float3 dB1 = epos - eoldpos;
|
||||||
@ -1094,7 +1031,12 @@ namespace MagicaCloth2
|
|||||||
return -C;
|
return -C;
|
||||||
}
|
}
|
||||||
|
|
||||||
float EdgePlaneColliderDetection(ref float3x2 nextPosE, in float2 radiusE, in ColliderManager.WorkData cwork, out float3 normal)
|
static float EdgePlaneColliderDetection(
|
||||||
|
ref float3x2 nextPosE,
|
||||||
|
in float2 radiusE,
|
||||||
|
in ColliderManager.WorkData cwork,
|
||||||
|
out float3 normal
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
// ★たとえ接触していなくともコライダーまでの距離と法線を返さなければならない!
|
||||||
|
|
||||||
@ -1115,82 +1057,4 @@ namespace MagicaCloth2
|
|||||||
return math.min(dist0, dist1);
|
return math.min(dist0, dist1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// エッジコライダーコリジョン結果の集計
|
|
||||||
/// </summary>
|
|
||||||
[BurstCompile]
|
|
||||||
struct SolveEdgeBufferAndClearJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> jobParticleIndexList;
|
|
||||||
|
|
||||||
// particle
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> collisionNormalArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
|
|
||||||
// aggregate
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> countArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> sumArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> tempFrictionArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> tempNormalArray;
|
|
||||||
|
|
||||||
// ステップ有効パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int pindex = jobParticleIndexList[index];
|
|
||||||
|
|
||||||
// nextpos
|
|
||||||
int count = countArray[pindex];
|
|
||||||
int dataIndex = pindex * 3;
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
float3 add = InterlockUtility.ReadAverageFloat3(pindex, countArray, sumArray);
|
|
||||||
|
|
||||||
// 書き出し
|
|
||||||
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
|
||||||
|
|
||||||
// 速度影響
|
|
||||||
//float attn = param.colliderCollisionConstraint.colliderVelocityAttenuation;
|
|
||||||
//float attn = Define.System.ColliderCollisionVelocityAttenuation;
|
|
||||||
//velocityPosArray[pindex] = velocityPosArray[pindex] + add * attn;
|
|
||||||
|
|
||||||
// バッファクリア
|
|
||||||
countArray[pindex] = 0;
|
|
||||||
sumArray[dataIndex] = 0;
|
|
||||||
sumArray[dataIndex + 1] = 0;
|
|
||||||
sumArray[dataIndex + 2] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// friction
|
|
||||||
float f = InterlockUtility.ReadFloat(pindex, tempFrictionArray);
|
|
||||||
if (f > 0.0f && f > frictionArray[pindex])
|
|
||||||
{
|
|
||||||
frictionArray[pindex] = f;
|
|
||||||
tempFrictionArray[pindex] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// collision normal
|
|
||||||
float3 n = InterlockUtility.ReadFloat3(pindex, tempNormalArray);
|
|
||||||
if (math.lengthsq(n) > 0.0f)
|
|
||||||
{
|
|
||||||
n = math.normalize(n);
|
|
||||||
collisionNormalArray[pindex] = n;
|
|
||||||
tempNormalArray[dataIndex] = 0;
|
|
||||||
tempNormalArray[dataIndex + 1] = 0;
|
|
||||||
tempNormalArray[dataIndex + 2] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,9 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -85,9 +83,10 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 制約データ
|
/// 制約データ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class ConstraintData : IValid
|
[System.Serializable]
|
||||||
|
public class ConstraintData : IValid
|
||||||
{
|
{
|
||||||
internal ResultCode result;
|
public ResultCode result;
|
||||||
|
|
||||||
public uint[] indexArray;
|
public uint[] indexArray;
|
||||||
public ushort[] dataArray;
|
public ushort[] dataArray;
|
||||||
@ -151,7 +150,7 @@ namespace MagicaCloth2
|
|||||||
/// 制約データの作成
|
/// 制約データの作成
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cbase"></param>
|
/// <param name="cbase"></param>
|
||||||
internal static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters)
|
public static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters)
|
||||||
{
|
{
|
||||||
var constraintData = new ConstraintData();
|
var constraintData = new ConstraintData();
|
||||||
|
|
||||||
@ -216,7 +215,7 @@ namespace MagicaCloth2
|
|||||||
for (int l = 0; l < ecnt; l++)
|
for (int l = 0; l < ecnt; l++)
|
||||||
{
|
{
|
||||||
int2 edge = proxyMesh.edges[l];
|
int2 edge = proxyMesh.edges[l];
|
||||||
var tset = proxyMesh.edgeToTriangles.ToFixedList128Bytes(edge);
|
var tset = proxyMesh.edgeToTriangles.MC2ToFixedList128Bytes(edge);
|
||||||
int tcnt = tset.Length;
|
int tcnt = tset.Length;
|
||||||
if (tcnt < 2)
|
if (tcnt < 2)
|
||||||
continue;
|
continue;
|
||||||
@ -377,103 +376,34 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Solver
|
||||||
/// 制約の解決
|
//=========================================================================================
|
||||||
/// </summary>
|
internal static void SolverConstraint(
|
||||||
/// <param name="clothBase"></param>
|
DataChunk chunk,
|
||||||
/// <param name="jobHandle"></param>
|
float4 simulationPower,
|
||||||
/// <returns></returns>
|
|
||||||
unsafe internal JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
|
|
||||||
var job = new DistanceConstraintJob()
|
|
||||||
{
|
|
||||||
simulationPower = MagicaManager.Time.SimulationPower,
|
|
||||||
|
|
||||||
stepParticleIndexArray = sm.processingStepParticle.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
depthArray = vm.vertexDepths.GetNativeArray(),
|
|
||||||
|
|
||||||
teamIdArray = sm.teamIdArray.GetNativeArray(),
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
basePosArray = sm.basePosArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
|
|
||||||
//stepBasicPositionBuffer = sm.stepBasicPositionBuffer,
|
|
||||||
|
|
||||||
indexArray = indexArray.GetNativeArray(),
|
|
||||||
dataArray = dataArray.GetNativeArray(),
|
|
||||||
distanceArray = distanceArray.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle);
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 距離制約の解決
|
|
||||||
/// </summary>
|
|
||||||
[BurstCompile]
|
|
||||||
struct DistanceConstraintJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
public float4 simulationPower;
|
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepParticleIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> depthArray,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> depthArray;
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<short> teamIdArray;
|
ref NativeArray<float3> basePosArray,
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float3> velocityPosArray,
|
||||||
public NativeArray<float3> nextPosArray;
|
ref NativeArray<float> frictionArray,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> basePosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
|
|
||||||
// buffer
|
|
||||||
//[Unity.Collections.ReadOnly]
|
|
||||||
//public NativeArray<float3> stepBasicPositionBuffer;
|
|
||||||
|
|
||||||
// constrants
|
// constrants
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<uint> indexArray,
|
||||||
public NativeArray<uint> indexArray;
|
ref NativeArray<ushort> dataArray,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float> distanceArray
|
||||||
public NativeArray<ushort> dataArray;
|
)
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> distanceArray;
|
|
||||||
|
|
||||||
// ステップ有効パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
// pindexのチームは有効であることが保証されている
|
var sc = tdata.distanceStartChunk;
|
||||||
int pindex = stepParticleIndexArray[index];
|
var dc = tdata.distanceDataChunk;
|
||||||
|
if (sc.dataLength == 0)
|
||||||
int teamId = teamIdArray[pindex];
|
return;
|
||||||
var tdata = teamDataArray[teamId];
|
int c_start = sc.startIndex;
|
||||||
var parameter = parameterArray[teamId];
|
int d_start = dc.startIndex;
|
||||||
|
|
||||||
// 復元を基本姿勢で行うかアニメーション後の姿勢で行うかの判定
|
// 復元を基本姿勢で行うかアニメーション後の姿勢で行うかの判定
|
||||||
float blendRatio = tdata.animationPoseRatio;
|
float blendRatio = tdata.animationPoseRatio;
|
||||||
@ -481,20 +411,20 @@ namespace MagicaCloth2
|
|||||||
// スケール倍率
|
// スケール倍率
|
||||||
float scl = tdata.InitScale * tdata.scaleRatio;
|
float scl = tdata.InitScale * tdata.scaleRatio;
|
||||||
|
|
||||||
|
bool isSpring = tdata.IsSpring;
|
||||||
|
|
||||||
|
// パーティクルごと
|
||||||
int p_start = tdata.particleChunk.startIndex;
|
int p_start = tdata.particleChunk.startIndex;
|
||||||
int l_index = pindex - p_start;
|
int pindex = p_start + chunk.startIndex;
|
||||||
|
//int pindex = p_start;
|
||||||
var sc = tdata.distanceStartChunk;
|
|
||||||
var dc = tdata.distanceDataChunk;
|
|
||||||
|
|
||||||
if (sc.dataLength == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int c_start = sc.startIndex;
|
|
||||||
int d_start = dc.startIndex;
|
|
||||||
int v_start = tdata.proxyCommonChunk.startIndex;
|
int v_start = tdata.proxyCommonChunk.startIndex;
|
||||||
int vindex = v_start + l_index;
|
int vindex = v_start + chunk.startIndex;
|
||||||
|
//int vindex = v_start;
|
||||||
|
int dataIndex = chunk.startIndex;
|
||||||
|
//int dataIndex = 0;
|
||||||
|
//for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++, dataIndex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++, dataIndex++)
|
||||||
|
{
|
||||||
// パーティクル情報
|
// パーティクル情報
|
||||||
var nextPos = nextPosArray[pindex];
|
var nextPos = nextPosArray[pindex];
|
||||||
var attr = attributes[vindex];
|
var attr = attributes[vindex];
|
||||||
@ -502,36 +432,31 @@ namespace MagicaCloth2
|
|||||||
float friction = frictionArray[pindex];
|
float friction = frictionArray[pindex];
|
||||||
|
|
||||||
if (attr.IsInvalid())
|
if (attr.IsInvalid())
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
// Spring利用中は固定も通す
|
// Spring利用中は固定も通す
|
||||||
bool isSpring = tdata.IsSpring;
|
|
||||||
if (attr.IsDontMove() && isSpring == false)
|
if (attr.IsDontMove() && isSpring == false)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
// 固定点の重量
|
// 固定点の重量
|
||||||
float fixMass = isSpring ? 10.0f : 50.0f;
|
float fixMass = isSpring ? 10.0f : 50.0f;
|
||||||
|
|
||||||
// 重量
|
// 重量
|
||||||
// BoneSpringでは固定点の重量加算を行わない
|
// BoneSpringでは固定点の重量加算を行わない
|
||||||
//float invMass = MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove() && isSpring == false);
|
|
||||||
float invMass = MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove(), fixMass);
|
float invMass = MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove(), fixMass);
|
||||||
//float invMass = isSpring && attr.IsDontMove() ? 1.0f / 2.0f : MathUtility.CalcInverseMass(friction, depth, attr.IsDontMove());
|
|
||||||
|
|
||||||
// 基本剛性
|
// 基本剛性
|
||||||
float stiffness = parameter.distanceConstraint.restorationStiffness.EvaluateCurveClamp01(depth);
|
float stiffness = param.distanceConstraint.restorationStiffness.MC2EvaluateCurveClamp01(depth);
|
||||||
//stiffness *= simulationPower;
|
|
||||||
//stiffness *= (simulationPower * simulationPower);
|
|
||||||
stiffness *= simulationPower.y;
|
stiffness *= simulationPower.y;
|
||||||
|
|
||||||
var pack = indexArray[c_start + l_index];
|
//var pack = indexArray[c_start + k];
|
||||||
|
var pack = indexArray[c_start + dataIndex];
|
||||||
DataUtility.Unpack12_20(pack, out int dcnt, out int dstart);
|
DataUtility.Unpack12_20(pack, out int dcnt, out int dstart);
|
||||||
|
|
||||||
if (dcnt > 0)
|
if (dcnt > 0)
|
||||||
{
|
{
|
||||||
// 基準座標を切り替え
|
// 基準座標を切り替え
|
||||||
float3 basePos = basePosArray[pindex];
|
float3 basePos = basePosArray[pindex];
|
||||||
//float3 basicPos = stepBasicPositionBuffer[pindex];
|
|
||||||
|
|
||||||
float3 addPos = 0;
|
float3 addPos = 0;
|
||||||
int addCnt = 0;
|
int addCnt = 0;
|
||||||
@ -550,22 +475,18 @@ namespace MagicaCloth2
|
|||||||
int tvindex = v_start + t_l_index;
|
int tvindex = v_start + t_l_index;
|
||||||
var t_nextPos = nextPosArray[tpindex];
|
var t_nextPos = nextPosArray[tpindex];
|
||||||
float3 t_basePos = basePosArray[tpindex];
|
float3 t_basePos = basePosArray[tpindex];
|
||||||
//float3 t_basicPos = stepBasicPositionBuffer[tpindex];
|
|
||||||
float t_depth = depthArray[tvindex];
|
float t_depth = depthArray[tvindex];
|
||||||
float t_friction = frictionArray[tpindex];
|
float t_friction = frictionArray[tpindex];
|
||||||
var t_attr = attributes[tvindex];
|
var t_attr = attributes[tvindex];
|
||||||
|
|
||||||
// 重量
|
// 重量
|
||||||
// BoneSpringでは固定点の重量加算を行わない
|
// BoneSpringでは固定点の重量加算を行わない
|
||||||
//float t_invMass = MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove() && isSpring == false);
|
|
||||||
float t_invMass = MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove(), fixMass);
|
float t_invMass = MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove(), fixMass);
|
||||||
//float t_invMass = isSpring && t_attr.IsDontMove() ? 1.0f / 2.0f : MathUtility.CalcInverseMass(t_friction, t_depth, t_attr.IsDontMove());
|
|
||||||
|
|
||||||
// 復元する長さ
|
// 復元する長さ
|
||||||
// !Distance制約は初期化時に保存した距離を見るようにしないと駄目
|
// !Distance制約は初期化時に保存した距離を見るようにしないと駄目
|
||||||
// フラグにより初期値かアニメーション後の姿勢かを切り替える
|
// フラグにより初期値かアニメーション後の姿勢かを切り替える
|
||||||
float restLength = math.lerp(math.abs(restDist) * scl, math.distance(basePos, t_basePos), blendRatio);
|
float restLength = math.lerp(math.abs(restDist) * scl, math.distance(basePos, t_basePos), blendRatio);
|
||||||
//float restLength = math.distance(basicPos, t_basicPos);
|
|
||||||
|
|
||||||
var v = t_nextPos - nextPos;
|
var v = t_nextPos - nextPos;
|
||||||
|
|
||||||
@ -595,7 +516,7 @@ namespace MagicaCloth2
|
|||||||
nextPosArray[pindex] = nextPos;
|
nextPosArray[pindex] = nextPos;
|
||||||
|
|
||||||
// 速度影響
|
// 速度影響
|
||||||
float attn = parameter.distanceConstraint.velocityAttenuation;
|
float attn = param.distanceConstraint.velocityAttenuation;
|
||||||
velocityPosArray[pindex] = velocityPosArray[pindex] + addPos * attn;
|
velocityPosArray[pindex] = velocityPosArray[pindex] + addPos * attn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,28 @@ namespace MagicaCloth2
|
|||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class SerializeData : IDataValidate
|
public class SerializeData : IDataValidate
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Anchor that cancels inertia.
|
||||||
|
/// Anchor translation and rotation are excluded from simulation.
|
||||||
|
/// This is useful if your character rides a vehicle.
|
||||||
|
/// 慣性を打ち消すアンカー
|
||||||
|
/// アンカーの移動と回転はシミュレーションから除外されます
|
||||||
|
/// これはキャラクターが乗り物に乗る場合に便利です
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
public Transform anchor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Anchor Influence (0.0 ~ 1.0)
|
||||||
|
/// アンカーの影響(0.0 ~ 1.0)
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
[Range(0.0f, 1.0f)]
|
||||||
|
public float anchorInertia;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// World Influence (0.0 ~ 1.0).
|
/// World Influence (0.0 ~ 1.0).
|
||||||
/// ワールド移動影響(0.0 ~ 1.0)
|
/// ワールド移動影響(0.0 ~ 1.0)
|
||||||
@ -49,6 +71,15 @@ namespace MagicaCloth2
|
|||||||
[Range(0.0f, 1.0f)]
|
[Range(0.0f, 1.0f)]
|
||||||
public float worldInertia;
|
public float worldInertia;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// World Influence Smoothing (0.0 ~ 1.0).
|
||||||
|
/// ワールド移動影響平滑化(0.0 ~ 1.0)
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [OK] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
[Range(0.0f, 1.0f)]
|
||||||
|
public float movementInertiaSmoothing;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// World movement speed limit (m/s).
|
/// World movement speed limit (m/s).
|
||||||
/// ワールド移動速度制限(m/s)
|
/// ワールド移動速度制限(m/s)
|
||||||
@ -144,7 +175,12 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public SerializeData()
|
public SerializeData()
|
||||||
{
|
{
|
||||||
|
anchor = null;
|
||||||
|
anchorInertia = 0.0f;
|
||||||
worldInertia = 1.0f;
|
worldInertia = 1.0f;
|
||||||
|
//movementInertiaSmoothing = 0.65f; // ->0.0524
|
||||||
|
//movementInertiaSmoothing = 0.5f; // ->0.13375
|
||||||
|
movementInertiaSmoothing = 0.4f;
|
||||||
movementSpeedLimit = new CheckSliderSerializeData(true, 5.0f);
|
movementSpeedLimit = new CheckSliderSerializeData(true, 5.0f);
|
||||||
rotationSpeedLimit = new CheckSliderSerializeData(true, 720.0f);
|
rotationSpeedLimit = new CheckSliderSerializeData(true, 720.0f);
|
||||||
localInertia = 1.0f;
|
localInertia = 1.0f;
|
||||||
@ -162,7 +198,10 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
return new SerializeData()
|
return new SerializeData()
|
||||||
{
|
{
|
||||||
|
anchor = anchor,
|
||||||
|
anchorInertia = anchorInertia,
|
||||||
worldInertia = worldInertia,
|
worldInertia = worldInertia,
|
||||||
|
movementInertiaSmoothing = movementInertiaSmoothing,
|
||||||
movementSpeedLimit = movementSpeedLimit.Clone(),
|
movementSpeedLimit = movementSpeedLimit.Clone(),
|
||||||
rotationSpeedLimit = rotationSpeedLimit.Clone(),
|
rotationSpeedLimit = rotationSpeedLimit.Clone(),
|
||||||
localInertia = localInertia,
|
localInertia = localInertia,
|
||||||
@ -179,7 +218,9 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void DataValidate()
|
public void DataValidate()
|
||||||
{
|
{
|
||||||
|
anchorInertia = Mathf.Clamp01(anchorInertia);
|
||||||
worldInertia = Mathf.Clamp01(worldInertia);
|
worldInertia = Mathf.Clamp01(worldInertia);
|
||||||
|
movementInertiaSmoothing = Mathf.Clamp01(movementInertiaSmoothing);
|
||||||
movementSpeedLimit.DataValidate(0.0f, Define.System.MaxMovementSpeedLimit);
|
movementSpeedLimit.DataValidate(0.0f, Define.System.MaxMovementSpeedLimit);
|
||||||
rotationSpeedLimit.DataValidate(0.0f, Define.System.MaxRotationSpeedLimit);
|
rotationSpeedLimit.DataValidate(0.0f, Define.System.MaxRotationSpeedLimit);
|
||||||
localInertia = Mathf.Clamp01(localInertia);
|
localInertia = Mathf.Clamp01(localInertia);
|
||||||
@ -195,18 +236,30 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public struct InertiaConstraintParams
|
public struct InertiaConstraintParams
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// アンカー影響率(0.0 ~ 1.0)
|
||||||
|
/// </summary>
|
||||||
|
public float anchorInertia;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ワールド慣性影響(0.0 ~ 1.0)
|
/// ワールド慣性影響(0.0 ~ 1.0)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float worldInertia;
|
public float worldInertia;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ワールド慣性スムージング率(0.0 ~ 1.0)
|
||||||
|
/// </summary>
|
||||||
|
public float movementInertiaSmoothing;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ワールド移動速度制限(m/s)
|
/// ワールド移動速度制限(m/s)
|
||||||
|
/// 無制限時は(-1)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float movementSpeedLimit;
|
public float movementSpeedLimit;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ワールド回転速度制限(deg/s)
|
/// ワールド回転速度制限(deg/s)
|
||||||
|
/// 無制限時は(-1)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float rotationSpeedLimit;
|
public float rotationSpeedLimit;
|
||||||
|
|
||||||
@ -258,7 +311,9 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Convert(SerializeData sdata)
|
public void Convert(SerializeData sdata)
|
||||||
{
|
{
|
||||||
|
anchorInertia = sdata.anchorInertia;
|
||||||
worldInertia = sdata.worldInertia;
|
worldInertia = sdata.worldInertia;
|
||||||
|
movementInertiaSmoothing = sdata.movementInertiaSmoothing;
|
||||||
movementSpeedLimit = sdata.movementSpeedLimit.GetValue(-1);
|
movementSpeedLimit = sdata.movementSpeedLimit.GetValue(-1);
|
||||||
rotationSpeedLimit = sdata.rotationSpeedLimit.GetValue(-1);
|
rotationSpeedLimit = sdata.rotationSpeedLimit.GetValue(-1);
|
||||||
localInertia = sdata.localInertia;
|
localInertia = sdata.localInertia;
|
||||||
@ -277,8 +332,26 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// センタートランスフォームのデータ
|
/// センタートランスフォームのデータ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[System.Serializable]
|
||||||
public struct CenterData
|
public struct CenterData
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 現在のアンカー姿勢
|
||||||
|
/// </summary>
|
||||||
|
public float3 anchorPosition;
|
||||||
|
public quaternion anchorRotation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前フレームのアンカー姿勢
|
||||||
|
/// </summary>
|
||||||
|
public float3 oldAnchorPosition;
|
||||||
|
public quaternion oldAnchorRotation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// アンカー空間でのコンポーネントのローカル座標
|
||||||
|
/// </summary>
|
||||||
|
public float3 anchorComponentLocalPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 参照すべきセンタートランスフォームインデックス
|
/// 参照すべきセンタートランスフォームインデックス
|
||||||
/// 同期時は同期先チームのもにになる
|
/// 同期時は同期先チームのもにになる
|
||||||
@ -290,12 +363,14 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 componentWorldPosition;
|
public float3 componentWorldPosition;
|
||||||
public quaternion componentWorldRotation;
|
public quaternion componentWorldRotation;
|
||||||
|
public float3 componentWorldScale;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 前フレームのコンポーネント姿勢
|
/// 前フレームのコンポーネント姿勢
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 oldComponentWorldPosition;
|
public float3 oldComponentWorldPosition;
|
||||||
public quaternion oldComponentWorldRotation;
|
public quaternion oldComponentWorldRotation;
|
||||||
|
public float3 oldComponentWorldScale;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 現フレームのコンポーネント移動量
|
/// 現フレームのコンポーネント移動量
|
||||||
@ -329,7 +404,7 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 nowWorldPosition;
|
public float3 nowWorldPosition;
|
||||||
public quaternion nowWorldRotation;
|
public quaternion nowWorldRotation;
|
||||||
public float3 nowWorldScale; // ※現在未使用
|
//public float3 nowWorldScale; // ※現在未使用
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 前回ステップでの姿勢
|
/// 前回ステップでの姿勢
|
||||||
@ -395,10 +470,26 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 initLocalGravityDirection;
|
public float3 initLocalGravityDirection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// スムージングされた現在のワールド慣性速度ベクトル
|
||||||
|
/// </summary>
|
||||||
|
public float3 smoothingVelocity; // (m/s)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// マイナススケールによる反転を打ち消すための変換マトリックス
|
||||||
|
/// センター空間
|
||||||
|
/// </summary>
|
||||||
|
public float4x4 negativeScaleMatrix;
|
||||||
|
|
||||||
internal void Initialize()
|
internal void Initialize()
|
||||||
{
|
{
|
||||||
|
anchorRotation = quaternion.identity;
|
||||||
|
oldAnchorRotation = quaternion.identity;
|
||||||
|
|
||||||
componentWorldRotation = quaternion.identity;
|
componentWorldRotation = quaternion.identity;
|
||||||
|
componentWorldScale = 1;
|
||||||
oldComponentWorldRotation = quaternion.identity;
|
oldComponentWorldRotation = quaternion.identity;
|
||||||
|
oldComponentWorldScale = 1;
|
||||||
frameComponentShiftRotation = quaternion.identity;
|
frameComponentShiftRotation = quaternion.identity;
|
||||||
|
|
||||||
frameWorldRotation = quaternion.identity;
|
frameWorldRotation = quaternion.identity;
|
||||||
@ -412,6 +503,7 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 制約データ
|
/// 制約データ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[System.Serializable]
|
||||||
public class ConstraintData
|
public class ConstraintData
|
||||||
{
|
{
|
||||||
public ResultCode result;
|
public ResultCode result;
|
||||||
@ -450,7 +542,7 @@ namespace MagicaCloth2
|
|||||||
/// 制約データの作成
|
/// 制約データの作成
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cbase"></param>
|
/// <param name="cbase"></param>
|
||||||
internal static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters)
|
public static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters)
|
||||||
{
|
{
|
||||||
var constraintData = new ConstraintData();
|
var constraintData = new ConstraintData();
|
||||||
|
|
||||||
@ -489,7 +581,7 @@ namespace MagicaCloth2
|
|||||||
// 初期センター姿勢からローカル重力方向を算出する
|
// 初期センター姿勢からローカル重力方向を算出する
|
||||||
var rot = MathUtility.ToRotation(math.normalize(nor), math.normalize(tan));
|
var rot = MathUtility.ToRotation(math.normalize(nor), math.normalize(tan));
|
||||||
var irot = math.inverse(rot);
|
var irot = math.inverse(rot);
|
||||||
localGravityDirection = math.mul(irot, parameters.gravityDirection);
|
localGravityDirection = math.mul(irot, parameters.worldGravityDirection);
|
||||||
}
|
}
|
||||||
constraintData.initLocalGravityDirection = localGravityDirection;
|
constraintData.initLocalGravityDirection = localGravityDirection;
|
||||||
|
|
||||||
@ -519,12 +611,13 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 初期化時のローカル重力方向
|
// 初期化時のローカル重力方向
|
||||||
cdata.initLocalGravityDirection = cprocess.inertiaConstraintData.initLocalGravityDirection;
|
cdata.initLocalGravityDirection = cprocess.inertiaConstraintData.initLocalGravityDirection;
|
||||||
|
//Debug.Log($"[{cprocess.TeamId}] initLocalGravityDirection:{cdata.initLocalGravityDirection}");
|
||||||
|
|
||||||
// 固定点リスト
|
// 固定点リスト
|
||||||
var c = new DataChunk();
|
var c = new DataChunk();
|
||||||
if (cprocess.ProxyMesh.CenterFixedPointCount > 0)
|
if (cprocess.ProxyMeshContainer.shareVirtualMesh.CenterFixedPointCount > 0)
|
||||||
{
|
{
|
||||||
c = fixedArray.AddRange(cprocess.ProxyMesh.centerFixedList);
|
c = fixedArray.AddRange(cprocess.ProxyMeshContainer.shareVirtualMesh.centerFixedList);
|
||||||
}
|
}
|
||||||
tdata.fixedDataChunk = c;
|
tdata.fixedDataChunk = c;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System;
|
using System;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -134,97 +132,45 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Solver
|
||||||
/// 制約の解決
|
//=========================================================================================
|
||||||
/// </summary>
|
internal static void SolverConstraint(
|
||||||
/// <param name="jobHandle"></param>
|
DataChunk chunk,
|
||||||
/// <returns></returns>
|
|
||||||
unsafe internal JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
|
|
||||||
var job = new MotionConstraintJob()
|
|
||||||
{
|
|
||||||
stepParticleIndexArray = sm.processingStepMotionParticle.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
vertexDepths = vm.vertexDepths.GetNativeArray(),
|
|
||||||
|
|
||||||
teamIdArray = sm.teamIdArray.GetNativeArray(),
|
|
||||||
basePosArray = sm.basePosArray.GetNativeArray(),
|
|
||||||
baseRotArray = sm.baseRotArray.GetNativeArray(),
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
collisionNormalArray = sm.collisionNormalArray.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(sm.processingStepMotionParticle.GetJobSchedulePtr(), 32, jobHandle);
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct MotionConstraintJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepParticleIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> vertexDepths,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> vertexDepths;
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> basePosArray,
|
||||||
public NativeArray<short> teamIdArray;
|
ref NativeArray<quaternion> baseRotArray,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<float3> basePosArray;
|
ref NativeArray<float3> velocityPosArray,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float> frictionArray,
|
||||||
public NativeArray<quaternion> baseRotArray;
|
ref NativeArray<float3> collisionNormalArray
|
||||||
[NativeDisableParallelForRestriction]
|
)
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> collisionNormalArray;
|
|
||||||
|
|
||||||
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
// pindexのチームは有効であることが保証されている
|
if (param.motionConstraint.useMaxDistance == false && param.motionConstraint.useBackstop == false)
|
||||||
int pindex = stepParticleIndexArray[index];
|
|
||||||
|
|
||||||
int teamId = teamIdArray[pindex];
|
|
||||||
var tdata = teamDataArray[teamId];
|
|
||||||
var param = parameterArray[teamId];
|
|
||||||
var motionParam = param.motionConstraint;
|
|
||||||
var normalAxis = param.normalAxis;
|
|
||||||
if (motionParam.useMaxDistance == false && motionParam.useBackstop == false)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int p_start = tdata.particleChunk.startIndex;
|
// stiffness
|
||||||
int l_index = pindex - p_start;
|
float stiffness = param.motionConstraint.stiffness;
|
||||||
int v_start = tdata.proxyCommonChunk.startIndex;
|
|
||||||
int vindex = v_start + l_index;
|
|
||||||
|
|
||||||
|
float backstopRadius = param.motionConstraint.backstopRadius;
|
||||||
|
|
||||||
|
// パーティクルごと
|
||||||
|
//int pindex = tdata.particleChunk.startIndex;
|
||||||
|
//int vindex = tdata.proxyCommonChunk.startIndex;
|
||||||
|
int pindex = tdata.particleChunk.startIndex + chunk.startIndex;
|
||||||
|
int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
{
|
||||||
// 移動パーティクルのみ
|
// 移動パーティクルのみ
|
||||||
var attr = attributes[vindex];
|
var attr = attributes[vindex];
|
||||||
if (attr.IsMove() == false)
|
if (attr.IsMove() == false)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
var nextPos = nextPosArray[pindex];
|
var nextPos = nextPosArray[pindex];
|
||||||
var basePos = basePosArray[pindex];
|
var basePos = basePosArray[pindex];
|
||||||
@ -233,17 +179,13 @@ namespace MagicaCloth2
|
|||||||
// !MaxDistanceとBackstop制約は常にアニメーション姿勢(basePose)から計算されるので注意!
|
// !MaxDistanceとBackstop制約は常にアニメーション姿勢(basePose)から計算されるので注意!
|
||||||
// !そのためAnimationBlendRatioは影響しない。
|
// !そのためAnimationBlendRatioは影響しない。
|
||||||
|
|
||||||
// stiffness
|
|
||||||
float stiffness = motionParam.stiffness;
|
|
||||||
|
|
||||||
// 適用頂点属性チェック
|
// 適用頂点属性チェック
|
||||||
if (attr.IsMotion())
|
if (attr.IsMotion())
|
||||||
{
|
{
|
||||||
var opos = nextPos;
|
var opos = nextPos;
|
||||||
|
|
||||||
// パーティクル半径
|
// パーティクル半径
|
||||||
float radius = math.max(param.radiusCurveData.EvaluateCurve(depth), 0.0001f); // safe
|
float radius = math.max(param.radiusCurveData.MC2EvaluateCurve(depth), 0.0001f); // safe
|
||||||
//radius *= tdata.scaleRatio;
|
|
||||||
|
|
||||||
// 摩擦影響距離
|
// 摩擦影響距離
|
||||||
float cfr = radius * 1.0f;
|
float cfr = radius * 1.0f;
|
||||||
@ -256,7 +198,7 @@ namespace MagicaCloth2
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
var baseRot = baseRotArray[pindex];
|
var baseRot = baseRotArray[pindex];
|
||||||
float3 dir = math.up();
|
float3 dir = math.up();
|
||||||
switch (normalAxis)
|
switch (param.normalAxis)
|
||||||
{
|
{
|
||||||
case ClothNormalAxis.Right:
|
case ClothNormalAxis.Right:
|
||||||
dir = math.right();
|
dir = math.right();
|
||||||
@ -282,9 +224,9 @@ namespace MagicaCloth2
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
// Max Distance
|
// Max Distance
|
||||||
//=========================================================
|
//=========================================================
|
||||||
if (motionParam.useMaxDistance)
|
if (param.motionConstraint.useMaxDistance)
|
||||||
{
|
{
|
||||||
float maxDistance = motionParam.maxDistanceCurveData.EvaluateCurve(depth);
|
float maxDistance = param.motionConstraint.maxDistanceCurveData.MC2EvaluateCurve(depth);
|
||||||
//var cen = basePos + dir * (motionParam.maxDistanceOffset * maxDistance);
|
//var cen = basePos + dir * (motionParam.maxDistanceOffset * maxDistance);
|
||||||
var cen = basePos;
|
var cen = basePos;
|
||||||
var v = MathUtility.ClampVector(nextPos - cen, maxDistance);
|
var v = MathUtility.ClampVector(nextPos - cen, maxDistance);
|
||||||
@ -294,10 +236,9 @@ namespace MagicaCloth2
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
// Backstop
|
// Backstop
|
||||||
//=========================================================
|
//=========================================================
|
||||||
if (motionParam.useBackstop)
|
if (param.motionConstraint.useBackstop)
|
||||||
{
|
{
|
||||||
float backstopRadius = motionParam.backstopRadius;
|
float backstopDistance = param.motionConstraint.backstopDistanceCurveData.MC2EvaluateCurve(depth);
|
||||||
float backstopDistance = motionParam.backstopDistanceCurveData.EvaluateCurve(depth);
|
|
||||||
if (backstopRadius > 0.0f)
|
if (backstopRadius > 0.0f)
|
||||||
{
|
{
|
||||||
// バックストップは法線逆方向
|
// バックストップは法線逆方向
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,6 @@
|
|||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Unity.Jobs;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
@ -127,11 +126,5 @@ namespace MagicaCloth2
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
|
||||||
unsafe internal JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System;
|
using System;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -32,7 +30,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public SerializeData()
|
public SerializeData()
|
||||||
{
|
{
|
||||||
distanceCompression = 0.9f;
|
distanceCompression = 0.4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DataValidate()
|
public void DataValidate()
|
||||||
@ -85,102 +83,41 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Solver
|
||||||
/// 制約の解決
|
//=========================================================================================
|
||||||
/// </summary>
|
internal static void SolverConstraint(
|
||||||
/// <param name="clothBase"></param>
|
DataChunk chunk,
|
||||||
/// <param name="jobHandle"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
unsafe internal JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
|
|
||||||
var job = new TethreConstraintJob()
|
|
||||||
{
|
|
||||||
stepParticleIndexArray = sm.processingStepParticle.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
centerDataArray = tm.centerDataArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
vertexDepths = vm.vertexDepths.GetNativeArray(),
|
|
||||||
vertexRootIndices = vm.vertexRootIndices.GetNativeArray(),
|
|
||||||
|
|
||||||
teamIdArray = sm.teamIdArray.GetNativeArray(),
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
|
|
||||||
stepBasicPositionBuffer = sm.stepBasicPositionBuffer,
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 32, jobHandle);
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct TethreConstraintJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepParticleIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
ref InertiaConstraint.CenterData cdata,
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<InertiaConstraint.CenterData> centerDataArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> vertexDepths,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<int> vertexRootIndices,
|
||||||
public NativeArray<float> vertexDepths;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> vertexRootIndices;
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<short> teamIdArray;
|
ref NativeArray<float3> velocityPosArray,
|
||||||
[NativeDisableParallelForRestriction]
|
ref NativeArray<float> frictionArray,
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
|
|
||||||
// buffer
|
// buffer
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> stepBasicPositionBuffer
|
||||||
public NativeArray<float3> stepBasicPositionBuffer;
|
)
|
||||||
|
|
||||||
// パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
// pindexのチームは有効であることが保証されている
|
|
||||||
int pindex = stepParticleIndexArray[index];
|
|
||||||
|
|
||||||
int teamId = teamIdArray[pindex];
|
|
||||||
var tdata = teamDataArray[teamId];
|
|
||||||
var param = parameterArray[teamId].tetherConstraint;
|
|
||||||
//if (param.stiffness < 1e-06f)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
int p_start = tdata.particleChunk.startIndex;
|
int p_start = tdata.particleChunk.startIndex;
|
||||||
int l_index = pindex - p_start;
|
//int pindex = p_start;
|
||||||
int v_start = tdata.proxyCommonChunk.startIndex;
|
int pindex = p_start + chunk.startIndex;
|
||||||
int vindex = v_start + l_index;
|
//int vindex = tdata.proxyCommonChunk.startIndex;
|
||||||
|
int vindex = tdata.proxyCommonChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
{
|
||||||
var attr = attributes[vindex];
|
var attr = attributes[vindex];
|
||||||
if (attr.IsMove() == false)
|
if (attr.IsMove() == false)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
int rootIndex = vertexRootIndices[vindex];
|
int rootIndex = vertexRootIndices[vindex];
|
||||||
if (rootIndex < 0)
|
if (rootIndex < 0)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
//Debug.Log($"Tether [{pindex}] root:{rootIndex + p_start}");
|
//Debug.Log($"Tether [{pindex}] root:{rootIndex + p_start}");
|
||||||
|
|
||||||
@ -198,7 +135,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 距離がほぼ0ならば処理をスキップする(エラーの回避)
|
// 距離がほぼ0ならば処理をスキップする(エラーの回避)
|
||||||
if (distance < Define.System.Epsilon)
|
if (distance < Define.System.Epsilon)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
// 復元距離
|
// 復元距離
|
||||||
// フラグにより初期姿勢かアニメーション後姿勢かを切り替える
|
// フラグにより初期姿勢かアニメーション後姿勢かを切り替える
|
||||||
@ -210,7 +147,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 初期位置がまったく同じ状況を考慮
|
// 初期位置がまったく同じ状況を考慮
|
||||||
if (calcDistance == 0.0f)
|
if (calcDistance == 0.0f)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
// 現在の伸縮割合
|
// 現在の伸縮割合
|
||||||
//Develop.Assert(calcDistance > 0.0f);
|
//Develop.Assert(calcDistance > 0.0f);
|
||||||
@ -220,8 +157,8 @@ namespace MagicaCloth2
|
|||||||
float dist = 0;
|
float dist = 0;
|
||||||
float stiffness;
|
float stiffness;
|
||||||
float attn;
|
float attn;
|
||||||
float compressionLimit = 1.0f - param.compressionLimit;
|
float compressionLimit = 1.0f - param.tetherConstraint.compressionLimit;
|
||||||
float stretchLimit = 1.0f + param.stretchLimit;
|
float stretchLimit = 1.0f + param.tetherConstraint.stretchLimit;
|
||||||
//float widthRatio = math.max(param.stiffnessWidth, 0.001f); // 0.2?
|
//float widthRatio = math.max(param.stiffnessWidth, 0.001f); // 0.2?
|
||||||
//float widthRatio = 0.1f; // 0.2?
|
//float widthRatio = 0.1f; // 0.2?
|
||||||
if (ratio < compressionLimit)
|
if (ratio < compressionLimit)
|
||||||
@ -243,7 +180,7 @@ namespace MagicaCloth2
|
|||||||
attn = Define.System.TetherStretchVelocityAttenuation;
|
attn = Define.System.TetherStretchVelocityAttenuation;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
// 移動量
|
// 移動量
|
||||||
float3 add = (v / distance) * (dist * stiffness);
|
float3 add = (v / distance) * (dist * stiffness);
|
||||||
|
|||||||
@ -4,9 +4,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Collections.LowLevel.Unsafe;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -17,6 +16,11 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TriangleBendingConstraint : IDisposable
|
public class TriangleBendingConstraint : IDisposable
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ボリュームとして処理する判定フラグ
|
||||||
|
/// </summary>
|
||||||
|
const sbyte VOLUME_SIGN = 100;
|
||||||
|
|
||||||
public enum Method
|
public enum Method
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
@ -29,7 +33,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 方向性ありの2面角曲げ制約
|
/// 方向性ありの2面角曲げ制約
|
||||||
/// 初期姿勢を保た持つように復元する
|
/// 初期姿勢を保つように復元する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DirectionDihedralAngle = 2,
|
DirectionDihedralAngle = 2,
|
||||||
}
|
}
|
||||||
@ -73,16 +77,17 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Convert(SerializeData sdata)
|
public void Convert(SerializeData sdata)
|
||||||
{
|
{
|
||||||
//method = sdata.method;
|
|
||||||
// モードはDirectionDihedralAngleに固定する
|
// モードはDirectionDihedralAngleに固定する
|
||||||
method = sdata.stiffness > Define.System.Epsilon ? Method.DirectionDihedralAngle : Method.None;
|
method = sdata.stiffness > Define.System.Epsilon ? Method.DirectionDihedralAngle : Method.None;
|
||||||
|
//method = sdata.stiffness > Define.System.Epsilon ? Method.DihedralAngle : Method.None;
|
||||||
|
|
||||||
stiffness = sdata.stiffness;
|
stiffness = sdata.stiffness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
internal class ConstraintData : IValid
|
[System.Serializable]
|
||||||
|
public class ConstraintData : IValid
|
||||||
{
|
{
|
||||||
public ResultCode result;
|
public ResultCode result;
|
||||||
public ulong[] trianglePairArray;
|
public ulong[] trianglePairArray;
|
||||||
@ -116,29 +121,16 @@ namespace MagicaCloth2
|
|||||||
public ExNativeArray<float> restAngleOrVolumeArray;
|
public ExNativeArray<float> restAngleOrVolumeArray;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// トライアングルペアごとの復元方向もしくはボリューム判定(100=このペアはボリュームである)
|
/// トライアングルペアごとの復元方向もしくはボリューム判定(VOLUME_SIGN(100)=このペアはボリュームである)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ExNativeArray<sbyte> signOrVolumeArray;
|
public ExNativeArray<sbyte> signOrVolumeArray;
|
||||||
|
|
||||||
/// <summary>
|
//public int DataCount => trianglePairArray?.Count ?? 0;
|
||||||
/// トライアングルペアごとの結果書き込みローカルインデックス
|
|
||||||
/// 4つのbyteを1つのuintに結合したもの
|
|
||||||
/// </summary>
|
|
||||||
public ExNativeArray<uint> writeDataArray;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 頂点ごとの書き込みバッファの数と開始インデックス
|
/// ボリューム計算の浮動小数点誤差を回避するための倍数
|
||||||
/// (上位10bit = カウンタ, 下位22bit = 開始インデックス)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ExNativeArray<uint> writeIndexArray;
|
const float VolumeScale = 1000.0f;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 頂点ごとの書き込みバッファ(集計用)
|
|
||||||
/// writeIndexArrayに従う
|
|
||||||
/// </summary>
|
|
||||||
public ExNativeArray<float3> writeBuffer;
|
|
||||||
|
|
||||||
public int DataCount => trianglePairArray?.Count ?? 0;
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public TriangleBendingConstraint()
|
public TriangleBendingConstraint()
|
||||||
@ -146,9 +138,6 @@ namespace MagicaCloth2
|
|||||||
trianglePairArray = new ExNativeArray<ulong>(0, true);
|
trianglePairArray = new ExNativeArray<ulong>(0, true);
|
||||||
restAngleOrVolumeArray = new ExNativeArray<float>(0, true);
|
restAngleOrVolumeArray = new ExNativeArray<float>(0, true);
|
||||||
signOrVolumeArray = new ExNativeArray<sbyte>(0, true);
|
signOrVolumeArray = new ExNativeArray<sbyte>(0, true);
|
||||||
writeDataArray = new ExNativeArray<uint>(0, true);
|
|
||||||
writeIndexArray = new ExNativeArray<uint>(0, true);
|
|
||||||
writeBuffer = new ExNativeArray<float3>(0, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -156,9 +145,6 @@ namespace MagicaCloth2
|
|||||||
trianglePairArray?.Dispose();
|
trianglePairArray?.Dispose();
|
||||||
restAngleOrVolumeArray?.Dispose();
|
restAngleOrVolumeArray?.Dispose();
|
||||||
signOrVolumeArray?.Dispose();
|
signOrVolumeArray?.Dispose();
|
||||||
writeDataArray?.Dispose();
|
|
||||||
writeIndexArray?.Dispose();
|
|
||||||
writeBuffer?.Dispose();
|
|
||||||
|
|
||||||
trianglePairArray = null;
|
trianglePairArray = null;
|
||||||
restAngleOrVolumeArray = null;
|
restAngleOrVolumeArray = null;
|
||||||
@ -172,9 +158,6 @@ namespace MagicaCloth2
|
|||||||
sb.AppendLine($" -trianglePairArray:{trianglePairArray.ToSummary()}");
|
sb.AppendLine($" -trianglePairArray:{trianglePairArray.ToSummary()}");
|
||||||
sb.AppendLine($" -restAngleOrVolumeArray:{restAngleOrVolumeArray.ToSummary()}");
|
sb.AppendLine($" -restAngleOrVolumeArray:{restAngleOrVolumeArray.ToSummary()}");
|
||||||
sb.AppendLine($" -signOrVolumeArray:{signOrVolumeArray.ToSummary()}");
|
sb.AppendLine($" -signOrVolumeArray:{signOrVolumeArray.ToSummary()}");
|
||||||
sb.AppendLine($" -writeDataArray:{writeDataArray.ToSummary()}");
|
|
||||||
sb.AppendLine($" -writeIndexArray:{writeIndexArray.ToSummary()}");
|
|
||||||
sb.AppendLine($" -writeBuffer:{writeBuffer.ToSummary()}");
|
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
@ -186,7 +169,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="proxyMesh"></param>
|
/// <param name="proxyMesh"></param>
|
||||||
/// <param name="parameters"></param>
|
/// <param name="parameters"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters)
|
public static ConstraintData CreateData(VirtualMesh proxyMesh, in ClothParameters parameters)
|
||||||
{
|
{
|
||||||
var constraintData = new ConstraintData();
|
var constraintData = new ConstraintData();
|
||||||
|
|
||||||
@ -223,7 +206,7 @@ namespace MagicaCloth2
|
|||||||
if (proxyMesh.edgeToTriangles.ContainsKey(edge) == false)
|
if (proxyMesh.edgeToTriangles.ContainsKey(edge) == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var triangles = proxyMesh.edgeToTriangles.ToFixedList128Bytes(edge);
|
var triangles = proxyMesh.edgeToTriangles.MC2ToFixedList128Bytes(edge);
|
||||||
int tcnt = triangles.Length;
|
int tcnt = triangles.Length;
|
||||||
|
|
||||||
// トライアングルの組み合わせ
|
// トライアングルの組み合わせ
|
||||||
@ -276,6 +259,7 @@ namespace MagicaCloth2
|
|||||||
trianglePairList.Add(pair);
|
trianglePairList.Add(pair);
|
||||||
restAngleOrVolumeList.Add(restData);
|
restAngleOrVolumeList.Add(restData);
|
||||||
signOrVolumeList.Add(signFlag);
|
signOrVolumeList.Add(signFlag);
|
||||||
|
//Debug.Log($"rest angle:{math.degrees(restData)}, signFlag:{signFlag}");
|
||||||
|
|
||||||
uint writeData = DataUtility.Pack32(
|
uint writeData = DataUtility.Pack32(
|
||||||
multiBuilder.CountValuesForKey(vtx.x),
|
multiBuilder.CountValuesForKey(vtx.x),
|
||||||
@ -320,7 +304,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
volumeCount++;
|
volumeCount++;
|
||||||
|
|
||||||
//Develop.DebugLog($"Volume Pair. edge:{edge}, tri:({tri0},{tri1}) restAngle:{degAngle}");
|
//Develop.DebugLog($"Volume Pair. edge:{edge}, tri:({tri0},{tri1}) restAngle:{degAngle}, restData:{restData}, signFlag:{signFlag}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (math.all(tri0 - 243) == false || math.all(tri1 - 243) == false)
|
//if (math.all(tri0 - 243) == false || math.all(tri1 - 243) == false)
|
||||||
@ -357,13 +341,15 @@ namespace MagicaCloth2
|
|||||||
static void InitVolume(VirtualMesh proxyMesh, int v0, int v1, int v2, int v3, out float volumeRest, out sbyte signFlag)
|
static void InitVolume(VirtualMesh proxyMesh, int v0, int v1, int v2, int v3, out float volumeRest, out sbyte signFlag)
|
||||||
{
|
{
|
||||||
// 0/1が対角点,2/3が共通辺
|
// 0/1が対角点,2/3が共通辺
|
||||||
float3 pos0 = proxyMesh.localPositions[v0];
|
// ここは実行時とボリューム値を合わせるためワールド座標で計算する必要がある。
|
||||||
float3 pos1 = proxyMesh.localPositions[v1];
|
float3 pos0 = MathUtility.TransformPoint(proxyMesh.localPositions[v0], proxyMesh.initLocalToWorld);
|
||||||
float3 pos2 = proxyMesh.localPositions[v2];
|
float3 pos1 = MathUtility.TransformPoint(proxyMesh.localPositions[v1], proxyMesh.initLocalToWorld);
|
||||||
float3 pos3 = proxyMesh.localPositions[v3];
|
float3 pos2 = MathUtility.TransformPoint(proxyMesh.localPositions[v2], proxyMesh.initLocalToWorld);
|
||||||
|
float3 pos3 = MathUtility.TransformPoint(proxyMesh.localPositions[v3], proxyMesh.initLocalToWorld);
|
||||||
|
|
||||||
volumeRest = (1.0f / 6.0f) * math.dot(math.cross(pos1 - pos0, pos2 - pos0), pos3 - pos0);
|
volumeRest = (1.0f / 6.0f) * math.dot(math.cross(pos1 - pos0, pos2 - pos0), pos3 - pos0);
|
||||||
signFlag = 100; // Volume
|
volumeRest *= VolumeScale; // 浮動小数点演算誤差回避
|
||||||
|
signFlag = VOLUME_SIGN; // Volume
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitDihedralAngle(VirtualMesh proxyMesh, int v0, int v1, int v2, int v3, out float restAngle, out sbyte signFlag)
|
static void InitDihedralAngle(VirtualMesh proxyMesh, int v0, int v1, int v2, int v3, out float restAngle, out sbyte signFlag)
|
||||||
@ -409,11 +395,6 @@ namespace MagicaCloth2
|
|||||||
tdata.bendingPairChunk = trianglePairArray.AddRange(cdata.trianglePairArray);
|
tdata.bendingPairChunk = trianglePairArray.AddRange(cdata.trianglePairArray);
|
||||||
restAngleOrVolumeArray.AddRange(cdata.restAngleOrVolumeArray);
|
restAngleOrVolumeArray.AddRange(cdata.restAngleOrVolumeArray);
|
||||||
signOrVolumeArray.AddRange(cdata.signOrVolumeArray);
|
signOrVolumeArray.AddRange(cdata.signOrVolumeArray);
|
||||||
writeDataArray.AddRange(cdata.writeDataArray);
|
|
||||||
|
|
||||||
// write buffer
|
|
||||||
tdata.bendingWriteIndexChunk = writeIndexArray.AddRange(cdata.writeIndexArray);
|
|
||||||
tdata.bendingBufferChunk = writeBuffer.AddRange(cdata.writeBufferCount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,159 +411,78 @@ namespace MagicaCloth2
|
|||||||
trianglePairArray.Remove(tdata.bendingPairChunk);
|
trianglePairArray.Remove(tdata.bendingPairChunk);
|
||||||
restAngleOrVolumeArray.Remove(tdata.bendingPairChunk);
|
restAngleOrVolumeArray.Remove(tdata.bendingPairChunk);
|
||||||
signOrVolumeArray.Remove(tdata.bendingPairChunk);
|
signOrVolumeArray.Remove(tdata.bendingPairChunk);
|
||||||
writeDataArray.Remove(tdata.bendingPairChunk);
|
|
||||||
|
|
||||||
// write buffer
|
|
||||||
writeIndexArray.Remove(tdata.bendingWriteIndexChunk);
|
|
||||||
writeBuffer.Remove(tdata.bendingBufferChunk);
|
|
||||||
|
|
||||||
tdata.bendingPairChunk.Clear();
|
tdata.bendingPairChunk.Clear();
|
||||||
tdata.bendingWriteIndexChunk.Clear();
|
|
||||||
tdata.bendingBufferChunk.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
// Solver
|
||||||
/// 制約の解決
|
//=========================================================================================
|
||||||
/// </summary>
|
internal unsafe static void SolverConstraint(
|
||||||
/// <param name="jobHandle"></param>
|
DataChunk chunk,
|
||||||
/// <returns></returns>
|
in float4 simulationPower,
|
||||||
unsafe internal JobHandle SolverConstraint(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
|
|
||||||
if (DataCount > 0)
|
|
||||||
{
|
|
||||||
var triangleBendingJob = new TriangleBendingJob()
|
|
||||||
{
|
|
||||||
simulationPower = MagicaManager.Time.SimulationPower,
|
|
||||||
|
|
||||||
stepTriangleBendIndexArray = sm.processingStepTriangleBending.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
parameterArray = tm.parameterArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
depthArray = vm.vertexDepths.GetNativeArray(),
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
frictionArray = sm.frictionArray.GetNativeArray(),
|
|
||||||
|
|
||||||
trianglePairArray = trianglePairArray.GetNativeArray(),
|
|
||||||
restAngleOrVolumeArray = restAngleOrVolumeArray.GetNativeArray(),
|
|
||||||
signOrVolumeArray = signOrVolumeArray.GetNativeArray(),
|
|
||||||
|
|
||||||
writeDataArray = writeDataArray.GetNativeArray(),
|
|
||||||
writeIndexArray = writeIndexArray.GetNativeArray(),
|
|
||||||
writeBuffer = writeBuffer.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = triangleBendingJob.Schedule(sm.processingStepTriangleBending.GetJobSchedulePtr(), 16, jobHandle);
|
|
||||||
|
|
||||||
// 集計(速度影響はなし)
|
|
||||||
var aggregateJob = new SolveAggregateBufferJob()
|
|
||||||
{
|
|
||||||
stepParticleIndexArray = sm.processingStepParticle.Buffer,
|
|
||||||
|
|
||||||
teamDataArray = tm.teamDataArray.GetNativeArray(),
|
|
||||||
|
|
||||||
attributes = vm.attributes.GetNativeArray(),
|
|
||||||
|
|
||||||
teamIdArray = sm.teamIdArray.GetNativeArray(),
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
writeIndexArray = writeIndexArray.GetNativeArray(),
|
|
||||||
writeBuffer = writeBuffer.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = aggregateJob.Schedule(sm.processingStepParticle.GetJobSchedulePtr(), 16, jobHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct TriangleBendingJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
public float4 simulationPower;
|
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepTriangleBendIndexArray;
|
|
||||||
|
|
||||||
// team
|
// team
|
||||||
[Unity.Collections.ReadOnly]
|
ref TeamManager.TeamData tdata,
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
ref ClothParameters param,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ClothParameters> parameterArray;
|
|
||||||
|
|
||||||
// vmesh
|
// vmesh
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
public NativeArray<VertexAttribute> attributes;
|
ref NativeArray<float> depthArray,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> depthArray;
|
|
||||||
|
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> nextPosArray,
|
||||||
public NativeArray<float3> nextPosArray;
|
ref NativeArray<float> frictionArray,
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float> frictionArray;
|
|
||||||
|
|
||||||
// constraints
|
// constraints
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<ulong> trianglePairArray,
|
||||||
public NativeArray<ulong> trianglePairArray;
|
ref NativeArray<float> restAngleOrVolumeArray,
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<sbyte> signOrVolumeArray,
|
||||||
public NativeArray<float> restAngleOrVolumeArray;
|
// buffer2
|
||||||
[Unity.Collections.ReadOnly]
|
ref NativeArray<float3> tempVectorBufferA,
|
||||||
public NativeArray<sbyte> signOrVolumeArray;
|
ref NativeArray<int> tempCountBuffer
|
||||||
[Unity.Collections.ReadOnly]
|
)
|
||||||
public NativeArray<uint> writeDataArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<uint> writeIndexArray;
|
|
||||||
|
|
||||||
// output
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> writeBuffer;
|
|
||||||
|
|
||||||
// ベンドトライアングルペアごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
{
|
||||||
// インデックスのチームは有効であることが保証されている
|
if (param.triangleBendingConstraint.method == Method.None)
|
||||||
//int pairIndex = stepTriangleBendIndexArray[index];
|
return;
|
||||||
//int teamId = trianglePairTeamIdArray[pairIndex];
|
|
||||||
uint pack = (uint)stepTriangleBendIndexArray[index];
|
if (tdata.bendingPairChunk.IsValid == false)
|
||||||
int pairIndex = DataUtility.Unpack12_20Low(pack);
|
|
||||||
int teamId = DataUtility.Unpack12_20Hi(pack);
|
|
||||||
var tdata = teamDataArray[teamId];
|
|
||||||
var parameter = parameterArray[teamId].triangleBendingConstraint;
|
|
||||||
if (parameter.method == Method.None)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 剛性
|
// 剛性
|
||||||
float stiffness = parameter.stiffness;
|
float stiffness = param.triangleBendingConstraint.stiffness;
|
||||||
if (stiffness < 1e-06f)
|
if (stiffness < 1e-06f)
|
||||||
return;
|
return;
|
||||||
stiffness = math.saturate(stiffness * simulationPower.y);
|
stiffness = math.saturate(stiffness * simulationPower.y);
|
||||||
|
|
||||||
|
|
||||||
int p_start = tdata.particleChunk.startIndex;
|
int p_start = tdata.particleChunk.startIndex;
|
||||||
int v_start = tdata.proxyCommonChunk.startIndex;
|
int v_start = tdata.proxyCommonChunk.startIndex;
|
||||||
|
int pindex;
|
||||||
|
int vindex;
|
||||||
|
|
||||||
|
int* sumPt = (int*)tempVectorBufferA.GetUnsafePtr();
|
||||||
|
int* cntPt = (int*)tempCountBuffer.GetUnsafePtr();
|
||||||
|
|
||||||
|
// ■計算
|
||||||
|
// ベンドペアごと
|
||||||
|
//int pairIndex = tdata.bendingPairChunk.startIndex;
|
||||||
|
int pairIndex = tdata.bendingPairChunk.startIndex + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.bendingPairChunk.dataLength; k++, pairIndex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pairIndex++)
|
||||||
|
{
|
||||||
// トライアングルペア
|
// トライアングルペア
|
||||||
var pairData = trianglePairArray[pairIndex];
|
var pairData = trianglePairArray[pairIndex];
|
||||||
int4 vertices = DataUtility.Unpack64(pairData);
|
int4 vertices = DataUtility.Unpack64(pairData);
|
||||||
//Debug.Log(vertices);
|
//Debug.Log(vertices);
|
||||||
|
|
||||||
|
int4 pindex4 = vertices + p_start;
|
||||||
|
int4 vindex4 = vertices + v_start;
|
||||||
|
|
||||||
// 状態
|
// 状態
|
||||||
float3x4 nextPosBuffer = 0;
|
float3x4 nextPosBuffer = 0;
|
||||||
float3x4 addPosBuffer = 0;
|
float3x4 addPosBuffer = 0;
|
||||||
float4 invMassBuffer = 1;
|
float4 invMassBuffer = 1;
|
||||||
//int4 fixedBuffer = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
int pindex = p_start + vertices[i];
|
pindex = pindex4[i];
|
||||||
int vindex = v_start + vertices[i];
|
vindex = vindex4[i];
|
||||||
nextPosBuffer[i] = nextPosArray[pindex];
|
nextPosBuffer[i] = nextPosArray[pindex];
|
||||||
float friction = frictionArray[pindex];
|
float friction = frictionArray[pindex];
|
||||||
float depth = depthArray[vindex];
|
float depth = depthArray[vindex];
|
||||||
@ -598,45 +498,116 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// メソッドごとの解決
|
// メソッドごとの解決
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (signOrVolume == 100)
|
if (signOrVolume == VOLUME_SIGN)
|
||||||
{
|
{
|
||||||
// Volume
|
// Volume
|
||||||
result = Volume(nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer);
|
float volumeRest = restAngle * tdata.scaleRatio; // スケール倍率
|
||||||
|
|
||||||
|
// マイナススケール
|
||||||
|
volumeRest *= tdata.negativeScaleSign;
|
||||||
|
|
||||||
|
result = CalcVolume(nextPosBuffer, invMassBuffer, volumeRest, stiffness, ref addPosBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Triangle Bending
|
// Triangle Bending
|
||||||
float sign = signOrVolume < 0 ? -1 : 1;
|
if (param.triangleBendingConstraint.method == Method.DihedralAngle)
|
||||||
if (parameter.method == Method.DihedralAngle)
|
|
||||||
{
|
{
|
||||||
// 二面角
|
// 方向性なし二面角
|
||||||
result = DihedralAngle(0, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer);
|
result = CalcDihedralAngle(0, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer);
|
||||||
}
|
}
|
||||||
else if (parameter.method == Method.DirectionDihedralAngle)
|
else if (param.triangleBendingConstraint.method == Method.DirectionDihedralAngle)
|
||||||
{
|
{
|
||||||
// 方向性二面角
|
// 方向性あり二面角
|
||||||
|
float sign = signOrVolume < 0 ? -1 : 1;
|
||||||
restAngle *= sign;
|
restAngle *= sign;
|
||||||
result = DihedralAngle(sign, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer);
|
|
||||||
|
// マイナススケール
|
||||||
|
restAngle *= tdata.negativeScaleSign;
|
||||||
|
|
||||||
|
result = CalcDihedralAngle(sign, nextPosBuffer, invMassBuffer, restAngle, stiffness, ref addPosBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 集計バッファへ格納
|
// 集計バッファへ格納
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
int4 writeData = DataUtility.Unpack32(writeDataArray[dataIndex]);
|
|
||||||
int indexStart = tdata.bendingWriteIndexChunk.startIndex;
|
|
||||||
int bufferStart = tdata.bendingBufferChunk.startIndex;
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
int l_vindex = vertices[i];
|
pindex = pindex4[i];
|
||||||
int start = DataUtility.Unpack12_20Low(writeIndexArray[indexStart + l_vindex]);
|
InterlockUtility.AddFloat3(pindex, addPosBuffer[i], cntPt, sumPt);
|
||||||
int bufferIndex = bufferStart + start + writeData[i];
|
}
|
||||||
writeBuffer[bufferIndex] = addPosBuffer[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Volume(in float3x4 nextPosBuffer, in float4 invMassBuffer, float volumeRest, float stiffness, ref float3x4 addPosBuffer)
|
internal unsafe static void SumConstraint(
|
||||||
|
DataChunk chunk,
|
||||||
|
// team
|
||||||
|
ref TeamManager.TeamData tdata,
|
||||||
|
ref ClothParameters param,
|
||||||
|
// vmesh
|
||||||
|
ref NativeArray<VertexAttribute> attributes,
|
||||||
|
// particle
|
||||||
|
ref NativeArray<float3> nextPosArray,
|
||||||
|
// buffer2
|
||||||
|
ref NativeArray<float3> tempVectorBufferA,
|
||||||
|
ref NativeArray<int> tempCountBuffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (param.triangleBendingConstraint.method == Method.None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tdata.bendingPairChunk.IsValid == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 剛性
|
||||||
|
float stiffness = param.triangleBendingConstraint.stiffness;
|
||||||
|
if (stiffness < 1e-06f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int p_start = tdata.particleChunk.startIndex;
|
||||||
|
int v_start = tdata.proxyCommonChunk.startIndex;
|
||||||
|
|
||||||
|
int* sumPt = (int*)tempVectorBufferA.GetUnsafePtr();
|
||||||
|
int* cntPt = (int*)tempCountBuffer.GetUnsafePtr();
|
||||||
|
|
||||||
|
// ■集計
|
||||||
|
// パーティクルごと
|
||||||
|
int pindex = p_start + chunk.startIndex;
|
||||||
|
int vindex = v_start + chunk.startIndex;
|
||||||
|
//for (int k = 0; k < tdata.particleChunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
for (int k = 0; k < chunk.dataLength; k++, pindex++, vindex++)
|
||||||
|
{
|
||||||
|
// 移動のみ
|
||||||
|
if (attributes[vindex].IsDontMove() == false)
|
||||||
|
{
|
||||||
|
int cnt = cntPt[pindex];
|
||||||
|
if (cnt > 0)
|
||||||
|
{
|
||||||
|
int pindex2 = pindex * 3;
|
||||||
|
float3 add = new float3(sumPt[pindex2], sumPt[pindex2 + 1], sumPt[pindex2 + 2]);
|
||||||
|
add /= cnt;
|
||||||
|
// データは固定小数点なので戻す
|
||||||
|
add *= InterlockUtility.ToFloat;
|
||||||
|
|
||||||
|
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// バッファクリア
|
||||||
|
tempCountBuffer[pindex] = 0;
|
||||||
|
tempVectorBufferA[pindex] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CalcVolume(
|
||||||
|
in float3x4 nextPosBuffer,
|
||||||
|
in float4 invMassBuffer,
|
||||||
|
float volumeRest,
|
||||||
|
float stiffness,
|
||||||
|
ref float3x4 addPosBuffer
|
||||||
|
)
|
||||||
{
|
{
|
||||||
float3 nextPos0 = nextPosBuffer[0];
|
float3 nextPos0 = nextPosBuffer[0];
|
||||||
float3 nextPos1 = nextPosBuffer[1];
|
float3 nextPos1 = nextPosBuffer[1];
|
||||||
@ -649,6 +620,7 @@ namespace MagicaCloth2
|
|||||||
float invMass3 = invMassBuffer[3];
|
float invMass3 = invMassBuffer[3];
|
||||||
|
|
||||||
float volume = (1.0f / 6.0f) * math.dot(math.cross(nextPos1 - nextPos0, nextPos2 - nextPos0), nextPos3 - nextPos0);
|
float volume = (1.0f / 6.0f) * math.dot(math.cross(nextPos1 - nextPos0, nextPos2 - nextPos0), nextPos3 - nextPos0);
|
||||||
|
volume *= VolumeScale; // 浮動小数点演算誤差回避
|
||||||
|
|
||||||
float3 grad0 = math.cross(nextPos1 - nextPos2, nextPos3 - nextPos2);
|
float3 grad0 = math.cross(nextPos1 - nextPos2, nextPos3 - nextPos2);
|
||||||
float3 grad1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0);
|
float3 grad1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0);
|
||||||
@ -660,21 +632,29 @@ namespace MagicaCloth2
|
|||||||
invMass1 * math.lengthsq(grad1) +
|
invMass1 * math.lengthsq(grad1) +
|
||||||
invMass2 * math.lengthsq(grad2) +
|
invMass2 * math.lengthsq(grad2) +
|
||||||
invMass3 * math.lengthsq(grad3);
|
invMass3 * math.lengthsq(grad3);
|
||||||
|
lambda *= VolumeScale; // 浮動小数点演算誤差回避
|
||||||
|
|
||||||
if (math.abs(lambda) < 1e-06f)
|
if (math.abs(lambda) < 1e-06f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
lambda = stiffness * (volume - volumeRest) / lambda;
|
lambda = stiffness * (volumeRest - volume) / lambda;
|
||||||
|
|
||||||
addPosBuffer[0] = -lambda * invMass0 * grad0;
|
addPosBuffer[0] = lambda * invMass0 * grad0;
|
||||||
addPosBuffer[1] = -lambda * invMass1 * grad1;
|
addPosBuffer[1] = lambda * invMass1 * grad1;
|
||||||
addPosBuffer[2] = -lambda * invMass2 * grad2;
|
addPosBuffer[2] = lambda * invMass2 * grad2;
|
||||||
addPosBuffer[3] = -lambda * invMass3 * grad3;
|
addPosBuffer[3] = lambda * invMass3 * grad3;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DihedralAngle(float sign, in float3x4 nextPosBuffer, in float4 invMassBuffer, float restAngle, float stiffness, ref float3x4 addPosBuffer)
|
static bool CalcDihedralAngle(
|
||||||
|
float sign,
|
||||||
|
in float3x4 nextPosBuffer,
|
||||||
|
in float4 invMassBuffer,
|
||||||
|
float restAngle,
|
||||||
|
float stiffness,
|
||||||
|
ref float3x4 addPosBuffer
|
||||||
|
)
|
||||||
{
|
{
|
||||||
float3 nextPos0 = nextPosBuffer[0];
|
float3 nextPos0 = nextPosBuffer[0];
|
||||||
float3 nextPos1 = nextPosBuffer[1];
|
float3 nextPos1 = nextPosBuffer[1];
|
||||||
@ -695,6 +675,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
float3 n1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0);
|
float3 n1 = math.cross(nextPos2 - nextPos0, nextPos3 - nextPos0);
|
||||||
float3 n2 = math.cross(nextPos3 - nextPos1, nextPos2 - nextPos1);
|
float3 n2 = math.cross(nextPos3 - nextPos1, nextPos2 - nextPos1);
|
||||||
|
|
||||||
float n1_lengsq = math.lengthsq(n1);
|
float n1_lengsq = math.lengthsq(n1);
|
||||||
float n2_lengsq = math.lengthsq(n2);
|
float n2_lengsq = math.lengthsq(n2);
|
||||||
|
|
||||||
@ -717,14 +698,6 @@ namespace MagicaCloth2
|
|||||||
dot = MathUtility.Clamp1(dot);
|
dot = MathUtility.Clamp1(dot);
|
||||||
float phi = math.acos(dot);
|
float phi = math.acos(dot);
|
||||||
|
|
||||||
// 方向性
|
|
||||||
float dir = math.dot(math.cross(n1, n2), e);
|
|
||||||
if (sign != 0)
|
|
||||||
{
|
|
||||||
phi *= math.sign(dir);
|
|
||||||
dir = 1; // lambdaを反転させるため
|
|
||||||
}
|
|
||||||
|
|
||||||
float lambda =
|
float lambda =
|
||||||
invMass0 * math.lengthsq(d0) +
|
invMass0 * math.lengthsq(d0) +
|
||||||
invMass1 * math.lengthsq(d1) +
|
invMass1 * math.lengthsq(d1) +
|
||||||
@ -734,10 +707,20 @@ namespace MagicaCloth2
|
|||||||
if (lambda == 0.0f)
|
if (lambda == 0.0f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
lambda = (phi - restAngle) / lambda * stiffness;
|
// 方向性
|
||||||
|
float dirSign = math.sign(math.dot(math.cross(n1, n2), e));
|
||||||
|
if (sign != 0)
|
||||||
|
{
|
||||||
|
// 方向性あり(DirectionDihedralAngle)
|
||||||
|
phi *= dirSign;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 方向性なし(DihedralAngle)
|
||||||
|
lambda *= dirSign;
|
||||||
|
}
|
||||||
|
|
||||||
if (dir > 0.0f)
|
lambda = (restAngle - phi) / lambda * stiffness;
|
||||||
lambda = -lambda;
|
|
||||||
|
|
||||||
float3 corr0 = -invMass0 * lambda * d0;
|
float3 corr0 = -invMass0 * lambda * d0;
|
||||||
float3 corr1 = -invMass1 * lambda * d1;
|
float3 corr1 = -invMass1 * lambda * d1;
|
||||||
@ -752,66 +735,4 @@ namespace MagicaCloth2
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct SolveAggregateBufferJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> stepParticleIndexArray;
|
|
||||||
|
|
||||||
// team
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<TeamManager.TeamData> teamDataArray;
|
|
||||||
|
|
||||||
// vmesh
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<VertexAttribute> attributes;
|
|
||||||
|
|
||||||
// particle
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<short> teamIdArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
|
|
||||||
// constraint
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<uint> writeIndexArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> writeBuffer;
|
|
||||||
|
|
||||||
// ステップパーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
// pindexのチームは有効であることが保証されている
|
|
||||||
int pindex = stepParticleIndexArray[index];
|
|
||||||
int teamId = teamIdArray[pindex];
|
|
||||||
var tdata = teamDataArray[teamId];
|
|
||||||
if (tdata.bendingPairChunk.IsValid == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int l_index = pindex - tdata.particleChunk.startIndex;
|
|
||||||
|
|
||||||
// 固定なら無効
|
|
||||||
int vindex = tdata.proxyCommonChunk.startIndex + l_index;
|
|
||||||
if (attributes[vindex].IsDontMove())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 書き込みバッファの値を平均化してnextPosに加算する
|
|
||||||
uint pack = writeIndexArray[tdata.bendingWriteIndexChunk.startIndex + l_index];
|
|
||||||
int cnt = DataUtility.Unpack12_20Hi(pack);
|
|
||||||
int start = DataUtility.Unpack12_20Low(pack);
|
|
||||||
int bufferIndex = tdata.bendingBufferChunk.startIndex + start;
|
|
||||||
float3 add = 0;
|
|
||||||
for (int i = 0; i < cnt; i++)
|
|
||||||
{
|
|
||||||
add += writeBuffer[bufferIndex + i];
|
|
||||||
}
|
|
||||||
if (cnt > 0)
|
|
||||||
{
|
|
||||||
add /= cnt;
|
|
||||||
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
// Magica Cloth 2.
|
||||||
|
// Copyright (c) 2025 MagicaSoft.
|
||||||
|
// https://magicasoft.jp
|
||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
@ -83,8 +86,57 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Renderer> cameraCullingRenderers = new List<Renderer>();
|
public List<Renderer> cameraCullingRenderers = new List<Renderer>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 距離カリングの状態と距離
|
||||||
|
/// Distance Culling State and Distance.
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
public CheckSliderSerializeData distanceCullingLength;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 距離カリングのフェード割合(0.0 ~ 1.0)
|
||||||
|
/// Distance culling fade rate (0.0 to 1.0).
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
[Range(0.0f, 1.0f)]
|
||||||
|
public float distanceCullingFadeRatio;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 距離カリングの測定対象(None=メインカメラ)
|
||||||
|
/// Distance culling measurement target (None = main camera).
|
||||||
|
/// [OK] Runtime changes.
|
||||||
|
/// [NG] Export/Import with Presets
|
||||||
|
/// </summary>
|
||||||
|
public GameObject distanceCullingReferenceObject;
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
public struct CullingParams
|
||||||
|
{
|
||||||
|
public bool useDistanceCulling;
|
||||||
|
public float distanceCullingLength;
|
||||||
|
public float distanceCullingFadeRatio;
|
||||||
|
|
||||||
|
public void Convert(CullingSettings cullingSettings)
|
||||||
|
{
|
||||||
|
useDistanceCulling = cullingSettings.distanceCullingLength.use;
|
||||||
|
distanceCullingLength = cullingSettings.distanceCullingLength.value;
|
||||||
|
distanceCullingFadeRatio = cullingSettings.distanceCullingFadeRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
public CullingSettings()
|
||||||
|
{
|
||||||
|
distanceCullingLength = new CheckSliderSerializeData(false, 30.0f);
|
||||||
|
distanceCullingFadeRatio = 0.2f;
|
||||||
|
}
|
||||||
|
|
||||||
public void DataValidate()
|
public void DataValidate()
|
||||||
{
|
{
|
||||||
|
distanceCullingLength.DataValidate(0.0f, Define.System.DistanceCullingMaxLength);
|
||||||
|
distanceCullingFadeRatio = Mathf.Clamp01(distanceCullingFadeRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CullingSettings Clone()
|
public CullingSettings Clone()
|
||||||
@ -94,6 +146,9 @@ namespace MagicaCloth2
|
|||||||
cameraCullingMode = cameraCullingMode,
|
cameraCullingMode = cameraCullingMode,
|
||||||
cameraCullingMethod = cameraCullingMethod,
|
cameraCullingMethod = cameraCullingMethod,
|
||||||
cameraCullingRenderers = new List<Renderer>(cameraCullingRenderers),
|
cameraCullingRenderers = new List<Renderer>(cameraCullingRenderers),
|
||||||
|
distanceCullingLength = distanceCullingLength.Clone(),
|
||||||
|
distanceCullingFadeRatio = distanceCullingFadeRatio,
|
||||||
|
distanceCullingReferenceObject = distanceCullingReferenceObject,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,8 @@ namespace MagicaCloth2
|
|||||||
public bool enable = false;
|
public bool enable = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// bones for skinning.
|
/// Bones for custom skinning.
|
||||||
/// Calculated from the parent-child structure line of bones registered here.
|
/// カスタムスキニング用ボーン
|
||||||
/// スキニング用ボーン
|
|
||||||
/// ここに登録されたボーンの親子構造ラインから算出される
|
|
||||||
/// [NG] Runtime changes.
|
/// [NG] Runtime changes.
|
||||||
/// [NG] Export/Import with Presets
|
/// [NG] Export/Import with Presets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -42,7 +42,14 @@ namespace MagicaCloth2
|
|||||||
/// General processing.
|
/// General processing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ClothProcess process = new ClothProcess();
|
private ClothProcess process = new ClothProcess();
|
||||||
public ClothProcess Process { get { process.cloth = this; return process; } }
|
public ClothProcess Process
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
process.cloth = this;
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cloth component transform.
|
/// Cloth component transform.
|
||||||
@ -53,7 +60,14 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Synchronization target.
|
/// Synchronization target.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MagicaCloth SyncCloth => SerializeData.IsBoneSpring() ? null : SerializeData.selfCollisionConstraint.GetSyncPartner();
|
public MagicaCloth SyncPartnerCloth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var syncCloth = SerializeData.IsBoneSpring() ? null : SerializeData.selfCollisionConstraint.GetSyncPartner();
|
||||||
|
return syncCloth == this ? null : syncCloth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if the cloth component is in a valid state.
|
/// Check if the cloth component is in a valid state.
|
||||||
@ -66,18 +80,27 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
|
private void Reset()
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
// Automatically generate pre-build ID
|
||||||
|
serializeData2.preBuildData.buildId = PreBuildSerializeData.GenerateBuildID();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
Process.DataUpdate();
|
Process.DataUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (MagicaManager.initializationLocation == MagicaManager.InitializationLocation.Awake)
|
||||||
{
|
{
|
||||||
Process.Init();
|
Process.Init();
|
||||||
|
|
||||||
// If Awake() is called, OnDestroy() will also be called, so remove it from monitoring.
|
|
||||||
MagicaManager.Team.RemoveMonitoringProcess(Process);
|
MagicaManager.Team.RemoveMonitoringProcess(Process);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
@ -91,6 +114,12 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
|
if (MagicaManager.initializationLocation == MagicaManager.InitializationLocation.Start)
|
||||||
|
{
|
||||||
|
Process.Init();
|
||||||
|
MagicaManager.Team.RemoveMonitoringProcess(Process);
|
||||||
|
}
|
||||||
|
|
||||||
Process.AutoBuild();
|
Process.AutoBuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ MonoImporter:
|
|||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 5
|
||||||
icon: {fileID: 2800000, guid: cf7e3400035e987478c3a19e57b4cf75, type: 3}
|
icon: {fileID: 2800000, guid: cf7e3400035e987478c3a19e57b4cf75, type: 3}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
|
|||||||
@ -29,8 +29,14 @@ namespace MagicaCloth2
|
|||||||
/// Event after completion of cloth data construction.
|
/// Event after completion of cloth data construction.
|
||||||
/// (true = Success, false = Failure)
|
/// (true = Success, false = Failure)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<bool> OnBuildComplete;
|
public Action<MagicaCloth, bool> OnBuildComplete;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// レンダラーメッシュ変更後イベント
|
||||||
|
/// Renderer mesh change event.
|
||||||
|
/// (true = Change to custom mesh, false = Change to original mesh)
|
||||||
|
/// </summary>
|
||||||
|
public Action<MagicaCloth, Renderer, bool> OnRendererMeshChange;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初期化を実行します
|
/// 初期化を実行します
|
||||||
@ -66,22 +72,33 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>true=start build. false=build failed.</returns>
|
/// <returns>true=start build. false=build failed.</returns>
|
||||||
public bool BuildAndRun()
|
public bool BuildAndRun()
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
bool buildComplate = true;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (Application.isPlaying == false)
|
if (Application.isPlaying == false)
|
||||||
return false;
|
throw new MagicaClothProcessingException();
|
||||||
|
|
||||||
DisableAutoBuild();
|
DisableAutoBuild();
|
||||||
|
|
||||||
if (Process.IsState(ClothProcess.State_Build))
|
if (Process.IsState(ClothProcess.State_Build))
|
||||||
{
|
{
|
||||||
Develop.LogError($"Already built.:{this.name}");
|
Develop.LogError($"Already built.:{this.name}");
|
||||||
return false;
|
throw new MagicaClothProcessingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize generated data.
|
// initialize generated data.
|
||||||
if (Process.GenerateInitialization() == false)
|
if (Process.GenerateInitialization() == false)
|
||||||
return false;
|
throw new MagicaClothProcessingException();
|
||||||
|
|
||||||
|
// check Pre-Build
|
||||||
|
bool usePreBuildData = serializeData2.preBuildData.UsePreBuild();
|
||||||
|
|
||||||
|
if (usePreBuildData == false)
|
||||||
|
{
|
||||||
|
// Runtime Build.
|
||||||
// setting by type.
|
// setting by type.
|
||||||
switch (serializeData.clothType)
|
switch (serializeData.clothType)
|
||||||
{
|
{
|
||||||
@ -93,15 +110,37 @@ namespace MagicaCloth2
|
|||||||
if (nowSelection == null || nowSelection.IsValid() == false || nowSelection.IsUserEdit() == false)
|
if (nowSelection == null || nowSelection.IsValid() == false || nowSelection.IsUserEdit() == false)
|
||||||
{
|
{
|
||||||
if (Process.GenerateBoneClothSelection() == false)
|
if (Process.GenerateBoneClothSelection() == false)
|
||||||
return false;
|
throw new MagicaClothProcessingException();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// build and run.
|
// build and run.
|
||||||
Process.StartBuild();
|
ret = Process.StartRuntimeBuild();
|
||||||
|
if (ret)
|
||||||
|
buildComplate = false; // OnBuildCompleteはランタイム構築後に呼ばれる
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pre-build
|
||||||
|
ret = Process.PreBuildDataConstruction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MagicaClothProcessingException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Debug.LogException(exception);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// ビルド完了イベント
|
||||||
|
if (buildComplate)
|
||||||
|
OnBuildComplete?.Invoke(this, ret);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -123,7 +162,7 @@ namespace MagicaCloth2
|
|||||||
var replaceDict = new Dictionary<int, Transform>();
|
var replaceDict = new Dictionary<int, Transform>();
|
||||||
foreach (var t in useTransformSet)
|
foreach (var t in useTransformSet)
|
||||||
{
|
{
|
||||||
if (targetTransformDict.ContainsKey(t.name))
|
if (t && targetTransformDict.ContainsKey(t.name))
|
||||||
{
|
{
|
||||||
replaceDict.Add(t.GetInstanceID(), targetTransformDict[t.name]);
|
replaceDict.Add(t.GetInstanceID(), targetTransformDict[t.name]);
|
||||||
}
|
}
|
||||||
@ -133,6 +172,18 @@ namespace MagicaCloth2
|
|||||||
Process.ReplaceTransform(replaceDict);
|
Process.ReplaceTransform(replaceDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// コンポーネントが保持するすべてのトランスフォームを取得します。
|
||||||
|
/// Gets all the transforms held by the component.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public HashSet<Transform> GetUsedTransform()
|
||||||
|
{
|
||||||
|
var useTransformSet = new HashSet<Transform>();
|
||||||
|
Process.GetUsedTransform(useTransformSet);
|
||||||
|
return useTransformSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// パラメータの変更を通知
|
/// パラメータの変更を通知
|
||||||
@ -197,8 +248,8 @@ namespace MagicaCloth2
|
|||||||
// Reset
|
// Reset
|
||||||
tdata.flag.SetBits(TeamManager.Flag_Reset, true);
|
tdata.flag.SetBits(TeamManager.Flag_Reset, true);
|
||||||
tdata.flag.SetBits(TeamManager.Flag_TimeReset, true);
|
tdata.flag.SetBits(TeamManager.Flag_TimeReset, true);
|
||||||
tdata.flag.SetBits(TeamManager.Flag_CullingKeep, false);
|
tdata.flag.SetBits(TeamManager.Flag_CameraCullingKeep, false);
|
||||||
Process.SetState(ClothProcess.State_CullingKeep, false);
|
Process.SetState(ClothProcess.State_CameraCullingKeep, false);
|
||||||
Process.UpdateRendererUse();
|
Process.UpdateRendererUse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,5 +302,50 @@ namespace MagicaCloth2
|
|||||||
Process.SetSkipWriting(sw);
|
Process.SetSkipWriting(sw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RenderData GetRenderData(Renderer ren)
|
||||||
|
{
|
||||||
|
if (IsValid() == false || ren == null)
|
||||||
|
return null;
|
||||||
|
int handle = ren.GetInstanceID();
|
||||||
|
return MagicaManager.Render.GetRendererData(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MeshClothのオリジナルメッシュを取得します
|
||||||
|
/// Get the original mesh of MeshCloth.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ren"></param>
|
||||||
|
/// <returns>null if not found</returns>
|
||||||
|
public Mesh GetOriginalMesh(Renderer ren)
|
||||||
|
{
|
||||||
|
return GetRenderData(ren)?.originalMesh ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MeshClothのカスタムメッシュを取得します
|
||||||
|
/// Get the custom mesh for MeshCloth.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ren"></param>
|
||||||
|
/// <returns>null if not found</returns>
|
||||||
|
public Mesh GetCustomMesh(Renderer ren)
|
||||||
|
{
|
||||||
|
return GetRenderData(ren)?.customMesh ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MeshClothのSkinnedMeshRendererに設定されているカスタムボーンリストを取得します
|
||||||
|
/// カスタムボーンリストはオリジナルのBonesからスキニングに不要なTransformをnullに設定し、
|
||||||
|
/// また最後にレンダラーのTransformが追加されるなど加工されているので注意してください。
|
||||||
|
/// Gets the custom bone list set for the SkinnedMeshRenderer of MeshCloth.
|
||||||
|
/// Please note that the custom bone list has been processed by setting Transforms
|
||||||
|
/// that are not necessary for skinning to null from the original Bones, and adding the renderer Transform at the end.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ren"></param>
|
||||||
|
/// <returns>null if not found</returns>
|
||||||
|
public List<Transform> GetCustomBones(Renderer ren)
|
||||||
|
{
|
||||||
|
return GetRenderData(ren)?.transformList ?? null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -212,13 +212,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Fill(VertexAttribute attr)
|
public void Fill(VertexAttribute attr)
|
||||||
{
|
{
|
||||||
#if UNITY_2020
|
|
||||||
int cnt = Count;
|
|
||||||
for (int i = 0; i < cnt; i++)
|
|
||||||
attributes[i] = attr;
|
|
||||||
#else
|
|
||||||
Array.Fill(attributes, attr);
|
Array.Fill(attributes, attr);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
|
|||||||
@ -200,8 +200,9 @@ namespace MagicaCloth2
|
|||||||
public void SetWindDirection(Vector3 dir, bool localSpace = false)
|
public void SetWindDirection(Vector3 dir, bool localSpace = false)
|
||||||
{
|
{
|
||||||
Vector3 lv = localSpace ? dir : transform.InverseTransformDirection(dir);
|
Vector3 lv = localSpace ? dir : transform.InverseTransformDirection(dir);
|
||||||
directionAngleX = Mathf.Atan2(lv.z, lv.x) * Mathf.Rad2Deg;
|
var angles = Quaternion.FromToRotation(Vector3.forward, lv).eulerAngles;
|
||||||
directionAngleY = Mathf.Atan2(lv.z, lv.y) * Mathf.Rad2Deg;
|
directionAngleX = angles.x > 180 ? angles.x - 360 : angles.x;
|
||||||
|
directionAngleY = angles.y > 180 ? angles.y - 360 : angles.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,8 @@ namespace MagicaCloth2
|
|||||||
RenderMesh_UnknownWarning = 10100,
|
RenderMesh_UnknownWarning = 10100,
|
||||||
RenderMesh_VertexWeightIs5BonesOrMore,
|
RenderMesh_VertexWeightIs5BonesOrMore,
|
||||||
|
|
||||||
|
Init_NonUniformScale = 10200,
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
// Error(20000 - )
|
// Error(20000 - )
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
@ -42,11 +44,15 @@ namespace MagicaCloth2
|
|||||||
// Validating serialized data
|
// Validating serialized data
|
||||||
SerializeData_InvalidData = 20050,
|
SerializeData_InvalidData = 20050,
|
||||||
SerializeData_Over31Renderers,
|
SerializeData_Over31Renderers,
|
||||||
|
SerializeData_DuplicateRootBone,
|
||||||
|
SerializeData_DuplicateRenderer,
|
||||||
|
|
||||||
// init
|
// init
|
||||||
Init_InvalidData = 20100,
|
Init_InvalidData = 20100,
|
||||||
Init_InvalidPaintMap,
|
Init_InvalidPaintMap,
|
||||||
Init_PaintMapNotReadable,
|
Init_PaintMapNotReadable,
|
||||||
|
Init_ScaleIsZero,
|
||||||
|
Init_NegativeScale,
|
||||||
|
|
||||||
// RenderSetup
|
// RenderSetup
|
||||||
RenderSetup_Exception = 20200,
|
RenderSetup_Exception = 20200,
|
||||||
@ -76,6 +82,11 @@ namespace MagicaCloth2
|
|||||||
CreateCloth_InvalidPaintMap,
|
CreateCloth_InvalidPaintMap,
|
||||||
CreateCloth_PaintMapNotReadable,
|
CreateCloth_PaintMapNotReadable,
|
||||||
CreateCloth_PaintMapCountMismatch,
|
CreateCloth_PaintMapCountMismatch,
|
||||||
|
CreateCloth_CanNotStart,
|
||||||
|
CreateCloth_VertexAttributeListCountMismatch,
|
||||||
|
CreateCloth_VertexAttributeListIsNull,
|
||||||
|
CreateCloth_VertexAttributeListDataMismatch,
|
||||||
|
CreateCloth_InvalidVertexAttributeData,
|
||||||
|
|
||||||
// Reduction
|
// Reduction
|
||||||
Reduction_Exception = 20500,
|
Reduction_Exception = 20500,
|
||||||
@ -131,6 +142,41 @@ namespace MagicaCloth2
|
|||||||
MagicaMesh_Invalid,
|
MagicaMesh_Invalid,
|
||||||
MagicaMesh_InvalidRenderer,
|
MagicaMesh_InvalidRenderer,
|
||||||
MagicaMesh_InvalidMeshFilter,
|
MagicaMesh_InvalidMeshFilter,
|
||||||
|
|
||||||
|
// PreBuildData
|
||||||
|
PreBuildData_UnknownError = 22600,
|
||||||
|
PreBuildData_MagicaClothException,
|
||||||
|
PreBuildData_VirtualMeshDeserializationException,
|
||||||
|
PreBuildData_VerificationResult,
|
||||||
|
PreBuildData_VersionMismatch,
|
||||||
|
PreBuildData_InvalidClothData,
|
||||||
|
PreBuildData_Empty,
|
||||||
|
PreBuildData_InvalidScale,
|
||||||
|
|
||||||
|
// PreBuild
|
||||||
|
PreBuild_UnknownError = 22700,
|
||||||
|
PreBuild_Exception,
|
||||||
|
PreBuild_InvalidPreBuildData,
|
||||||
|
PreBuild_InvalidRenderSetupData,
|
||||||
|
PreBuild_SetupDeserializationError,
|
||||||
|
|
||||||
|
// PreBuild Deserialization
|
||||||
|
Deserialization_UnknownError = 22800,
|
||||||
|
Deserialization_Exception,
|
||||||
|
|
||||||
|
// Init SerializeData
|
||||||
|
InitSerializeData_UnknownError = 22900,
|
||||||
|
InitSerializeData_InvalidHash,
|
||||||
|
InitSerializeData_InvalidVersion,
|
||||||
|
InitSerializeData_InvalidSetupData,
|
||||||
|
InitSerializeData_ClothTypeMismatch,
|
||||||
|
InitSerializeData_SetupCountMismatch,
|
||||||
|
InitSerializeData_CustomSkinningBoneCountMismatch,
|
||||||
|
InitSerializeData_MeshClothSetupValidationError,
|
||||||
|
InitSerializeData_BoneClothSetupValidationError,
|
||||||
|
InitSerializeData_BoneSpringSetupValidationError,
|
||||||
|
InitSerializeData_DeserializationError,
|
||||||
|
InitSerializeData_InvalidCloneMesh,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,11 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string DefineSymbol = "MAGICACLOTH2";
|
public const string DefineSymbol = "MAGICACLOTH2";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 現在有効なPreBuildの最新バージョン
|
||||||
|
/// </summary>
|
||||||
|
public const int LatestPreBuildVersion = 2;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 計算を省略する最小の浮動小数点数
|
/// 計算を省略する最小の浮動小数点数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -72,6 +77,16 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const float SameSurfaceAngle = 80.0f;
|
public const float SameSurfaceAngle = 80.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 未来予測時のルートからの距離制限倍率
|
||||||
|
/// </summary>
|
||||||
|
public const float MaxDistanceRatioFutuerPrediction = 1.3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分割ジョブを適用するプロキシメッシュメッシュの頂点数
|
||||||
|
/// </summary>
|
||||||
|
public const int SplitProxyMeshVertexCount = 300;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Reduction]
|
/// [Reduction]
|
||||||
/// 有効フラグ。常にtrueとする。
|
/// 有効フラグ。常にtrueとする。
|
||||||
@ -319,7 +334,19 @@ namespace MagicaCloth2
|
|||||||
/// [Self Collision]
|
/// [Self Collision]
|
||||||
/// 反復回数
|
/// 反復回数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int SelfCollisionSolverIteration = 4;
|
public const int SelfCollisionSolverIteration = 4; // 4
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Self Collision]
|
||||||
|
/// 無効グリッド座標
|
||||||
|
/// </summary>
|
||||||
|
public const int SelfCollisionIgnoreGrid = 1000000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Self Collision]
|
||||||
|
/// 交差判定の分割数
|
||||||
|
/// </summary>
|
||||||
|
public const int SelfCollisionIntersectDiv = 2; // 8
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Self Collision]
|
/// [Self Collision]
|
||||||
@ -351,12 +378,6 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly float SelfCollisionPointTriangleAngleCos = math.cos(math.radians(60.0f));
|
public static readonly float SelfCollisionPointTriangleAngleCos = math.cos(math.radians(60.0f));
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// [Self Collision]
|
|
||||||
/// 交差判定の分割数
|
|
||||||
/// </summary>
|
|
||||||
public const int SelfCollisionIntersectDiv = 8;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Self Collision]
|
/// [Self Collision]
|
||||||
/// Thicknessの最小値(m)
|
/// Thicknessの最小値(m)
|
||||||
@ -398,6 +419,12 @@ namespace MagicaCloth2
|
|||||||
/// BoneSpring利用時のfriction値
|
/// BoneSpring利用時のfriction値
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float BoneSpringCollisionFriction = 0.5f;
|
public const float BoneSpringCollisionFriction = 0.5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Culling]
|
||||||
|
/// 距離カリングの最大距離
|
||||||
|
/// </summary>
|
||||||
|
public const float DistanceCullingMaxLength = 100.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace MagicaCloth2
|
|||||||
public class ClothManager : IManager, IValid
|
public class ClothManager : IManager, IValid
|
||||||
{
|
{
|
||||||
// すべて
|
// すべて
|
||||||
internal HashSet<ClothProcess> clothSet = new HashSet<ClothProcess>();
|
internal HashSet<ClothProcess> clothSet = new HashSet<ClothProcess>(256);
|
||||||
|
|
||||||
// BoneCloth,BoneSpring
|
// BoneCloth,BoneSpring
|
||||||
internal HashSet<ClothProcess> boneClothSet = new HashSet<ClothProcess>();
|
internal HashSet<ClothProcess> boneClothSet = new HashSet<ClothProcess>();
|
||||||
@ -50,6 +50,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 更新処理
|
// 更新処理
|
||||||
MagicaManager.afterEarlyUpdateDelegate -= OnEarlyClothUpdate;
|
MagicaManager.afterEarlyUpdateDelegate -= OnEarlyClothUpdate;
|
||||||
|
MagicaManager.firstPreUpdateDelegate -= OnFirstPreUpdate;
|
||||||
MagicaManager.afterLateUpdateDelegate -= OnAfterLateUpdate;
|
MagicaManager.afterLateUpdateDelegate -= OnAfterLateUpdate;
|
||||||
MagicaManager.beforeLateUpdateDelegate -= OnBeforeLateUpdate;
|
MagicaManager.beforeLateUpdateDelegate -= OnBeforeLateUpdate;
|
||||||
}
|
}
|
||||||
@ -69,6 +70,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 更新処理
|
// 更新処理
|
||||||
MagicaManager.afterEarlyUpdateDelegate += OnEarlyClothUpdate;
|
MagicaManager.afterEarlyUpdateDelegate += OnEarlyClothUpdate;
|
||||||
|
MagicaManager.firstPreUpdateDelegate += OnFirstPreUpdate;
|
||||||
MagicaManager.afterLateUpdateDelegate += OnAfterLateUpdate;
|
MagicaManager.afterLateUpdateDelegate += OnAfterLateUpdate;
|
||||||
MagicaManager.beforeLateUpdateDelegate += OnBeforeLateUpdate;
|
MagicaManager.beforeLateUpdateDelegate += OnBeforeLateUpdate;
|
||||||
|
|
||||||
@ -118,6 +120,9 @@ namespace MagicaCloth2
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// チームマネージャの作業バッファへ登録
|
||||||
|
MagicaManager.Team.comp2TeamIdMap.Add(cprocess.cloth.GetInstanceID(), teamId);
|
||||||
|
|
||||||
return teamId;
|
return teamId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,11 +145,15 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void OnEarlyClothUpdate()
|
void OnEarlyClothUpdate()
|
||||||
{
|
{
|
||||||
|
//Debug.Log($"OnEarlyClothUpdate. F:{Time.frameCount}");
|
||||||
|
if (MagicaManager.Team.TrueTeamCount > 0) // カリング判定があるのでDisableチームもまわす必要がある
|
||||||
|
{
|
||||||
|
// カメラカリング更新
|
||||||
if (MagicaManager.Team.ActiveTeamCount > 0)
|
if (MagicaManager.Team.ActiveTeamCount > 0)
|
||||||
{
|
{
|
||||||
//Debug.Log($"TransformRestoreUpdate. F:{Time.frameCount}");
|
// この更新は次のTransform復元の前に行う必要がある
|
||||||
// チームカリング更新
|
MagicaManager.Team.CameraCullingPostProcess();
|
||||||
MagicaManager.Team.TeamCullingUpdate();
|
}
|
||||||
|
|
||||||
// BoneClothのTransform復元更新
|
// BoneClothのTransform復元更新
|
||||||
ClearMasterJob();
|
ClearMasterJob();
|
||||||
@ -153,6 +162,25 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PreUpdate開始時に実行される更新処理
|
||||||
|
/// </summary>
|
||||||
|
void OnFirstPreUpdate()
|
||||||
|
{
|
||||||
|
//Debug.Log($"OnFirstPreUpdate. F:{Time.frameCount}");
|
||||||
|
if (MagicaManager.Team.TrueTeamCount > 0) // カリング判定があるのでDisableチームもまわす必要がある
|
||||||
|
{
|
||||||
|
//Debug.Log($"existFixedTeam:{MagicaManager.Bone.existFixedTeam.Value}");
|
||||||
|
// FixedUpdateが0回かつFixedTeamが存在する場合のみ
|
||||||
|
if (MagicaManager.Time.FixedUpdateCount == 0 && MagicaManager.Bone.existFixedTeam.Value)
|
||||||
|
{
|
||||||
|
ClearMasterJob();
|
||||||
|
masterJob = MagicaManager.Bone.RestoreBaseTransform(masterJob);
|
||||||
|
CompleteMasterJob();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OnBeforeLateUpdate()
|
void OnBeforeLateUpdate()
|
||||||
{
|
{
|
||||||
if (MagicaManager.Time.updateLocation == TimeManager.UpdateLocation.BeforeLateUpdate)
|
if (MagicaManager.Time.updateLocation == TimeManager.UpdateLocation.BeforeLateUpdate)
|
||||||
@ -166,7 +194,9 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
static readonly ProfilerMarker startClothUpdateMainProfiler = new ProfilerMarker("StartClothUpdate.Main");
|
static readonly ProfilerMarker startClothUpdateTimeProfiler = new ProfilerMarker("StartClothUpdate.Time");
|
||||||
|
static readonly ProfilerMarker startClothUpdateTeamProfiler = new ProfilerMarker("StartClothUpdate.Team");
|
||||||
|
static readonly ProfilerMarker startClothUpdatePrePareProfiler = new ProfilerMarker("StartClothUpdate.Prepare");
|
||||||
static readonly ProfilerMarker startClothUpdateScheduleProfiler = new ProfilerMarker("StartClothUpdate.Schedule");
|
static readonly ProfilerMarker startClothUpdateScheduleProfiler = new ProfilerMarker("StartClothUpdate.Schedule");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -177,13 +207,16 @@ namespace MagicaCloth2
|
|||||||
if (MagicaManager.IsPlaying() == false)
|
if (MagicaManager.IsPlaying() == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// ■コンポーネント0なら終了
|
||||||
|
var tm = MagicaManager.Team;
|
||||||
|
if (tm.TrueTeamCount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// シミュレーション開始イベント
|
// シミュレーション開始イベント
|
||||||
MagicaManager.OnPreSimulation?.Invoke();
|
MagicaManager.OnPreSimulation?.Invoke();
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
var tm = MagicaManager.Team;
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
var sm = MagicaManager.Simulation;
|
var sm = MagicaManager.Simulation;
|
||||||
var bm = MagicaManager.Bone;
|
var bm = MagicaManager.Bone;
|
||||||
var wm = MagicaManager.Wind;
|
var wm = MagicaManager.Wind;
|
||||||
@ -192,22 +225,21 @@ namespace MagicaCloth2
|
|||||||
//Develop.DebugLog($"StartClothUpdate. F:{Time.frameCount}, dtime:{Time.deltaTime}, stime:{Time.smoothDeltaTime}");
|
//Develop.DebugLog($"StartClothUpdate. F:{Time.frameCount}, dtime:{Time.deltaTime}, stime:{Time.smoothDeltaTime}");
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
startClothUpdateMainProfiler.Begin();
|
|
||||||
// ■時間マネージャ更新
|
// ■時間マネージャ更新
|
||||||
|
startClothUpdateTimeProfiler.Begin();
|
||||||
MagicaManager.Time.FrameUpdate();
|
MagicaManager.Time.FrameUpdate();
|
||||||
|
startClothUpdateTimeProfiler.End();
|
||||||
|
|
||||||
// ■常に実行するチーム更新
|
// ■常に実行するチーム更新
|
||||||
|
startClothUpdateTeamProfiler.Begin();
|
||||||
tm.AlwaysTeamUpdate();
|
tm.AlwaysTeamUpdate();
|
||||||
|
startClothUpdateTeamProfiler.End();
|
||||||
|
|
||||||
// ■ここで実行チーム数が0ならば終了
|
// ■ここで実行チーム数が0ならば終了
|
||||||
if (tm.ActiveTeamCount == 0)
|
if (tm.ActiveTeamCount == 0)
|
||||||
{
|
|
||||||
startClothUpdateMainProfiler.End();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
int maxUpdateCount = tm.maxUpdateCount.Value;
|
startClothUpdatePrePareProfiler.Begin();
|
||||||
//Debug.Log($"maxUpdateCount:{maxUpdateCount}");
|
|
||||||
|
|
||||||
// ■常に実行する風ゾーン更新
|
// ■常に実行する風ゾーン更新
|
||||||
wm.AlwaysWindUpdate();
|
wm.AlwaysWindUpdate();
|
||||||
@ -215,106 +247,32 @@ namespace MagicaCloth2
|
|||||||
// ■作業バッファ更新
|
// ■作業バッファ更新
|
||||||
sm.WorkBufferUpdate();
|
sm.WorkBufferUpdate();
|
||||||
|
|
||||||
startClothUpdateMainProfiler.End();
|
startClothUpdatePrePareProfiler.End();
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if true
|
|
||||||
startClothUpdateScheduleProfiler.Begin();
|
startClothUpdateScheduleProfiler.Begin();
|
||||||
|
|
||||||
// マスタージョブ初期化
|
// マスタージョブ初期化
|
||||||
ClearMasterJob();
|
ClearMasterJob();
|
||||||
|
|
||||||
// ■トランスフォーム情報の読み込み
|
// ■トランスフォーム情報の読み込み
|
||||||
masterJob = bm.ReadTransform(masterJob);
|
masterJob = bm.ReadTransformSchedule(masterJob);
|
||||||
|
|
||||||
// ■プロキシメッシュをスキニングし基本姿勢を求める
|
// ■シミュレーションジョブ
|
||||||
masterJob = vm.PreProxyMeshUpdate(masterJob);
|
masterJob = sm.ClothSimulationSchedule(masterJob);
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// チームのセンター姿勢の決定と慣性用の移動量計算
|
|
||||||
masterJob = tm.CalcCenterAndInertiaAndWind(masterJob);
|
|
||||||
|
|
||||||
// パーティクルリセットの適用
|
|
||||||
masterJob = sm.PreSimulationUpdate(masterJob);
|
|
||||||
|
|
||||||
// ■コライダーのローカル姿勢を求める
|
|
||||||
masterJob = MagicaManager.Collider.PreSimulationUpdate(masterJob);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// ■クロスシミュレーション実行
|
|
||||||
// ステップ実行
|
|
||||||
for (int i = 0; i < maxUpdateCount; i++)
|
|
||||||
{
|
|
||||||
masterJob = sm.SimulationStepUpdate(maxUpdateCount, i, masterJob);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// 表示位置の決定
|
|
||||||
masterJob = sm.CalcDisplayPosition(masterJob);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// ■クロスシミュレーション後の頂点姿勢計算
|
|
||||||
// プロキシメッシュの頂点から法線接線を求め姿勢を確定させる
|
|
||||||
// ラインがある場合はベースラインごとに姿勢を整える
|
|
||||||
// BoneClothの場合は頂点姿勢を連動するトランスフォームデータにコピーする
|
|
||||||
masterJob = vm.PostProxyMeshUpdate(masterJob);
|
|
||||||
|
|
||||||
// マッピングメッシュ
|
|
||||||
int mappingCount = tm.MappingCount;
|
|
||||||
if (mappingCount > 0)
|
|
||||||
{
|
|
||||||
// マッピングメッシュ頂点姿勢をプロキシメッシュからスキニングし求める
|
|
||||||
// マッピングメッシュのローカル空間に座標変換する
|
|
||||||
masterJob = vm.PostMappingMeshUpdate(masterJob);
|
|
||||||
|
|
||||||
// レンダーデータへ反映する
|
|
||||||
foreach (var cprocess in meshClothSet)
|
|
||||||
{
|
|
||||||
if (cprocess == null || cprocess.IsValid() == false || cprocess.IsEnable == false)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// カリングによる非表示中ならば書き込まない
|
|
||||||
if (cprocess.IsCullingInvisible())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int cnt = cprocess.renderMeshInfoList.Count;
|
|
||||||
for (int i = 0; i < cnt; i++)
|
|
||||||
{
|
|
||||||
var info = cprocess.renderMeshInfoList[i];
|
|
||||||
var renderData = MagicaManager.Render.GetRendererData(info.renderHandle);
|
|
||||||
|
|
||||||
// Position/Normal書き込み
|
|
||||||
masterJob = renderData.UpdatePositionNormal(info.mappingChunk, masterJob);
|
|
||||||
|
|
||||||
// BoneWeight書き込み
|
|
||||||
if (renderData.ChangeCustomMesh)
|
|
||||||
{
|
|
||||||
masterJob = renderData.UpdateBoneWeight(info.mappingChunk, masterJob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// ■BoneClothのTransformへの書き込み
|
|
||||||
masterJob = bm.WriteTransform(masterJob);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// ■コライダー更新後処理
|
|
||||||
masterJob = MagicaManager.Collider.PostSimulationUpdate(masterJob);
|
|
||||||
|
|
||||||
// ■チーム更新後処理
|
|
||||||
masterJob = tm.PostTeamUpdate(masterJob);
|
|
||||||
|
|
||||||
startClothUpdateScheduleProfiler.End();
|
startClothUpdateScheduleProfiler.End();
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
//JobHandle.ScheduleBatchedJobs();
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// ジョブを即実行
|
// ■ジョブ完了待ちの間に行う処理
|
||||||
//JobHandle.ScheduleBatchedJobs();
|
// カメラカリングの準備
|
||||||
|
tm.CameraCullingPreProcess();
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// ■現在は即時実行のためここでジョブの完了待ちを行う
|
// ■現在は即時実行のためここでジョブの完了待ちを行う
|
||||||
CompleteMasterJob();
|
CompleteMasterJob();
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// シミュレーション終了イベント
|
// シミュレーション終了イベント
|
||||||
|
|||||||
@ -40,6 +40,7 @@ namespace MagicaCloth2
|
|||||||
public static SimulationManager Simulation => managers?[6] as SimulationManager;
|
public static SimulationManager Simulation => managers?[6] as SimulationManager;
|
||||||
public static ColliderManager Collider => managers?[7] as ColliderManager;
|
public static ColliderManager Collider => managers?[7] as ColliderManager;
|
||||||
public static WindManager Wind => managers?[8] as WindManager;
|
public static WindManager Wind => managers?[8] as WindManager;
|
||||||
|
public static PreBuildManager PreBuild => managers?[9] as PreBuildManager;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
// player loop delegate
|
// player loop delegate
|
||||||
@ -55,6 +56,11 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static UpdateMethod afterFixedUpdateDelegate;
|
public static UpdateMethod afterFixedUpdateDelegate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PreUpdate()の開始直後
|
||||||
|
/// </summary>
|
||||||
|
public static UpdateMethod firstPreUpdateDelegate;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update()の後
|
/// Update()の後
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -91,8 +97,6 @@ namespace MagicaCloth2
|
|||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
static volatile bool isPlaying = false;
|
static volatile bool isPlaying = false;
|
||||||
|
|
||||||
//static bool isValid = false;
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reload Domain 対策
|
/// Reload Domain 対策
|
||||||
@ -122,6 +126,7 @@ namespace MagicaCloth2
|
|||||||
managers.Add(new SimulationManager()); // [6]
|
managers.Add(new SimulationManager()); // [6]
|
||||||
managers.Add(new ColliderManager()); // [7]
|
managers.Add(new ColliderManager()); // [7]
|
||||||
managers.Add(new WindManager()); // [8]
|
managers.Add(new WindManager()); // [8]
|
||||||
|
managers.Add(new PreBuildManager()); // [9]
|
||||||
foreach (var manager in managers)
|
foreach (var manager in managers)
|
||||||
manager.Initialize();
|
manager.Initialize();
|
||||||
|
|
||||||
@ -321,7 +326,7 @@ namespace MagicaCloth2
|
|||||||
type = typeof(MagicaManager),
|
type = typeof(MagicaManager),
|
||||||
updateDelegate = () => afterEarlyUpdateDelegate?.Invoke()
|
updateDelegate = () => afterEarlyUpdateDelegate?.Invoke()
|
||||||
};
|
};
|
||||||
AddPlayerLoop(afterEarlyUpdate, ref playerLoop, "EarlyUpdate", string.Empty, last: true);
|
AddPlayerLoop(afterEarlyUpdate, ref playerLoop, "EarlyUpdate", string.Empty, firstLast: 1);
|
||||||
|
|
||||||
// after fixed update
|
// after fixed update
|
||||||
// FixedUpdate()の後
|
// FixedUpdate()の後
|
||||||
@ -335,6 +340,17 @@ namespace MagicaCloth2
|
|||||||
};
|
};
|
||||||
AddPlayerLoop(afterFixedUpdate, ref playerLoop, "FixedUpdate", "ScriptRunBehaviourFixedUpdate");
|
AddPlayerLoop(afterFixedUpdate, ref playerLoop, "FixedUpdate", "ScriptRunBehaviourFixedUpdate");
|
||||||
|
|
||||||
|
// first pre update
|
||||||
|
PlayerLoopSystem firstPreUpdate = new PlayerLoopSystem()
|
||||||
|
{
|
||||||
|
type = typeof(MagicaManager),
|
||||||
|
updateDelegate = () =>
|
||||||
|
{
|
||||||
|
firstPreUpdateDelegate?.Invoke();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AddPlayerLoop(firstPreUpdate, ref playerLoop, "PreUpdate", string.Empty, firstLast: -1);
|
||||||
|
|
||||||
// after update
|
// after update
|
||||||
// Update()の後
|
// Update()の後
|
||||||
PlayerLoopSystem afterUpdate = new PlayerLoopSystem()
|
PlayerLoopSystem afterUpdate = new PlayerLoopSystem()
|
||||||
@ -403,13 +419,18 @@ namespace MagicaCloth2
|
|||||||
/// <param name="playerLoop"></param>
|
/// <param name="playerLoop"></param>
|
||||||
/// <param name="categoryName"></param>
|
/// <param name="categoryName"></param>
|
||||||
/// <param name="systemName"></param>
|
/// <param name="systemName"></param>
|
||||||
static void AddPlayerLoop(PlayerLoopSystem method, ref PlayerLoopSystem playerLoop, string categoryName, string systemName, bool last = false, bool before = false)
|
static void AddPlayerLoop(PlayerLoopSystem method, ref PlayerLoopSystem playerLoop, string categoryName, string systemName, int firstLast = 0, bool before = false)
|
||||||
{
|
{
|
||||||
int sysIndex = Array.FindIndex(playerLoop.subSystemList, (s) => s.type.Name == categoryName);
|
int sysIndex = Array.FindIndex(playerLoop.subSystemList, (s) => s.type.Name == categoryName);
|
||||||
PlayerLoopSystem category = playerLoop.subSystemList[sysIndex];
|
PlayerLoopSystem category = playerLoop.subSystemList[sysIndex];
|
||||||
var systemList = new List<PlayerLoopSystem>(category.subSystemList);
|
var systemList = new List<PlayerLoopSystem>(category.subSystemList);
|
||||||
|
|
||||||
if (last)
|
if (firstLast < 0)
|
||||||
|
{
|
||||||
|
// 最初に追加
|
||||||
|
systemList.Insert(0, method);
|
||||||
|
}
|
||||||
|
else if (firstLast > 0)
|
||||||
{
|
{
|
||||||
// 最後に追加
|
// 最後に追加
|
||||||
systemList.Add(method);
|
systemList.Add(method);
|
||||||
|
|||||||
@ -33,7 +33,6 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
if (IsPlaying())
|
if (IsPlaying())
|
||||||
{
|
{
|
||||||
//Team.globalTimeScale = Mathf.Clamp01(timeScale);
|
|
||||||
Time.GlobalTimeScale = Mathf.Clamp01(timeScale);
|
Time.GlobalTimeScale = Mathf.Clamp01(timeScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,7 +46,6 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
if (IsPlaying())
|
if (IsPlaying())
|
||||||
{
|
{
|
||||||
//return Team.globalTimeScale;
|
|
||||||
return Time.GlobalTimeScale;
|
return Time.GlobalTimeScale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -153,5 +151,74 @@ namespace MagicaCloth2
|
|||||||
return TimeManager.UpdateLocation.AfterLateUpdate;
|
return TimeManager.UpdateLocation.AfterLateUpdate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 未使用のデータをすべて解放します
|
||||||
|
/// Free all unused data.
|
||||||
|
/// - Unused PreBuild data
|
||||||
|
/// </summary>
|
||||||
|
public static void UnloadUnusedData()
|
||||||
|
{
|
||||||
|
if (IsPlaying())
|
||||||
|
{
|
||||||
|
PreBuild.UnloadUnusedData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MonoBehaviourでのMagicaClothの初期化場所
|
||||||
|
/// MagicaCloth initialization location in MonoBehaviour.
|
||||||
|
/// </summary>
|
||||||
|
public enum InitializationLocation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize with MonoBehaviour.Start().
|
||||||
|
/// (Default)
|
||||||
|
/// </summary>
|
||||||
|
Start = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize with MonoBehaviour.Awake().
|
||||||
|
/// </summary>
|
||||||
|
Awake = 1,
|
||||||
|
}
|
||||||
|
internal static InitializationLocation initializationLocation = InitializationLocation.Start;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MonoBehaviourでのMagicaClothの初期化場所を設定する
|
||||||
|
/// Setting MagicaCloth initialization location in MonoBehaviour.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="initLocation"></param>
|
||||||
|
public static void SetInitializationLocation(InitializationLocation initLocation)
|
||||||
|
{
|
||||||
|
initializationLocation = initLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分割ジョブを適用するプロキシメッシュの頂点数を設定する
|
||||||
|
/// Sets the number of vertices for the proxy mesh to which the split job will be applied.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vertexCount"></param>
|
||||||
|
public static void SetSplitProxyMeshVertexCount(int vertexCount)
|
||||||
|
{
|
||||||
|
if (IsPlaying())
|
||||||
|
Simulation.splitProxyMeshVertexCount = vertexCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 分割ジョブを適用するプロキシメッシュの頂点数を取得する
|
||||||
|
/// Gets the vertex count of the proxy mesh to which the split job is applied.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetSplitProxyMeshVertexCount()
|
||||||
|
{
|
||||||
|
if (IsPlaying())
|
||||||
|
return Simulation.splitProxyMeshVertexCount;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Develop.LogError("MagicaManager is not starting!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,8 @@ namespace MagicaCloth2
|
|||||||
public enum RefreshMode
|
public enum RefreshMode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// コンポーネント生成時に1度だけ送信する
|
/// コンポーネントのAwake()で1度だけ送信する
|
||||||
/// Send only once when the component is created.
|
/// Send once at the component's Awake()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
OnAwake = 0,
|
OnAwake = 0,
|
||||||
|
|
||||||
@ -25,6 +25,18 @@ namespace MagicaCloth2
|
|||||||
/// Send content every frame.
|
/// Send content every frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
EveryFrame = 1,
|
EveryFrame = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// コンポーネントのStart()で一度だけ送信する
|
||||||
|
/// Send once at the component's Start().
|
||||||
|
/// </summary>
|
||||||
|
OnStart = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// コンポーネントは何もしません。送信には手動でRefresh()を呼ぶ必要があります
|
||||||
|
/// The component does nothing. You must manually call Refresh() to submit.
|
||||||
|
/// </summary>
|
||||||
|
Manual = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -64,6 +76,12 @@ namespace MagicaCloth2
|
|||||||
[Range(Define.System.MaxSimulationCountPerFrame_Low, Define.System.MaxSimulationCountPerFrame_Hi)]
|
[Range(Define.System.MaxSimulationCountPerFrame_Low, Define.System.MaxSimulationCountPerFrame_Hi)]
|
||||||
public int maxSimulationCountPerFrame = Define.System.DefaultMaxSimulationCountPerFrame;
|
public int maxSimulationCountPerFrame = Define.System.DefaultMaxSimulationCountPerFrame;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MonoBehaviourでのMagicaClothの初期化場所。
|
||||||
|
/// MagicaCloth initialization location in MonoBehaviour.
|
||||||
|
/// </summary>
|
||||||
|
public MagicaManager.InitializationLocation initializationLocation = MagicaManager.InitializationLocation.Start;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// シミュレーションの更新場所
|
/// シミュレーションの更新場所
|
||||||
/// BeforeLateUpdate : LateUpdate()の前に実行します。これはUnity 2D Animationで利用する場合に必要です。
|
/// BeforeLateUpdate : LateUpdate()の前に実行します。これはUnity 2D Animationで利用する場合に必要です。
|
||||||
@ -75,6 +93,27 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeManager.UpdateLocation updateLocation = TimeManager.UpdateLocation.AfterLateUpdate;
|
public TimeManager.UpdateLocation updateLocation = TimeManager.UpdateLocation.AfterLateUpdate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PlayerLoopの監視
|
||||||
|
/// MagicaClothのシステムはUnityのPlayerLoopに登録することで動作します
|
||||||
|
/// この登録が他の外部アセットにより上書きされてしまうと、MagicaClothのシステムが停止してしまいます
|
||||||
|
/// このフラグを有効にすると、PlayerLoopを監視して、上書きされていた場合は再度システムを登録するようになります
|
||||||
|
///
|
||||||
|
/// PlayerLoop monitoring.
|
||||||
|
/// The MagicaCloth system works by registering it in Unity's PlayerLoop.
|
||||||
|
/// If this registration is overwritten by other external assets, the MagicaCloth system will stop working.
|
||||||
|
/// When this flag is enabled, the PlayerLoop will be monitored, and the system will be registered again if it has been overwritten.
|
||||||
|
/// </summary>
|
||||||
|
public bool monitorPlayerLoop = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ジョブ分割を適用するプロキシメッシュの頂点数
|
||||||
|
///
|
||||||
|
/// The number of proxy mesh vertices to apply job splitting to.
|
||||||
|
/// </summary>
|
||||||
|
[Min(0)]
|
||||||
|
public int splitProxyMeshVertexCount = Define.System.SplitProxyMeshVertexCount;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public void Awake()
|
public void Awake()
|
||||||
{
|
{
|
||||||
@ -82,6 +121,12 @@ namespace MagicaCloth2
|
|||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (refreshMode == RefreshMode.OnStart)
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (refreshMode == RefreshMode.EveryFrame)
|
if (refreshMode == RefreshMode.EveryFrame)
|
||||||
@ -108,7 +153,12 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
MagicaManager.SetSimulationFrequency(simulationFrequency);
|
MagicaManager.SetSimulationFrequency(simulationFrequency);
|
||||||
MagicaManager.SetMaxSimulationCountPerFrame(maxSimulationCountPerFrame);
|
MagicaManager.SetMaxSimulationCountPerFrame(maxSimulationCountPerFrame);
|
||||||
|
MagicaManager.SetInitializationLocation(initializationLocation);
|
||||||
MagicaManager.SetUpdateLocation(updateLocation);
|
MagicaManager.SetUpdateLocation(updateLocation);
|
||||||
|
MagicaManager.SetSplitProxyMeshVertexCount(splitProxyMeshVertexCount);
|
||||||
|
|
||||||
|
if (monitorPlayerLoop)
|
||||||
|
MagicaManager.InitCustomGameLoop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,7 +4,7 @@ MonoImporter:
|
|||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: -50
|
||||||
icon: {fileID: 2800000, guid: 4b0d1adb21ff82e4e8e9ea02f486a85f, type: 3}
|
icon: {fileID: 2800000, guid: 4b0d1adb21ff82e4e8e9ea02f486a85f, type: 3}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
|
|||||||
@ -5,10 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
@ -37,6 +34,7 @@ namespace MagicaCloth2
|
|||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
// セットアップデータ
|
// セットアップデータ
|
||||||
internal RenderSetupData setupData;
|
internal RenderSetupData setupData;
|
||||||
|
internal RenderSetupData.UniqueSerializationData preBuildUniqueSerializeData;
|
||||||
|
|
||||||
internal string Name => setupData?.name ?? "(empty)";
|
internal string Name => setupData?.name ?? "(empty)";
|
||||||
|
|
||||||
@ -44,40 +42,27 @@ namespace MagicaCloth2
|
|||||||
internal bool HasBoneWeight => setupData?.hasBoneWeight ?? false;
|
internal bool HasBoneWeight => setupData?.hasBoneWeight ?? false;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
// カスタムメッシュ情報
|
// オリジナル情報
|
||||||
Mesh customMesh;
|
internal Mesh originalMesh { get; private set; }
|
||||||
NativeArray<Vector3> localPositions;
|
private Renderer renderer;
|
||||||
NativeArray<Vector3> localNormals;
|
private SkinnedMeshRenderer skinnedMeshRendere;
|
||||||
NativeArray<BoneWeight> boneWeights;
|
private MeshFilter meshFilter;
|
||||||
BoneWeight centerBoneWeight;
|
internal List<Transform> transformList { get; private set; }
|
||||||
|
internal Mesh customMesh { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
// RenderDataWorkバッファへのインデックス(RenderManagerが管理)
|
||||||
/// カスタムメッシュの使用フラグ
|
internal int renderDataWorkIndex { get; private set; } = -1;
|
||||||
/// </summary>
|
|
||||||
public bool UseCustomMesh { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// カスタムメッシュの変更フラグ
|
|
||||||
/// </summary>
|
|
||||||
public bool ChangeCustomMesh { get; private set; }
|
|
||||||
|
|
||||||
public bool ChangePositionNormal { get; private set; }
|
|
||||||
public bool ChangeBoneWeight { get; private set; }
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// オリジナルメッシュに戻す
|
// オリジナルメッシュに戻す
|
||||||
SwapOriginalMesh();
|
SwapOriginalMesh(null);
|
||||||
|
|
||||||
setupData?.Dispose();
|
setupData?.Dispose();
|
||||||
|
preBuildUniqueSerializeData = null;
|
||||||
|
|
||||||
if (localPositions.IsCreated)
|
MagicaManager.Render.RemoveRenderDataWork(renderDataWorkIndex);
|
||||||
localPositions.Dispose();
|
|
||||||
if (localNormals.IsCreated)
|
|
||||||
localNormals.Dispose();
|
|
||||||
if (boneWeights.IsCreated)
|
|
||||||
boneWeights.Dispose();
|
|
||||||
|
|
||||||
if (customMesh)
|
if (customMesh)
|
||||||
GameObject.Destroy(customMesh);
|
GameObject.Destroy(customMesh);
|
||||||
@ -98,17 +83,42 @@ namespace MagicaCloth2
|
|||||||
/// この処理はスレッド化できないので少し負荷がかかるが即時実行する
|
/// この処理はスレッド化できないので少し負荷がかかるが即時実行する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ren"></param>
|
/// <param name="ren"></param>
|
||||||
internal void Initialize(Renderer ren)
|
internal void Initialize(
|
||||||
|
Renderer ren,
|
||||||
|
RenderSetupData referenceSetupData,
|
||||||
|
RenderSetupData.UniqueSerializationData referencePreBuildUniqueSetupData,
|
||||||
|
RenderSetupSerializeData referenceInitSetupData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Debug.Assert(ren);
|
Debug.Assert(ren);
|
||||||
|
|
||||||
// セットアップデータ作成
|
// セットアップデータ作成
|
||||||
setupData = new RenderSetupData(ren);
|
// PreBuildでは外部から受け渡される
|
||||||
|
if (referenceSetupData != null && referencePreBuildUniqueSetupData != null)
|
||||||
|
{
|
||||||
|
setupData = referenceSetupData;
|
||||||
|
preBuildUniqueSerializeData = referencePreBuildUniqueSetupData;
|
||||||
|
|
||||||
// センタートランスフォーム用ボーンウエイト
|
originalMesh = preBuildUniqueSerializeData.originalMesh;
|
||||||
centerBoneWeight = new BoneWeight();
|
renderer = preBuildUniqueSerializeData.renderer;
|
||||||
centerBoneWeight.boneIndex0 = setupData.renderTransformIndex;
|
skinnedMeshRendere = preBuildUniqueSerializeData.skinRenderer;
|
||||||
centerBoneWeight.weight0 = 1.0f;
|
meshFilter = preBuildUniqueSerializeData.meshFilter;
|
||||||
|
transformList = preBuildUniqueSerializeData.transformList;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setupData = new RenderSetupData(referenceInitSetupData, ren);
|
||||||
|
preBuildUniqueSerializeData = null;
|
||||||
|
|
||||||
|
originalMesh = setupData.originalMesh;
|
||||||
|
renderer = setupData.renderer;
|
||||||
|
skinnedMeshRendere = setupData.skinRenderer;
|
||||||
|
meshFilter = setupData.meshFilter;
|
||||||
|
transformList = setupData.transformList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// レンダーデータワークを確保
|
||||||
|
renderDataWorkIndex = MagicaManager.Render.AddRenderDataWork(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ResultCode Result => setupData?.result ?? ResultCode.None;
|
internal ResultCode Result => setupData?.result ?? ResultCode.None;
|
||||||
@ -127,41 +137,39 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
void SwapCustomMesh()
|
void SwapCustomMesh(ClothProcess process)
|
||||||
{
|
{
|
||||||
Debug.Assert(setupData != null);
|
Debug.Assert(setupData != null);
|
||||||
|
|
||||||
if (setupData.IsFaild())
|
if (setupData.IsFaild())
|
||||||
return;
|
return;
|
||||||
if (setupData.originalMesh == null)
|
if (originalMesh == null)
|
||||||
|
return;
|
||||||
|
if (MagicaManager.Render.IsSetRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// カスタムメッシュの作成
|
// カスタムメッシュの作成
|
||||||
if (customMesh == null)
|
if (customMesh == null)
|
||||||
{
|
{
|
||||||
Debug.Assert(setupData.originalMesh);
|
//Debug.Assert(setupData.originalMesh);
|
||||||
|
|
||||||
// クローン作成
|
// クローン作成
|
||||||
customMesh = GameObject.Instantiate(setupData.originalMesh);
|
customMesh = GameObject.Instantiate(originalMesh);
|
||||||
customMesh.MarkDynamic();
|
customMesh.MarkDynamic();
|
||||||
|
|
||||||
// 作業配列
|
|
||||||
int vertexCount = setupData.vertexCount;
|
|
||||||
localPositions = new NativeArray<Vector3>(vertexCount, Allocator.Persistent);
|
|
||||||
localNormals = new NativeArray<Vector3>(vertexCount, Allocator.Persistent);
|
|
||||||
if (HasBoneWeight)
|
|
||||||
boneWeights = new NativeArray<BoneWeight>(vertexCount, Allocator.Persistent);
|
|
||||||
|
|
||||||
// bind pose
|
// bind pose
|
||||||
if (HasBoneWeight)
|
if (HasBoneWeight)
|
||||||
{
|
{
|
||||||
int transformCount = setupData.TransformCount;
|
int transformCount = preBuildUniqueSerializeData != null ? preBuildUniqueSerializeData.transformList.Count : setupData.TransformCount;
|
||||||
var bindPoseList = new List<Matrix4x4>(transformCount);
|
var bindPoseList = new List<Matrix4x4>(transformCount);
|
||||||
bindPoseList.AddRange(setupData.bindPoseList);
|
bindPoseList.AddRange(setupData.bindPoseList);
|
||||||
// rootBone/skinning bones
|
// rootBone/skinning bones
|
||||||
while (bindPoseList.Count < transformCount)
|
while (bindPoseList.Count < transformCount)
|
||||||
bindPoseList.Add(Matrix4x4.identity);
|
bindPoseList.Add(Matrix4x4.identity);
|
||||||
customMesh.bindposes = bindPoseList.ToArray();
|
customMesh.bindposes = bindPoseList.ToArray();
|
||||||
|
|
||||||
|
// スキニング用ボーンを書き換える
|
||||||
|
// このリストにはオリジナルのスキニングボーン+レンダラーのトランスフォームが含まれている
|
||||||
|
skinnedMeshRendere.bones = transformList.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,45 +178,76 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// カスタムメッシュに表示切り替え
|
// カスタムメッシュに表示切り替え
|
||||||
SetMesh(customMesh);
|
SetMesh(customMesh);
|
||||||
|
MagicaManager.Render.SetBitsRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh, true);
|
||||||
|
|
||||||
// スキニング用ボーンを書き換える
|
// Event
|
||||||
if (HasBoneWeight)
|
if (process != null)
|
||||||
{
|
process.cloth?.OnRendererMeshChange?.Invoke(process.cloth, renderer, true);
|
||||||
// このリストにはオリジナルのスキニングボーン+レンダラーのトランスフォームが含まれている
|
|
||||||
setupData.skinRenderer.bones = setupData.transformList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
UseCustomMesh = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetCustomMeshWorkData()
|
void ResetCustomMeshWorkData()
|
||||||
{
|
{
|
||||||
|
var rm = MagicaManager.Render;
|
||||||
|
ref var wdata = ref rm.GetRenderDataWorkRef(renderDataWorkIndex);
|
||||||
|
int vcnt = setupData.vertexCount;
|
||||||
|
|
||||||
// オリジナルデータをコピーする
|
// オリジナルデータをコピーする
|
||||||
|
if (setupData.HasMeshDataArray)
|
||||||
|
{
|
||||||
var meshData = setupData.meshDataArray[0];
|
var meshData = setupData.meshDataArray[0];
|
||||||
|
using var localPositions = new NativeArray<Vector3>(vcnt, Allocator.TempJob);
|
||||||
|
using var localNormals = new NativeArray<Vector3>(vcnt, Allocator.TempJob);
|
||||||
meshData.GetVertices(localPositions);
|
meshData.GetVertices(localPositions);
|
||||||
meshData.GetNormals(localNormals);
|
meshData.GetNormals(localNormals);
|
||||||
if (HasBoneWeight)
|
rm.renderMeshPositions.CopyFrom(localPositions, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt);
|
||||||
|
rm.renderMeshNormals.CopyFrom(localNormals, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt);
|
||||||
|
if (wdata.HasMeshTangent)
|
||||||
{
|
{
|
||||||
|
using var localTangents = new NativeArray<Vector4>(vcnt, Allocator.TempJob);
|
||||||
|
meshData.GetTangents(localTangents);
|
||||||
|
rm.renderMeshTangents.CopyFrom(localTangents, wdata.renderMeshTangentChunk.startIndex, vcnt);
|
||||||
|
wdata.flag.SetBits(RenderManager.RenderDataFlag_HasTangent, true); // 最終的な接線あり
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rm.renderMeshPositions.CopyFrom(setupData.localPositions, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt);
|
||||||
|
rm.renderMeshNormals.CopyFrom(setupData.localNormals, wdata.renderMeshPositionAndNormalChunk.startIndex, vcnt);
|
||||||
|
if (wdata.HasMeshTangent && setupData.HasTangent)
|
||||||
|
{
|
||||||
|
rm.renderMeshTangents.CopyFrom(setupData.localTangents, wdata.renderMeshTangentChunk.startIndex, vcnt);
|
||||||
|
wdata.flag.SetBits(RenderManager.RenderDataFlag_HasTangent, true); // 最終的な接線あり
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (HasBoneWeight && wdata.HasBoneWeight)
|
||||||
|
{
|
||||||
|
using var boneWeights = new NativeArray<BoneWeight>(vcnt, Allocator.TempJob);
|
||||||
setupData.GetBoneWeightsRun(boneWeights);
|
setupData.GetBoneWeightsRun(boneWeights);
|
||||||
|
rm.renderMeshBoneWeights.CopyFrom(boneWeights, wdata.renderMeshBoneWeightChunk.startIndex, vcnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// オリジナルメッシュに戻す
|
/// オリジナルメッシュに戻す
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SwapOriginalMesh()
|
void SwapOriginalMesh(ClothProcess process)
|
||||||
{
|
{
|
||||||
if (UseCustomMesh && setupData != null)
|
var rm = MagicaManager.Render;
|
||||||
{
|
|
||||||
SetMesh(setupData.originalMesh);
|
|
||||||
|
|
||||||
if (setupData.skinRenderer != null)
|
if (rm.IsSetRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh) && setupData != null)
|
||||||
{
|
{
|
||||||
setupData.skinRenderer.bones = setupData.transformList.ToArray();
|
SetMesh(originalMesh);
|
||||||
|
|
||||||
|
if (skinnedMeshRendere != null)
|
||||||
|
{
|
||||||
|
skinnedMeshRendere.bones = transformList.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rm.SetBitsRenderDataWorkFlag(renderDataWorkIndex, RenderManager.RenderDataFlag_UseCustomMesh, false);
|
||||||
|
|
||||||
UseCustomMesh = false;
|
// Event
|
||||||
|
if (process != null)
|
||||||
|
process.cloth?.OnRendererMeshChange?.Invoke(process.cloth, renderer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -222,13 +261,13 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
if (setupData != null)
|
if (setupData != null)
|
||||||
{
|
{
|
||||||
if (setupData.meshFilter != null)
|
if (meshFilter != null)
|
||||||
{
|
{
|
||||||
setupData.meshFilter.mesh = mesh;
|
meshFilter.mesh = mesh;
|
||||||
}
|
}
|
||||||
else if (setupData.skinRenderer != null)
|
else if (skinnedMeshRendere != null)
|
||||||
{
|
{
|
||||||
setupData.skinRenderer.sharedMesh = mesh;
|
skinnedMeshRendere.sharedMesh = mesh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,7 +290,7 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void EndUse(ClothProcess cprocess)
|
public void EndUse(ClothProcess cprocess)
|
||||||
{
|
{
|
||||||
Debug.Assert(useProcessSet.Count > 0);
|
//Debug.Assert(useProcessSet.Count > 0);
|
||||||
UpdateUse(cprocess, -1);
|
UpdateUse(cprocess, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,36 +302,62 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
else if (add < 0)
|
else if (add < 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(useProcessSet.Count > 0);
|
//Debug.Assert(useProcessSet.Count > 0);
|
||||||
|
if (useProcessSet.Contains(cprocess))
|
||||||
useProcessSet.Remove(cprocess);
|
useProcessSet.Remove(cprocess);
|
||||||
|
else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invisible状態
|
// Invisible状態
|
||||||
bool invisible = useProcessSet.Any(x => x.IsCullingInvisible() && x.IsCullingKeep() == false);
|
bool invisible = useProcessSet.Any(x => (x.IsCameraCullingInvisible() && x.IsCameraCullingKeep() == false) || x.IsDistanceCullingInvisible());
|
||||||
|
|
||||||
// 状態変更
|
// 状態変更
|
||||||
|
bool modifyBoneWeight = false;
|
||||||
if (invisible || useProcessSet.Count == 0)
|
if (invisible || useProcessSet.Count == 0)
|
||||||
{
|
{
|
||||||
// 利用停止
|
// 利用停止
|
||||||
// オリジナルメッシュに切り替え
|
// オリジナルメッシュに切り替え
|
||||||
SwapOriginalMesh();
|
SwapOriginalMesh(cprocess);
|
||||||
ChangeCustomMesh = true;
|
|
||||||
}
|
}
|
||||||
else if (useProcessSet.Count == 1)
|
else if (add == 0 && useProcessSet.Count > 0)
|
||||||
|
{
|
||||||
|
// カリング復帰
|
||||||
|
// カスタムメッシュに切り替え、および作業バッファ作成
|
||||||
|
// すでにカスタムメッシュが存在する場合は作業バッファのみ再初期化する
|
||||||
|
SwapCustomMesh(cprocess);
|
||||||
|
modifyBoneWeight = true;
|
||||||
|
}
|
||||||
|
else if (add > 0 && useProcessSet.Count == 1)
|
||||||
{
|
{
|
||||||
// 利用開始
|
// 利用開始
|
||||||
// カスタムメッシュに切り替え、および作業バッファ作成
|
// カスタムメッシュに切り替え、および作業バッファ作成
|
||||||
// すでにカスタムメッシュが存在する場合は作業バッファのみ最初期化する
|
// すでにカスタムメッシュが存在する場合は作業バッファのみ再初期化する
|
||||||
SwapCustomMesh();
|
SwapCustomMesh(cprocess);
|
||||||
ChangeCustomMesh = true;
|
modifyBoneWeight = true;
|
||||||
}
|
}
|
||||||
else if (add != 0)
|
else if (add != 0)
|
||||||
{
|
{
|
||||||
// 複数から利用されている状態で1つが停止した。
|
// 複数から利用されている状態で1つが停止した。
|
||||||
// バッファを最初期化する
|
// バッファを最初期化する
|
||||||
ResetCustomMeshWorkData();
|
ResetCustomMeshWorkData();
|
||||||
ChangeCustomMesh = true;
|
modifyBoneWeight = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoneWeight変更を連動するマッピングに指示する
|
||||||
|
if (modifyBoneWeight)
|
||||||
|
{
|
||||||
|
ref var wdata = ref MagicaManager.Render.GetRenderDataWorkRef(renderDataWorkIndex);
|
||||||
|
int mcnt = wdata.mappingDataIndexList.Length;
|
||||||
|
for (int i = 0; i < mcnt; i++)
|
||||||
|
{
|
||||||
|
int mindex = wdata.mappingDataIndexList[i];
|
||||||
|
ref var mdata = ref MagicaManager.Team.GetMappingDataRef(mindex);
|
||||||
|
mdata.flag.SetBits(TeamManager.MappingDataFlag_ModifyBoneWeight, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Debug.Log($"add:{add}, invisible:{invisible}, useCount:{useProcessSet.Count}, ModifyBoneWeight = {flag.IsSet(Flag_ModifyBoneWeight)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
@ -312,177 +377,39 @@ namespace MagicaCloth2
|
|||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
internal void WriteMesh()
|
internal void WriteMesh()
|
||||||
{
|
{
|
||||||
if (UseCustomMesh == false || useProcessSet.Count == 0)
|
var rm = MagicaManager.Render;
|
||||||
|
ref var wdata = ref rm.GetRenderDataWorkRef(renderDataWorkIndex);
|
||||||
|
|
||||||
|
if (wdata.UseCustomMesh == false || useProcessSet.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 書き込み停止中ならスキップ
|
// 書き込み停止中ならスキップ
|
||||||
if (isSkipWriting)
|
if (isSkipWriting)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//Debug.Log($"WriteMesh [{Name}] ChangePositionNormal:{flag.IsSet(Flag_ChangePositionNormal)}, ChangeBoneWeight:{flag.IsSet(Flag_ChangeBoneWeight)}");
|
||||||
|
|
||||||
// メッシュに反映
|
// メッシュに反映
|
||||||
if (ChangePositionNormal)
|
if (wdata.flag.IsSet(RenderManager.RenderDataFlag_WritePositionNormal))
|
||||||
{
|
{
|
||||||
customMesh.SetVertices(localPositions);
|
customMesh.SetVertices(rm.renderMeshPositions.GetNativeArray(), wdata.renderMeshPositionAndNormalChunk.startIndex, wdata.renderMeshPositionAndNormalChunk.dataLength);
|
||||||
customMesh.SetNormals(localNormals);
|
customMesh.SetNormals(rm.renderMeshNormals.GetNativeArray(), wdata.renderMeshPositionAndNormalChunk.startIndex, wdata.renderMeshPositionAndNormalChunk.dataLength);
|
||||||
|
wdata.flag.SetBits(RenderManager.RenderDataFlag_WritePositionNormal, false);
|
||||||
|
//Debug.Log($"[{customMesh.name}] Write Position+Normal");
|
||||||
}
|
}
|
||||||
if (ChangeBoneWeight && HasBoneWeight)
|
if (wdata.flag.IsSet(RenderManager.RenderDataFlag_WriteTangent))
|
||||||
{
|
{
|
||||||
customMesh.boneWeights = boneWeights.ToArray();
|
customMesh.SetTangents(rm.renderMeshTangents.GetNativeArray(), wdata.renderMeshTangentChunk.startIndex, wdata.renderMeshTangentChunk.dataLength);
|
||||||
|
wdata.flag.SetBits(RenderManager.RenderDataFlag_WriteTangent, false);
|
||||||
|
//Debug.Log($"[{customMesh.name}] Write Tangent");
|
||||||
}
|
}
|
||||||
|
if (wdata.flag.IsSet(RenderManager.RenderDataFlag_WriteBoneWeight))
|
||||||
// 完了
|
|
||||||
ChangeCustomMesh = false;
|
|
||||||
ChangePositionNormal = false;
|
|
||||||
ChangeBoneWeight = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========================================================================================
|
|
||||||
/// <summary>
|
|
||||||
/// メッシュの位置法線を更新
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mappingChunk"></param>
|
|
||||||
/// <param name="jobHandle"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal JobHandle UpdatePositionNormal(DataChunk mappingChunk, JobHandle jobHandle = default)
|
|
||||||
{
|
{
|
||||||
if (UseCustomMesh == false)
|
// BoneWeightはNativeArrayの区間指定ができない
|
||||||
return jobHandle;
|
var boneWeightsSlice = new NativeSlice<BoneWeight>(rm.renderMeshBoneWeights.GetNativeArray(), wdata.renderMeshBoneWeightChunk.startIndex, wdata.renderMeshBoneWeightChunk.dataLength);
|
||||||
|
customMesh.boneWeights = boneWeightsSlice.ToArray();
|
||||||
var vm = MagicaManager.VMesh;
|
wdata.flag.SetBits(RenderManager.RenderDataFlag_WriteBoneWeight, false);
|
||||||
|
//Debug.Log($"[{customMesh.name}] Write BoneWeight");
|
||||||
// 座標・法線の差分書き換え
|
|
||||||
var job = new UpdatePositionNormalJob2()
|
|
||||||
{
|
|
||||||
startIndex = mappingChunk.startIndex,
|
|
||||||
|
|
||||||
meshLocalPositions = localPositions.Reinterpret<float3>(),
|
|
||||||
meshLocalNormals = localNormals.Reinterpret<float3>(),
|
|
||||||
|
|
||||||
mappingReferenceIndices = vm.mappingReferenceIndices.GetNativeArray(),
|
|
||||||
mappingAttributes = vm.mappingAttributes.GetNativeArray(),
|
|
||||||
mappingPositions = vm.mappingPositions.GetNativeArray(),
|
|
||||||
mappingNormals = vm.mappingNormals.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(mappingChunk.dataLength, 32, jobHandle);
|
|
||||||
|
|
||||||
ChangePositionNormal = true;
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct UpdatePositionNormalJob2 : IJobParallelFor
|
|
||||||
{
|
|
||||||
public int startIndex;
|
|
||||||
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
[Unity.Collections.WriteOnly]
|
|
||||||
public NativeArray<float3> meshLocalPositions;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
[Unity.Collections.WriteOnly]
|
|
||||||
public NativeArray<float3> meshLocalNormals;
|
|
||||||
|
|
||||||
// mapping mesh
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> mappingReferenceIndices;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<VertexAttribute> mappingAttributes;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> mappingPositions;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> mappingNormals;
|
|
||||||
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int vindex = index + startIndex;
|
|
||||||
|
|
||||||
// 無効頂点なら書き込まない
|
|
||||||
var attr = mappingAttributes[vindex];
|
|
||||||
if (attr.IsInvalid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 固定も書き込まない(todo:一旦こうする)
|
|
||||||
if (attr.IsFixed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 書き込む頂点インデックス
|
|
||||||
int windex = mappingReferenceIndices[vindex];
|
|
||||||
|
|
||||||
// 座標書き込み
|
|
||||||
meshLocalPositions[windex] = mappingPositions[vindex];
|
|
||||||
|
|
||||||
// 法線書き込み
|
|
||||||
meshLocalNormals[windex] = mappingNormals[vindex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// メッシュのボーンウエイト書き込み
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="vmesh"></param>
|
|
||||||
/// <param name="jobHandle"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal JobHandle UpdateBoneWeight(DataChunk mappingChunk, JobHandle jobHandle = default)
|
|
||||||
{
|
|
||||||
if (UseCustomMesh == false)
|
|
||||||
return jobHandle;
|
|
||||||
|
|
||||||
// ボーンウエイトの差分書き換え
|
|
||||||
if (HasBoneWeight)
|
|
||||||
{
|
|
||||||
var vm = MagicaManager.VMesh;
|
|
||||||
|
|
||||||
var job = new UpdateBoneWeightJob2()
|
|
||||||
{
|
|
||||||
startIndex = mappingChunk.startIndex,
|
|
||||||
centerBoneWeight = centerBoneWeight,
|
|
||||||
meshBoneWeights = boneWeights,
|
|
||||||
|
|
||||||
mappingReferenceIndices = vm.mappingReferenceIndices.GetNativeArray(),
|
|
||||||
mappingAttributes = vm.mappingAttributes.GetNativeArray(),
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(mappingChunk.dataLength, 32, jobHandle);
|
|
||||||
|
|
||||||
ChangeBoneWeight = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct UpdateBoneWeightJob2 : IJobParallelFor
|
|
||||||
{
|
|
||||||
public int startIndex;
|
|
||||||
public BoneWeight centerBoneWeight;
|
|
||||||
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
[Unity.Collections.WriteOnly]
|
|
||||||
public NativeArray<BoneWeight> meshBoneWeights;
|
|
||||||
|
|
||||||
// mapping mesh
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> mappingReferenceIndices;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<VertexAttribute> mappingAttributes;
|
|
||||||
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int vindex = index + startIndex;
|
|
||||||
|
|
||||||
// 無効頂点なら書き込まない
|
|
||||||
var attr = mappingAttributes[vindex];
|
|
||||||
if (attr.IsInvalid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 固定も書き込まない(todo:一旦こうする)
|
|
||||||
if (attr.IsFixed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 書き込む頂点インデックス
|
|
||||||
int windex = mappingReferenceIndices[vindex];
|
|
||||||
|
|
||||||
// 使用頂点のウエイトはcenterTransform100%で書き込む
|
|
||||||
meshBoneWeights[windex] = centerBoneWeight;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Unity.Collections;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
using Unity.Profiling;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
@ -17,6 +20,78 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Dictionary<int, RenderData> renderDataDict = new Dictionary<int, RenderData>();
|
Dictionary<int, RenderData> renderDataDict = new Dictionary<int, RenderData>();
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
// ■RenderData
|
||||||
|
//=========================================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// RenderDataの状態フラグ(32bit)
|
||||||
|
/// </summary>
|
||||||
|
public const int RenderDataFlag_UseCustomMesh = 0; // カスタムメッシュの利用
|
||||||
|
public const int RenderDataFlag_WritePositionNormal = 1; // 座標および法線の書き込み
|
||||||
|
public const int RenderDataFlag_WriteBoneWeight = 2; // ボーンウエイトの書き込み
|
||||||
|
//public const int RenderDataFlag_ModifyBoneWeight = 3; // ボーンウエイトの変更
|
||||||
|
public const int RenderDataFlag_HasMeshTangent = 4; // オリジナルメッシュが接線を持っているかどうか
|
||||||
|
public const int RenderDataFlag_HasTangent = 5; // 最終的に接線情報を持っているかどうか
|
||||||
|
public const int RenderDataFlag_WriteTangent = 6; // 接線の書き込み
|
||||||
|
public const int RenderDataFlag_HasSkinnedMesh = 7;
|
||||||
|
public const int RenderDataFlag_HasBoneWeight = 8;
|
||||||
|
|
||||||
|
public struct RenderDataWork : IValid
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// RenderData状態フラグ
|
||||||
|
/// </summary>
|
||||||
|
public BitField32 flag;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// バッファへの格納先情報
|
||||||
|
/// </summary>
|
||||||
|
public DataChunk renderMeshPositionAndNormalChunk;
|
||||||
|
public DataChunk renderMeshTangentChunk;
|
||||||
|
public DataChunk renderMeshBoneWeightChunk;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 制御頂点に設定するボーンウエイト
|
||||||
|
/// </summary>
|
||||||
|
public BoneWeight centerBoneWeight;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 紐づけられているマッピングメッシュデータへのインデックスリスト
|
||||||
|
/// </summary>
|
||||||
|
public FixedList32Bytes<short> mappingDataIndexList;
|
||||||
|
|
||||||
|
public bool IsValid()
|
||||||
|
{
|
||||||
|
return renderMeshPositionAndNormalChunk.IsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseCustomMesh => flag.IsSet(RenderDataFlag_UseCustomMesh);
|
||||||
|
public bool HasMeshTangent => flag.IsSet(RenderDataFlag_HasMeshTangent);
|
||||||
|
public bool HasTangent => flag.IsSet(RenderDataFlag_HasTangent);
|
||||||
|
public bool HasBoneWeight => flag.IsSet(RenderDataFlag_HasBoneWeight);
|
||||||
|
|
||||||
|
public void AddMappingIndex(int mindex)
|
||||||
|
{
|
||||||
|
mappingDataIndexList.Add((short)mindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveMappingIndex(int mindex)
|
||||||
|
{
|
||||||
|
mappingDataIndexList.MC2RemoveItemAtSwapBack((short)mindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ExNativeArray<RenderDataWork> renderDataWorkArray;
|
||||||
|
|
||||||
|
public int RenderDataWorkCount => renderDataWorkArray?.Count ?? 0;
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
// ■RenderMesh
|
||||||
|
//=========================================================================================
|
||||||
|
public ExNativeArray<float3> renderMeshPositions;
|
||||||
|
public ExNativeArray<float3> renderMeshNormals;
|
||||||
|
public ExNativeArray<float4> renderMeshTangents;
|
||||||
|
public ExNativeArray<BoneWeight> renderMeshBoneWeights;
|
||||||
|
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
@ -24,6 +99,15 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
|
|
||||||
|
// 作業バッファ
|
||||||
|
const int capacity = 0;
|
||||||
|
const bool create = true;
|
||||||
|
renderDataWorkArray = new ExNativeArray<RenderDataWork>(capacity, create);
|
||||||
|
renderMeshPositions = new ExNativeArray<float3>(capacity, create);
|
||||||
|
renderMeshNormals = new ExNativeArray<float3>(capacity, create);
|
||||||
|
renderMeshTangents = new ExNativeArray<float4>(capacity, create);
|
||||||
|
renderMeshBoneWeights = new ExNativeArray<BoneWeight>(capacity, create);
|
||||||
|
|
||||||
// 更新処理
|
// 更新処理
|
||||||
MagicaManager.afterDelayedDelegate += PreRenderingUpdate;
|
MagicaManager.afterDelayedDelegate += PreRenderingUpdate;
|
||||||
|
|
||||||
@ -48,6 +132,18 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
renderDataDict.Clear();
|
renderDataDict.Clear();
|
||||||
|
|
||||||
|
// 作業バッファ
|
||||||
|
renderDataWorkArray?.Dispose();
|
||||||
|
renderMeshPositions?.Dispose();
|
||||||
|
renderMeshNormals?.Dispose();
|
||||||
|
renderMeshTangents?.Dispose();
|
||||||
|
renderMeshBoneWeights?.Dispose();
|
||||||
|
renderDataWorkArray = null;
|
||||||
|
renderMeshPositions = null;
|
||||||
|
renderMeshNormals = null;
|
||||||
|
renderMeshBoneWeights = null;
|
||||||
|
renderMeshTangents = null;
|
||||||
|
|
||||||
// 更新処理
|
// 更新処理
|
||||||
MagicaManager.afterDelayedDelegate -= PreRenderingUpdate;
|
MagicaManager.afterDelayedDelegate -= PreRenderingUpdate;
|
||||||
}
|
}
|
||||||
@ -63,7 +159,12 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ren"></param>
|
/// <param name="ren"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public int AddRenderer(Renderer ren)
|
public int AddRenderer(
|
||||||
|
Renderer ren,
|
||||||
|
RenderSetupData referenceSetupData,
|
||||||
|
RenderSetupData.UniqueSerializationData referenceUniqueSetupData,
|
||||||
|
RenderSetupSerializeData referenceInitSetupData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (isValid == false)
|
if (isValid == false)
|
||||||
return 0;
|
return 0;
|
||||||
@ -78,7 +179,7 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
// 新規
|
// 新規
|
||||||
var rdata = new RenderData();
|
var rdata = new RenderData();
|
||||||
rdata.Initialize(ren);
|
rdata.Initialize(ren, referenceSetupData, referenceUniqueSetupData, referenceInitSetupData);
|
||||||
renderDataDict.Add(handle, rdata);
|
renderDataDict.Add(handle, rdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +197,6 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
bool delete = false;
|
bool delete = false;
|
||||||
|
|
||||||
//if(renderDataDict.ContainsKey(handle) == )
|
|
||||||
|
|
||||||
//Debug.Log($"RemoveRenderer:{handle}");
|
//Debug.Log($"RemoveRenderer:{handle}");
|
||||||
//Debug.Assert(ren);
|
//Debug.Assert(ren);
|
||||||
Debug.Assert(renderDataDict.ContainsKey(handle));
|
Debug.Assert(renderDataDict.ContainsKey(handle));
|
||||||
@ -137,6 +236,92 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
public int AddRenderDataWork(RenderData rdata)
|
||||||
|
{
|
||||||
|
if (isValid == false)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
var wdata = new RenderDataWork();
|
||||||
|
|
||||||
|
// オリジナルメッシュの接線情報を確認
|
||||||
|
wdata.flag.SetBits(RenderDataFlag_HasMeshTangent, rdata.originalMesh.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent));
|
||||||
|
//Debug.Log($"OriginalMesh[{originalMesh.name}] hasTangent:{originalMesh.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent)}");
|
||||||
|
|
||||||
|
// Flag
|
||||||
|
wdata.flag.SetBits(RenderDataFlag_HasSkinnedMesh, rdata.HasSkinnedMesh);
|
||||||
|
wdata.flag.SetBits(RenderDataFlag_HasBoneWeight, rdata.HasBoneWeight);
|
||||||
|
|
||||||
|
// センタートランスフォーム用ボーンウエイト
|
||||||
|
var centerBoneWeight = new BoneWeight();
|
||||||
|
centerBoneWeight.boneIndex0 = rdata.setupData.renderTransformIndex;
|
||||||
|
centerBoneWeight.weight0 = 1.0f;
|
||||||
|
wdata.centerBoneWeight = centerBoneWeight;
|
||||||
|
|
||||||
|
// レンダーメッシュ用バッファ確保
|
||||||
|
int vcnt = rdata.originalMesh.vertexCount;
|
||||||
|
wdata.renderMeshPositionAndNormalChunk = renderMeshPositions.AddRange(vcnt);
|
||||||
|
renderMeshNormals.AddRange(vcnt);
|
||||||
|
if (wdata.HasMeshTangent)
|
||||||
|
wdata.renderMeshTangentChunk = renderMeshTangents.AddRange(vcnt);
|
||||||
|
if (wdata.HasBoneWeight)
|
||||||
|
{
|
||||||
|
wdata.renderMeshBoneWeightChunk = renderMeshBoneWeights.AddRange(vcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格納
|
||||||
|
var c = renderDataWorkArray.Add(wdata);
|
||||||
|
return c.startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRenderDataWork(int index)
|
||||||
|
{
|
||||||
|
if (isValid == false)
|
||||||
|
return;
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// バッファ削除
|
||||||
|
ref var wdata = ref GetRenderDataWorkRef(index);
|
||||||
|
if (wdata.renderMeshPositionAndNormalChunk.IsValid)
|
||||||
|
{
|
||||||
|
renderMeshPositions.Remove(wdata.renderMeshPositionAndNormalChunk);
|
||||||
|
renderMeshNormals.Remove(wdata.renderMeshPositionAndNormalChunk);
|
||||||
|
}
|
||||||
|
if (wdata.renderMeshTangentChunk.IsValid)
|
||||||
|
{
|
||||||
|
renderMeshTangents.Remove(wdata.renderMeshTangentChunk);
|
||||||
|
}
|
||||||
|
if (wdata.renderMeshBoneWeightChunk.IsValid)
|
||||||
|
{
|
||||||
|
renderMeshBoneWeights.Remove(wdata.renderMeshBoneWeightChunk);
|
||||||
|
}
|
||||||
|
wdata.renderMeshPositionAndNormalChunk.Clear();
|
||||||
|
wdata.renderMeshTangentChunk.Clear();
|
||||||
|
wdata.renderMeshBoneWeightChunk.Clear();
|
||||||
|
wdata.flag.Clear();
|
||||||
|
|
||||||
|
// 削除
|
||||||
|
renderDataWorkArray.RemoveAndFill(new DataChunk(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref RenderDataWork GetRenderDataWorkRef(int index)
|
||||||
|
{
|
||||||
|
return ref renderDataWorkArray.GetRef(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSetRenderDataWorkFlag(int index, int flag)
|
||||||
|
{
|
||||||
|
ref var wdata = ref GetRenderDataWorkRef(index);
|
||||||
|
return wdata.flag.IsSet(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBitsRenderDataWorkFlag(int index, int flag, bool sw)
|
||||||
|
{
|
||||||
|
ref var wdata = ref GetRenderDataWorkRef(index);
|
||||||
|
wdata.flag.SetBits(flag, sw);
|
||||||
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 有効化
|
/// 有効化
|
||||||
@ -157,14 +342,21 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
|
static readonly ProfilerMarker writeMeshTimeProfiler = new ProfilerMarker("WriteMesh");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// レンダリング前更新
|
/// レンダリング前更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void PreRenderingUpdate()
|
void PreRenderingUpdate()
|
||||||
{
|
{
|
||||||
|
if (renderDataDict.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// メッシュへの反映
|
// メッシュへの反映
|
||||||
|
writeMeshTimeProfiler.Begin();
|
||||||
foreach (var rdata in renderDataDict.Values)
|
foreach (var rdata in renderDataDict.Values)
|
||||||
rdata?.WriteMesh();
|
rdata?.WriteMesh();
|
||||||
|
writeMeshTimeProfiler.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
@ -179,7 +371,25 @@ namespace MagicaCloth2
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sb.AppendLine($"Render Manager. Count({renderDataDict.Count})");
|
sb.AppendLine($"Render Manager. Count({renderDataDict.Count})");
|
||||||
|
sb.AppendLine($" [RenderMeshBuffer]");
|
||||||
|
sb.AppendLine($" -renderMeshPositions:{renderMeshPositions.ToSummary()}");
|
||||||
|
sb.AppendLine($" -renderMeshNormals:{renderMeshNormals.ToSummary()}");
|
||||||
|
sb.AppendLine($" -renderMeshTangents:{renderMeshTangents.ToSummary()}");
|
||||||
|
|
||||||
|
sb.AppendLine($" [RenderDataWork]");
|
||||||
|
sb.AppendLine($" -Count:{renderDataWorkArray.Count}");
|
||||||
|
if (renderDataWorkArray.Count > 0)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < renderDataWorkArray.Count; j++)
|
||||||
|
{
|
||||||
|
var wdata = renderDataWorkArray[j];
|
||||||
|
if (wdata.IsValid() == false)
|
||||||
|
continue;
|
||||||
|
sb.AppendLine($" [{j}] MappingListCount:{wdata.mappingDataIndexList.Length}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine($" [RenderData]");
|
||||||
foreach (var kv in renderDataDict)
|
foreach (var kv in renderDataDict)
|
||||||
{
|
{
|
||||||
sb.Append(kv.Value.ToString());
|
sb.Append(kv.Value.ToString());
|
||||||
|
|||||||
@ -7,6 +7,7 @@ using Unity.Burst;
|
|||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using Unity.Profiling;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Jobs;
|
using UnityEngine.Jobs;
|
||||||
|
|
||||||
@ -19,10 +20,11 @@ namespace MagicaCloth2
|
|||||||
/// またこの情報はキャラクターが動き出す前に取得しておく必要がある
|
/// またこの情報はキャラクターが動き出す前に取得しておく必要がある
|
||||||
/// そのためAwake()などで実行する
|
/// そのためAwake()などで実行する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RenderSetupData : IDisposable, ITransform
|
public partial class RenderSetupData : IDisposable, ITransform
|
||||||
{
|
{
|
||||||
public ResultCode result;
|
public ResultCode result;
|
||||||
public string name = string.Empty;
|
public string name = string.Empty;
|
||||||
|
public bool isManaged; // pre-build DeserializeManager管理
|
||||||
|
|
||||||
// タイプ
|
// タイプ
|
||||||
public enum SetupType
|
public enum SetupType
|
||||||
@ -45,11 +47,17 @@ namespace MagicaCloth2
|
|||||||
public Mesh.MeshDataArray meshDataArray; // Jobで利用するためのMeshData
|
public Mesh.MeshDataArray meshDataArray; // Jobで利用するためのMeshData
|
||||||
public int skinRootBoneIndex;
|
public int skinRootBoneIndex;
|
||||||
public int skinBoneCount;
|
public int skinBoneCount;
|
||||||
|
|
||||||
// MeshDataでは取得できないメッシュ情報
|
// MeshDataでは取得できないメッシュ情報
|
||||||
public List<Matrix4x4> bindPoseList;
|
public List<Matrix4x4> bindPoseList;
|
||||||
public NativeArray<byte> bonesPerVertexArray;
|
public NativeArray<byte> bonesPerVertexArray;
|
||||||
public NativeArray<BoneWeight1> boneWeightArray;
|
public NativeArray<BoneWeight1> boneWeightArray;
|
||||||
|
|
||||||
|
// PreBuild時のみ保持する情報.逆にmeshDataArrayは持たない
|
||||||
|
public NativeArray<Vector3> localPositions;
|
||||||
|
public NativeArray<Vector3> localNormals;
|
||||||
|
public NativeArray<Vector4> localTangents;
|
||||||
|
|
||||||
// Bone ---------------------------------------------------------------
|
// Bone ---------------------------------------------------------------
|
||||||
public List<int> rootTransformIdList;
|
public List<int> rootTransformIdList;
|
||||||
public enum BoneConnectionMode
|
public enum BoneConnectionMode
|
||||||
@ -82,7 +90,7 @@ namespace MagicaCloth2
|
|||||||
public List<FixedList512Bytes<int>> transformChildIdList; // 子IDリスト
|
public List<FixedList512Bytes<int>> transformChildIdList; // 子IDリスト
|
||||||
public NativeArray<float3> transformPositions;
|
public NativeArray<float3> transformPositions;
|
||||||
public NativeArray<quaternion> transformRotations;
|
public NativeArray<quaternion> transformRotations;
|
||||||
public NativeArray<float3> transformLocalPositins;
|
public NativeArray<float3> transformLocalPositions;
|
||||||
public NativeArray<quaternion> transformLocalRotations;
|
public NativeArray<quaternion> transformLocalRotations;
|
||||||
public NativeArray<float3> transformScales;
|
public NativeArray<float3> transformScales;
|
||||||
public NativeArray<quaternion> transformInverseRotations;
|
public NativeArray<quaternion> transformInverseRotations;
|
||||||
@ -95,16 +103,21 @@ namespace MagicaCloth2
|
|||||||
public bool IsSuccess() => result.IsSuccess();
|
public bool IsSuccess() => result.IsSuccess();
|
||||||
public bool IsFaild() => result.IsFaild();
|
public bool IsFaild() => result.IsFaild();
|
||||||
public int TransformCount => transformList?.Count ?? 0;
|
public int TransformCount => transformList?.Count ?? 0;
|
||||||
|
public bool HasMeshDataArray => meshDataArray.Length > 0;
|
||||||
|
public bool HasLocalPositions => localPositions.IsCreated;
|
||||||
|
public bool HasTangent => localTangents.IsCreated && localTangents.Length > 0;
|
||||||
|
|
||||||
//static readonly ProfilerMarker initProfiler = new ProfilerMarker("Render Setup");
|
static readonly ProfilerMarker readTransformProfiler = new ProfilerMarker("readTransform");
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
|
public RenderSetupData() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// レンダラーから基本情報を作成する(メインスレッドのみ)
|
/// レンダラーから基本情報を作成する(メインスレッドのみ)
|
||||||
/// タイプはMeshになる
|
/// タイプはMeshになる
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ren"></param>
|
/// <param name="ren"></param>
|
||||||
public RenderSetupData(Renderer ren)
|
public RenderSetupData(RenderSetupSerializeData referenceInitSetupData, Renderer ren)
|
||||||
{
|
{
|
||||||
//using (initProfiler.Auto())
|
//using (initProfiler.Auto())
|
||||||
{
|
{
|
||||||
@ -119,6 +132,9 @@ namespace MagicaCloth2
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初期化データの有無
|
||||||
|
bool useInitData = referenceInitSetupData != null;
|
||||||
|
|
||||||
name = ren.name;
|
name = ren.name;
|
||||||
|
|
||||||
var sren = ren as SkinnedMeshRenderer;
|
var sren = ren as SkinnedMeshRenderer;
|
||||||
@ -133,7 +149,36 @@ namespace MagicaCloth2
|
|||||||
// 描画の基準トランスフォーム
|
// 描画の基準トランスフォーム
|
||||||
var renderTransform = ren.transform;
|
var renderTransform = ren.transform;
|
||||||
|
|
||||||
if (sren)
|
if (useInitData)
|
||||||
|
{
|
||||||
|
// 初期化データがある場合はコピーして終わり
|
||||||
|
skinBoneCount = referenceInitSetupData.skinBoneCount;
|
||||||
|
skinRootBoneIndex = referenceInitSetupData.skinRootBoneIndex;
|
||||||
|
renderTransformIndex = referenceInitSetupData.renderTransformIndex;
|
||||||
|
hasBoneWeight = referenceInitSetupData.hasBoneWeight;
|
||||||
|
|
||||||
|
// transformList復元
|
||||||
|
transformList = new List<Transform>(new Transform[referenceInitSetupData.transformCount]);
|
||||||
|
int ucnt = referenceInitSetupData.useTransformCount;
|
||||||
|
for (int i = 0; i < ucnt; i++)
|
||||||
|
{
|
||||||
|
int tindex = referenceInitSetupData.useTransformIndexArray[i];
|
||||||
|
transformList[tindex] = referenceInitSetupData.transformArray[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SkinnedMeshRendererかつオリジナルメッシュが存在する場合はSkinnedMeshRenererを復元する
|
||||||
|
// 実行時キャラクターコピーへの対応
|
||||||
|
if (sren && referenceInitSetupData.originalMesh && sren.sharedMesh != referenceInitSetupData.originalMesh && skinBoneCount > 0)
|
||||||
|
{
|
||||||
|
sren.sharedMesh = referenceInitSetupData.originalMesh;
|
||||||
|
var newBones = new Transform[skinBoneCount];
|
||||||
|
transformList.CopyTo(0, newBones, 0, skinBoneCount);
|
||||||
|
sren.bones = newBones;
|
||||||
|
sren.rootBone = transformList[skinRootBoneIndex];
|
||||||
|
//Debug.Log($"★SkinnedMeshRenderer再構成");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sren)
|
||||||
{
|
{
|
||||||
// bones
|
// bones
|
||||||
// このスキニングボーンの取得が特に重くメモリアロケーションも頻発する問題児
|
// このスキニングボーンの取得が特に重くメモリアロケーションも頻発する問題児
|
||||||
@ -188,7 +233,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
// トランスフォーム情報の読み取り
|
// トランスフォーム情報の読み取り
|
||||||
ReadTransformInformation(includeChilds: false);
|
ReadTransformInformation(includeChilds: false, referenceInitSetupData, ren.transform);
|
||||||
|
|
||||||
// bindpose / weights
|
// bindpose / weights
|
||||||
if (sren)
|
if (sren)
|
||||||
@ -207,12 +252,14 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// どうもコピーを作らないとダメらしい..
|
// どうもコピーを作らないとダメらしい..
|
||||||
// ※具体的にはメッシュのクローンを作成したときに壊れる
|
// ※具体的にはメッシュのクローンを作成したときに壊れる
|
||||||
var weightArray = mesh.GetAllBoneWeights();
|
using var weightArray = mesh.GetAllBoneWeights();
|
||||||
var perVertexArray = mesh.GetBonesPerVertex();
|
using var perVertexArray = mesh.GetBonesPerVertex();
|
||||||
boneWeightArray = new NativeArray<BoneWeight1>(weightArray, Allocator.Persistent);
|
boneWeightArray = new NativeArray<BoneWeight1>(weightArray, Allocator.Persistent);
|
||||||
bonesPerVertexArray = new NativeArray<byte>(perVertexArray, Allocator.Persistent);
|
bonesPerVertexArray = new NativeArray<byte>(perVertexArray, Allocator.Persistent);
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
// 5ボーン以上を利用する頂点ウエイトは警告とする。一応無効となるだけで動くのでエラーにはしない。
|
// 5ボーン以上を利用する頂点ウエイトは警告とする。一応無効となるだけで動くのでエラーにはしない。
|
||||||
|
// なおこの検証はビルド環境では行わない
|
||||||
int vcnt = mesh.vertexCount;
|
int vcnt = mesh.vertexCount;
|
||||||
using var bonesPerVertexResult = new NativeReference<Define.Result>(Allocator.TempJob);
|
using var bonesPerVertexResult = new NativeReference<Define.Result>(Allocator.TempJob);
|
||||||
var job = new VertexWeight5BoneCheckJob()
|
var job = new VertexWeight5BoneCheckJob()
|
||||||
@ -223,6 +270,7 @@ namespace MagicaCloth2
|
|||||||
};
|
};
|
||||||
job.Run();
|
job.Run();
|
||||||
result.SetWarning(bonesPerVertexResult.Value);
|
result.SetWarning(bonesPerVertexResult.Value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -276,6 +324,10 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// 5ウエイト以上の検出
|
||||||
|
/// </summary>
|
||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct VertexWeight5BoneCheckJob : IJob
|
struct VertexWeight5BoneCheckJob : IJob
|
||||||
{
|
{
|
||||||
@ -301,6 +353,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ルートボーンリストから基本情報を作成する(メインスレッドのみ)
|
/// ルートボーンリストから基本情報を作成する(メインスレッドのみ)
|
||||||
@ -309,6 +362,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="renderTransform"></param>
|
/// <param name="renderTransform"></param>
|
||||||
/// <param name="rootTransforms"></param>
|
/// <param name="rootTransforms"></param>
|
||||||
public RenderSetupData(
|
public RenderSetupData(
|
||||||
|
RenderSetupSerializeData referenceInitSetupData,
|
||||||
SetupType setType,
|
SetupType setType,
|
||||||
Transform renderTransform,
|
Transform renderTransform,
|
||||||
List<Transform> rootTransforms,
|
List<Transform> rootTransforms,
|
||||||
@ -322,6 +376,8 @@ namespace MagicaCloth2
|
|||||||
//using (initProfiler.Auto())
|
//using (initProfiler.Auto())
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
bool useInitData = referenceInitSetupData != null;
|
||||||
|
|
||||||
// Boneタイプに設定
|
// Boneタイプに設定
|
||||||
setupType = setType;
|
setupType = setType;
|
||||||
|
|
||||||
@ -344,6 +400,15 @@ namespace MagicaCloth2
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
// 必要なトランスフォーム情報
|
// 必要なトランスフォーム情報
|
||||||
|
if (useInitData)
|
||||||
|
{
|
||||||
|
// 初期化データがある場合はコピーして終わり
|
||||||
|
transformList = new List<Transform>(referenceInitSetupData.transformArray);
|
||||||
|
skinBoneCount = referenceInitSetupData.skinBoneCount;
|
||||||
|
renderTransformIndex = referenceInitSetupData.renderTransformIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
var indexDict = new Dictionary<Transform, int>(256);
|
var indexDict = new Dictionary<Transform, int>(256);
|
||||||
transformList = new List<Transform>(256);
|
transformList = new List<Transform>(256);
|
||||||
|
|
||||||
@ -370,6 +435,14 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// スキニングボーン数
|
||||||
|
skinBoneCount = transformList.Count;
|
||||||
|
|
||||||
|
// レンダートランスフォームを最後に追加
|
||||||
|
renderTransformIndex = transformList.Count;
|
||||||
|
transformList.Add(renderTransform);
|
||||||
|
}
|
||||||
|
|
||||||
// root transform id
|
// root transform id
|
||||||
rootTransformIdList = new List<int>(rootTransforms.Count);
|
rootTransformIdList = new List<int>(rootTransforms.Count);
|
||||||
foreach (var t in rootTransforms)
|
foreach (var t in rootTransforms)
|
||||||
@ -392,15 +465,8 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// スキニングボーン数
|
|
||||||
skinBoneCount = transformList.Count;
|
|
||||||
|
|
||||||
// レンダートランスフォームを最後に追加
|
|
||||||
renderTransformIndex = transformList.Count;
|
|
||||||
transformList.Add(renderTransform);
|
|
||||||
|
|
||||||
// トランスフォーム情報の読み取り
|
// トランスフォーム情報の読み取り
|
||||||
ReadTransformInformation(includeChilds: true);
|
ReadTransformInformation(includeChilds: true, referenceInitSetupData, renderTransform);
|
||||||
|
|
||||||
// 完了
|
// 完了
|
||||||
result.SetSuccess();
|
result.SetSuccess();
|
||||||
@ -422,24 +488,90 @@ namespace MagicaCloth2
|
|||||||
/// トランスフォーム情報の読み取り(メインスレッドのみ)
|
/// トランスフォーム情報の読み取り(メインスレッドのみ)
|
||||||
/// この情報だけはキャラクターが動く前に取得する必要がある
|
/// この情報だけはキャラクターが動く前に取得する必要がある
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ReadTransformInformation(bool includeChilds)
|
void ReadTransformInformation(bool includeChilds, RenderSetupSerializeData referenceInitSetupData, Transform rendererTransform)
|
||||||
{
|
{
|
||||||
|
readTransformProfiler.Begin();
|
||||||
|
|
||||||
int tcnt = transformList.Count;
|
int tcnt = transformList.Count;
|
||||||
using var transformArray = new TransformAccessArray(transformList.ToArray());
|
bool useInitData = referenceInitSetupData != null;
|
||||||
|
|
||||||
|
// バッファ作成
|
||||||
transformPositions = new NativeArray<float3>(tcnt, Allocator.Persistent);
|
transformPositions = new NativeArray<float3>(tcnt, Allocator.Persistent);
|
||||||
transformRotations = new NativeArray<quaternion>(tcnt, Allocator.Persistent);
|
transformRotations = new NativeArray<quaternion>(tcnt, Allocator.Persistent);
|
||||||
transformLocalPositins = new NativeArray<float3>(tcnt, Allocator.Persistent);
|
transformLocalPositions = new NativeArray<float3>(tcnt, Allocator.Persistent);
|
||||||
transformLocalRotations = new NativeArray<quaternion>(tcnt, Allocator.Persistent);
|
transformLocalRotations = new NativeArray<quaternion>(tcnt, Allocator.Persistent);
|
||||||
transformScales = new NativeArray<float3>(tcnt, Allocator.Persistent);
|
transformScales = new NativeArray<float3>(tcnt, Allocator.Persistent);
|
||||||
transformInverseRotations = new NativeArray<quaternion>(tcnt, Allocator.Persistent);
|
transformInverseRotations = new NativeArray<quaternion>(tcnt, Allocator.Persistent);
|
||||||
|
|
||||||
|
// 読み取り
|
||||||
|
if (useInitData)
|
||||||
|
{
|
||||||
|
Debug.Assert(tcnt == referenceInitSetupData.transformCount);
|
||||||
|
|
||||||
|
// 初期化データがある場合はコピーして終わり
|
||||||
|
int ucnt = referenceInitSetupData.useTransformCount;
|
||||||
|
|
||||||
|
if (ucnt == tcnt)
|
||||||
|
{
|
||||||
|
// 全体コピー
|
||||||
|
NativeArray<float3>.Copy(referenceInitSetupData.transformPositions, 0, transformPositions, 0, ucnt);
|
||||||
|
NativeArray<quaternion>.Copy(referenceInitSetupData.transformRotations, 0, transformRotations, 0, ucnt);
|
||||||
|
NativeArray<float3>.Copy(referenceInitSetupData.transformLocalPositions, 0, transformLocalPositions, 0, ucnt);
|
||||||
|
NativeArray<quaternion>.Copy(referenceInitSetupData.transformLocalRotations, 0, transformLocalRotations, 0, ucnt);
|
||||||
|
NativeArray<float3>.Copy(referenceInitSetupData.transformScales, 0, transformScales, 0, ucnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 差分
|
||||||
|
for (int i = 0; i < ucnt; i++)
|
||||||
|
{
|
||||||
|
int tindex = referenceInitSetupData.useTransformIndexArray[i];
|
||||||
|
transformPositions[tindex] = referenceInitSetupData.transformPositions[i];
|
||||||
|
transformRotations[tindex] = referenceInitSetupData.transformRotations[i];
|
||||||
|
transformLocalPositions[tindex] = referenceInitSetupData.transformLocalPositions[i];
|
||||||
|
transformLocalRotations[tindex] = referenceInitSetupData.transformLocalRotations[i];
|
||||||
|
transformScales[tindex] = referenceInitSetupData.transformScales[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逆回転のみ計算で求める
|
||||||
|
var job = new CalcInverseRotationJob()
|
||||||
|
{
|
||||||
|
rotations = transformRotations,
|
||||||
|
inverseRotations = transformInverseRotations,
|
||||||
|
};
|
||||||
|
job.Run(tcnt);
|
||||||
|
|
||||||
|
// 初期センタートランスフォームを別途コピーしておく
|
||||||
|
initRenderLocalToWorld = referenceInitSetupData.initRenderLocalToWorld;
|
||||||
|
initRenderWorldtoLocal = referenceInitSetupData.initRenderWorldtoLocal;
|
||||||
|
initRenderRotation = referenceInitSetupData.initRenderRotation;
|
||||||
|
initRenderScale = referenceInitSetupData.initRenderScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//using var transformArray = new TransformAccessArray(transformList.ToArray());
|
||||||
|
// Unity6.1対応
|
||||||
|
using var transformArray = new TransformAccessArray(transformList.Count);
|
||||||
|
int cnt = transformList.Count;
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
var t = transformList[i];
|
||||||
|
if (t == null)
|
||||||
|
t = rendererTransform;
|
||||||
|
//transformArray[i] = t;
|
||||||
|
transformArray.Add(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var job = new ReadTransformJob()
|
var job = new ReadTransformJob()
|
||||||
{
|
{
|
||||||
positions = transformPositions,
|
positions = transformPositions,
|
||||||
rotations = transformRotations,
|
rotations = transformRotations,
|
||||||
scales = transformScales,
|
scales = transformScales,
|
||||||
localPositions = transformLocalPositins,
|
localPositions = transformLocalPositions,
|
||||||
localRotations = transformLocalRotations,
|
localRotations = transformLocalRotations,
|
||||||
inverseRotations = transformInverseRotations,
|
inverseRotations = transformInverseRotations
|
||||||
};
|
};
|
||||||
// シミュレーション以外でワーカーを消費したくないのでRun()版にしておく
|
// シミュレーション以外でワーカーを消費したくないのでRun()版にしておく
|
||||||
job.RunReadOnly(transformArray);
|
job.RunReadOnly(transformArray);
|
||||||
@ -449,15 +581,24 @@ namespace MagicaCloth2
|
|||||||
initRenderWorldtoLocal = math.inverse(initRenderLocalToWorld);
|
initRenderWorldtoLocal = math.inverse(initRenderLocalToWorld);
|
||||||
initRenderRotation = transformRotations[renderTransformIndex];
|
initRenderRotation = transformRotations[renderTransformIndex];
|
||||||
initRenderScale = transformScales[renderTransformIndex];
|
initRenderScale = transformScales[renderTransformIndex];
|
||||||
|
}
|
||||||
|
|
||||||
// id
|
// id / parent id
|
||||||
transformIdList = new List<int>(tcnt);
|
transformIdList = new List<int>(tcnt);
|
||||||
transformParentIdList = new List<int>(tcnt);
|
transformParentIdList = new List<int>(tcnt);
|
||||||
for (int i = 0; i < tcnt; i++)
|
for (int i = 0; i < tcnt; i++)
|
||||||
{
|
{
|
||||||
|
int id = 0, pid = 0;
|
||||||
|
|
||||||
var t = transformList[i];
|
var t = transformList[i];
|
||||||
transformIdList.Add(t?.GetInstanceID() ?? 0);
|
if (t)
|
||||||
transformParentIdList.Add(t?.parent?.GetInstanceID() ?? 0);
|
{
|
||||||
|
id = t.GetInstanceID();
|
||||||
|
if (includeChilds && t.parent)
|
||||||
|
pid = t.parent.GetInstanceID();
|
||||||
|
}
|
||||||
|
transformIdList.Add(id);
|
||||||
|
transformParentIdList.Add(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// child id
|
// child id
|
||||||
@ -468,7 +609,7 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
var t = transformList[i];
|
var t = transformList[i];
|
||||||
var clist = new FixedList512Bytes<int>();
|
var clist = new FixedList512Bytes<int>();
|
||||||
if (t?.childCount > 0)
|
if (t && t.childCount > 0)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < t.childCount; j++)
|
for (int j = 0; j < t.childCount; j++)
|
||||||
{
|
{
|
||||||
@ -479,6 +620,32 @@ namespace MagicaCloth2
|
|||||||
transformChildIdList.Add(clist);
|
transformChildIdList.Add(clist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readTransformProfiler.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 逆回転を計算で求める
|
||||||
|
/// </summary>
|
||||||
|
[BurstCompile]
|
||||||
|
struct CalcInverseRotationJob : IJobParallelFor
|
||||||
|
{
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<quaternion> rotations;
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
|
[Unity.Collections.WriteOnly]
|
||||||
|
public NativeArray<quaternion> inverseRotations;
|
||||||
|
|
||||||
|
public void Execute(int index)
|
||||||
|
{
|
||||||
|
var rot = rotations[index];
|
||||||
|
if (math.any(rot.value))
|
||||||
|
{
|
||||||
|
// どれか1つでも != 0 なら実行する
|
||||||
|
var irot = math.inverse(rot);
|
||||||
|
inverseRotations[index] = irot;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -487,16 +654,22 @@ namespace MagicaCloth2
|
|||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct ReadTransformJob : IJobParallelForTransform
|
struct ReadTransformJob : IJobParallelForTransform
|
||||||
{
|
{
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<float3> positions;
|
public NativeArray<float3> positions;
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<quaternion> rotations;
|
public NativeArray<quaternion> rotations;
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<float3> scales;
|
public NativeArray<float3> scales;
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<float3> localPositions;
|
public NativeArray<float3> localPositions;
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<quaternion> localRotations;
|
public NativeArray<quaternion> localRotations;
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<quaternion> inverseRotations;
|
public NativeArray<quaternion> inverseRotations;
|
||||||
|
|
||||||
@ -527,23 +700,22 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (bonesPerVertexArray.IsCreated)
|
// Pre-Build DeserializeManager管理中は破棄させない
|
||||||
bonesPerVertexArray.Dispose();
|
if (isManaged)
|
||||||
if (boneWeightArray.IsCreated)
|
return;
|
||||||
boneWeightArray.Dispose();
|
|
||||||
|
|
||||||
if (transformPositions.IsCreated)
|
bonesPerVertexArray.MC2DisposeSafe();
|
||||||
transformPositions.Dispose();
|
boneWeightArray.MC2DisposeSafe();
|
||||||
if (transformRotations.IsCreated)
|
localPositions.MC2DisposeSafe();
|
||||||
transformRotations.Dispose();
|
localNormals.MC2DisposeSafe();
|
||||||
if (transformLocalPositins.IsCreated)
|
localTangents.MC2DisposeSafe();
|
||||||
transformLocalPositins.Dispose();
|
|
||||||
if (transformLocalRotations.IsCreated)
|
transformPositions.MC2DisposeSafe();
|
||||||
transformLocalRotations.Dispose();
|
transformRotations.MC2DisposeSafe();
|
||||||
if (transformScales.IsCreated)
|
transformLocalPositions.MC2DisposeSafe();
|
||||||
transformScales.Dispose();
|
transformLocalRotations.MC2DisposeSafe();
|
||||||
if (transformInverseRotations.IsCreated)
|
transformScales.MC2DisposeSafe();
|
||||||
transformInverseRotations.Dispose();
|
transformInverseRotations.MC2DisposeSafe();
|
||||||
|
|
||||||
// MeshDataArrayはメインスレッドのみDispose()可能
|
// MeshDataArrayはメインスレッドのみDispose()可能
|
||||||
if (setupType == SetupType.MeshCloth)
|
if (setupType == SetupType.MeshCloth)
|
||||||
@ -554,10 +726,14 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void GetUsedTransform(HashSet<Transform> transformSet)
|
public void GetUsedTransform(HashSet<Transform> transformSet)
|
||||||
|
{
|
||||||
|
if (transformList != null)
|
||||||
{
|
{
|
||||||
foreach (var t in transformList)
|
foreach (var t in transformList)
|
||||||
|
if (t)
|
||||||
transformSet.Add(t);
|
transformSet.Add(t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
|
||||||
{
|
{
|
||||||
@ -622,9 +798,10 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public float4x4 GetRendeerLocalToWorldMatrix()
|
public float4x4 GetRendeerLocalToWorldMatrix()
|
||||||
{
|
{
|
||||||
var pos = transformPositions[renderTransformIndex];
|
int index = renderTransformIndex;
|
||||||
var rot = transformRotations[renderTransformIndex];
|
var pos = transformPositions[index];
|
||||||
var scl = transformScales[renderTransformIndex];
|
var rot = transformRotations[index];
|
||||||
|
var scl = transformScales[index];
|
||||||
return float4x4.TRS(pos, rot, scl);
|
return float4x4.TRS(pos, rot, scl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -96,7 +96,7 @@ namespace MagicaCloth2
|
|||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
void AfterFixedUpdate()
|
void AfterFixedUpdate()
|
||||||
{
|
{
|
||||||
//Debug.Log($"AF. F:{Time.frameCount}");
|
//Debug.Log($"AfterFixedUpdate. F:{Time.frameCount}");
|
||||||
FixedUpdateCount++;
|
FixedUpdateCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ namespace MagicaCloth2
|
|||||||
sb.AppendLine($"MaxSimulationCountPerFrame:{maxSimulationCountPerFrame}");
|
sb.AppendLine($"MaxSimulationCountPerFrame:{maxSimulationCountPerFrame}");
|
||||||
sb.AppendLine($"GlobalTimeScale:{GlobalTimeScale}");
|
sb.AppendLine($"GlobalTimeScale:{GlobalTimeScale}");
|
||||||
sb.AppendLine($"SimulationDeltaTime:{SimulationDeltaTime}");
|
sb.AppendLine($"SimulationDeltaTime:{SimulationDeltaTime}");
|
||||||
sb.AppendLine($"MaxDeltaTime:{MaxDeltaTime}");
|
//sb.AppendLine($"MaxDeltaTime:{MaxDeltaTime}");
|
||||||
sb.AppendLine($"SimulationPower:{SimulationPower}");
|
sb.AppendLine($"SimulationPower:{SimulationPower}");
|
||||||
}
|
}
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -86,6 +86,12 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyFrom(in TeamWindData wdata)
|
||||||
|
{
|
||||||
|
windZoneList = wdata.windZoneList;
|
||||||
|
movingWind = wdata.movingWind;
|
||||||
|
}
|
||||||
|
|
||||||
//public void DebugLog(int teamId)
|
//public void DebugLog(int teamId)
|
||||||
//{
|
//{
|
||||||
// Debug.Log($"TeamWindData:{teamId}, zoneCnt:{ZoneCount}");
|
// Debug.Log($"TeamWindData:{teamId}, zoneCnt:{ZoneCount}");
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
@ -16,7 +17,7 @@ namespace MagicaCloth2
|
|||||||
/// TransformAccessArrayを中心とした一連のTransform管理クラス
|
/// TransformAccessArrayを中心とした一連のTransform管理クラス
|
||||||
/// スレッドで利用できるように様々な工夫を行っている
|
/// スレッドで利用できるように様々な工夫を行っている
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TransformData : IDisposable
|
public partial class TransformData : IDisposable
|
||||||
{
|
{
|
||||||
internal List<Transform> transformList;
|
internal List<Transform> transformList;
|
||||||
|
|
||||||
@ -101,10 +102,7 @@ namespace MagicaCloth2
|
|||||||
Queue<int> emptyStack;
|
Queue<int> emptyStack;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public TransformData()
|
public TransformData() { }
|
||||||
{
|
|
||||||
Init(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformData(int capacity)
|
public TransformData(int capacity)
|
||||||
{
|
{
|
||||||
@ -133,7 +131,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
transformList.Clear();
|
transformList?.Clear();
|
||||||
idArray?.Dispose();
|
idArray?.Dispose();
|
||||||
parentIdArray?.Dispose();
|
parentIdArray?.Dispose();
|
||||||
flagArray?.Dispose();
|
flagArray?.Dispose();
|
||||||
@ -145,15 +143,11 @@ namespace MagicaCloth2
|
|||||||
localPositionArray?.Dispose();
|
localPositionArray?.Dispose();
|
||||||
localRotationArray?.Dispose();
|
localRotationArray?.Dispose();
|
||||||
inverseRotationArray?.Dispose();
|
inverseRotationArray?.Dispose();
|
||||||
emptyStack.Clear();
|
emptyStack?.Clear();
|
||||||
|
|
||||||
// transformAccessArrayはメインスレッドのみ
|
// transformAccessArrayはメインスレッドのみ
|
||||||
if (transformAccessArray.isCreated)
|
if (transformAccessArray.isCreated)
|
||||||
{
|
{
|
||||||
//if (MagicaManager.Discard != null)
|
|
||||||
// MagicaManager.Discard.AddMain(transformAccessArray);
|
|
||||||
//else
|
|
||||||
// transformAccessArray.Dispose();
|
|
||||||
transformAccessArray.Dispose();
|
transformAccessArray.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,6 +155,7 @@ namespace MagicaCloth2
|
|||||||
public int Count => transformList.Count;
|
public int Count => transformList.Count;
|
||||||
public int RootCount => rootIdList?.Count ?? 0;
|
public int RootCount => rootIdList?.Count ?? 0;
|
||||||
public bool IsDirty => isDirty;
|
public bool IsDirty => isDirty;
|
||||||
|
public bool IsEmpty => transformList == null;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -951,5 +946,19 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
return math.inverse(GetLocalToWorldMatrix(index));
|
return math.inverse(GetLocalToWorldMatrix(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
int transformListCount = transformList?.Count ?? 0;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendLine("==== TransformData ====");
|
||||||
|
sb.AppendLine($"isDirty:{isDirty}");
|
||||||
|
sb.AppendLine($"transformList:{transformListCount}");
|
||||||
|
sb.AppendLine($"flagArray:{flagArray.Length}");
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,16 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal ExNativeArray<quaternion> initLocalRotationArray;
|
internal ExNativeArray<quaternion> initLocalRotationArray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// シミュレーションの基準となるlocalPosition
|
||||||
|
/// </summary>
|
||||||
|
internal ExNativeArray<float3> baseLocalPositionArray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// シミュレーションの基準となるlocalRotation
|
||||||
|
/// </summary>
|
||||||
|
internal ExNativeArray<quaternion> baseLocalRotationArray;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ワールド座標
|
/// ワールド座標
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,7 +54,7 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ワールド逆回転
|
/// ワールド逆回転
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal ExNativeArray<quaternion> inverseRotationArray;
|
//internal ExNativeArray<quaternion> inverseRotationArray;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ワールドスケール
|
/// ワールドスケール
|
||||||
@ -62,6 +72,16 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal ExNativeArray<quaternion> localRotationArray;
|
internal ExNativeArray<quaternion> localRotationArray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ローカルスケール
|
||||||
|
/// </summary>
|
||||||
|
internal ExNativeArray<float3> localScaleArray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ワールド変換マトリックス
|
||||||
|
/// </summary>
|
||||||
|
internal ExNativeArray<float4x4> localToWorldMatrixArray;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 接続チームID(0=なし)
|
/// 接続チームID(0=なし)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -78,15 +98,16 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 書き込み用トランスフォームのデータ参照インデックス
|
/// コンポーネント用ワールド座標
|
||||||
/// つまり上記配列へのインデックス
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
//internal ExNativeArray<short> writeIndexArray;
|
internal ExNativeArray<float3> componentPositionArray;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 書き込み用トランスフォームアクセス配列
|
/// コンポーネント用トランスフォーム
|
||||||
/// </summary>
|
/// </summary>
|
||||||
//internal TransformAccessArray writeTransformAccessArray;
|
internal TransformAccessArray componentTransformAccessArray;
|
||||||
|
|
||||||
|
internal NativeReference<bool> existFixedTeam;
|
||||||
|
|
||||||
bool isValid;
|
bool isValid;
|
||||||
|
|
||||||
@ -98,24 +119,32 @@ namespace MagicaCloth2
|
|||||||
flagArray?.Dispose();
|
flagArray?.Dispose();
|
||||||
initLocalPositionArray?.Dispose();
|
initLocalPositionArray?.Dispose();
|
||||||
initLocalRotationArray?.Dispose();
|
initLocalRotationArray?.Dispose();
|
||||||
|
baseLocalPositionArray?.Dispose();
|
||||||
|
baseLocalRotationArray?.Dispose();
|
||||||
positionArray?.Dispose();
|
positionArray?.Dispose();
|
||||||
rotationArray?.Dispose();
|
rotationArray?.Dispose();
|
||||||
inverseRotationArray?.Dispose();
|
//inverseRotationArray?.Dispose();
|
||||||
scaleArray?.Dispose();
|
scaleArray?.Dispose();
|
||||||
localPositionArray?.Dispose();
|
localPositionArray?.Dispose();
|
||||||
localRotationArray?.Dispose();
|
localRotationArray?.Dispose();
|
||||||
|
localScaleArray?.Dispose();
|
||||||
|
localToWorldMatrixArray?.Dispose();
|
||||||
teamIdArray?.Dispose();
|
teamIdArray?.Dispose();
|
||||||
//writeIndexArray?.Dispose();
|
//writeIndexArray?.Dispose();
|
||||||
|
|
||||||
flagArray = null;
|
flagArray = null;
|
||||||
initLocalPositionArray = null;
|
initLocalPositionArray = null;
|
||||||
initLocalRotationArray = null;
|
initLocalRotationArray = null;
|
||||||
|
baseLocalPositionArray = null;
|
||||||
|
baseLocalRotationArray = null;
|
||||||
positionArray = null;
|
positionArray = null;
|
||||||
rotationArray = null;
|
rotationArray = null;
|
||||||
inverseRotationArray = null;
|
//inverseRotationArray = null;
|
||||||
scaleArray = null;
|
scaleArray = null;
|
||||||
localPositionArray = null;
|
localPositionArray = null;
|
||||||
localRotationArray = null;
|
localRotationArray = null;
|
||||||
|
localScaleArray = null;
|
||||||
|
localToWorldMatrixArray = null;
|
||||||
teamIdArray = null;
|
teamIdArray = null;
|
||||||
//writeIndexArray = null;
|
//writeIndexArray = null;
|
||||||
|
|
||||||
@ -123,6 +152,13 @@ namespace MagicaCloth2
|
|||||||
transformAccessArray.Dispose();
|
transformAccessArray.Dispose();
|
||||||
//if (writeTransformAccessArray.isCreated)
|
//if (writeTransformAccessArray.isCreated)
|
||||||
// writeTransformAccessArray.Dispose();
|
// writeTransformAccessArray.Dispose();
|
||||||
|
|
||||||
|
componentPositionArray?.Dispose();
|
||||||
|
if (componentTransformAccessArray.isCreated)
|
||||||
|
componentTransformAccessArray.Dispose();
|
||||||
|
|
||||||
|
if (existFixedTeam.IsCreated)
|
||||||
|
existFixedTeam.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnterdEditMode()
|
public void EnterdEditMode()
|
||||||
@ -138,16 +174,25 @@ namespace MagicaCloth2
|
|||||||
flagArray = new ExNativeArray<ExBitFlag8>(capacity);
|
flagArray = new ExNativeArray<ExBitFlag8>(capacity);
|
||||||
initLocalPositionArray = new ExNativeArray<float3>(capacity);
|
initLocalPositionArray = new ExNativeArray<float3>(capacity);
|
||||||
initLocalRotationArray = new ExNativeArray<quaternion>(capacity);
|
initLocalRotationArray = new ExNativeArray<quaternion>(capacity);
|
||||||
|
baseLocalPositionArray = new ExNativeArray<float3>(capacity);
|
||||||
|
baseLocalRotationArray = new ExNativeArray<quaternion>(capacity);
|
||||||
positionArray = new ExNativeArray<float3>(capacity);
|
positionArray = new ExNativeArray<float3>(capacity);
|
||||||
rotationArray = new ExNativeArray<quaternion>(capacity);
|
rotationArray = new ExNativeArray<quaternion>(capacity);
|
||||||
inverseRotationArray = new ExNativeArray<quaternion>(capacity);
|
//inverseRotationArray = new ExNativeArray<quaternion>(capacity);
|
||||||
scaleArray = new ExNativeArray<float3>(capacity);
|
scaleArray = new ExNativeArray<float3>(capacity);
|
||||||
localPositionArray = new ExNativeArray<float3>(capacity);
|
localPositionArray = new ExNativeArray<float3>(capacity);
|
||||||
localRotationArray = new ExNativeArray<quaternion>(capacity);
|
localRotationArray = new ExNativeArray<quaternion>(capacity);
|
||||||
|
localScaleArray = new ExNativeArray<float3>(capacity);
|
||||||
|
localToWorldMatrixArray = new ExNativeArray<float4x4>(capacity);
|
||||||
teamIdArray = new ExNativeArray<short>(capacity);
|
teamIdArray = new ExNativeArray<short>(capacity);
|
||||||
|
|
||||||
transformAccessArray = new TransformAccessArray(capacity);
|
transformAccessArray = new TransformAccessArray(capacity);
|
||||||
|
|
||||||
|
componentPositionArray = new ExNativeArray<float3>(capacity);
|
||||||
|
componentTransformAccessArray = new TransformAccessArray(capacity);
|
||||||
|
|
||||||
|
existFixedTeam = new NativeReference<bool>(Allocator.Persistent);
|
||||||
|
|
||||||
isValid = true;
|
isValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,30 +203,34 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TransformDataを追加する
|
/// VirtualMeshのTransformDataを追加する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tdata"></param>
|
/// <param name="tdata"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal DataChunk AddTransform(TransformData tdata, int teamId)
|
internal DataChunk AddTransform(VirtualMeshContainer cmesh, int teamId)
|
||||||
{
|
{
|
||||||
if (isValid == false)
|
if (isValid == false)
|
||||||
return default;
|
return default;
|
||||||
|
|
||||||
Debug.Assert(tdata != null);
|
Debug.Assert(cmesh != null);
|
||||||
int cnt = tdata.Count;
|
int cnt = cmesh.GetTransformCount();
|
||||||
|
|
||||||
// データコピー追加
|
// データコピー追加
|
||||||
var c = flagArray.AddRange(tdata.flagArray);
|
var c = flagArray.AddRange(cmesh.shareVirtualMesh.transformData.flagArray);
|
||||||
initLocalPositionArray.AddRange(tdata.initLocalPositionArray);
|
initLocalPositionArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalPositionArray);
|
||||||
initLocalRotationArray.AddRange(tdata.initLocalRotationArray);
|
initLocalRotationArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalRotationArray);
|
||||||
|
baseLocalPositionArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalPositionArray);
|
||||||
|
baseLocalRotationArray.AddRange(cmesh.shareVirtualMesh.transformData.initLocalRotationArray);
|
||||||
|
|
||||||
// 領域のみ追加
|
// 領域のみ追加
|
||||||
positionArray.AddRange(cnt);
|
positionArray.AddRange(cnt);
|
||||||
rotationArray.AddRange(cnt);
|
rotationArray.AddRange(cnt);
|
||||||
inverseRotationArray.AddRange(cnt);
|
//inverseRotationArray.AddRange(cnt);
|
||||||
scaleArray.AddRange(cnt);
|
scaleArray.AddRange(cnt);
|
||||||
localPositionArray.AddRange(cnt);
|
localPositionArray.AddRange(cnt);
|
||||||
localRotationArray.AddRange(cnt);
|
localRotationArray.AddRange(cnt);
|
||||||
|
localScaleArray.AddRange(cnt);
|
||||||
|
localToWorldMatrixArray.AddRange(cnt);
|
||||||
|
|
||||||
// チームID
|
// チームID
|
||||||
teamIdArray.AddRange(cnt, (short)teamId);
|
teamIdArray.AddRange(cnt, (short)teamId);
|
||||||
@ -190,16 +239,19 @@ namespace MagicaCloth2
|
|||||||
int nowcnt = transformAccessArray.length;
|
int nowcnt = transformAccessArray.length;
|
||||||
|
|
||||||
// データチャンクの開始まで埋める
|
// データチャンクの開始まで埋める
|
||||||
|
var meshT = cmesh.GetCenterTransform();
|
||||||
int start = c.startIndex;
|
int start = c.startIndex;
|
||||||
while (nowcnt < start)
|
while (nowcnt < start)
|
||||||
{
|
{
|
||||||
transformAccessArray.Add(null);
|
transformAccessArray.Add(meshT);
|
||||||
nowcnt++;
|
nowcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < cnt; i++)
|
for (int i = 0; i < cnt; i++)
|
||||||
{
|
{
|
||||||
var t = tdata.transformList[i];
|
Transform t = cmesh.GetTransformFromIndex(i);
|
||||||
|
if (t == null)
|
||||||
|
t = meshT;
|
||||||
int index = c.startIndex + i;
|
int index = c.startIndex + i;
|
||||||
if (index < nowcnt)
|
if (index < nowcnt)
|
||||||
transformAccessArray[index] = t;
|
transformAccessArray[index] = t;
|
||||||
@ -215,7 +267,7 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="count"></param>
|
/// <param name="count"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal DataChunk AddTransform(int count, int teamId)
|
internal DataChunk AddTransform(int count, int teamId, Transform t)
|
||||||
{
|
{
|
||||||
if (isValid == false)
|
if (isValid == false)
|
||||||
return default;
|
return default;
|
||||||
@ -224,30 +276,34 @@ namespace MagicaCloth2
|
|||||||
var c = flagArray.AddRange(count);
|
var c = flagArray.AddRange(count);
|
||||||
initLocalPositionArray.AddRange(count);
|
initLocalPositionArray.AddRange(count);
|
||||||
initLocalRotationArray.AddRange(count);
|
initLocalRotationArray.AddRange(count);
|
||||||
|
baseLocalPositionArray.AddRange(count);
|
||||||
|
baseLocalRotationArray.AddRange(count);
|
||||||
positionArray.AddRange(count);
|
positionArray.AddRange(count);
|
||||||
rotationArray.AddRange(count);
|
rotationArray.AddRange(count);
|
||||||
inverseRotationArray.AddRange(count);
|
//inverseRotationArray.AddRange(count);
|
||||||
scaleArray.AddRange(count);
|
scaleArray.AddRange(count);
|
||||||
localPositionArray.AddRange(count);
|
localPositionArray.AddRange(count);
|
||||||
localRotationArray.AddRange(count);
|
localRotationArray.AddRange(count);
|
||||||
|
localScaleArray.AddRange(count);
|
||||||
|
localToWorldMatrixArray.AddRange(count);
|
||||||
|
|
||||||
// チームID
|
// チームID
|
||||||
teamIdArray.AddRange(count, (short)teamId);
|
teamIdArray.AddRange(count, (short)teamId);
|
||||||
|
|
||||||
// トランスフォームはすべてnullで登録する
|
// トランスフォームはすべてnullで登録する(Unity6.1でnull登録はNGになった!)
|
||||||
int nowcnt = transformAccessArray.length;
|
int nowcnt = transformAccessArray.length;
|
||||||
|
|
||||||
// データチャンクの開始まで埋める
|
// データチャンクの開始まで埋める
|
||||||
int start = c.startIndex;
|
int start = c.startIndex;
|
||||||
while (nowcnt < start)
|
while (nowcnt < start)
|
||||||
{
|
{
|
||||||
transformAccessArray.Add(null);
|
transformAccessArray.Add(t);
|
||||||
nowcnt++;
|
nowcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Transform t = null;
|
//Transform t = null;
|
||||||
int index = c.startIndex + i;
|
int index = c.startIndex + i;
|
||||||
if (index < nowcnt)
|
if (index < nowcnt)
|
||||||
transformAccessArray[index] = t;
|
transformAccessArray[index] = t;
|
||||||
@ -273,12 +329,16 @@ namespace MagicaCloth2
|
|||||||
var c = flagArray.Add(flag);
|
var c = flagArray.Add(flag);
|
||||||
initLocalPositionArray.Add(t.localPosition);
|
initLocalPositionArray.Add(t.localPosition);
|
||||||
initLocalRotationArray.Add(t.localRotation);
|
initLocalRotationArray.Add(t.localRotation);
|
||||||
|
baseLocalPositionArray.Add(t.localPosition);
|
||||||
|
baseLocalRotationArray.Add(t.localRotation);
|
||||||
positionArray.Add(t.position);
|
positionArray.Add(t.position);
|
||||||
rotationArray.Add(t.rotation);
|
rotationArray.Add(t.rotation);
|
||||||
inverseRotationArray.Add(math.inverse(t.rotation));
|
//inverseRotationArray.Add(math.inverse(t.rotation));
|
||||||
scaleArray.Add(t.lossyScale);
|
scaleArray.Add(t.lossyScale);
|
||||||
localPositionArray.Add(t.localPosition);
|
localPositionArray.Add(t.localPosition);
|
||||||
localRotationArray.Add(t.localRotation);
|
localRotationArray.Add(t.localRotation);
|
||||||
|
localScaleArray.Add(t.localScale);
|
||||||
|
localToWorldMatrixArray.Add(float4x4.identity); // ここは単位行列
|
||||||
|
|
||||||
// チームID
|
// チームID
|
||||||
teamIdArray.Add((short)teamId);
|
teamIdArray.Add((short)teamId);
|
||||||
@ -311,12 +371,16 @@ namespace MagicaCloth2
|
|||||||
flagArray[index] = flag;
|
flagArray[index] = flag;
|
||||||
initLocalPositionArray[index] = t.localPosition;
|
initLocalPositionArray[index] = t.localPosition;
|
||||||
initLocalRotationArray[index] = t.localRotation;
|
initLocalRotationArray[index] = t.localRotation;
|
||||||
|
baseLocalPositionArray[index] = t.localPosition;
|
||||||
|
baseLocalRotationArray[index] = t.localRotation;
|
||||||
positionArray[index] = t.position;
|
positionArray[index] = t.position;
|
||||||
rotationArray[index] = t.rotation;
|
rotationArray[index] = t.rotation;
|
||||||
inverseRotationArray[index] = math.inverse(t.rotation);
|
//inverseRotationArray[index] = math.inverse(t.rotation);
|
||||||
scaleArray[index] = t.lossyScale;
|
scaleArray[index] = t.lossyScale;
|
||||||
localPositionArray[index] = t.localPosition;
|
localPositionArray[index] = t.localPosition;
|
||||||
localRotationArray[index] = t.localRotation;
|
localRotationArray[index] = t.localRotation;
|
||||||
|
localScaleArray[index] = t.localScale;
|
||||||
|
//localToWorldMatrix[index] = t.localToWorldMatrix; // ここは不要
|
||||||
teamIdArray[index] = (short)teamId;
|
teamIdArray[index] = (short)teamId;
|
||||||
transformAccessArray[index] = t;
|
transformAccessArray[index] = t;
|
||||||
}
|
}
|
||||||
@ -342,12 +406,16 @@ namespace MagicaCloth2
|
|||||||
flagArray[toIndex] = flagArray[fromIndex];
|
flagArray[toIndex] = flagArray[fromIndex];
|
||||||
initLocalPositionArray[toIndex] = initLocalPositionArray[fromIndex];
|
initLocalPositionArray[toIndex] = initLocalPositionArray[fromIndex];
|
||||||
initLocalRotationArray[toIndex] = initLocalRotationArray[fromIndex];
|
initLocalRotationArray[toIndex] = initLocalRotationArray[fromIndex];
|
||||||
|
baseLocalPositionArray[toIndex] = baseLocalPositionArray[fromIndex];
|
||||||
|
baseLocalRotationArray[toIndex] = baseLocalRotationArray[fromIndex];
|
||||||
positionArray[toIndex] = positionArray[fromIndex];
|
positionArray[toIndex] = positionArray[fromIndex];
|
||||||
rotationArray[toIndex] = rotationArray[fromIndex];
|
rotationArray[toIndex] = rotationArray[fromIndex];
|
||||||
inverseRotationArray[toIndex] = inverseRotationArray[fromIndex];
|
//inverseRotationArray[toIndex] = inverseRotationArray[fromIndex];
|
||||||
scaleArray[toIndex] = scaleArray[fromIndex];
|
scaleArray[toIndex] = scaleArray[fromIndex];
|
||||||
localPositionArray[toIndex] = localPositionArray[fromIndex];
|
localPositionArray[toIndex] = localPositionArray[fromIndex];
|
||||||
localRotationArray[toIndex] = localRotationArray[fromIndex];
|
localRotationArray[toIndex] = localRotationArray[fromIndex];
|
||||||
|
localScaleArray[toIndex] = localScaleArray[fromIndex];
|
||||||
|
//localToWorldMatrix[toIndex] = localToWorldMatrix[fromIndex]; // ここは不要
|
||||||
transformAccessArray[toIndex] = transformAccessArray[fromIndex];
|
transformAccessArray[toIndex] = transformAccessArray[fromIndex];
|
||||||
teamIdArray[toIndex] = teamIdArray[fromIndex];
|
teamIdArray[toIndex] = teamIdArray[fromIndex];
|
||||||
}
|
}
|
||||||
@ -366,12 +434,16 @@ namespace MagicaCloth2
|
|||||||
flagArray.RemoveAndFill(c);
|
flagArray.RemoveAndFill(c);
|
||||||
initLocalPositionArray.Remove(c);
|
initLocalPositionArray.Remove(c);
|
||||||
initLocalRotationArray.Remove(c);
|
initLocalRotationArray.Remove(c);
|
||||||
|
baseLocalPositionArray.Remove(c);
|
||||||
|
baseLocalRotationArray.Remove(c);
|
||||||
positionArray.Remove(c);
|
positionArray.Remove(c);
|
||||||
rotationArray.Remove(c);
|
rotationArray.Remove(c);
|
||||||
inverseRotationArray.Remove(c);
|
//inverseRotationArray.Remove(c);
|
||||||
scaleArray.Remove(c);
|
scaleArray.Remove(c);
|
||||||
localPositionArray.Remove(c);
|
localPositionArray.Remove(c);
|
||||||
localRotationArray.Remove(c);
|
localRotationArray.Remove(c);
|
||||||
|
localScaleArray.Remove(c);
|
||||||
|
localToWorldMatrixArray.Remove(c);
|
||||||
teamIdArray.RemoveAndFill(c, 0);
|
teamIdArray.RemoveAndFill(c, 0);
|
||||||
|
|
||||||
// トランスフォーム削除
|
// トランスフォーム削除
|
||||||
@ -454,12 +526,16 @@ namespace MagicaCloth2
|
|||||||
var nc = flagArray.Expand(c, newLength);
|
var nc = flagArray.Expand(c, newLength);
|
||||||
initLocalPositionArray.Expand(c, newLength);
|
initLocalPositionArray.Expand(c, newLength);
|
||||||
initLocalRotationArray.Expand(c, newLength);
|
initLocalRotationArray.Expand(c, newLength);
|
||||||
|
baseLocalPositionArray.Expand(c, newLength);
|
||||||
|
baseLocalRotationArray.Expand(c, newLength);
|
||||||
positionArray.Expand(c, newLength);
|
positionArray.Expand(c, newLength);
|
||||||
rotationArray.Expand(c, newLength);
|
rotationArray.Expand(c, newLength);
|
||||||
inverseRotationArray.Expand(c, newLength);
|
//inverseRotationArray.Expand(c, newLength);
|
||||||
scaleArray.Expand(c, newLength);
|
scaleArray.Expand(c, newLength);
|
||||||
localPositionArray.Expand(c, newLength);
|
localPositionArray.Expand(c, newLength);
|
||||||
localRotationArray.Expand(c, newLength);
|
localRotationArray.Expand(c, newLength);
|
||||||
|
localScaleArray.Expand(c, newLength);
|
||||||
|
localToWorldMatrixArray.Expand(c, newLength);
|
||||||
|
|
||||||
// チームID
|
// チームID
|
||||||
teamIdArray.Expand(c, newLength);
|
teamIdArray.Expand(c, newLength);
|
||||||
@ -467,8 +543,11 @@ namespace MagicaCloth2
|
|||||||
// トランスフォームアクセス配列の拡張
|
// トランスフォームアクセス配列の拡張
|
||||||
if (c.startIndex != nc.startIndex)
|
if (c.startIndex != nc.startIndex)
|
||||||
{
|
{
|
||||||
|
// 旧領域の先頭Transform
|
||||||
|
Transform frontT = transformAccessArray[c.startIndex];
|
||||||
|
|
||||||
while (transformAccessArray.length < (nc.startIndex + nc.dataLength))
|
while (transformAccessArray.length < (nc.startIndex + nc.dataLength))
|
||||||
transformAccessArray.Add(null);
|
transformAccessArray.Add(frontT);
|
||||||
|
|
||||||
for (int i = 0; i < c.dataLength; i++)
|
for (int i = 0; i < c.dataLength; i++)
|
||||||
{
|
{
|
||||||
@ -490,11 +569,14 @@ namespace MagicaCloth2
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public JobHandle RestoreTransform(JobHandle jobHandle)
|
public JobHandle RestoreTransform(JobHandle jobHandle)
|
||||||
{
|
{
|
||||||
|
existFixedTeam.Value = false;
|
||||||
if (Count > 0)
|
if (Count > 0)
|
||||||
{
|
{
|
||||||
//Debug.Log("RestoreTransform");
|
//Debug.Log("RestoreTransform");
|
||||||
var job = new RestoreTransformJob()
|
var job = new RestoreTransformJob()
|
||||||
{
|
{
|
||||||
|
existFixedTeam = existFixedTeam,
|
||||||
|
|
||||||
flagList = flagArray.GetNativeArray(),
|
flagList = flagArray.GetNativeArray(),
|
||||||
localPositionArray = initLocalPositionArray.GetNativeArray(),
|
localPositionArray = initLocalPositionArray.GetNativeArray(),
|
||||||
localRotationArray = initLocalRotationArray.GetNativeArray(),
|
localRotationArray = initLocalRotationArray.GetNativeArray(),
|
||||||
@ -511,6 +593,9 @@ namespace MagicaCloth2
|
|||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct RestoreTransformJob : IJobParallelForTransform
|
struct RestoreTransformJob : IJobParallelForTransform
|
||||||
{
|
{
|
||||||
|
[NativeDisableParallelForRestriction]
|
||||||
|
public NativeReference<bool> existFixedTeam;
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
public NativeArray<ExBitFlag8> flagList;
|
public NativeArray<ExBitFlag8> flagList;
|
||||||
|
|
||||||
@ -531,19 +616,102 @@ namespace MagicaCloth2
|
|||||||
if (transform.isValid == false)
|
if (transform.isValid == false)
|
||||||
return;
|
return;
|
||||||
var flag = flagList[index];
|
var flag = flagList[index];
|
||||||
if (flag.IsSet(Flag_Enable) == false)
|
|
||||||
return;
|
|
||||||
if (flag.IsSet(Flag_Restore) == false)
|
if (flag.IsSet(Flag_Restore) == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Keepカリング時はスキップする
|
|
||||||
int teamId = teamIdArray[index];
|
int teamId = teamIdArray[index];
|
||||||
var tdata = teamDataArray[teamId];
|
var tdata = teamDataArray[teamId];
|
||||||
if (tdata.IsCullingInvisible && tdata.IsCullingKeep)
|
|
||||||
|
// 一度のみ復元フラグが立っている場合は実行する
|
||||||
|
if (flag.IsSet(Flag_Enable) == false && tdata.flag.IsSet(TeamManager.Flag_RestoreTransformOnlyOnec) == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Keepカリング時はスキップする
|
||||||
|
if ((tdata.IsCameraCullingInvisible && tdata.IsCameraCullingKeep) || tdata.IsDistanceCullingInvisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
transform.localPosition = localPositionArray[index];
|
transform.localPosition = localPositionArray[index];
|
||||||
transform.localRotation = localRotationArray[index];
|
transform.localRotation = localRotationArray[index];
|
||||||
|
|
||||||
|
// 物理更新チームの存在
|
||||||
|
if (tdata.IsFixedUpdate)
|
||||||
|
existFixedTeam.Value = true;
|
||||||
|
|
||||||
|
//Debug.Log($"RestoreTransform [{index}] lpos:{localPositionArray[index]}, lrot:{localRotationArray[index]}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// UnityPhysicsチームかつFixedUpdateが実行されなかったフレームは退避させておいたベース姿勢で再度復元させる
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <param name="jobHandle"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public JobHandle RestoreBaseTransform(JobHandle jobHandle)
|
||||||
|
{
|
||||||
|
if (Count > 0)
|
||||||
|
{
|
||||||
|
//Debug.Log("RestoreTransform");
|
||||||
|
var job = new RestoreBaseTransformJob()
|
||||||
|
{
|
||||||
|
flagList = flagArray.GetNativeArray(),
|
||||||
|
baseLocalPositionArray = baseLocalPositionArray.GetNativeArray(),
|
||||||
|
baseLocalRotationArray = baseLocalRotationArray.GetNativeArray(),
|
||||||
|
teamIdArray = teamIdArray.GetNativeArray(),
|
||||||
|
|
||||||
|
teamDataArray = MagicaManager.Team.teamDataArray.GetNativeArray(),
|
||||||
|
};
|
||||||
|
jobHandle = job.Schedule(transformAccessArray, jobHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BurstCompile]
|
||||||
|
struct RestoreBaseTransformJob : IJobParallelForTransform
|
||||||
|
{
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<ExBitFlag8> flagList;
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<float3> baseLocalPositionArray;
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<quaternion> baseLocalRotationArray;
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<short> teamIdArray;
|
||||||
|
|
||||||
|
// team
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<TeamManager.TeamData> teamDataArray;
|
||||||
|
|
||||||
|
|
||||||
|
public void Execute(int index, TransformAccess transform)
|
||||||
|
{
|
||||||
|
if (transform.isValid == false)
|
||||||
|
return;
|
||||||
|
var flag = flagList[index];
|
||||||
|
if (flag.IsSet(Flag_Restore) == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int teamId = teamIdArray[index];
|
||||||
|
var tdata = teamDataArray[teamId];
|
||||||
|
|
||||||
|
// Fixed更新チームのみ
|
||||||
|
if (tdata.IsFixedUpdate == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 一度のみ復元フラグが立っている場合は実行する
|
||||||
|
if (flag.IsSet(Flag_Enable) == false && tdata.flag.IsSet(TeamManager.Flag_RestoreTransformOnlyOnec) == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Keepカリング時はスキップする
|
||||||
|
if ((tdata.IsCameraCullingInvisible && tdata.IsCameraCullingKeep) || tdata.IsDistanceCullingInvisible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
transform.localPosition = baseLocalPositionArray[index];
|
||||||
|
transform.localRotation = baseLocalRotationArray[index];
|
||||||
|
|
||||||
|
//Debug.Log($"RestoreTransform [{index}] lpos:{baseLocalPositionArray[index]}, lrot:{baseLocalRotationArray[index].value}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,21 +721,25 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="jobHandle"></param>
|
/// <param name="jobHandle"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public JobHandle ReadTransform(JobHandle jobHandle)
|
public JobHandle ReadTransformSchedule(JobHandle jobHandle)
|
||||||
{
|
{
|
||||||
if (Count > 0)
|
if (Count > 0)
|
||||||
{
|
{
|
||||||
// todo:未来予測などがあると色々複雑化するところ
|
|
||||||
|
|
||||||
var job = new ReadTransformJob()
|
var job = new ReadTransformJob()
|
||||||
{
|
{
|
||||||
|
fixedUpdateCount = MagicaManager.Time.FixedUpdateCount,
|
||||||
|
|
||||||
flagList = flagArray.GetNativeArray(),
|
flagList = flagArray.GetNativeArray(),
|
||||||
positionArray = positionArray.GetNativeArray(),
|
positionArray = positionArray.GetNativeArray(),
|
||||||
rotationArray = rotationArray.GetNativeArray(),
|
rotationArray = rotationArray.GetNativeArray(),
|
||||||
scaleList = scaleArray.GetNativeArray(),
|
scaleList = scaleArray.GetNativeArray(),
|
||||||
localPositionArray = localPositionArray.GetNativeArray(),
|
localPositionArray = localPositionArray.GetNativeArray(),
|
||||||
localRotationArray = localRotationArray.GetNativeArray(),
|
localRotationArray = localRotationArray.GetNativeArray(),
|
||||||
inverseRotationArray = inverseRotationArray.GetNativeArray(),
|
localScaleArray = localScaleArray.GetNativeArray(),
|
||||||
|
//inverseRotationArray = inverseRotationArray.GetNativeArray(),
|
||||||
|
localToWorldMatrixArray = localToWorldMatrixArray.GetNativeArray(),
|
||||||
|
baseLocalPositionArray = baseLocalPositionArray.GetNativeArray(),
|
||||||
|
baseLocalRotationArray = baseLocalRotationArray.GetNativeArray(),
|
||||||
|
|
||||||
teamIdArray = teamIdArray.GetNativeArray(),
|
teamIdArray = teamIdArray.GetNativeArray(),
|
||||||
|
|
||||||
@ -582,6 +754,8 @@ namespace MagicaCloth2
|
|||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct ReadTransformJob : IJobParallelForTransform
|
struct ReadTransformJob : IJobParallelForTransform
|
||||||
{
|
{
|
||||||
|
public int fixedUpdateCount;
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
public NativeArray<ExBitFlag8> flagList;
|
public NativeArray<ExBitFlag8> flagList;
|
||||||
|
|
||||||
@ -596,7 +770,15 @@ namespace MagicaCloth2
|
|||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<quaternion> localRotationArray;
|
public NativeArray<quaternion> localRotationArray;
|
||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<quaternion> inverseRotationArray;
|
public NativeArray<float3> localScaleArray;
|
||||||
|
//[Unity.Collections.WriteOnly]
|
||||||
|
//public NativeArray<quaternion> inverseRotationArray;
|
||||||
|
[Unity.Collections.WriteOnly]
|
||||||
|
public NativeArray<float4x4> localToWorldMatrixArray;
|
||||||
|
[Unity.Collections.WriteOnly]
|
||||||
|
public NativeArray<float3> baseLocalPositionArray;
|
||||||
|
[Unity.Collections.WriteOnly]
|
||||||
|
public NativeArray<quaternion> baseLocalRotationArray;
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
public NativeArray<short> teamIdArray;
|
public NativeArray<short> teamIdArray;
|
||||||
@ -615,7 +797,7 @@ namespace MagicaCloth2
|
|||||||
if (flag.IsSet(Flag_Read) == false)
|
if (flag.IsSet(Flag_Read) == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// カリング時は書き込まない
|
// カリング時は読み込まない
|
||||||
int teamId = teamIdArray[index];
|
int teamId = teamIdArray[index];
|
||||||
var tdata = teamDataArray[teamId];
|
var tdata = teamDataArray[teamId];
|
||||||
if (tdata.IsCullingInvisible)
|
if (tdata.IsCullingInvisible)
|
||||||
@ -629,6 +811,7 @@ namespace MagicaCloth2
|
|||||||
rotationArray[index] = rot;
|
rotationArray[index] = rot;
|
||||||
localPositionArray[index] = transform.localPosition;
|
localPositionArray[index] = transform.localPosition;
|
||||||
localRotationArray[index] = transform.localRotation;
|
localRotationArray[index] = transform.localRotation;
|
||||||
|
localScaleArray[index] = transform.localScale;
|
||||||
|
|
||||||
// マトリックスから正確なスケール値を算出する(これはTransform.lossyScaleと等価)
|
// マトリックスから正確なスケール値を算出する(これはTransform.lossyScaleと等価)
|
||||||
var irot = math.inverse(rot);
|
var irot = math.inverse(rot);
|
||||||
@ -636,8 +819,24 @@ namespace MagicaCloth2
|
|||||||
var scl = new float3(m2.c0.x, m2.c1.y, m2.c2.z);
|
var scl = new float3(m2.c0.x, m2.c1.y, m2.c2.z);
|
||||||
scaleList[index] = scl;
|
scaleList[index] = scl;
|
||||||
|
|
||||||
|
//Debug.Log($"ReadTransform [{index}] pos:{pos}, rot:{rot}, scl:{scl}");
|
||||||
|
//Debug.Log($"LtoW:\n{LtoW}");
|
||||||
|
|
||||||
// ワールド->ローカル変換用の逆クォータニオン
|
// ワールド->ローカル変換用の逆クォータニオン
|
||||||
inverseRotationArray[index] = math.inverse(rot);
|
//inverseRotationArray[index] = math.inverse(rot);
|
||||||
|
|
||||||
|
// ワールド変換マトリックス
|
||||||
|
localToWorldMatrixArray[index] = LtoW;
|
||||||
|
|
||||||
|
// 今回の姿勢を基本姿勢として退避させる
|
||||||
|
// Fixed更新チームかつFixedUpdateが実行されている場合、そもそもFixed更新出ない場合は毎回
|
||||||
|
if ((tdata.IsFixedUpdate && fixedUpdateCount > 0) || tdata.IsFixedUpdate == false)
|
||||||
|
{
|
||||||
|
baseLocalPositionArray[index] = transform.localPosition;
|
||||||
|
baseLocalRotationArray[index] = transform.localRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Debug.Log($"ReadTransform [{index}] pos:{pos}, rot:{rot}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +847,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="count"></param>
|
/// <param name="count"></param>
|
||||||
/// <param name="jobHandle"></param>
|
/// <param name="jobHandle"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public JobHandle WriteTransform(JobHandle jobHandle)
|
public JobHandle WriteTransformSchedule(JobHandle jobHandle)
|
||||||
{
|
{
|
||||||
var job = new WriteTransformJob()
|
var job = new WriteTransformJob()
|
||||||
{
|
{
|
||||||
@ -700,6 +899,7 @@ namespace MagicaCloth2
|
|||||||
// カリング時は書き込まない
|
// カリング時は書き込まない
|
||||||
int teamId = teamIdArray[index];
|
int teamId = teamIdArray[index];
|
||||||
var tdata = teamDataArray[teamId];
|
var tdata = teamDataArray[teamId];
|
||||||
|
//if (tdata.IsCameraCullingInvisible)
|
||||||
if (tdata.IsCullingInvisible)
|
if (tdata.IsCullingInvisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -711,20 +911,101 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
// ワールド回転
|
// ワールド回転
|
||||||
transform.rotation = worldRotations[index];
|
transform.rotation = worldRotations[index];
|
||||||
|
//Debug.Log($"WriteTransform [{index}] (World!) rot:{worldRotations[index]}");
|
||||||
|
|
||||||
// BoneSpringのみワールド座標を書き込む
|
// BoneSpringのみワールド座標を書き込む
|
||||||
if (tdata.IsSpring)
|
if (tdata.IsSpring)
|
||||||
|
{
|
||||||
transform.position = worldPositions[index];
|
transform.position = worldPositions[index];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (flag.IsSet(Flag_LocalPosRotWrite))
|
else if (flag.IsSet(Flag_LocalPosRotWrite))
|
||||||
{
|
{
|
||||||
// ローカル座標・回転を書き込む
|
// ローカル座標・回転を書き込む
|
||||||
transform.localPosition = localPositions[index];
|
transform.localPosition = localPositions[index];
|
||||||
transform.localRotation = localRotations[index];
|
transform.localRotation = localRotations[index];
|
||||||
|
|
||||||
|
//Debug.Log($"WriteTransform [{index}] (local!) lpos:{localPositions[index]}, lrot:{localRotations[index]}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// コンポーネント用トランスフォームの登録
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal int AddComponentTransform(Transform t)
|
||||||
|
{
|
||||||
|
if (isValid == false)
|
||||||
|
return -1;
|
||||||
|
Debug.Assert(t);
|
||||||
|
|
||||||
|
int index = componentPositionArray.Add(float3.zero).startIndex;
|
||||||
|
|
||||||
|
// トランスフォーム
|
||||||
|
int nowcnt = componentTransformAccessArray.length;
|
||||||
|
if (index < nowcnt)
|
||||||
|
componentTransformAccessArray[index] = t;
|
||||||
|
else
|
||||||
|
componentTransformAccessArray.Add(t);
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// コンポーネント用トランスフォームの削除
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
internal void RemoveComponentTransform(int index)
|
||||||
|
{
|
||||||
|
if (isValid == false)
|
||||||
|
return;
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
componentPositionArray.Remove(index);
|
||||||
|
|
||||||
|
// トランスフォーム削除
|
||||||
|
componentTransformAccessArray[index] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// トランスフォームを読み込むジョブを発行する
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="jobHandle"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal JobHandle ReadComponentTransform(JobHandle jobHandle)
|
||||||
|
{
|
||||||
|
if (componentPositionArray.Count > 0)
|
||||||
|
{
|
||||||
|
var job = new ReadComponentTransformJob()
|
||||||
|
{
|
||||||
|
positionArray = componentPositionArray.GetNativeArray(),
|
||||||
|
};
|
||||||
|
jobHandle = job.ScheduleReadOnly(componentTransformAccessArray, 16, jobHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BurstCompile]
|
||||||
|
struct ReadComponentTransformJob : IJobParallelForTransform
|
||||||
|
{
|
||||||
|
[Unity.Collections.WriteOnly]
|
||||||
|
public NativeArray<float3> positionArray;
|
||||||
|
|
||||||
|
public void Execute(int index, TransformAccess transform)
|
||||||
|
{
|
||||||
|
if (transform.isValid == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
positionArray[index] = transform.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public void InformationLog(StringBuilder allsb)
|
public void InformationLog(StringBuilder allsb)
|
||||||
{
|
{
|
||||||
@ -741,12 +1022,16 @@ namespace MagicaCloth2
|
|||||||
sb.AppendLine($" -flagArray:{flagArray.ToSummary()}");
|
sb.AppendLine($" -flagArray:{flagArray.ToSummary()}");
|
||||||
sb.AppendLine($" -initLocalPositionArray:{initLocalPositionArray.ToSummary()}");
|
sb.AppendLine($" -initLocalPositionArray:{initLocalPositionArray.ToSummary()}");
|
||||||
sb.AppendLine($" -initLocalRotationArray:{initLocalRotationArray.ToSummary()}");
|
sb.AppendLine($" -initLocalRotationArray:{initLocalRotationArray.ToSummary()}");
|
||||||
|
sb.AppendLine($" -baseLocalPositionArray:{baseLocalPositionArray.ToSummary()}");
|
||||||
|
sb.AppendLine($" -baseLocalRotationArray:{baseLocalRotationArray.ToSummary()}");
|
||||||
sb.AppendLine($" -positionArray:{positionArray.ToSummary()}");
|
sb.AppendLine($" -positionArray:{positionArray.ToSummary()}");
|
||||||
sb.AppendLine($" -rotationArray:{rotationArray.ToSummary()}");
|
sb.AppendLine($" -rotationArray:{rotationArray.ToSummary()}");
|
||||||
sb.AppendLine($" -inverseRotationArray:{inverseRotationArray.ToSummary()}");
|
//sb.AppendLine($" -inverseRotationArray:{inverseRotationArray.ToSummary()}");
|
||||||
sb.AppendLine($" -scaleArray:{scaleArray.ToSummary()}");
|
sb.AppendLine($" -scaleArray:{scaleArray.ToSummary()}");
|
||||||
sb.AppendLine($" -localPositionArray:{localPositionArray.ToSummary()}");
|
sb.AppendLine($" -localPositionArray:{localPositionArray.ToSummary()}");
|
||||||
sb.AppendLine($" -localRotationArray:{localRotationArray.ToSummary()}");
|
sb.AppendLine($" -localRotationArray:{localRotationArray.ToSummary()}");
|
||||||
|
sb.AppendLine($" -localScaleArray:{localScaleArray.ToSummary()}");
|
||||||
|
sb.AppendLine($" -localToWorldMatirxArray:{localToWorldMatrixArray.ToSummary()}");
|
||||||
sb.AppendLine($" -teamIdArray:{teamIdArray.ToSummary()}");
|
sb.AppendLine($" -teamIdArray:{teamIdArray.ToSummary()}");
|
||||||
|
|
||||||
if (transformAccessArray.isCreated)
|
if (transformAccessArray.isCreated)
|
||||||
|
|||||||
@ -22,12 +22,15 @@ namespace MagicaCloth2
|
|||||||
public Matrix4x4 worldToLocalMatrix;
|
public Matrix4x4 worldToLocalMatrix;
|
||||||
public int pid;
|
public int pid;
|
||||||
|
|
||||||
public TransformRecord(Transform t)
|
public TransformRecord(Transform t, bool read)
|
||||||
{
|
{
|
||||||
if (t)
|
if (t)
|
||||||
{
|
{
|
||||||
transform = t;
|
transform = t;
|
||||||
id = t.GetInstanceID();
|
id = t.GetInstanceID();
|
||||||
|
|
||||||
|
if (read)
|
||||||
|
{
|
||||||
localPosition = t.localPosition;
|
localPosition = t.localPosition;
|
||||||
localRotation = t.localRotation;
|
localRotation = t.localRotation;
|
||||||
position = t.position;
|
position = t.position;
|
||||||
@ -35,6 +38,7 @@ namespace MagicaCloth2
|
|||||||
scale = t.lossyScale;
|
scale = t.lossyScale;
|
||||||
localToWorldMatrix = t.localToWorldMatrix;
|
localToWorldMatrix = t.localToWorldMatrix;
|
||||||
worldToLocalMatrix = t.worldToLocalMatrix;
|
worldToLocalMatrix = t.worldToLocalMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
if (t.parent)
|
if (t.parent)
|
||||||
pid = t.parent.GetInstanceID();
|
pid = t.parent.GetInstanceID();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,8 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
GridMap<int> gridMap;
|
GridMap<int> gridMap;
|
||||||
NativeParallelHashSet<int2> joinPairSet;
|
//NativeParallelHashSet<int2> joinPairSet;
|
||||||
|
NativeParallelMultiHashMap<ushort, ushort> joinPairMap;
|
||||||
NativeReference<int> resultRef;
|
NativeReference<int> resultRef;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
@ -48,8 +49,10 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
if (joinPairSet.IsCreated)
|
//if (joinPairSet.IsCreated)
|
||||||
joinPairSet.Dispose();
|
// joinPairSet.Dispose();
|
||||||
|
if (joinPairMap.IsCreated)
|
||||||
|
joinPairMap.Dispose();
|
||||||
if (resultRef.IsCreated)
|
if (resultRef.IsCreated)
|
||||||
resultRef.Dispose();
|
resultRef.Dispose();
|
||||||
gridMap?.Dispose();
|
gridMap?.Dispose();
|
||||||
@ -77,7 +80,8 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 頂点ごとの接続マップ
|
// 頂点ごとの接続マップ
|
||||||
// インデックスが若い方が記録する
|
// インデックスが若い方が記録する
|
||||||
joinPairSet = new NativeParallelHashSet<int2>(vmesh.VertexCount / 4, Allocator.Persistent);
|
//joinPairSet = new NativeParallelHashSet<int2>(vmesh.VertexCount / 4, Allocator.Persistent);
|
||||||
|
joinPairMap = new NativeParallelMultiHashMap<ushort, ushort>(vmesh.VertexCount, Allocator.Persistent);
|
||||||
resultRef = new NativeReference<int>(Allocator.Persistent);
|
resultRef = new NativeReference<int>(Allocator.Persistent);
|
||||||
|
|
||||||
// ポイントをグリッドに登録
|
// ポイントをグリッドに登録
|
||||||
@ -100,14 +104,18 @@ namespace MagicaCloth2
|
|||||||
localPositions = vmesh.localPositions.GetNativeArray(),
|
localPositions = vmesh.localPositions.GetNativeArray(),
|
||||||
joinIndices = workData.vertexJoinIndices,
|
joinIndices = workData.vertexJoinIndices,
|
||||||
gridMap = gridMap.GetMultiHashMap(),
|
gridMap = gridMap.GetMultiHashMap(),
|
||||||
joinPairSet = joinPairSet,
|
//joinPairSet = joinPairSet,
|
||||||
|
joinPairMap = joinPairMap,
|
||||||
};
|
};
|
||||||
searchJoinJob.Run();
|
searchJoinJob.Run();
|
||||||
|
|
||||||
// 結合する
|
// 結合する
|
||||||
|
#if false
|
||||||
var joinJob = new JoinJob()
|
var joinJob = new JoinJob()
|
||||||
{
|
{
|
||||||
joinPairSet = joinPairSet,
|
vertexCount = vmesh.VertexCount,
|
||||||
|
//joinPairSet = joinPairSet,
|
||||||
|
joinPairMap = joinPairMap,
|
||||||
joinIndices = workData.vertexJoinIndices,
|
joinIndices = workData.vertexJoinIndices,
|
||||||
vertexToVertexMap = workData.vertexToVertexMap,
|
vertexToVertexMap = workData.vertexToVertexMap,
|
||||||
boneWeights = vmesh.boneWeights.GetNativeArray(),
|
boneWeights = vmesh.boneWeights.GetNativeArray(),
|
||||||
@ -115,6 +123,25 @@ namespace MagicaCloth2
|
|||||||
result = resultRef,
|
result = resultRef,
|
||||||
};
|
};
|
||||||
joinJob.Run();
|
joinJob.Run();
|
||||||
|
#endif
|
||||||
|
#if true
|
||||||
|
// 高速化および詳細メッシュがある場合に1つの頂点に大量に結合しオーバーフローが発生する問題を回避したもの
|
||||||
|
// 以前はA->B->C結合時にA->C間が接続距離以上でもA->Cが結合されてしまったが、この改良版ではそれがおこならない
|
||||||
|
// そのため以前とは結果がことなることに注意!
|
||||||
|
using var tempList = new NativeList<ushort>(2048, Allocator.Persistent);
|
||||||
|
var joinJob2 = new JoinJob2()
|
||||||
|
{
|
||||||
|
vertexCount = vmesh.VertexCount,
|
||||||
|
joinPairMap = joinPairMap,
|
||||||
|
joinIndices = workData.vertexJoinIndices,
|
||||||
|
vertexToVertexMap = workData.vertexToVertexMap,
|
||||||
|
boneWeights = vmesh.boneWeights.GetNativeArray(),
|
||||||
|
attributes = vmesh.attributes.GetNativeArray(),
|
||||||
|
result = resultRef,
|
||||||
|
tempList = tempList,
|
||||||
|
};
|
||||||
|
joinJob2.Run();
|
||||||
|
#endif
|
||||||
|
|
||||||
// 頂点の接続状態を最新に更新する。すべて最新の生存ポイントを指すように変更する
|
// 頂点の接続状態を最新に更新する。すべて最新の生存ポイントを指すように変更する
|
||||||
UpdateJoinAndLink();
|
UpdateJoinAndLink();
|
||||||
@ -191,7 +218,8 @@ namespace MagicaCloth2
|
|||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
public NativeParallelMultiHashMap<int3, int> gridMap;
|
public NativeParallelMultiHashMap<int3, int> gridMap;
|
||||||
|
|
||||||
public NativeParallelHashSet<int2> joinPairSet;
|
//public NativeParallelHashSet<int2> joinPairSet;
|
||||||
|
public NativeParallelMultiHashMap<ushort, ushort> joinPairMap;
|
||||||
|
|
||||||
public void Execute()
|
public void Execute()
|
||||||
{
|
{
|
||||||
@ -222,14 +250,91 @@ namespace MagicaCloth2
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 結合登録
|
// 結合登録
|
||||||
int2 ehash = DataUtility.PackInt2(vindex, tvindex);
|
//int2 ehash = DataUtility.PackInt2(vindex, tvindex);
|
||||||
joinPairSet.Add(ehash);
|
//joinPairSet.Add(ehash);
|
||||||
|
joinPairMap.Add((ushort)vindex, (ushort)tvindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BurstCompile]
|
||||||
|
struct JoinJob2 : IJob
|
||||||
|
{
|
||||||
|
public int vertexCount;
|
||||||
|
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeParallelMultiHashMap<ushort, ushort> joinPairMap;
|
||||||
|
|
||||||
|
public NativeArray<int> joinIndices;
|
||||||
|
public NativeParallelMultiHashMap<ushort, ushort> vertexToVertexMap;
|
||||||
|
public NativeArray<VirtualMeshBoneWeight> boneWeights;
|
||||||
|
public NativeArray<VertexAttribute> attributes;
|
||||||
|
public NativeReference<int> result;
|
||||||
|
|
||||||
|
public NativeList<ushort> tempList;
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
for (ushort vindexLive = 0; vindexLive < vertexCount; vindexLive++)
|
||||||
|
{
|
||||||
|
// すでに結合済みならスキップ
|
||||||
|
if (joinIndices[vindexLive] >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 対象ループ
|
||||||
|
foreach (ushort vindexDead in joinPairMap.GetValuesForKey(vindexLive))
|
||||||
|
{
|
||||||
|
// 対象がすでに結合ずみならスキップ
|
||||||
|
if (joinIndices[vindexDead] >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 結合(vertexDead -> vertexLive)
|
||||||
|
joinIndices[vindexDead] = vindexLive;
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
vertexToVertexMap.MC2RemoveValue(vindexLive, vindexDead);
|
||||||
|
|
||||||
|
tempList.Clear();
|
||||||
|
foreach (ushort i in vertexToVertexMap.GetValuesForKey(vindexDead))
|
||||||
|
{
|
||||||
|
tempList.Add(i);
|
||||||
|
}
|
||||||
|
foreach (ushort i in tempList)
|
||||||
|
{
|
||||||
|
if (joinIndices[i] >= 0)
|
||||||
|
continue;
|
||||||
|
if (i == vindexLive || i == vindexDead)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vertexToVertexMap.MC2RemoveValue(i, vindexDead);
|
||||||
|
|
||||||
|
vertexToVertexMap.MC2UniqueAdd(vindexLive, i);
|
||||||
|
vertexToVertexMap.MC2UniqueAdd(i, vindexLive);
|
||||||
|
|
||||||
|
// p2にBoneWeightを結合
|
||||||
|
var bw = boneWeights[vindexLive];
|
||||||
|
bw.AddWeight(boneWeights[vindexDead]);
|
||||||
|
boneWeights[vindexLive] = bw;
|
||||||
|
|
||||||
|
// 属性
|
||||||
|
var attr1 = attributes[vindexDead];
|
||||||
|
var attr2 = attributes[vindexLive];
|
||||||
|
attributes[vindexLive] = VertexAttribute.JoinAttribute(attr1, attr2);
|
||||||
|
attributes[vindexDead] = VertexAttribute.Invalid; // 削除頂点は無効にする
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 削除頂点数記録
|
||||||
|
result.Value = cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if false // old
|
||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct JoinJob : IJob
|
struct JoinJob : IJob
|
||||||
{
|
{
|
||||||
@ -245,32 +350,31 @@ namespace MagicaCloth2
|
|||||||
public void Execute()
|
public void Execute()
|
||||||
{
|
{
|
||||||
var workSet = new FixedList512Bytes<ushort>();
|
var workSet = new FixedList512Bytes<ushort>();
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
foreach (var ehash in joinPairSet)
|
foreach (var ehash in joinPairSet)
|
||||||
{
|
{
|
||||||
int vindex2 = ehash[0]; // 生存側
|
int vindexLive = ehash[0]; // 生存側
|
||||||
int vindex1 = ehash[1]; // 削除側
|
int vindexDead = ehash[1]; // 削除側
|
||||||
|
|
||||||
// 両方とも生存インデックスに変換する
|
while (joinIndices[vindexDead] >= 0)
|
||||||
while (joinIndices[vindex1] >= 0)
|
|
||||||
{
|
{
|
||||||
vindex1 = joinIndices[vindex1];
|
vindexDead = joinIndices[vindexDead];
|
||||||
}
|
}
|
||||||
while (joinIndices[vindex2] >= 0)
|
while (joinIndices[vindexLive] >= 0)
|
||||||
{
|
{
|
||||||
vindex2 = joinIndices[vindex2];
|
vindexLive = joinIndices[vindexLive];
|
||||||
}
|
}
|
||||||
if (vindex1 == vindex2)
|
if (vindexDead == vindexLive)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 結合(vertex1 -> vertex2)
|
// 結合(vertex1 -> vertex2)
|
||||||
joinIndices[vindex1] = vindex2;
|
joinIndices[vindexDead] = vindexLive;
|
||||||
cnt++;
|
cnt++;
|
||||||
|
|
||||||
// 接続数を結合する(重複は弾かれる)
|
// 接続数を結合する(重複は弾かれる)
|
||||||
workSet.Clear();
|
workSet.Clear();
|
||||||
foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindex1))
|
foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindexDead))
|
||||||
{
|
{
|
||||||
int index = i;
|
int index = i;
|
||||||
// 生存インデックス
|
// 生存インデックス
|
||||||
@ -278,10 +382,10 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
index = joinIndices[index];
|
index = joinIndices[index];
|
||||||
}
|
}
|
||||||
if (index != vindex1 && index != vindex2)
|
if (index != vindexDead && index != vindexLive)
|
||||||
workSet.Set((ushort)index);
|
workSet.MC2Set((ushort)index);
|
||||||
}
|
}
|
||||||
foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindex2))
|
foreach (ushort i in vertexToVertexMap.GetValuesForKey((ushort)vindexLive))
|
||||||
{
|
{
|
||||||
int index = i;
|
int index = i;
|
||||||
// 生存インデックス
|
// 生存インデックス
|
||||||
@ -289,32 +393,33 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
index = joinIndices[index];
|
index = joinIndices[index];
|
||||||
}
|
}
|
||||||
if (index != vindex1 && index != vindex2)
|
if (index != vindexDead && index != vindexLive)
|
||||||
workSet.Set((ushort)index);
|
workSet.MC2Set((ushort)index);
|
||||||
}
|
}
|
||||||
vertexToVertexMap.Remove((ushort)vindex2);
|
vertexToVertexMap.Remove((ushort)vindexLive);
|
||||||
for (int i = 0; i < workSet.Length; i++)
|
for (int i = 0; i < workSet.Length; i++)
|
||||||
{
|
{
|
||||||
vertexToVertexMap.Add((ushort)vindex2, workSet[i]);
|
vertexToVertexMap.Add((ushort)vindexLive, workSet[i]);
|
||||||
}
|
}
|
||||||
//Debug.Assert(workSet.Length > 0);
|
//Debug.Assert(workSet.Length > 0);
|
||||||
|
|
||||||
// p2にBoneWeightを結合
|
// p2にBoneWeightを結合
|
||||||
var bw = boneWeights[vindex2];
|
var bw = boneWeights[vindexLive];
|
||||||
bw.AddWeight(boneWeights[vindex1]);
|
bw.AddWeight(boneWeights[vindexDead]);
|
||||||
boneWeights[vindex2] = bw;
|
boneWeights[vindexLive] = bw;
|
||||||
|
|
||||||
// 属性
|
// 属性
|
||||||
var attr1 = attributes[vindex1];
|
var attr1 = attributes[vindexDead];
|
||||||
var attr2 = attributes[vindex2];
|
var attr2 = attributes[vindexLive];
|
||||||
attributes[vindex2] = VertexAttribute.JoinAttribute(attr1, attr2);
|
attributes[vindexLive] = VertexAttribute.JoinAttribute(attr1, attr2);
|
||||||
attributes[vindex1] = VertexAttribute.Invalid; // 削除頂点は無効にする
|
attributes[vindexDead] = VertexAttribute.Invalid; // 削除頂点は無効にする
|
||||||
}
|
}
|
||||||
|
|
||||||
// 削除頂点数記録
|
// 削除頂点数記録
|
||||||
result.Value = cnt;
|
result.Value = cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -395,7 +500,7 @@ namespace MagicaCloth2
|
|||||||
if (tvindex == vindex)
|
if (tvindex == vindex)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
newLinkSet.Set((ushort)tvindex);
|
newLinkSet.MC2Set((ushort)tvindex);
|
||||||
}
|
}
|
||||||
// 生存のみの新しいセットに入れ替え
|
// 生存のみの新しいセットに入れ替え
|
||||||
vertexToVertexMap.Remove((ushort)vindex);
|
vertexToVertexMap.Remove((ushort)vindex);
|
||||||
|
|||||||
@ -450,12 +450,12 @@ namespace MagicaCloth2
|
|||||||
foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)vindex1))
|
foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)vindex1))
|
||||||
{
|
{
|
||||||
if (nindex != vindex1 && nindex != vindex2)
|
if (nindex != vindex1 && nindex != vindex2)
|
||||||
newLink.Set(nindex);
|
newLink.MC2Set(nindex);
|
||||||
}
|
}
|
||||||
foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)vindex2))
|
foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)vindex2))
|
||||||
{
|
{
|
||||||
if (nindex != vindex1 && nindex != vindex2)
|
if (nindex != vindex1 && nindex != vindex2)
|
||||||
newLink.Set(nindex);
|
newLink.MC2Set(nindex);
|
||||||
}
|
}
|
||||||
vertexToVertexMap.Remove((ushort)vindex2);
|
vertexToVertexMap.Remove((ushort)vindex2);
|
||||||
for (int i = 0; i < newLink.Length; i++)
|
for (int i = 0; i < newLink.Length; i++)
|
||||||
@ -558,7 +558,7 @@ namespace MagicaCloth2
|
|||||||
if (tvindex == vindex)
|
if (tvindex == vindex)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
newLinkSet.Set((ushort)tvindex);
|
newLinkSet.MC2Set((ushort)tvindex);
|
||||||
}
|
}
|
||||||
// 生存のみの新しいセットに入れ替え
|
// 生存のみの新しいセットに入れ替え
|
||||||
vertexToVertexMap.Remove((ushort)vindex);
|
vertexToVertexMap.Remove((ushort)vindex);
|
||||||
@ -640,12 +640,12 @@ namespace MagicaCloth2
|
|||||||
foreach (ushort index in vertexToVertexMap.GetValuesForKey((ushort)vindex))
|
foreach (ushort index in vertexToVertexMap.GetValuesForKey((ushort)vindex))
|
||||||
{
|
{
|
||||||
if (index != vindex && index != tvindex)
|
if (index != vindex && index != tvindex)
|
||||||
joinVlink.Set(index);
|
joinVlink.MC2Set(index);
|
||||||
}
|
}
|
||||||
foreach (ushort index in vertexToVertexMap.GetValuesForKey((ushort)tvindex))
|
foreach (ushort index in vertexToVertexMap.GetValuesForKey((ushort)tvindex))
|
||||||
{
|
{
|
||||||
if (index != vindex && index != tvindex)
|
if (index != vindex && index != tvindex)
|
||||||
joinVlink.Set(index);
|
joinVlink.MC2Set(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点になるのはNG
|
// 点になるのはNG
|
||||||
@ -662,20 +662,20 @@ namespace MagicaCloth2
|
|||||||
// 結合後のトライアングルの外周をひと筆書きし、すべての外周頂点が使われているならOK!
|
// 結合後のトライアングルの外周をひと筆書きし、すべての外周頂点が使われているならOK!
|
||||||
// 外周頂点が一筆書きできない場合は2つ以上のグループに分かれいる(X型になる)
|
// 外周頂点が一筆書きできない場合は2つ以上のグループに分かれいる(X型になる)
|
||||||
var stack = new FixedList512Bytes<ushort>();
|
var stack = new FixedList512Bytes<ushort>();
|
||||||
stack.Push(joinVlink[0]);
|
stack.MC2Push(joinVlink[0]);
|
||||||
while (stack.Length > 0)
|
while (stack.Length > 0)
|
||||||
{
|
{
|
||||||
ushort index = stack.Pop();
|
ushort index = stack.MC2Pop();
|
||||||
if (joinVlink.Contains(index) == false)
|
if (joinVlink.Contains(index) == false)
|
||||||
continue;
|
continue;
|
||||||
joinVlink.RemoveItemAtSwapBack(index);
|
joinVlink.MC2RemoveItemAtSwapBack(index);
|
||||||
|
|
||||||
foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)index))
|
foreach (ushort nindex in vertexToVertexMap.GetValuesForKey((ushort)index))
|
||||||
{
|
{
|
||||||
if (joinVlink.Contains(nindex))
|
if (joinVlink.Contains(nindex))
|
||||||
{
|
{
|
||||||
// next
|
// next
|
||||||
stack.Push(nindex);
|
stack.MC2Push(nindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -716,13 +716,13 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
int index = vlist[i];
|
int index = vlist[i];
|
||||||
if (index != vindex && index != tvindex)
|
if (index != vindex && index != tvindex)
|
||||||
joinVlink.SetLimit((ushort)index);
|
joinVlink.MC2SetLimit((ushort)index);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < tvlist.Length; i++)
|
for (int i = 0; i < tvlist.Length; i++)
|
||||||
{
|
{
|
||||||
int index = tvlist[i];
|
int index = tvlist[i];
|
||||||
if (index != vindex && index != tvindex)
|
if (index != vindex && index != tvindex)
|
||||||
joinVlink.SetLimit((ushort)index);
|
joinVlink.MC2SetLimit((ushort)index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点になるのはNG
|
// 点になるのはNG
|
||||||
@ -739,13 +739,13 @@ namespace MagicaCloth2
|
|||||||
// 結合後のトライアングルの外周をひと筆書きし、すべての外周頂点が使われているならOK!
|
// 結合後のトライアングルの外周をひと筆書きし、すべての外周頂点が使われているならOK!
|
||||||
// 外周頂点が一筆書きできない場合は2つ以上のグループに分かれいる(X型になる)
|
// 外周頂点が一筆書きできない場合は2つ以上のグループに分かれいる(X型になる)
|
||||||
var stack = new FixedList512Bytes<ushort>();
|
var stack = new FixedList512Bytes<ushort>();
|
||||||
stack.Push(joinVlink[0]);
|
stack.MC2Push(joinVlink[0]);
|
||||||
while (stack.Length > 0)
|
while (stack.Length > 0)
|
||||||
{
|
{
|
||||||
ushort index = stack.Pop();
|
ushort index = stack.MC2Pop();
|
||||||
if (joinVlink.Contains(index) == false)
|
if (joinVlink.Contains(index) == false)
|
||||||
continue;
|
continue;
|
||||||
joinVlink.RemoveItemAtSwapBack(index);
|
joinVlink.MC2RemoveItemAtSwapBack(index);
|
||||||
|
|
||||||
var link = vertexToVertexArray[index];
|
var link = vertexToVertexArray[index];
|
||||||
for (int i = 0; i < link.Length; i++)
|
for (int i = 0; i < link.Length; i++)
|
||||||
@ -754,7 +754,7 @@ namespace MagicaCloth2
|
|||||||
if (joinVlink.Contains(nindex))
|
if (joinVlink.Contains(nindex))
|
||||||
{
|
{
|
||||||
// next
|
// next
|
||||||
stack.Push(nindex);
|
stack.MC2Push(nindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,9 +35,7 @@ namespace MagicaCloth2
|
|||||||
public DebugAxis animatedAxis = DebugAxis.None;
|
public DebugAxis animatedAxis = DebugAxis.None;
|
||||||
public bool animatedShape = false;
|
public bool animatedShape = false;
|
||||||
public bool inertiaCenter = true;
|
public bool inertiaCenter = true;
|
||||||
//public bool basicPosition = false;
|
public bool customSkinningBone = true;
|
||||||
//public DebugAxis basicAxis = DebugAxis.None;
|
|
||||||
//public bool basicShape = false;
|
|
||||||
|
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
// ■デバッグ用
|
// ■デバッグ用
|
||||||
@ -60,6 +58,7 @@ namespace MagicaCloth2
|
|||||||
//public bool horizontalDistanceConstraint = false;
|
//public bool horizontalDistanceConstraint = false;
|
||||||
public bool collisionNormal = false;
|
public bool collisionNormal = false;
|
||||||
public bool cellCube = false;
|
public bool cellCube = false;
|
||||||
|
public bool baseLinePos = false;
|
||||||
public int vertexMinIndex = 0;
|
public int vertexMinIndex = 0;
|
||||||
public int vertexMaxIndex = 100000;
|
public int vertexMaxIndex = 100000;
|
||||||
public int triangleMinIndex = 0;
|
public int triangleMinIndex = 0;
|
||||||
@ -103,16 +102,11 @@ namespace MagicaCloth2
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetLineSize()
|
public float GetLineSize() => 0.05f; // 固定
|
||||||
{
|
|
||||||
//return 0.03f; // 固定
|
|
||||||
return 0.05f; // 固定
|
|
||||||
}
|
|
||||||
|
|
||||||
public float GetInertiaCenterRadius()
|
public float GetInertiaCenterRadius() => 0.01f; // 固定
|
||||||
{
|
|
||||||
return 0.01f; // 固定
|
public float GetCustomSkinningRadius() => 0.02f; // 固定
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsReferOldPos()
|
public bool IsReferOldPos()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// Magica Cloth 2.
|
// Magica Cloth 2.
|
||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -428,7 +429,7 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
float time = i / 15.0f;
|
float time = i / 15.0f;
|
||||||
float val = curve.Evaluate(time);
|
float val = curve.Evaluate(time);
|
||||||
m.SetValue(i, val);
|
m.MC2SetValue(i, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
@ -447,32 +448,81 @@ namespace MagicaCloth2
|
|||||||
int index = (int)(math.saturate(time) * 15);
|
int index = (int)(math.saturate(time) * 15);
|
||||||
time -= index * interval;
|
time -= index * interval;
|
||||||
float t = time / interval;
|
float t = time / interval;
|
||||||
return math.lerp(curve.GetValue(index), curve.GetValue(index + 1), t);
|
return math.lerp(curve.MC2GetValue(index), curve.MC2GetValue(index + 1), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 8bitフラグからコライダータイプを取得する
|
/// 16bitフラグにコライダータイプを設定する
|
||||||
/// </summary>
|
|
||||||
/// <param name="flag"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static ColliderManager.ColliderType GetColliderType(in ExBitFlag8 flag)
|
|
||||||
{
|
|
||||||
return (ColliderManager.ColliderType)(flag.Value & 0x0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 8bitフラグにコライダータイプを設定する
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="flag"></param>
|
/// <param name="flag"></param>
|
||||||
/// <param name="ctype"></param>
|
/// <param name="ctype"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ExBitFlag8 SetColliderType(ExBitFlag8 flag, ColliderManager.ColliderType ctype)
|
public static ExBitFlag16 SetColliderType(ExBitFlag16 flag, ColliderManager.ColliderType ctype)
|
||||||
{
|
{
|
||||||
flag.Value = (byte)(flag.Value & 0xf0 | (byte)ctype);
|
flag.Value = (ushort)((flag.Value & 0xfff0) | (ushort)ctype);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 16bitフラグからコライダータイプを取得する
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flag"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ColliderManager.ColliderType GetColliderType(in ExBitFlag16 flag)
|
||||||
|
{
|
||||||
|
return (ColliderManager.ColliderType)(flag.Value & 0x000f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 16bitフラグにシンメトリータイプを設定する
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flag"></param>
|
||||||
|
/// <param name="stype"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ExBitFlag16 SetSymmetryType(ExBitFlag16 flag, ColliderManager.SymmetryType stype)
|
||||||
|
{
|
||||||
|
flag.Value = (ushort)((flag.Value & 0xff0f) | (((ushort)stype) << 4));
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 16bitフラグからシンメトリータイプを取得する
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flag"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ColliderManager.SymmetryType GetSymmetryType(in ExBitFlag16 flag)
|
||||||
|
{
|
||||||
|
return (ColliderManager.SymmetryType)((flag.Value & 0x00f0) >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// 配列をDeepコピーする
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="src"></param>
|
||||||
|
/// <param name="dst"></param>
|
||||||
|
public static void ArrayCopy<T>(T[] src, ref T[] dst)
|
||||||
|
{
|
||||||
|
if (src == null)
|
||||||
|
{
|
||||||
|
dst = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (src.Length == 0)
|
||||||
|
{
|
||||||
|
dst = new T[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst = new T[src.Length];
|
||||||
|
Array.Copy(src, dst, src.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace MagicaCloth2
|
|||||||
/// GridSize>0である必要あり!
|
/// GridSize>0である必要あり!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public class GridMap<T> : IDisposable where T : unmanaged, IEquatable<T>
|
public class GridMap<T> : IDisposable where T : unmanaged // , IEquatable<T>
|
||||||
{
|
{
|
||||||
private NativeParallelMultiHashMap<int3, T> gridMap;
|
private NativeParallelMultiHashMap<int3, T> gridMap;
|
||||||
|
|
||||||
|
|||||||
@ -3,10 +3,6 @@
|
|||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Unity.Burst;
|
|
||||||
using Unity.Collections;
|
|
||||||
using Unity.Collections.LowLevel.Unsafe;
|
|
||||||
using Unity.Jobs;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
@ -19,13 +15,12 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 固定小数点への変換倍率
|
/// 固定小数点への変換倍率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
const int ToFixed = 100000;
|
internal const int ToFixed = 1000000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 少数への復元倍率
|
/// 少数への復元倍率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
const float ToFloat = 0.00001f;
|
internal const float ToFloat = 0.000001f;
|
||||||
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -65,17 +60,6 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 集計バッファのカウンタのみインクリメントする
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index"></param>
|
|
||||||
/// <param name="cntPt"></param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
unsafe internal static void Increment(int index, int* cntPt)
|
|
||||||
{
|
|
||||||
Interlocked.Increment(ref cntPt[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
unsafe internal static void Max(int index, float value, int* pt)
|
unsafe internal static void Max(int index, float value, int* pt)
|
||||||
{
|
{
|
||||||
@ -91,16 +75,16 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static float3 ReadAverageFloat3(int index, in NativeArray<int> countArray, in NativeArray<int> sumArray)
|
unsafe internal static float3 ReadAverageFloat3(int index, int* cntPt, int* sumPt)
|
||||||
{
|
{
|
||||||
int count = countArray[index];
|
int count = cntPt[index];
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int dataIndex = index * 3;
|
int dataIndex = index * 3;
|
||||||
|
|
||||||
// 集計
|
// 集計
|
||||||
float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]);
|
float3 add = new float3(sumPt[dataIndex], sumPt[dataIndex + 1], sumPt[dataIndex + 2]);
|
||||||
add /= count;
|
add /= count;
|
||||||
|
|
||||||
// データは固定小数点なので戻す
|
// データは固定小数点なので戻す
|
||||||
@ -110,10 +94,10 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static float3 ReadFloat3(int index, in NativeArray<int> bufferArray)
|
unsafe internal static float3 ReadFloat3(int index, int* vecPt)
|
||||||
{
|
{
|
||||||
int dataIndex = index * 3;
|
int dataIndex = index * 3;
|
||||||
float3 v = new float3(bufferArray[dataIndex], bufferArray[dataIndex + 1], bufferArray[dataIndex + 2]);
|
float3 v = new float3(vecPt[dataIndex], vecPt[dataIndex + 1], vecPt[dataIndex + 2]);
|
||||||
|
|
||||||
// データは固定小数点なので戻す
|
// データは固定小数点なので戻す
|
||||||
v *= ToFloat;
|
v *= ToFloat;
|
||||||
@ -122,351 +106,9 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static float ReadFloat(int index, in NativeArray<int> bufferArray)
|
unsafe internal static float ReadFloat(int index, int* floatPt)
|
||||||
{
|
{
|
||||||
return bufferArray[index] * ToFloat;
|
return floatPt[index] * ToFloat;
|
||||||
}
|
|
||||||
|
|
||||||
#if false
|
|
||||||
/// <summary>
|
|
||||||
/// 指定アドレスにfloat値を加算する
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pt"></param>
|
|
||||||
/// <param name="index"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
unsafe public static void AddFloat(int* pt, int index, float value)
|
|
||||||
{
|
|
||||||
float current = UnsafeUtility.ReadArrayElement<float>(pt, index);
|
|
||||||
int currenti = math.asint(current);
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
float next = current + value;
|
|
||||||
int nexti = math.asint(next);
|
|
||||||
int prev = Interlocked.CompareExchange(ref pt[index], nexti, currenti);
|
|
||||||
if (prev == currenti)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currenti = prev;
|
|
||||||
current = math.asfloat(prev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//=========================================================================================
|
|
||||||
/// <summary>
|
|
||||||
/// 加算集計バッファを平均化してnextPosに加算する
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="particleList"></param>
|
|
||||||
/// <param name="jobHandle"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static JobHandle SolveAggregateBufferAndClear(in NativeList<int> particleList, float velocityAttenuation, JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
|
|
||||||
if (velocityAttenuation > 1e-06f)
|
|
||||||
{
|
|
||||||
// 速度影響あり
|
|
||||||
var job = new AggregateWithVelocityJob()
|
|
||||||
{
|
|
||||||
jobParticleIndexList = particleList,
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
velocityAttenuation = velocityAttenuation,
|
|
||||||
countArray = sm.countArray,
|
|
||||||
sumArray = sm.sumArray,
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(particleList, 16, jobHandle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 速度影響なし
|
|
||||||
var job = new AggregateJob()
|
|
||||||
{
|
|
||||||
//velocityLimit = velocityLimit,
|
|
||||||
jobParticleIndexList = particleList,
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
countArray = sm.countArray,
|
|
||||||
sumArray = sm.sumArray,
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule(particleList, 16, jobHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct AggregateJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
// 速度制限
|
|
||||||
//public float velocityLimit;
|
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeList<int> jobParticleIndexList;
|
|
||||||
|
|
||||||
// particle
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
|
|
||||||
// aggregate
|
|
||||||
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> countArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> sumArray;
|
|
||||||
|
|
||||||
// 集計パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int pindex = jobParticleIndexList[index];
|
|
||||||
|
|
||||||
int count = countArray[pindex];
|
|
||||||
if (count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int dataIndex = pindex * 3;
|
|
||||||
|
|
||||||
// 集計
|
|
||||||
float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]);
|
|
||||||
add /= count;
|
|
||||||
|
|
||||||
// データは固定小数点なので戻す
|
|
||||||
add *= ToFloat;
|
|
||||||
|
|
||||||
// 速度制限
|
|
||||||
//add = MathUtility.ClampVector(add, velocityLimit);
|
|
||||||
|
|
||||||
// 書き出し
|
|
||||||
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
|
||||||
|
|
||||||
// 集計バッファクリア
|
|
||||||
countArray[pindex] = 0;
|
|
||||||
sumArray[dataIndex] = 0;
|
|
||||||
sumArray[dataIndex + 1] = 0;
|
|
||||||
sumArray[dataIndex + 2] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 速度影響あり
|
|
||||||
/// </summary>
|
|
||||||
[BurstCompile]
|
|
||||||
struct AggregateWithVelocityJob : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeList<int> jobParticleIndexList;
|
|
||||||
|
|
||||||
// particle
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
|
|
||||||
// aggregate
|
|
||||||
public float velocityAttenuation;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> countArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> sumArray;
|
|
||||||
|
|
||||||
// 集計パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int pindex = jobParticleIndexList[index];
|
|
||||||
|
|
||||||
int count = countArray[pindex];
|
|
||||||
if (count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int dataIndex = pindex * 3;
|
|
||||||
|
|
||||||
// 集計
|
|
||||||
float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]);
|
|
||||||
add /= count;
|
|
||||||
|
|
||||||
// データは固定小数点なので戻す
|
|
||||||
add *= ToFloat;
|
|
||||||
|
|
||||||
// 書き出し
|
|
||||||
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
|
||||||
|
|
||||||
// 速度影響
|
|
||||||
velocityPosArray[pindex] = velocityPosArray[pindex] + add * velocityAttenuation;
|
|
||||||
|
|
||||||
// 集計バッファクリア
|
|
||||||
countArray[pindex] = 0;
|
|
||||||
sumArray[dataIndex] = 0;
|
|
||||||
sumArray[dataIndex + 1] = 0;
|
|
||||||
sumArray[dataIndex + 2] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static JobHandle SolveAggregateBufferAndClear(in ExProcessingList<int> processingList, float velocityAttenuation, JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
return SolveAggregateBufferAndClear(processingList.Buffer, processingList.Counter, velocityAttenuation, jobHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe internal static JobHandle SolveAggregateBufferAndClear(in NativeArray<int> particleArray, in NativeReference<int> counter, float velocityAttenuation, JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
|
|
||||||
if (velocityAttenuation > 1e-06f)
|
|
||||||
{
|
|
||||||
// 速度影響あり
|
|
||||||
var job = new AggregateWithVelocityJob2()
|
|
||||||
{
|
|
||||||
particleIndexArray = particleArray,
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
velocityPosArray = sm.velocityPosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
velocityAttenuation = velocityAttenuation,
|
|
||||||
countArray = sm.countArray,
|
|
||||||
sumArray = sm.sumArray,
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule((int*)counter.GetUnsafePtrWithoutChecks(), 16, jobHandle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 速度影響なし
|
|
||||||
var job = new AggregateJob2()
|
|
||||||
{
|
|
||||||
//velocityLimit = velocityLimit,
|
|
||||||
particleIndexArray = particleArray,
|
|
||||||
|
|
||||||
nextPosArray = sm.nextPosArray.GetNativeArray(),
|
|
||||||
|
|
||||||
countArray = sm.countArray,
|
|
||||||
sumArray = sm.sumArray,
|
|
||||||
};
|
|
||||||
jobHandle = job.Schedule((int*)counter.GetUnsafePtrWithoutChecks(), 16, jobHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jobHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BurstCompile]
|
|
||||||
struct AggregateJob2 : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
// 速度制限
|
|
||||||
//public float velocityLimit;
|
|
||||||
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> particleIndexArray;
|
|
||||||
|
|
||||||
// particle
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
|
|
||||||
// aggregate
|
|
||||||
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> countArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> sumArray;
|
|
||||||
|
|
||||||
// 集計パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int pindex = particleIndexArray[index];
|
|
||||||
|
|
||||||
int count = countArray[pindex];
|
|
||||||
if (count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int dataIndex = pindex * 3;
|
|
||||||
|
|
||||||
// 集計
|
|
||||||
float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]);
|
|
||||||
add /= count;
|
|
||||||
|
|
||||||
// データは固定小数点なので戻す
|
|
||||||
add *= ToFloat;
|
|
||||||
|
|
||||||
// 速度制限
|
|
||||||
//add = MathUtility.ClampVector(add, velocityLimit);
|
|
||||||
|
|
||||||
// 書き出し
|
|
||||||
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
|
||||||
|
|
||||||
// 集計バッファクリア
|
|
||||||
countArray[pindex] = 0;
|
|
||||||
sumArray[dataIndex] = 0;
|
|
||||||
sumArray[dataIndex + 1] = 0;
|
|
||||||
sumArray[dataIndex + 2] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 速度影響あり
|
|
||||||
/// </summary>
|
|
||||||
[BurstCompile]
|
|
||||||
struct AggregateWithVelocityJob2 : IJobParallelForDefer
|
|
||||||
{
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> particleIndexArray;
|
|
||||||
|
|
||||||
// particle
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> nextPosArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<float3> velocityPosArray;
|
|
||||||
|
|
||||||
// aggregate
|
|
||||||
public float velocityAttenuation;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> countArray;
|
|
||||||
[NativeDisableParallelForRestriction]
|
|
||||||
public NativeArray<int> sumArray;
|
|
||||||
|
|
||||||
// 集計パーティクルごと
|
|
||||||
public void Execute(int index)
|
|
||||||
{
|
|
||||||
int pindex = particleIndexArray[index];
|
|
||||||
|
|
||||||
int count = countArray[pindex];
|
|
||||||
if (count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int dataIndex = pindex * 3;
|
|
||||||
|
|
||||||
// 集計
|
|
||||||
float3 add = new float3(sumArray[dataIndex], sumArray[dataIndex + 1], sumArray[dataIndex + 2]);
|
|
||||||
add /= count;
|
|
||||||
|
|
||||||
// データは固定小数点なので戻す
|
|
||||||
add *= ToFloat;
|
|
||||||
|
|
||||||
// 書き出し
|
|
||||||
nextPosArray[pindex] = nextPosArray[pindex] + add;
|
|
||||||
|
|
||||||
// 速度影響
|
|
||||||
velocityPosArray[pindex] = velocityPosArray[pindex] + add * velocityAttenuation;
|
|
||||||
|
|
||||||
// 集計バッファクリア
|
|
||||||
countArray[pindex] = 0;
|
|
||||||
sumArray[dataIndex] = 0;
|
|
||||||
sumArray[dataIndex + 1] = 0;
|
|
||||||
sumArray[dataIndex + 2] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 集計バッファのカウンタのみゼロクリアする
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="jobHandle"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static JobHandle ClearCountArray(JobHandle jobHandle)
|
|
||||||
{
|
|
||||||
var sm = MagicaManager.Simulation;
|
|
||||||
|
|
||||||
return JobUtility.Fill(sm.countArray, sm.countArray.Length, 0, jobHandle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float GetValue(in this float4x4 m, int index)
|
public static float MC2GetValue(in this float4x4 m, int index)
|
||||||
{
|
{
|
||||||
index = math.clamp(index, 0, 15);
|
index = math.clamp(index, 0, 15);
|
||||||
return m[index / 4][index % 4];
|
return m[index / 4][index % 4];
|
||||||
@ -28,7 +28,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void SetValue(ref this float4x4 m, int index, float value)
|
public static void MC2SetValue(ref this float4x4 m, int index, float value)
|
||||||
{
|
{
|
||||||
index = math.clamp(index, 0, 15);
|
index = math.clamp(index, 0, 15);
|
||||||
m[index / 4][index % 4] = value;
|
m[index / 4][index % 4] = value;
|
||||||
@ -41,7 +41,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="time">0.0 ~ 1.0</param>
|
/// <param name="time">0.0 ~ 1.0</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float EvaluateCurveClamp01(in this float4x4 m, float time)
|
public static float MC2EvaluateCurveClamp01(in this float4x4 m, float time)
|
||||||
{
|
{
|
||||||
return math.saturate(DataUtility.EvaluateCurve(m, time));
|
return math.saturate(DataUtility.EvaluateCurve(m, time));
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="time">0.0 ~ 1.0</param>
|
/// <param name="time">0.0 ~ 1.0</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float EvaluateCurve(in this float4x4 m, float time)
|
public static float MC2EvaluateCurve(in this float4x4 m, float time)
|
||||||
{
|
{
|
||||||
return DataUtility.EvaluateCurve(m, time);
|
return DataUtility.EvaluateCurve(m, time);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -223,6 +223,45 @@ namespace MagicaCloth2
|
|||||||
return quaternion.AxisAngle(math.normalize(axis), angle * t);
|
return quaternion.AxisAngle(math.normalize(axis), angle * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// fromからtoへ回転させるクォータニオンを返します(単位化なし)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from"></param>
|
||||||
|
/// <param name="to"></param>
|
||||||
|
/// <param name="t">補間率(0.0-1.0)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static quaternion FromToRotationWithoutNormalize(in float3 v1, in float3 v2, float t = 1.0f)
|
||||||
|
{
|
||||||
|
//float3 v1 = math.normalize(from);
|
||||||
|
//float3 v2 = math.normalize(to);
|
||||||
|
|
||||||
|
float c = Clamp1(math.dot(v1, v2));
|
||||||
|
float angle = math.acos(c);
|
||||||
|
float3 axis = math.cross(v1, v2);
|
||||||
|
|
||||||
|
if (math.abs(1.0f + c) < 1e-06f)
|
||||||
|
{
|
||||||
|
angle = (float)math.PI;
|
||||||
|
|
||||||
|
if (v1.x > v1.y && v1.x > v1.z)
|
||||||
|
{
|
||||||
|
axis = math.cross(v1, new float3(0, 1, 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
axis = math.cross(v1, new float3(1, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (math.abs(1.0f - c) < 1e-06f)
|
||||||
|
{
|
||||||
|
//angle = 0.0f;
|
||||||
|
//axis = new float3(1, 0, 0);
|
||||||
|
return quaternion.identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quaternion.AxisAngle(math.normalize(axis), angle * t);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// fromからtoへ回転させるクォータニオンを返します
|
/// fromからtoへ回転させるクォータニオンを返します
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -287,13 +326,15 @@ namespace MagicaCloth2
|
|||||||
public static quaternion ToRotation(in float3 nor, in float3 tan)
|
public static quaternion ToRotation(in float3 nor, in float3 tan)
|
||||||
{
|
{
|
||||||
#if MC2_DEBUG
|
#if MC2_DEBUG
|
||||||
|
// 安全性確認
|
||||||
float ln = math.length(nor);
|
float ln = math.length(nor);
|
||||||
float lt = math.length(tan);
|
float lt = math.length(tan);
|
||||||
Develop.Assert(ln > 0.0f);
|
Develop.Assert(ln > 0.99f && ln < 1.01f);
|
||||||
Develop.Assert(lt > 0.0f);
|
Develop.Assert(lt > 0.99f && lt < 1.01f);
|
||||||
float dot = math.dot(nor / ln, tan / lt);
|
float dot = math.dot(nor / ln, tan / lt);
|
||||||
Develop.Assert(dot != 1.0f && dot != -1.0f);
|
Develop.Assert(dot != 1.0f && dot != -1.0f);
|
||||||
#endif
|
#endif
|
||||||
|
// 2 つの入力ベクトルは単位長であり、同一直線上にないことが前提となります。
|
||||||
return quaternion.LookRotation(tan, nor);
|
return quaternion.LookRotation(tan, nor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,6 +443,45 @@ namespace MagicaCloth2
|
|||||||
axis = q.value.xyz / s;
|
axis = q.value.xyz / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// クォータニオンからオイラー角度を計算して返す
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="q"></param>
|
||||||
|
/// <returns>(Deg)角度</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float3 ToEuler(in quaternion q)
|
||||||
|
{
|
||||||
|
float3 angles = 0;
|
||||||
|
|
||||||
|
// クォータニオンの成分
|
||||||
|
float qx = q.value.x;
|
||||||
|
float qy = q.value.y;
|
||||||
|
float qz = q.value.z;
|
||||||
|
float qw = q.value.w;
|
||||||
|
|
||||||
|
// ピッチ (x軸回転)
|
||||||
|
float sinX = 2f * (qw * qx - qz * qy);
|
||||||
|
if (math.abs(sinX) >= 0.99999f) // ジンバルロックの検出
|
||||||
|
{
|
||||||
|
angles.x = math.sign(sinX) * 90f; // ±90度(deg)
|
||||||
|
angles.y = math.atan2(2f * (qw * qy + qx * qz), 1f - 2f * (qx * qx + qy * qy));
|
||||||
|
angles.y = math.degrees(angles.y);
|
||||||
|
angles.z = 0f; // ジンバルロックでロールは不定
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
angles.x = math.asin(sinX);
|
||||||
|
// ヨー (y軸回転)
|
||||||
|
angles.y = math.atan2(2f * (qw * qy + qx * qz), 1f - 2f * (qx * qx + qy * qy));
|
||||||
|
// ロール (z軸回転)
|
||||||
|
//angles.z = math.atan2(2f * (qw * qz + qx * qy), 1f - 2f * (qy * qy + qz * qz));
|
||||||
|
angles.z = math.atan2(2f * (qw * qz + qx * qy), 1f - 2f * (qx * qx + qz * qz)); // どうやらこれっぽい
|
||||||
|
angles = math.degrees(angles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return angles;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 与えられた線分abおよび点cに対して、ab上の最近接点t(0.0-1.0)を計算して返す
|
/// 与えられた線分abおよび点cに対して、ab上の最近接点t(0.0-1.0)を計算して返す
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -570,6 +650,82 @@ namespace MagicaCloth2
|
|||||||
return math.dot(c1 - c2, c1 - c2);
|
return math.dot(c1 - c2, c1 - c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 2つの線分(p1-q1)(p2-q2)の最近接点(s, t)を計算する
|
||||||
|
/// この関数ではs/tのみで接点と距離は計算しない
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p1">線分1の始点</param>
|
||||||
|
/// <param name="q1">線分1の終点</param>
|
||||||
|
/// <param name="p2">線分2の始点</param>
|
||||||
|
/// <param name="q2">線分2の終点</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void ClosestPtSegmentSegment2(in float3 p1, in float3 q1, in float3 p2, in float3 q2, out float s, out float t)
|
||||||
|
{
|
||||||
|
//s = 0.0f;
|
||||||
|
//t = 0.0f;
|
||||||
|
float3 d1 = q1 - p1; // 線分s1の方向ベクトル
|
||||||
|
float3 d2 = q2 - p2; // 線分s2の方向ベクトル
|
||||||
|
float3 r = p1 - p2;
|
||||||
|
float a = math.dot(d1, d1); // 線分s1の距離の平方、常に正
|
||||||
|
float e = math.dot(d2, d2); // 線分s2の距離の平方、常に正
|
||||||
|
float f = math.dot(d2, r);
|
||||||
|
// 片方あるいは両方の線分が点に縮退しているかどうかチェック
|
||||||
|
if (a <= 1e-8f && e <= 1e-8f)
|
||||||
|
{
|
||||||
|
// 両方の線分が点に縮退
|
||||||
|
s = t = 0.0f;
|
||||||
|
}
|
||||||
|
else if (a <= 1e-8f)
|
||||||
|
{
|
||||||
|
// 最初の線分が点に縮退
|
||||||
|
s = 0.0f;
|
||||||
|
t = math.saturate(f / e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float c = math.dot(d1, r);
|
||||||
|
if (e <= 1e-8f)
|
||||||
|
{
|
||||||
|
// 2番目の線分が点に縮退
|
||||||
|
t = 0.0f;
|
||||||
|
s = math.saturate(-c / a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ここから一般的な縮退の場合を開始
|
||||||
|
float b = math.dot(d1, d2);
|
||||||
|
float denom = a * e - b * b; // 常に正
|
||||||
|
// 線分が平行でない場合、L1上のL2に対する最近接点を計算、そして
|
||||||
|
// 線分s1に対してクランプ。そうでない場合は任意s(ここでは0)を選択
|
||||||
|
if (denom != 0.0f)
|
||||||
|
{
|
||||||
|
s = math.saturate((b * f - c * e) / denom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s = 0.0f;
|
||||||
|
}
|
||||||
|
// L2上のs1(s)に対する最近接点を以下を用いて計算
|
||||||
|
// t = dot((p1 + d1 * s) - p2, d2) / dot(d2, d2) = (b * s + f) / e
|
||||||
|
t = (b * s + f) / e;
|
||||||
|
// tが[0,1]の中にあれば終了。
|
||||||
|
// そうでなければtをクランプ、sをtの新しい値に対して以下を用いて再計算
|
||||||
|
// s = dot((p2 + d2 * t) - p1, d1) / dot(d1, d1) = (t * b - c) / a
|
||||||
|
// そしてsを[0,1]にクランプ
|
||||||
|
if (t < 0.0f)
|
||||||
|
{
|
||||||
|
t = 0.0f;
|
||||||
|
s = math.saturate(-c / a);
|
||||||
|
}
|
||||||
|
else if (t > 1.0f)
|
||||||
|
{
|
||||||
|
t = 1.0f;
|
||||||
|
s = math.saturate((b - c) / a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 三角形(abc)から点(p)への最近接点とその重心座標uvwを返す
|
/// 三角形(abc)から点(p)への最近接点とその重心座標uvwを返す
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -780,6 +936,7 @@ namespace MagicaCloth2
|
|||||||
return tan;
|
return tan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if false
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// トライアングルの回転姿勢を返す
|
/// トライアングルの回転姿勢を返す
|
||||||
/// 法線と(重心-p0)の軸からなるクォータニオン
|
/// 法線と(重心-p0)の軸からなるクォータニオン
|
||||||
@ -815,6 +972,7 @@ namespace MagicaCloth2
|
|||||||
var tan = math.normalize(p3 - p2);
|
var tan = math.normalize(p3 - p2);
|
||||||
return quaternion.LookRotation(tan, n);
|
return quaternion.LookRotation(tan, n);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// トライアングルペアのなす角を返す(ラジアン)
|
/// トライアングルペアのなす角を返す(ラジアン)
|
||||||
@ -1064,30 +1222,45 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float3 TransformPoint(in float3 pos, in float4x4 localToWorldMatrix)
|
public static float3 TransformPoint(in float3 pos, in float3 wpos, in quaternion wrot, in float3 wscl)
|
||||||
{
|
{
|
||||||
return math.transform(localToWorldMatrix, pos);
|
return math.transform(Matrix4x4.TRS(wpos, wrot, wscl), pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float3 TransformVector(in float3 vec, in float4x4 localToWorldMatrix)
|
public static float3 TransformPoint(in float3 pos, in float4x4 m)
|
||||||
{
|
{
|
||||||
return math.mul(localToWorldMatrix, new float4(vec, 0)).xyz;
|
return math.transform(m, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float3 TransformDirection(in float3 dir, in float4x4 localToWorldMatrix)
|
public static float3 TransformVector(in float3 vec, in float4x4 m)
|
||||||
|
{
|
||||||
|
return math.mul(m, new float4(vec, 0)).xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float3 TransformDirection(in float3 dir, in float4x4 m)
|
||||||
{
|
{
|
||||||
float len = math.length(dir);
|
float len = math.length(dir);
|
||||||
if (len > 0.0f)
|
if (len > 0.0f)
|
||||||
return math.normalize(TransformVector(dir, localToWorldMatrix)) * len;
|
return math.normalize(TransformVector(dir, m)) * len;
|
||||||
else
|
else
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static quaternion TransformRotation(in quaternion rot, in float4x4 m, in float3 normalTangentFlip)
|
||||||
|
{
|
||||||
|
ToNormalTangent(rot, out float3 nor, out float3 tan);
|
||||||
|
nor = math.mul(m, new float4(nor, 0)).xyz * normalTangentFlip.y;
|
||||||
|
tan = math.mul(m, new float4(tan, 0)).xyz * normalTangentFlip.z;
|
||||||
|
return quaternion.LookRotation(tan, nor);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 距離を空間変換する
|
/// 距離を空間変換する
|
||||||
/// 不均等スケールを考慮して各軸の平均値を返す
|
/// 非一様スケールを考慮して各軸の平均値を返す
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dist"></param>
|
/// <param name="dist"></param>
|
||||||
/// <param name="localToWorldMatrix"></param>
|
/// <param name="localToWorldMatrix"></param>
|
||||||
@ -1139,6 +1312,12 @@ namespace MagicaCloth2
|
|||||||
return math.transform(worldToLocalMatrix, pos);
|
return math.transform(worldToLocalMatrix, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float3 InverseTransformPoint(in float3 pos, in float3 wpos, in quaternion wrot, in float3 wscl)
|
||||||
|
{
|
||||||
|
return math.transform(math.inverse(Matrix4x4.TRS(wpos, wrot, wscl)), pos);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float3 InverseTransformVector(in float3 vec, in float4x4 worldToLocalMatrix)
|
public static float3 InverseTransformVector(in float3 vec, in float4x4 worldToLocalMatrix)
|
||||||
{
|
{
|
||||||
@ -1364,6 +1543,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
if (math.dot(planeDir, v) < 0.0f)
|
if (math.dot(planeDir, v) < 0.0f)
|
||||||
{
|
{
|
||||||
|
// 押し出し発生
|
||||||
// 押出し座標
|
// 押出し座標
|
||||||
outPos = pos - gv;
|
outPos = pos - gv;
|
||||||
|
|
||||||
@ -1373,9 +1553,10 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// 押し出し不要。何もしない
|
||||||
outPos = pos;
|
outPos = pos;
|
||||||
|
|
||||||
// 面までの距離を返す
|
// 面までの距離を返す(+)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1554,5 +1735,57 @@ namespace MagicaCloth2
|
|||||||
Develop.Assert(mass > 0.0f);
|
Develop.Assert(mass > 0.0f);
|
||||||
return 1.0f / mass;
|
return 1.0f / mass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数をn分割して、指定インデックスの範囲を返します。
|
||||||
|
/// 数は整数のみ。
|
||||||
|
/// 例:100(dataLength)を5(divCount)分割した結果
|
||||||
|
/// divIndex(0):0~20
|
||||||
|
/// divIndex(1):20~40
|
||||||
|
/// divIndex(2):40~60
|
||||||
|
/// divIndex(3):60~80
|
||||||
|
/// divIndex(4):80~100
|
||||||
|
///
|
||||||
|
/// ただし、数が分割数を下回る場合は範囲外のインデックスは-1となる
|
||||||
|
/// 例:3(dataLength)を5(divCount)分割した結果
|
||||||
|
/// divIndex(0):0~1
|
||||||
|
/// divIndex(1):1~2
|
||||||
|
/// divIndex(2):2~3
|
||||||
|
/// divIndex(3):-1~-1
|
||||||
|
/// divIndex(4):-1~-1
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataLength"></param>
|
||||||
|
/// <param name="divCount"></param>
|
||||||
|
/// <param name="divIndex"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int2 CalcSplitRange(int dataLength, int divCount, int divIndex)
|
||||||
|
{
|
||||||
|
if (dataLength <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (dataLength < divCount)
|
||||||
|
{
|
||||||
|
if (divIndex < dataLength)
|
||||||
|
return new int2(divIndex, divIndex + 1);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float segment = (float)dataLength / divCount;
|
||||||
|
int start = (int)(segment * divIndex);
|
||||||
|
int end = (divIndex == divCount - 1) ? dataLength : (int)(segment * (divIndex + 1));
|
||||||
|
return new int2(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static DataChunk GetWorkerChunk(int dataLenght, int workerCount, int workerIndex)
|
||||||
|
{
|
||||||
|
int2 range = CalcSplitRange(dataLenght, workerCount, workerIndex);
|
||||||
|
if (range.x < 0)
|
||||||
|
return DataChunk.Empty;
|
||||||
|
else
|
||||||
|
return new DataChunk(range.x, range.y - range.x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ using System.Text;
|
|||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Collections.LowLevel.Unsafe;
|
using Unity.Collections.LowLevel.Unsafe;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
{
|
{
|
||||||
@ -389,6 +390,12 @@ namespace MagicaCloth2
|
|||||||
NativeArray<T>.Copy(nativeArray, array);
|
NativeArray<T>.Copy(nativeArray, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyTo(T[] array, int startIndex)
|
||||||
|
{
|
||||||
|
Debug.Assert(array != null);
|
||||||
|
NativeArray<T>.Copy(nativeArray, startIndex, array, 0, array.Length);
|
||||||
|
}
|
||||||
|
|
||||||
public void CopyTo<U>(U[] array) where U : struct
|
public void CopyTo<U>(U[] array) where U : struct
|
||||||
{
|
{
|
||||||
NativeArray<U>.Copy(nativeArray.Reinterpret<U>(), array);
|
NativeArray<U>.Copy(nativeArray.Reinterpret<U>(), array);
|
||||||
@ -399,11 +406,22 @@ namespace MagicaCloth2
|
|||||||
NativeArray<T>.Copy(array, nativeArray);
|
NativeArray<T>.Copy(array, nativeArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyFrom(T[] array, int startIndex)
|
||||||
|
{
|
||||||
|
Debug.Assert(array != null);
|
||||||
|
NativeArray<T>.Copy(array, 0, nativeArray, startIndex, array.Length);
|
||||||
|
}
|
||||||
|
|
||||||
public void CopyFrom<U>(NativeArray<U> array) where U : struct
|
public void CopyFrom<U>(NativeArray<U> array) where U : struct
|
||||||
{
|
{
|
||||||
NativeArray<T>.Copy(array.Reinterpret<T>(), nativeArray);
|
NativeArray<T>.Copy(array.Reinterpret<T>(), nativeArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyFrom<U>(NativeArray<U> array, int dstIndex, int length) where U : struct
|
||||||
|
{
|
||||||
|
NativeArray<T>.Copy(array.Reinterpret<T>(), 0, nativeArray, dstIndex, length);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 型もサイズも異なる配列にデータをコピーする。
|
/// 型もサイズも異なる配列にデータをコピーする。
|
||||||
/// int3 -> int[]など
|
/// int3 -> int[]など
|
||||||
@ -474,6 +492,11 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove(int index)
|
||||||
|
{
|
||||||
|
Remove(new DataChunk(index));
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveAndFill(DataChunk chunk, T clearData = default(T))
|
public void RemoveAndFill(DataChunk chunk, T clearData = default(T))
|
||||||
{
|
{
|
||||||
Remove(chunk);
|
Remove(chunk);
|
||||||
|
|||||||
@ -67,6 +67,11 @@ namespace MagicaCloth2
|
|||||||
count = length;
|
count = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExSimpleNativeArray(SerializationData sdata)
|
||||||
|
{
|
||||||
|
Deserialize(sdata);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (nativeArray.IsCreated)
|
if (nativeArray.IsCreated)
|
||||||
@ -108,11 +113,13 @@ namespace MagicaCloth2
|
|||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 領域のみ拡張する
|
/// 領域のみ拡張する
|
||||||
|
/// すでにその長さの領域が確保されている場合は何もしない
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capacity"></param>
|
/// <param name="newLength"></param>
|
||||||
public void AddCapacity(int capacity)
|
public void SetLength(int newLength)
|
||||||
{
|
{
|
||||||
Expand(capacity, true);
|
if (newLength > length)
|
||||||
|
Expand(newLength - length, force: true, copy: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -216,6 +223,16 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddRange(NativeArray<T> narray, int start, int length)
|
||||||
|
{
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
Expand(length);
|
||||||
|
NativeArray<T>.Copy(narray, start, nativeArray, count, length);
|
||||||
|
count += length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void AddRange(NativeList<T> nlist)
|
public void AddRange(NativeList<T> nlist)
|
||||||
{
|
{
|
||||||
Debug.Assert(nlist.IsCreated);
|
Debug.Assert(nlist.IsCreated);
|
||||||
@ -481,7 +498,8 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataLength"></param>
|
/// <param name="dataLength"></param>
|
||||||
/// <param name="force">強制的に領域を追加</param>
|
/// <param name="force">強制的に領域を追加</param>
|
||||||
void Expand(int dataLength, bool force = false)
|
/// <param name="copy">古いデータをコピーするかどうか</param>
|
||||||
|
void Expand(int dataLength, bool force = false, bool copy = true)
|
||||||
{
|
{
|
||||||
int newlength = force ? length + dataLength : count + dataLength;
|
int newlength = force ? length + dataLength : count + dataLength;
|
||||||
|
|
||||||
@ -499,8 +517,11 @@ namespace MagicaCloth2
|
|||||||
var newNativeArray = new NativeArray<T>(newlength, Allocator.Persistent);
|
var newNativeArray = new NativeArray<T>(newlength, Allocator.Persistent);
|
||||||
|
|
||||||
// copy
|
// copy
|
||||||
|
if (copy)
|
||||||
|
{
|
||||||
// コピーは使用分だけ
|
// コピーは使用分だけ
|
||||||
NativeArray<T>.Copy(nativeArray, newNativeArray, count);
|
NativeArray<T>.Copy(nativeArray, newNativeArray, count);
|
||||||
|
}
|
||||||
|
|
||||||
nativeArray.Dispose();
|
nativeArray.Dispose();
|
||||||
nativeArray = newNativeArray;
|
nativeArray = newNativeArray;
|
||||||
@ -512,8 +533,8 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.AppendLine($"ExNativeArray Length:{Length} Count:{Count} IsValid:{IsValid}");
|
sb.AppendLine($"ExSimpleNativeArray Length:{Length} Count:{Count} IsValid:{IsValid}");
|
||||||
sb.AppendLine("---- Datas[100] ----");
|
sb.AppendLine("---- Datas[~100] ----");
|
||||||
if (IsValid)
|
if (IsValid)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Length && i < 100; i++)
|
for (int i = 0; i < Length && i < 100; i++)
|
||||||
@ -524,5 +545,59 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// シリアライズデータ
|
||||||
|
/// </summary>
|
||||||
|
[System.Serializable]
|
||||||
|
public class SerializationData
|
||||||
|
{
|
||||||
|
public int count;
|
||||||
|
public int length;
|
||||||
|
public byte[] arrayBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// シリアライズする
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public SerializationData Serialize()
|
||||||
|
{
|
||||||
|
var data = new SerializationData();
|
||||||
|
data.count = count;
|
||||||
|
data.length = length;
|
||||||
|
if (nativeArray.IsCreated && nativeArray.Length > 0)
|
||||||
|
{
|
||||||
|
data.arrayBytes = nativeArray.MC2ToRawBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// デシリアライズする
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Deserialize(SerializationData data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
count = data.count;
|
||||||
|
length = data.length;
|
||||||
|
if (data.length > 0 && data.arrayBytes != null)
|
||||||
|
{
|
||||||
|
nativeArray = NativeArrayExtensions.MC2FromRawBytes<T>(data.arrayBytes, Allocator.Persistent);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Debug.LogException(exception);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace MagicaCloth2
|
|||||||
// Common
|
// Common
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsCapacity<T>(ref this FixedList128Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static bool MC2IsCapacity<T>(ref this FixedList128Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
return fixedList.Length >= fixedList.Capacity;
|
return fixedList.Length >= fixedList.Capacity;
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Set<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Set<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Contains(item) == false)
|
if (fixedList.Contains(item) == false)
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void SetLimit<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2SetLimit<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Length >= fixedList.Capacity)
|
if (fixedList.Length >= fixedList.Capacity)
|
||||||
{
|
{
|
||||||
@ -67,7 +67,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void RemoveItemAtSwapBack<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2RemoveItemAtSwapBack<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fixedList.Length; i++)
|
for (int i = 0; i < fixedList.Length; i++)
|
||||||
{
|
{
|
||||||
@ -83,13 +83,13 @@ namespace MagicaCloth2
|
|||||||
// Stack
|
// Stack
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Push<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Push<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Pop<T>(ref this FixedList128Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Pop<T>(ref this FixedList128Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
int index = fixedList.Length - 1;
|
int index = fixedList.Length - 1;
|
||||||
T item = fixedList[index];
|
T item = fixedList[index];
|
||||||
@ -101,13 +101,13 @@ namespace MagicaCloth2
|
|||||||
// Queue
|
// Queue
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Enqueue<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Enqueue<T>(ref this FixedList128Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Dequque<T>(ref this FixedList128Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Dequque<T>(ref this FixedList128Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
T item = fixedList[0];
|
T item = fixedList[0];
|
||||||
fixedList.RemoveAt(0);
|
fixedList.RemoveAt(0);
|
||||||
|
|||||||
@ -8,14 +8,13 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
{
|
{
|
||||||
//[BurstCompatible]
|
|
||||||
public static class FixedList32BytesExtensions
|
public static class FixedList32BytesExtensions
|
||||||
{
|
{
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
// Common
|
// Common
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsCapacity<T>(ref this FixedList32Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static bool MC2IsCapacity<T>(ref this FixedList32Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
return fixedList.Length >= fixedList.Capacity;
|
return fixedList.Length >= fixedList.Capacity;
|
||||||
}
|
}
|
||||||
@ -31,7 +30,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Set<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Set<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Contains(item) == false)
|
if (fixedList.Contains(item) == false)
|
||||||
{
|
{
|
||||||
@ -47,7 +46,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void SetLimit<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2SetLimit<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Length >= fixedList.Capacity)
|
if (fixedList.Length >= fixedList.Capacity)
|
||||||
{
|
{
|
||||||
@ -68,7 +67,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void RemoveItemAtSwapBack<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2RemoveItemAtSwapBack<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fixedList.Length; i++)
|
for (int i = 0; i < fixedList.Length; i++)
|
||||||
{
|
{
|
||||||
@ -84,13 +83,13 @@ namespace MagicaCloth2
|
|||||||
// Stack
|
// Stack
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Push<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Push<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Pop<T>(ref this FixedList32Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Pop<T>(ref this FixedList32Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
int index = fixedList.Length - 1;
|
int index = fixedList.Length - 1;
|
||||||
T item = fixedList[index];
|
T item = fixedList[index];
|
||||||
@ -102,13 +101,13 @@ namespace MagicaCloth2
|
|||||||
// Queue
|
// Queue
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Enqueue<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Enqueue<T>(ref this FixedList32Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Dequque<T>(ref this FixedList32Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Dequque<T>(ref this FixedList32Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
T item = fixedList[0];
|
T item = fixedList[0];
|
||||||
fixedList.RemoveAt(0);
|
fixedList.RemoveAt(0);
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace MagicaCloth2
|
|||||||
// Common
|
// Common
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsCapacity<T>(ref this FixedList4096Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static bool MC2IsCapacity<T>(ref this FixedList4096Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
return fixedList.Length >= fixedList.Capacity;
|
return fixedList.Length >= fixedList.Capacity;
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Set<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Set<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Contains(item) == false)
|
if (fixedList.Contains(item) == false)
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void SetLimit<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2SetLimit<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Length >= fixedList.Capacity)
|
if (fixedList.Length >= fixedList.Capacity)
|
||||||
{
|
{
|
||||||
@ -67,7 +67,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void RemoveItemAtSwapBack<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2RemoveItemAtSwapBack<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fixedList.Length; i++)
|
for (int i = 0; i < fixedList.Length; i++)
|
||||||
{
|
{
|
||||||
@ -83,13 +83,13 @@ namespace MagicaCloth2
|
|||||||
// Stack
|
// Stack
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Push<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Push<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Pop<T>(ref this FixedList4096Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Pop<T>(ref this FixedList4096Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
int index = fixedList.Length - 1;
|
int index = fixedList.Length - 1;
|
||||||
T item = fixedList[index];
|
T item = fixedList[index];
|
||||||
@ -101,13 +101,13 @@ namespace MagicaCloth2
|
|||||||
// Queue
|
// Queue
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Enqueue<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Enqueue<T>(ref this FixedList4096Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Dequque<T>(ref this FixedList4096Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Dequque<T>(ref this FixedList4096Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
T item = fixedList[0];
|
T item = fixedList[0];
|
||||||
fixedList.RemoveAt(0);
|
fixedList.RemoveAt(0);
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace MagicaCloth2
|
|||||||
// Common
|
// Common
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsCapacity<T>(ref this FixedList512Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static bool MC2IsCapacity<T>(ref this FixedList512Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
return fixedList.Length >= fixedList.Capacity;
|
return fixedList.Length >= fixedList.Capacity;
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Set<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Set<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Contains(item) == false)
|
if (fixedList.Contains(item) == false)
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void SetLimit<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2SetLimit<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Length >= fixedList.Capacity)
|
if (fixedList.Length >= fixedList.Capacity)
|
||||||
{
|
{
|
||||||
@ -67,7 +67,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void RemoveItemAtSwapBack<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2RemoveItemAtSwapBack<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fixedList.Length; i++)
|
for (int i = 0; i < fixedList.Length; i++)
|
||||||
{
|
{
|
||||||
@ -83,13 +83,13 @@ namespace MagicaCloth2
|
|||||||
// Stack
|
// Stack
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Push<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Push<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Pop<T>(ref this FixedList512Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Pop<T>(ref this FixedList512Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
int index = fixedList.Length - 1;
|
int index = fixedList.Length - 1;
|
||||||
T item = fixedList[index];
|
T item = fixedList[index];
|
||||||
@ -101,13 +101,13 @@ namespace MagicaCloth2
|
|||||||
// Queue
|
// Queue
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Enqueue<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Enqueue<T>(ref this FixedList512Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Dequque<T>(ref this FixedList512Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Dequque<T>(ref this FixedList512Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
T item = fixedList[0];
|
T item = fixedList[0];
|
||||||
fixedList.RemoveAt(0);
|
fixedList.RemoveAt(0);
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace MagicaCloth2
|
|||||||
// Common
|
// Common
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsCapacity<T>(ref this FixedList64Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static bool MC2IsCapacity<T>(ref this FixedList64Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
return fixedList.Length >= fixedList.Capacity;
|
return fixedList.Length >= fixedList.Capacity;
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Set<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Set<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Contains(item) == false)
|
if (fixedList.Contains(item) == false)
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void SetLimit<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2SetLimit<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (fixedList.Length >= fixedList.Capacity)
|
if (fixedList.Length >= fixedList.Capacity)
|
||||||
{
|
{
|
||||||
@ -67,7 +67,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="fixedList"></param>
|
/// <param name="fixedList"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void RemoveItemAtSwapBack<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2RemoveItemAtSwapBack<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fixedList.Length; i++)
|
for (int i = 0; i < fixedList.Length; i++)
|
||||||
{
|
{
|
||||||
@ -83,13 +83,13 @@ namespace MagicaCloth2
|
|||||||
// Stack
|
// Stack
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Push<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Push<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Pop<T>(ref this FixedList64Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Pop<T>(ref this FixedList64Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
int index = fixedList.Length - 1;
|
int index = fixedList.Length - 1;
|
||||||
T item = fixedList[index];
|
T item = fixedList[index];
|
||||||
@ -101,13 +101,13 @@ namespace MagicaCloth2
|
|||||||
// Queue
|
// Queue
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Enqueue<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
public static void MC2Enqueue<T>(ref this FixedList64Bytes<T> fixedList, T item) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
fixedList.Add(item);
|
fixedList.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T Dequque<T>(ref this FixedList64Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
public static T MC2Dequque<T>(ref this FixedList64Bytes<T> fixedList) where T : unmanaged, IEquatable<T>
|
||||||
{
|
{
|
||||||
T item = fixedList[0];
|
T item = fixedList[0];
|
||||||
fixedList.RemoveAt(0);
|
fixedList.RemoveAt(0);
|
||||||
|
|||||||
@ -8,14 +8,14 @@ namespace MagicaCloth2
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// NativeArrayの拡張メソッド
|
/// NativeArrayの拡張メソッド
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static class NativeArrayExtensions
|
public static class NativeArrayExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NativeArrayが確保されている場合のみDispose()する
|
/// NativeArrayが確保されている場合のみDispose()する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="array"></param>
|
/// <param name="array"></param>
|
||||||
public static void DisposeSafe<T>(ref this NativeArray<T> array) where T : unmanaged
|
public static void MC2DisposeSafe<T>(ref this NativeArray<T> array) where T : unmanaged
|
||||||
{
|
{
|
||||||
if (array.IsCreated)
|
if (array.IsCreated)
|
||||||
array.Dispose();
|
array.Dispose();
|
||||||
@ -31,13 +31,55 @@ namespace MagicaCloth2
|
|||||||
/// <param name="size"></param>
|
/// <param name="size"></param>
|
||||||
/// <param name="allocator"></param>
|
/// <param name="allocator"></param>
|
||||||
/// <param name="options"></param>
|
/// <param name="options"></param>
|
||||||
public static void Resize<T>(ref this NativeArray<T> array, int size, Allocator allocator = Allocator.Persistent, NativeArrayOptions options = NativeArrayOptions.ClearMemory) where T : unmanaged
|
public static void MC2Resize<T>(ref this NativeArray<T> array, int size, Allocator allocator = Allocator.Persistent, NativeArrayOptions options = NativeArrayOptions.ClearMemory) where T : unmanaged
|
||||||
{
|
{
|
||||||
if (array.IsCreated == false || array.Length < size)
|
if (array.IsCreated == false || array.Length < size)
|
||||||
{
|
{
|
||||||
array.DisposeSafe();
|
array.MC2DisposeSafe();
|
||||||
array = new NativeArray<T>(size, allocator, options);
|
array = new NativeArray<T>(size, allocator, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NativeArrayをbyte[]に変換する
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="array"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static byte[] MC2ToRawBytes<T>(ref this NativeArray<T> array) where T : unmanaged
|
||||||
|
{
|
||||||
|
if (array.IsCreated == false || array.Length == 0)
|
||||||
|
return null;
|
||||||
|
var slice = new NativeSlice<T>(array).SliceConvert<byte>();
|
||||||
|
var bytes = new byte[slice.Length];
|
||||||
|
slice.CopyTo(bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// byte[]からNativeArrayを作成する
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="bytes"></param>
|
||||||
|
/// <param name="allocator"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static NativeArray<T> MC2FromRawBytes<T>(byte[] bytes, Allocator allocator = Allocator.Persistent) where T : unmanaged
|
||||||
|
{
|
||||||
|
if (bytes == null)
|
||||||
|
return new NativeArray<T>();
|
||||||
|
|
||||||
|
int structSize = Unity.Collections.LowLevel.Unsafe.UnsafeUtility.SizeOf<T>();
|
||||||
|
|
||||||
|
int length = bytes.Length / structSize;
|
||||||
|
var array = new NativeArray<T>(length, allocator);
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
using var byteArray = new NativeArray<byte>(bytes, Allocator.Temp);
|
||||||
|
//using var byteArray = new NativeArray<byte>(bytes, Allocator.Persistent);
|
||||||
|
var slice = new NativeSlice<byte>(byteArray).SliceConvert<T>();
|
||||||
|
slice.CopyTo(array);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,17 +2,21 @@
|
|||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System;
|
using System;
|
||||||
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
|
using Unity.Jobs;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NativeMultiHashMapの拡張メソッド
|
/// NativeMultiHashMapの拡張メソッド
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static class NativeMultiHashMapExtensions
|
public static class NativeMultiHashMapExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NativeMultiHashMapのキーに指定データが存在するか判定する
|
/// NativeParallelMultiHashMapのキーに指定データが存在するか判定する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TKey"></typeparam>
|
/// <typeparam name="TKey"></typeparam>
|
||||||
/// <typeparam name="TValue"></typeparam>
|
/// <typeparam name="TValue"></typeparam>
|
||||||
@ -21,9 +25,9 @@ namespace MagicaCloth2
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
#if MC2_COLLECTIONS_200
|
#if MC2_COLLECTIONS_200
|
||||||
public static bool Contains<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
public static bool MC2Contains<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
#else
|
#else
|
||||||
public static bool Contains<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : struct, IEquatable<TKey> where TValue : struct, IEquatable<TValue>
|
public static bool MC2Contains<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : struct, IEquatable<TKey> where TValue : struct, IEquatable<TValue>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
foreach (TValue val in map.GetValuesForKey(key))
|
foreach (TValue val in map.GetValuesForKey(key))
|
||||||
@ -35,7 +39,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NativeMultiHashMapのキーに対して重複なしのデータを追加する
|
/// NativeParallelMultiHashMapキーに対して重複なしのデータを追加する
|
||||||
/// すでにキーに同じデータが存在する場合は追加しない。
|
/// すでにキーに同じデータが存在する場合は追加しない。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TKey"></typeparam>
|
/// <typeparam name="TKey"></typeparam>
|
||||||
@ -44,26 +48,59 @@ namespace MagicaCloth2
|
|||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
#if MC2_COLLECTIONS_200
|
#if MC2_COLLECTIONS_200
|
||||||
public static void UniqueAdd<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
public static void MC2UniqueAdd<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
#else
|
#else
|
||||||
public static void UniqueAdd<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : struct, IEquatable<TKey> where TValue : struct, IEquatable<TValue>
|
public static void MC2UniqueAdd<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : struct, IEquatable<TKey> where TValue : struct, IEquatable<TValue>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (map.Contains(key, value) == false)
|
if (map.MC2Contains(key, value) == false)
|
||||||
{
|
{
|
||||||
map.Add(key, value);
|
map.Add(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NativeMultiHashMapのキーに存在するデータを削除する
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="map"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
#if MC2_COLLECTIONS_200
|
||||||
|
public static bool MC2RemoveValue<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
|
#else
|
||||||
|
public static bool MC2RemoveValue<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key, TValue value) where TKey : struct, IEquatable<TKey> where TValue : struct, IEquatable<TValue>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
NativeParallelMultiHashMapIterator<TKey> it;
|
||||||
|
TValue item;
|
||||||
|
if (map.TryGetFirstValue(key, out item, out it))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (item.Equals(value))
|
||||||
|
{
|
||||||
|
map.Remove(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (map.TryGetNextValue(out item, ref it));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 現在のキーのデータをFixedList512Bytesに変換して返す
|
/// 現在のキーのデータをFixedList512Bytesに変換して返す
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
#if MC2_COLLECTIONS_200
|
#if MC2_COLLECTIONS_200
|
||||||
public static FixedList512Bytes<TValue> ToFixedList512Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
public static FixedList512Bytes<TValue> MC2ToFixedList512Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
#else
|
#else
|
||||||
public static FixedList512Bytes<TValue> ToFixedList512Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : struct, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
public static FixedList512Bytes<TValue> MC2ToFixedList512Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : struct, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
var fixlist = new FixedList512Bytes<TValue>();
|
var fixlist = new FixedList512Bytes<TValue>();
|
||||||
@ -84,9 +121,9 @@ namespace MagicaCloth2
|
|||||||
/// <param name="index"></param>
|
/// <param name="index"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
#if MC2_COLLECTIONS_200
|
#if MC2_COLLECTIONS_200
|
||||||
public static FixedList128Bytes<TValue> ToFixedList128Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
public static FixedList128Bytes<TValue> MC2ToFixedList128Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
#else
|
#else
|
||||||
public static FixedList128Bytes<TValue> ToFixedList128Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : struct, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
public static FixedList128Bytes<TValue> MC2ToFixedList128Bytes<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map, TKey key) where TKey : struct, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
var fixlist = new FixedList128Bytes<TValue>();
|
var fixlist = new FixedList128Bytes<TValue>();
|
||||||
@ -100,5 +137,91 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
return fixlist;
|
return fixlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NativeParallelMultiHashMapをKeyとValueの配列に変換します
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="map"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
#if MC2_COLLECTIONS_200
|
||||||
|
public static (TKey[], TValue[]) MC2Serialize<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged
|
||||||
|
#else
|
||||||
|
public static (TKey[], TValue[]) MC2Serialize<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map) where TKey : struct, IEquatable<TKey> where TValue : struct
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (map.IsCreated == false || map.Count() == 0 || map.IsEmpty)
|
||||||
|
return (null, null);
|
||||||
|
|
||||||
|
using var keyNativeArray = map.GetKeyArray(Allocator.Persistent);
|
||||||
|
using var valueNativeArray = map.GetValueArray(Allocator.Persistent);
|
||||||
|
|
||||||
|
return (keyNativeArray.ToArray(), valueNativeArray.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// KeyとValueの配列からNativeParallelMultiHashMapを復元します
|
||||||
|
/// 高速化のためBurstを利用
|
||||||
|
/// ジェネリック型ジョブは明示的に型を指定する必要があるため型ごとに関数が発生します
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keyArray"></param>
|
||||||
|
/// <param name="valueArray"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static NativeParallelMultiHashMap<int2, ushort> MC2Deserialize(int2[] keyArray, ushort[] valueArray)
|
||||||
|
{
|
||||||
|
int keyCount = keyArray?.Length ?? 0;
|
||||||
|
int valueCount = valueArray?.Length ?? 0;
|
||||||
|
Debug.Assert(keyCount == valueCount);
|
||||||
|
var map = new NativeParallelMultiHashMap<int2, ushort>(keyCount, Allocator.Persistent);
|
||||||
|
if (keyCount > 0 && valueCount > 0)
|
||||||
|
{
|
||||||
|
using var keyNativeArray = new NativeArray<int2>(keyArray, Allocator.Persistent);
|
||||||
|
using var valueNativeArray = new NativeArray<ushort>(valueArray, Allocator.Persistent);
|
||||||
|
var job = new SetParallelMultiHashMapJob<int2, ushort>() { map = map, keyArray = keyNativeArray, valueArray = valueNativeArray };
|
||||||
|
job.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BurstCompile]
|
||||||
|
#if MC2_COLLECTIONS_200
|
||||||
|
struct SetParallelMultiHashMapJob<TKey, TValue> : IJob where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged
|
||||||
|
#else
|
||||||
|
struct SetParallelMultiHashMapJob<TKey, TValue> : IJob where TKey : struct, IEquatable<TKey> where TValue : struct
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public NativeParallelMultiHashMap<TKey, TValue> map;
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<TKey> keyArray;
|
||||||
|
[Unity.Collections.ReadOnly]
|
||||||
|
public NativeArray<TValue> valueArray;
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
int cnt = keyArray.Length;
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
map.Add(keyArray[i], valueArray[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NativeParallelMultiHashMapが確保されている場合のみDispose()する
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="map"></param>
|
||||||
|
#if MC2_COLLECTIONS_200
|
||||||
|
public static void MC2DisposeSafe<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map) where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
|
||||||
|
#else
|
||||||
|
public static void MC2DisposeSafe<TKey, TValue>(ref this NativeParallelMultiHashMap<TKey, TValue> map) where TKey : struct, IEquatable<TKey> where TValue : struct, IEquatable<TValue>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (map.IsCreated)
|
||||||
|
map.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="dataCount"></param>
|
/// <param name="dataCount"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
unsafe public static int InterlockedStartIndex(ref this NativeReference<int> counter, int dataCount)
|
unsafe public static int MC2InterlockedStartIndex(ref this NativeReference<int> counter, int dataCount)
|
||||||
{
|
{
|
||||||
int* cntPt = (int*)counter.GetUnsafePtr();
|
int* cntPt = (int*)counter.GetUnsafePtr();
|
||||||
int start = Interlocked.Add(ref *cntPt, dataCount) - dataCount;
|
int start = Interlocked.Add(ref *cntPt, dataCount) - dataCount;
|
||||||
|
|||||||
@ -2,25 +2,31 @@
|
|||||||
// Copyright (c) 2023 MagicaSoft.
|
// Copyright (c) 2023 MagicaSoft.
|
||||||
// https://magicasoft.jp
|
// https://magicasoft.jp
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MagicaCloth2
|
namespace MagicaCloth2
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 様々な処理の結果
|
/// 様々な処理の結果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[System.Serializable]
|
||||||
public struct ResultCode
|
public struct ResultCode
|
||||||
{
|
{
|
||||||
|
[SerializeField]
|
||||||
volatile Define.Result result;
|
volatile Define.Result result;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 警告:警告は1つのみ保持
|
/// 警告:警告は1つのみ保持
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[SerializeField]
|
||||||
volatile Define.Result warning;
|
volatile Define.Result warning;
|
||||||
|
|
||||||
public Define.Result Result => result;
|
public Define.Result Result => result;
|
||||||
|
|
||||||
public static ResultCode None => new ResultCode(Define.Result.None);
|
public static ResultCode None => new ResultCode(Define.Result.None);
|
||||||
public static ResultCode Empty => new ResultCode(Define.Result.Empty);
|
public static ResultCode Empty => new ResultCode(Define.Result.Empty);
|
||||||
|
public static ResultCode Success => new ResultCode(Define.Result.Success);
|
||||||
|
public static ResultCode Error => new ResultCode(Define.Result.Error);
|
||||||
|
|
||||||
public ResultCode(Define.Result initResult)
|
public ResultCode(Define.Result initResult)
|
||||||
{
|
{
|
||||||
@ -119,9 +125,13 @@ namespace MagicaCloth2
|
|||||||
case Define.Result.RenderSetup_Unreadable:
|
case Define.Result.RenderSetup_Unreadable:
|
||||||
return "It is necessary to turn on [Read/Write] in the model import settings.";
|
return "It is necessary to turn on [Read/Write] in the model import settings.";
|
||||||
case Define.Result.RenderSetup_Over65535vertices:
|
case Define.Result.RenderSetup_Over65535vertices:
|
||||||
return "Original mesh must have no more than 65,535 vertices";
|
return "Original mesh must have no more than 65,535 vertices.";
|
||||||
case Define.Result.SerializeData_Over31Renderers:
|
case Define.Result.SerializeData_Over31Renderers:
|
||||||
return $"There are {Define.System.MaxRendererCount} renderers that can be set.";
|
return $"There are {Define.System.MaxRendererCount} renderers that can be set.";
|
||||||
|
case Define.Result.Init_ScaleIsZero:
|
||||||
|
return "Component scale values is 0.";
|
||||||
|
case Define.Result.Init_NegativeScale:
|
||||||
|
return "Component has negative scale.";
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -133,6 +143,8 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
case Define.Result.RenderMesh_VertexWeightIs5BonesOrMore:
|
case Define.Result.RenderMesh_VertexWeightIs5BonesOrMore:
|
||||||
return "The source renderer mesh contains vertex weights that utilize more than 5 bones.\nA weight of 5 or more is invalid.";
|
return "The source renderer mesh contains vertex weights that utilize more than 5 bones.\nA weight of 5 or more is invalid.";
|
||||||
|
case Define.Result.Init_NonUniformScale:
|
||||||
|
return "Component scale values should be uniform.\nIf the scale is not uniform, there is a risk that it will not work properly.";
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace MagicaCloth2
|
|||||||
string name = string.Empty;
|
string name = string.Empty;
|
||||||
DateTime stime;
|
DateTime stime;
|
||||||
DateTime etime;
|
DateTime etime;
|
||||||
//bool isFinish;
|
bool isFinish;
|
||||||
|
|
||||||
public TimeSpan() { }
|
public TimeSpan() { }
|
||||||
|
|
||||||
@ -21,21 +21,23 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
stime = DateTime.Now;
|
stime = DateTime.Now;
|
||||||
|
isFinish = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
stime = DateTime.Now;
|
stime = DateTime.Now;
|
||||||
|
isFinish = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Finish()
|
public void Finish()
|
||||||
{
|
{
|
||||||
etime = DateTime.Now;
|
|
||||||
//if (isFinish == false)
|
|
||||||
//{
|
|
||||||
//etime = DateTime.Now;
|
//etime = DateTime.Now;
|
||||||
// isFinish = true;
|
if (isFinish == false)
|
||||||
//}
|
{
|
||||||
|
etime = DateTime.Now;
|
||||||
|
isFinish = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double TotalSeconds()
|
public double TotalSeconds()
|
||||||
@ -60,5 +62,10 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
Develop.DebugLog(this);
|
Develop.DebugLog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Log()
|
||||||
|
{
|
||||||
|
Develop.Log(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace MagicaCloth2
|
|||||||
/// <param name="rsetup"></param>
|
/// <param name="rsetup"></param>
|
||||||
/// <param name="ct"></param>
|
/// <param name="ct"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void ImportFrom(RenderSetupData rsetup)
|
public void ImportFrom(RenderSetupData rsetup, int uvChannel)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -44,7 +44,7 @@ namespace MagicaCloth2
|
|||||||
rsetup.transformIdList,
|
rsetup.transformIdList,
|
||||||
rsetup.transformParentIdList,
|
rsetup.transformParentIdList,
|
||||||
rsetup.rootTransformIdList,
|
rsetup.rootTransformIdList,
|
||||||
rsetup.transformLocalPositins,
|
rsetup.transformLocalPositions,
|
||||||
rsetup.transformLocalRotations,
|
rsetup.transformLocalRotations,
|
||||||
rsetup.transformPositions,
|
rsetup.transformPositions,
|
||||||
rsetup.transformRotations,
|
rsetup.transformRotations,
|
||||||
@ -68,7 +68,7 @@ namespace MagicaCloth2
|
|||||||
// メッシュタイプ
|
// メッシュタイプ
|
||||||
meshType = MeshType.NormalMesh;
|
meshType = MeshType.NormalMesh;
|
||||||
isBoneCloth = false;
|
isBoneCloth = false;
|
||||||
ImportMeshType(rsetup, indices);
|
ImportMeshType(rsetup, indices, uvChannel);
|
||||||
|
|
||||||
// スキニングメッシュでは1回スキニングを行いクロスローカル空間に姿勢を変換する
|
// スキニングメッシュでは1回スキニングを行いクロスローカル空間に姿勢を変換する
|
||||||
if (rsetup.hasBoneWeight)
|
if (rsetup.hasBoneWeight)
|
||||||
@ -129,7 +129,7 @@ namespace MagicaCloth2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rsetup"></param>
|
/// <param name="rsetup"></param>
|
||||||
/// <param name="transformIndices"></param>
|
/// <param name="transformIndices"></param>
|
||||||
void ImportMeshType(RenderSetupData rsetup, int[] transformIndices)
|
void ImportMeshType(RenderSetupData rsetup, int[] transformIndices, int uvChannel)
|
||||||
{
|
{
|
||||||
// root bone
|
// root bone
|
||||||
skinRootIndex = transformIndices[rsetup.skinRootBoneIndex];
|
skinRootIndex = transformIndices[rsetup.skinRootBoneIndex];
|
||||||
@ -155,6 +155,7 @@ namespace MagicaCloth2
|
|||||||
meshData.GetNormals(localNormals.GetNativeArray<Vector3>());
|
meshData.GetNormals(localNormals.GetNativeArray<Vector3>());
|
||||||
if (meshData.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent))
|
if (meshData.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.Tangent))
|
||||||
{
|
{
|
||||||
|
// 接線情報がメッシュに存在する
|
||||||
using var tangents = new NativeArray<Vector4>(vcnt, Allocator.TempJob);
|
using var tangents = new NativeArray<Vector4>(vcnt, Allocator.TempJob);
|
||||||
meshData.GetTangents(tangents);
|
meshData.GetTangents(tangents);
|
||||||
// tangent変換(Vector4->float3)
|
// tangent変換(Vector4->float3)
|
||||||
@ -162,6 +163,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// 接線情報がメッシュに存在しない
|
||||||
Develop.DebugLogWarning($"[{name}] Tangents not found!");
|
Develop.DebugLogWarning($"[{name}] Tangents not found!");
|
||||||
// tangentを生成する
|
// tangentを生成する
|
||||||
// このtangentは描画用では無く姿勢制御用なのである意味適当でも大丈夫
|
// このtangentは描画用では無く姿勢制御用なのである意味適当でも大丈夫
|
||||||
@ -174,11 +176,19 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
if (meshData.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.TexCoord0))
|
if (meshData.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.TexCoord0))
|
||||||
{
|
{
|
||||||
meshData.GetUVs(0, uv.GetNativeArray<Vector2>());
|
uvChannel = Mathf.Clamp(uvChannel, 0, 7);
|
||||||
|
UnityEngine.Rendering.VertexAttribute useTexCoord = UnityEngine.Rendering.VertexAttribute.TexCoord0 + uvChannel;
|
||||||
|
if (meshData.HasVertexAttribute(useTexCoord) == false)
|
||||||
|
{
|
||||||
|
Develop.LogWarning($"[{name}] UV{uvChannel} not found! => Use UV0.");
|
||||||
|
uvChannel = 0;
|
||||||
|
}
|
||||||
|
//Debug.Log($"Fetch UV:{uvChannel}");
|
||||||
|
meshData.GetUVs(uvChannel, uv.GetNativeArray<Vector2>());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[{name}] UV not found!");
|
Develop.LogWarning($"[{name}] UV0 not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 属性
|
// 属性
|
||||||
@ -439,7 +449,7 @@ namespace MagicaCloth2
|
|||||||
skinBoneTransformIndices.AddRange(transformIndices, rsetup.skinBoneCount);
|
skinBoneTransformIndices.AddRange(transformIndices, rsetup.skinBoneCount);
|
||||||
skinBoneBindPoses.AddRange(vcnt);
|
skinBoneBindPoses.AddRange(vcnt);
|
||||||
|
|
||||||
// Transformの情報をローカル空間に変換し頂点情報に割り当てる
|
// Transformの情報をクロスローカル空間に変換し頂点情報に割り当てる
|
||||||
// およびバインドポーズの算出
|
// およびバインドポーズの算出
|
||||||
var WtoL = rsetup.initRenderWorldtoLocal;
|
var WtoL = rsetup.initRenderWorldtoLocal;
|
||||||
var LtoW = rsetup.initRenderLocalToWorld;
|
var LtoW = rsetup.initRenderLocalToWorld;
|
||||||
@ -899,13 +909,17 @@ namespace MagicaCloth2
|
|||||||
quaternion rot = transformRotations[vindex];
|
quaternion rot = transformRotations[vindex];
|
||||||
float3 scl = transformScales[vindex];
|
float3 scl = transformScales[vindex];
|
||||||
|
|
||||||
// トランスフォーム姿勢をローカル空間に変換する
|
// トランスフォーム姿勢をクロスローカル空間に変換する
|
||||||
|
// オリジナル
|
||||||
|
#if true
|
||||||
float3 lpos = MathUtility.InverseTransformPoint(pos, WtoL);
|
float3 lpos = MathUtility.InverseTransformPoint(pos, WtoL);
|
||||||
float3 lnor, ltan;
|
float3 lnor, ltan;
|
||||||
lnor = math.mul(rot, math.up());
|
lnor = math.mul(rot, math.up());
|
||||||
ltan = math.mul(rot, math.forward());
|
ltan = math.mul(rot, math.forward());
|
||||||
lnor = MathUtility.InverseTransformDirection(lnor, WtoL);
|
lnor = MathUtility.InverseTransformDirection(lnor, WtoL);
|
||||||
ltan = MathUtility.InverseTransformDirection(ltan, WtoL);
|
ltan = MathUtility.InverseTransformDirection(ltan, WtoL);
|
||||||
|
#endif
|
||||||
|
//Debug.Log($"Import [{vindex}] lpos:{lpos}, lnor:{lnor}, ltan:{ltan}");
|
||||||
|
|
||||||
localPositions[vindex] = lpos;
|
localPositions[vindex] = lpos;
|
||||||
localNormals[vindex] = lnor;
|
localNormals[vindex] = lnor;
|
||||||
@ -928,7 +942,7 @@ namespace MagicaCloth2
|
|||||||
/// レンダーデータからインポートする
|
/// レンダーデータからインポートする
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="renderData"></param>
|
/// <param name="renderData"></param>
|
||||||
public void ImportFrom(RenderData renderData)
|
public void ImportFrom(RenderData renderData, int uvChannel)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -938,7 +952,7 @@ namespace MagicaCloth2
|
|||||||
throw new MagicaClothProcessingException();
|
throw new MagicaClothProcessingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportFrom(renderData.setupData);
|
ImportFrom(renderData.setupData, uvChannel);
|
||||||
}
|
}
|
||||||
catch (MagicaClothProcessingException)
|
catch (MagicaClothProcessingException)
|
||||||
{
|
{
|
||||||
@ -1764,16 +1778,6 @@ namespace MagicaCloth2
|
|||||||
return transformData.GetTransformFromIndex(centerTransformIndex);
|
return transformData.GetTransformFromIndex(centerTransformIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float4x4 GetCenterLocalToWorldMatrix()
|
|
||||||
{
|
|
||||||
return transformData.GetLocalToWorldMatrix(centerTransformIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float4x4 GetCenterWorldToLocalMatrix()
|
|
||||||
{
|
|
||||||
return transformData.GetWorldToLocalMatrix(centerTransformIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// カスタムスキニング用ボーンを登録する
|
/// カスタムスキニング用ボーンを登録する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1828,6 +1832,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
|
#if false
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UnityMeshに出力する(メインスレッドのみ)
|
/// UnityMeshに出力する(メインスレッドのみ)
|
||||||
/// ※ほぼデバッグ用
|
/// ※ほぼデバッグ用
|
||||||
@ -1893,93 +1898,6 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/// <summary>
|
|
||||||
/// メッシュの基準トランスフォームを返す
|
|
||||||
/// 通常はレンダラーのtransform
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Transform ExportCenterTransform()
|
|
||||||
{
|
|
||||||
return transformData.GetTransformFromIndex(centerTransformIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Transform ExportSkinRootBone()
|
|
||||||
{
|
|
||||||
return transformData.GetTransformFromIndex(skinRootIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// メッシュのスキニング用ボーンリストを返す
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public List<Transform> ExportSkinningBones()
|
|
||||||
{
|
|
||||||
var sbones = new List<Transform>(SkinBoneCount);
|
|
||||||
for (int i = 0; i < SkinBoneCount; i++)
|
|
||||||
{
|
|
||||||
sbones.Add(transformData.GetTransformFromIndex(skinBoneTransformIndices[i]));
|
|
||||||
}
|
|
||||||
return sbones;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// メッシュのバウンディングボックスを返す
|
|
||||||
/// スキニングの場合はスキニングルートボーンからのバウンディングボックスとなる
|
|
||||||
/// それ以外はセンターボーンからのバウンディングボックスとなる
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
/*public Bounds ExportBounds()
|
|
||||||
{
|
|
||||||
float3 offset = 0;
|
|
||||||
if (skinRootIndex >= 0 && centerTransformIndex != skinRootIndex)
|
|
||||||
{
|
|
||||||
// スキニングのルートボーンが別の場合
|
|
||||||
// ちょっと面倒
|
|
||||||
float3 wmin = transformData.TransformPoint(centerTransformIndex, boundingBox.Value.Min);
|
|
||||||
float3 wmax = transformData.TransformPoint(centerTransformIndex, boundingBox.Value.Max);
|
|
||||||
float3 lmin = transformData.InverseTransformPoint(skinRootIndex, wmin);
|
|
||||||
float3 lmax = transformData.InverseTransformPoint(skinRootIndex, wmax);
|
|
||||||
float3 cen = (lmax + lmin) * 0.5f;
|
|
||||||
float3 size = math.abs(lmax - lmin);
|
|
||||||
return new Bounds(cen, size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new Bounds(boundingBox.Value.Center, boundingBox.Value.Extents);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 現在のメッシュをレンダラーに反映させる(主にデバッグ用)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ren"></param>
|
|
||||||
public Mesh ToRenderer(Renderer ren)
|
|
||||||
{
|
|
||||||
Mesh mesh = null;
|
|
||||||
if (IsSuccess == false)
|
|
||||||
return mesh;
|
|
||||||
|
|
||||||
if (ren is MeshRenderer)
|
|
||||||
{
|
|
||||||
mesh = ExportToMesh();
|
|
||||||
var filter = ren.GetComponent<MeshFilter>();
|
|
||||||
filter.mesh = mesh;
|
|
||||||
}
|
|
||||||
else if (ren is SkinnedMeshRenderer)
|
|
||||||
{
|
|
||||||
var sren = ren as SkinnedMeshRenderer;
|
|
||||||
mesh = ExportToMesh(true);
|
|
||||||
var rootBone = ExportSkinRootBone();
|
|
||||||
var skinBones = ExportSkinningBones().ToArray();
|
|
||||||
|
|
||||||
sren.rootBone = rootBone;
|
|
||||||
sren.bones = skinBones;
|
|
||||||
sren.sharedMesh = mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -237,6 +237,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BurstCompile]
|
||||||
struct Mapping_CalcDirectWeightJob : IJob
|
struct Mapping_CalcDirectWeightJob : IJob
|
||||||
{
|
{
|
||||||
// data
|
// data
|
||||||
@ -282,10 +283,10 @@ namespace MagicaCloth2
|
|||||||
// ウエイトバッファ
|
// ウエイトバッファ
|
||||||
var weights = new ExCostSortedList4(-1);
|
var weights = new ExCostSortedList4(-1);
|
||||||
|
|
||||||
stack.Push(pindex);
|
stack.MC2Push(pindex);
|
||||||
while (stack.IsEmpty == false)
|
while (stack.IsEmpty == false)
|
||||||
{
|
{
|
||||||
pindex = stack.Pop();
|
pindex = stack.MC2Pop();
|
||||||
|
|
||||||
if (useSet.Contains(pindex))
|
if (useSet.Contains(pindex))
|
||||||
continue;
|
continue;
|
||||||
@ -305,7 +306,7 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
// 次の接続
|
// 次の接続
|
||||||
DataUtility.Unpack12_20(proxyVertexToVertexIndexArray[pindex], out var dcnt, out var dstart);
|
DataUtility.Unpack12_20(proxyVertexToVertexIndexArray[pindex], out var dcnt, out var dstart);
|
||||||
for (int i = 0; i < dcnt && stack.IsCapacity() == false; i++)
|
for (int i = 0; i < dcnt && stack.MC2IsCapacity() == false; i++)
|
||||||
{
|
{
|
||||||
ushort tindex = proxyVertexToVertexDataArray[dstart + i];
|
ushort tindex = proxyVertexToVertexDataArray[dstart + i];
|
||||||
|
|
||||||
@ -317,7 +318,7 @@ namespace MagicaCloth2
|
|||||||
if (dist > weightLength)
|
if (dist > weightLength)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
stack.Push(tindex);
|
stack.MC2Push(tindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,13 +94,13 @@ namespace MagicaCloth2
|
|||||||
if (edgeToTriangleList.ContainsKey(edge))
|
if (edgeToTriangleList.ContainsKey(edge))
|
||||||
{
|
{
|
||||||
var tlist = edgeToTriangleList[edge];
|
var tlist = edgeToTriangleList[edge];
|
||||||
tlist.Set(i);
|
tlist.MC2Set(i);
|
||||||
edgeToTriangleList[edge] = tlist;
|
edgeToTriangleList[edge] = tlist;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var tlist = new FixedList128Bytes<int>();
|
var tlist = new FixedList128Bytes<int>();
|
||||||
tlist.Set(i);
|
tlist.MC2Set(i);
|
||||||
edgeToTriangleList.Add(edge, tlist);
|
edgeToTriangleList.Add(edge, tlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -346,9 +346,6 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
center = center,
|
center = center,
|
||||||
localPositions = localPositions.GetNativeArray(),
|
localPositions = localPositions.GetNativeArray(),
|
||||||
vertexParentIndices = vertexParentIndices,
|
|
||||||
vertexChildIndexArray = vertexChildIndexArray,
|
|
||||||
vertexChildDataArray = vertexChildDataArray,
|
|
||||||
|
|
||||||
localNormals = localNormals.GetNativeArray(),
|
localNormals = localNormals.GetNativeArray(),
|
||||||
localTangents = localTangents.GetNativeArray(),
|
localTangents = localTangents.GetNativeArray(),
|
||||||
@ -356,96 +353,7 @@ namespace MagicaCloth2
|
|||||||
};
|
};
|
||||||
job1.Run(vcnt);
|
job1.Run(vcnt);
|
||||||
}
|
}
|
||||||
#if false // ★どうもうまくいかないので一旦停止!
|
|
||||||
// 頂点ウエイトから
|
|
||||||
else if (mode == NormalAlignmentSettings.AlignmentMode.BoneWeight)
|
|
||||||
{
|
|
||||||
var job2 = new ProxyNormalWeightAdjustmentJob()
|
|
||||||
{
|
|
||||||
WtoL = initWorldToLocal,
|
|
||||||
localPositions = localPositions.GetNativeArray(),
|
|
||||||
boneWeights = boneWeights.GetNativeArray(),
|
|
||||||
|
|
||||||
transformPositionArray = transformData.positionArray.GetNativeArray(),
|
|
||||||
|
|
||||||
localNormals = localNormals.GetNativeArray(),
|
|
||||||
localTangents = localTangents.GetNativeArray(),
|
|
||||||
normalAdjustmentRotations = normalAdjustmentRotations,
|
|
||||||
};
|
|
||||||
job2.Run(vcnt);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if false
|
|
||||||
[BurstCompile]
|
|
||||||
struct ProxyNormalWeightAdjustmentJob : IJobParallelFor
|
|
||||||
{
|
|
||||||
public float4x4 WtoL;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> localPositions;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<VirtualMeshBoneWeight> boneWeights;
|
|
||||||
|
|
||||||
// transform
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<float3> transformPositionArray;
|
|
||||||
|
|
||||||
// out
|
|
||||||
//[Unity.Collections.WriteOnly]
|
|
||||||
public NativeArray<float3> localNormals;
|
|
||||||
//[Unity.Collections.WriteOnly]
|
|
||||||
public NativeArray<float3> localTangents;
|
|
||||||
[Unity.Collections.WriteOnly]
|
|
||||||
public NativeArray<quaternion> normalAdjustmentRotations;
|
|
||||||
|
|
||||||
public void Execute(int vindex)
|
|
||||||
{
|
|
||||||
var lpos = localPositions[vindex];
|
|
||||||
var bw = boneWeights[vindex];
|
|
||||||
|
|
||||||
// 現在の回転
|
|
||||||
var lrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]);
|
|
||||||
|
|
||||||
// 影響するボーンへの方向をまとめる
|
|
||||||
float3 bv = 0;
|
|
||||||
int bcnt = bw.Count;
|
|
||||||
if (bcnt == 0)
|
|
||||||
return;
|
|
||||||
for (int i = 0; i < bcnt; i++)
|
|
||||||
{
|
|
||||||
var bonePos = math.transform(WtoL, transformPositionArray[bw.boneIndices[i]]);
|
|
||||||
//var v = transformPositionArray[bw.boneIndices[i]] - lpos;
|
|
||||||
var v = lpos - bonePos;
|
|
||||||
v = math.normalizesafe(v, float3.zero);
|
|
||||||
v *= bw.weights[i];
|
|
||||||
bv += v;
|
|
||||||
}
|
|
||||||
if (math.lengthsq(bv) < Define.System.Epsilon)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 法線確定
|
|
||||||
float3 n = math.normalize(bv);
|
|
||||||
|
|
||||||
// 法線をもとに接線を計算する
|
|
||||||
var lnor = localNormals[vindex];
|
|
||||||
var ltan = localTangents[vindex];
|
|
||||||
var dotNormal = math.dot(n, lnor);
|
|
||||||
var dotTangent = math.dot(n, ltan);
|
|
||||||
float3 tv = dotNormal < dotTangent ? lnor : ltan;
|
|
||||||
float3 tan = math.cross(tv, n);
|
|
||||||
|
|
||||||
//localNormals[vindex] = tan;
|
|
||||||
//localTangents[vindex] = n;
|
|
||||||
localNormals[vindex] = n;
|
|
||||||
localTangents[vindex] = tan;
|
|
||||||
var nrot = MathUtility.ToRotation(n, tan);
|
|
||||||
|
|
||||||
// 補正用回転を算出し格納する
|
|
||||||
normalAdjustmentRotations[vindex] = math.mul(math.inverse(lrot), nrot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct ProxyNormalRadiationAdjustmentJob : IJobParallelFor
|
struct ProxyNormalRadiationAdjustmentJob : IJobParallelFor
|
||||||
@ -453,12 +361,6 @@ namespace MagicaCloth2
|
|||||||
public float3 center;
|
public float3 center;
|
||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
public NativeArray<float3> localPositions;
|
public NativeArray<float3> localPositions;
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<int> vertexParentIndices;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<uint> vertexChildIndexArray;
|
|
||||||
[Unity.Collections.ReadOnly]
|
|
||||||
public NativeArray<ushort> vertexChildDataArray;
|
|
||||||
|
|
||||||
// out
|
// out
|
||||||
public NativeArray<float3> localNormals;
|
public NativeArray<float3> localNormals;
|
||||||
@ -472,57 +374,32 @@ namespace MagicaCloth2
|
|||||||
var v = lpos - center;
|
var v = lpos - center;
|
||||||
if (math.length(v) < Define.System.Epsilon)
|
if (math.length(v) < Define.System.Epsilon)
|
||||||
return;
|
return;
|
||||||
v = math.normalize(v);
|
|
||||||
|
// 指定されたセンターからの放射方向に法線を変更する
|
||||||
|
var n = math.normalize(v);
|
||||||
|
|
||||||
// 現在の回転
|
// 現在の回転
|
||||||
var lrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]);
|
var ln = localNormals[vindex];
|
||||||
|
var lt = localTangents[vindex];
|
||||||
|
var lrot = MathUtility.ToRotation(ln, lt);
|
||||||
|
|
||||||
// 子がいる場合は子へのベクトルから算出
|
// 接線を補正する
|
||||||
var nrot = lrot;
|
float dot = math.dot(n, lt);
|
||||||
int pindex = vertexParentIndices[vindex];
|
if (dot < 0.99f)
|
||||||
var pack = vertexChildIndexArray[vindex];
|
|
||||||
DataUtility.Unpack12_20(pack, out var dcnt, out var dstart);
|
|
||||||
if (dcnt > 0)
|
|
||||||
{
|
{
|
||||||
float3 cv = 0;
|
float3 bn = math.normalize(math.cross(n, lt));
|
||||||
for (int i = 0; i < dcnt; i++)
|
lt = math.normalize(math.cross(bn, n));
|
||||||
{
|
|
||||||
int cindex = vertexChildDataArray[dstart + i];
|
|
||||||
cv += localPositions[cindex] - lpos;
|
|
||||||
}
|
}
|
||||||
if (math.lengthsq(cv) > Define.System.Epsilon)
|
else
|
||||||
{
|
{
|
||||||
cv = math.normalize(cv);
|
// 元の接線と新しい法線が同じベクトルの場合は、従法線から新しい接線を算出する
|
||||||
float3 n = math.cross(cv, v);
|
var lbn = math.normalize(math.cross(ln, lt));
|
||||||
n = math.cross(n, cv);
|
lt = math.normalize(math.cross(lbn, n));
|
||||||
|
}
|
||||||
|
|
||||||
if (math.lengthsq(n) > Define.System.Epsilon)
|
|
||||||
{
|
|
||||||
n = math.normalize(n);
|
|
||||||
localNormals[vindex] = n;
|
localNormals[vindex] = n;
|
||||||
localTangents[vindex] = cv;
|
localTangents[vindex] = lt;
|
||||||
nrot = MathUtility.ToRotation(n, cv);
|
var nrot = MathUtility.ToRotation(n, lt);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 子がいなく親がいる場合は親からのベクトルから算出
|
|
||||||
else if (pindex >= 0)
|
|
||||||
{
|
|
||||||
var ppos = localPositions[pindex];
|
|
||||||
var w = lpos - ppos;
|
|
||||||
w = math.normalize(w);
|
|
||||||
|
|
||||||
float3 n = math.cross(w, v);
|
|
||||||
n = math.cross(n, w);
|
|
||||||
|
|
||||||
if (math.lengthsq(n) > Define.System.Epsilon)
|
|
||||||
{
|
|
||||||
n = math.normalize(n);
|
|
||||||
localNormals[vindex] = n;
|
|
||||||
localTangents[vindex] = w;
|
|
||||||
nrot = MathUtility.ToRotation(n, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 補正用回転を算出し格納する
|
// 補正用回転を算出し格納する
|
||||||
normalAdjustmentRotations[vindex] = math.mul(math.inverse(lrot), nrot);
|
normalAdjustmentRotations[vindex] = math.mul(math.inverse(lrot), nrot);
|
||||||
@ -837,11 +714,11 @@ namespace MagicaCloth2
|
|||||||
var vset_z = (ptr + tri.z);
|
var vset_z = (ptr + tri.z);
|
||||||
|
|
||||||
if (vset_x->Length < 7)
|
if (vset_x->Length < 7)
|
||||||
vset_x->Set(tindex);
|
vset_x->MC2Set(tindex);
|
||||||
if (vset_y->Length < 7)
|
if (vset_y->Length < 7)
|
||||||
vset_y->Set(tindex);
|
vset_y->MC2Set(tindex);
|
||||||
if (vset_z->Length < 7)
|
if (vset_z->Length < 7)
|
||||||
vset_z->Set(tindex);
|
vset_z->MC2Set(tindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1103,7 +980,10 @@ namespace MagicaCloth2
|
|||||||
// 頂点のローカル回転
|
// 頂点のローカル回転
|
||||||
var vrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]);
|
var vrot = MathUtility.ToRotation(localNormals[vindex], localTangents[vindex]);
|
||||||
|
|
||||||
vertexToTransformRotations[vindex] = math.mul(math.inverse(vrot), trot);
|
// 頂点ローカル回転をトランスフォームローカル回転に復元する回転を求める
|
||||||
|
var toRot = math.mul(math.inverse(vrot), trot);
|
||||||
|
|
||||||
|
vertexToTransformRotations[vindex] = toRot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1131,7 +1011,7 @@ namespace MagicaCloth2
|
|||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
int2 edge = edges[j];
|
int2 edge = edges[j];
|
||||||
edgeToTriangles.UniqueAdd(edge, (ushort)i);
|
edgeToTriangles.MC2UniqueAdd(edge, (ushort)i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1157,13 +1037,13 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public void Execute(int vindex)
|
public void Execute(int vindex)
|
||||||
{
|
{
|
||||||
float3 pos = localPositions[vindex];
|
float3 lpos = localPositions[vindex];
|
||||||
var nor = localNormals[vindex];
|
var lnor = localNormals[vindex];
|
||||||
var tan = localTangents[vindex];
|
var ltan = localTangents[vindex];
|
||||||
|
|
||||||
// マッピング用の頂点バインドポーズを求める
|
// マッピング用の頂点バインドポーズを求める
|
||||||
quaternion rot = MathUtility.ToRotation(nor, tan);
|
quaternion rot = MathUtility.ToRotation(lnor, ltan);
|
||||||
vertexBindPosePositions[vindex] = -pos;
|
vertexBindPosePositions[vindex] = -lpos;
|
||||||
vertexBindPoseRotations[vindex] = math.inverse(rot);
|
vertexBindPoseRotations[vindex] = math.inverse(rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1192,12 +1072,12 @@ namespace MagicaCloth2
|
|||||||
ushort y = (ushort)tri.y;
|
ushort y = (ushort)tri.y;
|
||||||
ushort z = (ushort)tri.z;
|
ushort z = (ushort)tri.z;
|
||||||
|
|
||||||
vertexToVertexMap.UniqueAdd(tri.x, y);
|
vertexToVertexMap.MC2UniqueAdd(tri.x, y);
|
||||||
vertexToVertexMap.UniqueAdd(tri.x, z);
|
vertexToVertexMap.MC2UniqueAdd(tri.x, z);
|
||||||
vertexToVertexMap.UniqueAdd(tri.y, x);
|
vertexToVertexMap.MC2UniqueAdd(tri.y, x);
|
||||||
vertexToVertexMap.UniqueAdd(tri.y, z);
|
vertexToVertexMap.MC2UniqueAdd(tri.y, z);
|
||||||
vertexToVertexMap.UniqueAdd(tri.z, x);
|
vertexToVertexMap.MC2UniqueAdd(tri.z, x);
|
||||||
vertexToVertexMap.UniqueAdd(tri.z, y);
|
vertexToVertexMap.MC2UniqueAdd(tri.z, y);
|
||||||
|
|
||||||
edgeSet.Add(DataUtility.PackInt2(tri.xy));
|
edgeSet.Add(DataUtility.PackInt2(tri.xy));
|
||||||
edgeSet.Add(DataUtility.PackInt2(tri.yz));
|
edgeSet.Add(DataUtility.PackInt2(tri.yz));
|
||||||
@ -1226,8 +1106,8 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
int2 line = lines[i];
|
int2 line = lines[i];
|
||||||
|
|
||||||
vertexToVertexMap.UniqueAdd(line.x, (ushort)line.y);
|
vertexToVertexMap.MC2UniqueAdd(line.x, (ushort)line.y);
|
||||||
vertexToVertexMap.UniqueAdd(line.y, (ushort)line.x);
|
vertexToVertexMap.MC2UniqueAdd(line.y, (ushort)line.x);
|
||||||
|
|
||||||
edgeSet.Add(DataUtility.PackInt2(line));
|
edgeSet.Add(DataUtility.PackInt2(line));
|
||||||
}
|
}
|
||||||
@ -1268,10 +1148,10 @@ namespace MagicaCloth2
|
|||||||
struct SkinningBoneInfo
|
struct SkinningBoneInfo
|
||||||
{
|
{
|
||||||
//public int transformIndex;
|
//public int transformIndex;
|
||||||
public int startTransformIndex;
|
public int parentTransformIndex;
|
||||||
public float3 startPos;
|
public float3 parentPos;
|
||||||
public int endTransformIndex;
|
public int childTransformIndex;
|
||||||
public float3 endPos;
|
public float3 childPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1282,39 +1162,6 @@ namespace MagicaCloth2
|
|||||||
if (CustomSkinningBoneCount == 0)
|
if (CustomSkinningBoneCount == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if false
|
|
||||||
// ボーン情報の構築
|
|
||||||
using var boneInfoList = new NativeList<SkinningBoneInfo>(CustomSkinningBoneCount, Allocator.Persistent);
|
|
||||||
for (int i = 0; i < CustomSkinningBoneCount; i++)
|
|
||||||
{
|
|
||||||
int tindex = customSkinningBoneIndices[i];
|
|
||||||
if (tindex == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// 登録
|
|
||||||
var info = new SkinningBoneInfo();
|
|
||||||
info.transformIndex = tindex;
|
|
||||||
info.startPos = bones[i].localPosition;
|
|
||||||
boneInfoList.Add(info);
|
|
||||||
Debug.Log($"[{boneInfoList.Length - 1}] {i}, tindex:{tindex}");
|
|
||||||
}
|
|
||||||
if (boneInfoList.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 頂点ごとにカスタムスキニングウエイトを算出
|
|
||||||
var job = new Proxy_CalcCustomSkinningWeightsJob2()
|
|
||||||
{
|
|
||||||
distanceReduction = setting.distanceReduction,
|
|
||||||
distancePow = setting.distancePow,
|
|
||||||
|
|
||||||
//attributes = attributes.GetNativeArray(),
|
|
||||||
localPositions = localPositions.GetNativeArray(),
|
|
||||||
boneInfoList = boneInfoList,
|
|
||||||
boneWeights = boneWeights.GetNativeArray(),
|
|
||||||
};
|
|
||||||
job.Run(VertexCount);
|
|
||||||
#endif
|
|
||||||
#if true
|
|
||||||
// ボーン情報の構築
|
// ボーン情報の構築
|
||||||
using var boneInfoList = new NativeList<SkinningBoneInfo>(CustomSkinningBoneCount * 2, Allocator.Persistent);
|
using var boneInfoList = new NativeList<SkinningBoneInfo>(CustomSkinningBoneCount * 2, Allocator.Persistent);
|
||||||
for (int i = 0; i < CustomSkinningBoneCount; i++)
|
for (int i = 0; i < CustomSkinningBoneCount; i++)
|
||||||
@ -1322,6 +1169,9 @@ namespace MagicaCloth2
|
|||||||
int tindex = customSkinningBoneIndices[i];
|
int tindex = customSkinningBoneIndices[i];
|
||||||
if (tindex == -1)
|
if (tindex == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#if MC2_CUSTOM_SKINNING_V1
|
||||||
|
// 旧
|
||||||
int pid = bones[i].pid;
|
int pid = bones[i].pid;
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -1330,16 +1180,22 @@ namespace MagicaCloth2
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// ボーンライン情報の作成
|
// ボーンライン情報の作成
|
||||||
|
// localPositonはクロス空間での座標に変換済み
|
||||||
var info = new SkinningBoneInfo();
|
var info = new SkinningBoneInfo();
|
||||||
//info.transformIndex = customSkinningBoneIndices[pindex];
|
info.parentTransformIndex = customSkinningBoneIndices[pindex];
|
||||||
info.startTransformIndex = customSkinningBoneIndices[pindex];
|
info.parentPos = bones[pindex].localPosition;
|
||||||
info.startPos = bones[pindex].localPosition;
|
info.childTransformIndex = tindex;
|
||||||
info.endTransformIndex = tindex;
|
info.childPos = bones[i].localPosition;
|
||||||
info.endPos = bones[i].localPosition;
|
|
||||||
|
|
||||||
// 距離がほぼ0なら無効
|
// 距離がほぼ0なら無効
|
||||||
if (math.distance(info.startPos, info.endPos) < Define.System.Epsilon)
|
if (math.distance(info.parentPos, info.childPos) < Define.System.Epsilon)
|
||||||
continue;
|
continue;
|
||||||
|
#else
|
||||||
|
// V2
|
||||||
|
var info = new SkinningBoneInfo();
|
||||||
|
info.childTransformIndex = tindex;
|
||||||
|
info.childPos = bones[i].localPosition;
|
||||||
|
#endif
|
||||||
|
|
||||||
// 登録
|
// 登録
|
||||||
boneInfoList.Add(info);
|
boneInfoList.Add(info);
|
||||||
@ -1349,12 +1205,11 @@ namespace MagicaCloth2
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// 頂点ごとにカスタムスキニングウエイトを算出
|
// 頂点ごとにカスタムスキニングウエイトを算出
|
||||||
|
#if MC2_CUSTOM_SKINNING_V1
|
||||||
|
// 旧
|
||||||
var job = new Proxy_CalcCustomSkinningWeightsJob()
|
var job = new Proxy_CalcCustomSkinningWeightsJob()
|
||||||
{
|
{
|
||||||
isBoneCloth = isBoneCloth,
|
isBoneCloth = isBoneCloth,
|
||||||
//angularAttenuation = setting.angularAttenuation,
|
|
||||||
//distanceReduction = setting.distanceReduction,
|
|
||||||
//distancePow = setting.distancePow,
|
|
||||||
angularAttenuation = Define.System.CustomSkinningAngularAttenuation,
|
angularAttenuation = Define.System.CustomSkinningAngularAttenuation,
|
||||||
distanceReduction = Define.System.CustomSkinningDistanceReduction,
|
distanceReduction = Define.System.CustomSkinningDistanceReduction,
|
||||||
distancePow = Define.System.CustomSkinningDistancePow,
|
distancePow = Define.System.CustomSkinningDistancePow,
|
||||||
@ -1364,19 +1219,36 @@ namespace MagicaCloth2
|
|||||||
boneInfoList = boneInfoList,
|
boneInfoList = boneInfoList,
|
||||||
boneWeights = boneWeights.GetNativeArray(),
|
boneWeights = boneWeights.GetNativeArray(),
|
||||||
};
|
};
|
||||||
job.Run(VertexCount);
|
#else
|
||||||
|
// V2
|
||||||
|
var job = new Proxy_CalcCustomSkinningWeightsJobV2()
|
||||||
|
{
|
||||||
|
isBoneCloth = isBoneCloth,
|
||||||
|
angularAttenuation = Define.System.CustomSkinningAngularAttenuation,
|
||||||
|
distanceReduction = Define.System.CustomSkinningDistanceReduction,
|
||||||
|
distancePow = Define.System.CustomSkinningDistancePow,
|
||||||
|
|
||||||
|
attributes = attributes.GetNativeArray(),
|
||||||
|
localPositions = localPositions.GetNativeArray(),
|
||||||
|
boneInfoList = boneInfoList,
|
||||||
|
boneWeights = boneWeights.GetNativeArray(),
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
job.Run(VertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if false
|
#if !MC2_CUSTOM_SKINNING_V1
|
||||||
|
// V2
|
||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct Proxy_CalcCustomSkinningWeightsJob2 : IJobParallelFor
|
struct Proxy_CalcCustomSkinningWeightsJobV2 : IJobParallelFor
|
||||||
{
|
{
|
||||||
|
public bool isBoneCloth;
|
||||||
|
public float angularAttenuation;
|
||||||
public float distanceReduction;
|
public float distanceReduction;
|
||||||
public float distancePow;
|
public float distancePow;
|
||||||
|
|
||||||
//[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
//public NativeArray<VertexAttribute> attributes;
|
public NativeArray<VertexAttribute> attributes;
|
||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
public NativeArray<float3> localPositions;
|
public NativeArray<float3> localPositions;
|
||||||
[Unity.Collections.ReadOnly]
|
[Unity.Collections.ReadOnly]
|
||||||
@ -1384,12 +1256,12 @@ namespace MagicaCloth2
|
|||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<VirtualMeshBoneWeight> boneWeights;
|
public NativeArray<VirtualMeshBoneWeight> boneWeights;
|
||||||
|
|
||||||
|
// プロキシメッシュ頂点ごと
|
||||||
public void Execute(int vindex)
|
public void Execute(int vindex)
|
||||||
{
|
{
|
||||||
// 固定は無効(※この時点ではまだ属性がない!)
|
// 移動属性のみ
|
||||||
//var attr = attributes[vindex];
|
if (attributes[vindex].IsDontMove())
|
||||||
//if (attr.IsMove() == false)
|
return;
|
||||||
// return;
|
|
||||||
|
|
||||||
var lpos = localPositions[vindex];
|
var lpos = localPositions[vindex];
|
||||||
|
|
||||||
@ -1398,12 +1270,14 @@ namespace MagicaCloth2
|
|||||||
for (int i = 0; i < bcnt; i++)
|
for (int i = 0; i < bcnt; i++)
|
||||||
{
|
{
|
||||||
var binfo = boneInfoList[i];
|
var binfo = boneInfoList[i];
|
||||||
|
var bpos = binfo.childPos;
|
||||||
|
int boneIndex = binfo.childTransformIndex;
|
||||||
|
|
||||||
// 距離
|
// 距離
|
||||||
float dist = math.distance(lpos, binfo.startPos);
|
var v = lpos - bpos;
|
||||||
|
float dist = math.length(v);
|
||||||
|
|
||||||
// 登録。すでに登録済みならばdistがより小さい場合のみ再登録
|
// 登録。すでに登録済みならばdistがより小さい場合のみ再登録
|
||||||
int boneIndex = binfo.transformIndex;
|
|
||||||
int nowIndex = costList.indexOf(boneIndex);
|
int nowIndex = costList.indexOf(boneIndex);
|
||||||
if (nowIndex >= 0)
|
if (nowIndex >= 0)
|
||||||
{
|
{
|
||||||
@ -1417,34 +1291,44 @@ namespace MagicaCloth2
|
|||||||
costList.Add(dist, boneIndex);
|
costList.Add(dist, boneIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ウエイト算出
|
// (1)最小距離のn%を減算する
|
||||||
// (0)最小距離のn%を減算する
|
|
||||||
int cnt = costList.Count;
|
int cnt = costList.Count;
|
||||||
//const float lengthWeight = 0.8f;
|
float mindist = costList.MinCost * distanceReduction; // 0.6
|
||||||
float mindist = costList.MinCost * distanceReduction;
|
for (int i = 0; i < cnt; i++)
|
||||||
costList.costs -= mindist;
|
costList.costs[i] = costList.costs[i] - mindist;
|
||||||
|
|
||||||
// (1)distanceをn乗する
|
// (2)distanceをn乗する
|
||||||
//const float pow = 2.0f;
|
for (int i = 0; i < cnt; i++)
|
||||||
costList.costs = math.pow(costList.costs, distancePow);
|
costList.costs[i] = math.pow(costList.costs[i], distancePow); // 2.0
|
||||||
|
|
||||||
// (2)最小値の逆数にする
|
// ウエイト算出
|
||||||
float min = math.max(costList.MinCost, 1e-06f);
|
if (costList.MinCost < Define.System.Epsilon)
|
||||||
|
{
|
||||||
|
costList.costs = new float4(1, 0, 0, 0);
|
||||||
|
costList.data = new int4(costList.data[0], 0, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// コストの逆数の合計
|
||||||
|
cnt = costList.Count;
|
||||||
float sum = 0;
|
float sum = 0;
|
||||||
for (int i = 0; i < cnt; i++)
|
for (int i = 0; i < cnt; i++)
|
||||||
{
|
{
|
||||||
costList.costs[i] = min / costList.costs[i];
|
sum += 1.0f / costList.costs[i];
|
||||||
sum += costList.costs[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// (3)割合を出す
|
// 1.0fに正規化
|
||||||
costList.costs /= sum;
|
for (int i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
costList.costs[i] = (1.0f / costList.costs[i]) / sum;
|
||||||
|
}
|
||||||
|
|
||||||
// (4)極小のウエイトは削除する
|
// 極小のウエイトは削除する
|
||||||
|
const float InvalidWeight = 0.001f; // 0.1%
|
||||||
sum = 0;
|
sum = 0;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (costList.costs[i] < 0.01f || i >= cnt)
|
if (costList.costs[i] < InvalidWeight || i >= cnt)
|
||||||
{
|
{
|
||||||
// 打ち切り
|
// 打ち切り
|
||||||
costList.costs[i] = 0.0f;
|
costList.costs[i] = 0.0f;
|
||||||
@ -1456,20 +1340,18 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug.Assert(sum > 0);
|
Debug.Assert(sum > 0);
|
||||||
|
costList.costs /= sum; // 再度1.0正規化
|
||||||
// (5)再度1.0に平均化
|
}
|
||||||
costList.costs /= sum;
|
|
||||||
|
|
||||||
//Debug.Log($"[{vindex}] :{costList}");
|
//Debug.Log($"[{vindex}] :{costList}");
|
||||||
|
|
||||||
// ウエイト作成
|
// ウエイト構造体に変換して格納
|
||||||
var bw = new VirtualMeshBoneWeight(costList.data, costList.costs);
|
var bw = new VirtualMeshBoneWeight(costList.data, costList.costs);
|
||||||
boneWeights[vindex] = bw;
|
boneWeights[vindex] = bw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if true
|
#if MC2_CUSTOM_SKINNING_V1
|
||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
struct Proxy_CalcCustomSkinningWeightsJob : IJobParallelFor
|
struct Proxy_CalcCustomSkinningWeightsJob : IJobParallelFor
|
||||||
{
|
{
|
||||||
@ -1487,7 +1369,7 @@ namespace MagicaCloth2
|
|||||||
[Unity.Collections.WriteOnly]
|
[Unity.Collections.WriteOnly]
|
||||||
public NativeArray<VirtualMeshBoneWeight> boneWeights;
|
public NativeArray<VirtualMeshBoneWeight> boneWeights;
|
||||||
|
|
||||||
|
// プロキシメッシュ頂点ごと
|
||||||
public void Execute(int vindex)
|
public void Execute(int vindex)
|
||||||
{
|
{
|
||||||
// BoneClothカスタムスキニングでは固定は動かさない
|
// BoneClothカスタムスキニングでは固定は動かさない
|
||||||
@ -1501,21 +1383,21 @@ namespace MagicaCloth2
|
|||||||
for (int i = 0; i < bcnt; i++)
|
for (int i = 0; i < bcnt; i++)
|
||||||
{
|
{
|
||||||
var binfo = boneInfoList[i];
|
var binfo = boneInfoList[i];
|
||||||
float3 d = MathUtility.ClosestPtPointSegment(lpos, binfo.startPos, binfo.endPos);
|
float3 d = MathUtility.ClosestPtPointSegment(lpos, binfo.parentPos, binfo.childPos);
|
||||||
//float dist = math.distance(lpos, d);
|
//float dist = math.distance(lpos, d);
|
||||||
|
|
||||||
// ボーンラインとの角度により判定距離を調整する
|
// ボーンラインとの角度により判定距離を調整する
|
||||||
// ラインと水平になるほど影響がよわくなる
|
// ラインと水平になるほど影響がよわくなる
|
||||||
var v = lpos - d;
|
var v = lpos - d;
|
||||||
var bv = binfo.endPos - binfo.startPos;
|
var bv = binfo.childPos - binfo.parentPos;
|
||||||
float dot = math.dot(math.normalize(v), math.normalize(bv));
|
float dot = math.dot(math.normalize(v), math.normalize(bv));
|
||||||
float ratio = 1.0f + math.abs(dot) * angularAttenuation;
|
float ratio = 1.0f + math.abs(dot) * angularAttenuation; // 1.0
|
||||||
|
|
||||||
// 登録。すでに登録済みならばdistがより小さい場合のみ再登録
|
// 登録。すでに登録済みならばdistがより小さい場合のみ再登録
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
int boneIndex = j == 0 ? binfo.startTransformIndex : binfo.endTransformIndex;
|
int boneIndex = j == 0 ? binfo.parentTransformIndex : binfo.childTransformIndex;
|
||||||
float dist = j == 0 ? math.distance(lpos, binfo.startPos) : math.distance(lpos, binfo.endPos);
|
float dist = j == 0 ? math.distance(lpos, binfo.parentPos) : math.distance(lpos, binfo.childPos);
|
||||||
dist *= ratio;
|
dist *= ratio;
|
||||||
|
|
||||||
int nowIndex = costList.indexOf(boneIndex);
|
int nowIndex = costList.indexOf(boneIndex);
|
||||||
@ -1535,11 +1417,11 @@ namespace MagicaCloth2
|
|||||||
// ウエイト算出
|
// ウエイト算出
|
||||||
// (0)最小距離のn%を減算する
|
// (0)最小距離のn%を減算する
|
||||||
int cnt = costList.Count;
|
int cnt = costList.Count;
|
||||||
float mindist = costList.MinCost * distanceReduction;
|
float mindist = costList.MinCost * distanceReduction; // 0.6
|
||||||
costList.costs -= mindist;
|
costList.costs -= mindist;
|
||||||
|
|
||||||
// (1)distanceをn乗する
|
// (1)distanceをn乗する
|
||||||
costList.costs = math.pow(costList.costs, distancePow);
|
costList.costs = math.pow(costList.costs, distancePow); // 2.0
|
||||||
|
|
||||||
// (2)最小値の逆数にする
|
// (2)最小値の逆数にする
|
||||||
float min = math.max(costList.MinCost, 1e-06f);
|
float min = math.max(costList.MinCost, 1e-06f);
|
||||||
@ -1950,7 +1832,7 @@ namespace MagicaCloth2
|
|||||||
int pindex = vertexParentIndices[vindex];
|
int pindex = vertexParentIndices[vindex];
|
||||||
if (pindex >= 0)
|
if (pindex >= 0)
|
||||||
{
|
{
|
||||||
vertexChildMap.UniqueAdd(pindex, (ushort)vindex);
|
vertexChildMap.MC2UniqueAdd(pindex, (ushort)vindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2261,16 +2143,21 @@ namespace MagicaCloth2
|
|||||||
float3 tan = localTangents[vindex];
|
float3 tan = localTangents[vindex];
|
||||||
quaternion rot = MathUtility.ToRotation(nor, tan);
|
quaternion rot = MathUtility.ToRotation(nor, tan);
|
||||||
|
|
||||||
|
|
||||||
float3 lpos = math.mul(iprot, pos - ppos);
|
float3 lpos = math.mul(iprot, pos - ppos);
|
||||||
quaternion lrot = math.mul(iprot, rot);
|
quaternion lrot = math.mul(iprot, rot);
|
||||||
vertexLocalPositions[vindex] = lpos;
|
vertexLocalPositions[vindex] = lpos;
|
||||||
vertexLocalRotations[vindex] = lrot;
|
vertexLocalRotations[vindex] = lrot;
|
||||||
|
|
||||||
|
//Debug.Log($"vertexLocalPositions [{vindex}] : {lpos}");
|
||||||
|
//Debug.Log($"vertexLocalRotations [{vindex}] : {lrot}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vertexLocalPositions[vindex] = 0;
|
vertexLocalPositions[vindex] = 0;
|
||||||
vertexLocalRotations[vindex] = quaternion.identity;
|
vertexLocalRotations[vindex] = quaternion.identity;
|
||||||
|
|
||||||
|
//Debug.Log($"vertexLocalPositions [{vindex}] : 0");
|
||||||
|
//Debug.Log($"vertexLocalRotations [{vindex}] : (0, 0, 0, 1)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2379,7 +2266,7 @@ namespace MagicaCloth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
#if false // pitch/yaw個別制限はv1.0では実装しないので一旦ん停止
|
#if false // pitch/yaw個別制限はv1.0では実装しないので一旦停止
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角度制限計算用ローカル回転の算出
|
/// 角度制限計算用ローカル回転の算出
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -48,7 +48,7 @@ namespace MagicaCloth2
|
|||||||
float sameDistance = maxSideLength * math.saturate(Define.System.ReductionSameDistance);
|
float sameDistance = maxSideLength * math.saturate(Define.System.ReductionSameDistance);
|
||||||
float simpleDistance = maxSideLength * math.saturate(settings.simpleDistance);
|
float simpleDistance = maxSideLength * math.saturate(settings.simpleDistance);
|
||||||
float shapeDistance = maxSideLength * math.saturate(settings.shapeDistance);
|
float shapeDistance = maxSideLength * math.saturate(settings.shapeDistance);
|
||||||
//Develop.DebugLog($"ReductionDista. maxSideLength:{maxSideLength}, same:{sameDistance}, simple:{simpleDistance}, shape:{shapeDistance}");
|
Develop.DebugLog($"ReductionDista. maxSideLength:{maxSideLength}, same:{sameDistance}, simple:{simpleDistance}, shape:{shapeDistance}");
|
||||||
|
|
||||||
// 同一距離リダクション
|
// 同一距離リダクション
|
||||||
ct.ThrowIfCancellationRequested();
|
ct.ThrowIfCancellationRequested();
|
||||||
@ -659,7 +659,7 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
int newIndex2 = vertexRemapIndices[oldVertexIndex];
|
int newIndex2 = vertexRemapIndices[oldVertexIndex];
|
||||||
//Debug.Assert(newIndex != newIndex2);
|
//Debug.Assert(newIndex != newIndex2);
|
||||||
newVertexToVertexMap.UniqueAdd((ushort)newIndex, (ushort)newIndex2);
|
newVertexToVertexMap.MC2UniqueAdd((ushort)newIndex, (ushort)newIndex2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Debug.Log($"[{newIndex}] cnt:{newVertexToVertexMap.CountValuesForKey((ushort)newIndex)}");
|
//Debug.Log($"[{newIndex}] cnt:{newVertexToVertexMap.CountValuesForKey((ushort)newIndex)}");
|
||||||
@ -764,7 +764,7 @@ namespace MagicaCloth2
|
|||||||
if (vindex == edge.x || vindex == edge.y)
|
if (vindex == edge.x || vindex == edge.y)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (newVertexToVertexMap.Contains((ushort)edge.y, vindex))
|
if (newVertexToVertexMap.MC2Contains((ushort)edge.y, vindex))
|
||||||
{
|
{
|
||||||
// トライアングル生成
|
// トライアングル生成
|
||||||
int3 tri = DataUtility.PackInt3(edge.x, edge.y, vindex);
|
int3 tri = DataUtility.PackInt3(edge.x, edge.y, vindex);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace MagicaCloth2
|
|||||||
{
|
{
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 頂点間の平均/最大距離を調べてる(スレッド可)
|
/// 頂点間の平均/最大距離を調べる(スレッド可)
|
||||||
/// 結果はaverageVertexDistance/maxVertexDistanceに格納される
|
/// 結果はaverageVertexDistance/maxVertexDistanceに格納される
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void CalcAverageAndMaxVertexDistanceRun()
|
internal void CalcAverageAndMaxVertexDistanceRun()
|
||||||
|
|||||||
@ -22,6 +22,8 @@ namespace MagicaCloth2
|
|||||||
|
|
||||||
public ResultCode result = new ResultCode();
|
public ResultCode result = new ResultCode();
|
||||||
|
|
||||||
|
public bool isManaged; // PreBuild DeserializeManager管理
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// メッシュタイプ
|
/// メッシュタイプ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -360,26 +362,34 @@ namespace MagicaCloth2
|
|||||||
public int mappingId;
|
public int mappingId;
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
public VirtualMesh()
|
public VirtualMesh() { }
|
||||||
|
|
||||||
|
public VirtualMesh(bool initialize)
|
||||||
{
|
{
|
||||||
transformData = new TransformData();
|
if (initialize)
|
||||||
|
{
|
||||||
|
transformData = new TransformData(100);
|
||||||
|
|
||||||
// 最小限のデータ
|
// 最小限のデータ
|
||||||
averageVertexDistance = new NativeReference<float>(0.0f, Allocator.Persistent);
|
averageVertexDistance = new NativeReference<float>(0.0f, Allocator.Persistent);
|
||||||
maxVertexDistance = new NativeReference<float>(0.0f, Allocator.Persistent);
|
maxVertexDistance = new NativeReference<float>(0.0f, Allocator.Persistent);
|
||||||
|
|
||||||
|
|
||||||
// 作業中にしておく
|
// 作業中にしておく
|
||||||
result.SetProcess();
|
result.SetProcess();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public VirtualMesh(string name) : this()
|
public VirtualMesh(string name) : this(true)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
// PreBuild DeserializeManager管理中は破棄させない
|
||||||
|
if (isManaged)
|
||||||
|
return;
|
||||||
|
|
||||||
result.Clear();
|
result.Clear();
|
||||||
referenceIndices.Dispose();
|
referenceIndices.Dispose();
|
||||||
attributes.Dispose();
|
attributes.Dispose();
|
||||||
@ -471,7 +481,8 @@ namespace MagicaCloth2
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// レンダラーが存在する場合はその存在を確認する
|
// レンダラーが存在する場合はその存在を確認する
|
||||||
if (centerTransformIndex >= 0 && transformData.GetTransformFromIndex(centerTransformIndex) == null)
|
// ただしPreBuildではtransformListは空なのでスキップする
|
||||||
|
if (centerTransformIndex >= 0 && transformData.IsEmpty == false && transformData.GetTransformFromIndex(centerTransformIndex) == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -483,23 +494,38 @@ namespace MagicaCloth2
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.AppendLine($"===== {name} =====");
|
sb.AppendLine($"===== {name} =====");
|
||||||
sb.Append($"Result:{result}");
|
sb.AppendLine($"Result:{result.GetResultString()}");
|
||||||
sb.Append($", Type:{meshType}");
|
sb.AppendLine($"Type:{meshType}");
|
||||||
sb.Append($", Vertex:{VertexCount}");
|
sb.AppendLine($"Vertex:{VertexCount}");
|
||||||
sb.Append($", Line:{LineCount}");
|
sb.AppendLine($"Line:{LineCount}");
|
||||||
sb.Append($", Triangle:{TriangleCount}");
|
sb.AppendLine($"Triangle:{TriangleCount}");
|
||||||
sb.Append($", Edge:{EdgeCount}");
|
sb.AppendLine($"Edge:{EdgeCount}");
|
||||||
sb.Append($", SkinBone:{SkinBoneCount}");
|
sb.AppendLine($"SkinBone:{SkinBoneCount}");
|
||||||
sb.Append($", Transform:{transformData?.Count}");
|
sb.AppendLine($"Transform:{TransformCount}");
|
||||||
sb.Append($", BaseLine:{BaseLineCount}");
|
if (averageVertexDistance.IsCreated)
|
||||||
|
sb.AppendLine($"avgDist:{averageVertexDistance.Value}");
|
||||||
|
if (maxVertexDistance.IsCreated)
|
||||||
|
sb.AppendLine($"maxDist:{maxVertexDistance.Value}");
|
||||||
|
if (boundingBox.IsCreated)
|
||||||
|
sb.AppendLine($"AABB:{boundingBox.Value}");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|
||||||
if (averageVertexDistance.IsCreated)
|
sb.AppendLine($"<<< Proxy >>>");
|
||||||
sb.Append($"avgDist:{averageVertexDistance.Value}");
|
sb.AppendLine($"BaseLine:{BaseLineCount}");
|
||||||
if (maxVertexDistance.IsCreated)
|
sb.AppendLine($"EdgeCount:{EdgeCount}");
|
||||||
sb.Append($", maxDist:{maxVertexDistance.Value}");
|
int edgeToTrianglesCnt = edgeToTriangles.IsCreated ? edgeToTriangles.Count() : 0;
|
||||||
if (boundingBox.IsCreated)
|
sb.AppendLine($"edgeToTriangles:{edgeToTrianglesCnt}");
|
||||||
sb.Append($", AABB:{boundingBox.Value}");
|
sb.AppendLine($"CustomSkinningBoneCount:{CustomSkinningBoneCount}");
|
||||||
|
sb.AppendLine($"CenterFixedPointCount:{CenterFixedPointCount}");
|
||||||
|
sb.AppendLine($"NormalAdjustmentRotationCount:{NormalAdjustmentRotationCount}");
|
||||||
|
sb.AppendLine();
|
||||||
|
|
||||||
|
sb.AppendLine($"<<< Mapping >>>");
|
||||||
|
sb.AppendLine($"centerWorldPosition:{centerWorldPosition}");
|
||||||
|
sb.AppendLine();
|
||||||
|
|
||||||
|
//sb.AppendLine($"<<< TransformData >>>");
|
||||||
|
sb.AppendLine(transformData?.ToString() ?? "(none)");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user