diff --git a/src/Player.zig b/src/Player.zig index 5496fa0..2f728e2 100644 --- a/src/Player.zig +++ b/src/Player.zig @@ -181,24 +181,24 @@ movement_state: MovementState, pub const camera_height_vx = 1.62; -pub const horizontal_speed_sv = c.sv(11.0); -pub const vertical_speed_sv = c.sv(7.49); +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 collision_half_width_sv = c.sv(0.4); -pub const collision_height_sv = c.sv(1.8); +pub const collision_half_width_sv = sv(0.4); +pub const collision_height_sv = sv(1.8); -pub const speed_sv = c.sv(5.612); -pub const step_up_sv = c.sv(0.53125); -pub const step_down_sv = c.sv(0.53125); -pub const jump_velocity_sv = c.sv(6.1237245); -pub const gravity_sv = c.sv(15); -pub const vertical_velocity_cap_sv = c.sv(30); -pub const ground_acceleration_sv = c.sv(56.12); -pub const air_acceleration_sv = c.sv(56.12); -pub const air_speed_limit_sv = c.sv(0.5612); +pub const speed_sv = sv(5.612); +pub const step_up_sv = sv(0.53125); +pub const step_down_sv = sv(0.53125); +pub const jump_velocity_sv = sv(6.1237245); +pub const gravity_sv = sv(15); +pub const vertical_velocity_cap_sv = sv(30); +pub const ground_acceleration_sv = sv(56.12); +pub const air_acceleration_sv = sv(56.12); +pub const air_speed_limit_sv = sv(0.5612); pub fn init(position_sv: Vector3Int, pitch_rad: f32, yaw_rad: f32) Player { return .{ @@ -286,9 +286,10 @@ pub fn update(self: *Player, dt: f32, chunks: *const std.AutoHashMapUnmanaged([3 const adjustment = hit.normal_frac .asVector2Int() .mulScalarFrac(hit.projected_distance_sv); - std.debug.print("i={} | n={} | d={} | adj={} | disp={}->", .{ + std.debug.print("i={} | pos={X} | n={} | d={X} | adj={X} | disp={X}->", .{ i, - hit.normal_frac.vector, + position_sv.vector, + hit.normal_frac.asVector3Frac().vector, hit.projected_distance_sv, adjustment.vector, horizontal_displacement_sv.vector, @@ -297,7 +298,7 @@ pub fn update(self: *Player, dt: f32, chunks: *const std.AutoHashMapUnmanaged([3 horizontal_displacement_sv, adjustment, ); - std.debug.print("{}\n", .{horizontal_displacement_sv.vector}); + std.debug.print("{X}\n", .{horizontal_displacement_sv.vector}); } else { break; } @@ -325,17 +326,17 @@ fn sweepCastDown(origin_sv: Vector3Int, distance_sv: i32, chunks: *const std.Aut const min_origin_sv = origin_sv.add(.init(-collision_half_width_sv, -collision_half_width_sv, 0)); const max_origin_sv = origin_sv.add(.init(collision_half_width_sv, collision_half_width_sv, collision_height_sv)); - const min_x_vx = voxelFromSubvoxel(.border_up, min_origin_sv.getX()); - const min_y_vx = voxelFromSubvoxel(.border_up, min_origin_sv.getY()); - const max_x_vx = voxelFromSubvoxel(.border_down, max_origin_sv.getX()); - const max_y_vx = voxelFromSubvoxel(.border_down, max_origin_sv.getY()); + const min_x_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getX()); + const min_y_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getY()); + const max_x_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getX()); + const max_y_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getY()); - const start_z_vx = voxelFromSubvoxel(.next_down, min_origin_sv.getZ()); - const end_z_vx = voxelFromSubvoxel(.border_up, min_origin_sv.getZ() - distance_sv); + const start_z_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getZ()) - 1; + const end_z_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getZ() - distance_sv); var z_vx: i32 = start_z_vx; while (z_vx >= end_z_vx) : (z_vx -= 1) { - const z_sv = (z_vx + 1) * c.sv_per_vx; + const z_sv = c.voxelsToSubvoxels(z_vx + 1); var it = Iterator2(i32).init(.{ .min = .{ min_x_vx, min_y_vx }, .max = .{ max_x_vx, max_y_vx }, @@ -358,17 +359,17 @@ fn sweepCastUp(origin_sv: Vector3Int, distance_sv: i32, chunks: *const std.AutoH const min_origin_sv = origin_sv.add(.init(-collision_half_width_sv, -collision_half_width_sv, 0)); const max_origin_sv = origin_sv.add(.init(collision_half_width_sv, collision_half_width_sv, collision_height_sv)); - const min_x_vx = voxelFromSubvoxel(.border_up, min_origin_sv.getX()); - const min_y_vx = voxelFromSubvoxel(.border_up, min_origin_sv.getY()); - const max_x_vx = voxelFromSubvoxel(.border_down, max_origin_sv.getX()); - const max_y_vx = voxelFromSubvoxel(.border_down, max_origin_sv.getY()); + const min_x_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getX()); + const min_y_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getY()); + const max_x_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getX()); + const max_y_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getY()); - const start_z_vx = voxelFromSubvoxel(.next_up, max_origin_sv.getZ()); - const end_z_vx = voxelFromSubvoxel(.border_up, max_origin_sv.getZ() + distance_sv); + const start_z_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getZ()) + 1; + const end_z_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getZ() + distance_sv); var z_vx: i32 = start_z_vx; while (z_vx <= end_z_vx) : (z_vx += 1) { - const z_sv = z_vx * c.sv_per_vx; + const z_sv = c.voxelsToSubvoxels(z_vx); var it = Iterator2(i32).init(.{ .min = .{ min_x_vx, min_y_vx }, .max = .{ max_x_vx, max_y_vx }, @@ -391,8 +392,8 @@ fn sweepCastHorizontal(origin_sv: Vector3Int, ray_sv: Vector2Int, chunks: *const const min_origin_sv = origin_sv.add(.init(-collision_half_width_sv, -collision_half_width_sv, 0)); const max_origin_sv = origin_sv.add(.init(collision_half_width_sv, collision_half_width_sv, collision_height_sv)); - const min_z_vx = voxelFromSubvoxel(.border_up, min_origin_sv.getZ()); - const max_z_vx = voxelFromSubvoxel(.border_down, max_origin_sv.getZ()); + const min_z_vx = c.subvoxelsToVoxels(.border_up, min_origin_sv.getZ()); + const max_z_vx = c.subvoxelsToVoxels(.border_down, max_origin_sv.getZ()); var hit: ?SweepHit = null; var hit_distance_squared = std.math.inf(f32); @@ -406,14 +407,14 @@ fn sweepCastHorizontal(origin_sv: Vector3Int, ray_sv: Vector2Int, chunks: *const const y0_sv = min_origin_sv.getY(); const y1_sv = max_origin_sv.getY(); - const start_x_vx = voxelFromSubvoxel(.next_up, x0_sv); - const end_x_vx = voxelFromSubvoxel(.border_down, x0_sv + ray_sv.getX()); + const start_x_vx = c.subvoxelsToVoxels(.border_down, x0_sv) + 1; + const end_x_vx = c.subvoxelsToVoxels(.border_down, x0_sv + ray_sv.getX()); var x_vx: i32 = start_x_vx; px: while (x_vx <= end_x_vx) : (x_vx += 1) { - const x_sv = x_vx * c.sv_per_vx; - const min_y_vx = voxelFromSubvoxel(.border_up, wideMulDivFloor(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y0_sv); - const max_y_vx = voxelFromSubvoxel(.border_down, wideMulDivCeil(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y1_sv); + const x_sv = c.voxelsToSubvoxels(x_vx); + const min_y_vx = c.subvoxelsToVoxels(.border_up, wideMulDivFloor(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y0_sv); + const max_y_vx = c.subvoxelsToVoxels(.border_down, wideMulDivCeil(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_y_vx, min_z_vx }, .max = .{ max_y_vx, max_z_vx }, @@ -444,14 +445,14 @@ fn sweepCastHorizontal(origin_sv: Vector3Int, ray_sv: Vector2Int, chunks: *const const y0_sv = min_origin_sv.getY(); const y1_sv = max_origin_sv.getY(); - const start_x_vx = voxelFromSubvoxel(.next_down, x0_sv); - const end_x_vx = voxelFromSubvoxel(.border_up, x0_sv + ray_sv.getX()); + const start_x_vx = c.subvoxelsToVoxels(.border_up, x0_sv) - 1; + const end_x_vx = c.subvoxelsToVoxels(.border_up, x0_sv + ray_sv.getX()); var x_vx: i32 = start_x_vx; nx: while (x_vx >= end_x_vx) : (x_vx -= 1) { - const x_sv = (x_vx + 1) * c.sv_per_vx; - const min_y_vx = voxelFromSubvoxel(.border_up, wideMulDivFloor(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y0_sv); - const max_y_vx = voxelFromSubvoxel(.border_down, wideMulDivCeil(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y1_sv); + const x_sv = c.voxelsToSubvoxels(x_vx + 1); + const min_y_vx = c.subvoxelsToVoxels(.border_up, wideMulDivFloor(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y0_sv); + const max_y_vx = c.subvoxelsToVoxels(.border_down, wideMulDivCeil(x_sv - x0_sv, ray_sv.getY(), ray_sv.getX()) + y1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_y_vx, min_z_vx }, .max = .{ max_y_vx, max_z_vx }, @@ -482,14 +483,14 @@ fn sweepCastHorizontal(origin_sv: Vector3Int, ray_sv: Vector2Int, chunks: *const const x0_sv = min_origin_sv.getX(); const x1_sv = max_origin_sv.getX(); - const start_y_vx = voxelFromSubvoxel(.next_up, y0_sv); - const end_y_vx = voxelFromSubvoxel(.border_down, y0_sv + ray_sv.getY()); + const start_y_vx = c.subvoxelsToVoxels(.border_down, y0_sv) + 1; + const end_y_vx = c.subvoxelsToVoxels(.border_down, y0_sv + ray_sv.getY()); var y_vx = start_y_vx; py: while (y_vx <= end_y_vx) : (y_vx += 1) { - const y_sv = y_vx * c.sv_per_vx; - const min_x_vx = voxelFromSubvoxel(.border_up, wideMulDivFloor(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x0_sv); - const max_x_vx = voxelFromSubvoxel(.border_down, wideMulDivCeil(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x1_sv); + const y_sv = c.voxelsToSubvoxels(y_vx); + const min_x_vx = c.subvoxelsToVoxels(.border_up, wideMulDivFloor(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x0_sv); + const max_x_vx = c.subvoxelsToVoxels(.border_down, wideMulDivCeil(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_x_vx, min_z_vx }, .max = .{ max_x_vx, max_z_vx }, @@ -523,14 +524,14 @@ fn sweepCastHorizontal(origin_sv: Vector3Int, ray_sv: Vector2Int, chunks: *const const x0_sv = min_origin_sv.getX(); const x1_sv = max_origin_sv.getX(); - const start_y_vx = voxelFromSubvoxel(.next_down, y0_sv); - const end_y_vx = voxelFromSubvoxel(.border_up, y0_sv + ray_sv.getY()); + const start_y_vx = c.subvoxelsToVoxels(.border_up, y0_sv) - 1; + const end_y_vx = c.subvoxelsToVoxels(.border_up, y0_sv + ray_sv.getY()); var y_vx = start_y_vx; ny: while (y_vx >= end_y_vx) : (y_vx -= 1) { - const y_sv = (y_vx + 1) * c.sv_per_vx; - const min_x_vx = voxelFromSubvoxel(.border_up, wideMulDivFloor(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x0_sv); - const max_x_vx = voxelFromSubvoxel(.border_down, wideMulDivCeil(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x1_sv); + const y_sv = c.voxelsToSubvoxels(y_vx + 1); + const min_x_vx = c.subvoxelsToVoxels(.border_up, wideMulDivFloor(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x0_sv); + const max_x_vx = c.subvoxelsToVoxels(.border_down, wideMulDivCeil(y_sv - y0_sv, ray_sv.getX(), ray_sv.getY()) + x1_sv); var it = Iterator2(i32).init(.{ .min = .{ min_x_vx, min_z_vx }, .max = .{ max_x_vx, max_z_vx }, @@ -595,13 +596,6 @@ fn isSolid(chunks: *const std.AutoHashMapUnmanaged([3]i16, Chunk), vx: Vector3In return maybe_id != .air; } -const RoundingMode = enum { - border_down, - border_up, - next_down, - next_up, -}; - inline fn wideMulDivFloor(a: i32, mul: i32, div: i32) i32 { return @intCast(@divFloor(@as(i64, a) * @as(i64, mul), div)); } @@ -610,11 +604,6 @@ inline fn wideMulDivCeil(a: i32, mul: i32, div: i32) i32 { return @intCast(@divFloor(@as(i64, a) * @as(i64, mul) + @as(i64, div) - 1, div)); } -inline fn voxelFromSubvoxel(comptime rounding_mode: RoundingMode, subvoxel: i32) i32 { - return switch (rounding_mode) { - .border_down => @divFloor(subvoxel - 1, c.sv_per_vx), - .border_up => @divFloor(subvoxel, c.sv_per_vx), - .next_down => @divFloor(subvoxel - c.sv_per_vx, c.sv_per_vx), - .next_up => @divFloor(subvoxel + (c.sv_per_vx - 1), c.sv_per_vx), - }; +inline fn sv(comptime vx: comptime_float) comptime_int { + return @intFromFloat(@round(vx * c.sv_per_vx)); } diff --git a/src/const.zig b/src/const.zig index d32dd53..83cf2f6 100644 --- a/src/const.zig +++ b/src/const.zig @@ -38,6 +38,61 @@ pub const sv_per_vx = 4096; pub const vx_per_ck = 16; pub const sv_per_ck = sv_per_vx * vx_per_ck; -pub inline fn sv(comptime vx: comptime_float) comptime_int { - return @intFromFloat(@round(vx * sv_per_vx)); +pub const RoundingMode = enum { + border_down, + border_up, +}; + +/// SV to VX +pub inline fn subvoxelsToVoxels(comptime rounding_mode: RoundingMode, sv: i32) i32 { + return switch (rounding_mode) { + .border_down => @divFloor(sv, sv_per_vx - 1), + .border_up => @divFloor(sv, sv_per_vx), + }; +} + +/// SV to CK +pub inline fn subvoxelsToChunks(comptime rounding_mode: RoundingMode, sv: i32) i32 { + return switch (rounding_mode) { + .border_down => @divFloor(sv, sv_per_ck - 1), + .border_up => @divFloor(sv, sv_per_ck), + }; +} + +/// SV to CKSV +pub inline fn subvoxelsToChunkSubvoxels(sv: i32) std.math.IntFittingRange(0, sv_per_ck - 1) { + return @intCast(@mod(sv, sv_per_ck)); +} + +/// SV to VXSV +pub inline fn subvoxelsToVoxelSubvoxels(sv: i32) std.math.IntFittingRange(0, sv_per_vx - 1) { + return @intCast(@mod(sv, sv_per_vx)); +} + +/// VX to SV +pub inline fn voxelsToSubvoxels(vx: i32) i32 { + return vx * sv_per_vx; +} + +/// VX to CK +pub inline fn voxelsToChunks(comptime rounding_mode: RoundingMode, vx: i32) i32 { + return switch (rounding_mode) { + .border_down => @divFloor(vx, vx_per_ck - 1), + .border_up => @divFloor(vx, vx_per_ck), + }; +} + +/// VX to CKVX +pub inline fn voxelsToChunkVoxels(vx: i32) std.math.IntFittingRange(0, vx_per_ck) { + return @intCast(@mod(vx, vx_per_ck)); +} + +/// CK to SV +pub inline fn chunksToSubvoxels(ck: i32) i32 { + return ck * sv_per_ck; +} + +/// CK to VX +pub inline fn chunksToVoxels(ck: i32) i32 { + return ck * vx_per_ck; }