voxel-test/src/world/chunk.zig

261 lines
11 KiB
Zig
Raw Normal View History

2024-09-09 18:05:14 +01:00
const std = @import("std");
const rh = @import("../util/raylib_helper.zig");
const raylib = rh.raylib;
2024-09-12 22:51:16 +01:00
const v3 = rh.v3;
2024-09-09 18:05:14 +01:00
const A7r = std.mem.Allocator;
2024-09-12 22:51:16 +01:00
const RawQuad = struct {
tile: i32,
top_left: raylib.Vector3,
top_right: raylib.Vector3,
bottom_right: raylib.Vector3,
bottom_left: raylib.Vector3,
normal: raylib.Vector3,
};
2024-09-09 18:05:14 +01:00
pub const Chunk = struct {
tiles: []i32,
a7r: A7r,
pub fn init(a7r: A7r) !Chunk {
2024-09-12 22:51:16 +01:00
const self = Chunk{
2024-09-09 18:05:14 +01:00
.a7r = a7r,
.tiles = try a7r.alloc(i32, 32 * 32 * 32),
};
2024-09-12 22:51:16 +01:00
@memset(self.tiles, 0);
return self;
2024-09-09 18:05:14 +01:00
}
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;
}
2024-09-12 22:51:16 +01:00
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);
};
}
2024-09-09 18:05:14 +01:00
2024-09-12 22:51:16 +01:00
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);
2024-09-09 18:05:14 +01:00
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)));
2024-09-12 22:51:16 +01:00
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;
}
2024-09-09 18:05:14 +01:00
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;
}
};