diff --git a/src/main.zig b/src/main.zig index e71c7b4..5c6ddbe 100644 --- a/src/main.zig +++ b/src/main.zig @@ -29,9 +29,10 @@ pub fn main() !void { if (status == .leak) std.debug.print("MEMORY LEAK DETECTED!!!!!!!!!!!!!!!!!!!!!!\n", .{}) else std.debug.print("no leaks detected.\n", .{}); } - raylib.SetConfigFlags(raylib.FLAG_WINDOW_RESIZABLE); + raylib.SetConfigFlags(raylib.FLAG_WINDOW_RESIZABLE | raylib.FLAG_FULLSCREEN_MODE); - raylib.InitWindow(1024, 768, "voxel test"); + const display = raylib.GetCurrentMonitor(); + raylib.InitWindow(raylib.GetMonitorWidth(display), raylib.GetMonitorHeight(display), "voxel test"); defer raylib.CloseWindow(); raylib.DisableCursor(); @@ -45,18 +46,34 @@ pub fn main() !void { .projection = raylib.CAMERA_PERSPECTIVE, }; + const checked = raylib.GenImageChecked(2, 2, 1, 1, raylib.BLUE, raylib.GREEN); + const texture = raylib.LoadTextureFromImage(checked); + defer raylib.UnloadTexture(texture); + raylib.UnloadImage(checked); + var chunk = try chunks.Chunk.init(a7r); defer chunk.deinit(); - for (0..32) |x| for (0..32) |z| { - chunk.setTile(@intCast(x), 0, @intCast(z), 1); - chunk.setTile(@intCast(x), 31, @intCast(z), 1); + for (0..32) |raw_x| for (0..32) |raw_z| { + const x: u5 = @intCast(raw_x); + const z: u5 = @intCast(raw_z); + chunk.setTile(x, 0, z, 1); + chunk.setTile(x, 31, z, 1); }; + for (0..32) |raw_a| { + const a: u5 = @intCast(raw_a); + chunk.setTile(a, a, a, 1); + chunk.setTile(a, 31 - a, a, 1); + chunk.setTile(31 - a, a, a, 1); + chunk.setTile(31 - a, 31 - a, a, 1); + } - const mesh = chunk.createMesh(); - defer raylib.UnloadMesh(mesh); + const model = raylib.LoadModelFromMesh(try chunk.createMesh()); + defer raylib.UnloadModel(model); + + model.materials[0].maps[raylib.MATERIAL_MAP_DIFFUSE].texture = texture; while (!raylib.WindowShouldClose()) { - raylib.ClearBackground(raylib.GRAY); + raylib.ClearBackground(raylib.BLACK); const right = v3.neg(v3.nor(v3.cross(camera.up, v3.sub(camera.target, camera.position)))); const forward = v3.cross(right, v3.new(0, -1, 0)); @@ -81,20 +98,13 @@ pub fn main() !void { raylib.BeginDrawing(); defer raylib.EndDrawing(); + const model_position = v3.new(0, 0, 0); + { raylib.BeginMode3D(camera); defer raylib.EndMode3D(); - var x: f32 = 0; - while (x < 16) : (x += 1) { - var y: f32 = 0; - while (y < 16) : (y += 1) { - var z: f32 = 0; - while (z < 16) : (z += 1) { - raylib.DrawCube(v3.new(x - 48, y, z), 1, 1, 1, raylib.RED); - } - } - } + raylib.DrawModel(model, model_position, 0.5, raylib.WHITE); } raylib.DrawFPS(10, 10); diff --git a/src/world/chunk.zig b/src/world/chunk.zig index 9f2f875..14696c4 100644 --- a/src/world/chunk.zig +++ b/src/world/chunk.zig @@ -1,17 +1,29 @@ 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 { - return 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 { @@ -26,41 +38,201 @@ pub const Chunk = struct { self.tiles[@as(u15, x) << 10 | @as(u15, y) << 5 | @as(u15, z)] = tile; } - pub fn createMesh(_: Chunk) raylib.Mesh { - const triangle_count: u32 = 1; + 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); + }; + } - const arr_size: c_uint = triangle_count * 3 * @sizeOf(f32); + 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))); - vertices[0] = 0.0; - vertices[1] = 0.0; - vertices[2] = 0.0; - normals[0] = 0.0; - normals[1] = 1.0; - normals[2] = 0.0; - texcoords[0] = 0.0; - texcoords[1] = 0.0; + 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[3] = 1.0; - vertices[4] = 0.0; - vertices[5] = 2.0; - normals[3] = 0.0; - normals[4] = 1.0; - normals[5] = 0.0; - texcoords[2] = 0.5; - texcoords[3] = 1.0; + 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[6] = 2.0; - vertices[7] = 0.0; - vertices[8] = 0.0; - normals[6] = 0.0; - normals[7] = 1.0; - normals[8] = 0.0; - texcoords[4] = 1.0; - texcoords[5] = 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,