-
-
Save FaffyWaffles/e7724e4ea863e8f8cd78837909b29384 to your computer and use it in GitHub Desktop.
Odin Bug Report
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
using Sirenix.OdinInspector; | |
public class MeshDebug : SerializedMonoBehaviour | |
{ | |
private GameObject target; | |
private MeshFilter meshFilter; | |
public enum DrawType { Both, Face, Vertex, Neither }; | |
public DrawType drawType; | |
public enum LabelDrawType { Vertex, Shared }; | |
public LabelDrawType labelDrawType; | |
public enum RayType { Ray, Arrow }; | |
public bool drawNormals = true; | |
[ShowIfGroup("drawNormals")] | |
[FoldoutGroup("drawNormals/Normals", expanded: true)] | |
[Range(.001f, .01f)] public float gizmoSize = .005f; | |
[FoldoutGroup("drawNormals/Normals", expanded: true)] | |
[Range(.001f, .075f)] public float length = .0275f; | |
[FoldoutGroup("drawNormals/Normals", expanded: true)] | |
public RayType rayType; | |
[FoldoutGroup("drawNormals/Normals", expanded: true)] | |
public Color faceColor = Color.green; | |
[FoldoutGroup("drawNormals/Normals", expanded: true)] | |
public Color vertexColor = Color.red; | |
public bool drawLabels; | |
[ShowIfGroup("drawLabels")] | |
[FoldoutGroup("drawLabels/Labels", expanded: true)] | |
[Range(-.05f, .05f)] | |
public float labelOffsetNormal = 0f; | |
[FoldoutGroup("drawLabels/Labels", expanded: true)] | |
[Range(-.01f, .01f)] | |
public float labelOffsetX, labelOffsetY, labelOffsetZ = 0f; | |
public bool drawUVs; | |
public bool drawWireframe = true; | |
public bool drawEdges; | |
public int findIndex = -1; | |
public Color findColor = Color.yellow; | |
private Mesh mesh; | |
public Vector3[] vertices; | |
public int[] triangles; | |
public Vector3[] normals; | |
public Vector2[] uvs; | |
public Color[] gizmoColor; | |
private bool init = false; | |
private void Awake() | |
{ | |
Initialize(); | |
DistinctRandomColors(vertices.Length, out gizmoColor, UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 1f, 1f)); | |
init = true; | |
} | |
private void OnDrawGizmosSelected() | |
{ | |
if (init) | |
{ | |
DrawNormals(); | |
if (drawEdges) | |
DrawEdges(); | |
EditorUtility.SetSelectedWireframeHidden(GetComponent<Renderer>(), !drawWireframe); | |
} | |
} | |
private void Initialize() | |
{ | |
if (target == null) | |
target = this.gameObject; | |
if (meshFilter == null) | |
{ | |
meshFilter = GetComponent<MeshFilter>(); | |
if (meshFilter == null) | |
Debug.LogError("MeshFilter Required"); | |
} | |
mesh = meshFilter.sharedMesh; | |
vertices = mesh.vertices; | |
triangles = mesh.triangles; | |
normals = mesh.normals; | |
uvs = mesh.uv; | |
FindSharedVerts(); | |
} | |
private void DrawNormals() | |
{ | |
switch (drawType) | |
{ | |
case DrawType.Both: | |
DrawFaceNormals(); | |
DrawVertexNormals(); | |
break; | |
case DrawType.Face: | |
DrawFaceNormals(); | |
break; | |
case DrawType.Vertex: | |
DrawVertexNormals(); | |
break; | |
} | |
} | |
//[LabelText("$submeshCount")] | |
//[InfoBox("@\"Submesh Count= \" + submeshCount.ToString()", InfoMessageType.None)] | |
public int submeshCount; | |
public void DrawFaceNormals() | |
{ | |
for (int i = 0; i < triangles.Length; i += 3) | |
{ | |
Vector3 center = FindCenter(i).Item1; | |
Vector3 dir = FindCenter(i).Item2; | |
if (drawNormals) | |
Draw(center, dir, faceColor); | |
if (drawLabels) | |
DrawLabels(center, dir, (i / 3).ToString()); | |
} | |
submeshCount = mesh.subMeshCount; | |
if (WaffleWare.WLists.CheckIndex(findIndex * 3, 0, (triangles.Length / 3) - 1)) | |
{ | |
Vector3 center = FindCenter(findIndex * 3).Item1; | |
Vector3 dir = FindCenter(findIndex * 3).Item2; | |
DrawFound(center, dir, findColor); | |
} | |
} | |
public bool vertexGroups; | |
public void DrawVertexNormals() | |
{ | |
if (labelDrawType == LabelDrawType.Vertex) | |
{ | |
for (int i = 0; i < vertices.Length; i++) | |
{ | |
Vector3 tPoint = transform.TransformPoint(vertices[i]); | |
Vector3 tVector = transform.TransformVector(normals[i]); | |
if (drawNormals) | |
if (vertexGroups) | |
Draw(tPoint, tVector, gizmoColor[i]); | |
else | |
Draw(tPoint, tVector, vertexColor); | |
if (drawLabels) | |
DrawLabels(tPoint, tVector, i.ToString()); | |
if (drawUVs) | |
{ | |
Vector2 uv = uvs[triangles[i]]; | |
DrawLabels(tPoint, tVector, uv.ToString()); | |
} | |
} | |
} | |
else if (labelDrawType == LabelDrawType.Shared) | |
{ | |
for (int i = 0; i < sharedVerts.Count; i++) | |
{ | |
Vector3 tPoint = transform.TransformPoint(sharedVerts[i].vertex); | |
//Vector3 tVector = transform.TransformVector(normals[sharedVerts[i].sharedIndices[0]]); | |
Vector3 tVector = transform.TransformVector(sharedVerts[i].normalAverage); | |
if (drawNormals) | |
if (vertexGroups) | |
Draw(tPoint, tVector, gizmoColor[i]); | |
else | |
Draw(tPoint, tVector, vertexColor); | |
if (drawLabels) | |
DrawLabels(tPoint, tVector, i.ToString()); | |
if (drawUVs) | |
{ | |
Vector2 uv = uvs[triangles[i]]; | |
DrawLabels(tPoint, tVector, uv.ToString()); | |
} | |
} | |
} | |
if (WaffleWare.WLists.CheckIndex(findIndex * 3, 0, vertices.Length)) | |
{ | |
Vector3 iPoint = transform.TransformPoint(vertices[findIndex * 3]); | |
Vector3 iVector = transform.TransformVector(normals[findIndex * 3]); | |
if (WaffleWare.WLists.CheckIndex(findIndex * 3, 0, vertices.Length)) | |
DrawFound(iPoint, iVector, findColor); | |
} | |
} | |
public void Draw(Vector3 from, Vector3 direction, Color color) | |
{ | |
from = target.transform.TransformPoint(from); | |
Vector3 v = from + (direction * .1f); | |
//if (!Physics.Linecast(Camera.current.transform.position, v)) | |
if ((DepthCulling(v) && depthCulling) || !depthCulling) | |
{ | |
Gizmos.color = color; | |
Gizmos.DrawSphere(from, gizmoSize); | |
if (rayType == RayType.Ray) | |
Gizmos.DrawRay(from, direction * length); | |
else if (rayType == RayType.Arrow) | |
{ | |
Handles.color = color; | |
Handles.ArrowHandleCap(0, from, Quaternion.LookRotation(direction), length, EventType.Repaint); | |
} | |
} | |
//if (Camera.current.transform.InverseTransformDirection(direction).z < 0f) | |
//{ | |
//Gizmos.color = color; | |
// Gizmos.DrawSphere(from, .005f); | |
// Gizmos.DrawRay(from, direction * .1f); | |
//} | |
} | |
public void DrawFound(Vector3 from, Vector3 direction, Color color) | |
{ | |
//if (Camera.current.transform.InverseTransformDirection(direction).z < 0f) | |
//{ | |
Gizmos.color = color; | |
Gizmos.DrawSphere(from, .01f); | |
Gizmos.DrawRay(from, direction * 1f); | |
//} | |
} | |
public bool depthCulling; | |
public void DrawLabels(Vector3 from, Vector3 direction, string label) | |
{ | |
from = target.transform.TransformPoint(from); | |
Vector3 labelOffset = new Vector3(labelOffsetX, labelOffsetY, labelOffsetZ); | |
Vector3 v = from + (direction * labelOffsetNormal) + labelOffset; | |
if (drawNormals) | |
v += (direction * length); | |
//if (!Physics.Linecast(Camera.current.transform.position, v)) | |
// Handles.Label(v, label); | |
if ((DepthCulling(v) && depthCulling) || !depthCulling) | |
Handles.Label(v, label); | |
//if (((DepthCulling(target.transform.TransformPoint(v))) && (depthCulling)) || ((!depthCulling))) | |
// Handles.Label(v, label); | |
//if (Camera.current.transform.InverseTransformDirection(direction).z < 0f) | |
//{ | |
// Vector3 v = from + (direction * .1f); | |
// Handles.Label(v, label); | |
//} | |
} | |
public void DrawEdges() | |
{ | |
foreach (var item in edgeDict) | |
{ | |
Edge e = item.Value; | |
if (!e.shared) | |
Debug.DrawLine(e.vertexX, e.vertexY, Color.red); | |
} | |
} | |
public (Vector3, Vector3) FindCenter(int i) | |
{ | |
Vector3 v0 = transform.TransformPoint(vertices[triangles[i]]); | |
Vector3 v1 = transform.TransformPoint(vertices[triangles[i + 1]]); | |
Vector3 v2 = transform.TransformPoint(vertices[triangles[i + 2]]); | |
Vector3 center = (v0 + v1 + v2) / 3; | |
Vector3 dir = Vector3.Cross(v1 - v0, v2 - v0); | |
dir /= dir.magnitude; | |
return (center, dir); | |
} | |
private bool DepthCulling(Vector3 v) ///needs to be mesh collider | |
{ | |
if (Physics.Linecast(Camera.current.transform.position, v)) | |
return false; | |
return true; | |
} | |
[Range(.0001f, .001f)] public float buffer = .0001f; | |
private bool done = false; | |
[HideReferenceObjectPicker] | |
public class Vert | |
{ | |
[HorizontalGroup("Split", Width = 75)] | |
[ListDrawerSettings(Expanded = true)] | |
public List<int> sharedIndices; | |
[HideInInspector] | |
public Vector3 vertex; | |
//[HideInInspector] | |
public Vector3 normalAverage; | |
//[HideInInspector] | |
public List<Vector3> vertNormals = new List<Vector3>(); | |
[VerticalGroup("Split/Right")] | |
[BoxGroup("Split/Right/Vertex"), LabelWidth(15)] | |
public float x, y, z; | |
public Vert(List<int> sharedIndices, Vector3 vertex) | |
{ | |
this.sharedIndices = sharedIndices; | |
this.vertex = vertex; | |
this.x = vertex.x; | |
this.y = vertex.y; | |
this.z = vertex.z; | |
} | |
} | |
[HideReferenceObjectPicker] | |
[ListDrawerSettings(ShowIndexLabels = true, NumberOfItemsPerPage = 10)] | |
public List<Vert> sharedVerts = new List<Vert>(); | |
public Dictionary<int, int> vertDict = new Dictionary<int, int>(); | |
public Dictionary<HashSet<int>, Edge> edgeDict = new Dictionary<HashSet<int>, Edge>(HashSet<int>.CreateSetComparer()); | |
[HideReferenceObjectPicker] | |
public class Edge | |
{ | |
public Vector2Int edgeIndices; | |
public Vector3 vertexX; | |
public Vector3 vertexY; | |
public bool shared; | |
public Edge(Vector2Int edgeIndices, Vector3 vertexX, Vector3 vertexY) | |
{ | |
this.edgeIndices = edgeIndices; | |
this.vertexX = vertexX; | |
this.vertexY = vertexY; | |
} | |
} | |
public List<Vector2Int> edgeIndices = new List<Vector2Int>(); | |
public void FindSharedVerts() | |
{ | |
sharedVerts = new List<Vert>(); | |
vertDict = new Dictionary<int, int>(); | |
edgeDict = new Dictionary<HashSet<int>, Edge>(HashSet<int>.CreateSetComparer()); | |
edgeIndices = new List<Vector2Int>(); | |
HashSet<int> hashedIndices = new HashSet<int>(); | |
for (int i = 0; i < vertices.Length; i++) | |
{ | |
Vert v = new Vert(new List<int>(), vertices[i]); | |
if (!hashedIndices.Contains(i)) | |
{ | |
for (int j = 0; j < vertices.Length; j++) | |
{ | |
if (!hashedIndices.Contains(j)) | |
{ | |
if (Mathf.Abs((vertices[i] - vertices[j]).sqrMagnitude) < (buffer * buffer)) | |
{ | |
hashedIndices.Add(j); | |
v.sharedIndices.Add(j); | |
v.vertNormals.Add(normals[j]); | |
} | |
} | |
} | |
hashedIndices.Add(i); | |
sharedVerts.Add(v); | |
} | |
} | |
int sharedVertCount = sharedVerts.Count; | |
for (int i = 0; i < sharedVertCount; i++) | |
{ | |
sharedVerts[i].normalAverage = Centroid(sharedVerts[i].vertNormals); | |
foreach (int vertIndex in sharedVerts[i].sharedIndices) | |
vertDict.Add(vertIndex, i); | |
} | |
FindSharedEdges(); | |
} | |
public void FindSharedEdges() | |
{ | |
edgeDict = new Dictionary<HashSet<int>, Edge>(HashSet<int>.CreateSetComparer()); | |
for (int i = 0; i <= (triangles.Length / 3) - 1; i++) | |
{ | |
int i0 = triangles[i * 3 + 0]; | |
int i1 = triangles[i * 3 + 1]; | |
int i2 = triangles[i * 3 + 2]; | |
int t0 = vertDict[i0]; | |
int t1 = vertDict[i1]; | |
int t2 = vertDict[i2]; | |
AddEdge(t0, t1); | |
AddEdge(t1, t2); | |
AddEdge(t2, t0); | |
} | |
foreach (var item in edgeDict) | |
{ | |
Edge e = item.Value; | |
if (!e.shared) | |
{ | |
edgeIndices.Add(new Vector2Int(e.edgeIndices.x, e.edgeIndices.y)); | |
edgeIndices.Add(new Vector2Int(e.edgeIndices.y, e.edgeIndices.x)); | |
} | |
} | |
done = true; | |
} | |
void AddEdge(int x, int y) | |
{ | |
HashSet<int> edgeHash = new HashSet<int>(); | |
edgeHash.Add(x); | |
edgeHash.Add(y); | |
if (!edgeDict.ContainsKey(edgeHash)) | |
{ | |
Vector2Int v2 = new Vector2Int(x, y); | |
Vector3 v3X = sharedVerts[x].vertex; | |
Vector3 v3Y = sharedVerts[y].vertex; | |
edgeDict.Add(edgeHash, new Edge(v2, v3X, v3Y)); | |
//edgeIndices.Add(new Vector2Int(x, y)); | |
} | |
else | |
edgeDict[edgeHash].shared = true; | |
} | |
void DistinctRandomColors(int colorCount, out Color[] colors, Color initColor) | |
{ | |
colors = new Color[colorCount]; | |
//Color initColor = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 1f, 1f); | |
colors[0] = initColor; | |
float hue, saturation, value; | |
Color.RGBToHSV(initColor, out hue, out saturation, out value); | |
float normalizedHue = Mathf.Clamp01(hue); | |
for (int i = 1; i < colorCount; i++) | |
{ | |
float angle = (((360 * colorCount) - (360 * i)) / colorCount); | |
float normalized = (angle / 360) + normalizedHue; | |
Color newColor = Color.HSVToRGB(normalized % 1, saturation, value); | |
colors[i] = newColor; | |
} | |
} | |
Vector3 Centroid(List<Vector3> vertNormals) | |
{ | |
Vector3 vSum = new Vector3(); | |
foreach (Vector3 v in vertNormals) | |
vSum += v; | |
return (vSum) / vertNormals.Count; | |
} | |
} |
Author
FaffyWaffles
commented
Jun 1, 2022
This script has been confirmed to be able to reproduce the error by isolating it in a new scene
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment