Use castle for vecmath (doesn't work fully yet)

This commit is contained in:
2026-01-04 17:13:58 +01:00
parent 21c1d2e139
commit fed1e982d2
23 changed files with 424 additions and 1894 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "castle"]
path = castle
url = https://gitea.renati.me/renati/castle.git

View File

@@ -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);

View File

@@ -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",

1
castle Submodule

Submodule castle added at 7e8103565d

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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,
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,
origin.x + 1, origin.y + 1, origin.z, 1,
),
.negative_y => .init(
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,
-1, 0, 0, 0,
0, -1, 0, 0,
0, 0, -1, 0,
origin.getX() + 1, origin.getY() + 1, origin.getZ(), 1,
0, 0, 1, 0,
origin.x + 1, origin.y + 1, origin.z, 1,
),
// zig fmt: on
};

View File

@@ -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,

View File

@@ -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";

View File

@@ -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),
},
});

View File

@@ -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));
}

View File

@@ -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),
);
}
};

View File

@@ -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,
);
}
};

View File

@@ -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,
},
};
}
};

View File

@@ -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());
}
};

View File

@@ -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,
};
}
};

View File

@@ -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)),
));
}
};

View File

@@ -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);
}
};

View File

@@ -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 };
}
};

View File

@@ -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;
}

View File

@@ -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").*;

View File

@@ -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));
}