Block placing
This commit is contained in:
@@ -5,6 +5,7 @@ const c = @import("const.zig");
|
|||||||
const math = @import("math.zig");
|
const math = @import("math.zig");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const vm = @import("vecmath");
|
const vm = @import("vecmath");
|
||||||
|
const voxels = @import("voxels.zig");
|
||||||
|
|
||||||
const Blocks = @import("assets/Blocks.zig");
|
const Blocks = @import("assets/Blocks.zig");
|
||||||
const Chunk = @import("assets/Chunk.zig");
|
const Chunk = @import("assets/Chunk.zig");
|
||||||
@@ -20,6 +21,7 @@ pub const SweepHit = struct {
|
|||||||
|
|
||||||
pub const RaycastHit = struct {
|
pub const RaycastHit = struct {
|
||||||
voxel: vm.Vector3Int,
|
voxel: vm.Vector3Int,
|
||||||
|
side: voxels.Orientation,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn deinit(self: *Chunks, engine: *Engine, descriptor_pool: vk.DescriptorPool, allocator: std.mem.Allocator) void {
|
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 min_ck = vm.Vector3Int.initScalar(std.math.minInt(i16));
|
||||||
const max_ck = vm.Vector3Int.initScalar(std.math.maxInt(i16));
|
const max_ck = vm.Vector3Int.initScalar(std.math.maxInt(i16));
|
||||||
const ck = vx.divScalar(c.vx_per_ck);
|
const ck = vx.divScalar(c.vx_per_ck);
|
||||||
@@ -65,11 +76,12 @@ pub fn destroyVoxelAt(self: *const Chunks, vx: vm.Vector3Int, engine: *Engine, b
|
|||||||
const y: i16 = @intCast(ck.y);
|
const y: i16 = @intCast(ck.y);
|
||||||
const z: i16 = @intCast(ck.z);
|
const z: i16 = @intCast(ck.z);
|
||||||
|
|
||||||
if (self.chunks.getPtr(.{ x, y, z })) |chunk| {
|
const chunk = try self.getOrCreateChunk(ck, engine, descriptor_pool, per_batch_descriptor_set_layout, allocator);
|
||||||
|
|
||||||
const ckvx = vx.modScalar(c.vx_per_ck);
|
const ckvx = vx.modScalar(c.vx_per_ck);
|
||||||
const block = &chunk.blocks[@intCast(ckvx.z)][@intCast(ckvx.y)][@intCast(ckvx.x)];
|
const block = &chunk.blocks[@intCast(ckvx.z)][@intCast(ckvx.y)][@intCast(ckvx.x)];
|
||||||
if (block.* != .air) {
|
if (block.* != id) {
|
||||||
block.* = .air;
|
block.* = id;
|
||||||
|
|
||||||
try chunk.refresh(engine, blocks, .{
|
try chunk.refresh(engine, blocks, .{
|
||||||
.positive_x = self.chunks.getPtr(.{ x + 1, y, z }),
|
.positive_x = self.chunks.getPtr(.{ x + 1, y, z }),
|
||||||
@@ -153,7 +165,6 @@ pub fn destroyVoxelAt(self: *const Chunks, vx: vm.Vector3Int, engine: *Engine, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isSolid(self: *const Chunks, vx: vm.Vector3Int) bool {
|
pub fn isSolid(self: *const Chunks, vx: vm.Vector3Int) bool {
|
||||||
const maybe_id = getVoxelAt(self, vx);
|
const maybe_id = getVoxelAt(self, vx);
|
||||||
@@ -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);
|
var cross_indices = order3(i_index, j_index, k_index, cross_i, cross_j, cross_k, &ind_buf);
|
||||||
for (cross_indices) |cross_index| {
|
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);
|
const voxel = vm.Vector3Int.initArray(current_vx);
|
||||||
if (self.isSolid(voxel)) {
|
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);
|
cross_indices = order3(i_index, j_index, k_index, cross_i, cross_j, cross_k, &ind_buf);
|
||||||
for (cross_indices) |cross_index| {
|
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);
|
const voxel = vm.Vector3Int.initArray(current_vx);
|
||||||
if (self.isSolid(voxel)) {
|
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);
|
cross_indices = order3(i_index, j_index, k_index, cross_i, cross_j, cross_k, &ind_buf);
|
||||||
for (cross_indices) |cross_index| {
|
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);
|
const voxel = vm.Vector3Int.initArray(current_vx);
|
||||||
if (self.isSolid(voxel)) {
|
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;
|
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 {
|
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_i >= 0 and cross_i < 1) {
|
||||||
if (cross_j >= 0 and cross_j < 1) {
|
if (cross_j >= 0 and cross_j < 1) {
|
||||||
|
|||||||
@@ -177,6 +177,19 @@ vertical_fov_deg: f32 = 80,
|
|||||||
|
|
||||||
movement_state: MovementState,
|
movement_state: MovementState,
|
||||||
maybe_raycast_hit: ?Chunks.RaycastHit = null,
|
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;
|
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.x_input.onKeyDown(key);
|
||||||
self.y_input.onKeyDown(key);
|
self.y_input.onKeyDown(key);
|
||||||
self.z_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 {
|
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| {
|
if (self.maybe_raycast_hit) |raycast_hit| {
|
||||||
switch (button) {
|
switch (button) {
|
||||||
.left => {
|
.left => {
|
||||||
game.chunks.destroyVoxelAt(
|
game.chunks.setVoxelAt(
|
||||||
raycast_hit.voxel,
|
raycast_hit.voxel,
|
||||||
|
.air,
|
||||||
game.engine,
|
game.engine,
|
||||||
&game.blocks,
|
&game.blocks,
|
||||||
|
game.descriptor_pool,
|
||||||
|
game.per_batch_descriptor_set_layout,
|
||||||
game.allocator,
|
game.allocator,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
std.log.err("Error while destroying voxel {f}: {}", .{ raycast_hit.voxel, 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 => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const c = @import("const.zig");
|
const c = @import("const.zig");
|
||||||
|
const vm = @import("vecmath");
|
||||||
|
|
||||||
const Materials = @import("assets/Materials.zig");
|
const Materials = @import("assets/Materials.zig");
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ pub const Orientation = enum(u3) {
|
|||||||
pub fn initSignIndex(sign: i2, index: u2) Orientation {
|
pub fn initSignIndex(sign: i2, index: u2) Orientation {
|
||||||
std.debug.assert(sign == -1 or sign == 1);
|
std.debug.assert(sign == -1 or sign == 1);
|
||||||
std.debug.assert(index < 3);
|
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);
|
return @enumFromInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +33,14 @@ pub const Orientation = enum(u3) {
|
|||||||
return if (@intFromEnum(self) & 0b100 != 0) -1 else 1;
|
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 {
|
pub fn getOffsetVx(self: Orientation) i32 {
|
||||||
return if (@intFromEnum(self) & 0b100 != 0) 1 else 0;
|
return if (@intFromEnum(self) & 0b100 != 0) 1 else 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user