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

@@ -8,6 +8,45 @@ layout(set = 0, binding = 2, rgba16f) uniform writeonly restrict imageCube _Cube
const float INV_PI = 0.31830987;
const float HALF_INV_PI = 0.15915494;
const mat3x3 MATRIX_2D_TO_CUBE[6] = mat3x3[](
// Positive X
mat3x3(
0, 0, -1,
0, -1, 0,
1, 0, 0
),
// Negative X
mat3x3(
0, 0, 1,
0, -1, 0,
-1, 0, 0
),
// Positive Y
mat3x3(
1, 0, 0,
0, 0, 1,
0, 1, 0
),
// Negative Y
mat3x3(
1, 0, 0,
0, 0, -1,
0, -1, 0
),
// Positive Z
mat3x3(
1, 0, 0,
0, -1, 0,
0, 0, 1
),
// Negative Z
mat3x3(
-1, 0, 0,
0, -1, 0,
0, 0, -1
)
);
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main() {
vec2 size = vec2(imageSize(_CubemapImage).xy);
@@ -16,27 +55,7 @@ void main() {
texCoord = texCoord * vec2(2.0) - vec2(1.0); // Map to range [-1, 1]
vec3 cubeCoord;
if (layerIndex == 0) {
// Positive X
cubeCoord = vec3(1, -texCoord.y, -texCoord.x);
} else if (layerIndex == 1) {
// Negative X
cubeCoord = vec3(-1, -texCoord.y, texCoord.x);
} else if (layerIndex == 2) {
// Positive Y
cubeCoord = vec3(texCoord.x, 1, texCoord.y);
} else if (layerIndex == 3) {
// Negative Y
cubeCoord = vec3(texCoord.x, -1, -texCoord.y);
} else if (layerIndex == 4) {
// Positive Z
cubeCoord = vec3(texCoord.x, -texCoord.y, 1);
} else if (layerIndex == 5) {
// Negative Z
cubeCoord = vec3(-texCoord.x, -texCoord.y, -1);
}
vec3 cubeCoord = MATRIX_2D_TO_CUBE[layerIndex] * vec3(texCoord, 1.0);
vec3 cubeDir = normalize(cubeCoord);
float theta = atan(cubeDir.y, cubeDir.x);
@@ -45,5 +64,5 @@ void main() {
vec2 equirectCoord = vec2(theta * HALF_INV_PI, phi * INV_PI) + vec2(0.5);
vec4 irradiance = texture(sampler2D(_EquirectangularTexture, _EquirectangularSampler), equirectCoord);
imageStore(_CubemapImage, ivec3(ivec2(gl_GlobalInvocationID.xy), layerIndex), irradiance);
imageStore(_CubemapImage, ivec3(gl_GlobalInvocationID.xyz), irradiance);
}

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: {