// Magica Cloth 2.
// Copyright (c) 2023 MagicaSoft.
// https://magicasoft.jp
using System.Collections.Generic;
using Unity.Collections;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
namespace MagicaCloth2
{
///
/// クロスコンポーネントのギズモ表示
///
public static class ClothEditorUtility
{
public static readonly Color MovePointColor = new Color(0.8f, 0.8f, 0.8f, 0.8f);
//public static readonly Color MovePointColor = Color.white;
public static readonly Color FixedPointColor = new Color(1.0f, 0.0f, 0.0f, 0.8f);
public static readonly Color InvalidPointColor = new Color(0.0f, 0.0f, 0.0f, 0.8f);
public static readonly Color AngleLimitConeColor = new Color(0.0f, 0.349f, 0.725f, 0.325f);
public static readonly Color AngleLimitWireColor = new Color(0.0f, 0.843f, 1.0f, 0.313f);
public static readonly Color BaseTriangleColor = new Color(204 / 255f, 153 / 255f, 255 / 255f);
public static readonly Color BaseLineColor = new Color(153 / 255f, 204 / 255f, 255 / 255f);
public static readonly Color TriangleColor = new Color(1.0f, 0.0f, 0.8f, 1f);
public static readonly Color LineColor = Color.cyan;
public static readonly Color SkininngLine = Color.yellow;
///
/// クロスペイント時のギズモ表示設定
///
internal static readonly ClothDebugSettings PaintSettings = new ClothDebugSettings()
{
enable = true,
position = false,
collider = false,
//basicShape = true,
animatedShape = true,
};
//=========================================================================================
static List positionBuffer0 = new List(1024);
static List positionBuffer1 = new List(1024);
static List positionBuffer2 = new List(1024);
static List segmentBuffer0 = new List(2048);
static List segmentBuffer1 = new List(2048);
static List segmentBuffer2 = new List(2048);
//=========================================================================================
///
/// 編集時のクロスデータの表示(すべてHandlesクラスで描画)
///
///
///
public static void DrawClothEditor(VirtualMesh editMesh, ClothDebugSettings drawSettings, ClothSerializeData serializeData, bool selected, bool direction, bool paint)
{
if (editMesh == null || editMesh.IsSuccess == false)
return;
if (drawSettings.enable == false || serializeData == null)
return;
// シーンカメラ
var scam = SceneView.currentDrawingSceneView?.camera;
if (scam == null)
return;
var crot = scam.transform.rotation;
// 座標空間に合わせる
var t = editMesh.GetCenterTransform();
if (t == null)
return;
Handles.zTest = drawSettings.ztest ? UnityEngine.Rendering.CompareFunction.LessEqual : UnityEngine.Rendering.CompareFunction.Always;
Handles.lighting = true;
Handles.matrix = t.localToWorldMatrix;
// シーンカメラ回転をローカル空間へ変換する
crot = Quaternion.Inverse(t.rotation) * crot;
int vcnt = editMesh.VertexCount;
float worldToLocalScale = 1.0f / t.lossyScale.x;
float drawPointSize = drawSettings.GetPointSize() * worldToLocalScale;
float drawLineSize = drawSettings.GetLineSize() * worldToLocalScale;
float3 cdir = crot * Vector3.forward; // ローカルカメラ方向
float colorScale = selected ? 1.0f : 0.5f;
// position
if (drawSettings.position || drawSettings.animatedPosition)
{
using var pointList = new NativeList(vcnt, Allocator.TempJob);
for (int i = 0; i < vcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
var point = new ClothPainter.Point()
{
vindex = i,
};
pointList.AddNoResize(point);
}
if (pointList.Length > 0)
{
// カメラ距離でソート
ClothPainter.CalcPointCameraDistance(editMesh.localPositions.GetNativeArray(), 0, t.localToWorldMatrix, scam.transform.position, pointList);
// 描画
int cnt = pointList.Length;
for (int i = 0; i < cnt; i++)
{
var p = pointList[i];
var attr = editMesh.attributes[p.vindex];
var col = InvalidPointColor;
if (attr.IsFixed()) col = FixedPointColor;
else if (attr.IsMove()) col = MovePointColor;
GizmoUtility.SetColor(col * colorScale, true);
// radius
float depth = editMesh.vertexDepths[p.vindex];
float radius = serializeData.radius.Evaluate(depth);
radius *= worldToLocalScale;
var pos = editMesh.localPositions[p.vindex];
GizmoUtility.DrawSphere(pos, drawSettings.CheckRadiusDrawing() ? radius : drawPointSize, true);
}
}
}
// animated shape / shape
if (drawSettings.animatedShape || drawSettings.shape)
{
positionBuffer0.Clear();
segmentBuffer0.Clear();
for (int i = 0; i < vcnt; i++)
{
positionBuffer0.Add(editMesh.localPositions[i]);
}
GizmoUtility.SetColor(drawSettings.animatedShape ? BaseTriangleColor : TriangleColor, true);
int tcnt = editMesh.TriangleCount;
for (int i = 0; i < tcnt; i++)
{
if (drawSettings.CheckTriangleDrawing(i) == false)
continue;
int3 tri = editMesh.triangles[i];
// 方向性
if (direction)
{
var tn = MathUtility.TriangleNormal(editMesh.localPositions[tri.x], editMesh.localPositions[tri.y], editMesh.localPositions[tri.z]);
if (math.dot(tn, cdir) >= 0.0f)
continue;
}
segmentBuffer0.Add(tri.x);
segmentBuffer0.Add(tri.y);
segmentBuffer0.Add(tri.y);
segmentBuffer0.Add(tri.z);
segmentBuffer0.Add(tri.z);
segmentBuffer0.Add(tri.x);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
segmentBuffer0.Clear();
GizmoUtility.SetColor((drawSettings.animatedShape ? BaseLineColor : LineColor) * colorScale, true);
int lcnt = editMesh.LineCount;
for (int i = 0; i < lcnt; i++)
{
int2 line = editMesh.lines[i];
segmentBuffer0.Add(line.x);
segmentBuffer0.Add(line.y);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
// base line
if (drawSettings.baseLine && editMesh.BaseLineCount > 0)
{
GizmoUtility.SetColor(new Color(1.0f, 0.27f, 0.0f) * colorScale, true);
int bcnt = editMesh.BaseLineCount;
for (int i = 0; i < bcnt; i++)
{
int dstart = editMesh.baseLineStartDataIndices[i];
int dcnt = editMesh.baseLineDataCounts[i];
for (int j = 1; j < dcnt; j++)
{
int vindex = editMesh.baseLineData[dstart + j];
int pindex = editMesh.vertexParentIndices[vindex];
if (pindex >= 0)
{
var pos = editMesh.localPositions[vindex];
var ppos = editMesh.localPositions[pindex];
GizmoUtility.DrawLine(pos, ppos, true);
}
}
}
}
// axis
if (drawSettings.axis != ClothDebugSettings.DebugAxis.None || drawSettings.animatedAxis != ClothDebugSettings.DebugAxis.None)
{
positionBuffer0.Clear();
positionBuffer1.Clear();
positionBuffer2.Clear();
segmentBuffer0.Clear();
segmentBuffer1.Clear();
segmentBuffer2.Clear();
for (int i = 0; i < vcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
var pos = editMesh.localPositions[i];
var rot = MathUtility.ToRotation(editMesh.localNormals[i], editMesh.localTangents[i]);
// 基準軸の変換用ローカル回転
float len = drawLineSize;
// 基準軸
bool xaxis = false, yaxis = false, zaxis = false;
if (drawSettings.axis == ClothDebugSettings.DebugAxis.Normal || drawSettings.animatedAxis == ClothDebugSettings.DebugAxis.Normal)
{
switch (serializeData.normalAxis)
{
case ClothNormalAxis.Right:
case ClothNormalAxis.InverseRight:
xaxis = true;
break;
case ClothNormalAxis.Up:
case ClothNormalAxis.InverseUp:
yaxis = true;
break;
case ClothNormalAxis.Forward:
case ClothNormalAxis.InverseForward:
zaxis = true;
break;
}
}
if (drawSettings.axis == ClothDebugSettings.DebugAxis.All || drawSettings.animatedAxis == ClothDebugSettings.DebugAxis.All)
{
xaxis = yaxis = zaxis = true;
}
if (xaxis)
{
int index = positionBuffer0.Count;
positionBuffer0.Add(pos);
positionBuffer0.Add(pos + MathUtility.ToBinormal(rot) * len);
segmentBuffer0.Add(index);
segmentBuffer0.Add(index + 1);
}
if (yaxis)
{
int index = positionBuffer1.Count;
positionBuffer1.Add(pos);
positionBuffer1.Add(pos + MathUtility.ToNormal(rot) * len);
segmentBuffer1.Add(index);
segmentBuffer1.Add(index + 1);
}
if (zaxis)
{
int index = positionBuffer2.Count;
positionBuffer2.Add(pos);
positionBuffer2.Add(pos + MathUtility.ToTangent(rot) * len);
segmentBuffer2.Add(index);
segmentBuffer2.Add(index + 1);
}
}
if (positionBuffer0.Count > 0)
{
Handles.color = Color.red * colorScale;
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
if (positionBuffer1.Count > 0)
{
Handles.color = Color.green * colorScale;
Handles.DrawLines(positionBuffer1.ToArray(), segmentBuffer1.ToArray());
}
if (positionBuffer2.Count > 0)
{
Handles.color = Color.blue * colorScale;
Handles.DrawLines(positionBuffer2.ToArray(), segmentBuffer2.ToArray());
}
}
// depth
if (drawSettings.depth)
{
for (int i = 0; i < vcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
var pos = editMesh.localPositions[i];
var depth = editMesh.vertexDepths[i];
if (depth > 0.0f)
Handles.Label(pos, $"{depth:0.##}");
}
}
#if MC2_DEBUG
// number
else if (drawSettings.particleNumber || drawSettings.localNumber)
{
for (int i = 0; i < vcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
var pos = editMesh.localPositions[i];
Handles.Label(pos, i.ToString());
}
}
// attribute
else if (drawSettings.attribute)
{
for (int i = 0; i < vcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
var pos = editMesh.localPositions[i];
var attr = editMesh.attributes[i];
Handles.Label(pos, $"0x{attr.Value:X2}");
}
}
// triangle number
else if (drawSettings.triangleNumber)
{
int tcnt = editMesh.TriangleCount;
for (int i = 0; i < tcnt; i++)
{
if (drawSettings.CheckTriangleDrawing(i) == false)
continue;
int3 tri = editMesh.triangles[i];
var pos1 = editMesh.localPositions[tri.x];
var pos2 = editMesh.localPositions[tri.y];
var pos3 = editMesh.localPositions[tri.z];
var cen = MathUtility.TriangleCenter(pos1, pos2, pos3);
Handles.Label(cen, i.ToString());
}
}
#endif
// inertia center
if (paint == false && editMesh.CenterFixedPointCount > 0)
{
float3 pos = 0;
int ccnt = editMesh.CenterFixedPointCount;
for (int i = 0; i < ccnt; i++)
{
pos += editMesh.localPositions[editMesh.centerFixedList[i]];
}
pos /= ccnt;
GizmoUtility.SetColor(Color.magenta * colorScale, true);
GizmoUtility.DrawSphere(pos, drawSettings.GetInertiaCenterRadius() * worldToLocalScale, true);
}
Handles.matrix = Matrix4x4.identity;
// custom skinning bone
if (paint == false)
{
Handles.color = SkininngLine * colorScale;
var boneList = serializeData.customSkinningSetting.skinningBones;
for (int i = 0; i < boneList.Count - 1; i++)
{
var bone1 = boneList[i];
if (bone1 == null)
continue;
for (int j = i + 1; j < boneList.Count; j++)
{
var bone2 = boneList[j];
if (bone2 == null)
continue;
if (bone1.parent == bone2 || bone2.parent == bone1)
{
Handles.DrawLine(bone1.position, bone2.position);
}
}
}
}
}
///
/// 実行時のクロスデータの表示(すべてHandlesクラスで描画)
///
///
///
public static void DrawClothRuntime(ClothProcess cprocess, ClothDebugSettings drawSettings, bool selected)
{
if (cprocess == null || cprocess.IsValid() == false)
return;
if (drawSettings.enable == false)
return;
if (MagicaManager.Team == null)
return;
if (MagicaManager.Team.ContainsTeamData(cprocess.TeamId) == false)
return;
// プロキシメッシュ
var proxyMesh = cprocess.ProxyMesh;
if (proxyMesh == null || proxyMesh.IsSuccess == false)
return;
// シーンカメラ
var scam = SceneView.currentDrawingSceneView?.camera;
if (scam == null)
return;
var crot = scam.transform.rotation;
// チームデータ
var tdata = MagicaManager.Team.GetTeamData(cprocess.TeamId);
var cdata = MagicaManager.Team.centerDataArray[cprocess.TeamId];
int pcnt = tdata.ParticleCount;
int pstart = tdata.particleChunk.startIndex;
int vstart = tdata.proxyCommonChunk.startIndex;
float drawPointSize = drawSettings.GetPointSize();
float drawLineSize = drawSettings.GetLineSize();
// 座標空間に合わせる
var t = cprocess.cloth.ClothTransform;
if (t == null)
return;
Handles.zTest = drawSettings.ztest ? UnityEngine.Rendering.CompareFunction.LessEqual : UnityEngine.Rendering.CompareFunction.Always;
Handles.matrix = Matrix4x4.identity;
float colorScale = selected ? 1 : 0.5f;
var sim = MagicaManager.Simulation;
var vm = MagicaManager.VMesh;
// 座標参照先
var positionArray = drawSettings.IsReferOldPos() ? sim.oldPosArray : sim.dispPosArray;
// position
if (drawSettings.position)
{
using var pointList = new NativeList(pcnt, Allocator.TempJob);
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
var point = new ClothPainter.Point()
{
vindex = i,
};
pointList.AddNoResize(point);
}
if (pointList.Length > 0)
{
// カメラ距離でソート
ClothPainter.CalcPointCameraDistance(positionArray.GetNativeArray(), pstart, float4x4.identity, scam.transform.position, pointList);
// 描画
int cnt = pointList.Length;
for (int i = 0; i < cnt; i++)
{
var p = pointList[i];
int pindex = pstart + p.vindex;
int cvindex = tdata.proxyCommonChunk.startIndex + p.vindex;
var attr = vm.attributes[cvindex];
var col = InvalidPointColor;
if (attr.IsFixed()) col = FixedPointColor;
else if (attr.IsMove()) col = MovePointColor;
GizmoUtility.SetColor(col * colorScale, true);
// radius
float depth = vm.vertexDepths[cvindex];
float radius = cprocess.parameters.radiusCurveData.EvaluateCurve(depth);
radius *= tdata.scaleRatio;
var pos = positionArray[pindex];
GizmoUtility.DrawSphere(pos, drawSettings.CheckRadiusDrawing() ? radius : drawPointSize, true);
}
}
}
// rotation axis / area
if (drawSettings.axis != ClothDebugSettings.DebugAxis.None)
{
positionBuffer0.Clear();
positionBuffer1.Clear();
positionBuffer2.Clear();
segmentBuffer0.Clear();
segmentBuffer1.Clear();
segmentBuffer2.Clear();
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = pstart + i;
int cvindex = tdata.proxyCommonChunk.startIndex + i;
var pos = positionArray[pindex];
var rot = vm.rotations[cvindex]; // 計算済みの前フレームの最終姿勢
float len = drawLineSize;
// 基準軸
bool xaxis = false, yaxis = false, zaxis = false;
if (drawSettings.axis == ClothDebugSettings.DebugAxis.Normal)
{
switch (cprocess.parameters.normalAxis)
{
case ClothNormalAxis.Right:
case ClothNormalAxis.InverseRight:
xaxis = true;
break;
case ClothNormalAxis.Up:
case ClothNormalAxis.InverseUp:
yaxis = true;
break;
case ClothNormalAxis.Forward:
case ClothNormalAxis.InverseForward:
zaxis = true;
break;
}
}
if (drawSettings.axis == ClothDebugSettings.DebugAxis.All)
{
xaxis = yaxis = zaxis = true;
}
if (xaxis)
{
int index = positionBuffer0.Count;
positionBuffer0.Add(pos);
positionBuffer0.Add(pos + MathUtility.ToBinormal(rot) * len);
segmentBuffer0.Add(index);
segmentBuffer0.Add(index + 1);
}
if (yaxis)
{
int index = positionBuffer1.Count;
positionBuffer1.Add(pos);
positionBuffer1.Add(pos + MathUtility.ToNormal(rot) * len);
segmentBuffer1.Add(index);
segmentBuffer1.Add(index + 1);
}
if (zaxis)
{
int index = positionBuffer2.Count;
positionBuffer2.Add(pos);
positionBuffer2.Add(pos + MathUtility.ToTangent(rot) * len);
segmentBuffer2.Add(index);
segmentBuffer2.Add(index + 1);
}
}
if (positionBuffer0.Count > 0)
{
Handles.color = Color.red * colorScale;
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
if (positionBuffer1.Count > 0)
{
Handles.color = Color.green * colorScale;
Handles.DrawLines(positionBuffer1.ToArray(), segmentBuffer1.ToArray());
}
if (positionBuffer2.Count > 0)
{
Handles.color = Color.blue * colorScale;
Handles.DrawLines(positionBuffer2.ToArray(), segmentBuffer2.ToArray());
}
}
#if MC2_DEBUG
// collision normal
if (drawSettings.collisionNormal)
{
GizmoUtility.SetColor(Color.yellow * colorScale, true);
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = pstart + i;
var pos = positionArray[pindex];
float3 cn = sim.collisionNormalArray[pindex];
if (math.lengthsq(cn) > 1e-06f)
{
GizmoUtility.DrawLine(pos, pos + cn * drawPointSize, true);
}
}
}
#endif
// animated shape
if (drawSettings.animatedShape)
{
positionBuffer0.Clear();
segmentBuffer0.Clear();
for (int i = 0; i < pcnt; i++)
{
positionBuffer0.Add(sim.basePosArray[pstart + i]);
//positionBuffer0.Add(sim.stepBasicPositionBuffer[pstart + i]);
}
GizmoUtility.SetColor(BaseTriangleColor, true);
int tcnt = tdata.proxyTriangleChunk.dataLength;
for (int i = 0; i < tcnt; i++)
{
if (drawSettings.CheckTriangleDrawing(i) == false)
continue;
int tindex = tdata.proxyTriangleChunk.startIndex + i;
int3 tri = vm.triangles[tindex];
//int3 vtri = tri + tdata.proxyCommonChunk.startIndex;
//if (vm.attributes[vtri.x].IsInvalid() || vm.attributes[vtri.y].IsInvalid() || vm.attributes[vtri.z].IsInvalid())
// continue;
segmentBuffer0.Add(tri.x);
segmentBuffer0.Add(tri.y);
segmentBuffer0.Add(tri.y);
segmentBuffer0.Add(tri.z);
segmentBuffer0.Add(tri.z);
segmentBuffer0.Add(tri.x);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
segmentBuffer0.Clear();
GizmoUtility.SetColor(BaseLineColor * colorScale, true);
int lcnt = proxyMesh.LineCount;
for (int i = 0; i < lcnt; i++)
{
int2 line = proxyMesh.lines[i];
segmentBuffer0.Add(line.x);
segmentBuffer0.Add(line.y);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
// shape
if (drawSettings.shape)
{
positionBuffer0.Clear();
segmentBuffer0.Clear();
for (int i = 0; i < pcnt; i++)
{
positionBuffer0.Add(positionArray[pstart + i]);
}
GizmoUtility.SetColor(TriangleColor * colorScale, true);
int tcnt = tdata.proxyTriangleChunk.dataLength;
for (int i = 0; i < tcnt; i++)
{
if (drawSettings.CheckTriangleDrawing(i) == false)
continue;
int tindex = tdata.proxyTriangleChunk.startIndex + i;
int3 tri = vm.triangles[tindex];
segmentBuffer0.Add(tri.x);
segmentBuffer0.Add(tri.y);
segmentBuffer0.Add(tri.y);
segmentBuffer0.Add(tri.z);
segmentBuffer0.Add(tri.z);
segmentBuffer0.Add(tri.x);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
segmentBuffer0.Clear();
GizmoUtility.SetColor(LineColor * colorScale, true);
int lcnt = proxyMesh.LineCount;
for (int i = 0; i < lcnt; i++)
{
int2 line = proxyMesh.lines[i];
segmentBuffer0.Add(line.x);
segmentBuffer0.Add(line.y);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
// base line
if (drawSettings.baseLine && proxyMesh.BaseLineCount > 0)
{
GizmoUtility.SetColor(new Color(1.0f, 0.27f, 0.0f) * colorScale, true);
int bcnt = proxyMesh.BaseLineCount;
for (int i = 0; i < bcnt; i++)
{
int dstart = proxyMesh.baseLineStartDataIndices[i];
int dcnt = proxyMesh.baseLineDataCounts[i];
for (int j = 1; j < dcnt; j++)
{
int vindex = proxyMesh.baseLineData[dstart + j];
int pindex = proxyMesh.vertexParentIndices[vindex];
if (pindex >= 0)
{
var pos = positionArray[pstart + vindex];
var ppos = positionArray[pstart + pindex];
GizmoUtility.DrawLine(pos, ppos, true);
}
}
}
}
// animated position
if (drawSettings.animatedPosition)
{
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = tdata.particleChunk.startIndex + i;
//int cvindex = tdata.proxyCommonChunk.startIndex + i;
//var attr = vm.attributes[cvindex];
//if (attr.IsInvalid())
// continue;
var pos = sim.basePosArray[pindex];
//var pos = sim.stepBasicPositionBuffer[pindex];
GizmoUtility.SetColor(Color.cyan * colorScale, true);
GizmoUtility.DrawSphere(pos, drawPointSize, true);
}
}
// animated axis
if (drawSettings.animatedAxis != ClothDebugSettings.DebugAxis.None)
{
float size = drawLineSize;
positionBuffer0.Clear();
positionBuffer1.Clear();
positionBuffer2.Clear();
segmentBuffer0.Clear();
segmentBuffer1.Clear();
segmentBuffer2.Clear();
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = tdata.particleChunk.startIndex + i;
int cvindex = tdata.proxyCommonChunk.startIndex + i;
//var attr = vm.attributes[cvindex];
//if (attr.IsInvalid())
// continue;
var pos = sim.basePosArray[pindex];
var rot = sim.baseRotArray[pindex];
//var pos = sim.stepBasicPositionBuffer[pindex];
//var rot = sim.stepBasicRotationBuffer[pindex];
// 基準軸
bool xaxis = false, yaxis = false, zaxis = false;
if (drawSettings.animatedAxis == ClothDebugSettings.DebugAxis.Normal)
{
switch (cprocess.parameters.normalAxis)
{
case ClothNormalAxis.Right:
case ClothNormalAxis.InverseRight:
xaxis = true;
break;
case ClothNormalAxis.Up:
case ClothNormalAxis.InverseUp:
yaxis = true;
break;
case ClothNormalAxis.Forward:
case ClothNormalAxis.InverseForward:
zaxis = true;
break;
}
}
if (drawSettings.animatedAxis == ClothDebugSettings.DebugAxis.All)
{
xaxis = yaxis = zaxis = true;
}
if (xaxis)
{
int index = positionBuffer0.Count;
positionBuffer0.Add(pos);
positionBuffer0.Add(pos + MathUtility.ToBinormal(rot) * size);
segmentBuffer0.Add(index);
segmentBuffer0.Add(index + 1);
}
if (yaxis)
{
int index = positionBuffer1.Count;
positionBuffer1.Add(pos);
positionBuffer1.Add(pos + MathUtility.ToNormal(rot) * size);
segmentBuffer1.Add(index);
segmentBuffer1.Add(index + 1);
}
if (zaxis)
{
int index = positionBuffer2.Count;
positionBuffer2.Add(pos);
positionBuffer2.Add(pos + MathUtility.ToTangent(rot) * size);
segmentBuffer2.Add(index);
segmentBuffer2.Add(index + 1);
}
}
if (positionBuffer0.Count > 0)
{
Handles.color = Color.red * colorScale;
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
if (positionBuffer1.Count > 0)
{
Handles.color = Color.green * colorScale;
Handles.DrawLines(positionBuffer1.ToArray(), segmentBuffer1.ToArray());
}
if (positionBuffer2.Count > 0)
{
Handles.color = Color.blue * colorScale;
Handles.DrawLines(positionBuffer2.ToArray(), segmentBuffer2.ToArray());
}
}
#if false
// distance constraint
//for (int k = 0; k < DistanceConstraint.TypeCount; k++)
{
//bool drawFlag = false;
//switch (k)
//{
// case DistanceConstraint.Type_Vertical: drawFlag = drawSettings.verticalDistanceConstraint; break;
// case DistanceConstraint.Type_Horizontal: drawFlag = drawSettings.horizontalDistanceConstraint; break;
//}
//if (drawFlag == false)
// continue;
var distanceConstraint = sim.distanceConstraint;
//var nData = distanceConstraint.nativeData[k];
var sc = tdata.distanceStartChunk;
var dc = tdata.distanceDataChunk;
if (sc.IsValid)
{
//var col = Color.black;
//switch (k)
//{
// case DistanceConstraint.Type_Vertical:
// col = Color.yellow;
// break;
// case DistanceConstraint.Type_Horizontal:
// col = Color.red;
// break;
//}
//GizmoUtility.SetColor(col * colorScale, true);
positionBuffer0.Clear();
segmentBuffer0.Clear();
for (int i = 0; i < pcnt; i++)
{
positionBuffer0.Add(positionArray[pstart + i]);
}
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int cindex = sc.startIndex + i;
var pack = distanceConstraint.indexArray[cindex];
DataUtility.Unpack10_22(pack, out int dcnt, out int dstart);
if (dcnt > 0)
{
for (int j = 0; j < dcnt; j++)
{
int targetIndex = distanceConstraint.dataArray[dc.startIndex + dstart + j];
segmentBuffer0.Add(i);
segmentBuffer0.Add(targetIndex);
}
}
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
}
#endif
// depth
if (drawSettings.depth)
{
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = tdata.particleChunk.startIndex + i;
int cvindex = tdata.proxyCommonChunk.startIndex + i;
var pos = positionArray[pindex];
var depth = vm.vertexDepths[cvindex];
Handles.Label(pos, $"{depth:0.##}");
}
}
#if MC2_DEBUG
// number
else if (drawSettings.particleNumber || drawSettings.localNumber)
{
for (int i = 0; i < pcnt; i++)
{
//if (drawSettings.CheckParticleDrawing(i) == false)
// continue;
int pindex = tdata.particleChunk.startIndex + i;
var pos = positionArray[pindex];
if (drawSettings.particleNumber && drawSettings.CheckParticleDrawing(pindex))
Handles.Label(pos, pindex.ToString());
else if (drawSettings.localNumber && drawSettings.CheckParticleDrawing(i))
Handles.Label(pos, i.ToString());
}
}
// attribute
else if (drawSettings.attribute)
{
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = tdata.particleChunk.startIndex + i;
int cvindex = tdata.proxyCommonChunk.startIndex + i;
var pos = positionArray[pindex];
var attr = vm.attributes[cvindex];
Handles.Label(pos, $"0x{attr.Value:X2}");
}
}
// friction
else if (drawSettings.friction)
{
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = tdata.particleChunk.startIndex + i;
int cvindex = tdata.proxyCommonChunk.startIndex + i;
var pos = positionArray[pindex];
var friction = sim.frictionArray[pindex];
if (friction > 1e-06f)
Handles.Label(pos, $"{friction:0.##}");
}
}
// static friction
else if (drawSettings.staticFriction)
{
for (int i = 0; i < pcnt; i++)
{
if (drawSettings.CheckParticleDrawing(i) == false)
continue;
int pindex = tdata.particleChunk.startIndex + i;
int cvindex = tdata.proxyCommonChunk.startIndex + i;
var pos = positionArray[pindex];
var friction = sim.staticFrictionArray[pindex];
if (friction > 1e-06f)
Handles.Label(pos, $"{friction:0.##}");
}
}
// triangle number
else if (drawSettings.triangleNumber)
{
int tcnt = tdata.proxyTriangleChunk.dataLength;
for (int i = 0; i < tcnt; i++)
{
if (drawSettings.CheckTriangleDrawing(i) == false)
continue;
int tindex = tdata.proxyTriangleChunk.startIndex + i;
int3 tri = vm.triangles[tindex];
var pos1 = positionArray[pstart + tri.x];
var pos2 = positionArray[pstart + tri.y];
var pos3 = positionArray[pstart + tri.z];
var cen = MathUtility.TriangleCenter(pos1, pos2, pos3);
Handles.Label(cen, i.ToString());
}
}
#endif
// 空間を戻す
Handles.matrix = Matrix4x4.identity;
// 以下はワールド
// custom skinning bone
{
Handles.color = SkininngLine * colorScale;
var boneList = cprocess.cloth.SerializeData.customSkinningSetting.skinningBones;
for (int i = 0; i < boneList.Count - 1; i++)
{
var bone1 = boneList[i];
if (bone1 == null)
continue;
for (int j = i + 1; j < boneList.Count; j++)
{
var bone2 = boneList[j];
if (bone2 == null)
continue;
if (bone1.parent == bone2 || bone2.parent == bone1)
{
Handles.DrawLine(bone1.position, bone2.position);
}
}
}
}
// inertia center
{
var pos = cdata.nowWorldPosition;
var rot = cdata.nowWorldRotation;
GizmoUtility.SetColor(Color.magenta * colorScale, true);
GizmoUtility.DrawSphere(pos, drawSettings.GetInertiaCenterRadius(), true);
GizmoUtility.DrawCross(pos, rot, drawSettings.GetInertiaCenterRadius() * 2.0f, true);
}
#if MC2_DEBUG
// cell cube
//if (drawSettings.cellCube)
//{
// GizmoUtility.SetColor(Color.black * colorScale, true);
// GizmoUtility.DrawWireCube(tdata.cubeWorldCenter, Quaternion.identity, Vector3.one * tdata.cubeSize, true);
//}
#endif
}
}
}