From 5cecadb81ccab1a2e6ff264349f5fa73a720db9f Mon Sep 17 00:00:00 2001 From: tslil clingman <> Date: Fri, 22 Oct 2021 17:21:10 -0400 Subject: Specialise layers to be either lists of vertices or squares --- src/level.zig | 35 +++++++++++++++-------------------- src/main.zig | 57 +++++++++++++++++++++------------------------------------ src/render.zig | 44 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 76 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/level.zig b/src/level.zig index f277b19..31d86df 100644 --- a/src/level.zig +++ b/src/level.zig @@ -17,35 +17,30 @@ const std = @import("std"); -pub const Layer = struct { +pub const Polygon = union(enum) { pub const MAX_VERTS = 16; - height : f32 = 0, - vertical_texture : u8 = 0, - vertical_texture_scale : f32 = 4, - horizontal_texture : u8 = 0, - // What happened to this error? Is it comptime? + square: void, vertices: std.BoundedArray([2]f32, MAX_VERTS), }; +pub const Layer = struct { + height: f32 = 0, + vertical_texture: u8 = 0, + vertical_texture_scale: f32 = 4, + horizontal_texture: u8 = 0, + + polygon: Polygon, +}; + pub const Cell = struct { pub const MAX_LAYERS = 16; - // floor_height: f32 = 0, - // ceiling_height: f32 = DEFAULT_HEIGHT, - // draw_down: bool = false, - // lower_texture: u8 = 0, - // upper_texture: u8 = 0, - // floor_texture: u8 = 0, - // ceiling_texture: u8 = 2, - - lower_layers : std.BoundedArray(Layer, MAX_LAYERS), - - // I'm not sure how i feel about reaching into the implementation of - // BoundedArray like this. Surely there should be an ``.empty'' or something - // default? + + lower_layers: std.BoundedArray(Layer, MAX_LAYERS), + fn empty() !Cell { const lower_layers = try std.BoundedArray(Layer, MAX_LAYERS).init(0); - return Cell{ . lower_layers = lower_layers }; + return Cell{ .lower_layers = lower_layers }; } pub const DEFAULT_HEIGHT: f32 = 4; diff --git a/src/main.zig b/src/main.zig index 8b77440..781b9a7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -49,58 +49,43 @@ pub fn main() !void { var map = try level.Map.new(16, 16, &gpa.allocator); defer map.deinit(); - // floor - const square_coords = [_][2]f32{ - .{ 0.00, 0.00 }, - .{ 1.00, 0.00 }, - .{ 1.00, 1.00 }, - .{ 0.00, 1.00 }, - }; - var y: u32 = 0; while (y < 16) : (y += 1) { var x: usize = 0; while (x < 16) : (x += 1) { - var floor_verts = try std.BoundedArray([2]f32, level.Layer.MAX_VERTS).fromSlice(square_coords[0..]); - try map.cells.items[y * 16 + x].lower_layers.append(level.Layer{ .height = 0, .vertices = floor_verts }); + try map.cells.items[y * 16 + x].lower_layers.append(level.Layer{ .height = 0, .polygon = .square }); if (y == 0 or y == 15 or x == 0) { - try map.cells.items[y * 16 + x].lower_layers.append(level.Layer{ .height = 2, .vertices = floor_verts }); + try map.cells.items[y * 16 + x].lower_layers.append(level.Layer{ .height = 2, .polygon = .square }); } else { if (x == 15) - try map.cells.items[y * 16 + x].lower_layers.append(level.Layer{ .height = 2, .vertices = floor_verts, .vertical_texture = 2 }); + try map.cells.items[y * 16 + x].lower_layers.append(level.Layer{ .height = 2, .polygon = .square, .vertical_texture = 2 }); } if (y == 7 and x >= 5 and x <= 10) { const vert_coords0 = [_][2]f32{ - .{ 0.10, 0.10 }, - .{ 0.90, 0.10 }, - .{ 0.90, 0.90 }, - .{ 0.10, 0.90 }, + .{ 0.50, 0.10 }, + .{ 0.10, 0.80 }, + .{ 0.90, 0.80 }, }; - var verts = try std.BoundedArray([2]f32, level.Layer.MAX_VERTS).fromSlice(vert_coords0[0..]); - var layer = level.Layer{ .height = 0.5, .vertices = verts, .vertical_texture = 3, .horizontal_texture = 1 }; + var verts = try std.BoundedArray([2]f32, level.Polygon.MAX_VERTS).fromSlice(vert_coords0[0..]); + var layer = level.Layer{ .height = 0.5, .polygon = .{ .vertices = verts }, .vertical_texture = 3, .horizontal_texture = 1, .vertical_texture_scale = 3 }; try map.cells.items[y * 16 + x].lower_layers.append(layer); - const vert_coords1 = [_][2]f32{ - .{ 0.75, 0.5 }, - .{ 0.72838634, 0.60168415 }, - .{ 0.66728264, 0.68578625 }, - .{ 0.57725424, 0.7377641 }, - .{ 0.47386786, 0.74863046 }, - .{ 0.375, 0.71650636 }, - .{ 0.29774573, 0.6469463 }, - .{ 0.2554631, 0.5519779 }, - .{ 0.25546312, 0.44802207 }, - .{ 0.29774576, 0.35305366 }, - .{ 0.37500003, 0.28349364 }, - .{ 0.47386792, 0.25136954 }, - .{ 0.5772543, 0.26223588 }, - .{ 0.6672827, 0.3142138 }, - .{ 0.7283864, 0.39831588 }, + // cylinder + const vert_coords1 = comptime blk: { + const size = level.Polygon.MAX_VERTS; + var shape: [size][2]f32 = [_][2]f32{.{ 0, 0 }} ** size; + for (shape) |*pair, i| { + const theta = @intToFloat(f32, i) / @intToFloat(f32, shape.len) * 2 * std.math.pi; + pair.*[0] = 0.5 + 0.2 * std.math.cos(theta); + pair.*[1] = 0.5 + 0.2 * std.math.sin(theta); + } + break :blk shape; }; - verts = try std.BoundedArray([2]f32, level.Layer.MAX_VERTS).fromSlice(vert_coords1[0..]); - layer = level.Layer{ .height = 1, .vertices = verts, .vertical_texture = 1, .horizontal_texture = 2, .vertical_texture_scale = 2 }; + verts = try std.BoundedArray([2]f32, level.Polygon.MAX_VERTS).fromSlice(vert_coords1[0..]); + + layer = level.Layer{ .height = 1, .polygon = .{ .vertices = verts }, .vertical_texture = 1, .horizontal_texture = 2, .vertical_texture_scale = 2 }; try map.cells.items[y * 16 + x].lower_layers.append(layer); } } diff --git a/src/render.zig b/src/render.zig index 72121f2..6c54a00 100644 --- a/src/render.zig +++ b/src/render.zig @@ -316,9 +316,40 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { } var previous_layer_height: f32 = 0; - var previous_highest_drawn:f32 = highest_drawn; + var previous_highest_drawn: f32 = highest_drawn; for (cell.lower_layers.constSlice()) |layer| { - if (hitDistLocalCoords(ray0_x, ray0_y, ray1_x, ray1_y, layer.vertices.constSlice())) |hit| { + const should_try_to_draw_layer = switch (layer.polygon) { + .square => hit: { + // we have to compute texture_frac by hand. + var texfrac : f32 = undefined; + // Using the notation in the below diagram, + // we want face_i to have [0.25i, 0.25(i+1)] + // of the texture. + + // <---2--- + // | ^ + // 3 | + // | 1 + // v | + // ---0---> + + if (hit_horizontal) { + // a horizontal hit means we take the horizontal coordinate + texfrac = std.math.modf(distance * cosra + ppos_x).fpart / 4; + // we're either 0 or 2, if sinra < 0 then we're 2 + if (sinra < 0) texfrac = 0.50 + (0.25 - texfrac); + } else { + // a vertical hit means we take the vertical coordinate + texfrac = std.math.modf(distance * sinra + ppos_y).fpart / 4; + // we're either 1 or 3, if cosra < 0 then we're 1 + if (cosra < 0) texfrac += 0.25 else texfrac = 0.75 + (0.25 - texfrac); + } + + break :hit LocalCoordHit{ .local_dist = 0, .texture_frac = texfrac }; + }, + .vertices => |vs| hitDistLocalCoords(ray0_x, ray0_y, ray1_x, ray1_y, vs.constSlice()), + }; + if (should_try_to_draw_layer) |hit| { // TODO: Correct for fisheye? Is this what FOV_SCALE does? const adj_distance = distance + hit.local_dist * FOV_SCALE; @@ -397,14 +428,19 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { const sy = ppos_y + row_dist * sinra; // only proceed if it's in the current square - if (@floatToInt(i32, sx) != ipos_x or @floatToInt(i32, sy) != ipos_y) continue; + if (sx < 0 or sy < 0 or @floatToInt(i32, sx) != ipos_x or @floatToInt(i32, sy) != ipos_y) continue; // where does it land in the square? const rx = std.math.modf(sx).fpart; const ry = std.math.modf(sy).fpart; // is it in the polygon? - if (pointInPoly(rx, ry, layer.vertices.constSlice())) { + const should_be_drawn = switch (layer.polygon) { + .square => true, + .vertices => |vs| pointInPoly(rx, ry, vs.constSlice()), + }; + + if (should_be_drawn) { const px = @floatToInt(c_uint, constants.TextureDim * rx); const py = @floatToInt(c_uint, constants.TextureDim * ry); pixels[pix_index] = surfaces_image.getPixel(.{ .x = toff + px, .y = py }); -- cgit v1.3.1