render-zig

A 3D rendering engine written in Zig
git clone git://git.christianermann.dev/render-zig
Log | Files | Refs

half_edge_map.zig (2107B)


      1 const std = @import("std");
      2 
      3 const HalfEdgeMap = @This();
      4 
      5 const HalfEdge = struct {
      6     head: u32,
      7     tail: u32,
      8 };
      9 
     10 map: std.AutoArrayHashMapUnmanaged(HalfEdge, u32),
     11 
     12 pub fn init(indices: []u32, allocator: std.mem.Allocator) !HalfEdgeMap {
     13     const num_indices: u32 = @intCast(indices.len);
     14     const num_triangles = num_indices / 3;
     15 
     16     var map = std.AutoArrayHashMapUnmanaged(HalfEdge, u32){};
     17     try map.ensureTotalCapacity(allocator, num_indices);
     18 
     19     for (0..num_triangles) |triangle_idx| {
     20         const i = @as(u32, @intCast(triangle_idx)) * 3;
     21         const a = indices[i];
     22         const b = indices[i + 1];
     23         const c = indices[i + 2];
     24         map.putAssumeCapacityNoClobber(.{ .head = a, .tail = b }, c);
     25         map.putAssumeCapacityNoClobber(.{ .head = b, .tail = c }, a);
     26         map.putAssumeCapacityNoClobber(.{ .head = c, .tail = a }, b);
     27     }
     28     return .{
     29         .map = map,
     30     };
     31 }
     32 
     33 pub fn insert(self: *HalfEdgeMap, tri: [3]u32) void {
     34     const a = tri[0];
     35     const b = tri[1];
     36     const c = tri[2];
     37     self.map.putAssumeCapacityNoClobber(.{ .head = a, .tail = b }, c);
     38     self.map.putAssumeCapacityNoClobber(.{ .head = b, .tail = c }, a);
     39     self.map.putAssumeCapacityNoClobber(.{ .head = c, .tail = a }, b);
     40 }
     41 
     42 pub fn remove(self: *HalfEdgeMap, tri: [3]u32) bool {
     43     const success0 = self.map.swapRemove(.{ .head = tri[0], .tail = tri[1] });
     44     const success1 = self.map.swapRemove(.{ .head = tri[1], .tail = tri[2] });
     45     const success2 = self.map.swapRemove(.{ .head = tri[2], .tail = tri[0] });
     46     return success0 and success1 and success2;
     47 }
     48 
     49 pub fn adjacentTo(self: *HalfEdgeMap, tri: [3]u32, side: u32) ?[3]u32 {
     50     const a = tri[(side + 1) % 3];
     51     const b = tri[side];
     52     const c = self.map.get(.{ .head = a, .tail = b }) orelse {
     53         return null;
     54     };
     55     return [3]u32{ a, b, c };
     56 }
     57 
     58 pub fn count(self: *const HalfEdgeMap) usize {
     59     return self.map.count();
     60 }
     61 
     62 pub fn pop(self: *HalfEdgeMap) [3]u32 {
     63     const kv = self.map.pop();
     64     const tri = [3]u32{ kv.key.head, kv.key.tail, kv.value };
     65     _ = self.remove(tri);
     66     return tri;
     67 }