const std = @import("std"); pub fn Matrix(comptime n: usize, comptime Element: type) type { return [n]@Vector(n, Element); } pub const ProjectionMatrix = Matrix(4, f32); pub const Rect = struct { left: f32, top: f32, right: f32, bottom: f32, }; pub fn cross(v1: anytype, v2: anytype) @typeInfo(@TypeOf(v1, v2)).Vector.child { const multipled = v1 * v2; const vector_info = @typeInfo(@TypeOf(v1)).Vector; var result = multipled[0]; comptime var index = @as(usize, 1); inline while (index < vector_info.len) : (index += 1) { result -= multipled[index]; } return result; } pub fn distance(v1: anytype, v2: anytype) @typeInfo(@TypeOf(v1, v2)).Vector.child { return length(v1 - v2); } pub fn dot(v1: anytype, v2: anytype) @typeInfo(@TypeOf(v1, v2)).Vector.child { const multipled = v1 * v2; const vector_info = @typeInfo(@TypeOf(v1)).Vector; var result = multipled[0]; comptime var index = @as(usize, 1); inline while (index < vector_info.len) : (index += 1) { result += multipled[index]; } return result; } pub fn length(v: anytype) @typeInfo(@TypeOf(v)).Vector.child { return @sqrt(length_squared(v)); } pub fn length_squared(v: anytype) @typeInfo(@TypeOf(v)).Vector.child { return dot(v, v); } pub fn normal(v: anytype) @TypeOf(v) { const ls = length_squared(v); const Vector = @TypeOf(v); if (ls > std.math.floatEps(@typeInfo(Vector).Vector.child)) { return v / @as(Vector, @splat(@sqrt(ls))); } return v; } pub fn orthographic_projection(near: f32, far: f32, viewport: Rect) Matrix(4, f32) { const width = viewport.right - viewport.left; const height = viewport.bottom - viewport.top; return .{ .{2 / width, 0, 0, 0}, .{0, 2 / height, 0, 0}, .{0, 0, 1 / (far - near), 0}, .{-((viewport.left + viewport.right) / width), -((viewport.top + viewport.bottom) / height), near / (near - far), 1}, }; }