Zig utility library
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add math module containing angles and projection matrices

IamPyu ca718108 d4fecfdf

+188 -47
+1 -1
README.md
··· 1 1 # mitochondria 2 2 3 - Zig utility library providing data structures, linear algebra, and helper functions 3 + Zig utility library providing data structures, linear algebra, and helper functions.
+68 -46
src/la.zig
··· 1 1 const std = @import("std"); 2 2 const math = std.math; 3 + const assert = std.debug.assert; 3 4 4 5 /// Create a `columns`x`rows` matrix of `T` 5 6 pub fn Matrix(comptime T: type, rows: usize, columns: usize) type { 6 - std.debug.assert(rows > 0); 7 - std.debug.assert(columns > 0); 7 + assert(rows > 0); 8 + assert(columns > 0); 8 9 9 10 { 10 11 const t = @typeInfo(T); ··· 61 62 62 63 /// Add all elements of the matrix to another matrix 63 64 pub fn add(self: *const Self, other: *const Self) Self { 64 - var mat = self.copy(); 65 + var out = self.copy(); 65 66 66 - for (mat.inner, 0..) |row, i| { 67 - mat.inner[i] = row + other.inner[i]; 67 + for (out.inner, 0..) |row, i| { 68 + out.inner[i] = row + other.inner[i]; 68 69 } 69 70 70 - return mat; 71 + return out; 71 72 } 72 73 73 74 /// Subtract all elements of the matrix from another matrix 74 75 pub fn sub(self: *const Self, other: *const Self) Self { 75 - var mat = self.copy(); 76 + var out = self.copy(); 76 77 77 - for (mat.inner, 0..) |row, i| { 78 - mat.inner[i] = row - other.inner[i]; 78 + for (out.inner, 0..) |row, i| { 79 + out.inner[i] = row - other.inner[i]; 79 80 } 80 81 81 - return mat; 82 + return out; 82 83 } 83 84 84 85 /// Multiply all elements of the matrix by a scalar 85 86 pub fn mul(self: *const Self, scalar: T) Self { 86 - var mat = self.copy(); 87 + var out = self.copy(); 87 88 88 - for (mat.inner, 0..) |row, i| { 89 - mat.inner[i] = row * @as(Row, @splat(scalar)); 89 + for (out.inner, 0..) |row, i| { 90 + out.inner[i] = row * @as(Row, @splat(scalar)); 90 91 } 91 92 92 - return mat; 93 + return out; 93 94 } 94 95 95 96 /// Multiply a matrix with another matrix 96 97 /// Each element in the matrix is multiplied by the 97 98 /// element at the same index of the other matrix 98 99 pub fn mul2(self: *const Self, other: *const Self) Self { 99 - var mat = self.copy(); 100 + var out = self.copy(); 100 101 101 - for (mat.inner, other.inner, 0..) |r1, r2, i| { 102 - mat.inner[i] = r1 * r2; 102 + for (out.inner, other.inner, 0..) |r1, r2, i| { 103 + out.inner[i] = r1 * r2; 103 104 } 104 105 105 - return mat; 106 + return out; 106 107 } 107 108 108 109 /// Divide all elements of the matrix by a scalar 109 110 pub fn div(self: *const Self, scalar: T) Self { 110 - var mat = self.copy(); 111 + var out = self.copy(); 111 112 112 - for (mat.inner, 0..) |row, i| { 113 - mat.inner[i] = row / @as(Row, @splat(scalar)); 113 + for (out.inner, 0..) |row, i| { 114 + out.inner[i] = row / @as(Row, @splat(scalar)); 114 115 } 115 116 116 - return mat; 117 + return out; 117 118 } 118 119 119 120 /// Divide a matrix by another matrix 120 121 /// Each element in the matrix is divided by the 121 122 /// element at the same index of the other matrix 122 123 pub fn div2(self: *const Self, other: *const Self) Self { 123 - var mat = self.copy(); 124 + var out = self.copy(); 124 125 125 - for (mat.inner, other.inner, 0..) |r1, r2, i| { 126 - mat.inner[i] = r1 / r2; 126 + for (out.inner, other.inner, 0..) |r1, r2, i| { 127 + out.inner[i] = r1 / r2; 127 128 } 128 129 129 - return mat; 130 + return out; 130 131 } 131 132 132 133 /// Get the magnitude of the vector ··· 203 204 204 205 /// Call `func` on all the elements of the matrix 205 206 pub fn map(self: *const Self, func: *const fn (T) T) Self { 206 - var mat = self.copy(); 207 + var out = self.copy(); 207 208 208 - for (0..mat.inner.len) |i| { 209 - for (0..mat.inner[i].len) |j| { 210 - mat.inner[i][j] = func(mat.inner[i][j]); 209 + for (0..out.inner.len) |i| { 210 + for (0..out.inner[i].len) |j| { 211 + out.inner[i][j] = func(out.inner[i][j]); 211 212 } 212 213 } 213 214 214 - return mat; 215 + return out; 215 216 } 216 217 217 218 /// Return a X unit matrix 218 219 pub fn unitX() Self { 219 - var mat = Self.zeroed(); 220 + var out = Self.zeroed(); 220 221 221 - for (&mat.inner) |*row| { 222 + for (&out.inner) |*row| { 222 223 row[0] = 1; 223 224 } 224 225 225 - return mat; 226 + return out; 226 227 } 227 228 228 229 /// Return a Y unit matrix 229 230 pub fn unitY() Self { 230 - std.debug.assert(rows >= 2); 231 + assert(rows >= 2); 231 232 232 - var mat = Self.zeroed(); 233 + var out = Self.zeroed(); 233 234 234 - for (&mat.inner) |*row| { 235 + for (&out.inner) |*row| { 235 236 row[1] = 1; 236 237 } 237 238 238 - return mat; 239 + return out; 239 240 } 240 241 241 242 /// Return a Z unit matrix 242 243 pub fn unitZ() Self { 243 - std.debug.assert(rows >= 3); 244 + assert(rows >= 3); 244 245 245 - var mat = Self.zeroed(); 246 + var out = Self.zeroed(); 246 247 247 - for (&mat.inner) |*row| { 248 + for (&out.inner) |*row| { 248 249 row[2] = 1; 249 250 } 250 251 251 - return mat; 252 + return out; 252 253 } 253 254 254 255 /// Return a W unit matrix 255 256 pub fn unitW() Self { 256 - std.debug.assert(rows >= 4); 257 + assert(rows >= 4); 257 258 258 - var mat = Self.zeroed(); 259 + var out = Self.zeroed(); 259 260 260 - for (&mat.inner) |*row| { 261 + for (&out.inner) |*row| { 261 262 row[3] = 1; 262 263 } 263 264 264 - return mat; 265 + return out; 265 266 } 266 267 }; 267 268 } ··· 302 303 pub const Mat4D = Matrix(f64, 4, 4); 303 304 304 305 // TODO: idk how the fuck i will, but add quaternions eventually. 306 + 307 + pub fn vec(comptime T: type, comptime components: usize, v: @Vector(components, T)) Vector(T, components) { 308 + return Vector(T, components).init(.{v}); 309 + } 310 + 311 + pub fn mat( 312 + comptime T: type, 313 + comptime rows: usize, 314 + comptime columns: usize, 315 + rep: [columns]@Vector(rows, T), 316 + ) Matrix(T, rows, columns) { 317 + return Matrix(T, rows, columns).init(rep); 318 + } 305 319 306 320 test "mul" { 307 321 const x = Matrix(f32, 3, 5).init(.{ ··· 412 426 try std.testing.expectEqual(rm.inner[0], .{ 27, 30 }); 413 427 try std.testing.expectEqual(rm.inner[1], .{ -35, 36 }); 414 428 } 429 + 430 + test "shorthand" { 431 + _ = vec(f32, 2, .{ 3, 4 }); 432 + _ = mat(f32, 2, 2, .{ 433 + .{ 3, 4 }, 434 + .{ 5, 6 }, 435 + }); 436 + }
+116
src/math.zig
··· 1 + const std = @import("std"); 2 + const math = std.math; 3 + 4 + const la = @import("mitochondria").la; 5 + const Matrix = la.Matrix; 6 + const Vector = la.Vector; 7 + const vec = la.vec; 8 + const mat = la.mat; 9 + 10 + pub fn Angle(comptime T: type) type { 11 + return union(enum) { 12 + const Self = @This(); 13 + 14 + Rad: T, 15 + Deg: T, 16 + 17 + /// Initialize an `Angle` from degrees 18 + pub fn initDeg(v: T) Self { 19 + return Self{ .Deg = v }; 20 + } 21 + 22 + /// Initialize an `Angle` from radians 23 + pub fn initRad(v: T) Self { 24 + return Self{ .Rad = v }; 25 + } 26 + 27 + /// Return the angle as degrees 28 + pub fn degrees(self: Self) T { 29 + return switch (self) { 30 + .Rad => |v| math.radiansToDegrees(v), 31 + .Deg => |v| v, 32 + }; 33 + } 34 + 35 + /// Return the angle as radians 36 + pub fn radians(self: Self) T { 37 + return switch (self) { 38 + .Rad => |v| v, 39 + .Deg => |v| math.degreesToRadians(v), 40 + }; 41 + } 42 + }; 43 + } 44 + 45 + pub fn angleDeg(v: anytype) Angle(@TypeOf(v)) { 46 + return Angle(@TypeOf(v)).initDeg(v); 47 + } 48 + 49 + pub fn angleRad(v: anytype) Angle(@TypeOf(v)) { 50 + return Angle(@TypeOf(v)).initRad(v); 51 + } 52 + 53 + /// Create a perspective projection matrix 54 + pub fn perspective( 55 + comptime T: type, 56 + fovy: Angle(T), 57 + aspect: T, 58 + near: T, 59 + far: T, 60 + ) Matrix(T, 4, 4) { 61 + switch (@typeInfo(T)) { 62 + .float => {}, 63 + else => @panic("`T` should be float"), 64 + } 65 + 66 + const sinfov = math.sin(0.5 * fovy.radians()); 67 + const cosfov = math.cos(0.5 * fovy.radians()); 68 + 69 + const h = cosfov / sinfov; 70 + const w = h / aspect; 71 + const r = near - far; 72 + return mat(T, 4, 4, .{ 73 + .{ w, 0.0, 0.0, 0.0 }, 74 + .{ 0.0, h, 0.0, 0.0 }, 75 + .{ 0.0, 0.0, (near + far) / r, -1.0 }, 76 + .{ 0.0, 0.0, 2.0 * near * far / r, 0.0 }, 77 + }); 78 + } 79 + 80 + /// Create an orthographic projection matrix 81 + pub fn orthographic( 82 + comptime T: type, 83 + w: T, 84 + h: T, 85 + near: f32, 86 + far: f32, 87 + ) Matrix(T, 4, 4) { 88 + const r = near - far; 89 + return mat(T, 4, 4, .{ 90 + .{ 2 / w, 0.0, 0.0, 0.0 }, 91 + .{ 0.0, 2 / h, 0.0, 0.0 }, 92 + .{ 0.0, 0.0, 2 / r, 0.0 }, 93 + .{ 0.0, 0.0, (near + far) / r, 1.0 }, 94 + }); 95 + } 96 + 97 + test "perspective" { 98 + const persp = perspective( 99 + f32, 100 + angleDeg(@as(f32, 45.0)), 101 + 1.777, 102 + 0.1, 103 + 100.0, 104 + ); 105 + 106 + for (persp.inner) |r| 107 + std.debug.print("{any}\n", .{r}); 108 + std.debug.print("\n", .{}); 109 + } 110 + 111 + test "orthographic" { 112 + const ortho = orthographic(f32, 43, 54, 0.1, 100.0); 113 + for (ortho.inner) |r| 114 + std.debug.print("{any}\n", .{r}); 115 + std.debug.print("\n", .{}); 116 + }
+3
src/root.zig
··· 1 1 const std = @import("std"); 2 2 3 3 pub const la = @import("./la.zig"); 4 + pub const math = @import("./math.zig"); 5 + 4 6 pub const packet = @import("./packet.zig"); 5 7 6 8 const sparse_set = @import("./SparseSet.zig"); ··· 20 22 21 23 test { 22 24 _ = la; 25 + _ = math; 23 26 _ = packet; 24 27 _ = sparse_set; 25 28 _ = StringBuilder;