aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/level.zig31
-rw-r--r--src/main.zig57
-rw-r--r--src/render.zig44
3 files changed, 74 insertions, 58 deletions
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),
+ 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?
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 });