// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace MagicaCloth { /// /// クロスのギズモ表示 /// public class ClothGizmoDrawer { /// /// 常に表示するデータ /// /// /// internal static void AlwaysDrawClothGizmo( PhysicsTeam team, ClothParams param ) { if (ClothMonitorMenu.Monitor.UI.DrawCloth == false) return; // 無条件で表示するもの //DrawSkinningBone(team); } /// /// データ存在時の表示 /// /// /// /// /// /// /// /// public static bool DrawClothGizmo( PhysicsTeam team, ClothData clothData, ClothParams param, ClothSetup setup, IEditorMesh editorMesh, IEditorCloth editorCloth ) { if (ClothMonitorMenu.Monitor.UI.DrawCloth == false) return false; if (ClothMonitorMenu.Monitor.UI.DrawClothVertex == false && ClothMonitorMenu.Monitor.UI.DrawClothDepth == false && ClothMonitorMenu.Monitor.UI.DrawClothBase == false && ClothMonitorMenu.Monitor.UI.DrawClothCollider == false && ClothMonitorMenu.Monitor.UI.DrawClothStructDistanceLine == false && ClothMonitorMenu.Monitor.UI.DrawClothBendDistanceLine == false && ClothMonitorMenu.Monitor.UI.DrawClothNearDistanceLine == false && ClothMonitorMenu.Monitor.UI.DrawClothRotationLine == false && ClothMonitorMenu.Monitor.UI.DrawClothTriangleBend == false && ClothMonitorMenu.Monitor.UI.DrawClothPenetration == false && ClothMonitorMenu.Monitor.UI.DrawClothAxis == false #if MAGICACLOTH_DEBUG && ClothMonitorMenu.Monitor.UI.DrawClothVertexNumber == false && ClothMonitorMenu.Monitor.UI.DrawClothVertexIndex == false && ClothMonitorMenu.Monitor.UI.DrawPenetrationOrigin == false #endif ) return false; // 以下はデータが存在する場合のみ if (clothData == null) return false; if (Application.isPlaying) { if (clothData == null) return false; if (team.IsActive() == false) return false; if (team.IsCalculate == false) return false; // 頂点使用状態 //var useList = editorCloth.GetUseList(); var selList = editorCloth.GetSelectionList(); // 頂点情報 DrawVertexRuntime(team, clothData, param, setup, selList); // コライダー DrawCollider(team); // ライン DrawLineRuntime(team, clothData, setup, selList); // トライアングルベンド DrawTriangleBendRuntime(team, clothData, setup); // 回転ライン DrawRotationLineRuntime(team, clothData, setup, selList); // コライダー移動制限 DrawPenetrationRuntime(team, param, clothData, selList); //DrawBonePenetrationRuntime(team, param, clothData, selList); // 一旦休眠 // ボリューム //DrawVolumeRuntime(team, clothData, setup); // 回転調整ライン //DrawAdjustRotationLineRuntime(team, clothData); } else { // メッシュ頂点法線接線 List posList; List norList; List tanList; int vcnt = editorMesh.GetEditorPositionNormalTangent(out posList, out norList, out tanList); // 頂点使用状態 //var useList = editorCloth.GetUseList(); var selList = editorCloth.GetSelectionList(); // 頂点情報 DrawVertexClothData(clothData, param, vcnt, posList, norList, tanList, selList); // コライダー DrawCollider(team); // ライン DrawLineClothData(clothData, posList, selList); // トライアングルベンド DrawTriangleBendClothData(clothData, posList); // 回転ライン DrawRotationLineClothData(clothData, posList, selList); // コライダー移動制限 DrawPenetrationClothData(team, param, clothData, posList, norList, tanList, selList); //DrawBonePenetrationClothData(team, param, clothData, posList, norList, tanList, selList); // 一旦休眠 // ベーススキニング //DrawBaseSkinningClothData(team, clothData, posList, selList); // ボリューム //DrawVolumeClothData(clothData, posList); // 回転調整ライン //DrawAdjustRotationLineClothData(clothData, posList); } return true; } //========================================================================================= /// /// ランタイム状態での頂点表示 /// /// /// /// static void DrawVertexRuntime( PhysicsTeam team, ClothData clothData, ClothParams param, ClothSetup setup, List selList ) { bool drawVertex = ClothMonitorMenu.Monitor.UI.DrawClothVertex; bool drawRadius = ClothMonitorMenu.Monitor.UI.DrawClothRadius; bool drawDepth = ClothMonitorMenu.Monitor.UI.DrawClothDepth; bool drawAxis = ClothMonitorMenu.Monitor.UI.DrawClothAxis; #if MAGICACLOTH_DEBUG bool number = ClothMonitorMenu.Monitor.UI.DrawClothVertexNumber; bool drawIndex = ClothMonitorMenu.Monitor.UI.DrawClothVertexIndex; bool drawFriction = ClothMonitorMenu.Monitor.UI.DrawClothFriction; bool drawStaticFriction = ClothMonitorMenu.Monitor.UI.DrawClothStaticFriction; bool drawDepthNumber = ClothMonitorMenu.Monitor.UI.DrawClothDepthNumber; bool drawCollisionNormal = ClothMonitorMenu.Monitor.UI.DrawClothCollisionNormal; bool drawVelocity = ClothMonitorMenu.Monitor.UI.DrawClothVelocity; bool drawVelocityVector = ClothMonitorMenu.Monitor.UI.DrawClothVelocityVector; #else bool number = false; bool drawIndex = false; bool drawFriction = false; bool drawStaticFriction = false; bool drawDepthNumber = false; bool drawCollisionNormal = false; bool drawVelocity = false; bool drawVelocityVector = false; #endif if (!number && !drawVertex && !drawDepth && !drawAxis && !drawIndex && !drawFriction && !drawStaticFriction && !drawDepthNumber && !drawCollisionNormal && !drawVelocity && !drawVelocityVector) return; // チームスケール var teamTransform = team.InfluenceTarget ? team.InfluenceTarget : team.transform; float teamScale = clothData.initScale.magnitude > 0.0f ? teamTransform.lossyScale.magnitude / clothData.initScale.magnitude : 1.0f; float updateIntervalTime = MagicaPhysicsManager.Instance.UpdateTime.UpdateIntervalTime; int vcnt = clothData.useVertexList.Count; for (int i = 0; i < vcnt; i++) { int vindex = clothData.useVertexList[i]; int pindex = team.ParticleChunk.startIndex + i; Vector3 pos = MagicaPhysicsManager.Instance.Particle.posList[pindex]; float depth = MagicaPhysicsManager.Instance.Particle.depthList[pindex]; //float radius = PhysicsManager.Instance.Particle.radiusList[pindex]; float radius = drawRadius ? MagicaPhysicsManager.Instance.Particle.radiusList[pindex].x * teamScale : 0.001f; //float radius = param.GetRadius(depth); if (drawVertex || drawDepth || drawAxis) { Quaternion rot = MagicaPhysicsManager.Instance.Particle.rotList[pindex]; Gizmos.color = GetVertexColor(vindex, depth, selList); GizmoUtility.DrawWireSphere(pos, rot, Vector3.one, radius, drawVertex || drawDepth, drawAxis); } if (drawCollisionNormal) { Vector3 cn = MagicaPhysicsManager.Instance.Particle.collisionNormalList[pindex]; Gizmos.color = GizmoUtility.ColorCollisionNormal; Gizmos.DrawLine(pos, pos + cn * 0.03f); } if (drawVelocityVector) { Vector3 vel = MagicaPhysicsManager.Instance.Particle.velocityList[pindex]; Gizmos.color = GizmoUtility.ColorVelocity; Gizmos.DrawLine(pos, pos + vel * updateIntervalTime); } if (number) { Handles.Label(pos, i.ToString()); } if (drawIndex) { Handles.Label(pos, pindex.ToString()); } if (drawFriction) { float friction = MagicaPhysicsManager.Instance.Particle.frictionList[pindex]; Handles.Label(pos, string.Format("{0:#.##}", friction)); } if (drawStaticFriction) { float staticFriction = MagicaPhysicsManager.Instance.Particle.staticFrictionList[pindex]; Handles.Label(pos, string.Format("{0:#.##}", staticFriction)); } //if (drawDepthNumber) if (drawDepth) { float d = MagicaPhysicsManager.Instance.Particle.depthList[pindex]; Handles.Label(pos, string.Format("{0:#.##}", d)); } if (drawVelocity) { Vector3 v = MagicaPhysicsManager.Instance.Particle.velocityList[pindex]; Handles.Label(pos, string.Format("{0:#.##}", v.magnitude)); } } } /// /// エディタ状態での頂点表示 /// /// /// /// static void DrawVertexClothData( ClothData clothData, ClothParams param, int vcnt, List posList, List norList, List tanList, List selList ) { bool drawVertex = ClothMonitorMenu.Monitor.UI.DrawClothVertex; bool drawRadius = ClothMonitorMenu.Monitor.UI.DrawClothRadius; bool drawDepth = ClothMonitorMenu.Monitor.UI.DrawClothDepth; bool drawAxis = ClothMonitorMenu.Monitor.UI.DrawClothAxis; #if MAGICACLOTH_DEBUG bool number = ClothMonitorMenu.Monitor.UI.DrawClothVertexNumber; bool drawDepthNumber = ClothMonitorMenu.Monitor.UI.DrawClothDepthNumber; #else bool number = false; bool drawDepthNumber = false; #endif if (!number && !drawVertex && !drawDepth && !drawAxis && !drawDepthNumber) return; for (int i = 0; i < clothData.VertexUseCount; i++) { int vindex = clothData.useVertexList[i]; if (vindex >= posList.Count) continue; Vector3 pos = posList[vindex]; if (drawVertex || drawDepth || drawAxis) { Vector3 nor = norList[vindex]; Vector3 tan = tanList[vindex]; Quaternion rot = Quaternion.LookRotation(nor, tan); float depth = clothData == null ? 0.0f : clothData.vertexDepthList[i]; //float radius = param.GetRadius(depth); float radius = drawRadius ? param.GetRadius(depth) : 0.001f; Gizmos.color = GetVertexColor(vindex, depth, selList); GizmoUtility.DrawWireSphere(pos, rot, Vector3.one, radius, drawVertex || drawDepth, drawAxis); } if (number) { Handles.Label(pos, i.ToString()); } //if (drawDepthNumber) if (drawDepth) { float depth = clothData == null ? 0.0f : clothData.vertexDepthList[i]; Handles.Label(pos, string.Format("{0:#.##}", depth)); } } } /// /// クロス頂点カラー設定 /// /// /// /// static Color GetVertexColor(int vindex, float depth, List selList) { if (ClothMonitorMenu.Monitor.UI.DrawClothDepth) { return Color.Lerp(Color.red, Color.blue, depth); } else { if (selList == null || vindex >= selList.Count) return GizmoUtility.ColorDeformerPoint; else if (selList[vindex] == SelectionData.Fixed) return GizmoUtility.ColorKinematic; else if (selList[vindex] == SelectionData.Move) return GizmoUtility.ColorDynamic; else return GizmoUtility.ColorInvalid; } } static bool IsMove(int vindex, List selList) { if (selList == null || vindex >= selList.Count) return false; return selList[vindex] == SelectionData.Move; } //========================================================================================= /// /// クロスに紐づくコライダーの表示 /// /// public static void DrawCollider(PhysicsTeam team) { if (ClothMonitorMenu.Monitor.UI.DrawClothCollider == false) return; var colliderlist = team.TeamData.ColliderList; foreach (var collider in colliderlist) { if (collider == null || collider.isActiveAndEnabled == false) continue; if (collider is MagicaSphereCollider) MagicaSphereColliderGizmoDrawer.DrawGizmo(collider as MagicaSphereCollider, true); else if (collider is MagicaCapsuleCollider) MagicaCapsuleColliderGizmoDrawer.DrawGizmo(collider as MagicaCapsuleCollider, true); } } //========================================================================================= #if false /// /// エディタ状態でのベーススキニング表示 /// /// /// /// /// static void DrawBaseSkinningClothData( PhysicsTeam team, ClothData clothData, List posList, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothBaseSkinning == false) return; if (clothData.baseSkinningDataList == null) return; //var boneList = team.TeamData.SkinningBoneList; var boneList = team.TeamData.ColliderList; //Gizmos.color = GizmoUtility.ColorPenetration; for (int i = 0; i < clothData.VertexUseCount; i++) { int vindex = clothData.useVertexList[i]; if (vindex >= posList.Count) continue; if (IsMove(vindex, selList) == false) continue; Vector3 pos = posList[vindex]; for (int j = 0; j < Define.Compute.BaseSkinningWeightCount; j++) { int dindex = i * Define.Compute.BaseSkinningWeightCount + j; if (dindex >= clothData.baseSkinningDataList.Length) return; var data = clothData.baseSkinningDataList[dindex]; if (data.IsValid() == false) continue; int bindex = data.boneIndex; if (bindex >= boneList.Count) continue; var bone = boneList[bindex]; if (bone == null) continue; //Gizmos.color = j == 0 ? Color.red : Color.yellow; Gizmos.color = Color.gray; #if true Vector3 p, dir, d; bone.CalcNearPoint(pos, out p, out dir, out d, true); Gizmos.DrawLine(pos, p); #else //var cp = bone.TransformPoint(data.localPos); Vector3 cp; MeshUtility.ClosestPtBoneLine(pos, bone, 0.03f, out cp); Gizmos.DrawLine(pos, cp); #endif } } } #endif #if false // 一旦休眠 /// /// スキニング用ボーン構造の表示 /// /// static void DrawSkinningBone( PhysicsTeam team ) { if (ClothMonitorMenu.Monitor.UI.DrawClothSkinningBones == false) return; // スキニング用ボーン var boneList = team.TeamData.SkinningBoneList; if (boneList.Count >= 2) { //Gizmos.color = new Color(0.0f, 0.717f, 0.933f); //Gizmos.color = Color.magenta; foreach (var bone in boneList) { if (bone == null) continue; for (int k = 0; k < bone.childCount; k++) { var cbone = bone.GetChild(k); if (boneList.Contains(cbone)) { //Gizmos.DrawLine(bone.position, cbone.position); GizmoUtility.DrawBone(bone.position, cbone.position, 0.01f); } } } } } #endif //========================================================================================= /// /// ランタイム状態での浸透制限表示 /// /// /// /// static void DrawPenetrationRuntime( PhysicsTeam team, ClothParams param, ClothData clothData, List selList ) { #if !MAGICACLOTH_DEBUG if (ClothMonitorMenu.Monitor.UI.DrawClothPenetration == false) return; #else if (ClothMonitorMenu.Monitor.UI.DrawClothPenetration == false && ClothMonitorMenu.Monitor.UI.DrawPenetrationOrigin == false) return; #endif if (clothData.penetrationDataList == null) return; if (clothData.penetrationReferenceList == null) return; //var mode = param.GetPenetrationMode(); var mode = clothData.penetrationMode; // 一旦休眠 //if (mode == ClothParams.PenetrationMode.BonePenetration) // return; var colliderlist = team.TeamData.ColliderList; int vcnt = clothData.useVertexList.Count; for (int i = 0; i < vcnt; i++) { int vindex = clothData.useVertexList[i]; if (IsMove(vindex, selList) == false) continue; int pindex = team.ParticleChunk.startIndex + i; Vector3 pos = MagicaPhysicsManager.Instance.Particle.posList[pindex]; if (i >= clothData.penetrationReferenceList.Length) return; #if MAGICACLOTH_DEBUG Vector3 cen = Vector3.zero; Vector3 cdir = Vector3.zero; int ccnt = 0; GUIStyle style = new GUIStyle(); style.normal.textColor = Color.cyan; #endif var refdata = clothData.penetrationReferenceList[i]; for (int j = 0; j < refdata.count; j++) { var dindex = refdata.startIndex + j; var data = clothData.penetrationDataList[dindex]; if (data.IsValid() == false) continue; if (mode == ClothParams.PenetrationMode.SurfacePenetration) { Vector3 bpos = MagicaPhysicsManager.Instance.Particle.basePosList[pindex]; Quaternion brot = MagicaPhysicsManager.Instance.Particle.baseRotList[pindex]; var dir = brot * data.localDir; var depth = clothData.vertexDepthList[i]; var dist = param.GetPenetrationDistance().Evaluate(depth); Gizmos.color = GizmoUtility.ColorPenetration; Gizmos.DrawLine(bpos, bpos + dir * dist); break; } else if (mode == ClothParams.PenetrationMode.ColliderPenetration) { int cindex = data.colliderIndex; if (cindex >= colliderlist.Count) continue; var col = colliderlist[cindex]; if (col == null) continue; var cp = col.transform.TransformPoint(data.localPos); #if MAGICACLOTH_DEBUG var dir = col.transform.TransformDirection(data.localDir); var c = cp + dir * data.distance; cen += c; cdir += dir; ccnt++; #endif if (ClothMonitorMenu.Monitor.UI.DrawClothPenetration) { Gizmos.color = GizmoUtility.ColorPenetration; Gizmos.DrawLine(pos, cp); } } } #if MAGICACLOTH_DEBUG if (ClothMonitorMenu.Monitor.UI.DrawPenetrationOrigin && ccnt > 0) { cen /= ccnt; cdir /= ccnt; Gizmos.color = new Color(0.0f, 1.0f, 1.0f); Gizmos.DrawSphere(cen, 0.002f); Gizmos.color = Color.yellow; Gizmos.DrawLine(cen, cen + cdir.normalized * 0.02f); //Handles.color = Color.cyan; Handles.Label(cen, i.ToString(), style); } #endif } } #if false // 一旦休眠 static void DrawBonePenetrationRuntime( PhysicsTeam team, ClothParams param, ClothData clothData, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothPenetration == false) return; var mode = clothData.penetrationMode; if (mode != ClothParams.PenetrationMode.BonePenetration) return; if (clothData.penetrationDirectionDataList == null) return; for (int i = 0; i < clothData.VertexUseCount; i++) { int vindex = clothData.useVertexList[i]; if (IsMove(vindex, selList) == false) continue; if (i >= clothData.penetrationDirectionDataList.Length) return; var depth = clothData.vertexDepthList[i]; if (depth > param.PenetrationMaxDepth) continue; int pindex = team.ParticleChunk.startIndex + i; Vector3 bpos = MagicaPhysicsManager.Instance.Particle.basePosList[pindex]; Quaternion brot = MagicaPhysicsManager.Instance.Particle.baseRotList[pindex]; var ldir = clothData.penetrationDirectionDataList[i]; var dir = brot * ldir; Gizmos.color = Color.blue; //Gizmos.color = GizmoUtility.ColorPenetration; Gizmos.DrawLine(bpos, bpos + dir * 0.1f); } } #endif /// /// エディタ状態での浸透制限表示 /// /// /// /// /// static void DrawPenetrationClothData( PhysicsTeam team, ClothParams param, ClothData clothData, List posList, List norList, List tanList, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothPenetration == false) return; //var mode = param.GetPenetrationMode(); var mode = clothData.penetrationMode; if (clothData.penetrationDataList == null) return; if (clothData.penetrationReferenceList == null) return; var colliderlist = team.TeamData.ColliderList; for (int i = 0; i < clothData.VertexUseCount; i++) { int vindex = clothData.useVertexList[i]; if (vindex >= posList.Count) continue; if (IsMove(vindex, selList) == false) continue; //Vector3 pos = posList[vindex]; if (i >= clothData.penetrationReferenceList.Length) return; var refdata = clothData.penetrationReferenceList[i]; for (int j = 0; j < refdata.count; j++) { var dindex = refdata.startIndex + j; var data = clothData.penetrationDataList[dindex]; if (data.IsValid() == false) continue; if (mode == ClothParams.PenetrationMode.SurfacePenetration) { var pos = posList[vindex]; var rot = Quaternion.LookRotation(norList[vindex], tanList[vindex]); var dir = rot * data.localDir; var depth = clothData.vertexDepthList[i]; var dist = param.GetPenetrationDistance().Evaluate(depth); Gizmos.color = GizmoUtility.ColorPenetration; Gizmos.DrawLine(pos, pos + dir * dist); break; } else if (mode == ClothParams.PenetrationMode.ColliderPenetration) { int cindex = data.colliderIndex; if (cindex >= colliderlist.Count) continue; var col = colliderlist[cindex]; if (col == null) continue; var cp = col.transform.TransformPoint(data.localPos); var pos = cp + col.transform.TransformDirection(data.localDir) * data.distance; Gizmos.color = GizmoUtility.ColorPenetration; Gizmos.DrawLine(pos, cp); } } } } #if false // 一旦休眠 static void DrawBonePenetrationClothData( PhysicsTeam team, ClothParams param, ClothData clothData, List posList, List norList, List tanList, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothPenetration == false) return; var mode = clothData.penetrationMode; if (mode != ClothParams.PenetrationMode.BonePenetration) return; if (clothData.penetrationDirectionDataList == null) return; for (int i = 0; i < clothData.VertexUseCount; i++) { int vindex = clothData.useVertexList[i]; if (IsMove(vindex, selList) == false) continue; if (i >= clothData.penetrationDirectionDataList.Length) return; var depth = clothData.vertexDepthList[i]; if (depth > param.PenetrationMaxDepth) continue; var pos = posList[vindex]; var rot = Quaternion.LookRotation(norList[vindex], tanList[vindex]); var ldir = clothData.penetrationDirectionDataList[i]; var dir = rot * ldir; Gizmos.color = Color.blue; //Gizmos.color = GizmoUtility.ColorPenetration; Gizmos.DrawLine(pos, pos + dir * 0.1f); } } #endif //========================================================================================= /// /// ランタイム状態でのライン表示 /// /// /// /// static void DrawLineRuntime( PhysicsTeam team, ClothData clothData, ClothSetup setup, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothStructDistanceLine) { DrawLineRuntimeSub(team, GizmoUtility.ColorStructLine, clothData.structDistanceDataList, false); } if (ClothMonitorMenu.Monitor.UI.DrawClothBendDistanceLine) { DrawLineRuntimeSub(team, GizmoUtility.ColorBendLine, clothData.bendDistanceDataList, false); } if (ClothMonitorMenu.Monitor.UI.DrawClothNearDistanceLine) { DrawLineRuntimeSub(team, GizmoUtility.ColorNearLine, clothData.nearDistanceDataList, false); } if (ClothMonitorMenu.Monitor.UI.DrawClothBase) { DrawLineRuntimeSub(team, Color.red, clothData.structDistanceDataList, true); } } static void DrawLineRuntimeSub( PhysicsTeam team, Color color, RestoreDistanceConstraint.RestoreDistanceData[] distanceDataList, bool useBase ) { if (distanceDataList == null || distanceDataList.Length == 0) return; var manager = MagicaPhysicsManager.Instance; Gizmos.color = color; int cnt = distanceDataList.Length; for (int i = 0; i < cnt; i++) { var data = distanceDataList[i]; int vindex0, vindex1; vindex0 = data.vertexIndex; vindex1 = data.targetVertexIndex; int pindex0 = team.ParticleChunk.startIndex + vindex0; int pindex1 = team.ParticleChunk.startIndex + vindex1; Vector3 pos0 = useBase ? manager.Particle.basePosList[pindex0] : manager.Particle.posList[pindex0]; Vector3 pos1 = useBase ? manager.Particle.basePosList[pindex1] : manager.Particle.posList[pindex1]; Gizmos.DrawLine(pos0, pos1); } } /// /// エディタ状態でのライン表示 /// /// /// /// static void DrawLineClothData( ClothData clothData, List posList, List selList ) { if (clothData == null) return; if (ClothMonitorMenu.Monitor.UI.DrawClothStructDistanceLine) { DrawLineClothDataSub(clothData, posList, GizmoUtility.ColorStructLine, clothData.structDistanceDataList); } if (ClothMonitorMenu.Monitor.UI.DrawClothBendDistanceLine) { DrawLineClothDataSub(clothData, posList, GizmoUtility.ColorBendLine, clothData.bendDistanceDataList); } if (ClothMonitorMenu.Monitor.UI.DrawClothNearDistanceLine) { DrawLineClothDataSub(clothData, posList, GizmoUtility.ColorNearLine, clothData.nearDistanceDataList); } if (ClothMonitorMenu.Monitor.UI.DrawClothBase) { DrawLineClothDataSub(clothData, posList, Color.red, clothData.structDistanceDataList); } } static void DrawLineClothDataSub( ClothData clothData, List posList, Color color, RestoreDistanceConstraint.RestoreDistanceData[] distanceDataList ) { if (distanceDataList == null || distanceDataList.Length == 0) return; Gizmos.color = color; int cnt = distanceDataList.Length; for (int i = 0; i < cnt; i++) { var data = distanceDataList[i]; int index0, index1; index0 = data.vertexIndex; index1 = data.targetVertexIndex; int vindex0 = clothData.useVertexList[index0]; int vindex1 = clothData.useVertexList[index1]; if (vindex0 >= posList.Count || vindex1 >= posList.Count) continue; Vector3 pos0 = posList[vindex0]; Vector3 pos1 = posList[vindex1]; Gizmos.DrawLine(pos0, pos1); } } //========================================================================================= /// /// ランタイム状態での回転ライン表示 /// /// /// /// static void DrawRotationLineRuntime( PhysicsTeam team, ClothData clothData, ClothSetup setup, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothRotationLine == false) return; if (clothData == null) return; if (clothData.parentList == null || clothData.parentList.Count != clothData.VertexUseCount) return; var manager = MagicaPhysicsManager.Instance; Gizmos.color = GizmoUtility.ColorRotationLine; for (int i = 0; i < clothData.VertexUseCount; i++) { int pi = clothData.parentList[i]; if (pi < 0) continue; int pindex0 = team.ParticleChunk.startIndex + i; int pindex1 = team.ParticleChunk.startIndex + pi; Vector3 pos0 = manager.Particle.posList[pindex0]; Vector3 pos1 = manager.Particle.posList[pindex1]; Gizmos.DrawLine(pos0, pos1); } } /// /// エディタ状態での回転ライン表示 /// /// /// /// static void DrawRotationLineClothData( ClothData clothData, List posList, List selList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothRotationLine == false) return; if (clothData == null) return; if (clothData.parentList == null || clothData.parentList.Count != clothData.VertexUseCount) return; Gizmos.color = GizmoUtility.ColorRotationLine; for (int i = 0; i < clothData.VertexUseCount; i++) { int pi = clothData.parentList[i]; if (pi < 0) continue; int vindex0 = clothData.useVertexList[i]; int vindex1 = clothData.useVertexList[pi]; if (vindex0 >= posList.Count || vindex1 >= posList.Count) continue; Vector3 pos0 = posList[vindex0]; Vector3 pos1 = posList[vindex1]; Gizmos.DrawLine(pos0, pos1); } } //========================================================================================= #if false static void DrawAdjustRotationLineRuntime( PhysicsTeam team, ClothData clothData ) { if (ClothMonitorMenu.Monitor.UI.DrawAdjustRotationLine == false) return; var manager = MagicaPhysicsManager.Instance; Gizmos.color = GizmoUtility.ColorAdjustLine; int cnt = clothData.AdjustRotationConstraintCount; for (int i = 0; i < cnt; i++) { var data = clothData.adjustRotationDataList[i]; int tindex = data.targetIndex; if (tindex < 0) tindex = -tindex - 1; int pindex0 = team.ParticleChunk.startIndex + data.keyIndex; int pindex1 = team.ParticleChunk.startIndex + tindex; Vector3 pos0 = manager.Particle.posList[pindex0]; Vector3 pos1 = manager.Particle.posList[pindex1]; Gizmos.DrawLine(pos0, pos1); } } static void DrawAdjustRotationLineClothData( ClothData clothData, List posList ) { if (ClothMonitorMenu.Monitor.UI.DrawAdjustRotationLine == false) return; if (clothData == null) return; Gizmos.color = GizmoUtility.ColorAdjustLine; int cnt = clothData.AdjustRotationConstraintCount; for (int i = 0; i < cnt; i++) { var data = clothData.adjustRotationDataList[i]; int tindex = data.targetIndex; if (tindex < 0) tindex = -tindex - 1; int vindex0 = clothData.useVertexList[data.keyIndex]; int vindex1 = clothData.useVertexList[tindex]; Vector3 pos0 = posList[vindex0]; Vector3 pos1 = posList[vindex1]; Gizmos.DrawLine(pos0, pos1); } } #endif //========================================================================================= /// /// ランタイム状態でのトライアングルベンド表示 /// /// /// /// static void DrawTriangleBendRuntime( PhysicsTeam team, ClothData clothData, ClothSetup setup ) { if (ClothMonitorMenu.Monitor.UI.DrawClothTriangleBend == false) return; var manager = MagicaPhysicsManager.Instance; Gizmos.color = GizmoUtility.ColorTriangle; int cnt = clothData.TriangleBendConstraintCount; for (int i = 0; i < cnt; i++) { var data = clothData.triangleBendDataList[i]; int pindex0 = team.ParticleChunk.startIndex + data.vindex0; int pindex1 = team.ParticleChunk.startIndex + data.vindex1; int pindex2 = team.ParticleChunk.startIndex + data.vindex2; Vector3 pos0 = manager.Particle.posList[pindex0]; Vector3 pos1 = manager.Particle.posList[pindex1]; Vector3 pos2 = manager.Particle.posList[pindex2]; if (data.IsPositionBend() == false) { int pindex3 = team.ParticleChunk.startIndex + data.vindex3; Vector3 pos3 = manager.Particle.posList[pindex3]; Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos0, pos3); Gizmos.DrawLine(pos2, pos3); Gizmos.DrawLine(pos2, pos1); Gizmos.DrawLine(pos3, pos1); } else { Gizmos.DrawLine(pos0, pos1); Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos1, pos2); } } } /// /// エディタ状態でのトライアングルベンド表示 /// /// /// /// static void DrawTriangleBendClothData( ClothData clothData, List posList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothTriangleBend == false) return; if (clothData == null) return; Gizmos.color = GizmoUtility.ColorTriangle; int cnt = clothData.TriangleBendConstraintCount; for (int i = 0; i < cnt; i++) { var data = clothData.triangleBendDataList[i]; int vindex0 = clothData.useVertexList[data.vindex0]; int vindex1 = clothData.useVertexList[data.vindex1]; int vindex2 = clothData.useVertexList[data.vindex2]; Vector3 pos0 = posList[vindex0]; Vector3 pos1 = posList[vindex1]; Vector3 pos2 = posList[vindex2]; if (data.IsPositionBend() == false) { int vindex3 = clothData.useVertexList[data.vindex3]; Vector3 pos3 = posList[vindex3]; Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos0, pos3); Gizmos.DrawLine(pos2, pos3); Gizmos.DrawLine(pos2, pos1); Gizmos.DrawLine(pos3, pos1); } else { Gizmos.DrawLine(pos0, pos1); Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos1, pos2); } } } //========================================================================================= #if false /// /// ランタイム状態でのボリューム表示 /// /// /// /// static void DrawVolumeRuntime( PhysicsTeam team, ClothData clothData, ClothSetup setup ) { if (ClothMonitorMenu.Monitor.UI.DrawClothVolume == false) return; var manager = MagicaPhysicsManager.Instance; Gizmos.color = GizmoUtility.ColorTriangle; int cnt = clothData.VolumeConstraintCount; for (int i = 0; i < cnt; i++) { var data = clothData.volumeDataList[i]; int pindex0 = team.ParticleChunk.startIndex + data.vindex0; int pindex1 = team.ParticleChunk.startIndex + data.vindex1; int pindex2 = team.ParticleChunk.startIndex + data.vindex2; int pindex3 = team.ParticleChunk.startIndex + data.vindex3; Vector3 pos0 = manager.Particle.posList[pindex0]; Vector3 pos1 = manager.Particle.posList[pindex1]; Vector3 pos2 = manager.Particle.posList[pindex2]; Vector3 pos3 = manager.Particle.posList[pindex3]; Gizmos.DrawLine(pos0, pos1); Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos0, pos3); Gizmos.DrawLine(pos1, pos2); Gizmos.DrawLine(pos2, pos3); Gizmos.DrawLine(pos3, pos1); } } /// /// エディタ状態でのボリューム表示 /// /// /// /// static void DrawVolumeClothData( ClothData clothData, List posList ) { if (ClothMonitorMenu.Monitor.UI.DrawClothVolume == false) return; if (clothData == null) return; Gizmos.color = GizmoUtility.ColorTriangle; int cnt = clothData.VolumeConstraintCount; for (int i = 0; i < cnt; i++) { var data = clothData.volumeDataList[i]; int vindex0 = clothData.useVertexList[data.vindex0]; int vindex1 = clothData.useVertexList[data.vindex1]; int vindex2 = clothData.useVertexList[data.vindex2]; int vindex3 = clothData.useVertexList[data.vindex3]; Vector3 pos0 = posList[vindex0]; Vector3 pos1 = posList[vindex1]; Vector3 pos2 = posList[vindex2]; Vector3 pos3 = posList[vindex3]; Gizmos.DrawLine(pos0, pos1); Gizmos.DrawLine(pos0, pos2); Gizmos.DrawLine(pos0, pos3); Gizmos.DrawLine(pos1, pos2); Gizmos.DrawLine(pos2, pos3); Gizmos.DrawLine(pos3, pos1); } } #endif } }