diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..83ddddd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "castle"] + path = castle + url = https://gitea.renati.me/renati/castle.git diff --git a/build.zig b/build.zig index c6388a1..a3bf0b5 100644 --- a/build.zig +++ b/build.zig @@ -7,10 +7,12 @@ pub fn build(b: *std.Build) !void { const optimize = b.standardOptimizeOption(.{}); const llvm = b.option(bool, "llvm", "Use LLVM and LLD") orelse false; + const vecmath_dep = b.dependency("vecmath", .{}); const vulkan_dep = b.dependency("vulkan_zig", .{ .registry = b.path("vendor/vk.xml") }); const zglfw_dep = b.dependency("zglfw", .{ .import_vulkan = true }); const zstbi_dep = b.dependency("zstbi", .{}); + const vecmath_mod = vecmath_dep.module("vecmath"); const vulkan_mod = vulkan_dep.module("vulkan-zig"); const zglfw_mod = zglfw_dep.module("root"); const zstbi_mod = zstbi_dep.module("root"); @@ -25,6 +27,7 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }); + exe_mod.addImport("vecmath", vecmath_mod); exe_mod.addImport("vulkan", vulkan_mod); exe_mod.addImport("zglfw", zglfw_mod); exe_mod.addImport("zstbi", zstbi_mod); diff --git a/build.zig.zon b/build.zig.zon index fb6dd56..3ba66cf 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -5,6 +5,9 @@ .minimum_zig_version = "0.15.2", .dependencies = .{ + .vecmath = .{ + .path = "castle/packages/vecmath", + }, .vulkan_zig = .{ .url = "git+https://github.com/Snektron/vulkan-zig.git#1446b0b994c2362264cc24513d7c7ec31b469c50", .hash = "vulkan-0.0.0-r7Ytx_VDAwAiMl0YSu2UOkVMIGJN7CeIQaxJR-hUSfD6", diff --git a/castle b/castle new file mode 160000 index 0000000..7e81035 --- /dev/null +++ b/castle @@ -0,0 +1 @@ +Subproject commit 7e8103565d2d0eaeac8510b62dba59b6363c81cc diff --git a/src/Chunks.zig b/src/Chunks.zig index 2c5f788..339fd7a 100644 --- a/src/Chunks.zig +++ b/src/Chunks.zig @@ -4,18 +4,17 @@ const std = @import("std"); const c = @import("const.zig"); const math = @import("math.zig"); const vk = @import("vulkan"); +const vm = @import("vecmath"); const Blocks = @import("assets/Blocks.zig"); const Chunk = @import("assets/Chunk.zig"); const Engine = @import("engine/Engine.zig"); const Iterator2 = math.Iterator2; -const Vector2Int = math.Vector2Int; -const Vector3Int = math.Vector3Int; chunks: std.AutoHashMapUnmanaged([3]i16, Chunk), const RaycastHit = struct { - normal_frac: Vector3Int, + normal_frac: vm.Vector3Int, projected_distance_sv: i32, }; @@ -28,40 +27,41 @@ pub fn deinit(self: *Chunks, engine: *Engine, descriptor_pool: vk.DescriptorPool self.* = undefined; } -pub fn getVoxelAt(self: *const Chunks, vx: Vector3Int) ?Blocks.Id { - const min_ck = Vector3Int.initScalar(std.math.minInt(i16)); - const max_ck = Vector3Int.initScalar(std.math.maxInt(i16)); +pub fn getVoxelAt(self: *const Chunks, vx: vm.Vector3Int) ?Blocks.Id { + const min_ck = vm.Vector3Int.initScalar(std.math.minInt(i16)); + const max_ck = vm.Vector3Int.initScalar(std.math.maxInt(i16)); const ck = vx.divScalar(c.vx_per_ck); - if (@reduce(.Or, (ck.vector < min_ck.vector) | (ck.vector > max_ck.vector))) { + if ((ck.x < min_ck.x) | (ck.y < min_ck.y) | (ck.z < min_ck.z) | (ck.x > max_ck.x) | (ck.y > max_ck.y) | (ck.z > max_ck.z)) { + @branchHint(.unlikely); return null; } if (self.chunks.get(.{ - @intCast(ck.getX()), - @intCast(ck.getY()), - @intCast(ck.getZ()), + @intCast(ck.x), + @intCast(ck.y), + @intCast(ck.z), })) |chunk| { const ckvx = vx.modScalar(c.vx_per_ck); - return chunk.blocks[@intCast(ckvx.getZ())][@intCast(ckvx.getY())][@intCast(ckvx.getX())]; + return chunk.blocks[@intCast(ckvx.z)][@intCast(ckvx.y)][@intCast(ckvx.x)]; } else { return .air; } } -pub fn isSolid(self: *const Chunks, vx: Vector3Int) bool { +pub fn isSolid(self: *const Chunks, vx: vm.Vector3Int) bool { const maybe_id = getVoxelAt(self, vx); // NOTE `null` is considered solid, as it's out of bounds. return maybe_id != .air; } -pub fn sweepCastDown(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int, distance_sv: i32) ?RaycastHit { - const min_x_vx = c.subvoxelsToVoxels(.border_up, min_sv.getX()); - const min_y_vx = c.subvoxelsToVoxels(.border_up, min_sv.getY()); - const max_x_vx = c.subvoxelsToVoxels(.border_down, max_sv.getX()); - const max_y_vx = c.subvoxelsToVoxels(.border_down, max_sv.getY()); +pub fn sweepCastDown(self: *const Chunks, min_sv: vm.Vector3Int, max_sv: vm.Vector3Int, distance_sv: i32) ?RaycastHit { + const min_x_vx = c.subvoxelsToVoxels(.border_up, min_sv.x); + const min_y_vx = c.subvoxelsToVoxels(.border_up, min_sv.y); + const max_x_vx = c.subvoxelsToVoxels(.border_down, max_sv.x); + const max_y_vx = c.subvoxelsToVoxels(.border_down, max_sv.y); - const start_z_vx = c.subvoxelsToVoxels(.border_up, min_sv.getZ()) - 1; - const end_z_vx = c.subvoxelsToVoxels(.border_up, min_sv.getZ() - distance_sv); + const start_z_vx = c.subvoxelsToVoxels(.border_up, min_sv.z) - 1; + const end_z_vx = c.subvoxelsToVoxels(.border_up, min_sv.z - distance_sv); var z_vx: i32 = start_z_vx; while (z_vx >= end_z_vx) : (z_vx -= 1) { @@ -75,8 +75,8 @@ pub fn sweepCastDown(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int if (!self.isSolid(.init(x_vx, y_vx, z_vx))) continue; return .{ - .projected_distance_sv = distance_sv - (min_sv.getZ() - z_sv), - .normal_frac = .unit_z_frac, + .projected_distance_sv = distance_sv - (min_sv.z - z_sv), + .normal_frac = .init(0, 0, std.math.maxInt(i32)), }; } } @@ -84,14 +84,14 @@ pub fn sweepCastDown(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int return null; } -pub fn sweepCastUp(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int, distance_sv: i32) ?RaycastHit { - const min_x_vx = c.subvoxelsToVoxels(.border_up, min_sv.getX()); - const min_y_vx = c.subvoxelsToVoxels(.border_up, min_sv.getY()); - const max_x_vx = c.subvoxelsToVoxels(.border_down, max_sv.getX()); - const max_y_vx = c.subvoxelsToVoxels(.border_down, max_sv.getY()); +pub fn sweepCastUp(self: *const Chunks, min_sv: vm.Vector3Int, max_sv: vm.Vector3Int, distance_sv: i32) ?RaycastHit { + const min_x_vx = c.subvoxelsToVoxels(.border_up, min_sv.x); + const min_y_vx = c.subvoxelsToVoxels(.border_up, min_sv.y); + const max_x_vx = c.subvoxelsToVoxels(.border_down, max_sv.x); + const max_y_vx = c.subvoxelsToVoxels(.border_down, max_sv.y); - const start_z_vx = c.subvoxelsToVoxels(.border_down, max_sv.getZ()) + 1; - const end_z_vx = c.subvoxelsToVoxels(.border_down, max_sv.getZ() + distance_sv); + const start_z_vx = c.subvoxelsToVoxels(.border_down, max_sv.z) + 1; + const end_z_vx = c.subvoxelsToVoxels(.border_down, max_sv.z + distance_sv); var z_vx: i32 = start_z_vx; while (z_vx <= end_z_vx) : (z_vx += 1) { @@ -105,8 +105,8 @@ pub fn sweepCastUp(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int, if (!self.isSolid(.init(x_vx, y_vx, z_vx))) continue; return .{ - .projected_distance_sv = distance_sv - (z_sv - max_sv.getZ()), - .normal_frac = .unit_nz_frac, + .projected_distance_sv = distance_sv - (z_sv - max_sv.z), + .normal_frac = .init(0, 0, -std.math.maxInt(i32)), }; } } @@ -114,30 +114,30 @@ pub fn sweepCastUp(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int, return null; } -pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int, ray_sv: Vector2Int) ?RaycastHit { - const min_z_vx = c.subvoxelsToVoxels(.border_up, min_sv.getZ()); - const max_z_vx = c.subvoxelsToVoxels(.border_down, max_sv.getZ()); +pub fn sweepCastHorizontal(self: *const Chunks, min_sv: vm.Vector3Int, max_sv: vm.Vector3Int, ray_sv: vm.Vector2Int) ?RaycastHit { + const min_z_vx = c.subvoxelsToVoxels(.border_up, min_sv.z); + const max_z_vx = c.subvoxelsToVoxels(.border_down, max_sv.z); var hit: ?RaycastHit = null; var hit_distance_squared = std.math.inf(f32); - const fdydx: f32 = @as(f32, @floatFromInt(ray_sv.getY())) / @as(f32, @floatFromInt(ray_sv.getX())); - const fdxdy: f32 = @as(f32, @floatFromInt(ray_sv.getX())) / @as(f32, @floatFromInt(ray_sv.getY())); + const fdydx: f32 = @as(f32, @floatFromInt(ray_sv.y)) / @as(f32, @floatFromInt(ray_sv.x)); + const fdxdy: f32 = @as(f32, @floatFromInt(ray_sv.x)) / @as(f32, @floatFromInt(ray_sv.y)); // Positive X - if (ray_sv.getX() > 0) { - const x0_sv = max_sv.getX(); - const y0_sv = min_sv.getY(); - const y1_sv = max_sv.getY(); + if (ray_sv.x > 0) { + const x0_sv = max_sv.x; + const y0_sv = min_sv.y; + const y1_sv = max_sv.y; const start_x_vx = c.subvoxelsToVoxels(.border_down, x0_sv) + 1; - const end_x_vx = c.subvoxelsToVoxels(.border_down, x0_sv + ray_sv.getX()); + const end_x_vx = c.subvoxelsToVoxels(.border_down, x0_sv + ray_sv.x); var x_vx: i32 = start_x_vx; px: while (x_vx <= end_x_vx) : (x_vx += 1) { const x_sv = c.voxelsToSubvoxels(x_vx); - const min_y_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y0_sv); - const max_y_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y1_sv); + const min_y_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(x_sv - x0_sv, ray_sv.y, ray_sv.x) + y0_sv); + const max_y_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(x_sv - x0_sv, ray_sv.y, ray_sv.x) + y1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_y_vx, min_z_vx }, .max = .{ max_y_vx, max_z_vx }, @@ -151,8 +151,8 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect const fdy: f32 = fdx * fdydx; hit = .{ - .projected_distance_sv = ray_sv.getX() - dx, - .normal_frac = .unit_nx_frac, + .projected_distance_sv = ray_sv.x - dx, + .normal_frac = .init(-std.math.maxInt(i32), 0, 0), }; hit_distance_squared = fdx * fdx + fdy * fdy; // std.debug.print("HIT +X ({X}->{X}) at ({X}, {X}, {X}) [VX] | min_sv={X} max_sv={X} ray_sv={X} | proj_dist={X} \n", .{ start_x_vx, end_x_vx, x_vx, y_vx, z_vx, min_sv.vector, max_sv.vector, ray_sv.vector, hit.?.projected_distance_sv }); @@ -163,19 +163,19 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect } // Negative X - if (ray_sv.getX() < 0) { - const x0_sv = min_sv.getX(); - const y0_sv = min_sv.getY(); - const y1_sv = max_sv.getY(); + if (ray_sv.x < 0) { + const x0_sv = min_sv.x; + const y0_sv = min_sv.y; + const y1_sv = max_sv.y; const start_x_vx = c.subvoxelsToVoxels(.border_up, x0_sv) - 1; - const end_x_vx = c.subvoxelsToVoxels(.border_up, x0_sv + ray_sv.getX()); + const end_x_vx = c.subvoxelsToVoxels(.border_up, x0_sv + ray_sv.x); var x_vx: i32 = start_x_vx; nx: while (x_vx >= end_x_vx) : (x_vx -= 1) { const x_sv = c.voxelsToSubvoxels(x_vx + 1); - const min_y_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y0_sv); - const max_y_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y1_sv); + const min_y_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(x_sv - x0_sv, ray_sv.y, ray_sv.x) + y0_sv); + const max_y_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(x_sv - x0_sv, ray_sv.y, ray_sv.x) + y1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_y_vx, min_z_vx }, .max = .{ max_y_vx, max_z_vx }, @@ -189,8 +189,8 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect const fdy: f32 = fdx * fdydx; hit = .{ - .projected_distance_sv = -(ray_sv.getX() - dx), - .normal_frac = .unit_x_frac, + .projected_distance_sv = -(ray_sv.x - dx), + .normal_frac = .init(std.math.maxInt(i32), 0, 0), }; hit_distance_squared = fdx * fdx + fdy * fdy; // std.debug.print("HIT -X ({X}->{X}) at ({X}, {X}, {X}) [VX] | min_sv={X} max_sv={X} ray_sv={X} | proj_dist={X} \n", .{ start_x_vx, end_x_vx, x_vx, y_vx, z_vx, min_sv.vector, max_sv.vector, ray_sv.vector, hit.?.projected_distance_sv }); @@ -201,19 +201,19 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect } // Positive Y - if (ray_sv.getY() > 0) { - const y0_sv = max_sv.getY(); - const x0_sv = min_sv.getX(); - const x1_sv = max_sv.getX(); + if (ray_sv.y > 0) { + const y0_sv = max_sv.y; + const x0_sv = min_sv.x; + const x1_sv = max_sv.x; const start_y_vx = c.subvoxelsToVoxels(.border_down, y0_sv) + 1; - const end_y_vx = c.subvoxelsToVoxels(.border_down, y0_sv + ray_sv.getY()); + const end_y_vx = c.subvoxelsToVoxels(.border_down, y0_sv + ray_sv.y); var y_vx = start_y_vx; py: while (y_vx <= end_y_vx) : (y_vx += 1) { const y_sv = c.voxelsToSubvoxels(y_vx); - const min_x_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x0_sv); - const max_x_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x1_sv); + const min_x_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(y_sv - y0_sv, ray_sv.x, ray_sv.y) + x0_sv); + const max_x_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(y_sv - y0_sv, ray_sv.x, ray_sv.y) + x1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_x_vx, min_z_vx }, .max = .{ max_x_vx, max_z_vx }, @@ -229,8 +229,8 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect const this_hit_distance_squared = fdx * fdx + fdy * fdy; if (this_hit_distance_squared < hit_distance_squared) { hit = .{ - .projected_distance_sv = ray_sv.getY() - dy, - .normal_frac = .unit_ny_frac, + .projected_distance_sv = ray_sv.y - dy, + .normal_frac = .init(0, -std.math.maxInt(i32), 0), }; hit_distance_squared = this_hit_distance_squared; // std.debug.print("HIT +Y ({X}->{X}) at ({X}, {X}, {X}) [VX] | min_sv={X} max_sv={X} ray_sv={X} | proj_dist={X} \n", .{ start_y_vx, end_y_vx, x_vx, y_vx, z_vx, min_sv.vector, max_sv.vector, ray_sv.vector, hit.?.projected_distance_sv }); @@ -242,19 +242,19 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect } // Negative Y - if (ray_sv.getY() < 0.0) { - const y0_sv = min_sv.getY(); - const x0_sv = min_sv.getX(); - const x1_sv = max_sv.getX(); + if (ray_sv.y < 0.0) { + const y0_sv = min_sv.y; + const x0_sv = min_sv.x; + const x1_sv = max_sv.x; const start_y_vx = c.subvoxelsToVoxels(.border_up, y0_sv) - 1; - const end_y_vx = c.subvoxelsToVoxels(.border_up, y0_sv + ray_sv.getY()); + const end_y_vx = c.subvoxelsToVoxels(.border_up, y0_sv + ray_sv.y); var y_vx = start_y_vx; ny: while (y_vx >= end_y_vx) : (y_vx -= 1) { const y_sv = c.voxelsToSubvoxels(y_vx + 1); - const min_x_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x0_sv); - const max_x_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x1_sv); + const min_x_vx = c.subvoxelsToVoxels(.border_up, math.wideMulDivFloor(y_sv - y0_sv, ray_sv.x, ray_sv.y) + x0_sv); + const max_x_vx = c.subvoxelsToVoxels(.border_down, math.wideMulDivCeil(y_sv - y0_sv, ray_sv.x, ray_sv.y) + x1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_x_vx, min_z_vx }, .max = .{ max_x_vx, max_z_vx }, @@ -270,8 +270,8 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect const this_hit_distance_squared = fdx * fdx + fdy * fdy; if (this_hit_distance_squared < hit_distance_squared) { hit = .{ - .projected_distance_sv = -(ray_sv.getY() - dy), - .normal_frac = .unit_y_frac, + .projected_distance_sv = -(ray_sv.y - dy), + .normal_frac = .init(0, std.math.maxInt(i32), 0), }; hit_distance_squared = this_hit_distance_squared; // std.debug.print("HIT -Y ({X}->{X}) at ({X}, {X}, {X}) [VX] | min_sv={X} max_sv={X} ray_sv={X} | proj_dist={X} \n", .{ start_y_vx, end_y_vx, x_vx, y_vx, z_vx, min_sv.vector, max_sv.vector, ray_sv.vector, hit.?.projected_distance_sv }); @@ -285,64 +285,64 @@ pub fn sweepCastHorizontal(self: *const Chunks, min_sv: Vector3Int, max_sv: Vect return hit; } -pub fn raycast(self: *const Chunks, origin_sv: Vector3Int, ray_sv: Vector3Int) ?RaycastHit { +pub fn raycast(self: *const Chunks, origin_sv: vm.Vector3Int, ray_sv: vm.Vector3Int) ?RaycastHit { const end_sv = origin_sv.add(ray_sv); std.debug.print("Raycast from ({d}:{X}, {d}:{X}, {d}:{X}) to ({d}:{X}, {d}:{X}, {d}:{X})\n", .{ - c.subvoxelsToVoxels(.border_up, origin_sv.getX()), - c.subvoxelsToVoxelSubvoxels(origin_sv.getX()), - c.subvoxelsToVoxels(.border_up, origin_sv.getY()), - c.subvoxelsToVoxelSubvoxels(origin_sv.getY()), - c.subvoxelsToVoxels(.border_up, origin_sv.getZ()), - c.subvoxelsToVoxelSubvoxels(origin_sv.getZ()), - c.subvoxelsToVoxels(.border_up, end_sv.getX()), - c.subvoxelsToVoxelSubvoxels(end_sv.getX()), - c.subvoxelsToVoxels(.border_up, end_sv.getY()), - c.subvoxelsToVoxelSubvoxels(end_sv.getY()), - c.subvoxelsToVoxels(.border_up, end_sv.getZ()), - c.subvoxelsToVoxelSubvoxels(end_sv.getZ()), + c.subvoxelsToVoxels(.border_up, origin_sv.x), + c.subvoxelsToVoxelSubvoxels(origin_sv.x), + c.subvoxelsToVoxels(.border_up, origin_sv.y), + c.subvoxelsToVoxelSubvoxels(origin_sv.y), + c.subvoxelsToVoxels(.border_up, origin_sv.z), + c.subvoxelsToVoxelSubvoxels(origin_sv.z), + c.subvoxelsToVoxels(.border_up, end_sv.x), + c.subvoxelsToVoxelSubvoxels(end_sv.x), + c.subvoxelsToVoxels(.border_up, end_sv.y), + c.subvoxelsToVoxelSubvoxels(end_sv.y), + c.subvoxelsToVoxels(.border_up, end_sv.z), + c.subvoxelsToVoxelSubvoxels(end_sv.z), }); - const zero = Vector3Int.zero.vector; - const one = Vector3Int.one.vector; + const zero = vm.epi32(0); + const one = vm.epi32(1); - const ray_positive: Vector3Int = .{ .vector = @select(i32, ray_sv.vector > zero, one, zero) }; - const ray_negative: Vector3Int = .{ .vector = @select(i32, ray_sv.vector < zero, one, zero) }; - const ray_sign: Vector3Int = .sub(ray_positive, ray_negative); + const ray_positive: vm.Vector3Int = .{ .vector = @select(i32, ray_sv.vector > zero, one, zero) }; + const ray_negative: vm.Vector3Int = .{ .vector = @select(i32, ray_sv.vector < zero, one, zero) }; + const ray_sign: vm.Vector3Int = .sub(ray_positive, ray_negative); const start_vx = origin_sv.sub(ray_positive).divScalar(c.sv_per_vx).add(ray_sign); const end_vx = end_sv.sub(ray_positive).divScalar(c.sv_per_vx); const abs_ray_sv = ray_sv.abs(); std.debug.print("Start [VX]: ({d}, {d}, {d}) | End [VX]: ({d}, {d}, {d})\n", .{ - start_vx.getX(), - start_vx.getY(), - start_vx.getZ(), - end_vx.getX(), - end_vx.getY(), - end_vx.getZ(), + start_vx.x, + start_vx.y, + start_vx.z, + end_vx.x, + end_vx.y, + end_vx.z, }); var i_index: usize = undefined; var j_index: usize = undefined; var k_index: usize = undefined; - if (abs_ray_sv.getX() > abs_ray_sv.getY() and abs_ray_sv.getX() > abs_ray_sv.getZ()) { + if (abs_ray_sv.x > abs_ray_sv.y and abs_ray_sv.x > abs_ray_sv.z) { // Main axis: ±X i_index, j_index, k_index = .{ 0, 1, 2 }; std.debug.print("Order is (X, Y, Z)\n", .{}); - } else if (abs_ray_sv.getY() > abs_ray_sv.getZ()) { + } else if (abs_ray_sv.y > abs_ray_sv.z) { // Main axis: ±Y i_index, j_index, k_index = .{ 1, 2, 0 }; std.debug.print("Order is (Y, Z, X)\n", .{}); - } else if (abs_ray_sv.getZ() > 0) { + } else if (abs_ray_sv.z > 0) { // Main axis: ±Z i_index, j_index, k_index = .{ 2, 0, 1 }; std.debug.print("Order is (Z, X, Y)\n", .{}); } else { - std.debug.assert(abs_ray_sv.getX() == 0); - std.debug.assert(abs_ray_sv.getY() == 0); - std.debug.assert(abs_ray_sv.getZ() == 0); + std.debug.assert(abs_ray_sv.x == 0); + std.debug.assert(abs_ray_sv.y == 0); + std.debug.assert(abs_ray_sv.z == 0); return null; } diff --git a/src/Game.zig b/src/Game.zig index 73b43ca..5c9a049 100644 --- a/src/Game.zig +++ b/src/Game.zig @@ -6,6 +6,7 @@ const glfw = @import("zglfw"); const math = @import("math.zig"); const shaders = @import("shaders.zig"); const vk = @import("vulkan"); +const vm = @import("vecmath"); const worldgen = @import("worldgen.zig"); const Blocks = @import("assets/Blocks.zig"); @@ -15,17 +16,11 @@ const CommandBuffer = @import("engine/CommandBuffer.zig"); const Engine = @import("engine/Engine.zig"); const Iterator2 = math.Iterator2; const Materials = @import("assets/Materials.zig"); -const Matrix4x4 = math.Matrix4x4; const Player = @import("Player.zig"); -const Quaternion = math.Quaternion; const Skybox = @import("engine/Skybox.zig"); const StagingBuffer = @import("engine/StagingBuffer.zig"); const Swapchain = @import("engine/Swapchain.zig"); const Textures = @import("assets/Textures.zig"); -const Vector2 = math.Vector2; -const Vector2x8 = math.Vector2x8; -const Vector3 = math.Vector3; -const Vector3Int = math.Vector3Int; allocator: std.mem.Allocator, engine: *Engine, @@ -545,7 +540,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain while (it.next()) |chunk_coords2| { const chunk_coords3 = chunk_coords2 ++ [_]i16{0}; - const origin = Vector3.init( + const origin = vm.Vector3.init( @floatFromInt(chunk_coords3[0]), @floatFromInt(chunk_coords3[1]), @floatFromInt(chunk_coords3[2]), @@ -564,14 +559,14 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain var y: usize = 0; while (y < 16) : (y += 1) { - const fpos0 = Vector2x8.initScalars( + const fpos0 = vm.Vector2x8.init( .{ 0, 1, 2, 3, 4, 5, 6, 7 }, @splat(@floatFromInt(y)), - ).add(.initVector(origin.asVector2())); - const fpos1 = Vector2x8.initScalars( + ).add(.splat(origin.dropZ())); + const fpos1 = vm.Vector2x8.init( .{ 8, 9, 10, 11, 12, 13, 14, 15 }, @splat(@floatFromInt(y)), - ).add(.initVector(origin.asVector2())); + ).add(.splat(origin.dropZ())); const iheight0 = worldgen.heightIv(world_seed, fpos0); const iheight1 = worldgen.heightIv(world_seed, fpos1); @@ -596,7 +591,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain } } - const player_position_vx = Vector3Int.init(0, 0, worldgen.heightI(world_seed, .zero) + 1); + const player_position_vx = vm.Vector3Int.init(0, 0, worldgen.heightI(world_seed, .zero) + 1); const player_position_sv = player_position_vx .mulScalar(c.sv_per_vx) .add(.init(c.sv_per_vx / 2, c.sv_per_vx / 2, 0)); @@ -623,8 +618,8 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain const directional_lights_data: []const shaders.DirectionalLight = &.{ .{ - .directionWS = .{ 0, 0, -1 }, - .color = .{ 0.3, 0.3, 0.3 }, + .directionWS = .unit_nz, + .color = .init(0.3, 0.3, 0.3), }, }; try directional_lights.write(engine, .{ @@ -765,30 +760,33 @@ fn render(self: *Game) !void { const extent = self.swapchain.extent; - const framebuffer_size = Vector2.init( + const framebuffer_size = vm.Vector2.init( @floatFromInt(extent.width), @floatFromInt(extent.height), ); - const camera_position = self.player.position_sv - .asVector3() + const camera_position = vm.Vector3.init( + @floatFromInt(self.player.position_sv.x), + @floatFromInt(self.player.position_sv.y), + @floatFromInt(self.player.position_sv.z), + ) .divScalar(c.sv_per_vx) .add(.init(0, 0, Player.camera_height_vx)); - const camera_rotation = Quaternion.mulQuaternion( - .initRotationXY(self.player.yaw_rad), - .initRotationYZ(self.player.pitch_rad), + const camera_rotation = vm.Quaternion.mulQuaternion( + .initRotation(.XY, self.player.yaw_turns), + .initRotation(.YZ, self.player.pitch_turns), ); - const camera_aspect_ratio = framebuffer_size.getX() / framebuffer_size.getY(); + const camera_aspect_ratio = framebuffer_size.x / framebuffer_size.y; const camera_yscale = 1.0 / @tan(0.5 * self.player.vertical_fov_deg * std.math.rad_per_deg); const camera_xscale = camera_yscale / camera_aspect_ratio; - const matrix_ws_to_vs = Matrix4x4.mulMatrix( - Matrix4x4.initRotation(camera_rotation.conjugate()), - Matrix4x4.initTranslation(camera_position.negate()), + const matrix_ws_to_vs = vm.Matrix4x4.mulMatrixAffine( + .initRotation(camera_rotation.inverseUnit()), + .initTranslation(camera_position.negate()), ); // zig fmt: off - const matrix_vs_to_cs = Matrix4x4.init( + const matrix_vs_to_cs = vm.Matrix4x4.init( camera_xscale, 0, 0, 0, 0, 0, 0, 1, 0, -camera_yscale, 0, 0, @@ -796,12 +794,12 @@ fn render(self: *Game) !void { ); // zig fmt: on - const ambient_light = Vector3.init(0.01, 0.01, 0.01); + const ambient_light = vm.Vector3.init(0.01, 0.01, 0.01); const global_uniforms_data: shaders.GlobalUniforms = .{ - .matrixWStoVS = matrix_ws_to_vs.asArray(), - .matrixVStoCS = matrix_vs_to_cs.asArray(), - .ambientLight = ambient_light.asArray(), + .matrixWStoVS = matrix_ws_to_vs, + .matrixVStoCS = matrix_vs_to_cs, + .ambientLight = ambient_light, }; const staging_memory = try self.global_uniforms_staging_buffer.map(self.engine); diff --git a/src/Player.zig b/src/Player.zig index 1435748..1736001 100644 --- a/src/Player.zig +++ b/src/Player.zig @@ -4,15 +4,11 @@ const std = @import("std"); const c = @import("const.zig"); const glfw = @import("zglfw"); const math = @import("math.zig"); +const vm = @import("vecmath"); const Blocks = @import("assets/Blocks.zig"); const Chunks = @import("Chunks.zig"); const Iterator2 = math.Iterator2; -const Quaternion = math.Quaternion; -const Vector2 = math.Vector2; -const Vector3 = math.Vector3; -const Vector2Int = math.Vector2Int; -const Vector3Int = math.Vector3Int; const AxisState = enum { none, @@ -157,25 +153,25 @@ const Button = struct { const MovementState = union(enum) { ground: struct { - horizontal_velocity_sv: Vector2Int, + horizontal_velocity_sv: vm.Vector2Int, }, air: struct { - horizontal_velocity_sv: Vector2Int, + horizontal_velocity_sv: vm.Vector2Int, vertical_velocity_sv: i32, }, flight: void, }; -position_sv: Vector3Int, -pitch_rad: f32, -yaw_rad: f32, +position_sv: vm.Vector3Int, +pitch_turns: f32, +yaw_turns: f32, x_input: Axis = .init(.d, .a), y_input: Axis = .init(.w, .s), z_input: Axis = .init(.space, .left_shift), jump_input: Button = .init(.space), -mouse_sensitivity: f32 = 0.002, +mouse_sensitivity: f32 = 0.0003, vertical_fov_deg: f32 = 80, movement_state: MovementState, @@ -185,8 +181,8 @@ pub const camera_height_vx = 1.62; pub const horizontal_speed_sv = sv(11.0); pub const vertical_speed_sv = sv(7.49); -pub const min_pitch_rad = -0.5 * std.math.pi; -pub const max_pitch_rad = 0.5 * std.math.pi; +pub const min_pitch_turns = -0.25; +pub const max_pitch_turns = 0.25; pub const collision_half_width_sv = sv(0.4); pub const collision_height_sv = sv(1.8); @@ -203,11 +199,11 @@ pub const air_speed_limit_sv = sv(0.5612); pub const raycast_length_sv = sv(5.0); -pub fn init(position_sv: Vector3Int, pitch_rad: f32, yaw_rad: f32) Player { +pub fn init(position_sv: vm.Vector3Int, pitch_turns: f32, yaw_turns: f32) Player { return .{ .position_sv = position_sv, - .pitch_rad = pitch_rad, - .yaw_rad = yaw_rad, + .pitch_turns = pitch_turns, + .yaw_turns = yaw_turns, .movement_state = .flight, }; } @@ -225,8 +221,8 @@ pub fn onKeyUp(self: *Player, key: glfw.Key) void { } pub fn onMouseMove(self: *Player, dx: f32, dy: f32) void { - self.pitch_rad = std.math.clamp(self.pitch_rad - dy * self.mouse_sensitivity, min_pitch_rad, max_pitch_rad); - self.yaw_rad = @mod(self.yaw_rad - dx * self.mouse_sensitivity, std.math.tau); + self.pitch_turns = std.math.clamp(self.pitch_turns - dy * self.mouse_sensitivity, min_pitch_turns, max_pitch_turns); + self.yaw_turns = @mod(self.yaw_turns - dx * self.mouse_sensitivity, 1); } pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void { @@ -234,11 +230,11 @@ pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void { //const raycast_origin_sv = self.position_sv // .add(.init(0, 0, @intFromFloat(@round(c.sv_per_vx * camera_height_vx)))); - //const raycast_ray_sv = Vector3 + //const raycast_ray_sv = vm.Vector3 // .init(0, raycast_length_sv, 0) // .rotate(.mulQuaternion( - // .initRotationXY(self.yaw_rad), - // .initRotationYZ(self.pitch_rad), + // .initRotation(.XY, self.yaw_turns), + // .initRotation(.YZ, self.pitch_turns), // )) // .asVector3Int(); //const raycast_hit = chunks.raycast(raycast_origin_sv, raycast_ray_sv); @@ -246,14 +242,14 @@ pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void { // --- GATHER INPUTS ------------------------------------------------------- const horizontal_input_vector_frac = blk: { - var ret = Vector2 + var ret = vm.Vector2 .init(self.x_input.getComponentFloat(), self.y_input.getComponentFloat()) - .rotate(self.yaw_rad); + .rotate(.initRotation(self.yaw_turns)); const len_squared = ret.lenSquared(); if (len_squared > 1) { ret = ret.divScalar(@sqrt(len_squared)); } - break :blk ret.asVector2IntFrac(); + break :blk math.asIntFrac2(ret); }; const vertical_input_vector_frac = self.z_input.getComponentIntFrac(); @@ -279,10 +275,10 @@ pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void { .ground => {}, .air => {}, .flight => { - const horizontal_velocity_sv = horizontal_input_vector_frac.mulScalarFrac(horizontal_speed_sv); + const horizontal_velocity_sv = math.mulFrac2(horizontal_input_vector_frac, horizontal_speed_sv); const vertical_velocity_sv = math.mulFrac(vertical_input_vector_frac, vertical_speed_sv); - var horizontal_displacement_sv = horizontal_velocity_sv.mulScalarFloat(dt); + var horizontal_displacement_sv = math.mulIntFloat2(horizontal_velocity_sv, dt); var vertical_displacement_sv = math.mulIntFloat(vertical_velocity_sv, dt); var position_sv = self.position_sv; @@ -301,9 +297,7 @@ pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void { var i: usize = 0; while (i < 2) : (i += 1) { if (chunks.sweepCastHorizontal(min_sv, max_sv, horizontal_displacement_sv)) |hit| { - const adjustment = hit.normal_frac - .asVector2Int() - .mulScalarFrac(hit.projected_distance_sv); + const adjustment = math.mulFrac2(hit.normal_frac.dropZ(), hit.projected_distance_sv); horizontal_displacement_sv = .add( horizontal_displacement_sv, adjustment, @@ -312,11 +306,11 @@ pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void { break; } } - position_sv = .add(position_sv, horizontal_displacement_sv.asVector3Int(0)); + position_sv = .add(position_sv, horizontal_displacement_sv.withZ(0)); if (vertical_displacement_sv < 0.0) { - min_sv = .add(min_sv, horizontal_displacement_sv.asVector3Int(0)); - max_sv = .add(max_sv, horizontal_displacement_sv.asVector3Int(0)); + min_sv = .add(min_sv, horizontal_displacement_sv.withZ(0)); + max_sv = .add(max_sv, horizontal_displacement_sv.withZ(0)); if (chunks.sweepCastDown(min_sv, max_sv, -vertical_displacement_sv)) |hit| { vertical_displacement_sv += hit.projected_distance_sv; } diff --git a/src/assets/Chunk.zig b/src/assets/Chunk.zig index e136541..9c9adf0 100644 --- a/src/assets/Chunk.zig +++ b/src/assets/Chunk.zig @@ -4,6 +4,7 @@ const std = @import("std"); const math = @import("../math.zig"); const shaders = @import("../shaders.zig"); const vk = @import("vulkan"); +const vm = @import("vecmath"); const voxels = @import("../voxels.zig"); const Blocks = @import("Blocks.zig"); @@ -13,9 +14,7 @@ const Game = @import("../Game.zig"); const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer; const Materials = @import("Materials.zig"); -const Matrix4x4 = math.Matrix4x4; const ObjectUniformsBuffer = GenericBuffer(void, shaders.ObjectUniforms); -const Vector3 = math.Vector3; pub const chunk_size = 16; @@ -25,7 +24,7 @@ var next_chunk_id: std.atomic.Value(u64) = .init(0); /// To get the block at coordinates (x, y, z) relative to the chunk, read the /// value at `blocks[z][y][x]`. blocks: [chunk_size][chunk_size][chunk_size]Blocks.Id, -origin: Vector3, +origin: vm.Vector3, descriptor_set: vk.DescriptorSet, object_buffer: ObjectUniformsBuffer, object_count: u32, @@ -34,7 +33,7 @@ object_count: u32, chunk_id: u64, pub const InitInfo = struct { - origin: Vector3, + origin: vm.Vector3, descriptor_pool: vk.DescriptorPool, per_batch_descriptor_set_layout: vk.DescriptorSetLayout, }; @@ -110,14 +109,18 @@ pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, neighbors: for (row, 0..) |id, ix| { const fx: f32 = @floatFromInt(ix); const block: *const Blocks.Definition = &blocks.array.items[id.toInt()]; - const origin = Vector3.add(self.origin, .init(fx, fy, fz)); + const origin = vm.Vector3.add(self.origin, .init(fx, fy, fz)); inline for (@typeInfo(voxels.Orientation).@"enum".fields) |field| { const side = @field(voxels.Orientation, field.name); const material = @field(block.walls, field.name).material; if (material != .empty and self.getOpposite(side, ix, iy, iz, blocks, neighbors) == .empty) { const matrix = getMatrix(side, origin); - try uniforms.append(temp_allocator, .init(matrix, matrix, material)); + try uniforms.append(temp_allocator, .{ + .matrixOStoWS = matrix, + .matrixOStoWSNormal = matrix, + .material = material, + }); } } } @@ -209,44 +212,44 @@ fn getOpposite(self: *const Chunk, comptime side: voxels.Orientation, x: usize, }; } -fn getMatrix(comptime side: voxels.Orientation, origin: Vector3) Matrix4x4 { +fn getMatrix(comptime side: voxels.Orientation, origin: vm.Vector3) vm.Matrix4x4 { return switch (side) { // zig fmt: off .positive_x => .init( 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, - origin.getX() + 1, origin.getY(), origin.getZ(), 1, + origin.x + 1, origin.y, origin.z, 1, ), .negative_x => .init( - 0, -1, 0, 0, - 0, 0, 1, 0, - -1, 0, 0, 0, - origin.getX(), origin.getY() + 1, origin.getZ(), 1, + 0, -1, 0, 0, + 0, 0, 1, 0, + -1, 0, 0, 0, + origin.x, origin.y + 1, origin.z, 1, ), .positive_y => .init( -1, 0, 0, 0, - 0, 0, 1, 0, - 0, 1, 0, 0, - origin.getX() + 1, origin.getY() + 1, origin.getZ(), 1, + 0, 0, 1, 0, + 0, 1, 0, 0, + origin.x + 1, origin.y + 1, origin.z, 1, ), .negative_y => .init( - 1, 0, 0, 0, - 0, 0, 1, 0, + 1, 0, 0, 0, + 0, 0, 1, 0, 0, -1, 0, 0, - origin.getX(), origin.getY(), origin.getZ(), 1, + origin.x, origin.y, origin.z, 1, ), .positive_z => .init( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, - origin.getX(), origin.getY(), origin.getZ() + 1, 1, + origin.x, origin.y, origin.z + 1, 1, ), .negative_z => .init( - 1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, -1, 0, - origin.getX() + 1, origin.getY() + 1, origin.getZ(), 1, + -1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 1, 0, + origin.x + 1, origin.y + 1, origin.z, 1, ), // zig fmt: on }; diff --git a/src/assets/Materials.zig b/src/assets/Materials.zig index b1fb3d7..906cdb0 100644 --- a/src/assets/Materials.zig +++ b/src/assets/Materials.zig @@ -80,8 +80,8 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Materials { .element_offset = Id.empty.toInt(), .elements = &.{ .{ - .base_color = .{ 0, 0, 0 }, - .emissive = .{ 1, 0, 1 }, + .base_color = .zero, + .emissive = .init(1, 0, 1), .ior = 1.45, .metallic = 0, .normal_scale = 1, @@ -295,8 +295,8 @@ fn loadMaterial(self: *Materials, engine: *Engine, textures: *Textures, filename .element_offset = index, .elements = &.{ .{ - .base_color = material_json.baseColor, - .emissive = material_json.emissive, + .base_color = .initArray(material_json.baseColor), + .emissive = .initArray(material_json.emissive), .ior = material_json.ior, .metallic = material_json.metallic, .normal_scale = material_json.normalScale, diff --git a/src/const.zig b/src/const.zig index 083a662..92ddb0f 100644 --- a/src/const.zig +++ b/src/const.zig @@ -1,6 +1,5 @@ const std = @import("std"); - -const Vector2Int = @import("math.zig").Vector2Int; +const vm = @import("vecmath"); pub const app_name = "voxel-game"; pub const app_version_string = @import("config").version; @@ -11,11 +10,11 @@ pub const max_frametime = 1.0 / min_framerate; pub const default_window_width = 1280; pub const default_window_height = 720; -pub const default_window_size = Vector2Int.init(default_window_width, default_window_height); +pub const default_window_size = vm.Vector2Int.init(default_window_width, default_window_height); pub const min_window_width = 640; pub const min_window_height = 360; -pub const min_window_size = Vector2Int.init(default_window_width, default_window_height); +pub const min_window_size = vm.Vector2Int.init(default_window_width, default_window_height); pub const window_title = "Voxel Game"; diff --git a/src/engine/Skybox.zig b/src/engine/Skybox.zig index ce6a85f..8a4e023 100644 --- a/src/engine/Skybox.zig +++ b/src/engine/Skybox.zig @@ -4,6 +4,7 @@ const std = @import("std"); const shaders = @import("../shaders.zig"); const stbi = @import("zstbi"); const vk = @import("vulkan"); +const vm = @import("vecmath"); const CommandBuffer = @import("CommandBuffer.zig"); const Engine = @import("Engine.zig"); @@ -14,7 +15,7 @@ image: vk.Image, image_view: vk.ImageView, device_memory: vk.DeviceMemory, -vertex_buffer: GenericBuffer(void, [3]f32), +vertex_buffer: GenericBuffer(void, vm.Vector3), index_buffer: shaders.IndexBuffer, sampler: vk.Sampler, @@ -468,7 +469,7 @@ pub fn load(filename: []const u8, engine: *Engine, cube_size: u32, global_unifor // --- SKYBOX PIPELINE ----------------------------------------------------- - var vertex_buffer = try GenericBuffer(void, [3]f32).init(engine, .{ + var vertex_buffer = try GenericBuffer(void, vm.Vector3).init(engine, .{ .usage = .vertex, .target_queue = .graphics, .array_capacity = 8, @@ -485,14 +486,14 @@ pub fn load(filename: []const u8, engine: *Engine, cube_size: u32, global_unifor try vertex_buffer.write(engine, .{ .elements = &.{ - .{ -1, -1, -1 }, - .{ 1, -1, -1 }, - .{ -1, 1, -1 }, - .{ 1, 1, -1 }, - .{ -1, -1, 1 }, - .{ 1, -1, 1 }, - .{ -1, 1, 1 }, - .{ 1, 1, 1 }, + .init(-1, -1, -1), + .init(1, -1, -1), + .init(-1, 1, -1), + .init(1, 1, -1), + .init(-1, -1, 1), + .init(1, -1, 1), + .init(-1, 1, 1), + .init(1, 1, 1), }, }); diff --git a/src/math.zig b/src/math.zig index 21cf734..6bebec9 100644 --- a/src/math.zig +++ b/src/math.zig @@ -1,41 +1,8 @@ const std = @import("std"); +const vm = @import("vecmath"); pub const Iterator2 = @import("math/Iterator2.zig").Iterator2; pub const Iterator3 = @import("math/Iterator3.zig").Iterator3; -pub const Matrix4x4 = @import("math/Matrix4x4.zig").Matrix4x4; -pub const Quaternion = @import("math/Quaternion.zig").Quaternion; -pub const Vector2 = @import("math/Vector2.zig").Vector2; -pub const Vector2Int = @import("math/Vector2Int.zig").Vector2Int; -pub const Vector2x8 = @import("math/Vector2x8.zig").Vector2x8; -pub const Vector3 = @import("math/Vector3.zig").Vector3; -pub const Vector3Int = @import("math/Vector3Int.zig").Vector3Int; -pub const Vector4 = @import("math/Vector4.zig").Vector4; - -pub const f32x8 = @Vector(8, f32); -pub const i32x8 = @Vector(8, i32); -pub const u32x8 = @Vector(8, u32); -pub const u64x8 = @Vector(8, u64); - -pub inline fn ps(value: f32) f32x8 { - return @splat(value); -} - -pub inline fn epi32(value: i32) i32x8 { - return @splat(value); -} - -pub inline fn epu32(value: u32) u32x8 { - return @splat(value); -} - -pub inline fn epu64x2(value: u64) u64x8 { - return @splat(value); -} - -pub inline fn lerp(a: f32, b: f32, t: f32) f32 { - const s = 1.0 - t; - return a * s + b * t; -} pub const noise2 = @import("math/noise.zig").noise2; pub const noise2x8 = @import("math/noise.zig").noise2x8; @@ -46,18 +13,90 @@ pub inline fn asFloatFrac(frac: i32) f32 { return @floatCast(numerator / denominator); } +pub inline fn asFloatFrac2(frac: vm.Vector2Int) vm.Vector2 { + return .init( + asFloatFrac(frac.x), + asFloatFrac(frac.y), + ); +} + +pub inline fn asFloatFrac3(frac: vm.Vector3Int) vm.Vector3 { + return .init( + asFloatFrac(frac.x), + asFloatFrac(frac.y), + asFloatFrac(frac.z), + ); +} + +pub inline fn asFloatFrac4(frac: vm.Vector4Int) vm.Vector4 { + return .init( + asFloatFrac(frac.x), + asFloatFrac(frac.y), + asFloatFrac(frac.z), + asFloatFrac(frac.w), + ); +} + pub inline fn asIntFrac(frac: f32) i32 { const fraction: f64 = @floatCast(frac); const scale: f64 = std.math.maxInt(i32); return @intFromFloat(@round(fraction * scale)); } +pub inline fn asIntFrac2(frac: vm.Vector2) vm.Vector2Int { + return .init( + asIntFrac(frac.x), + asIntFrac(frac.y), + ); +} + +pub inline fn asIntFrac3(frac: vm.Vector3) vm.Vector3Int { + return .init( + asIntFrac(frac.x), + asIntFrac(frac.y), + asIntFrac(frac.z), + ); +} + +pub inline fn asIntFrac4(frac: vm.Vector4) vm.Vector4Int { + return .init( + asIntFrac(frac.x), + asIntFrac(frac.y), + asIntFrac(frac.z), + asIntFrac(frac.w), + ); +} + pub inline fn mulIntFloat(int: i32, float: f32) i32 { const int_float: f64 = @floatFromInt(int); const float_wide: f64 = @floatCast(float); return @intFromFloat(@round(int_float * float_wide)); } +pub inline fn mulIntFloat2(int: vm.Vector2Int, float: f32) vm.Vector2Int { + return .init( + mulIntFloat(int.x, float), + mulIntFloat(int.y, float), + ); +} + +pub inline fn mulIntFloat3(int: vm.Vector3Int, float: f32) vm.Vector3Int { + return .init( + mulIntFloat(int.x, float), + mulIntFloat(int.y, float), + mulIntFloat(int.z, float), + ); +} + +pub inline fn mulIntFloat4(int: vm.Vector4Int, float: f32) vm.Vector4Int { + return .init( + mulIntFloat(int.x, float), + mulIntFloat(int.y, float), + mulIntFloat(int.z, float), + mulIntFloat(int.w, float), + ); +} + pub inline fn mulFrac(a: i32, b: i32) i32 { const denominator: i64 = std.math.maxInt(i32); const rounding_bias: i64 = denominator >> 1; @@ -66,6 +105,30 @@ pub inline fn mulFrac(a: i32, b: i32) i32 { return @intCast(@divFloor(a_wide * b_wide + rounding_bias, denominator)); } +pub inline fn mulFrac2(a: vm.Vector2Int, b: i32) vm.Vector2Int { + return .init( + mulFrac(a.x, b), + mulFrac(a.y, b), + ); +} + +pub inline fn mulFrac3(a: vm.Vector3Int, b: i32) vm.Vector3Int { + return .init( + mulFrac(a.x, b), + mulFrac(a.y, b), + mulFrac(a.z, b), + ); +} + +pub inline fn mulFrac4(a: vm.Vector4Int, b: i32) vm.Vector4Int { + return .init( + mulFrac(a.x, b), + mulFrac(a.y, b), + mulFrac(a.z, b), + mulFrac(a.w, b), + ); +} + pub inline fn mulFracFrac(a: i32, b: i32) i32 { const denominator: i64 = std.math.maxInt(i32) * std.math.maxInt(i32); const rounding_bias: i64 = denominator >> 1; @@ -74,6 +137,30 @@ pub inline fn mulFracFrac(a: i32, b: i32) i32 { return .{ .vector = @intCast(@divFloor(a_wide * b_wide + rounding_bias, denominator)) }; } +pub inline fn mulFracFrac2(a: vm.Vector2Int, b: i32) vm.Vector2Int { + return .init( + mulFracFrac(a.x, b), + mulFracFrac(a.y, b), + ); +} + +pub inline fn mulFracFrac3(a: vm.Vector3Int, b: i32) vm.Vector3Int { + return .init( + mulFracFrac(a.x, b), + mulFracFrac(a.y, b), + mulFracFrac(a.z, b), + ); +} + +pub inline fn mulFracFrac4(a: vm.Vector4Int, b: i32) vm.Vector4Int { + return .init( + mulFracFrac(a.x, b), + mulFracFrac(a.y, b), + mulFracFrac(a.z, b), + mulFracFrac(a.w, b), + ); +} + pub inline fn wideMulDivFloor(a: i32, mul: i32, div: i32) i32 { return @intCast(@divFloor(@as(i64, a) * @as(i64, mul), div)); } diff --git a/src/math/Matrix4x4.zig b/src/math/Matrix4x4.zig deleted file mode 100644 index 83cb57a..0000000 --- a/src/math/Matrix4x4.zig +++ /dev/null @@ -1,283 +0,0 @@ -const Vector3 = @import("Vector3.zig").Vector3; -const Vector4 = @import("Vector4.zig").Vector4; -const Quaternion = @import("Quaternion.zig").Quaternion; - -pub const Matrix4x4 = extern struct { - i: Vector4, - j: Vector4, - k: Vector4, - t: Vector4, - - pub const identity = Matrix4x4.init( - // zig fmt: off - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - // zig fmt: on - ); - - // --- INIT --- - - pub inline fn init( - // zig fmt: off - ix: f32, iy: f32, iz: f32, iw: f32, - jx: f32, jy: f32, jz: f32, jw: f32, - kx: f32, ky: f32, kz: f32, kw: f32, - tx: f32, ty: f32, tz: f32, tw: f32, - // zig fmt: on - ) Matrix4x4 { - return .{ - .i = .init(ix, iy, iz, iw), - .j = .init(jx, jy, jz, jw), - .k = .init(kx, ky, kz, kw), - .t = .init(tx, ty, tz, tw), - }; - } - - pub inline fn initArray(array: [16]f32) Matrix4x4 { - return .{ - .i = .initArray(array[0..4].*), - .j = .initArray(array[4..8].*), - .k = .initArray(array[8..12].*), - .t = .initArray(array[12..16].*), - }; - } - - pub inline fn initVector4(i: Vector4, j: Vector4, k: Vector4, t: Vector4) Matrix4x4 { - return .{ .i = i, .j = j, .k = k, .t = t }; - } - - pub inline fn initTranslation(translation: Vector3) Matrix4x4 { - return .initVector4( - .unit_x, - .unit_y, - .unit_z, - translation.asVector4(1), - ); - } - - pub inline fn initRotation(rotation: Quaternion) Matrix4x4 { - const xx = rotation.vector.getX() * rotation.vector.getX(); - const xy = rotation.vector.getX() * rotation.vector.getY(); - const xz = rotation.vector.getX() * rotation.vector.getZ(); - const xw = rotation.vector.getX() * rotation.vector.getW(); - const yy = rotation.vector.getY() * rotation.vector.getY(); - const yz = rotation.vector.getY() * rotation.vector.getZ(); - const yw = rotation.vector.getY() * rotation.vector.getW(); - const zz = rotation.vector.getZ() * rotation.vector.getZ(); - const zw = rotation.vector.getZ() * rotation.vector.getW(); - - return .init( - // zig fmt: off - 1 - 2 * (yy + zz), 2 * (xy + zw), 2 * (xz - yw), 0, - 2 * (xy - zw), 1 - 2 * (xx + zz), 2 * (yz + xw), 0, - 2 * (xz + yw), 2 * (yz - xw), 1 - 2 * (xx + yy), 0, - 0, 0, 0, 1, - // zig fmt: on - ); - } - - pub inline fn initScale(scale: Vector3) Matrix4x4 { - return .init( - // zig fmt: off - scale.getX(), 0, 0, 0, - 0, scale.getY(), 0, 0, - 0, 0, scale.getZ(), 0, - 0, 0, 0, 1, - // zig fmt: on - ); - } - - pub inline fn initTranslationRotationScale( - translation: Vector3, - rotation: Quaternion, - scale: Vector3, - ) Matrix4x4 { - const xx = rotation.vector.getX() * rotation.vector.getX(); - const xy = rotation.vector.getX() * rotation.vector.getY(); - const xz = rotation.vector.getX() * rotation.vector.getZ(); - const xw = rotation.vector.getX() * rotation.vector.getW(); - const yy = rotation.vector.getY() * rotation.vector.getY(); - const yz = rotation.vector.getY() * rotation.vector.getZ(); - const yw = rotation.vector.getY() * rotation.vector.getW(); - const zz = rotation.vector.getZ() * rotation.vector.getZ(); - const zw = rotation.vector.getZ() * rotation.vector.getW(); - - const rotation_i = Vector4.init((1 - 2 * (yy + zz)), 2 * (xy + zw), 2 * (xz - yw), 0); - const rotation_j = Vector4.init(2 * (xy - zw), (1 - 2 * (xx + zz)), 2 * (yz + xw), 0); - const rotation_k = Vector4.init(2 * (xz + yw), 2 * (yz - xw), (1 - 2 * (xx + yy)), 0); - - return .initVector4( - .mulScalar(rotation_i, scale.getX()), - .mulScalar(rotation_j, scale.getY()), - .mulScalar(rotation_k, scale.getZ()), - translation.asVector4(1), - ); - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Matrix4x4) [16]f32 { - return self.i.asArray() ++ self.j.asArray() ++ self.k.asArray() ++ self.t.asArray(); - } - - pub inline fn asVector4(self: Matrix4x4) [4]Vector4 { - return .{ self.i, self.j, self.k, self.t }; - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Matrix4x4, other: Matrix4x4) Matrix4x4 { - return .initVector4( - .add(self.i, other.i), - .add(self.j, other.j), - .add(self.k, other.k), - .add(self.t, other.t), - ); - } - - pub inline fn sub(self: Matrix4x4, other: Matrix4x4) Matrix4x4 { - return .initVector4( - .sub(self.i, other.i), - .sub(self.j, other.j), - .sub(self.k, other.k), - .sub(self.t, other.t), - ); - } - - pub inline fn negate(self: Matrix4x4) Matrix4x4 { - return .initVector4( - .negate(self.i), - .negate(self.j), - .negate(self.k), - .negate(self.t), - ); - } - - pub inline fn mulScalar(self: Matrix4x4, scalar: f32) Matrix4x4 { - return .initVector4( - .mulScalar(self.i, scalar), - .mulScalar(self.j, scalar), - .mulScalar(self.k, scalar), - .mulScalar(self.t, scalar), - ); - } - - pub inline fn divScalar(self: Matrix4x4, scalar: f32) Matrix4x4 { - const inv_scalar = 1 / scalar; - return .initVector4( - .mulScalar(self.i, inv_scalar), - .mulScalar(self.j, inv_scalar), - .mulScalar(self.k, inv_scalar), - .mulScalar(self.t, inv_scalar), - ); - } - - // --- OTHER --- - - pub inline fn mulMatrix(self: Matrix4x4, other: Matrix4x4) Matrix4x4 { - return .initVector4( - self.i.mulScalar(other.i.getX()) - .add(self.j.mulScalar(other.i.getY())) - .add(self.k.mulScalar(other.i.getZ())) - .add(self.t.mulScalar(other.i.getW())), - self.i.mulScalar(other.j.getX()) - .add(self.j.mulScalar(other.j.getY())) - .add(self.k.mulScalar(other.j.getZ())) - .add(self.t.mulScalar(other.j.getW())), - self.i.mulScalar(other.k.getX()) - .add(self.j.mulScalar(other.k.getY())) - .add(self.k.mulScalar(other.k.getZ())) - .add(self.t.mulScalar(other.k.getW())), - self.i.mulScalar(other.t.getX()) - .add(self.j.mulScalar(other.t.getY())) - .add(self.k.mulScalar(other.t.getZ())) - .add(self.t.mulScalar(other.t.getW())), - ); - } - - pub inline fn inverseAffine(self: Matrix4x4) Matrix4x4 { - // zig fmt: off - const det = self.i.getX() * self.j.getY() * self.k.getZ() - + self.i.getY() * self.j.getZ() * self.k.getX() - + self.i.getZ() * self.j.getX() * self.k.getY() - - self.i.getX() * self.j.getZ() * self.k.getY() - - self.i.getY() * self.j.getX() * self.k.getZ() - - self.i.getZ() * self.j.getY() * self.k.getX(); - // zig fmt: on - const inv_det = 1 / det; - - const i = Vector3.init( - self.j.getY() * self.k.getZ() - self.j.getZ() * self.k.getY(), - self.i.getZ() * self.k.getY() - self.i.getY() * self.k.getZ(), - self.i.getY() * self.j.getZ() - self.i.getZ() * self.j.getY(), - ).mulScalar(inv_det); - - const j = Vector3.init( - self.j.getZ() * self.k.getX() - self.j.getX() * self.k.getZ(), - self.i.getX() * self.k.getZ() - self.i.getZ() * self.k.getX(), - self.i.getZ() * self.j.getX() - self.i.getX() * self.j.getZ(), - ).mulScalar(inv_det); - - const k = Vector3.init( - self.j.getX() * self.k.getY() - self.j.getY() * self.k.getX(), - self.i.getY() * self.k.getX() - self.i.getX() * self.k.getY(), - self.i.getX() * self.j.getY() - self.i.getY() * self.j.getX(), - ).mulScalar(inv_det); - - const t = self.i.asVector3().mulScalar(self.t.getX()) - .add(self.j.asVector3().mulScalar(self.t.getY())) - .add(self.k.asVector3().mulScalar(self.t.getZ())) - .negate(); - - return .initVector4( - i.asVector4(0), - j.asVector4(0), - k.asVector4(0), - t.asVector4(1), - ); - } - - pub inline fn inverseTransposeAffine(self: Matrix4x4) Matrix4x4 { - // zig fmt: off - const det = self.i.getX() * self.j.getY() * self.k.getZ() - + self.i.getY() * self.j.getZ() * self.k.getX() - + self.i.getZ() * self.j.getX() * self.k.getY() - - self.i.getX() * self.j.getZ() * self.k.getY() - - self.i.getY() * self.j.getX() * self.k.getZ() - - self.i.getZ() * self.j.getY() * self.k.getX(); - // zig fmt: on - const inv_det = 1 / det; - - const i = Vector3.init( - self.j.getY() * self.k.getZ() - self.j.getZ() * self.k.getY(), - self.j.getZ() * self.k.getX() - self.j.getX() * self.k.getZ(), - self.j.getX() * self.k.getY() - self.j.getY() * self.k.getX(), - ).mulScalar(inv_det); - - const j = Vector3.init( - self.i.getZ() * self.k.getY() - self.i.getY() * self.k.getZ(), - self.i.getX() * self.k.getZ() - self.i.getZ() * self.k.getX(), - self.i.getY() * self.k.getX() - self.i.getX() * self.k.getY(), - ).mulScalar(inv_det); - - const k = Vector3.init( - self.i.getY() * self.j.getZ() - self.i.getZ() * self.j.getY(), - self.i.getZ() * self.j.getX() - self.i.getX() * self.j.getZ(), - self.i.getX() * self.j.getY() - self.i.getY() * self.j.getX(), - ).mulScalar(inv_det); - - const t = self.i.asVector3().mulScalar(self.t.getX()) - .add(self.j.asVector3().mulScalar(self.t.getY())) - .add(self.k.asVector3().mulScalar(self.t.getZ())) - .negate(); - - return .initVector4( - i.asVector4(0), - j.asVector4(0), - k.asVector4(0), - t.asVector4(1), - ); - } -}; diff --git a/src/math/Quaternion.zig b/src/math/Quaternion.zig deleted file mode 100644 index 336a656..0000000 --- a/src/math/Quaternion.zig +++ /dev/null @@ -1,155 +0,0 @@ -const Vector3 = @import("Vector3.zig").Vector3; -const Vector4 = @import("Vector4.zig").Vector4; - -pub const Quaternion = extern struct { - vector: Vector4, - - pub const identity = Quaternion.init(0, 0, 0, 1); - - // --- INIT --- - - pub inline fn init(x: f32, y: f32, z: f32, w: f32) Quaternion { - return .{ .vector = .init(x, y, z, w) }; - } - - pub inline fn initArray(array: [4]f32) Quaternion { - return .{ .vector = .initArray(array) }; - } - - pub inline fn initVector4(vector: Vector4) Quaternion { - return .{ .vector = vector }; - } - - pub inline fn initRotationXY(angle_rad: f32) Quaternion { - const half_angle_rad = 0.5 * angle_rad; - const c = @cos(half_angle_rad); - const s = @sin(half_angle_rad); - return .init(0, 0, s, c); - } - - pub inline fn initRotationXZ(angle_rad: f32) Quaternion { - const half_angle_rad = 0.5 * angle_rad; - const c = @cos(half_angle_rad); - const s = @sin(half_angle_rad); - return .init(0, -s, 0, c); - } - - pub inline fn initRotationYX(angle_rad: f32) Quaternion { - const half_angle_rad = 0.5 * angle_rad; - const c = @cos(half_angle_rad); - const s = @sin(half_angle_rad); - return .init(0, 0, -s, c); - } - - pub inline fn initRotationYZ(angle_rad: f32) Quaternion { - const half_angle_rad = 0.5 * angle_rad; - const c = @cos(half_angle_rad); - const s = @sin(half_angle_rad); - return .init(s, 0, 0, c); - } - - pub inline fn initRotationZX(angle_rad: f32) Quaternion { - const half_angle_rad = 0.5 * angle_rad; - const c = @cos(half_angle_rad); - const s = @sin(half_angle_rad); - return .init(0, s, 0, c); - } - - pub inline fn initRotationZY(angle_rad: f32) Quaternion { - const half_angle_rad = 0.5 * angle_rad; - const c = @cos(half_angle_rad); - const s = @sin(half_angle_rad); - return .init(-s, 0, 0, c); - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Quaternion) [4]f32 { - return self.vector.vector; - } - - pub inline fn asVector4(self: Quaternion) Vector4 { - return self.vector; - } - - // --- ACCESSORS --- - - pub inline fn getVector(self: Quaternion) Vector3 { - return self.vector.asVector3(); - } - - pub inline fn getScalar(self: Quaternion) f32 { - return self.vector.getW(); - } - - pub inline fn setVector(self: Quaternion, vector: Vector3) Quaternion { - return .{ - .vector = .{ - .vector = @shuffle(f32, self.vector.vector, vector.vector, .{ ~@as(i32, 0), ~@as(i32, 1), ~@as(i32, 2), 3 }), - }, - }; - } - - pub inline fn setScalar(self: Quaternion, scalar: f32) Quaternion { - return .initVector4(self.vector.setW(scalar)); - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Quaternion, other: Quaternion) Quaternion { - return .initVector4(.add(self.vector, other.vector)); - } - - pub inline fn sub(self: Quaternion, other: Quaternion) Quaternion { - return .initVector4(.sub(self.vector, other.vector)); - } - - pub inline fn negate(self: Quaternion) Quaternion { - return .initVector4(.negate(self.vector)); - } - - pub inline fn conjugate(self: Quaternion) Quaternion { - return .initVector4(.mul(self.vector, .init(-1, -1, -1, 1))); - } - - pub inline fn mulScalar(self: Quaternion, scalar: f32) Quaternion { - return .initVector4(.mulScalar(self.vector, scalar)); - } - - pub inline fn divScalar(self: Quaternion, scalar: f32) Quaternion { - return .initVector4(.divScalar(self.vector, scalar)); - } - - // --- OTHER --- - - pub inline fn len(self: Quaternion) f32 { - return self.vector.len(); - } - - pub inline fn lenSquared(self: Quaternion) f32 { - return self.vector.lenSquared(); - } - - pub inline fn normalize(self: Quaternion) Quaternion { - return .initVector4(.normalize(self.vector)); - } - - pub inline fn dot(self: Quaternion, other: Quaternion) f32 { - return Vector4.dot(self.vector, other.vector); - } - - pub inline fn lerp(self: Quaternion, other: Quaternion, t: f32) Quaternion { - return .initVector4(.lerp(self.vector, other.vector, t)); - } - - pub inline fn mulQuaternion(self: Quaternion, other: Quaternion) Quaternion { - const x1, const y1, const z1, const w1 = self.vector.vector; - const x2, const y2, const z2, const w2 = other.vector.vector; - return .init( - w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2, - w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2, - w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2, - w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2, - ); - } -}; diff --git a/src/math/Vector2.zig b/src/math/Vector2.zig deleted file mode 100644 index c02a072..0000000 --- a/src/math/Vector2.zig +++ /dev/null @@ -1,172 +0,0 @@ -const std = @import("std"); - -const Vector2Int = @import("Vector2Int.zig").Vector2Int; -const Vector3 = @import("Vector3.zig").Vector3; -const Vector4 = @import("Vector3.zig").Vector4; - -pub const Vector2 = extern struct { - vector: Vector, - - pub const Vector = @Vector(2, f32); - pub const Array = [2]f32; - pub const Mask = enum(i32) { x = 0, y = 1 }; - - pub const zero = Vector2.initScalar(0); - pub const one = Vector2.initScalar(1); - pub const unit_x = Vector2.init(1, 0); - pub const unit_y = Vector2.init(0, 1); - pub const unit_nx = Vector2.init(-1, 0); - pub const unit_ny = Vector2.init(0, -1); - - // --- INIT --- - - pub inline fn initScalar(scalar: f32) Vector2 { - return .{ .vector = @splat(scalar) }; - } - - pub inline fn init(x: f32, y: f32) Vector2 { - return .{ .vector = .{ x, y } }; - } - - pub inline fn initArray(array: Array) Vector2 { - return .{ .vector = array }; - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Vector2) Array { - return self.vector; - } - - pub inline fn asArrayNorm(self: Vector2, comptime T: type) [2]T { - const scale_vector: Vector = @splat(std.math.maxInt(T)); - return @as(@Vector(2, T), @intFromFloat(@round(self.vector * scale_vector))); - } - - pub inline fn asVector2Int(self: Vector2) Vector2Int { - return .{ .vector = @intFromFloat(@round(self.vector)) }; - } - - pub inline fn asVector2IntFrac(self: Vector2) Vector2Int { - const fraction: @Vector(2, f64) = @floatCast(self.vector); - const scale: @Vector(2, f64) = @splat(std.math.maxInt(i32)); - return .{ .vector = @intFromFloat(@round(fraction * scale)) }; - } - - pub inline fn asVector3(self: Vector2, z: f32) Vector3 { - const z_vector: @Vector(3, f32) = .{ undefined, undefined, z }; - return .{ .vector = @shuffle(f32, self.vector, z_vector, [_]i32{ 0, 1, ~@as(i32, 2) }) }; - } - - pub inline fn asVector4(self: Vector4, z: f32, w: f32) Vector4 { - const zw_vector: @Vector(4, f32) = .{ undefined, undefined, z, w }; - return .{ .vector = @shuffle(f32, self.vector, zw_vector, [_]i32{ 0, 1, ~@as(i32, 2), ~@as(i32, 3) }) }; - } - - // --- ACCESSORS --- - - pub inline fn getX(self: Vector2) f32 { - return self.vector[0]; - } - - pub inline fn getY(self: Vector2) f32 { - return self.vector[1]; - } - - pub inline fn setX(self: Vector2, x: f32) Vector2 { - const x_vector: Vector = @splat(x); - return .{ .vector = @shuffle(f32, self.vector, x_vector, .{ ~@as(i32, 0), 1 }) }; - } - - pub inline fn setY(self: Vector2, y: f32) Vector2 { - const y_vector: Vector = @splat(y); - return .{ .vector = @shuffle(f32, self.vector, y_vector, .{ 0, ~@as(i32, 1) }) }; - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Vector2, other: Vector2) Vector2 { - return .{ .vector = self.vector + other.vector }; - } - - pub inline fn sub(self: Vector2, other: Vector2) Vector2 { - return .{ .vector = self.vector - other.vector }; - } - - pub inline fn mul(self: Vector2, other: Vector2) Vector2 { - return .{ .vector = self.vector * other.vector }; - } - - pub inline fn div(self: Vector2, other: Vector2) Vector2 { - return .{ .vector = self.vector / other.vector }; - } - - pub inline fn negate(self: Vector2) Vector2 { - return .{ .vector = -self.vector }; - } - - pub inline fn mulScalar(self: Vector2, scalar: f32) Vector2 { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = self.vector * scalar_vector }; - } - - pub inline fn divScalar(self: Vector2, scalar: f32) Vector2 { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = self.vector / scalar_vector }; - } - - // --- SWIZZLE --- - - pub inline fn swizzle2(self: Vector2, comptime mask: [2]Mask) Vector2 { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([2]i32, @bitCast(mask))) }; - } - - pub inline fn swizzle3(self: Vector2, comptime mask: [3]Mask) Vector3 { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([3]i32, @bitCast(mask))) }; - } - - pub inline fn swizzle4(self: Vector2, comptime mask: [4]Mask) Vector4 { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([4]i32, @bitCast(mask))) }; - } - - // --- OTHER --- - - pub inline fn len(self: Vector2) f32 { - return @sqrt(@reduce(.Add, self.vector * self.vector)); - } - - pub inline fn lenSquared(self: Vector2) f32 { - return @reduce(.Add, self.vector * self.vector); - } - - pub inline fn normalize(self: Vector2) Vector2 { - const len_vector: Vector = @splat(@sqrt(@reduce(.Add, self.vector * self.vector))); - return .{ .vector = self.vector / len_vector }; - } - - pub inline fn dot(self: Vector2, other: Vector2) f32 { - return @reduce(.Add, self.vector * other.vector); - } - - pub inline fn cross(self: Vector2, other: Vector2) f32 { - return self.getX() * other.getY() - self.getY() * other.getX(); - } - - pub inline fn lerp(self: Vector2, other: Vector2, t: f32) Vector2 { - const s = 1.0 - t; - const t_vector: Vector = @splat(t); - const s_vector: Vector = @splat(s); - return .{ .vector = self * s_vector + other * t_vector }; - } - - pub inline fn rotate(self: Vector2, angle_rad: f32) Vector2 { - const c = @cos(angle_rad); - const s = @sin(angle_rad); - return .{ - .vector = .{ - self.getX() * c - self.getY() * s, - self.getX() * s + self.getY() * c, - }, - }; - } -}; diff --git a/src/math/Vector2Int.zig b/src/math/Vector2Int.zig deleted file mode 100644 index d05382c..0000000 --- a/src/math/Vector2Int.zig +++ /dev/null @@ -1,199 +0,0 @@ -const std = @import("std"); - -const Vector2 = @import("Vector2.zig").Vector2; -const Vector3Int = @import("Vector3Int.zig").Vector3Int; - -pub const Vector2Int = extern struct { - vector: Vector, - - pub const Vector = @Vector(2, i32); - pub const Array = [2]i32; - pub const Mask = enum(i32) { x = 0, y = 1 }; - - pub const zero = Vector2Int.initScalar(0); - pub const one = Vector2Int.initScalar(1); - pub const one_frac = Vector2Int.initScalar(std.math.maxInt(i32)); - pub const unit_x = Vector2Int.init(1, 0); - pub const unit_y = Vector2Int.init(0, 1); - pub const unit_nx = Vector2Int.init(-1, 0); - pub const unit_ny = Vector2Int.init(0, -1); - pub const unit_x_frac = Vector2Int.init(std.math.maxInt(i32), 0); - pub const unit_y_frac = Vector2Int.init(0, std.math.maxInt(i32)); - pub const unit_nx_frac = Vector2Int.init(-std.math.maxInt(i32), 0); - pub const unit_ny_frac = Vector2Int.init(0, -std.math.maxInt(i32)); - - // --- INIT --- - - pub inline fn initScalar(scalar: i32) Vector2Int { - return .{ .vector = @splat(scalar) }; - } - - pub inline fn init(x: i32, y: i32) Vector2Int { - return .{ .vector = .{ x, y } }; - } - - pub inline fn initArray(array: Array) Vector2Int { - return .{ .vector = array }; - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Vector2Int) Array { - return self.vector; - } - - pub inline fn asVector2(self: Vector2Int) Vector2 { - return .{ .vector = @floatFromInt(self.vector) }; - } - - pub inline fn asVector2Frac(self: Vector2Int) Vector2 { - const numerator: @Vector(2, f64) = @floatFromInt(self.vector); - const denominator: @Vector(2, f64) = @splat(std.math.maxInt(i32)); - return .{ .vector = @floatCast(numerator / denominator) }; - } - - pub inline fn asVector3Int(self: Vector2Int, z: i32) Vector3Int { - const z_vector: @Vector(3, i32) = .{ undefined, undefined, z }; - return .{ .vector = @shuffle(i32, self.vector, z_vector, [_]i32{ 0, 1, ~@as(i32, 2) }) }; - } - - // --- ACCESSORS --- - - pub inline fn getX(self: Vector2Int) i32 { - return self.vector[0]; - } - - pub inline fn getY(self: Vector2Int) i32 { - return self.vector[1]; - } - - pub inline fn setX(self: Vector2Int, x: i32) Vector2Int { - const x_vector: Vector = @splat(x); - return .{ .vector = @shuffle(i32, self.vector, x_vector, .{ ~@as(i32, 0), 1 }) }; - } - - pub inline fn setY(self: Vector2Int, y: i32) Vector2Int { - const y_vector: Vector = @splat(y); - return .{ .vector = @shuffle(i32, self.vector, y_vector, .{ 0, ~@as(i32, 1) }) }; - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Vector2Int, other: Vector2Int) Vector2Int { - return .{ .vector = self.vector + other.vector }; - } - - pub inline fn sub(self: Vector2Int, other: Vector2Int) Vector2Int { - return .{ .vector = self.vector - other.vector }; - } - - pub inline fn mul(self: Vector2Int, other: Vector2Int) Vector2Int { - return .{ .vector = self.vector * other.vector }; - } - - pub inline fn mulFrac(self: Vector2Int, other: Vector2Int) Vector2Int { - const denominator: @Vector(2, i64) = @splat(std.math.maxInt(i32)); - const rounding_bias: @Vector(2, i64) = denominator >> @as(@Vector(2, u6), @splat(1)); - const self_wide: @Vector(2, i64) = self.vector; - const other_wide: @Vector(2, i64) = other.vector; - return .{ .vector = @intCast(@divFloor(self_wide * other_wide + rounding_bias, denominator)) }; - } - - pub inline fn mulFracFrac(self: Vector2Int, other: Vector2Int) Vector2Int { - const denominator: @Vector(2, i64) = @splat(std.math.maxInt(i32) * std.math.maxInt(i32)); - const rounding_bias: @Vector(2, i64) = denominator >> @as(@Vector(2, u6), @splat(1)); - const self_wide: @Vector(2, i64) = self.vector; - const other_wide: @Vector(2, i64) = other.vector; - return .{ .vector = @intCast(@divFloor(self_wide * other_wide + rounding_bias, denominator)) }; - } - - pub inline fn div(self: Vector2Int, other: Vector2Int) Vector2Int { - return .{ .vector = @divFloor(self.vector, other.vector) }; - } - - pub inline fn mod(self: Vector2Int, other: Vector2Int) Vector2Int { - return .{ .vector = @mod(self.vector, other.vector) }; - } - - pub inline fn negate(self: Vector2Int) Vector2Int { - return .{ .vector = -self.vector }; - } - - pub inline fn mulScalar(self: Vector2Int, scalar: i32) Vector2Int { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = self.vector * scalar_vector }; - } - - pub inline fn mulScalarFloat(self: Vector2Int, scalar: f32) Vector2Int { - const self_float: @Vector(2, f64) = @floatFromInt(self.vector); - const scalar_vector_float: @Vector(2, f64) = @splat(scalar); - return .{ .vector = @intFromFloat(@round(self_float * scalar_vector_float)) }; - } - - pub inline fn mulScalarFrac(self: Vector2Int, scalar: i32) Vector2Int { - const denominator: @Vector(2, i64) = @splat(std.math.maxInt(i32)); - const rounding_bias: @Vector(2, i64) = denominator >> @as(@Vector(2, u6), @splat(1)); - const self_wide: @Vector(2, i64) = self.vector; - const scalar_wide: @Vector(2, i64) = @splat(scalar); - return .{ .vector = @intCast(@divFloor(self_wide * scalar_wide + rounding_bias, denominator)) }; - } - - pub inline fn mulScalarFracFrac(self: Vector2Int, scalar: i32) Vector2Int { - const denominator: @Vector(2, i64) = @splat(std.math.maxInt(i32) * std.math.maxInt(i32)); - const rounding_bias: @Vector(2, i64) = denominator >> @as(@Vector(2, u6), @splat(1)); - const self_wide: @Vector(2, i64) = self.vector; - const scalar_wide: @Vector(2, i64) = @splat(scalar); - return .{ .vector = @intCast(@divFloor(self_wide * scalar_wide + rounding_bias, denominator)) }; - } - - pub inline fn divScalar(self: Vector2Int, scalar: i32) Vector2Int { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = @divFloor(self.vector, scalar_vector) }; - } - - pub inline fn divScalarFloat(self: Vector2Int, scalar: f32) Vector2Int { - const self_float: @Vector(2, f64) = @floatFromInt(self.vector); - const scalar_vector_float: @Vector(2, f64) = @splat(scalar); - return .{ .vector = @intFromFloat(@round(self_float / scalar_vector_float)) }; - } - - pub inline fn modScalar(self: Vector2Int, scalar: i32) Vector2Int { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = @mod(self.vector, scalar_vector) }; - } - - pub inline fn abs(self: Vector2Int) Vector2Int { - return .{ .vector = @intCast(@abs(self.vector)) }; - } - - pub inline fn sign(self: Vector2Int) Vector2Int { - return .{ .vector = std.math.sign(self.vector) }; - } - - // --- SWIZZLE --- - - pub inline fn swizzle2(self: Vector2Int, comptime mask: [2]Mask) Vector2Int { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([2]i32, @bitCast(mask))) }; - } - - pub inline fn swizzle3(self: Vector2Int, comptime mask: [3]Mask) Vector3Int { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([3]i32, @bitCast(mask))) }; - } - - // --- OTHER --- - - pub inline fn lenSquared(self: Vector2Int) i64 { - const self_wide: @Vector(2, i64) = self.vector; - return @reduce(.Add, self_wide * self_wide); - } - - pub inline fn dot(self: Vector2Int, other: Vector2Int) i64 { - const self_wide: @Vector(2, i64) = self.vector; - const other_wide: @Vector(2, i64) = other.vector; - return @reduce(.Add, self_wide * other_wide); - } - - pub inline fn cross(self: Vector2Int, other: Vector2Int) i64 { - return @as(i64, self.getX()) * @as(i64, other.getY()) - @as(i64, self.getY()) * @as(i64, other.getX()); - } -}; diff --git a/src/math/Vector2x8.zig b/src/math/Vector2x8.zig deleted file mode 100644 index def0c9d..0000000 --- a/src/math/Vector2x8.zig +++ /dev/null @@ -1,166 +0,0 @@ -const std = @import("std"); -const math = @import("../math.zig"); - -const Vector2 = @import("Vector2.zig").Vector2; - -const f32x8 = math.f32x8; -const ps = math.ps; - -pub const Vector2x8 = extern struct { - x: f32x8, - y: f32x8, - - pub const zero = Vector2x8.init(ps(0), ps(0)); - pub const one = Vector2x8.init(ps(1), ps(1)); - pub const unit_x = Vector2x8.init(ps(1), ps(0)); - pub const unit_y = Vector2x8.init(ps(0), ps(1)); - pub const unit_nx = Vector2x8.init(ps(-1), ps(0)); - pub const unit_ny = Vector2x8.init(ps(0), ps(-1)); - - // --- INIT --- - - pub inline fn initScalar(x: f32, y: f32) Vector2x8 { - return .{ .x = ps(x), .y = ps(y) }; - } - - pub inline fn initScalars(x: f32x8, y: f32x8) Vector2x8 { - return .{ .x = x, .y = y }; - } - - pub inline fn initVector(vector: Vector2) Vector2x8 { - return .{ .x = ps(vector.getX()), .y = ps(vector.getY()) }; - } - - pub inline fn initVectors(vectors: [8]Vector2) Vector2x8 { - const v0: f32x8 = @as([8]f32, @bitCast(vectors[0..4].*)); - const v1: f32x8 = @as([8]f32, @bitCast(vectors[4..8].*)); - const x: f32x8 = @shuffle(f32, v0, v1, [_]i32{ 0, 2, 4, 6, ~@as(i32, 0), ~@as(i32, 2), ~@as(i32, 4), ~@as(i32, 6) }); - const y: f32x8 = @shuffle(f32, v0, v1, [_]i32{ 1, 3, 5, 7, ~@as(i32, 1), ~@as(i32, 3), ~@as(i32, 5), ~@as(i32, 7) }); - return .{ .x = x, .y = y }; - } - - // --- CONVERSION --- - - pub inline fn asVectors(self: Vector2x8) [8]Vector2 { - const v0: f32x8 = @shuffle(f32, self.x, self.y, [_]i32{ 0, ~@as(i32, 0), 1, ~@as(i32, 1), 2, ~@as(i32, 2), 3, ~@as(i32, 3) }); - const v1: f32x8 = @shuffle(f32, self.x, self.y, [_]i32{ 4, ~@as(i32, 4), 5, ~@as(i32, 5), 6, ~@as(i32, 6), 7, ~@as(i32, 7) }); - return @as([4]Vector2, @bitCast(@as([8]f32, v0))) ++ @as([4]Vector2, @bitCast(@as([8]f32, v1))); - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Vector2x8, other: Vector2x8) Vector2x8 { - return .{ - .x = self.x + other.x, - .y = self.y + other.y, - }; - } - - pub inline fn sub(self: Vector2x8, other: Vector2x8) Vector2x8 { - return .{ - .x = self.x - other.x, - .y = self.y - other.y, - }; - } - - pub inline fn mul(self: Vector2x8, other: Vector2x8) Vector2x8 { - return .{ - .x = self.x * other.x, - .y = self.y * other.y, - }; - } - - pub inline fn div(self: Vector2x8, other: Vector2x8) Vector2x8 { - return .{ - .x = self.x / other.x, - .y = self.y / other.y, - }; - } - - pub inline fn negate(self: Vector2x8) Vector2x8 { - return .{ - .x = -self.x, - .y = -self.y, - }; - } - - pub inline fn mulScalar(self: Vector2x8, scalar: f32) Vector2x8 { - return .{ - .x = self.x * ps(scalar), - .y = self.y * ps(scalar), - }; - } - - pub inline fn mulScalars(self: Vector2x8, scalar: f32x8) Vector2x8 { - return .{ - .x = self.x * scalar, - .y = self.y * scalar, - }; - } - - pub inline fn divScalar(self: Vector2x8, scalar: f32) Vector2x8 { - return .{ - .x = self.x / ps(scalar), - .y = self.y / ps(scalar), - }; - } - - pub inline fn divScalars(self: Vector2x8, scalar: f32x8) Vector2x8 { - return .{ - .x = self.x / scalar, - .y = self.y / scalar, - }; - } - - // --- OTHER --- - - pub inline fn len(self: Vector2x8) f32x8 { - return @sqrt(self.x * self.x + self.y * self.y); - } - - pub inline fn lenSquared(self: Vector2x8) f32x8 { - return self.x * self.x + self.y * self.y; - } - - pub inline fn normalize(self: Vector2x8) Vector2x8 { - const len_vector: f32x8 = @sqrt(self.x * self.x + self.y * self.y); - return .{ - .x = self.x / len_vector, - .y = self.y / len_vector, - }; - } - - pub inline fn dot(self: Vector2x8, other: Vector2x8) f32x8 { - return self.x * other.x + self.y * other.y; - } - - pub inline fn cross(self: Vector2x8, other: Vector2x8) f32x8 { - return self.x * other.y - self.y * other.x; - } - - pub inline fn lerp(self: Vector2x8, other: Vector2x8, t: f32x8) Vector2x8 { - const s: f32x8 = ps(1.0) - t; - return .{ - .x = self.x * s + other.x * t, - .y = self.y * s + other.y * t, - }; - } - - pub inline fn rotate(self: Vector2x8, angle_rad: f32) Vector2x8 { - const c = @cos(angle_rad); - const s = @sin(angle_rad); - return .{ - .x = self.x * ps(c) - self.y * ps(s), - .y = self.x * ps(s) + self.y * ps(c), - }; - } - - pub inline fn rotatev(self: Vector2x8, angle_rad: f32x8) Vector2x8 { - const c = @cos(angle_rad); - const s = @sin(angle_rad); - return .{ - .x = self.x * c - self.y * s, - .y = self.x * s + self.y * c, - }; - } -}; diff --git a/src/math/Vector3.zig b/src/math/Vector3.zig deleted file mode 100644 index 2716ff3..0000000 --- a/src/math/Vector3.zig +++ /dev/null @@ -1,188 +0,0 @@ -const std = @import("std"); - -const Quaternion = @import("Quaternion.zig").Quaternion; -const Vector2 = @import("Vector2.zig").Vector2; -const Vector3Int = @import("Vector3Int.zig").Vector3Int; -const Vector4 = @import("Vector4.zig").Vector4; - -pub const Vector3 = extern struct { - vector: Vector, - - pub const Vector = @Vector(3, f32); - pub const Array = [3]f32; - pub const Mask = enum(i32) { x = 0, y = 1, z = 2 }; - - pub const zero = Vector3.initScalar(0); - pub const one = Vector3.initScalar(1); - pub const unit_x = Vector3.init(1, 0, 0); - pub const unit_y = Vector3.init(0, 1, 0); - pub const unit_z = Vector3.init(0, 0, 1); - pub const unit_nx = Vector3.init(-1, 0, 0); - pub const unit_ny = Vector3.init(0, -1, 0); - pub const unit_nz = Vector3.init(0, 0, -1); - - // --- INIT --- - - pub inline fn initScalar(scalar: f32) Vector3 { - return .{ .vector = @splat(scalar) }; - } - - pub inline fn init(x: f32, y: f32, z: f32) Vector3 { - return .{ .vector = .{ x, y, z } }; - } - - pub inline fn initArray(array: Array) Vector3 { - return .{ .vector = array }; - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Vector3) Array { - return self.vector; - } - - pub inline fn asArrayNorm(self: Vector3, comptime T: type) [3]T { - const scale_vector: Vector = @splat(std.math.maxInt(T)); - return @as(@Vector(3, T), @intFromFloat(@round(self.vector * scale_vector))); - } - - pub inline fn asVector3Int(self: Vector3) Vector3Int { - return .{ .vector = @intFromFloat(@round(self.vector)) }; - } - - pub inline fn asVector2IntFrac(self: Vector3) Vector3Int { - const fraction: @Vector(3, f64) = @floatCast(self.vector); - const scale: @Vector(3, f64) = @splat(std.math.maxInt(i32)); - return .{ .vector = @intFromFloat(@round(fraction * scale)) }; - } - - pub inline fn asVector2(self: Vector3) Vector2 { - return .{ .vector = @shuffle(f32, self.vector, undefined, [_]i32{ 0, 1 }) }; - } - - pub inline fn asVector4(self: Vector3, w: f32) Vector4 { - const w_vector: @Vector(4, f32) = .{ undefined, undefined, undefined, w }; - return .{ .vector = @shuffle(f32, self.vector, w_vector, [_]i32{ 0, 1, 2, ~@as(i32, 3) }) }; - } - - // --- ACCESSORS --- - - pub inline fn getX(self: Vector3) f32 { - return self.vector[0]; - } - - pub inline fn getY(self: Vector3) f32 { - return self.vector[1]; - } - - pub inline fn getZ(self: Vector3) f32 { - return self.vector[2]; - } - - pub inline fn setX(self: Vector3, x: f32) Vector3 { - const x_vector: Vector = @splat(x); - return .{ .vector = @shuffle(f32, self.vector, x_vector, [_]i32{ ~@as(i32, 0), 1, 2 }) }; - } - - pub inline fn setY(self: Vector3, y: f32) Vector3 { - const y_vector: Vector = @splat(y); - return .{ .vector = @shuffle(f32, self.vector, y_vector, [_]i32{ 0, ~@as(i32, 1), 2 }) }; - } - - pub inline fn setZ(self: Vector3, z: f32) Vector3 { - const z_vector: Vector = @splat(z); - return .{ .vector = @shuffle(f32, self.vector, z_vector, [_]i32{ 0, 1, ~@as(i32, 2) }) }; - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Vector3, other: Vector3) Vector3 { - return .{ .vector = self.vector + other.vector }; - } - - pub inline fn sub(self: Vector3, other: Vector3) Vector3 { - return .{ .vector = self.vector - other.vector }; - } - - pub inline fn mul(self: Vector3, other: Vector3) Vector3 { - return .{ .vector = self.vector * other.vector }; - } - - pub inline fn div(self: Vector3, other: Vector3) Vector3 { - return .{ .vector = self.vector / other.vector }; - } - - pub inline fn negate(self: Vector3) Vector3 { - return .{ .vector = -self.vector }; - } - - pub inline fn mulScalar(self: Vector3, scalar: f32) Vector3 { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = self.vector * scalar_vector }; - } - - pub inline fn divScalar(self: Vector3, scalar: f32) Vector3 { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = self.vector / scalar_vector }; - } - - // --- SWIZZLE --- - - pub inline fn swizzle2(self: Vector3, comptime mask: [2]Mask) Vector2 { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([2]i32, @bitCast(mask))) }; - } - - pub inline fn swizzle3(self: Vector3, comptime mask: [3]Mask) Vector3 { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([3]i32, @bitCast(mask))) }; - } - - pub inline fn swizzle4(self: Vector3, comptime mask: [4]Mask) Vector4 { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([4]i32, @bitCast(mask))) }; - } - - // --- OTHER --- - - pub inline fn len(self: Vector3) f32 { - return @sqrt(@reduce(.Add, self.vector * self.vector)); - } - - pub inline fn lenSquared(self: Vector3) f32 { - return @reduce(.Add, self.vector * self.vector); - } - - pub inline fn normalize(self: Vector3) Vector3 { - const len_vector: Vector = @splat(@sqrt(@reduce(.Add, self.vector * self.vector))); - return .{ .vector = self.vector / len_vector }; - } - - pub inline fn dot(self: Vector3, other: Vector3) f32 { - return @reduce(.Add, self.vector * other.vector); - } - - pub inline fn cross(self: Vector3, other: Vector3) Vector3 { - return .{ - .vector = .{ - self.getY() * other.getZ() - self.getZ() * other.getY(), - self.getZ() * other.getX() - self.getX() * other.getZ(), - self.getX() * other.getY() - self.getY() * other.getX(), - }, - }; - } - - pub inline fn lerp(self: Vector3, other: Vector3, t: f32) Vector3 { - const s = 1.0 - t; - const t_vector: Vector = @splat(t); - const s_vector: Vector = @splat(s); - return .{ .vector = self * s_vector + other * t_vector }; - } - - pub inline fn rotate(self: Vector3, quaternion: Quaternion) Vector3 { - const quaternion_scalar = quaternion.getScalar(); - const quaternion_vector = quaternion.getVector(); - - return .add(self, .cross( - .add(quaternion_vector, quaternion_vector), - .add(.cross(quaternion_vector, self), .mulScalar(self, quaternion_scalar)), - )); - } -}; diff --git a/src/math/Vector3Int.zig b/src/math/Vector3Int.zig deleted file mode 100644 index af90f5e..0000000 --- a/src/math/Vector3Int.zig +++ /dev/null @@ -1,207 +0,0 @@ -const std = @import("std"); - -const Vector2Int = @import("Vector2Int.zig").Vector2Int; -const Vector3 = @import("Vector3.zig").Vector3; - -pub const Vector3Int = extern struct { - vector: Vector, - - pub const Vector = @Vector(3, i32); - pub const Array = [3]i32; - pub const Mask = enum(i32) { x = 0, y = 1, z = 2 }; - - pub const zero = Vector3Int.initScalar(0); - pub const one = Vector3Int.initScalar(1); - pub const one_frac = Vector3Int.initScalar(std.math.maxInt(i32)); - pub const unit_x = Vector3Int.init(1, 0, 0); - pub const unit_y = Vector3Int.init(0, 1, 0); - pub const unit_z = Vector3Int.init(0, 0, 1); - pub const unit_nx = Vector3Int.init(-1, 0, 0); - pub const unit_ny = Vector3Int.init(0, -1, 0); - pub const unit_nz = Vector3Int.init(0, 0, -1); - pub const unit_x_frac = Vector3Int.init(std.math.maxInt(i32), 0, 0); - pub const unit_y_frac = Vector3Int.init(0, std.math.maxInt(i32), 0); - pub const unit_z_frac = Vector3Int.init(0, 0, std.math.maxInt(i32)); - pub const unit_nx_frac = Vector3Int.init(-std.math.maxInt(i32), 0, 0); - pub const unit_ny_frac = Vector3Int.init(0, -std.math.maxInt(i32), 0); - pub const unit_nz_frac = Vector3Int.init(0, 0, -std.math.maxInt(i32)); - - // --- INIT --- - - pub inline fn initScalar(scalar: i32) Vector3Int { - return .{ .vector = @splat(scalar) }; - } - - pub inline fn init(x: i32, y: i32, z: i32) Vector3Int { - return .{ .vector = .{ x, y, z } }; - } - - pub inline fn initArray(array: Array) Vector3Int { - return .{ .vector = array }; - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Vector3Int) Array { - return self.vector; - } - - pub inline fn asVector3(self: Vector3Int) Vector3 { - return .{ .vector = @floatFromInt(self.vector) }; - } - - pub inline fn asVector3Frac(self: Vector3Int) Vector3 { - const numerator: @Vector(3, f64) = @floatFromInt(self.vector); - const denominator: @Vector(3, f64) = @splat(std.math.maxInt(i32)); - return .{ .vector = @floatCast(numerator / denominator) }; - } - - pub inline fn asVector2Int(self: Vector3Int) Vector2Int { - return .{ .vector = @shuffle(i32, self.vector, undefined, [_]i32{ 0, 1 }) }; - } - - // --- ACCESSORS --- - - pub inline fn getX(self: Vector3Int) i32 { - return self.vector[0]; - } - - pub inline fn getY(self: Vector3Int) i32 { - return self.vector[1]; - } - - pub inline fn getZ(self: Vector3Int) i32 { - return self.vector[2]; - } - - pub inline fn setX(self: Vector3Int, x: i32) Vector3Int { - const x_vector: Vector = @splat(x); - return .{ .vector = @shuffle(i32, self.vector, x_vector, [_]i32{ ~@as(i32, 0), 1, 2 }) }; - } - - pub inline fn setY(self: Vector3Int, y: i32) Vector3Int { - const y_vector: Vector = @splat(y); - return .{ .vector = @shuffle(i32, self.vector, y_vector, [_]i32{ 0, ~@as(i32, 1), 2 }) }; - } - - pub inline fn setZ(self: Vector3Int, z: i32) Vector3Int { - const z_vector: Vector = @splat(z); - return .{ .vector = @shuffle(i32, self.vector, z_vector, [_]i32{ 0, 1, ~@as(i32, 2) }) }; - } - - // --- COMPONENT-WISE --- - - pub inline fn add(self: Vector3Int, other: Vector3Int) Vector3Int { - return .{ .vector = self.vector + other.vector }; - } - - pub inline fn sub(self: Vector3Int, other: Vector3Int) Vector3Int { - return .{ .vector = self.vector - other.vector }; - } - - pub inline fn mul(self: Vector3Int, other: Vector3Int) Vector3Int { - return .{ .vector = self.vector * other.vector }; - } - - pub inline fn mulFrac(self: Vector3Int, other: Vector3Int) Vector3Int { - const denominator: @Vector(3, i64) = @splat(std.math.maxInt(i32)); - const rounding_bias: @Vector(3, i64) = denominator >> @as(@Vector(2, u6), @splat(1)); - const self_wide: @Vector(3, i64) = self.vector; - const other_wide: @Vector(3, i64) = other.vector; - return .{ .vector = @intCast(@divFloor(self_wide * other_wide + rounding_bias, denominator)) }; - } - - pub inline fn mulFracFrac(self: Vector3Int, other: Vector3Int) Vector3Int { - const denominator: @Vector(3, i64) = @splat(std.math.maxInt(i32) * std.math.maxInt(i32)); - const rounding_bias: @Vector(3, i64) = denominator >> @as(@Vector(2, u6), @splat(1)); - const self_wide: @Vector(3, i64) = self.vector; - const other_wide: @Vector(3, i64) = other.vector; - return .{ .vector = @intCast(@divFloor(self_wide * other_wide + rounding_bias, denominator)) }; - } - - pub inline fn div(self: Vector3Int, other: Vector3Int) Vector3Int { - return .{ .vector = @divFloor(self.vector, other.vector) }; - } - - pub inline fn mod(self: Vector3Int, other: Vector3Int) Vector3Int { - return .{ .vector = @mod(self.vector, other.vector) }; - } - - pub inline fn negate(self: Vector3Int) Vector3Int { - return .{ .vector = -self.vector }; - } - - pub inline fn mulScalar(self: Vector3Int, scalar: i32) Vector3Int { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = self.vector * scalar_vector }; - } - - pub inline fn mulScalarFloat(self: Vector3Int, scalar: f32) Vector3Int { - const self_float: @Vector(3, f64) = @floatFromInt(self.vector); - const scalar_vector_float: @Vector(3, f64) = @splat(scalar); - return .{ .vector = @intFromFloat(@round(self_float * scalar_vector_float)) }; - } - - pub inline fn mulScalarFrac(self: Vector3Int, scalar: i32) Vector3Int { - const denominator: @Vector(3, i64) = @splat(std.math.maxInt(i32)); - const rounding_bias: @Vector(3, i64) = denominator >> @as(@Vector(3, u6), @splat(1)); - const self_wide: @Vector(3, i64) = self; - const scalar_wide: @Vector(3, i64) = @splat(scalar); - return .{ .vector = @intCast(@divFloor(self_wide * scalar_wide + rounding_bias, denominator)) }; - } - - pub inline fn mulScalarFracFrac(self: Vector3Int, scalar: i32) Vector3Int { - const denominator: @Vector(3, i64) = @splat(std.math.maxInt(i32) * std.math.maxInt(i32)); - const rounding_bias: @Vector(3, i64) = denominator >> @as(@Vector(3, u6), @splat(1)); - const self_wide: @Vector(3, i64) = self; - const scalar_wide: @Vector(3, i64) = @splat(scalar); - return .{ .vector = @intCast(@divFloor(self_wide * scalar_wide + rounding_bias, denominator)) }; - } - - pub inline fn divScalar(self: Vector3Int, scalar: i32) Vector3Int { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = @divFloor(self.vector, scalar_vector) }; - } - - pub inline fn divScalarFloat(self: Vector3Int, scalar: f32) Vector3Int { - const self_float: @Vector(3, f64) = @floatFromInt(self.vector); - const scalar_vector_float: @Vector(3, f64) = @splat(scalar); - return .{ .vector = @intFromFloat(@round(self_float / scalar_vector_float)) }; - } - - pub inline fn modScalar(self: Vector3Int, scalar: i32) Vector3Int { - const scalar_vector: Vector = @splat(scalar); - return .{ .vector = @mod(self.vector, scalar_vector) }; - } - - pub inline fn abs(self: Vector3Int) Vector3Int { - return .{ .vector = @intCast(@abs(self.vector)) }; - } - - pub inline fn sign(self: Vector3Int) Vector3Int { - return .{ .vector = std.math.sign(self.vector) }; - } - - // --- SWIZZLE --- - - pub inline fn swizzle2(self: Vector3Int, comptime mask: [2]Mask) Vector2Int { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([2]i32, @bitCast(mask))) }; - } - - pub inline fn swizzle3(self: Vector3Int, comptime mask: [3]Mask) Vector3Int { - return .{ .vector = @shuffle(f32, self.vector, undefined, @as([3]i32, @bitCast(mask))) }; - } - - // --- OTHER --- - - pub inline fn lenSquared(self: Vector3Int) i64 { - const self_wide: @Vector(2, i64) = self.vector; - return @reduce(.Add, self_wide * self_wide); - } - - pub inline fn dot(self: Vector3Int, other: Vector3Int) i64 { - const self_wide: @Vector(3, i64) = self.vector; - const other_wide: @Vector(3, i64) = other.vector; - return @reduce(.Add, self_wide * other_wide); - } -}; diff --git a/src/math/Vector4.zig b/src/math/Vector4.zig deleted file mode 100644 index c122c66..0000000 --- a/src/math/Vector4.zig +++ /dev/null @@ -1,166 +0,0 @@ -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 Array = [4]f32; - pub const Mask = enum(i32) { x = 0, y = 1, z = 2, w = 3 }; - - pub const zero = Vector4.initScalar(0); - pub const one = Vector4.initScalar(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); - pub const unit_nx = Vector4.init(-1, 0, 0, 0); - pub const unit_ny = Vector4.init(0, -1, 0, 0); - pub const unit_nz = Vector4.init(0, 0, -1, 0); - pub const unit_nw = Vector4.init(0, 0, 0, -1); - - // --- INIT --- - - pub inline fn initScalar(scalar: f32) Vector4 { - return .{ .vector = @splat(scalar) }; - } - - pub inline fn init(x: f32, y: f32, z: f32, w: f32) Vector4 { - return .{ .vector = .{ x, y, z, w } }; - } - - pub inline fn initArray(array: Array) Vector4 { - return .{ .vector = array }; - } - - // --- CONVERSION --- - - pub inline fn asArray(self: Vector4) Array { - 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 * s_vector + other * t_vector }; - } -}; diff --git a/src/math/noise.zig b/src/math/noise.zig index 94699ce..12e3a3e 100644 --- a/src/math/noise.zig +++ b/src/math/noise.zig @@ -1,26 +1,13 @@ const std = @import("std"); -const math = @import("../math.zig"); - -const Vector2 = math.Vector2; -const Vector2x8 = math.Vector2x8; - -const f32x8 = math.f32x8; -const i32x8 = math.i32x8; -const u32x8 = math.u32x8; -const u64x8 = math.u64x8; - -const ps = math.ps; -const epi32 = math.epi32; -const epu32 = math.epu32; -const epu64x2 = math.epu64x2; +const vm = @import("vecmath"); const prime_x: u64 = 17061574742423305691; const prime_y: u64 = 10555943830568207707; const prime_perm: u64 = 15540206209889782181; -const prime_xv: u64x8 = epu64x2(prime_x); -const prime_yv: u64x8 = epu64x2(prime_y); -const prime_permv: u64x8 = epu64x2(prime_perm); +const prime_xv: @Vector(8, u64) = @splat(prime_x); +const prime_yv: @Vector(8, u64) = @splat(prime_y); +const prime_permv: @Vector(8, u64) = @splat(prime_perm); fn perm(seed: u64, x: i32, y: i32) i32 { var hash: u64 = seed; @@ -31,13 +18,13 @@ fn perm(seed: u64, x: i32, y: i32) i32 { return @bitCast(@as(u32, @truncate(hash))); } -fn permv(seed: u64, x: i32x8, y: i32x8) i32x8 { - var hash: u64x8 = epu64x2(seed); - hash ^= prime_xv *% @as(u32x8, @bitCast(x)); - hash ^= prime_yv *% @as(u32x8, @bitCast(y)); +fn permv(seed: u64, x: vm.i32x8, y: vm.i32x8) vm.i32x8 { + var hash: @Vector(8, u64) = @splat(seed); + hash ^= prime_xv *% @as(vm.u32x8, @bitCast(x)); + hash ^= prime_yv *% @as(vm.u32x8, @bitCast(y)); hash = hash *% hash *% hash *% prime_permv; hash = (hash >> @splat(26)) ^ hash; - return @bitCast(@as(u32x8, @truncate(hash))); + return @bitCast(@as(vm.u32x8, @truncate(hash))); } fn grad2(hash: i32, x: f32, y: f32) f32 { @@ -47,26 +34,26 @@ fn grad2(hash: i32, x: f32, y: f32) f32 { return (if (h & 0b001 != 0) -u else u) + (if (h & 0b010 != 0) -2 * v else 2 * v); } -fn grad2x8(hash: i32x8, x: f32x8, y: f32x8) f32x8 { - const h: i32x8 = hash & epi32(0b111); - const u: f32x8 = @select(f32, h < epi32(4), x, y); - const v: f32x8 = @select(f32, h < epi32(4), y, x); - const r1: f32x8 = @select(f32, h & epi32(0b001) != epi32(0), -u, u); - const r2: f32x8 = @select(f32, h & epi32(0b010) != epi32(0), ps(-2) * v, ps(2) * v); +fn grad2x8(hash: vm.i32x8, x: vm.f32x8, y: vm.f32x8) vm.f32x8 { + const h: vm.i32x8 = hash & vm.epi32(0b111); + const u: vm.f32x8 = @select(f32, h < vm.epi32(4), x, y); + const v: vm.f32x8 = @select(f32, h < vm.epi32(4), y, x); + const r1: vm.f32x8 = @select(f32, h & vm.epi32(0b001) != vm.epi32(0), -u, u); + const r2: vm.f32x8 = @select(f32, h & vm.epi32(0b010) != vm.epi32(0), vm.ps(-2) * v, vm.ps(2) * v); return r1 + r2; } const F2: f32 = (@sqrt(@as(f32, 3)) - 1) / 2; const G2: f32 = (3 - @sqrt(@as(f32, 3))) / 6; -const F2v: f32x8 = ps(F2); -const G2v: f32x8 = ps(G2); +const F2v: vm.f32x8 = vm.ps(F2); +const G2v: vm.f32x8 = vm.ps(G2); // NOTE No idea why this value, derived experimentally const noise2_scale: f32 = 34.11; -const noise2x8_scale: f32x8 = ps(noise2_scale); +const noise2x8_scale: vm.f32x8 = vm.ps(noise2_scale); -pub fn noise2(seed: u64, v: Vector2) f32 { +pub fn noise2(seed: u64, v: vm.Vector2) f32 { const x: f32, const y: f32 = v.asArray(); const s: f32 = (x + y) * F2; @@ -106,43 +93,43 @@ pub fn noise2(seed: u64, v: Vector2) f32 { return ret; } -pub fn noise2x8(seed: u64, v: Vector2x8) f32x8 { - const x: f32x8 = v.x; - const y: f32x8 = v.y; +pub fn noise2x8(seed: u64, v: vm.Vector2x8) vm.f32x8 { + const x: vm.f32x8 = v.x; + const y: vm.f32x8 = v.y; - const s: f32x8 = (x + y) * F2v; - const xs: f32x8 = x + s; - const ys: f32x8 = y + s; - const i: i32x8 = @intFromFloat(@floor(xs)); - const j: i32x8 = @intFromFloat(@floor(ys)); + const s: vm.f32x8 = (x + y) * F2v; + const xs: vm.f32x8 = x + s; + const ys: vm.f32x8 = y + s; + const i: vm.i32x8 = @intFromFloat(@floor(xs)); + const j: vm.i32x8 = @intFromFloat(@floor(ys)); - const t: f32x8 = @as(f32x8, @floatFromInt(i + j)) * G2v; - const X0: f32x8 = @as(f32x8, @floatFromInt(i)) - t; - const Y0: f32x8 = @as(f32x8, @floatFromInt(j)) - t; - const x0: f32x8 = x - X0; - const y0: f32x8 = y - Y0; + const t: vm.f32x8 = @as(vm.f32x8, @floatFromInt(i + j)) * G2v; + const X0: vm.f32x8 = @as(vm.f32x8, @floatFromInt(i)) - t; + const Y0: vm.f32x8 = @as(vm.f32x8, @floatFromInt(j)) - t; + const x0: vm.f32x8 = x - X0; + const y0: vm.f32x8 = y - Y0; - const _i1: i32x8 = @select(i32, x0 > y0, epi32(1), epi32(0)); - const _j1: i32x8 = @select(i32, x0 > y0, epi32(0), epi32(1)); + const _i1: vm.i32x8 = @select(i32, x0 > y0, vm.epi32(1), vm.epi32(0)); + const _j1: vm.i32x8 = @select(i32, x0 > y0, vm.epi32(0), vm.epi32(1)); - const x1: f32x8 = x0 - @as(f32x8, @floatFromInt(_i1)) + G2v; - const y1: f32x8 = y0 - @as(f32x8, @floatFromInt(_j1)) + G2v; - const x2: f32x8 = x0 - ps(1) + ps(2) * G2v; - const y2: f32x8 = y0 - ps(1) + ps(2) * G2v; + const x1: vm.f32x8 = x0 - @as(vm.f32x8, @floatFromInt(_i1)) + G2v; + const y1: vm.f32x8 = y0 - @as(vm.f32x8, @floatFromInt(_j1)) + G2v; + const x2: vm.f32x8 = x0 - vm.ps(1) + vm.ps(2) * G2v; + const y2: vm.f32x8 = y0 - vm.ps(1) + vm.ps(2) * G2v; - const t0: f32x8 = ps(0.5) - x0 * x0 - y0 * y0; - const t1: f32x8 = ps(0.5) - x1 * x1 - y1 * y1; - const t2: f32x8 = ps(0.5) - x2 * x2 - y2 * y2; + const t0: vm.f32x8 = vm.ps(0.5) - x0 * x0 - y0 * y0; + const t1: vm.f32x8 = vm.ps(0.5) - x1 * x1 - y1 * y1; + const t2: vm.f32x8 = vm.ps(0.5) - x2 * x2 - y2 * y2; - const gi0: i32x8 = permv(seed, i, j); - const gi1: i32x8 = permv(seed, i + _i1, j + _j1); - const gi2: i32x8 = permv(seed, i + epi32(1), j + epi32(1)); + const gi0: vm.i32x8 = permv(seed, i, j); + const gi1: vm.i32x8 = permv(seed, i + _i1, j + _j1); + const gi2: vm.i32x8 = permv(seed, i + vm.epi32(1), j + vm.epi32(1)); - const n0: f32x8 = @select(f32, t0 < ps(0), ps(0), (t0 * t0) * (t0 * t0) * grad2x8(gi0, x0, y0)); - const n1: f32x8 = @select(f32, t1 < ps(0), ps(0), (t1 * t1) * (t1 * t1) * grad2x8(gi1, x1, y1)); - const n2: f32x8 = @select(f32, t2 < ps(0), ps(0), (t2 * t2) * (t2 * t2) * grad2x8(gi2, x2, y2)); + const n0: vm.f32x8 = @select(f32, t0 < vm.ps(0), vm.ps(0), (t0 * t0) * (t0 * t0) * grad2x8(gi0, x0, y0)); + const n1: vm.f32x8 = @select(f32, t1 < vm.ps(0), vm.ps(0), (t1 * t1) * (t1 * t1) * grad2x8(gi1, x1, y1)); + const n2: vm.f32x8 = @select(f32, t2 < vm.ps(0), vm.ps(0), (t2 * t2) * (t2 * t2) * grad2x8(gi2, x2, y2)); - const ret: f32x8 = noise2x8_scale * (n0 + n1 + n2); - std.debug.assert(@reduce(.And, ret >= ps(-1)) and @reduce(.And, ret <= ps(1))); + const ret: vm.f32x8 = noise2x8_scale * (n0 + n1 + n2); + std.debug.assert(@reduce(.And, (ret >= vm.ps(-1)) & (ret <= vm.ps(1)))); return ret; } diff --git a/src/shaders.zig b/src/shaders.zig index c8c6af4..a55e3db 100644 --- a/src/shaders.zig +++ b/src/shaders.zig @@ -1,12 +1,9 @@ -const math = @import("math.zig"); +const std = @import("std"); +const vm = @import("vecmath"); const Materials = @import("assets/Materials.zig"); -const Matrix4x4 = math.Matrix4x4; const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer; const Textures = @import("assets/Textures.zig"); -const Vector2 = math.Vector2; -const Vector3 = math.Vector3; -const Vector4 = math.Vector4; pub const VertexBuffer = GenericBuffer(void, Vertex); pub const IndexBuffer = GenericBuffer(void, Index); @@ -17,17 +14,29 @@ pub const MaterialBuffer = GenericBuffer(void, Material); pub const ObjectUniformsBuffer = GenericBuffer(void, ObjectUniforms); pub const Vertex = extern struct { - positionOS: [3]f32, + positionOS: vm.Vector3, texCoord: [2]u16, normalOS: [3]i8, tangentOS: [4]i8, - pub fn init(position_os: Vector3, tex_coord: Vector2, normal_os: Vector3, tangent_os: Vector4) Vertex { + pub fn init(position_os: vm.Vector3, tex_coord: vm.Vector2, normal_os: vm.Vector3, tangent_os: vm.Vector4) Vertex { return .{ - .positionOS = position_os.asArray(), - .texCoord = tex_coord.asArrayNorm(u16), - .normalOS = normal_os.asArrayNorm(i8), - .tangentOS = tangent_os.asArrayNorm(i8), + .positionOS = position_os, + .texCoord = [_]u16{ + @intFromFloat(@round(tex_coord.x * std.math.maxInt(u16))), + @intFromFloat(@round(tex_coord.y * std.math.maxInt(u16))), + }, + .normalOS = [_]i8{ + @intFromFloat(@round(normal_os.x * std.math.maxInt(i8))), + @intFromFloat(@round(normal_os.y * std.math.maxInt(i8))), + @intFromFloat(@round(normal_os.z * std.math.maxInt(i8))), + }, + .tangentOS = [_]i8{ + @intFromFloat(@round(tangent_os.x * std.math.maxInt(i8))), + @intFromFloat(@round(tangent_os.y * std.math.maxInt(i8))), + @intFromFloat(@round(tangent_os.z * std.math.maxInt(i8))), + @intFromFloat(@round(tangent_os.w * std.math.maxInt(i8))), + }, }; } }; @@ -35,46 +44,38 @@ pub const Vertex = extern struct { pub const Index = u16; pub const GlobalUniforms = extern struct { - matrixWStoVS: [16]f32, - matrixVStoCS: [16]f32, - ambientLight: [3]f32, - - pub fn init(matrix_ws_to_vs: Matrix4x4, matrix_vs_to_cs: Matrix4x4, ambient_light: Vector3) GlobalUniforms { - return .{ - .matrixWStoVS = matrix_ws_to_vs.asArray(), - .matrixVStoCS = matrix_vs_to_cs.asArray(), - .ambientLight = ambient_light.asArray(), - }; - } + matrixWStoVS: vm.Matrix4x4, + matrixVStoCS: vm.Matrix4x4, + ambientLight: vm.Vector3, }; pub const PointLight = extern struct { - positionWS: [3]f32, - color: [3]f32, + positionWS: vm.Vector3, + color: vm.Vector3, - pub fn init(position_ws: Vector3, color: Vector3) PointLight { + pub fn init(position_ws: vm.Vector3, color: vm.Vector3) PointLight { return .{ - .positionWS = position_ws.asArray(), - .color = color.asArray(), + .positionWS = position_ws, + .color = color, }; } }; pub const DirectionalLight = extern struct { - directionWS: [3]f32, - color: [3]f32, + directionWS: vm.Vector3, + color: vm.Vector3, - pub fn init(direction_ws: Vector3, color: Vector3) DirectionalLight { + pub fn init(direction_ws: vm.Vector3, color: vm.Vector3) DirectionalLight { return .{ - .directionWS = direction_ws.asArray(), - .color = color.asArray(), + .directionWS = direction_ws, + .color = color, }; } }; pub const Material = extern struct { - base_color: [3]f32, - emissive: [3]f32, + base_color: vm.Vector3, + emissive: vm.Vector3, ior: f32, metallic: f32, normal_scale: f32, @@ -88,18 +89,10 @@ pub const Material = extern struct { }; pub const ObjectUniforms = extern struct { - matrixOStoWS: [16]f32, - matrixOStoWSNormal: [16]f32, + matrixOStoWS: vm.Matrix4x4, + matrixOStoWSNormal: vm.Matrix4x4, material: Materials.Id, - - pub fn init(matrix_os_to_ws: Matrix4x4, matrix_ow_to_ws_normal: Matrix4x4, material: Materials.Id) ObjectUniforms { - return .{ - .matrixOStoWS = matrix_os_to_ws.asArray(), - .matrixOStoWSNormal = matrix_ow_to_ws_normal.asArray(), - .material = material, - }; - } }; pub const equirect_to_cube_comp_spv align(4) = @embedFile("shaders/equirect_to_cube_comp.spv").*; diff --git a/src/worldgen.zig b/src/worldgen.zig index e4351a3..4aa288e 100644 --- a/src/worldgen.zig +++ b/src/worldgen.zig @@ -1,25 +1,19 @@ const std = @import("std"); + const math = @import("math.zig"); - -const Vector2 = math.Vector2; -const Vector2x8 = math.Vector2x8; - -const f32x8 = math.f32x8; -const i32x8 = math.i32x8; - -const ps = math.ps; +const vm = @import("vecmath"); const Noise = struct { horizontal_scale: f32, value_median: f32, value_amplitude: f32, - pub fn sample(self: Noise, seed: u64, pos: Vector2) f32 { + pub fn sample(self: Noise, seed: u64, pos: vm.Vector2) f32 { return math.noise2(seed, pos.divScalar(self.horizontal_scale)) * self.value_amplitude + self.value_median; } - pub fn samplev(self: Noise, seed: u64, pos: Vector2x8) f32x8 { - return math.noise2x8(seed, pos.divScalar(self.horizontal_scale)) * ps(self.value_amplitude) + ps(self.value_median); + pub fn samplev(self: Noise, seed: u64, pos: vm.Vector2x8) vm.f32x8 { + return math.noise2x8(seed, pos.divScalarSingle(self.horizontal_scale)) * vm.ps(self.value_amplitude) + vm.ps(self.value_median); } }; @@ -35,22 +29,22 @@ const noise_secondary: Noise = .{ .value_amplitude = 0.5, }; -pub fn heightF(seed: u64, pos: Vector2) f32 { +pub fn heightF(seed: u64, pos: vm.Vector2) f32 { const main = noise_main.sample(seed, pos); const secondary = noise_secondary.sample(seed, pos); return @round(main + secondary); } -pub fn heightFv(seed: u64, pos: Vector2x8) f32x8 { +pub fn heightFv(seed: u64, pos: vm.Vector2x8) vm.f32x8 { const main = noise_main.samplev(seed, pos); const secondary = noise_secondary.samplev(seed, pos); return @round(main + secondary); } -pub fn heightI(seed: u64, pos: Vector2) i32 { +pub fn heightI(seed: u64, pos: vm.Vector2) i32 { return @intFromFloat(heightF(seed, pos)); } -pub fn heightIv(seed: u64, pos: Vector2x8) i32x8 { +pub fn heightIv(seed: u64, pos: vm.Vector2x8) vm.i32x8 { return @intFromFloat(heightFv(seed, pos)); }