// 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 } } }