const std = @import("std"); const rh = @import("../util/raylib_helper.zig"); const raylib = rh.raylib; const v3 = rh.v3; const A7r = std.mem.Allocator; const RawQuad = struct { tile: i32, top_left: raylib.Vector3, top_right: raylib.Vector3, bottom_right: raylib.Vector3, bottom_left: raylib.Vector3, normal: raylib.Vector3, }; pub const Chunk = struct { tiles: []i32, a7r: A7r, pub fn init(a7r: A7r) !Chunk { const self = Chunk{ .a7r = a7r, .tiles = try a7r.alloc(i32, 32 * 32 * 32), }; @memset(self.tiles, 0); return self; } pub fn deinit(self: Chunk) void { self.a7r.free(self.tiles); } pub fn getTile(self: Chunk, x: u5, y: u5, z: u5) i32 { return self.tiles[@as(u15, x) << 10 | @as(u15, y) << 5 | @as(u15, z)]; } pub fn setTile(self: Chunk, x: u5, y: u5, z: u5, tile: i32) void { self.tiles[@as(u15, x) << 10 | @as(u15, y) << 5 | @as(u15, z)] = tile; } 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); 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), }; 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 triangle_count: c_int = @intCast(raw_quads.items.len * 2); const arr_size: c_uint = @as(c_uint, @intCast(triangle_count)) * 3 * @sizeOf(f32); const vertices: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3))); const texcoords: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2))); const normals: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3))); for (raw_quads.items, 0..) |raw_quad, i| { for (0..6) |j| { normals[18 * i + 3 * j + 0] = raw_quad.normal.x; normals[18 * i + 3 * j + 1] = raw_quad.normal.y; normals[18 * i + 3 * j + 2] = raw_quad.normal.z; } vertices[18 * i + 0] = raw_quad.top_left.x; vertices[18 * i + 1] = raw_quad.top_left.y; vertices[18 * i + 2] = raw_quad.top_left.z; texcoords[12 * i + 0] = 0.0; texcoords[12 * i + 1] = 0.0; 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 + 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; 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; 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; 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 + 11] = 0.0; } var mesh = raylib.Mesh{ .triangleCount = triangle_count, .vertexCount = triangle_count * 3, .vertices = vertices, .texcoords = texcoords, .texcoords2 = null, .normals = normals, .tangents = null, .colors = null, .indices = null, .animVertices = null, .animNormals = null, .boneIds = null, .boneWeights = null, .vaoId = 0, .vboId = null, }; raylib.UploadMesh(@ptrCast(&mesh), false); return mesh; } };