implement greedy meshing
This commit is contained in:
parent
5cf2933210
commit
5c7f996eb6
4 changed files with 103 additions and 148 deletions
|
|
@ -37,6 +37,8 @@ pub fn build(b: *std.Build) void {
|
|||
.optimize = optimize,
|
||||
});
|
||||
|
||||
exe_unit_tests.linkLibrary(rl.artifact("raylib"));
|
||||
|
||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||
|
||||
const test_step = b.step("test", "Run unit tests");
|
||||
|
|
|
|||
26
src/main.zig
26
src/main.zig
|
|
@ -4,6 +4,9 @@ const raylib = rh.raylib;
|
|||
const v3 = rh.v3;
|
||||
const chunks = @import("world/chunk.zig");
|
||||
|
||||
const benchmark_chunk_meshing = false;
|
||||
const debug = false;
|
||||
|
||||
pub fn drawCameraPosition(camera: raylib.Camera3D, x: i32, y: i32) !void {
|
||||
var buf: [256:0]u8 = undefined;
|
||||
|
||||
|
|
@ -22,6 +25,8 @@ pub fn moveCamera(camera: *raylib.Camera3D, vec: raylib.Vector3) void {
|
|||
}
|
||||
|
||||
pub fn main() !void {
|
||||
if (!debug) raylib.SetTraceLogLevel(raylib.LOG_ERROR);
|
||||
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const a7r = gpa.allocator();
|
||||
defer {
|
||||
|
|
@ -53,6 +58,7 @@ pub fn main() !void {
|
|||
|
||||
var chunk = try chunks.Chunk.init(a7r);
|
||||
defer chunk.deinit();
|
||||
|
||||
for (0..32) |raw_x| for (0..32) |raw_z| {
|
||||
const x: u5 = @intCast(raw_x);
|
||||
const z: u5 = @intCast(raw_z);
|
||||
|
|
@ -66,6 +72,19 @@ pub fn main() !void {
|
|||
chunk.setTile(31 - a, a, a, 1);
|
||||
chunk.setTile(31 - a, 31 - a, a, 1);
|
||||
}
|
||||
if (benchmark_chunk_meshing) {
|
||||
var tmp: u64 = 0;
|
||||
for (0..500) |_| {
|
||||
const start = try std.time.Instant.now();
|
||||
const model = raylib.LoadModelFromMesh(try chunk.createMesh());
|
||||
defer raylib.UnloadModel(model);
|
||||
const end = try std.time.Instant.now();
|
||||
tmp += end.since(start);
|
||||
}
|
||||
std.debug.print("\nchunk meshing time: {d:.3}ms\n\n", .{
|
||||
@as(f64, @floatFromInt(tmp)) / std.time.ns_per_ms / 500,
|
||||
});
|
||||
}
|
||||
|
||||
const model = raylib.LoadModelFromMesh(try chunk.createMesh());
|
||||
defer raylib.UnloadModel(model);
|
||||
|
|
@ -112,9 +131,4 @@ pub fn main() !void {
|
|||
}
|
||||
}
|
||||
|
||||
test "simple test" {
|
||||
var list = std.ArrayList(i32).init(std.testing.allocator);
|
||||
defer list.deinit();
|
||||
try list.append(42);
|
||||
try std.testing.expectEqual(@as(i32, 42), list.pop());
|
||||
}
|
||||
test "empty test xd" {}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@ pub const v3 = struct {
|
|||
pub inline fn new(x: f32, y: f32, z: f32) raylib.Vector3 {
|
||||
return raylib.Vector3{ .x = x, .y = y, .z = z };
|
||||
}
|
||||
pub inline fn newShifted(x: f32, y: f32, z: f32, comptime d: comptime_int) raylib.Vector3 {
|
||||
if (d % 3 == 0) {
|
||||
return new(x, y, z);
|
||||
} else if (d % 3 == 1) {
|
||||
return new(y, z, x);
|
||||
} else if (d % 3 == 2) {
|
||||
return new(z, x, y);
|
||||
}
|
||||
}
|
||||
pub inline fn add(a: raylib.Vector3, b: raylib.Vector3) raylib.Vector3 {
|
||||
return raylib.Vector3Add(a, b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ const RawQuad = struct {
|
|||
bottom_right: raylib.Vector3,
|
||||
bottom_left: raylib.Vector3,
|
||||
normal: raylib.Vector3,
|
||||
width: f32,
|
||||
height: f32,
|
||||
};
|
||||
|
||||
pub const Chunk = struct {
|
||||
|
|
@ -38,148 +40,76 @@ pub const Chunk = struct {
|
|||
self.tiles[@as(u15, x) << 10 | @as(u15, y) << 5 | @as(u15, z)] = tile;
|
||||
}
|
||||
|
||||
fn getTileRaw(self: Chunk, x: u5, y: u5, z: u5) i32 {
|
||||
return self.tiles[@as(u15, x) << 10 | @as(u15, y) << 5 | @as(u15, z)];
|
||||
}
|
||||
|
||||
inline fn getTileRawShifted(self: Chunk, x: u5, y: u5, z: u5, comptime d: comptime_int) i32 {
|
||||
if (d % 3 == 0) {
|
||||
return self.getTileRaw(x, y, z);
|
||||
} else if (d % 3 == 1) {
|
||||
return self.getTileRaw(y, z, x);
|
||||
} else if (d % 3 == 2) {
|
||||
return self.getTileRaw(z, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createMesh(chunk: Chunk) !raylib.Mesh {
|
||||
var raw_quads = try std.ArrayList(RawQuad).initCapacity(chunk.a7r, 4096);
|
||||
defer raw_quads.deinit();
|
||||
for (0..32) |raw_x| {
|
||||
const x: u5 = @intCast(raw_x);
|
||||
var positive_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
var negative_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
for (0..32) |raw_y| for (0..32) |raw_z| {
|
||||
const y: u5 = @intCast(raw_y);
|
||||
const z: u5 = @intCast(raw_z);
|
||||
const tile: i32 = chunk.getTile(x, y, z);
|
||||
if (tile == 0) continue;
|
||||
if (x == 31 or chunk.getTile(x + 1, y, z) == 0) positive_tile_surfaces[y][z] = tile;
|
||||
if (x == 0 or chunk.getTile(x - 1, y, z) == 0) negative_tile_surfaces[y][z] = tile;
|
||||
};
|
||||
const xf: f32 = @floatFromInt(raw_x);
|
||||
for (0..32) |y| for (0..32) |z| {
|
||||
const surface = positive_tile_surfaces[y][z];
|
||||
if (surface == 0) continue;
|
||||
positive_tile_surfaces[y][z] = 0;
|
||||
const yf: f32 = @floatFromInt(y);
|
||||
const zf: f32 = @floatFromInt(z);
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.new(xf + 0.5, yf - 0.5, zf - 0.5),
|
||||
.top_right = v3.new(xf + 0.5, yf + 0.5, zf - 0.5),
|
||||
.bottom_left = v3.new(xf + 0.5, yf - 0.5, zf + 0.5),
|
||||
.bottom_right = v3.new(xf + 0.5, yf + 0.5, zf + 0.5),
|
||||
.normal = v3.new(1, 0, 0),
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
for (0..32) |y| for (0..32) |z| {
|
||||
const surface = negative_tile_surfaces[y][z];
|
||||
if (surface == 0) continue;
|
||||
negative_tile_surfaces[y][z] = 0;
|
||||
const yf: f32 = @floatFromInt(y);
|
||||
const zf: f32 = @floatFromInt(z);
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.new(xf - 0.5, yf + 0.5, zf - 0.5),
|
||||
.top_right = v3.new(xf - 0.5, yf - 0.5, zf - 0.5),
|
||||
.bottom_left = v3.new(xf - 0.5, yf + 0.5, zf + 0.5),
|
||||
.bottom_right = v3.new(xf - 0.5, yf - 0.5, zf + 0.5),
|
||||
.normal = v3.new(-1, 0, 0),
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
}
|
||||
|
||||
for (0..32) |raw_z| {
|
||||
const z: u5 = @intCast(raw_z);
|
||||
var positive_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
var negative_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
for (0..32) |raw_y| for (0..32) |raw_x| {
|
||||
const y: u5 = @intCast(raw_y);
|
||||
inline for (0..3) |d| {
|
||||
for (0..32) |raw_x| {
|
||||
const x: u5 = @intCast(raw_x);
|
||||
const tile: i32 = chunk.getTile(x, y, z);
|
||||
if (tile == 0) continue;
|
||||
if (z == 31 or chunk.getTile(x, y, z + 1) == 0) positive_tile_surfaces[y][x] = tile;
|
||||
if (z == 0 or chunk.getTile(x, y, z - 1) == 0) negative_tile_surfaces[y][x] = tile;
|
||||
};
|
||||
const zf: f32 = @floatFromInt(raw_z);
|
||||
for (0..32) |y| for (0..32) |x| {
|
||||
const surface = positive_tile_surfaces[y][x];
|
||||
if (surface == 0) continue;
|
||||
positive_tile_surfaces[y][x] = 0;
|
||||
const yf: f32 = @floatFromInt(y);
|
||||
const xf: f32 = @floatFromInt(x);
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.new(xf - 0.5, yf - 0.5, zf + 0.5),
|
||||
.top_right = v3.new(xf + 0.5, yf - 0.5, zf + 0.5),
|
||||
.bottom_left = v3.new(xf - 0.5, yf + 0.5, zf + 0.5),
|
||||
.bottom_right = v3.new(xf + 0.5, yf + 0.5, zf + 0.5),
|
||||
.normal = v3.new(0, 0, 1),
|
||||
var positive_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
var negative_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
for (0..32) |raw_y| for (0..32) |raw_z| {
|
||||
const y: u5 = @intCast(raw_y);
|
||||
const z: u5 = @intCast(raw_z);
|
||||
const tile: i32 = chunk.getTileRawShifted(x, y, z, d);
|
||||
if (tile == 0) continue;
|
||||
if (x == 31 or chunk.getTileRawShifted(x + 1, y, z, d) == 0) positive_tile_surfaces[y][z] = tile;
|
||||
if (x == 0 or chunk.getTileRawShifted(x - 1, y, z, d) == 0) negative_tile_surfaces[y][z] = tile;
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
for (0..32) |y| for (0..32) |x| {
|
||||
const surface = negative_tile_surfaces[y][x];
|
||||
if (surface == 0) continue;
|
||||
negative_tile_surfaces[y][x] = 0;
|
||||
const yf: f32 = @floatFromInt(y);
|
||||
const xf: f32 = @floatFromInt(x);
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.new(xf - 0.5, yf + 0.5, zf - 0.5),
|
||||
.top_right = v3.new(xf + 0.5, yf + 0.5, zf - 0.5),
|
||||
.bottom_left = v3.new(xf - 0.5, yf - 0.5, zf - 0.5),
|
||||
.bottom_right = v3.new(xf + 0.5, yf - 0.5, zf - 0.5),
|
||||
.normal = v3.new(0, 0, -1),
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
}
|
||||
|
||||
for (0..32) |raw_y| {
|
||||
const y: u5 = @intCast(raw_y);
|
||||
var positive_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
var negative_tile_surfaces: [32][32]i32 = .{.{0} ** 32} ** 32;
|
||||
for (0..32) |raw_x| for (0..32) |raw_z| {
|
||||
const x: u5 = @intCast(raw_x);
|
||||
const z: u5 = @intCast(raw_z);
|
||||
const tile: i32 = chunk.getTile(x, y, z);
|
||||
if (tile == 0) continue;
|
||||
if (y == 31 or chunk.getTile(x, y + 1, z) == 0) positive_tile_surfaces[x][z] = tile;
|
||||
if (y == 0 or chunk.getTile(x, y - 1, z) == 0) negative_tile_surfaces[x][z] = tile;
|
||||
};
|
||||
const yf: f32 = @floatFromInt(raw_y);
|
||||
for (0..32) |x| for (0..32) |z| {
|
||||
const surface = positive_tile_surfaces[x][z];
|
||||
if (surface == 0) continue;
|
||||
positive_tile_surfaces[x][z] = 0;
|
||||
const xf: f32 = @floatFromInt(x);
|
||||
const zf: f32 = @floatFromInt(z);
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.new(xf - 0.5, yf + 0.5, zf - 0.5),
|
||||
.top_right = v3.new(xf - 0.5, yf + 0.5, zf + 0.5),
|
||||
.bottom_left = v3.new(xf + 0.5, yf + 0.5, zf - 0.5),
|
||||
.bottom_right = v3.new(xf + 0.5, yf + 0.5, zf + 0.5),
|
||||
.normal = v3.new(0, 1, 0),
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
for (0..32) |x| for (0..32) |z| {
|
||||
const surface = negative_tile_surfaces[x][z];
|
||||
if (surface == 0) continue;
|
||||
negative_tile_surfaces[x][z] = 0;
|
||||
const xf: f32 = @floatFromInt(x);
|
||||
const zf: f32 = @floatFromInt(z);
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.new(xf + 0.5, yf - 0.5, zf - 0.5),
|
||||
.top_right = v3.new(xf + 0.5, yf - 0.5, zf + 0.5),
|
||||
.bottom_left = v3.new(xf - 0.5, yf - 0.5, zf - 0.5),
|
||||
.bottom_right = v3.new(xf - 0.5, yf - 0.5, zf + 0.5),
|
||||
.normal = v3.new(0, -1, 0),
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
const xf: f32 = @floatFromInt(raw_x);
|
||||
inline for (.{ -1, 1 }) |sign| {
|
||||
var tile_surfaces = if (sign == 1) positive_tile_surfaces else negative_tile_surfaces;
|
||||
for (0..32) |y| for (0..32) |z| {
|
||||
const surface = tile_surfaces[y][z];
|
||||
if (surface == 0) continue;
|
||||
var y2 = y + 1;
|
||||
while (y2 <= 31 and tile_surfaces[y2][z] == surface) : (y2 += 1) {
|
||||
tile_surfaces[y2][z] = 0;
|
||||
}
|
||||
var z2 = z + 1;
|
||||
zloop: while (z2 <= 31) : (z2 += 1) {
|
||||
for (y..y2) |ytmp| if (tile_surfaces[ytmp][z2] != surface) break :zloop;
|
||||
for (y..y2) |ytmp| tile_surfaces[ytmp][z2] = 0;
|
||||
tile_surfaces[y][z2] = 0;
|
||||
}
|
||||
y2 -= 1;
|
||||
z2 -= 1;
|
||||
tile_surfaces[y][z] = 0;
|
||||
const ymin: f32 = @as(f32, @floatFromInt(y)) - 0.5;
|
||||
const ymax: f32 = @as(f32, @floatFromInt(y2)) + 0.5;
|
||||
const zmin: f32 = @as(f32, @floatFromInt(z)) - 0.5;
|
||||
const zmax: f32 = @as(f32, @floatFromInt(z2)) + 0.5;
|
||||
const yleft: f32 = if (sign == 1) ymin else ymax;
|
||||
const yright: f32 = if (sign == 1) ymax else ymin;
|
||||
const raw_quad: RawQuad = .{
|
||||
.tile = surface,
|
||||
.top_left = v3.newShifted(xf + 0.5 * sign, yleft, zmin, d),
|
||||
.top_right = v3.newShifted(xf + 0.5 * sign, yright, zmin, d),
|
||||
.bottom_left = v3.newShifted(xf + 0.5 * sign, yleft, zmax, d),
|
||||
.bottom_right = v3.newShifted(xf + 0.5 * sign, yright, zmax, d),
|
||||
.normal = v3.newShifted(sign, 0, 0, d),
|
||||
.width = ymax - ymin,
|
||||
.height = zmax - zmin,
|
||||
};
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const triangle_count: c_int = @intCast(raw_quads.items.len * 2);
|
||||
|
|
@ -206,31 +136,31 @@ pub const Chunk = struct {
|
|||
vertices[18 * i + 3] = raw_quad.top_right.x;
|
||||
vertices[18 * i + 4] = raw_quad.top_right.y;
|
||||
vertices[18 * i + 5] = raw_quad.top_right.z;
|
||||
texcoords[12 * i + 2] = 1.0;
|
||||
texcoords[12 * i + 2] = raw_quad.width;
|
||||
texcoords[12 * i + 3] = 0.0;
|
||||
|
||||
vertices[18 * i + 6] = raw_quad.bottom_left.x;
|
||||
vertices[18 * i + 7] = raw_quad.bottom_left.y;
|
||||
vertices[18 * i + 8] = raw_quad.bottom_left.z;
|
||||
texcoords[12 * i + 4] = 0.0;
|
||||
texcoords[12 * i + 5] = 1.0;
|
||||
texcoords[12 * i + 5] = raw_quad.height;
|
||||
|
||||
vertices[18 * i + 9] = raw_quad.bottom_right.x;
|
||||
vertices[18 * i + 10] = raw_quad.bottom_right.y;
|
||||
vertices[18 * i + 11] = raw_quad.bottom_right.z;
|
||||
texcoords[12 * i + 6] = 1.0;
|
||||
texcoords[12 * i + 7] = 1.0;
|
||||
texcoords[12 * i + 6] = raw_quad.width;
|
||||
texcoords[12 * i + 7] = raw_quad.height;
|
||||
|
||||
vertices[18 * i + 12] = raw_quad.bottom_left.x;
|
||||
vertices[18 * i + 13] = raw_quad.bottom_left.y;
|
||||
vertices[18 * i + 14] = raw_quad.bottom_left.z;
|
||||
texcoords[12 * i + 8] = 0.0;
|
||||
texcoords[12 * i + 9] = 1.0;
|
||||
texcoords[12 * i + 9] = raw_quad.height;
|
||||
|
||||
vertices[18 * i + 15] = raw_quad.top_right.x;
|
||||
vertices[18 * i + 16] = raw_quad.top_right.y;
|
||||
vertices[18 * i + 17] = raw_quad.top_right.z;
|
||||
texcoords[12 * i + 10] = 1.0;
|
||||
texcoords[12 * i + 10] = raw_quad.width;
|
||||
texcoords[12 * i + 11] = 0.0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue