BITFALL/Assets/Plugins/MagicaCloth2/Scripts/Editor/Cloth/VirtualMeshEditorUtility.cs

497 lines
20 KiB
C#
Raw Normal View History

2023-06-08 14:09:50 +08:00
// Magica Cloth 2.
// Copyright (c) 2023 MagicaSoft.
// https://magicasoft.jp
#if MC2_DEBUG
using System.Collections.Generic;
using Unity.Collections;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
#endif
namespace MagicaCloth2
{
#if MC2_DEBUG
public static partial class VirtualMeshEditorUtility
{
//=========================================================================================
static List<Vector3> positionBuffer0 = new List<Vector3>(1024);
static List<Vector3> positionBuffer1 = new List<Vector3>(1024);
static List<Vector3> positionBuffer2 = new List<Vector3>(1024);
static List<int> segmentBuffer0 = new List<int>(2048);
static List<int> segmentBuffer1 = new List<int>(2048);
static List<int> segmentBuffer2 = new List<int>(2048);
//=========================================================================================
/// <summary>
/// VirtualMeshのデバッグ表示編集用
/// </summary>
/// <param name="vmesh"></param>
/// <param name="debugSettings"></param>
public static void DrawGizmos(VirtualMesh vmesh, VirtualMeshDebugSettings debugSettings, bool selected, bool useHandles)
{
if (debugSettings.enable == false)
return;
if (vmesh == null || vmesh.IsSuccess == false || vmesh.VertexCount == 0)
return;
var t = vmesh.GetCenterTransform();
if (t == null)
return;
using NativeArray<quaternion> dummyRotations = new NativeArray<quaternion>(0, Allocator.TempJob);
DrawGizmosInternal(
useHandles,
true,
selected,
vmesh,
debugSettings,
t,
0,
vmesh.attributes.GetNativeArray(),
vmesh.localPositions.GetNativeArray(),
dummyRotations,
vmesh.localNormals.GetNativeArray(),
vmesh.localTangents.GetNativeArray(),
vmesh.boneWeights.GetNativeArray()
);
}
/// <summary>
/// Proxy/Mappingメッシュのデバッグ表示ランタイム用
/// </summary>
/// <param name="cprocess"></param>
/// <param name="vmesh"></param>
/// <param name="debugSettings"></param>
public static void DrawRuntimeGizmos(ClothProcess cprocess, bool isMapping, VirtualMesh vmesh, VirtualMeshDebugSettings debugSettings, bool selected, bool useHandles)
{
if (cprocess == null || cprocess.IsValid() == false)
return;
if (debugSettings.enable == false)
return;
if (MagicaManager.Team == null)
return;
if (MagicaManager.Team.ContainsTeamData(cprocess.TeamId) == false)
return;
if (vmesh == null || vmesh.IsSuccess == false)
return;
// チームデータ
var tdata = MagicaManager.Team.GetTeamData(cprocess.TeamId);
var tm = MagicaManager.Team;
var vm = MagicaManager.VMesh;
// メッシュタイプにより参照するデータを切り替える
var attributes = vmesh.IsMapping ? vm.mappingAttributes : vm.attributes;
var positions = vmesh.IsMapping ? vm.mappingPositions : vm.positions;
var rotations = vmesh.IsMapping ? vm.mappingRotations : vm.rotations;
var boneWeights = vmesh.IsMapping ? vm.mappingBoneWeights : vm.boneWeights;
int vstart = vmesh.IsMapping ? tm.mappingDataArray[vmesh.mappingId].mappingCommonChunk.startIndex : tdata.proxyCommonChunk.startIndex;
// 座標空間に合わせる
var t = vmesh.GetCenterTransform();
if (t == null)
return;
DrawGizmosInternal(
useHandles,
isMapping ? true : false,
selected,
vmesh,
debugSettings,
t,
vstart,
attributes.GetNativeArray(),
positions.GetNativeArray(),
rotations.GetNativeArray(),
vmesh.localNormals.GetNativeArray(),
vmesh.localTangents.GetNativeArray(),
boneWeights.GetNativeArray()
);
}
static void DrawGizmosInternal(
bool useHandles,
bool isLocal,
bool selected,
VirtualMesh vmesh,
VirtualMeshDebugSettings debugSettings,
Transform center,
int vstart,
NativeArray<VertexAttribute> attributes,
NativeArray<float3> positions,
NativeArray<quaternion> rotations,
NativeArray<float3> normals,
NativeArray<float3> tangents,
NativeArray<VirtualMeshBoneWeight> boneWeights
)
{
// 座標空間に合わせる
if (isLocal)
{
Handles.matrix = center.localToWorldMatrix;
if (useHandles == false)
Gizmos.matrix = center.localToWorldMatrix;
}
else
{
Handles.matrix = Matrix4x4.identity;
Gizmos.matrix = Matrix4x4.identity;
}
// シーンカメラ
var scam = SceneView.currentDrawingSceneView?.camera;
if (scam == null)
return;
quaternion camRot = scam.transform.rotation;
quaternion invCamRot = math.inverse(camRot);
int vcnt = vmesh.VertexCount;
// 表示スケール調整
var scl = isLocal ? 1.0f / (center.lossyScale.magnitude / 1.7305f) : 1.0f;
var drawPointSize = debugSettings.pointSize * scl;
float drawAxisSize = debugSettings.lineSize * scl;
bool hasRotation = rotations.IsCreated && rotations.Length > 0;
float colorScale = selected ? 1 : 0.5f;
// position
if (debugSettings.position)
{
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
var attr = attributes[vstart + i];
var col = Color.black;
if (attr.IsFixed()) col = Color.red;
if (attr.IsMove()) col = Color.green;
GizmoUtility.SetColor(col * colorScale, useHandles);
GizmoUtility.DrawSphere(pos, drawPointSize, useHandles);
}
}
// rotation axis
if (debugSettings.axis)
{
positionBuffer0.Clear();
positionBuffer1.Clear();
positionBuffer2.Clear();
segmentBuffer0.Clear();
segmentBuffer1.Clear();
segmentBuffer2.Clear();
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
var y = hasRotation ? MathUtility.ToNormal(rotations[vstart + i]) : normals[vstart + i];
var z = hasRotation ? MathUtility.ToTangent(rotations[vstart + i]) : tangents[vstart + i];
var x = math.cross(y, z);
positionBuffer0.Add(pos);
positionBuffer0.Add(pos + x * drawAxisSize);
segmentBuffer0.Add(i * 2);
segmentBuffer0.Add(i * 2 + 1);
positionBuffer1.Add(pos);
positionBuffer1.Add(pos + y * drawAxisSize);
segmentBuffer1.Add(i * 2);
segmentBuffer1.Add(i * 2 + 1);
positionBuffer2.Add(pos);
positionBuffer2.Add(pos + z * drawAxisSize);
segmentBuffer2.Add(i * 2);
segmentBuffer2.Add(i * 2 + 1);
}
// x
Handles.color = Color.red * colorScale;
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
// y
Handles.color = Color.green * colorScale;
Handles.DrawLines(positionBuffer1.ToArray(), segmentBuffer1.ToArray());
// z
Handles.color = Color.blue * colorScale;
Handles.DrawLines(positionBuffer2.ToArray(), segmentBuffer2.ToArray());
}
// bone weight
if (debugSettings.boneWeight)
{
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
var bw = boneWeights[vstart + i];
Handles.Label(pos, $"[{bw.boneIndices.x},{bw.boneIndices.y},{bw.boneIndices.z},{bw.boneIndices.w}] w({bw.weights.x:0.###}, {bw.weights.y:0.###}, {bw.weights.z:0.###}, {bw.weights.w:0.###})");
}
}
// number
else if (debugSettings.indexNumber)
{
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
Handles.Label(pos, i.ToString());
}
}
// uv
else if (debugSettings.uv)
{
if (vmesh.IsProxy)
{
// プロキシのみ
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
var uv = vmesh.uv[i];
Handles.Label(pos, $"({uv.x:0.####}, {uv.y:0.####})");
}
}
}
// depth
else if (debugSettings.depth)
{
if (vmesh.IsProxy)
{
if (vmesh.vertexDepths.IsCreated)
{
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
var depth = vmesh.vertexDepths[i];
Handles.Label(pos, $"{depth:0.##}");
}
}
}
}
// root index
else if (debugSettings.rootIndex)
{
if (vmesh.IsProxy)
{
if (vmesh.vertexRootIndices.IsCreated)
{
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
int rootIndex = vmesh.vertexRootIndices[i];
if (rootIndex >= 0)
Handles.Label(pos, $"{rootIndex}");
}
}
}
}
// parent index
else if (debugSettings.parentIndex)
{
if (vmesh.IsProxy)
{
if (vmesh.vertexParentIndices.IsCreated)
{
for (int i = 0; i < vcnt; i++)
{
if (i < debugSettings.vertexMinIndex || i > debugSettings.vertexMaxIndex)
continue;
var pos = positions[vstart + i];
int parentIndex = vmesh.vertexParentIndices[i];
//if (parentIndex < 0)
Handles.Label(pos, $"{parentIndex}");
}
}
}
}
// triangls
if (debugSettings.triangle)
{
positionBuffer0.Clear();
segmentBuffer0.Clear();
switch (vmesh.meshType)
{
case VirtualMesh.MeshType.NormalMesh:
GizmoUtility.SetColor(Color.magenta * colorScale, useHandles);
break;
case VirtualMesh.MeshType.NormalBoneMesh:
GizmoUtility.SetColor(Color.magenta * colorScale, useHandles);
break;
case VirtualMesh.MeshType.ProxyMesh:
GizmoUtility.SetColor(new Color(0.8666f, 0.627f, 0.8666f) * colorScale, useHandles);
break;
case VirtualMesh.MeshType.ProxyBoneMesh:
GizmoUtility.SetColor(new Color(0.8666f, 0.627f, 0.8666f) * colorScale, useHandles);
break;
case VirtualMesh.MeshType.Mapping:
GizmoUtility.SetColor(new Color(0.851f, 0.644f, 0.125f) * colorScale, useHandles);
break;
}
for (int i = 0; i < vmesh.TriangleCount; i++)
{
if (i < debugSettings.triangleMinIndex || i > debugSettings.triangleMaxIndex)
continue;
int3 tri = vmesh.triangles[i];
var pos1 = positions[vstart + tri.x];
var pos2 = positions[vstart + tri.y];
var pos3 = positions[vstart + tri.z];
int index = positionBuffer0.Count;
positionBuffer0.Add(pos1);
positionBuffer0.Add(pos2);
positionBuffer0.Add(pos3);
segmentBuffer0.Add(index);
segmentBuffer0.Add(index + 1);
segmentBuffer0.Add(index + 1);
segmentBuffer0.Add(index + 2);
segmentBuffer0.Add(index + 2);
segmentBuffer0.Add(index);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
// line
if (debugSettings.line)
{
positionBuffer0.Clear();
segmentBuffer0.Clear();
GizmoUtility.SetColor(Color.cyan * colorScale, useHandles);
for (int i = 0; i < vmesh.LineCount; i++)
{
int2 line = vmesh.lines[i];
var pos1 = positions[vstart + line.x];
var pos2 = positions[vstart + line.y];
positionBuffer0.Add(pos1);
positionBuffer0.Add(pos2);
segmentBuffer0.Add(i * 2);
segmentBuffer0.Add(i * 2 + 1);
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
// edge number
if (debugSettings.edgeNumber)
{
int ecnt = vmesh.EdgeCount;
for (int i = 0; i < ecnt; i++)
{
if (i < debugSettings.edgeMinIndex || i > debugSettings.edgeMaxIndex)
continue;
int2 edge = vmesh.edges[i];
var pos1 = positions[vstart + edge.x];
var pos2 = positions[vstart + edge.y];
var c = (pos1 + pos2) * 0.5f;
Handles.Label(c, i.ToString());
}
}
// triangle normal
if (debugSettings.triangleNormal || debugSettings.triangleNumber)
{
positionBuffer0.Clear();
segmentBuffer0.Clear();
Color colF = Color.yellow;
//Color colB = new Color(1.0f, 0.3f, 0.3f, 1.0f);
for (int i = 0; i < vmesh.TriangleCount; i++)
{
if (i < debugSettings.triangleMinIndex || i > debugSettings.triangleMaxIndex)
continue;
int3 tri = vmesh.triangles[i];
var pos1 = positions[vstart + tri.x];
var pos2 = positions[vstart + tri.y];
var pos3 = positions[vstart + tri.z];
var n = MathUtility.TriangleNormal(pos1, pos2, pos3);
var c = MathUtility.TriangleCenter(pos1, pos2, pos3);
if (debugSettings.triangleNormal)
{
var dir = math.mul(invCamRot, n);
//GizmoUtility.SetColor((dir.z < 0.0f ? colF : colB) * colorScale, useHandles);
//GizmoUtility.DrawLine(c, c + n * drawAxisSize, useHandles);
positionBuffer0.Add(c);
positionBuffer0.Add(c + n * drawAxisSize);
segmentBuffer0.Add(i * 2);
segmentBuffer0.Add(i * 2 + 1);
}
if (debugSettings.triangleNumber)
Handles.Label(c, i.ToString());
}
if (debugSettings.triangleNormal)
{
GizmoUtility.SetColor(colF * colorScale, useHandles);
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
}
// base line
if (vmesh.IsProxy)
{
// プロキシのみ
if (debugSettings.baseLine && vmesh.BaseLineCount > 0)
{
GizmoUtility.SetColor(new Color(1.0f, 0.27f, 0.0f) * colorScale, useHandles);
positionBuffer0.Clear();
segmentBuffer0.Clear();
for (int i = 0; i < vcnt; i++)
{
int pindex = vmesh.vertexParentIndices[i];
if (pindex >= 0)
{
var pos = positions[vstart + i];
var ppos = positions[vstart + pindex];
//GizmoUtility.DrawLine(pos, ppos, useHandles);
positionBuffer0.Add(pos);
positionBuffer0.Add(ppos);
segmentBuffer0.Add(i * 2);
segmentBuffer0.Add(i * 2 + 1);
}
}
Handles.DrawLines(positionBuffer0.ToArray(), segmentBuffer0.ToArray());
}
}
// 空間を戻す
Handles.matrix = Matrix4x4.identity;
if (useHandles == false)
Gizmos.matrix = Matrix4x4.identity;
// bone name
if (debugSettings.boneName)
{
int cnt = vmesh.transformData.Count;
for (int i = 0; i < cnt; i++)
{
var t = vmesh.transformData.GetTransformFromIndex(i);
if (t)
{
var pos = t.position;
Handles.Label(pos, $"[{i}] {t.name}");
}
}
}
}
}
#endif // MC_DEBUG
}