Block placing
This commit is contained in:
234
src/Chunks.zig
234
src/Chunks.zig
@@ -5,6 +5,7 @@ const c = @import("const.zig");
|
||||
const math = @import("math.zig");
|
||||
const vk = @import("vulkan");
|
||||
const vm = @import("vecmath");
|
||||
const voxels = @import("voxels.zig");
|
||||
|
||||
const Blocks = @import("assets/Blocks.zig");
|
||||
const Chunk = @import("assets/Chunk.zig");
|
||||
@@ -20,6 +21,7 @@ pub const SweepHit = struct {
|
||||
|
||||
pub const RaycastHit = struct {
|
||||
voxel: vm.Vector3Int,
|
||||
side: voxels.Orientation,
|
||||
};
|
||||
|
||||
pub fn deinit(self: *Chunks, engine: *Engine, descriptor_pool: vk.DescriptorPool, allocator: std.mem.Allocator) void {
|
||||
@@ -52,7 +54,16 @@ pub fn getVoxelAt(self: *const Chunks, vx: vm.Vector3Int) ?Blocks.Id {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroyVoxelAt(self: *const Chunks, vx: vm.Vector3Int, engine: *Engine, blocks: *const Blocks, allocator: std.mem.Allocator) !void {
|
||||
pub fn setVoxelAt(
|
||||
self: *Chunks,
|
||||
vx: vm.Vector3Int,
|
||||
id: Blocks.Id,
|
||||
engine: *Engine,
|
||||
blocks: *const Blocks,
|
||||
descriptor_pool: vk.DescriptorPool,
|
||||
per_batch_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||
allocator: std.mem.Allocator,
|
||||
) !void {
|
||||
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);
|
||||
@@ -65,91 +76,91 @@ pub fn destroyVoxelAt(self: *const Chunks, vx: vm.Vector3Int, engine: *Engine, b
|
||||
const y: i16 = @intCast(ck.y);
|
||||
const z: i16 = @intCast(ck.z);
|
||||
|
||||
if (self.chunks.getPtr(.{ x, y, z })) |chunk| {
|
||||
const ckvx = vx.modScalar(c.vx_per_ck);
|
||||
const block = &chunk.blocks[@intCast(ckvx.z)][@intCast(ckvx.y)][@intCast(ckvx.x)];
|
||||
if (block.* != .air) {
|
||||
block.* = .air;
|
||||
const chunk = try self.getOrCreateChunk(ck, engine, descriptor_pool, per_batch_descriptor_set_layout, allocator);
|
||||
|
||||
try chunk.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 1, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 1, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y, z - 1 }),
|
||||
}, allocator);
|
||||
const ckvx = vx.modScalar(c.vx_per_ck);
|
||||
const block = &chunk.blocks[@intCast(ckvx.z)][@intCast(ckvx.y)][@intCast(ckvx.x)];
|
||||
if (block.* != id) {
|
||||
block.* = id;
|
||||
|
||||
if (ckvx.x == 0) {
|
||||
if (self.chunks.getPtr(.{ x - 1, y, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x, y, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 2, y, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x - 1, y + 1, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x - 1, y - 1, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x - 1, y, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x - 1, y, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
} else if (ckvx.x == c.vx_per_ck - 1) {
|
||||
if (self.chunks.getPtr(.{ x + 1, y, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 2, y, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x, y, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x + 1, y + 1, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x + 1, y - 1, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x + 1, y, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x + 1, y, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
try chunk.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 1, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 1, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y, z - 1 }),
|
||||
}, allocator);
|
||||
|
||||
if (ckvx.x == 0) {
|
||||
if (self.chunks.getPtr(.{ x - 1, y, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x, y, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 2, y, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x - 1, y + 1, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x - 1, y - 1, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x - 1, y, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x - 1, y, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
|
||||
if (ckvx.y == 0) {
|
||||
if (self.chunks.getPtr(.{ x, y - 1, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y - 1, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y - 1, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 2, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y - 1, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y - 1, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
} else if (ckvx.y == c.vx_per_ck - 1) {
|
||||
if (self.chunks.getPtr(.{ x, y + 1, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y + 1, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y + 1, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 2, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y + 1, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y + 1, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
} else if (ckvx.x == c.vx_per_ck - 1) {
|
||||
if (self.chunks.getPtr(.{ x + 1, y, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 2, y, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x, y, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x + 1, y + 1, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x + 1, y - 1, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x + 1, y, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x + 1, y, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
if (ckvx.z == 0) {
|
||||
if (self.chunks.getPtr(.{ x, y, z - 1 })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z - 1 }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y, z - 1 }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 1, z - 1 }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 1, z - 1 }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y, z }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y, z - 2 }),
|
||||
}, allocator);
|
||||
}
|
||||
} else if (ckvx.z == c.vx_per_ck - 1) {
|
||||
if (self.chunks.getPtr(.{ x, y, z + 1 })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z + 1 }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y, z + 1 }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 1, z + 1 }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 1, z + 1 }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y, z + 2 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y, z }),
|
||||
}, allocator);
|
||||
}
|
||||
if (ckvx.y == 0) {
|
||||
if (self.chunks.getPtr(.{ x, y - 1, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y - 1, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y - 1, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 2, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y - 1, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y - 1, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
} else if (ckvx.y == c.vx_per_ck - 1) {
|
||||
if (self.chunks.getPtr(.{ x, y + 1, z })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y + 1, z }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y + 1, z }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 2, z }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y, z }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y + 1, z + 1 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y + 1, z - 1 }),
|
||||
}, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
if (ckvx.z == 0) {
|
||||
if (self.chunks.getPtr(.{ x, y, z - 1 })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z - 1 }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y, z - 1 }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 1, z - 1 }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 1, z - 1 }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y, z }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y, z - 2 }),
|
||||
}, allocator);
|
||||
}
|
||||
} else if (ckvx.z == c.vx_per_ck - 1) {
|
||||
if (self.chunks.getPtr(.{ x, y, z + 1 })) |neighbor| {
|
||||
try neighbor.refresh(engine, blocks, .{
|
||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z + 1 }),
|
||||
.negative_x = self.chunks.getPtr(.{ x - 1, y, z + 1 }),
|
||||
.positive_y = self.chunks.getPtr(.{ x, y + 1, z + 1 }),
|
||||
.negative_y = self.chunks.getPtr(.{ x, y - 1, z + 1 }),
|
||||
.positive_z = self.chunks.getPtr(.{ x, y, z + 2 }),
|
||||
.negative_z = self.chunks.getPtr(.{ x, y, z }),
|
||||
}, allocator);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,10 +536,14 @@ pub fn raycast(self: *const Chunks, origin_sv: vm.Vector3Int, ray_sv: vm.Vector3
|
||||
|
||||
var cross_indices = order3(i_index, j_index, k_index, cross_i, cross_j, cross_k, &ind_buf);
|
||||
for (cross_indices) |cross_index| {
|
||||
current_vx[cross_index] += ray_sign.asArray()[cross_index];
|
||||
const rs = ray_sign.asArray()[cross_index];
|
||||
current_vx[cross_index] += rs;
|
||||
const voxel = vm.Vector3Int.initArray(current_vx);
|
||||
if (self.isSolid(voxel)) {
|
||||
return .{ .voxel = voxel };
|
||||
return .{
|
||||
.voxel = voxel,
|
||||
.side = .initSignIndex(@intCast(-rs), @intCast(cross_index)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,10 +592,14 @@ pub fn raycast(self: *const Chunks, origin_sv: vm.Vector3Int, ray_sv: vm.Vector3
|
||||
|
||||
cross_indices = order3(i_index, j_index, k_index, cross_i, cross_j, cross_k, &ind_buf);
|
||||
for (cross_indices) |cross_index| {
|
||||
current_vx[cross_index] += ray_sign.asArray()[cross_index];
|
||||
const rs = ray_sign.asArray()[cross_index];
|
||||
current_vx[cross_index] += rs;
|
||||
const voxel = vm.Vector3Int.initArray(current_vx);
|
||||
if (self.isSolid(voxel)) {
|
||||
return .{ .voxel = voxel };
|
||||
return .{
|
||||
.voxel = voxel,
|
||||
.side = .initSignIndex(@intCast(-rs), @intCast(cross_index)),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -629,10 +648,14 @@ pub fn raycast(self: *const Chunks, origin_sv: vm.Vector3Int, ray_sv: vm.Vector3
|
||||
|
||||
cross_indices = order3(i_index, j_index, k_index, cross_i, cross_j, cross_k, &ind_buf);
|
||||
for (cross_indices) |cross_index| {
|
||||
current_vx[cross_index] += ray_sign.asArray()[cross_index];
|
||||
const rs = ray_sign.asArray()[cross_index];
|
||||
current_vx[cross_index] += rs;
|
||||
const voxel = vm.Vector3Int.initArray(current_vx);
|
||||
if (self.isSolid(voxel)) {
|
||||
return .{ .voxel = voxel };
|
||||
return .{
|
||||
.voxel = voxel,
|
||||
.side = .initSignIndex(@intCast(-rs), @intCast(cross_index)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,6 +664,43 @@ pub fn raycast(self: *const Chunks, origin_sv: vm.Vector3Int, ray_sv: vm.Vector3
|
||||
return null;
|
||||
}
|
||||
|
||||
fn getOrCreateChunk(
|
||||
self: *Chunks,
|
||||
ck: vm.Vector3Int,
|
||||
engine: *Engine,
|
||||
descriptor_pool: vk.DescriptorPool,
|
||||
per_batch_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||
allocator: std.mem.Allocator,
|
||||
) !*Chunk {
|
||||
const min_ck = vm.Vector3Int.initScalar(std.math.minInt(i16));
|
||||
const max_ck = vm.Vector3Int.initScalar(std.math.maxInt(i16));
|
||||
std.debug.assert((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));
|
||||
|
||||
const key = [_]i16{
|
||||
@intCast(ck.x),
|
||||
@intCast(ck.y),
|
||||
@intCast(ck.z),
|
||||
};
|
||||
|
||||
const entry = try self.chunks.getOrPut(allocator, key);
|
||||
|
||||
if (entry.found_existing) {
|
||||
return entry.value_ptr;
|
||||
} else {
|
||||
errdefer _ = self.chunks.remove(key);
|
||||
|
||||
const origin = ck.asFloat().mulScalar(c.vx_per_ck);
|
||||
const chunk = try Chunk.init(engine, .{
|
||||
.origin = origin,
|
||||
.descriptor_pool = descriptor_pool,
|
||||
.per_batch_descriptor_set_layout = per_batch_descriptor_set_layout,
|
||||
});
|
||||
|
||||
entry.value_ptr.* = chunk;
|
||||
return entry.value_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
fn order3(i: usize, j: usize, k: usize, cross_i: f32, cross_j: f32, cross_k: f32, buf: *[3]usize) []usize {
|
||||
if (cross_i >= 0 and cross_i < 1) {
|
||||
if (cross_j >= 0 and cross_j < 1) {
|
||||
|
||||
@@ -177,6 +177,19 @@ vertical_fov_deg: f32 = 80,
|
||||
|
||||
movement_state: MovementState,
|
||||
maybe_raycast_hit: ?Chunks.RaycastHit = null,
|
||||
block_index: usize = 0,
|
||||
|
||||
pub const blocks = [9][:0]const u8{
|
||||
"Bricks.json",
|
||||
"ChiseledStoneBricks.json",
|
||||
"Cobblestone.json",
|
||||
"DiamondBlock.json",
|
||||
"GoldBlock.json",
|
||||
"IronBlock.json",
|
||||
"OakPlanks.json",
|
||||
"SmoothStone.json",
|
||||
"StoneBricks.json",
|
||||
};
|
||||
|
||||
pub const camera_height_vx = 1.62;
|
||||
|
||||
@@ -214,6 +227,12 @@ pub fn onKeyDown(self: *Player, key: glfw.Key) void {
|
||||
self.x_input.onKeyDown(key);
|
||||
self.y_input.onKeyDown(key);
|
||||
self.z_input.onKeyDown(key);
|
||||
|
||||
const key_code = @intFromEnum(key);
|
||||
if (key_code >= @intFromEnum(glfw.Key.one) and key_code <= @intFromEnum(glfw.Key.nine)) {
|
||||
self.block_index = @intCast(key_code - @intFromEnum(glfw.Key.one));
|
||||
std.log.info("Picked block {s}", .{blocks[self.block_index]});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn onKeyUp(self: *Player, key: glfw.Key) void {
|
||||
@@ -231,15 +250,36 @@ pub fn onMouseDown(self: *Player, button: glfw.MouseButton, game: *Game) void {
|
||||
if (self.maybe_raycast_hit) |raycast_hit| {
|
||||
switch (button) {
|
||||
.left => {
|
||||
game.chunks.destroyVoxelAt(
|
||||
game.chunks.setVoxelAt(
|
||||
raycast_hit.voxel,
|
||||
.air,
|
||||
game.engine,
|
||||
&game.blocks,
|
||||
game.descriptor_pool,
|
||||
game.per_batch_descriptor_set_layout,
|
||||
game.allocator,
|
||||
) catch |err| {
|
||||
std.log.err("Error while destroying voxel {f}: {}", .{ raycast_hit.voxel, err });
|
||||
};
|
||||
},
|
||||
.right => blk: {
|
||||
const target_vx = raycast_hit.voxel.add(raycast_hit.side.getSignVector());
|
||||
const id = game.blocks.getOrLoad(game.engine, &game.materials, &game.textures, blocks[self.block_index], game.allocator) catch |err| {
|
||||
std.log.err("Error while placing voxel at {f}: {}", .{ target_vx, err });
|
||||
break :blk;
|
||||
};
|
||||
game.chunks.setVoxelAt(
|
||||
target_vx,
|
||||
id,
|
||||
game.engine,
|
||||
&game.blocks,
|
||||
game.descriptor_pool,
|
||||
game.per_batch_descriptor_set_layout,
|
||||
game.allocator,
|
||||
) catch |err| {
|
||||
std.log.err("Error while placing voxel at {f}: {}", .{ target_vx, err });
|
||||
};
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
const c = @import("const.zig");
|
||||
const vm = @import("vecmath");
|
||||
|
||||
const Materials = @import("assets/Materials.zig");
|
||||
|
||||
@@ -15,7 +16,7 @@ pub const Orientation = enum(u3) {
|
||||
pub fn initSignIndex(sign: i2, index: u2) Orientation {
|
||||
std.debug.assert(sign == -1 or sign == 1);
|
||||
std.debug.assert(index < 3);
|
||||
const value: u3 = (if (sign > 0) @as(u3, 0b100) else @as(u3, 0b000)) | index;
|
||||
const value: u3 = if (sign > 0) @as(u3, index) else ~@as(u3, index);
|
||||
return @enumFromInt(value);
|
||||
}
|
||||
|
||||
@@ -32,6 +33,14 @@ pub const Orientation = enum(u3) {
|
||||
return if (@intFromEnum(self) & 0b100 != 0) -1 else 1;
|
||||
}
|
||||
|
||||
/// +1 for positive
|
||||
/// -1 for negative
|
||||
pub fn getSignVector(self: Orientation) vm.Vector3Int {
|
||||
var array: [3]i32 = .{ 0, 0, 0 };
|
||||
array[self.getIndex()] = self.getSign();
|
||||
return .initArray(array);
|
||||
}
|
||||
|
||||
pub fn getOffsetVx(self: Orientation) i32 {
|
||||
return if (@intFromEnum(self) & 0b100 != 0) 1 else 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user