Bad collisions
This commit is contained in:
16
src/Game.zig
16
src/Game.zig
@@ -56,7 +56,7 @@ player: Player,
|
||||
const max_textures = 1024;
|
||||
const max_point_lights = 1024;
|
||||
const max_directional_lights = 4;
|
||||
const chunk_descriptor_pool = 512;
|
||||
const chunk_descriptor_pool = 1024;
|
||||
|
||||
const camera_near_plane = 0.1;
|
||||
|
||||
@@ -180,25 +180,25 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
try vertex_buffer.write(engine, .{
|
||||
.elements = &.{
|
||||
.init(
|
||||
.init(-0.5, -0.5, 0),
|
||||
.init(0, 0, 0),
|
||||
.init(0, 1),
|
||||
.init(0, 0, 1),
|
||||
.init(1, 0, 0, -1),
|
||||
),
|
||||
.init(
|
||||
.init(0.5, -0.5, 0),
|
||||
.init(1, 0, 0),
|
||||
.init(1, 1),
|
||||
.init(0, 0, 1),
|
||||
.init(1, 0, 0, -1),
|
||||
),
|
||||
.init(
|
||||
.init(-0.5, 0.5, 0),
|
||||
.init(0, 1, 0),
|
||||
.init(0, 0),
|
||||
.init(0, 0, 1),
|
||||
.init(1, 0, 0, -1),
|
||||
),
|
||||
.init(
|
||||
.init(0.5, 0.5, 0),
|
||||
.init(1, 1, 0),
|
||||
.init(1, 0),
|
||||
.init(0, 0, 1),
|
||||
.init(1, 0, 0, -1),
|
||||
@@ -534,8 +534,8 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
const world_seed = engine.random.int(u64);
|
||||
std.log.info("Using world seed 0x{x:0<16}", .{world_seed});
|
||||
var it = Iterator2(i16).init(.{
|
||||
.min = .{ -8, -8 },
|
||||
.max = .{ 7, 7 },
|
||||
.min = .{ -12, -12 },
|
||||
.max = .{ 12, 12 },
|
||||
});
|
||||
while (it.next()) |chunk_coords2| {
|
||||
const chunk_coords3 = chunk_coords2 ++ [_]i16{0};
|
||||
@@ -697,7 +697,7 @@ pub fn deinit(self: *Game) void {
|
||||
}
|
||||
|
||||
pub fn update(self: *Game, dt: f32) void {
|
||||
self.player.update(dt);
|
||||
self.player.update(dt, &self.chunks);
|
||||
|
||||
self.render() catch |err| {
|
||||
std.log.err("Failed to render: {s}", .{@errorName(err)});
|
||||
|
||||
463
src/Player.zig
463
src/Player.zig
@@ -4,6 +4,8 @@ const std = @import("std");
|
||||
const glfw = @import("zglfw");
|
||||
const math = @import("math.zig");
|
||||
|
||||
const Chunk = @import("assets/Chunk.zig");
|
||||
const Iterator2 = math.Iterator2;
|
||||
const Vector2 = math.Vector2;
|
||||
const Vector3 = math.Vector3;
|
||||
|
||||
@@ -23,6 +25,17 @@ const AxisState = enum {
|
||||
}
|
||||
};
|
||||
|
||||
const ButtonState = struct {
|
||||
current: bool = false,
|
||||
pressed_this_frame: bool = false,
|
||||
released_this_frame: bool = false,
|
||||
|
||||
pub fn reset(self: *ButtonState) void {
|
||||
self.pressed_this_frame = false;
|
||||
self.released_this_frame = false;
|
||||
}
|
||||
};
|
||||
|
||||
const Axis = struct {
|
||||
state: AxisState = .none,
|
||||
positive_key: glfw.Key,
|
||||
@@ -72,6 +85,58 @@ const Axis = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const Button = struct {
|
||||
state: ButtonState = .{},
|
||||
key: glfw.Key,
|
||||
|
||||
pub fn init(key: glfw.Key) Button {
|
||||
return .{
|
||||
.key = key,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn onKeyDown(self: *Button, key_code: glfw.Key) void {
|
||||
if (key_code == self.key) {
|
||||
self.state.current = true;
|
||||
self.state.pressed_this_frame = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn onKeyUp(self: *Button, key_code: glfw.Key) void {
|
||||
if (key_code == self.key) {
|
||||
self.state.current = false;
|
||||
self.state.released_this_frame = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(self: *Button) void {
|
||||
self.state.reset();
|
||||
}
|
||||
|
||||
pub inline fn isDown(self: Button) bool {
|
||||
return self.state.current;
|
||||
}
|
||||
|
||||
pub inline fn isPressed(self: Button) bool {
|
||||
return self.state.pressed_this_frame;
|
||||
}
|
||||
|
||||
pub inline fn isReleased(self: Button) bool {
|
||||
return self.state.released_this_frame;
|
||||
}
|
||||
};
|
||||
|
||||
const MovementState = union(enum) {
|
||||
ground: struct {
|
||||
horizontal_velocity: Vector2,
|
||||
},
|
||||
air: struct {
|
||||
horizontal_velocity: Vector2,
|
||||
vertical_velocity: f32,
|
||||
},
|
||||
flight: void,
|
||||
};
|
||||
|
||||
position: Vector3,
|
||||
pitch_rad: f32,
|
||||
yaw_rad: f32,
|
||||
@@ -79,10 +144,13 @@ yaw_rad: 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,
|
||||
vertical_fov_deg: f32 = 80,
|
||||
|
||||
movement_state: MovementState,
|
||||
|
||||
pub const camera_height = 1.62;
|
||||
|
||||
pub const horizontal_speed = 11.0;
|
||||
@@ -91,11 +159,26 @@ pub const vertical_speed = 7.49;
|
||||
pub const min_pitch_rad = -0.5 * std.math.pi;
|
||||
pub const max_pitch_rad = 0.5 * std.math.pi;
|
||||
|
||||
pub const half_width = 0.4;
|
||||
pub const height = 1.8;
|
||||
pub const speed = 5.612;
|
||||
pub const step_up = 0.53125;
|
||||
pub const step_down = 0.53125;
|
||||
pub const jump_velocity = 6.1237245;
|
||||
pub const gravity = 15;
|
||||
pub const vertical_velocity_cap = 30;
|
||||
pub const ground_acceleration = 56.12;
|
||||
pub const air_acceleration = 56.12;
|
||||
pub const air_speed_limit = 0.5612;
|
||||
|
||||
const distance_from_surface = 0.0009765625;
|
||||
|
||||
pub fn init(position: Vector3, pitch_rad: f32, yaw_rad: f32) Player {
|
||||
return .{
|
||||
.position = position,
|
||||
.pitch_rad = pitch_rad,
|
||||
.yaw_rad = yaw_rad,
|
||||
.movement_state = .flight,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -116,20 +199,376 @@ pub fn onMouseMove(self: *Player, dx: f32, dy: f32) void {
|
||||
self.yaw_rad = @mod(self.yaw_rad - dx * self.mouse_sensitivity, std.math.tau);
|
||||
}
|
||||
|
||||
pub fn update(self: *Player, dt: f32) void {
|
||||
var horizontal_input_vector = Vector2
|
||||
.init(self.x_input.getComponent(), self.y_input.getComponent())
|
||||
.rotate(self.yaw_rad);
|
||||
const horizontal_input_vector_len_squared = horizontal_input_vector.lenSquared();
|
||||
if (horizontal_input_vector_len_squared > 1) {
|
||||
horizontal_input_vector = horizontal_input_vector.divScalar(horizontal_input_vector_len_squared);
|
||||
}
|
||||
pub fn update(self: *Player, dt: f32, chunks: *const std.AutoHashMapUnmanaged([3]i16, Chunk)) void {
|
||||
defer self.resetAllButtons();
|
||||
|
||||
// --- GATHER INPUTS -------------------------------------------------------
|
||||
|
||||
const horizontal_input_vector = blk: {
|
||||
var ret = Vector2
|
||||
.init(self.x_input.getComponent(), self.y_input.getComponent())
|
||||
.rotate(self.yaw_rad);
|
||||
const len_squared = ret.lenSquared();
|
||||
if (len_squared > 1) {
|
||||
ret = ret.divScalar(@sqrt(len_squared));
|
||||
}
|
||||
break :blk ret;
|
||||
};
|
||||
const vertical_input_vector = self.z_input.getComponent();
|
||||
|
||||
const horizontal_velocity = horizontal_input_vector.mulScalar(horizontal_speed);
|
||||
const vertical_velocity = vertical_input_vector * vertical_speed;
|
||||
// --- STATE TRANSITIONS ---------------------------------------------------
|
||||
|
||||
const displacement = horizontal_velocity.asVector3(vertical_velocity).mulScalar(dt);
|
||||
switch (self.movement_state) {
|
||||
.ground => |ground| {
|
||||
if (self.jump_input.isPressed()) {
|
||||
self.movement_state = .{
|
||||
.air = .{
|
||||
.horizontal_velocity = ground.horizontal_velocity,
|
||||
.vertical_velocity = jump_velocity,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
self.position = .add(self.position, displacement);
|
||||
// --- STATE HANDLING ------------------------------------------------------
|
||||
|
||||
switch (self.movement_state) {
|
||||
.ground => {},
|
||||
.air => {},
|
||||
.flight => {
|
||||
const horizontal_velocity = horizontal_input_vector.mulScalar(horizontal_speed);
|
||||
const vertical_velocity = vertical_input_vector * vertical_speed;
|
||||
|
||||
var horizontal_displacement = horizontal_velocity.mulScalar(dt);
|
||||
var vertical_displacement = vertical_velocity * dt;
|
||||
|
||||
if (vertical_displacement > 0.0) {
|
||||
if (sweepCastUp(self.position, vertical_displacement, chunks)) |hit| {
|
||||
vertical_displacement = hit.projected_distance - distance_from_surface;
|
||||
}
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < 2) : (i += 1) {
|
||||
if (sweepCastHorizontal(self.position, horizontal_displacement, chunks)) |hit| {
|
||||
horizontal_displacement = .add(
|
||||
horizontal_displacement,
|
||||
hit.normal
|
||||
.asVector2()
|
||||
.mulScalar(hit.projected_distance + distance_from_surface),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (vertical_displacement < 0.0) {
|
||||
if (sweepCastDown(self.position, -vertical_displacement, chunks)) |hit| {
|
||||
vertical_displacement = -(hit.projected_distance - distance_from_surface);
|
||||
}
|
||||
}
|
||||
|
||||
const displacement = horizontal_displacement.asVector3(vertical_displacement);
|
||||
self.position = .add(self.position, displacement);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const SweepHit = struct {
|
||||
normal: Vector3,
|
||||
projected_distance: f32,
|
||||
};
|
||||
|
||||
fn sweepCastDown(origin: Vector3, distance: f32, chunks: *const std.AutoHashMapUnmanaged([3]i16, Chunk)) ?SweepHit {
|
||||
const min_origin = origin.add(.init(-half_width, -half_width, 0.0));
|
||||
const max_origin = origin.add(.init(half_width, half_width, height));
|
||||
|
||||
const min_x = blockCoord(.border_up, min_origin.getX());
|
||||
const min_y = blockCoord(.border_up, min_origin.getY());
|
||||
const max_x = blockCoord(.border_down, max_origin.getX());
|
||||
const max_y = blockCoord(.border_down, max_origin.getY());
|
||||
|
||||
const start_z = blockCoord(.next_down_with_border, min_origin.getZ());
|
||||
const end_z = blockCoord(.border_down, min_origin.getZ() - distance);
|
||||
|
||||
var z: i32 = start_z;
|
||||
while (z >= end_z) : (z -= 1) {
|
||||
const fz = @as(f32, @floatFromInt(z)) + 1.0;
|
||||
var it = Iterator2(i32).init(.{
|
||||
.min = .{ min_x, min_y },
|
||||
.max = .{ max_x, max_y },
|
||||
});
|
||||
while (it.next()) |xy| {
|
||||
const x, const y = xy;
|
||||
if (!isSolid(chunks, x, y, z)) continue;
|
||||
|
||||
return .{
|
||||
.projected_distance = distance - (min_origin.getZ() - fz),
|
||||
.normal = .unit_z,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
fn sweepCastUp(origin: Vector3, distance: f32, chunks: *const std.AutoHashMapUnmanaged([3]i16, Chunk)) ?SweepHit {
|
||||
const min_origin = origin.add(.init(-half_width, -half_width, 0.0));
|
||||
const max_origin = origin.add(.init(half_width, half_width, height));
|
||||
|
||||
const min_x = blockCoord(.border_up, min_origin.getX());
|
||||
const min_y = blockCoord(.border_up, min_origin.getY());
|
||||
const max_x = blockCoord(.border_down, max_origin.getX());
|
||||
const max_y = blockCoord(.border_down, max_origin.getY());
|
||||
|
||||
const start_z = blockCoord(.next_up_with_border, max_origin.getZ());
|
||||
const end_z = blockCoord(.border_up, max_origin.getZ() + distance);
|
||||
|
||||
var z: i32 = start_z;
|
||||
while (z <= end_z) : (z += 1) {
|
||||
const fz = @as(f32, @floatFromInt(z));
|
||||
var it = Iterator2(i32).init(.{
|
||||
.min = .{ min_x, min_y },
|
||||
.max = .{ max_x, max_y },
|
||||
});
|
||||
while (it.next()) |xy| {
|
||||
const x, const y = xy;
|
||||
if (!isSolid(chunks, x, y, z)) continue;
|
||||
|
||||
return .{
|
||||
.projected_distance = distance - (fz - max_origin.getZ()),
|
||||
.normal = .negate(.unit_z),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
fn sweepCastHorizontal(origin: Vector3, ray: Vector2, chunks: *const std.AutoHashMapUnmanaged([3]i16, Chunk)) ?SweepHit {
|
||||
const min_origin = origin.add(.init(-half_width, -half_width, 0));
|
||||
const max_origin = origin.add(.init(half_width, half_width, height));
|
||||
|
||||
const min_z = blockCoord(.border_up, min_origin.getZ());
|
||||
const max_z = blockCoord(.border_down, max_origin.getZ());
|
||||
|
||||
var closest_hit: ?SweepHit = null;
|
||||
var closest_hit_distance = std.math.inf(f32);
|
||||
|
||||
const dydx = ray.getY() / ray.getX();
|
||||
const dxdy = ray.getX() / ray.getY();
|
||||
|
||||
// Positive X
|
||||
if (ray.getX() > 0.0) {
|
||||
const x0 = max_origin.getX();
|
||||
const y0 = min_origin.getY();
|
||||
const y1 = max_origin.getY();
|
||||
|
||||
const start_x = blockCoord(.next_up_with_border, x0);
|
||||
const end_x = blockCoord(.border_up, x0 + ray.getX());
|
||||
|
||||
var x: i32 = start_x;
|
||||
px: while (x <= end_x) : (x += 1) {
|
||||
const fx = @as(f32, @floatFromInt(x));
|
||||
const min_y = blockCoord(.border_up, (fx - x0) * dydx + y0);
|
||||
const max_y = blockCoord(.border_down, (fx - x0) * dydx + y1);
|
||||
var it = Iterator2(i32).init(.{
|
||||
.min = .{ min_y, min_z },
|
||||
.max = .{ max_y, max_z },
|
||||
});
|
||||
while (it.next()) |yz| {
|
||||
const y, const z = yz;
|
||||
if (!isSolid(chunks, x, y, z)) continue;
|
||||
|
||||
const dx = fx - x0;
|
||||
const dy = dydx * dx;
|
||||
const distance = Vector2.init(dx, dy).len();
|
||||
|
||||
if (distance >= closest_hit_distance) {
|
||||
break :px;
|
||||
}
|
||||
|
||||
closest_hit = .{
|
||||
.projected_distance = ray.getX() - dx,
|
||||
.normal = .negate(.unit_x),
|
||||
};
|
||||
closest_hit_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Negative X
|
||||
if (ray.getX() < 0.0) {
|
||||
const x0 = min_origin.getX();
|
||||
const y0 = min_origin.getY();
|
||||
const y1 = max_origin.getY();
|
||||
|
||||
const start_x = blockCoord(.next_down_with_border, x0);
|
||||
const end_x = blockCoord(.border_down, x0 + ray.getX());
|
||||
|
||||
var x: i32 = start_x;
|
||||
nx: while (x >= end_x) : (x -= 1) {
|
||||
const fx = @as(f32, @floatFromInt(x)) + 1.0;
|
||||
const min_y = blockCoord(.border_up, (fx - x0) * dydx + y0);
|
||||
const max_y = blockCoord(.border_down, (fx - x0) * dydx + y1);
|
||||
var it = Iterator2(i32).init(.{
|
||||
.min = .{ min_y, min_z },
|
||||
.max = .{ max_y, max_z },
|
||||
});
|
||||
while (it.next()) |yz| {
|
||||
const y, const z = yz;
|
||||
if (!isSolid(chunks, x, y, z)) continue;
|
||||
|
||||
const dx = fx - x0;
|
||||
const dy = dydx * dx;
|
||||
const distance = Vector2.init(dx, dy).len();
|
||||
|
||||
if (distance >= closest_hit_distance) {
|
||||
break :nx;
|
||||
}
|
||||
|
||||
closest_hit = .{
|
||||
.projected_distance = -(ray.getX() - dx),
|
||||
.normal = .unit_x,
|
||||
};
|
||||
closest_hit_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Positive Y
|
||||
if (ray.getY() > 0.0) {
|
||||
const y0 = max_origin.getY();
|
||||
const x0 = min_origin.getX();
|
||||
const x1 = max_origin.getX();
|
||||
|
||||
const start_y: i32 = @intFromFloat(@ceil(y0));
|
||||
const end_y: i32 = @intFromFloat(@floor(y0 + ray.getY()));
|
||||
|
||||
var y: i32 = start_y;
|
||||
py: while (y <= end_y) : (y += 1) {
|
||||
const fy = @as(f32, @floatFromInt(y));
|
||||
const min_x: i32 = @intFromFloat(@floor(fy - y0) * dxdy + x0);
|
||||
const max_x: i32 = @intFromFloat(@ceil((fy - y0) * dxdy + x1 - 1.0));
|
||||
var it = Iterator2(i32).init(.{
|
||||
.min = .{ min_x, min_z },
|
||||
.max = .{ max_x, max_z },
|
||||
});
|
||||
while (it.next()) |xz| {
|
||||
const x, const z = xz;
|
||||
if (!isSolid(chunks, x, y, z)) continue;
|
||||
|
||||
const dy = fy - y0;
|
||||
const dx = dxdy * dy;
|
||||
const distance = Vector2.init(dx, dy).len();
|
||||
|
||||
if (distance >= closest_hit_distance) {
|
||||
break :py;
|
||||
}
|
||||
|
||||
closest_hit = .{
|
||||
.projected_distance = ray.getY() - dy,
|
||||
.normal = .negate(.unit_y),
|
||||
};
|
||||
closest_hit_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Negative Y
|
||||
if (ray.getY() < 0.0) {
|
||||
const y0 = min_origin.getY();
|
||||
const x0 = min_origin.getX();
|
||||
const x1 = max_origin.getX();
|
||||
|
||||
const start_y = blockCoord(.next_down_with_border, y0);
|
||||
const end_y = blockCoord(.border_down, y0 + ray.getY());
|
||||
|
||||
var y: i32 = start_y;
|
||||
py: while (y >= end_y) : (y -= 1) {
|
||||
const fy = @as(f32, @floatFromInt(y)) + 1.0;
|
||||
const min_x: i32 = @intFromFloat(@floor(fy - y0) * dxdy + x0);
|
||||
const max_x: i32 = @intFromFloat(@ceil((fy - y0) * dxdy + x1 - 1.0));
|
||||
var it = Iterator2(i32).init(.{
|
||||
.min = .{ min_x, min_z },
|
||||
.max = .{ max_x, max_z },
|
||||
});
|
||||
while (it.next()) |xz| {
|
||||
const x, const z = xz;
|
||||
if (!isSolid(chunks, x, y, z)) continue;
|
||||
|
||||
const dy = fy - y0;
|
||||
const dx = dxdy * dy;
|
||||
const distance = Vector2.init(dx, dy).len();
|
||||
|
||||
if (distance >= closest_hit_distance) {
|
||||
break :py;
|
||||
}
|
||||
|
||||
closest_hit = .{
|
||||
.projected_distance = -(ray.getY() - dy),
|
||||
.normal = .unit_y,
|
||||
};
|
||||
closest_hit_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closest_hit;
|
||||
}
|
||||
|
||||
fn resetAllButtons(self: *Player) void {
|
||||
inline for (@typeInfo(Player).@"struct".fields) |field| {
|
||||
if (field.type == Button) {
|
||||
@field(self, field.name).reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn isSolid(chunks: *const std.AutoHashMapUnmanaged([3]i16, Chunk), x: i32, y: i32, z: i32) bool {
|
||||
const chunk_x = std.math.cast(i16, @divFloor(x, Chunk.chunk_size)) orelse return true;
|
||||
const chunk_y = std.math.cast(i16, @divFloor(y, Chunk.chunk_size)) orelse return true;
|
||||
const chunk_z = std.math.cast(i16, @divFloor(z, Chunk.chunk_size)) orelse return true;
|
||||
if (chunks.get(.{ chunk_x, chunk_y, chunk_z })) |chunk| {
|
||||
const local_x: u4 = @intCast(@mod(x, Chunk.chunk_size));
|
||||
const local_y: u4 = @intCast(@mod(y, Chunk.chunk_size));
|
||||
const local_z: u4 = @intCast(@mod(z, Chunk.chunk_size));
|
||||
return chunk.blocks[local_z][local_y][local_x] != .air;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const RoundingMode = enum {
|
||||
border_down,
|
||||
border_up,
|
||||
next_down_with_border,
|
||||
next_down_without_border,
|
||||
next_up_with_border,
|
||||
next_up_without_border,
|
||||
};
|
||||
|
||||
inline fn blockCoord(comptime rounding_mode: RoundingMode, coord: f32) i32 {
|
||||
return switch (rounding_mode) {
|
||||
.border_down => @intFromFloat(@ceil(coord - 1.0)),
|
||||
.border_up => @intFromFloat(@floor(coord)),
|
||||
.next_down_with_border => @intFromFloat(@floor(coord - 1.0)),
|
||||
.next_down_without_border => @intFromFloat(@ceil(coord - 2.0)),
|
||||
.next_up_with_border => @intFromFloat(@ceil(coord)),
|
||||
.next_up_without_border => @intFromFloat(@floor(coord + 1.0)),
|
||||
};
|
||||
}
|
||||
|
||||
inline fn blockCoord2(comptime rounding_mode: RoundingMode, coord: Vector2) [2]i32 {
|
||||
return switch (rounding_mode) {
|
||||
.border_down => @as(Vector2.Vector, @intFromFloat(@ceil(coord.sub(.one).vector))),
|
||||
.border_up => @as(Vector2.Vector, @intFromFloat(@floor(coord.vector))),
|
||||
};
|
||||
}
|
||||
|
||||
inline fn blockCoord3(comptime rounding_mode: RoundingMode, coord: Vector3) [3]i32 {
|
||||
return switch (rounding_mode) {
|
||||
.border_down => @as(Vector3.Vector, @intFromFloat(@ceil(coord.sub(.one).vector))),
|
||||
.border_up => @as(Vector3.Vector, @intFromFloat(@floor(coord.vector))),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -110,13 +110,13 @@ 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 center = Vector3.add(self.origin, .init(fx, fy, fz));
|
||||
const origin = 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, center);
|
||||
const matrix = getMatrix(side, origin);
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, material));
|
||||
}
|
||||
}
|
||||
@@ -209,44 +209,44 @@ fn getOpposite(self: *const Chunk, comptime side: voxels.Orientation, x: usize,
|
||||
};
|
||||
}
|
||||
|
||||
fn getMatrix(comptime side: voxels.Orientation, center: Vector3) Matrix4x4 {
|
||||
fn getMatrix(comptime side: voxels.Orientation, origin: Vector3) Matrix4x4 {
|
||||
return switch (side) {
|
||||
// zig fmt: off
|
||||
.positive_x => .init(
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
1, 0, 0, 0,
|
||||
center.getX() + 0.5, center.getY(), center.getZ(), 1,
|
||||
origin.getX() + 1, origin.getY(), origin.getZ(), 1,
|
||||
),
|
||||
.negative_x => .init(
|
||||
0, -1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, 0, 0, 0,
|
||||
center.getX() - 0.5, center.getY(), center.getZ(), 1,
|
||||
origin.getX(), origin.getY() + 1, origin.getZ(), 1,
|
||||
),
|
||||
.positive_y => .init(
|
||||
-1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 1, 0, 0,
|
||||
center.getX(), center.getY() + 0.5, center.getZ(), 1,
|
||||
origin.getX() + 1, origin.getY() + 1, origin.getZ(), 1,
|
||||
),
|
||||
.negative_y => .init(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
center.getX(), center.getY() - 0.5, center.getZ(), 1,
|
||||
origin.getX(), origin.getY(), origin.getZ(), 1,
|
||||
),
|
||||
.positive_z => .init(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
center.getX(), center.getY(), center.getZ() + 0.5, 1,
|
||||
origin.getX(), origin.getY(), origin.getZ() + 1, 1,
|
||||
),
|
||||
.negative_z => .init(
|
||||
1, 0, 0, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
center.getX(), center.getY(), center.getZ() - 0.5, 1,
|
||||
origin.getX() + 1, origin.getY() + 1, origin.getZ(), 1,
|
||||
),
|
||||
// zig fmt: on
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user