This commit is contained in:
catAngent 2024-09-09 18:05:14 +01:00
commit 1a18e45b89
5 changed files with 286 additions and 0 deletions

22
.gitignore vendored Normal file
View file

@ -0,0 +1,22 @@
# This file is for zig-specific build artifacts.
# If you have OS-specific or editor-specific files to ignore,
# such as *.swp or .DS_Store, put those in your global
# ~/.gitignore and put this in your ~/.gitconfig:
#
# [core]
# excludesfile = ~/.gitignore
#
# Cheers!
# -andrewrk
.zig-cache/
zig-out/
/release/
/debug/
/build/
/build-*/
/docgen_tmp/
# Although this was renamed to .zig-cache, let's leave it here for a few
# releases to make it less annoying to work with multiple branches.
zig-cache/

39
build.zig Normal file
View file

@ -0,0 +1,39 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "voxel_test",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.linkLibC();
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const exe_unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_exe_unit_tests.step);
}

16
build.zig.zon Normal file
View file

@ -0,0 +1,16 @@
.{
.name = "voxel_test",
.version = "0.0.0",
.dependencies = .{},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
// For example...
//"LICENSE",
//"README.md",
},
}

118
src/main.zig Normal file
View file

@ -0,0 +1,118 @@
const std = @import("std");
const raylib = @cImport({
@cInclude("../raylib/raylib.h");
@cInclude("../raylib/raymath.h");
@cInclude("../raylib/rlgl.h");
});
const chunks = @import("world/chunk.zig");
pub fn drawCameraPosition(camera: raylib.Camera3D, x: i32, y: i32) !void {
var buf: [256:0]u8 = undefined;
const slice = try std.fmt.bufPrintZ(
&buf,
"position: {d} {d} {d}",
.{ camera.position.x, camera.position.y, camera.position.z },
);
raylib.DrawText(slice, x, y, 20, raylib.YELLOW);
}
pub fn moveCamera(camera: *raylib.Camera3D, x: f32, y: f32, z: f32) void {
camera.position.x += x;
camera.target.x += x;
camera.position.y += y;
camera.target.y += y;
camera.position.z += z;
camera.target.z += z;
}
pub fn moveCameraVec(camera: *raylib.Camera3D, vec: raylib.Vector3) void {
camera.position = camera.position.add(vec);
camera.target = camera.target.add(vec);
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const a7r = gpa.allocator();
defer {
const status = gpa.deinit();
if (status == .leak) std.debug.print("MEMORY LEAK DETECTED!!!!!!!!!!!!!!!!!!!!!!\n", .{}) else std.debug.print("no leaks detected.\n", .{});
}
raylib.SetConfigFlags(raylib.ConfigFlags{ .FLAG_WINDOW_RESIZABLE = true });
raylib.InitWindow(1024, 768, "voxel test");
defer raylib.CloseWindow();
raylib.DisableCursor();
raylib.SetTargetFPS(60);
var camera = raylib.Camera3D{
.position = raylib.Vector3{ .x = 0, .y = 0, .z = 0 },
.up = raylib.Vector3{ .x = 0, .y = 1, .z = 0 },
.target = raylib.Vector3{ .x = 0, .y = 0, .z = -1 },
.fovy = 45,
.projection = raylib.CameraProjection.CAMERA_PERSPECTIVE,
};
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);
};
const mesh = chunk.createMesh();
defer raylib.UnloadMesh(mesh);
while (!raylib.WindowShouldClose()) {
raylib.ClearBackground(raylib.GRAY);
const right = raylib.Vector3CrossProduct(camera.up, raylib.Vector3Subtract(camera.target, camera.position)).normalize().neg();
const forward = raylib.Vector3CrossProduct(right, raylib.Vector3{ .x = 0, .y = -1, .z = 0 });
const movement = @as(f32, if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_LEFT_CONTROL)) 25 else 5) * raylib.GetFrameTime();
if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_SPACE)) moveCamera(&camera, 0, movement, 0);
if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_LEFT_SHIFT)) moveCamera(&camera, 0, -movement, 0);
if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_W)) moveCameraVec(&camera, forward.scale(movement));
if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_S)) moveCameraVec(&camera, forward.scale(-movement));
if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_D)) moveCameraVec(&camera, right.scale(movement));
if (raylib.IsKeyDown(raylib.KeyboardKey.KEY_A)) moveCameraVec(&camera, right.scale(-movement));
const delta = raylib.GetMouseDelta();
camera.target = camera.position.add(raylib.Vector3RotateByAxisAngle(camera.target.sub(camera.position), raylib.Vector3{ .x = 0, .y = 1, .z = 0 }, -0.005 * delta.x));
camera.target = camera.position.add(raylib.Vector3RotateByAxisAngle(camera.target.sub(camera.position), right, -0.005 * delta.y));
raylib.BeginDrawing();
defer raylib.EndDrawing();
{
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(raylib.Vector3{ .x = x + 48, .y = y, .z = z }, 1, 1, 1, raylib.RED);
}
}
}
}
raylib.DrawFPS(10, 10);
try drawCameraPosition(camera, 10, 30);
}
}
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());
}

91
src/world/chunk.zig Normal file
View file

@ -0,0 +1,91 @@
const std = @import("std");
const raylib = @cImport({
@cInclude("../../raylib/raylib.h");
@cInclude("../../raylib/raymath.h");
@cInclude("../../raylib/rlgl.h");
});
const A7r = std.mem.Allocator;
pub const Chunk = struct {
tiles: []i32,
a7r: A7r,
pub fn init(a7r: A7r) !Chunk {
return Chunk{
.a7r = a7r,
.tiles = try a7r.alloc(i32, 32 * 32 * 32),
};
}
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) raylib.Mesh {
const triangle_count: u32 = 1;
const arr_size: c_uint = 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;
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[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;
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;
}
};