const std = @import("std"); pub fn Vec3(comptime T: type) type { return struct { x: T, y: T, z: T }; } pub fn vec3Add(comptime T: type, a: Vec3(T), b: Vec3(T)) Vec3(T) { return .{ .x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z, }; } pub fn vec3Sub(comptime T: type, a: Vec3(T), b: Vec3(T)) Vec3(T) { return .{ .x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z, }; } pub fn vec3Dot(comptime T: type, a: Vec3(T), b: Vec3(T)) T { return a.x * b.x + a.y * b.y + a.z * b.z; } pub fn vec3Cross(comptime T: type, a: Vec3(T), b: Vec3(T)) Vec3(T) { const x = a.y * b.z - a.z * b.y; const y = a.z * b.x - a.x * b.z; const z = a.x * b.y - a.y * b.x; return .{ .x = x, .y = y, .z = z }; } pub fn Mat3(comptime T: type) type { return struct { row1: Vec3(T), row2: Vec3(T), row3: Vec3(T), }; } pub fn mat3Add(comptime T: type, a: Mat3(T), b: Mat3(T)) Mat3(T) { return .{ .row1 = vec3Add(T, a.row1, b.row1), .row2 = vec3Add(T, a.row2, b.row2), .row3 = vec3Add(T, a.row3, b.row3), }; } pub fn mat3Sub(comptime T: type, a: Mat3(T), b: Mat3(T)) Mat3(T) { return .{ .row1 = vec3Sub(T, a.row1, b.row1), .row2 = vec3Sub(T, a.row2, b.row2), .row3 = vec3Sub(T, a.row3, b.row3), }; } pub fn mat3Mul(comptime T: type, a: Mat3(T), b: Mat3(T)) Mat3(T) { const c_row1: Vec3(T) = .{ .x = a.row1.x * b.row1.x + a.row1.y * b.row2.x + a.row1.z * b.row3.x, .y = a.row1.x * b.row1.y + a.row1.y * b.row2.y + a.row1.z * b.row3.y, .z = a.row1.x * b.row1.z + a.row1.y * b.row2.z + a.row1.z * b.row3.z, }; const c_row2: Vec3(T) = .{ .x = a.row2.x * b.row1.x + a.row2.y * b.row2.x + a.row2.z * b.row3.x, .y = a.row2.x * b.row1.y + a.row2.y * b.row2.y + a.row2.z * b.row3.y, .z = a.row2.x * b.row1.z + a.row2.y * b.row2.z + a.row2.z * b.row3.z, }; const c_row3: Vec3(T) = .{ .x = a.row3.x * b.row1.x + a.row3.y * b.row2.x + a.row3.z * b.row3.x, .y = a.row3.x * b.row1.y + a.row3.y * b.row2.y + a.row3.z * b.row3.y, .z = a.row3.x * b.row1.z + a.row3.y * b.row2.z + a.row3.z * b.row3.z, }; return .{ .row1 = c_row1, .row2 = c_row2, .row3 = c_row3 }; } pub fn vec3MulMat3(comptime T: type, a: Vec3(T), b: Mat3(T)) Vec3(T) { return .{ .x = a.x * b.row1.x + a.y * b.row2.x + a.z * b.row3.x, .y = a.x * b.row1.y + a.y * b.row2.y + a.z * b.row3.y, .z = a.x * b.row1.z + a.y * b.row2.z + a.z * b.row3.z, }; } test "vec3Add adds properly" { const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 }; const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 }; const c = vec3Add(i8, a, b); try std.testing.expect(c.x == 4); try std.testing.expect(c.y == 3); try std.testing.expect(c.z == 3); } test "vec3Sub subs properly" { const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 }; const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 }; const c = vec3Sub(i8, a, b); try std.testing.expect(c.x == -2); try std.testing.expect(c.y == 1); try std.testing.expect(c.z == 3); } test "vec3Dot dots properly" { const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 }; const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 }; try std.testing.expect(vec3Dot(i8, a, b) == 5); } test "vec3Cross crosses properly" { const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 }; const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 }; const c = vec3Cross(i8, a, b); try std.testing.expect(c.x == -3); try std.testing.expect(c.y == 9); try std.testing.expect(c.z == -5); } test "Mat3 add works" { const a: Mat3(i8) = .{ .row1 = .{ .x = 1, .y = 2, .z = 3 }, .row2 = .{ .x = 0, .y = 1, .z = 5 }, .row3 = .{ .x = 0, .y = 0, .z = 9 }, }; const b: Mat3(i8) = .{ .row1 = .{ .x = 0, .y = 1, .z = 0 }, .row2 = .{ .x = 0, .y = 1, .z = 1 }, .row3 = .{ .x = 0, .y = 0, .z = 1 }, }; const c = mat3Add(i8, a, b); try std.testing.expect(c.row1.x == 1); try std.testing.expect(c.row1.y == 3); try std.testing.expect(c.row1.z == 3); try std.testing.expect(c.row2.x == 0); try std.testing.expect(c.row2.y == 2); try std.testing.expect(c.row2.z == 6); try std.testing.expect(c.row3.x == 0); try std.testing.expect(c.row3.y == 0); try std.testing.expect(c.row3.z == 10); } test "Mat3 sub works" { const a: Mat3(i8) = .{ .row1 = .{ .x = 1, .y = 2, .z = 3 }, .row2 = .{ .x = 0, .y = 1, .z = 5 }, .row3 = .{ .x = 0, .y = 0, .z = 9 }, }; const b: Mat3(i8) = .{ .row1 = .{ .x = 0, .y = 1, .z = 0 }, .row2 = .{ .x = 0, .y = 1, .z = 1 }, .row3 = .{ .x = 0, .y = 0, .z = 1 }, }; const c = mat3Sub(i8, a, b); try std.testing.expect(c.row1.x == 1); try std.testing.expect(c.row1.y == 1); try std.testing.expect(c.row1.z == 3); try std.testing.expect(c.row2.x == 0); try std.testing.expect(c.row2.y == 0); try std.testing.expect(c.row2.z == 4); try std.testing.expect(c.row3.x == 0); try std.testing.expect(c.row3.y == 0); try std.testing.expect(c.row3.z == 8); } test "Mat3 mul works" { const a: Mat3(i8) = .{ .row1 = .{ .x = 1, .y = 2, .z = 3 }, .row2 = .{ .x = 0, .y = 1, .z = 5 }, .row3 = .{ .x = 0, .y = 0, .z = 9 }, }; const b: Mat3(i8) = .{ .row1 = .{ .x = 0, .y = 1, .z = 0 }, .row2 = .{ .x = 0, .y = 1, .z = 1 }, .row3 = .{ .x = 0, .y = 0, .z = 1 }, }; const c = mat3Mul(i8, a, b); try std.testing.expect(c.row1.x == 0); try std.testing.expect(c.row1.y == 3); try std.testing.expect(c.row1.z == 5); try std.testing.expect(c.row2.x == 0); try std.testing.expect(c.row2.y == 1); try std.testing.expect(c.row2.z == 6); try std.testing.expect(c.row3.x == 0); try std.testing.expect(c.row3.y == 0); try std.testing.expect(c.row3.z == 9); } test "vec3 mul mat3 works" { const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 }; const b: Mat3(i8) = .{ .row1 = .{ .x = 0, .y = 1, .z = 0 }, .row2 = .{ .x = 0, .y = 1, .z = 1 }, .row3 = .{ .x = 0, .y = 0, .z = 1 }, }; const c = vec3MulMat3(i8, a, b); try std.testing.expect(c.x == 0); try std.testing.expect(c.y == 3); try std.testing.expect(c.z == 5); }