Attempts at raycast

This commit is contained in:
2026-01-04 15:44:29 +01:00
parent 8858e0c53e
commit 21c1d2e139
3 changed files with 245 additions and 27 deletions

View File

@@ -14,7 +14,7 @@ const Vector3Int = math.Vector3Int;
chunks: std.AutoHashMapUnmanaged([3]i16, Chunk),
const SweepHit = struct {
const RaycastHit = struct {
normal_frac: Vector3Int,
projected_distance_sv: i32,
};
@@ -54,7 +54,7 @@ pub fn isSolid(self: *const Chunks, vx: Vector3Int) bool {
return maybe_id != .air;
}
pub fn sweepCastDown(self: *const Chunks, min_sv: Vector3Int, max_sv: Vector3Int, distance_sv: i32) ?SweepHit {
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());
@@ -84,7 +84,7 @@ 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) ?SweepHit {
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());
@@ -114,11 +114,11 @@ 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) ?SweepHit {
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());
var hit: ?SweepHit = null;
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()));
@@ -284,3 +284,188 @@ 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 {
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()),
});
const zero = Vector3Int.zero.vector;
const one = Vector3Int.one.vector;
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 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(),
});
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()) {
// 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()) {
// 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) {
// 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);
return null;
}
const oi = origin_sv.vector[i_index];
const oj = origin_sv.vector[j_index];
const ok = origin_sv.vector[k_index];
const di = ray_sv.vector[i_index];
const dj = ray_sv.vector[j_index];
const dk = ray_sv.vector[k_index];
var i_vx = start_vx.vector[i_index];
var enter_i_sv = oi;
var enter_di_sv = enter_i_sv - oi;
var enter_jdi_sv = oj * di + enter_di_sv * dj;
var enter_kdi_sv = ok * di + enter_di_sv * dk;
var enter_i_vx = @divFloor(enter_i_sv - ray_positive.vector[i_index], c.sv_per_vx);
var enter_j_vx = @divFloor(enter_jdi_sv - ray_positive.vector[j_index], c.sv_per_vx * di);
var enter_k_vx = @divFloor(enter_kdi_sv - ray_positive.vector[k_index], c.sv_per_vx * di);
var exit_i_sv = c.voxelsToSubvoxels(i_vx + ray_negative.vector[i_index]);
var exit_di_sv = exit_i_sv - oi;
var exit_jdi_sv = oj * di + exit_di_sv * dj;
var exit_kdi_sv = ok * di + exit_di_sv * dk;
var exit_i_vx = @divFloor(exit_i_sv - ray_positive.vector[i_index], c.sv_per_vx);
var exit_j_vx = @divFloor(exit_jdi_sv - ray_positive.vector[j_index], c.sv_per_vx * di);
var exit_k_vx = @divFloor(exit_kdi_sv - ray_positive.vector[k_index], c.sv_per_vx * di);
std.debug.print("({d}:{X}, {d:.3}, {d:.3}) → ({d}:{X}, {d:.3}, {d:.3}) | ({d}, {d}, {d}) → ({d}, {d}, {d})\n", .{
c.subvoxelsToVoxels(.border_up, enter_i_sv),
c.subvoxelsToVoxelSubvoxels(enter_i_sv),
@as(f64, @floatFromInt(enter_jdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
@as(f64, @floatFromInt(enter_kdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
c.subvoxelsToVoxels(.border_up, exit_i_sv),
c.subvoxelsToVoxelSubvoxels(exit_i_sv),
@as(f64, @floatFromInt(exit_jdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
@as(f64, @floatFromInt(exit_kdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
enter_i_vx,
enter_j_vx,
enter_k_vx,
exit_i_vx,
exit_j_vx,
exit_k_vx,
});
while (i_vx != end_vx.vector[i_index]) : (i_vx += ray_sign.vector[i_index]) {
enter_i_sv = exit_i_sv;
enter_di_sv = exit_di_sv;
enter_jdi_sv = exit_jdi_sv;
enter_kdi_sv = exit_kdi_sv;
enter_i_vx = exit_i_vx;
enter_j_vx = exit_j_vx;
enter_k_vx = exit_k_vx;
exit_i_sv = c.voxelsToSubvoxels(i_vx + ray_positive.vector[i_index]);
exit_di_sv = exit_i_sv - oi;
exit_jdi_sv = oj * di + exit_di_sv * dj;
exit_kdi_sv = ok * di + exit_di_sv * dk;
exit_i_vx = @divFloor(exit_i_sv - ray_positive.vector[i_index], c.sv_per_vx);
exit_j_vx = @divFloor(exit_jdi_sv - ray_positive.vector[j_index], c.sv_per_vx * di);
exit_k_vx = @divFloor(exit_kdi_sv - ray_positive.vector[k_index], c.sv_per_vx * di);
std.debug.print("({d}:{X}, {d:.3}, {d:.3}) → ({d}:{X}, {d:.3}, {d:.3}) | ({d}, {d}, {d}) → ({d}, {d}, {d})\n", .{
c.subvoxelsToVoxels(.border_up, enter_i_sv),
c.subvoxelsToVoxelSubvoxels(enter_i_sv),
@as(f64, @floatFromInt(enter_jdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
@as(f64, @floatFromInt(enter_kdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
c.subvoxelsToVoxels(.border_up, exit_i_sv),
c.subvoxelsToVoxelSubvoxels(exit_i_sv),
@as(f64, @floatFromInt(exit_jdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
@as(f64, @floatFromInt(exit_kdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
enter_i_vx,
enter_j_vx,
enter_k_vx,
exit_i_vx,
exit_j_vx,
exit_k_vx,
});
}
enter_i_sv = exit_i_sv;
enter_di_sv = exit_di_sv;
enter_jdi_sv = exit_jdi_sv;
enter_kdi_sv = exit_kdi_sv;
enter_i_vx = exit_i_vx;
enter_j_vx = exit_j_vx;
enter_k_vx = exit_k_vx;
exit_i_sv = oi + di;
exit_di_sv = exit_i_sv - oi;
exit_jdi_sv = oj * di + exit_di_sv * dj;
exit_kdi_sv = ok * di + exit_di_sv * dk;
exit_i_vx = @divFloor(exit_i_sv - ray_positive.vector[i_index], c.sv_per_vx);
exit_j_vx = @divFloor(exit_jdi_sv - ray_positive.vector[j_index], c.sv_per_vx * di);
exit_k_vx = @divFloor(exit_kdi_sv - ray_positive.vector[k_index], c.sv_per_vx * di);
std.debug.print("({d}:{X}, {d:.3}, {d:.3}) → ({d}:{X}, {d:.3}, {d:.3}) | ({d}, {d}, {d}) → ({d}, {d}, {d})\n", .{
c.subvoxelsToVoxels(.border_up, enter_i_sv),
c.subvoxelsToVoxelSubvoxels(enter_i_sv),
@as(f64, @floatFromInt(enter_jdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
@as(f64, @floatFromInt(enter_kdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
c.subvoxelsToVoxels(.border_up, exit_i_sv),
c.subvoxelsToVoxelSubvoxels(exit_i_sv),
@as(f64, @floatFromInt(exit_jdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
@as(f64, @floatFromInt(exit_kdi_sv)) / @as(f64, @floatFromInt(di * c.sv_per_vx)),
enter_i_vx,
enter_j_vx,
enter_k_vx,
exit_i_vx,
exit_j_vx,
exit_k_vx,
});
// XXX
std.debug.print("\n", .{});
_ = self;
return null;
}

View File

@@ -8,6 +8,7 @@ const math = @import("math.zig");
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;
@@ -200,6 +201,8 @@ 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 const raycast_length_sv = sv(5.0);
pub fn init(position_sv: Vector3Int, pitch_rad: f32, yaw_rad: f32) Player {
return .{
.position_sv = position_sv,
@@ -229,6 +232,17 @@ pub fn onMouseMove(self: *Player, dx: f32, dy: f32) void {
pub fn update(self: *Player, dt: f32, chunks: *const Chunks) void {
defer self.resetAllButtons();
//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
// .init(0, raycast_length_sv, 0)
// .rotate(.mulQuaternion(
// .initRotationXY(self.yaw_rad),
// .initRotationYZ(self.pitch_rad),
// ))
// .asVector3Int();
//const raycast_hit = chunks.raycast(raycast_origin_sv, raycast_ray_sv);
// --- GATHER INPUTS -------------------------------------------------------
const horizontal_input_vector_frac = blk: {