2024-09-09 18:05:14 +01:00
|
|
|
const std = @import("std");
|
2024-09-09 21:07:10 +01:00
|
|
|
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-15 21:25:30 +01:00
|
|
|
width: f32,
|
|
|
|
|
height: f32,
|
2024-09-12 22:51:16 +01:00
|
|
|
};
|
|
|
|
|
|
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-15 21:25:30 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-19 21:33:32 +01:00
|
|
|
pub fn createMesh(chunk: Chunk, tile_rows: u32, tile_columns: u32) !raylib.Mesh {
|
2024-09-12 22:51:16 +01:00
|
|
|
var raw_quads = try std.ArrayList(RawQuad).initCapacity(chunk.a7r, 4096);
|
|
|
|
|
defer raw_quads.deinit();
|
2024-09-09 18:05:14 +01:00
|
|
|
|
2024-09-15 21:25:30 +01:00
|
|
|
inline for (0..3) |d| {
|
|
|
|
|
for (0..32) |raw_x| {
|
2024-09-12 22:51:16 +01:00
|
|
|
const x: u5 = @intCast(raw_x);
|
2024-09-15 21:25:30 +01:00
|
|
|
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;
|
2024-09-12 22:51:16 +01:00
|
|
|
};
|
2024-09-15 21:25:30 +01:00
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
var z2 = z + 1;
|
2024-09-15 21:25:30 +01:00
|
|
|
while (y2 <= 31 and tile_surfaces[y2][z] == surface) : (y2 += 1) {
|
|
|
|
|
tile_surfaces[y2][z] = 0;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-12 22:51:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)));
|
2024-09-19 21:33:32 +01:00
|
|
|
const texcoords2: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
|
2024-09-09 18:05:14 +01:00
|
|
|
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| {
|
2024-09-19 21:33:32 +01:00
|
|
|
if (raw_quad.tile <= 0) continue;
|
|
|
|
|
const tile = @as(u32, @intCast(raw_quad.tile));
|
|
|
|
|
|
2024-09-12 22:51:16 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-19 21:33:32 +01:00
|
|
|
const left_uv = @as(f32, @floatFromInt(tile % tile_columns)) / @as(f32, @floatFromInt(tile_columns));
|
|
|
|
|
const right_uv = @as(f32, @floatFromInt(tile % tile_columns + 1)) / @as(f32, @floatFromInt(tile_columns));
|
|
|
|
|
const top_uv = @as(f32, @floatFromInt(tile / tile_columns)) / @as(f32, @floatFromInt(tile_rows));
|
|
|
|
|
const bottom_uv = @as(f32, @floatFromInt(tile / tile_columns + 1)) / @as(f32, @floatFromInt(tile_rows));
|
|
|
|
|
|
2024-09-12 22:51:16 +01:00
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
texcoords[12 * i + 0] = left_uv;
|
|
|
|
|
texcoords[12 * i + 1] = top_uv;
|
|
|
|
|
texcoords2[12 * i + 0] = 0.0;
|
|
|
|
|
texcoords2[12 * i + 1] = 0.0;
|
2024-09-12 22:51:16 +01:00
|
|
|
|
|
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
texcoords[12 * i + 2] = right_uv;
|
|
|
|
|
texcoords[12 * i + 3] = top_uv;
|
|
|
|
|
texcoords2[12 * i + 2] = raw_quad.width;
|
|
|
|
|
texcoords2[12 * i + 3] = 0.0;
|
2024-09-12 22:51:16 +01:00
|
|
|
|
|
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
texcoords[12 * i + 4] = left_uv;
|
|
|
|
|
texcoords[12 * i + 5] = bottom_uv;
|
|
|
|
|
texcoords2[12 * i + 4] = 0.0;
|
|
|
|
|
texcoords2[12 * i + 5] = raw_quad.height;
|
2024-09-12 22:51:16 +01:00
|
|
|
|
|
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
texcoords[12 * i + 6] = right_uv;
|
|
|
|
|
texcoords[12 * i + 7] = bottom_uv;
|
|
|
|
|
texcoords2[12 * i + 6] = raw_quad.width;
|
|
|
|
|
texcoords2[12 * i + 7] = raw_quad.height;
|
2024-09-12 22:51:16 +01:00
|
|
|
|
|
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
texcoords[12 * i + 8] = left_uv;
|
|
|
|
|
texcoords[12 * i + 9] = bottom_uv;
|
|
|
|
|
texcoords2[12 * i + 8] = 0.0;
|
|
|
|
|
texcoords2[12 * i + 9] = raw_quad.height;
|
2024-09-12 22:51:16 +01:00
|
|
|
|
|
|
|
|
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;
|
2024-09-19 21:33:32 +01:00
|
|
|
texcoords[12 * i + 10] = right_uv;
|
|
|
|
|
texcoords[12 * i + 11] = top_uv;
|
|
|
|
|
texcoords2[12 * i + 10] = raw_quad.width;
|
|
|
|
|
texcoords2[12 * i + 11] = 0.0;
|
2024-09-12 22:51:16 +01:00
|
|
|
}
|
2024-09-09 18:05:14 +01:00
|
|
|
|
|
|
|
|
var mesh = raylib.Mesh{
|
|
|
|
|
.triangleCount = triangle_count,
|
|
|
|
|
.vertexCount = triangle_count * 3,
|
|
|
|
|
|
|
|
|
|
.vertices = vertices,
|
|
|
|
|
.texcoords = texcoords,
|
2024-09-19 21:33:32 +01:00
|
|
|
.texcoords2 = texcoords2,
|
2024-09-09 18:05:14 +01:00
|
|
|
.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;
|
|
|
|
|
}
|
|
|
|
|
};
|