Eliminate opposing walls
This commit is contained in:
@@ -10,6 +10,8 @@ const CommandBuffer = @import("../engine/CommandBuffer.zig").CommandBuffer;
|
||||
const Engine = @import("../engine/Engine.zig");
|
||||
const Game = @import("../Game.zig");
|
||||
const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer;
|
||||
const Materials = @import("Materials.zig");
|
||||
const Orientation = @import("../voxel.zig").Orientation;
|
||||
|
||||
const Matrix4x4 = math.Matrix4x4;
|
||||
const ObjectUniformsBuffer = GenericBuffer(void, Game.ObjectUniforms);
|
||||
@@ -20,11 +22,15 @@ pub const chunk_size = 16;
|
||||
const initial_capacity = 256;
|
||||
var next_chunk_id: std.atomic.Value(u64) = .init(0);
|
||||
|
||||
/// To get the block at coordinates (x, y, z) relative to the chunk, read the
|
||||
/// value at `blocks[z][y][x]`.
|
||||
blocks: [chunk_size][chunk_size][chunk_size]Blocks.Id,
|
||||
origin: Vector3,
|
||||
descriptor_set: vk.DescriptorSet,
|
||||
object_buffer: ObjectUniformsBuffer,
|
||||
object_count: u32,
|
||||
|
||||
/// For debug purposes, a unique "name" per chunk instance.
|
||||
chunk_id: u64,
|
||||
|
||||
pub const InitInfo = struct {
|
||||
@@ -33,6 +39,15 @@ pub const InitInfo = struct {
|
||||
per_batch_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||
};
|
||||
|
||||
pub const Neighbors = struct {
|
||||
positive_x: ?*const Chunk,
|
||||
negative_x: ?*const Chunk,
|
||||
positive_y: ?*const Chunk,
|
||||
negative_y: ?*const Chunk,
|
||||
positive_z: ?*const Chunk,
|
||||
negative_z: ?*const Chunk,
|
||||
};
|
||||
|
||||
pub fn init(engine: *Engine, init_info: InitInfo) !Chunk {
|
||||
const descriptor_set = try engine.allocateDescriptorSet(.{
|
||||
.descriptor_pool = init_info.descriptor_pool,
|
||||
@@ -89,23 +104,97 @@ pub fn deinit(self: *Chunk, engine: *Engine, descriptor_pool: vk.DescriptorPool)
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, temp_allocator: std.mem.Allocator) !void {
|
||||
var object_count: u32 = 0;
|
||||
pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, neighbors: Neighbors, temp_allocator: std.mem.Allocator) !void {
|
||||
var uniforms: std.ArrayList(Game.ObjectUniforms) = try .initCapacity(temp_allocator, initial_capacity);
|
||||
defer uniforms.deinit(temp_allocator);
|
||||
|
||||
for (self.blocks) |plane| {
|
||||
for (plane) |row| {
|
||||
for (row) |id| {
|
||||
for (self.blocks, 0..) |plane, iz| {
|
||||
const fz: f32 = @floatFromInt(iz);
|
||||
for (plane, 0..) |row, iy| {
|
||||
const fy: f32 = @floatFromInt(iy);
|
||||
for (row, 0..) |id, ix| {
|
||||
const fx: f32 = @floatFromInt(ix);
|
||||
const block = blocks.getBlock(id).?;
|
||||
object_count += @intFromBool(block.positive_x != .empty);
|
||||
object_count += @intFromBool(block.negative_x != .empty);
|
||||
object_count += @intFromBool(block.positive_y != .empty);
|
||||
object_count += @intFromBool(block.negative_y != .empty);
|
||||
object_count += @intFromBool(block.positive_z != .empty);
|
||||
object_count += @intFromBool(block.negative_z != .empty);
|
||||
|
||||
const center = Vector3.add(self.origin, .init(fx, fy, fz));
|
||||
const cx, const cy, const cz = center.asArray();
|
||||
|
||||
if (block.positive_x != .empty and self.getOpposite(.positive_x, ix, iy, iz, blocks, neighbors) == .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
1, 0, 0, 0,
|
||||
cx + 0.5, cy, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, block.positive_x));
|
||||
}
|
||||
|
||||
if (block.negative_x != .empty and self.getOpposite(.negative_x, ix, iy, iz, blocks, neighbors) == .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
0, -1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, 0, 0, 0,
|
||||
cx - 0.5, cy, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, block.negative_x));
|
||||
}
|
||||
|
||||
if (block.positive_y != .empty and self.getOpposite(.positive_y, ix, iy, iz, blocks, neighbors) == .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
-1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 1, 0, 0,
|
||||
cx, cy + 0.5, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, block.positive_y));
|
||||
}
|
||||
|
||||
if (block.negative_y != .empty and self.getOpposite(.negative_y, ix, iy, iz, blocks, neighbors) == .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
cx, cy - 0.5, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, block.negative_y));
|
||||
}
|
||||
|
||||
if (block.positive_z != .empty and self.getOpposite(.positive_z, ix, iy, iz, blocks, neighbors) == .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
cx, cy, cz + 0.5, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, block.positive_z));
|
||||
}
|
||||
|
||||
if (block.negative_z != .empty and self.getOpposite(.negative_z, ix, iy, iz, blocks, neighbors) == .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
cx, cy, cz - 0.5, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
try uniforms.append(temp_allocator, .init(matrix, matrix, block.negative_z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const object_count: u32 = @intCast(uniforms.items.len);
|
||||
if (self.object_buffer.array_capacity < object_count) {
|
||||
const desired_capacity = std.math.ceilPowerOfTwoAssert(u32, object_count);
|
||||
const new_object_buffer: ObjectUniformsBuffer = try .init(engine, .{
|
||||
@@ -140,105 +229,7 @@ pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, temp_alloca
|
||||
engine.setObjectName(new_object_buffer.device_memory, "DM Chunk[{d}]", .{self.chunk_id});
|
||||
}
|
||||
|
||||
const uniforms = try temp_allocator.alloc(Game.ObjectUniforms, object_count);
|
||||
var object_i: usize = 0;
|
||||
defer temp_allocator.free(uniforms);
|
||||
|
||||
for (self.blocks, 0..) |plane, iz| {
|
||||
const fz: f32 = @floatFromInt(iz);
|
||||
for (plane, 0..) |row, iy| {
|
||||
const fy: f32 = @floatFromInt(iy);
|
||||
for (row, 0..) |id, ix| {
|
||||
const fx: f32 = @floatFromInt(ix);
|
||||
const block = blocks.getBlock(id).?;
|
||||
|
||||
const center = Vector3.add(self.origin, .init(fx, fy, fz));
|
||||
const cx, const cy, const cz = center.asArray();
|
||||
|
||||
if (block.positive_x != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
1, 0, 0, 0,
|
||||
cx + 0.5, cy, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.positive_x);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.negative_x != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
0, -1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, 0, 0, 0,
|
||||
cx - 0.5, cy, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.negative_x);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.positive_y != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
-1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 1, 0, 0,
|
||||
cx, cy + 0.5, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.positive_y);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.negative_y != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
cx, cy - 0.5, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.negative_y);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.positive_z != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
cx, cy, cz + 0.5, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.positive_z);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.negative_z != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
cx, cy, cz - 0.5, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.negative_z);
|
||||
object_i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std.debug.assert(object_i == uniforms.len);
|
||||
|
||||
try self.object_buffer.write(engine, .{ .elements = uniforms });
|
||||
try self.object_buffer.write(engine, .{ .elements = uniforms.items });
|
||||
self.object_count = object_count;
|
||||
}
|
||||
|
||||
@@ -246,3 +237,44 @@ pub fn draw(self: *const Chunk, layout: vk.PipelineLayout, command_buffer: Comma
|
||||
command_buffer.bindDescriptorSets(.graphics, layout, 1, &.{self.descriptor_set}, &.{});
|
||||
command_buffer.drawIndexed(.{ .index_count = 6, .instance_count = self.object_count });
|
||||
}
|
||||
|
||||
fn getOpposite(self: *const Chunk, comptime side: Orientation, x: usize, y: usize, z: usize, blocks: *const Blocks, neighbors: Neighbors) Materials.Id {
|
||||
return switch (side) {
|
||||
.positive_x => if (x + 1 < chunk_size)
|
||||
blocks.getBlock(self.blocks[z][y][x + 1]).?.negative_x
|
||||
else if (neighbors.positive_x) |neighbor|
|
||||
blocks.getBlock(neighbor.blocks[z][y][0]).?.negative_x
|
||||
else
|
||||
.empty,
|
||||
.negative_x => if (x > 0)
|
||||
blocks.getBlock(self.blocks[z][y][x - 1]).?.positive_x
|
||||
else if (neighbors.negative_x) |neighbor|
|
||||
blocks.getBlock(neighbor.blocks[z][y][chunk_size - 1]).?.positive_x
|
||||
else
|
||||
.empty,
|
||||
.positive_y => if (y + 1 < chunk_size)
|
||||
blocks.getBlock(self.blocks[z][y + 1][x]).?.negative_y
|
||||
else if (neighbors.positive_y) |neighbor|
|
||||
blocks.getBlock(neighbor.blocks[z][0][x]).?.negative_y
|
||||
else
|
||||
.empty,
|
||||
.negative_y => if (y > 0)
|
||||
blocks.getBlock(self.blocks[z][y - 1][x]).?.positive_y
|
||||
else if (neighbors.negative_y) |neighbor|
|
||||
blocks.getBlock(neighbor.blocks[z][chunk_size - 1][x]).?.positive_y
|
||||
else
|
||||
.empty,
|
||||
.positive_z => if (z + 1 < chunk_size)
|
||||
blocks.getBlock(self.blocks[z + 1][y][x]).?.negative_z
|
||||
else if (neighbors.positive_z) |neighbor|
|
||||
blocks.getBlock(neighbor.blocks[0][y][x]).?.negative_z
|
||||
else
|
||||
.empty,
|
||||
.negative_z => if (z > 0)
|
||||
blocks.getBlock(self.blocks[z - 1][y][x]).?.positive_z
|
||||
else if (neighbors.negative_z) |neighbor|
|
||||
blocks.getBlock(neighbor.blocks[chunk_size - 1][y][x]).?.positive_z
|
||||
else
|
||||
.empty,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user