// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace MagicaCloth { /// /// Deformerのギズモ表示 /// public class DeformerGizmoDrawer { //========================================================================================= /// /// デフォーマーギズモの表示 /// /// /// nullの場合はすべての頂点を表示 /// /// public static void DrawDeformerGizmo( IEditorMesh editorMesh, IEditorCloth editorCloth, float size = 0.005f ) { if (ClothMonitorMenu.Monitor == null) return; if (ClothMonitorMenu.Monitor.UI.DrawDeformer == false) return; if (ClothMonitorMenu.Monitor.UI.DrawDeformerVertexPosition == false && ClothMonitorMenu.Monitor.UI.DrawDeformerTriangle == false && ClothMonitorMenu.Monitor.UI.DrawDeformerLine == false && ClothMonitorMenu.Monitor.UI.DrawDeformerVertexAxis == false #if MAGICACLOTH_DEBUG && ClothMonitorMenu.Monitor.UI.DrawDeformerVertexNumber == false && ClothMonitorMenu.Monitor.UI.DrawDeformerTriangleNormal == false #endif ) return; // メッシュ頂点法線接線 List posList; List norList; List tanList; int vcnt = editorMesh.GetEditorPositionNormalTangent(out posList, out norList, out tanList); if (posList.Count == 0) return; // 頂点使用状態 List useList = null; List selList = null; if (editorCloth != null) { useList = editorCloth.GetUseList(); selList = editorCloth.GetSelectionList(); } // 頂点 DrawVertex(vcnt, posList, norList, tanList, useList, selList, size); // トライアングル DrawTriangle(editorMesh, posList, norList, tanList, useList); // ライン DrawLine(editorMesh, posList, norList, tanList, useList); } //========================================================================================= /// /// 頂点情報の表示 /// /// /// /// /// static void DrawVertex( int vcnt, List posList, List norList, List tanList, List useList, List selList, float size ) { bool position = ClothMonitorMenu.Monitor.UI.DrawDeformerVertexPosition; bool axis = ClothMonitorMenu.Monitor.UI.DrawDeformerVertexAxis; #if MAGICACLOTH_DEBUG bool number = ClothMonitorMenu.Monitor.UI.DrawDeformerVertexNumber; if (position == false && axis == false && number == false) return; #else if (position == false && axis == false) return; #endif #if MAGICACLOTH_DEBUG float radius = -1; Vector3 center = Vector3.zero; if (ClothMonitorMenu.Monitor.UI.DebugDrawDeformerVertexNumber >= 0) { int vindex = ClothMonitorMenu.Monitor.UI.DebugDrawDeformerVertexNumber; if (vindex >= 0 && vindex < vcnt) { center = posList[vindex]; radius = 0.05f; } } #endif bool hasNormal = norList.Count > 0; bool hasTangent = tanList.Count > 0; for (int i = 0; i < vcnt; i++) { // 使用頂点のみ if (useList != null && vcnt <= useList.Count && useList[i] == 0) continue; Vector3 pos = posList[i]; // 表示範囲 #if MAGICACLOTH_DEBUG // 表示半径判定 if (radius > 0 && Vector3.Distance(pos, center) > radius) continue; #endif if (position) { Gizmos.color = GetVertexColor(selList, i); Gizmos.DrawSphere(pos, size); } if (axis && (hasNormal || hasTangent)) { const float axisSize = 0.03f; if (hasNormal) { Vector3 nor = norList[i]; Gizmos.color = Color.blue; Gizmos.DrawLine(pos, pos + nor * axisSize); } if (hasTangent) { Vector3 tan = tanList[i]; Gizmos.color = Color.green; Gizmos.DrawLine(pos, pos + tan * axisSize); } if (hasNormal && hasTangent) { Vector3 nor = norList[i]; Vector3 tan = tanList[i]; Vector3 bin = Vector3.Cross(tan, nor).normalized; Gizmos.color = Color.red; Gizmos.DrawLine(pos, pos + bin * axisSize); } } #if MAGICACLOTH_DEBUG if (number) { Handles.Label(pos, i.ToString()); } #endif } } private static Color GetVertexColor(List selList, int vindex) { if (selList == null || vindex >= selList.Count) return GizmoUtility.ColorDeformerPoint; if (selList[vindex] == SelectionData.Move) return Color.green; if (selList[vindex] == SelectionData.Fixed) return Color.red; return GizmoUtility.ColorDeformerPoint; } //========================================================================================= /// /// トライアングル情報の表示 /// /// static void DrawTriangle( IEditorMesh editorMesh, List posList, List norList, List tanList, List useList ) { bool drawTriangle = ClothMonitorMenu.Monitor.UI.DrawDeformerTriangle; #if MAGICACLOTH_DEBUG bool drawNormal = ClothMonitorMenu.Monitor.UI.DrawDeformerTriangleNormal; bool drawNumber = ClothMonitorMenu.Monitor.UI.DrawDeformerTriangleNumber; #else bool drawNormal = false; bool drawNumber = false; #endif if (!drawTriangle && !drawNormal && !drawNumber) return; var triangles = editorMesh.GetEditorTriangleList(); if (triangles == null || triangles.Count == 0) return; //Gizmos.color = GizmoUtility.ColorTriangle; int tcnt = triangles.Count / 3; // 表示半径 float radius = -1; Vector3 center = Vector3.zero; #if MAGICACLOTH_DEBUG if (ClothMonitorMenu.Monitor.UI.DebugDrawDeformerTriangleNumber >= 0) { int tindex = ClothMonitorMenu.Monitor.UI.DebugDrawDeformerTriangleNumber; if (tindex >= 0 && tindex < tcnt) { int index = tindex * 3; int i0 = triangles[index]; int i1 = triangles[index + 1]; int i2 = triangles[index + 2]; Vector3 pos0 = posList[i0]; Vector3 pos1 = posList[i1]; Vector3 pos2 = posList[i2]; center = (pos0 + pos1 + pos2) / 3.0f; radius = 0.05f; } } #endif // 表示 for (int tindex = 0; tindex < tcnt; tindex++) { DrawTriangle1(tindex, triangles, posList, useList, center, radius, drawTriangle, drawNormal, drawNumber); } } /// /// トライアングル1つ表示 /// /// /// /// /// /// /// /// /// /// static void DrawTriangle1( int tindex, List triangles, List posList, List useList, Vector3 center, float radius, bool drawTriangle, bool drawNormal, bool drawNumber ) { int index = tindex * 3; int i0 = triangles[index]; int i1 = triangles[index + 1]; int i2 = triangles[index + 2]; // 使用頂点のみ if (useList != null) { if (useList[i0] == 0 || useList[i1] == 0 || useList[i2] == 0) return; } Vector3 pos0 = posList[i0]; Vector3 pos1 = posList[i1]; Vector3 pos2 = posList[i2]; var pos = (pos0 + pos1 + pos2) / 3.0f; // 表示半径判定 if (radius > 0 && Vector3.Distance(pos, center) > radius) return; if (drawTriangle) { Gizmos.color = GizmoUtility.ColorTriangle; Gizmos.DrawLine(pos0, pos1); Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos1, pos2); } if (drawNormal) { var vn1 = pos1 - pos0; var vn2 = pos2 - pos0; var nor = Vector3.Cross(vn1, vn2).normalized; Gizmos.color = Color.blue; Gizmos.DrawLine(pos, pos + nor * 0.02f); } if (drawNumber) { Handles.Label(pos, tindex.ToString()); } } //========================================================================================= /// /// ライン情報の表示 /// /// static void DrawLine( IEditorMesh editorMesh, List posList, List norList, List tanList, List useList ) { if (ClothMonitorMenu.Monitor.UI.DrawDeformerLine == false) return; var lines = editorMesh.GetEditorLineList(); if (lines == null || lines.Count == 0) return; Gizmos.color = GizmoUtility.ColorStructLine; int lcnt = lines.Count / 2; for (int i = 0; i < lcnt; i++) { int index = i * 2; int i0 = lines[index]; int i1 = lines[index + 1]; // 利用頂点のみ if (useList != null) { if (i0 >= useList.Count || i1 >= useList.Count) continue; if (useList[i0] == 0 || useList[i1] == 0) continue; } if (i0 >= posList.Count || i1 >= posList.Count) continue; Vector3 pos0 = posList[i0]; Vector3 pos1 = posList[i1]; Gizmos.DrawLine(pos0, pos1); } } } }