const std = @import("std"); const Vector2 = @import("Vector2.zig").Vector2; const Vector3 = @import("Vector3.zig").Vector3; pub const Vector4 = extern struct { vector: Vector, pub const Vector = @Vector(4, f32); pub const Mask = enum(i32) { x = 0, y = 1, z = 2, w = 3 }; pub const zero = Vector4.init(0, 0, 0, 0); pub const one = Vector4.init(1, 1, 1, 1); pub const unit_x = Vector4.init(1, 0, 0, 0); pub const unit_y = Vector4.init(0, 1, 0, 0); pub const unit_z = Vector4.init(0, 0, 1, 0); pub const unit_w = Vector4.init(0, 0, 0, 1); // --- INIT --- pub inline fn init(x: f32, y: f32, z: f32, w: f32) Vector4 { return .{ .vector = .{ x, y, z, w } }; } pub inline fn initArray(array: [4]f32) Vector4 { return .{ .vector = array }; } // --- CONVERSION --- pub inline fn asArray(self: Vector4) [4]f32 { return self.vector; } pub inline fn asArrayNorm(self: Vector4, comptime T: type) [4]T { const scale_vector: Vector = @splat(std.math.maxInt(T)); return @as(@Vector(4, T), @intFromFloat(@round(self.vector * scale_vector))); } pub inline fn asVector2(self: Vector4) Vector2 { return .{ .vector = @shuffle(f32, self.vector, undefined, [_]i32{ 0, 1 }) }; } pub inline fn asVector3(self: Vector4) Vector3 { return .{ .vector = @shuffle(f32, self.vector, undefined, [_]i32{ 0, 1, 2 }) }; } // --- ACCESSORS --- pub inline fn getX(self: Vector4) f32 { return self.vector[0]; } pub inline fn getY(self: Vector4) f32 { return self.vector[1]; } pub inline fn getZ(self: Vector4) f32 { return self.vector[2]; } pub inline fn getW(self: Vector4) f32 { return self.vector[3]; } pub inline fn setX(self: Vector4, x: f32) Vector4 { const x_vector: Vector = @splat(x); return .{ .vector = @shuffle(f32, self.vector, x_vector, [_]i32{ ~@as(i32, 0), 1, 2, 3 }) }; } pub inline fn setY(self: Vector4, y: f32) Vector4 { const y_vector: Vector = @splat(y); return .{ .vector = @shuffle(f32, self.vector, y_vector, [_]i32{ 0, ~@as(i32, 1), 2, 3 }) }; } pub inline fn setZ(self: Vector4, z: f32) Vector4 { const z_vector: Vector = @splat(z); return .{ .vector = @shuffle(f32, self.vector, z_vector, [_]i32{ 0, 1, ~@as(i32, 2), 3 }) }; } pub inline fn setW(self: Vector4, w: f32) Vector4 { const w_vector: Vector = @splat(w); return .{ .vector = @shuffle(f32, self.vector, w_vector, [_]i32{ 0, 1, 2, ~@as(i32, 3) }) }; } // --- COMPONENT-WISE --- pub inline fn add(self: Vector4, other: Vector4) Vector4 { return .{ .vector = self.vector + other.vector }; } pub inline fn sub(self: Vector4, other: Vector4) Vector4 { return .{ .vector = self.vector - other.vector }; } pub inline fn mul(self: Vector4, other: Vector4) Vector4 { return .{ .vector = self.vector * other.vector }; } pub inline fn div(self: Vector4, other: Vector4) Vector4 { return .{ .vector = self.vector / other.vector }; } pub inline fn negate(self: Vector4) Vector4 { return .{ .vector = -self.vector }; } pub inline fn mulScalar(self: Vector4, scalar: f32) Vector4 { const scalar_vector: Vector = @splat(scalar); return .{ .vector = self.vector * scalar_vector }; } pub inline fn divScalar(self: Vector4, scalar: f32) Vector4 { const scalar_vector: Vector = @splat(scalar); return .{ .vector = self.vector / scalar_vector }; } // --- SWIZZLE --- pub inline fn swizzle2(self: Vector4, comptime mask: [2]Mask) Vector2 { return .{ .vector = @shuffle(f32, self.vector, undefined, @as([2]i32, @bitCast(mask))) }; } pub inline fn swizzle3(self: Vector4, comptime mask: [3]Mask) Vector3 { return .{ .vector = @shuffle(f32, self.vector, undefined, @as([3]i32, @bitCast(mask))) }; } pub inline fn swizzle4(self: Vector4, comptime mask: [4]Mask) Vector4 { return .{ .vector = @shuffle(f32, self.vector, undefined, @as([4]i32, @bitCast(mask))) }; } // --- OTHER --- pub inline fn len(self: Vector4) f32 { return @sqrt(@reduce(.Add, self.vector * self.vector)); } pub inline fn lenSquared(self: Vector4) f32 { return @reduce(.Add, self.vector * self.vector); } pub inline fn normalize(self: Vector4) Vector4 { const len_vector: Vector = @splat(@sqrt(@reduce(.Add, self.vector * self.vector))); return .{ .vector = self.vector / len_vector }; } pub inline fn dot(self: Vector4, other: Vector4) f32 { return @reduce(.Add, self.vector * other.vector); } pub inline fn lerp(self: Vector4, other: Vector4, t: f32) Vector4 { const s = 1.0 - t; const t_vector: Vector = @splat(t); const s_vector: Vector = @splat(s); return .{ .vector = self * t_vector + other * s_vector }; } };