diff options
| author | yum <yum.food.vr@gmail.com> | 2025-06-11 16:44:24 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-06-11 16:44:24 -0700 |
| commit | 5e7f865ece142d8a231983abf2af80392238d6cd (patch) | |
| tree | 2aab3146ec1a4983864acdf86aa0f30320a32818 /DecodeVertexData.cs | |
| parent | ee4cef4d76f7e4ee4107a0f54f605a6bfacbdfa5 (diff) | |
Submesh size calculations now occur in rotated basis
Fixes a bug where rotated submeshes would look weird.
Also optimize the visualizer by limiting it to the N nearest verts.
Diffstat (limited to 'DecodeVertexData.cs')
| -rw-r--r-- | DecodeVertexData.cs | 252 |
1 files changed, 134 insertions, 118 deletions
diff --git a/DecodeVertexData.cs b/DecodeVertexData.cs index 32933ce..d248773 100644 --- a/DecodeVertexData.cs +++ b/DecodeVertexData.cs @@ -1,184 +1,200 @@ using UnityEngine; using System.Collections.Generic; +using System.Linq; public class DecodeVertexVectors : MonoBehaviour { - [Header("Edge Interpolation")] - [SerializeField] private int edgeSubdivisions = 5; - [SerializeField] private float edgeGizmoScale = 0.3f; - [SerializeField] private Color edgeVectorColor = new Color(0.5f, 0.8f, 1f, 0.7f); - [SerializeField] private Color correctedVectorColor = new Color(1f, 0.5f, 0.2f, 0.7f); - - [Header("Orientation Visualization")] + [Header("Display Settings")] + [SerializeField] private int maxVertices = 100; + [SerializeField] private float vectorScale = 0.3f; + + [Header("Edge Visualization")] + [SerializeField] private bool showEdges = true; + [SerializeField] private int edgeSubdivisions = 2; + + [Header("Orientation")] [SerializeField] private bool showOrientations = true; - [SerializeField] private bool showAllAxes = true; - [SerializeField] private float orientationVectorLength = 1.0f; - + [SerializeField] private float orientationScale = 1.0f; + [Header("UV Channels")] [SerializeField] private int quaternionXYChannel = 1; [SerializeField] private int quaternionZWChannel = 2; - + [Header("Colors")] + [SerializeField] private Color vectorColor = new Color(0.5f, 0.8f, 1f); + [SerializeField] private Color correctedVectorColor = new Color(1f, 0.5f, 0.2f); [SerializeField] private Color forwardColor = Color.blue; - [SerializeField] private Color rightColor = Color.red; - [SerializeField] private Color upColor = Color.green; private void OnDrawGizmos() { var meshFilter = GetComponent<MeshFilter>(); - if (meshFilter == null) return; - + if (!meshFilter || !meshFilter.sharedMesh) return; + var mesh = meshFilter.sharedMesh; - if (mesh == null) return; - var vertices = mesh.vertices; - var vertexColors = mesh.colors; - - if (vertexColors != null && vertexColors.Length > 0) + var colors = mesh.colors; + + // Draw vertex vectors from colors + if (colors != null && colors.Length > 0) { - DrawInterpolatedEdges(mesh, vertices, vertexColors); + DrawVertexVectors(mesh, vertices, colors); } - + + // Draw orientations from UVs if (showOrientations) { DrawOrientations(mesh, vertices); } } - - void DrawInterpolatedEdges(Mesh mesh, Vector3[] vertices, Color[] vertexColors) + + void DrawVertexVectors(Mesh mesh, Vector3[] vertices, Color[] colors) { - var triangles = mesh.triangles; - HashSet<(int, int)> drawnEdges = new HashSet<(int, int)>(); - Vector2[] uvXY = GetUVData(mesh, quaternionXYChannel); Vector2[] uvZW = GetUVData(mesh, quaternionZWChannel); - bool hasQuaternions = uvXY != null && uvZW != null && uvXY.Length > 0 && uvZW.Length > 0; - - for (int i = 0; i < triangles.Length; i += 3) + bool hasQuaternions = uvXY != null && uvZW != null; + + int vertexStep = Mathf.Max(1, vertices.Length / maxVertices); + + // Draw vectors at vertices + for (int i = 0; i < vertices.Length; i += vertexStep) + { + if (i >= colors.Length) break; + + Vector3 worldPos = transform.TransformPoint(vertices[i]); + Vector3 decodedVector = DecodeVectorFromColor(colors[i]); + + // Basic vector + Gizmos.color = vectorColor; + DrawVector(worldPos, transform.TransformDirection(decodedVector), vectorScale); + + // Quaternion-corrected vector + if (hasQuaternions && i < uvXY.Length && i < uvZW.Length) + { + Quaternion quat = GetQuaternionFromUV(uvXY[i], uvZW[i]); + Vector3 corrected = quat * decodedVector; + + Gizmos.color = correctedVectorColor; + DrawVector(worldPos, transform.TransformDirection(corrected), vectorScale); + } + } + + // Draw edge interpolations + if (showEdges && edgeSubdivisions > 0) + { + DrawEdgeInterpolations(mesh, vertices, colors, uvXY, uvZW); + } + } + + void DrawEdgeInterpolations(Mesh mesh, Vector3[] vertices, Color[] colors, Vector2[] uvXY, Vector2[] uvZW) + { + var triangles = mesh.triangles; + HashSet<(int, int)> drawnEdges = new HashSet<(int, int)>(); + bool hasQuaternions = uvXY != null && uvZW != null; + + for (int i = 0; i < triangles.Length && drawnEdges.Count < maxVertices/2; i += 3) { for (int j = 0; j < 3; j++) { int v1 = triangles[i + j]; int v2 = triangles[i + ((j + 1) % 3)]; - + var edge = v1 < v2 ? (v1, v2) : (v2, v1); - if (drawnEdges.Contains(edge)) continue; - drawnEdges.Add(edge); - + if (!drawnEdges.Add(edge)) continue; + if (v1 >= vertices.Length || v2 >= vertices.Length || - v1 >= vertexColors.Length || v2 >= vertexColors.Length) - continue; - - bool canUseQuaternions = hasQuaternions && - v1 < uvXY.Length && v2 < uvXY.Length && - v1 < uvZW.Length && v2 < uvZW.Length; - - for (int k = 0; k <= edgeSubdivisions; k++) + v1 >= colors.Length || v2 >= colors.Length) continue; + + // Draw subdivisions along edge + for (int k = 1; k < edgeSubdivisions; k++) { float t = k / (float)edgeSubdivisions; - - Vector3 localPos = Vector3.Lerp(vertices[v1], vertices[v2], t); - Vector3 worldPos = transform.TransformPoint(localPos); - - Color interpolatedColor = Color.Lerp(vertexColors[v1], vertexColors[v2], t); - Vector3 decodedVector = DecodeVectorFromColor(interpolatedColor); - - Gizmos.color = edgeVectorColor; - Vector3 worldVector = transform.TransformDirection(decodedVector); - DrawVector(worldPos, worldVector, edgeGizmoScale); - - if (canUseQuaternions) + Vector3 pos = Vector3.Lerp(vertices[v1], vertices[v2], t); + Color col = Color.Lerp(colors[v1], colors[v2], t); + + Vector3 worldPos = transform.TransformPoint(pos); + Vector3 vec = DecodeVectorFromColor(col); + + // Basic vector + Gizmos.color = vectorColor * 0.7f; // Slightly dimmer for edge points + DrawVector(worldPos, transform.TransformDirection(vec), vectorScale * 0.8f); + + // Quaternion-corrected vector + if (hasQuaternions && v1 < uvXY.Length && v2 < uvXY.Length && + v1 < uvZW.Length && v2 < uvZW.Length) { - Quaternion q1 = GetQuaternionFromUV(uvXY[v1], uvZW[v1]); - Quaternion q2 = GetQuaternionFromUV(uvXY[v2], uvZW[v2]); - // Slerp is more correct, but lerp is what we'll actually get in the shader. - Quaternion interpolatedQuat = Quaternion.Lerp(q1, q2, t); - - Vector3 correctedVector = interpolatedQuat * decodedVector; - Vector3 worldCorrectedVector = transform.TransformDirection(correctedVector); - - Gizmos.color = correctedVectorColor; - DrawVector(worldPos, worldCorrectedVector, edgeGizmoScale); + Vector2 interpXY = Vector2.Lerp(uvXY[v1], uvXY[v2], t); + Vector2 interpZW = Vector2.Lerp(uvZW[v1], uvZW[v2], t); + Quaternion interpQuat = GetQuaternionFromUV(interpXY, interpZW); + Vector3 corrected = interpQuat * vec; + + Gizmos.color = correctedVectorColor * 0.7f; // Slightly dimmer for edge points + DrawVector(worldPos, transform.TransformDirection(corrected), vectorScale * 0.8f); } } } } } - - void DrawVector(Vector3 origin, Vector3 direction, float scale) - { - Vector3 end = origin + direction * scale; - Gizmos.DrawSphere(end, 0.02f); - Gizmos.DrawLine(origin, end); - } - - Quaternion GetQuaternionFromUV(Vector2 xy, Vector2 zw) - { - float x = xy.x; - float y = xy.y; - float z = zw.x; - float w = zw.y; - - return new Quaternion(x, y, z, w).normalized; - } - + void DrawOrientations(Mesh mesh, Vector3[] vertices) { Vector2[] uvXY = GetUVData(mesh, quaternionXYChannel); Vector2[] uvZW = GetUVData(mesh, quaternionZWChannel); - - if (uvXY == null || uvZW == null || uvXY.Length == 0 || uvZW.Length == 0) return; - - int vertexCount = Mathf.Min(vertices.Length, uvXY.Length, uvZW.Length); - - for (int vertIdx = 0; vertIdx < vertexCount; vertIdx++) + + if (uvXY == null || uvZW == null) return; + + int vertexStep = Mathf.Max(1, vertices.Length / maxVertices); + + for (int i = 0; i < vertices.Length; i += vertexStep) { - Quaternion quat = GetQuaternionFromUV(uvXY[vertIdx], uvZW[vertIdx]); - - Vector3 worldPos = transform.TransformPoint(vertices[vertIdx]); - + if (i >= uvXY.Length || i >= uvZW.Length) break; + + Vector3 worldPos = transform.TransformPoint(vertices[i]); + Quaternion quat = GetQuaternionFromUV(uvXY[i], uvZW[i]); + + // Draw forward direction + Gizmos.color = forwardColor; Vector3 forward = transform.TransformDirection(quat * Vector3.forward); - DrawArrow(worldPos, forward, forwardColor, orientationVectorLength); - - if (showAllAxes) - { - Vector3 right = transform.TransformDirection(quat * Vector3.right); - Vector3 up = transform.TransformDirection(quat * Vector3.up); - DrawArrow(worldPos, right, rightColor, orientationVectorLength * 0.8f); - DrawArrow(worldPos, up, upColor, orientationVectorLength * 0.8f); - } + DrawArrow(worldPos, forward, orientationScale); } } - - void DrawArrow(Vector3 origin, Vector3 direction, Color color, float length) + + void DrawVector(Vector3 origin, Vector3 direction, float scale) + { + Vector3 end = origin + direction * scale; + Gizmos.DrawLine(origin, end); + Gizmos.DrawSphere(end, 0.02f); + } + + void DrawArrow(Vector3 origin, Vector3 direction, float length) { - Gizmos.color = color; - Vector3 end = origin + direction * length; Gizmos.DrawLine(origin, end); - + + // Simple arrowhead Vector3 right = Vector3.Cross(direction, Vector3.up).normalized; if (right.magnitude < 0.01f) right = Vector3.Cross(direction, Vector3.right).normalized; - + Vector3 arrowBack = -direction * length * 0.2f; Vector3 arrowSide = right * length * 0.1f; - + Gizmos.DrawLine(end, end + arrowBack + arrowSide); Gizmos.DrawLine(end, end + arrowBack - arrowSide); - - Gizmos.DrawSphere(origin, 0.05f); } - - n (-1 to 1), aVectorontains scale factor. - /// </summary> - + + Quaternion GetQuaternionFromUV(Vector2 xy, Vector2 zw) + { + return new Quaternion(xy.x, xy.y, zw.x, zw.y).normalized; + } + + Vector3 DecodeVectorFromColor(Color color) + { return new Vector3( - (color.r * 2.0f - 1.0f), - (color.g * 2.0f - 1.0f), - (color.b * 2.0f - 1.0f)) / color.a; + color.r * 2.0f - 1.0f, + color.g * 2.0f - 1.0f, + color.b * 2.0f - 1.0f) / color.a; } - + Vector2[] GetUVData(Mesh mesh, int channel) { switch (channel) |
