package halfedge Vec3 :: [3]f32 Vertex :: struct { pos: Vec3, edge: Edge_Index, } Face :: struct { edge: Edge_Index, } Vertex_Index :: distinct u16 Face_Index :: distinct u16 Edge_Index :: distinct i16 Half_Edge :: struct { origin: Vertex_Index, twin: Edge_Index, face: Face_Index, next: Edge_Index, prev: Edge_Index, } Half_Edge_Mesh :: struct { vertices: []Vertex, faces: []Face, edges: []Half_Edge, } mesh_from_vertex_index_list :: proc( vertices: []Vec3, indices: []u16, allocator := context.allocator, ) -> Half_Edge_Mesh { mesh: Half_Edge_Mesh verts := make([]Vertex, len(vertices), allocator) faces := make([]Face, len(indices) / 3, allocator) edges := make([]Half_Edge, len(indices), allocator) mesh.vertices = verts mesh.faces = faces mesh.edges = edges for pos, i in vertices { verts[i].pos = pos verts[i].edge = -1 } temp_edges: map[[2]u16]Edge_Index = make_map(map[[2]u16]Edge_Index, context.temp_allocator) triangle_num := len(indices) / 3 for i in 0 ..< triangle_num { i1, i2, i3 := indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2] // v1, v2, v3 := vertices[i1], vertices[i2], vertices[i3] e1, e2, e3 := i * 3 + 0, i * 3 + 1, i * 3 + 2 faces[i].edge = Edge_Index(e1) edges[e1] = { origin = Vertex_Index(i1), twin = -1, face = Face_Index(i), next = Edge_Index(e2), prev = Edge_Index(e3), } edges[e2] = { origin = Vertex_Index(i2), twin = -1, face = Face_Index(i), next = Edge_Index(e3), prev = Edge_Index(e1), } edges[e3] = { origin = Vertex_Index(i3), twin = -1, face = Face_Index(i), next = Edge_Index(e1), prev = Edge_Index(e2), } edge_stable_indices := [][2]u16 { {min(i1, i2), max(i1, i2)}, {min(i2, i3), max(i2, i3)}, {min(i3, i1), max(i3, i1)}, } for stable_idx, j in edge_stable_indices { twin, ok := temp_edges[stable_idx] ei := i * 3 + j if ok { edges[ei].twin = twin edges[twin].twin = Edge_Index(ei) } else { temp_edges[stable_idx] = Edge_Index(ei) } } } return mesh }