MeshAdjacencyBuilder.cs
1 using System.Collections.Generic; 2 using UnityEngine; 3 using UnityEngine.Rendering; 4 5 /// <summary> 6 /// Converts a mesh so its index buffer encodes adjacency information 7 /// for use with geometry shaders that declare `triangleadj`. 8 /// </summary> 9 [RequireComponent(typeof(MeshFilter))] 10 public class MeshAdjacencyBuilder : MonoBehaviour 11 { 12 [ContextMenu("Build Adjacency Mesh")] 13 public void BuildAdjacencyMesh() 14 { 15 MeshFilter mf = GetComponent<MeshFilter>(); 16 Mesh original = mf.sharedMesh; 17 if (original == null) 18 { 19 Debug.LogError("No mesh found!"); 20 return; 21 } 22 23 Mesh adjMesh = BuildAdjacency(original); 24 mf.sharedMesh = adjMesh; 25 } 26 27 Mesh BuildAdjacency(Mesh mesh) 28 { 29 // Get data 30 Vector3[] verts = mesh.vertices; 31 int[] indices = mesh.triangles; 32 33 // Build edge → opposite vertex map 34 var edgeToVertex = new Dictionary<(int, int), int>(); 35 for (int i = 0; i < indices.Length; i += 3) 36 { 37 int v0 = indices[i]; 38 int v1 = indices[i + 1]; 39 int v2 = indices[i + 2]; 40 41 AddEdge(edgeToVertex, v0, v1, v2); 42 AddEdge(edgeToVertex, v1, v2, v0); 43 AddEdge(edgeToVertex, v2, v0, v1); 44 } 45 46 // New index buffer: 6 indices per triangle 47 List<int> newIndices = new List<int>(); 48 for (int i = 0; i < indices.Length; i += 3) 49 { 50 int v0 = indices[i]; 51 int v1 = indices[i + 1]; 52 int v2 = indices[i + 2]; 53 54 int a0 = FindAdj(edgeToVertex, v0, v1); 55 int a1 = FindAdj(edgeToVertex, v1, v2); 56 int a2 = FindAdj(edgeToVertex, v2, v0); 57 58 newIndices.Add(v0); newIndices.Add(a0); 59 newIndices.Add(v1); newIndices.Add(a1); 60 newIndices.Add(v2); newIndices.Add(a2); 61 } 62 63 // Build new mesh 64 Mesh adjMesh = new Mesh(); 65 adjMesh.name = mesh.name + "_Adjacency"; 66 adjMesh.vertices = verts; 67 adjMesh.normals = mesh.normals; 68 adjMesh.uv = mesh.uv; 69 adjMesh.uv2 = mesh.uv2; 70 adjMesh.colors = mesh.colors; 71 adjMesh.tangents = mesh.tangents; 72 adjMesh.SetIndices(newIndices.ToArray(), MeshTopology.Triangles, 0); 73 return adjMesh; 74 } 75 76 void AddEdge(Dictionary<(int, int), int> map, int v0, int v1, int opposite) 77 { 78 var key = (Mathf.Min(v0, v1), Mathf.Max(v0, v1)); 79 if (!map.ContainsKey(key)) 80 map[key] = opposite; 81 } 82 83 int FindAdj(Dictionary<(int, int), int> map, int v0, int v1) 84 { 85 var key = (Mathf.Min(v0, v1), Mathf.Max(v0, v1)); 86 if (map.TryGetValue(key, out int adj)) 87 return adj; 88 89 // No adjacent triangle (boundary edge) → duplicate one of the edge vertices 90 return v0; 91 } 92 }