diff options
| -rw-r--r-- | src/level.zig | 25 | ||||
| -rw-r--r-- | src/render.zig | 58 |
2 files changed, 74 insertions, 9 deletions
diff --git a/src/level.zig b/src/level.zig index a5d7330..dce2a14 100644 --- a/src/level.zig +++ b/src/level.zig @@ -18,26 +18,33 @@ const std = @import("std"); pub const Object = struct { - height : f32, - width : f32, - texture : u8, - pos_x : f32, - pos_y : f32, - pos_z : f32 = 0, + height: f32, + width: f32, + texture: u8, + pos_x: f32, + pos_y: f32, + pos_z: f32 = 0, }; pub const Cell = struct { floor_height: f32 = 0, - ceiling_height : f32 = DEFAULT_HEIGHT, + 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, - pub const floor = Cell{ }; + vertices: [][2]f32 = [][2]f32{ + .{ 0, 0 }, + .{ 1, 0 }, + .{ 1, 1 }, + .{ 0, 1 }, + }, - pub const DEFAULT_HEIGHT : f32 = 4; + pub const floor = Cell{}; + + pub const DEFAULT_HEIGHT: f32 = 4; }; pub const Map = struct { diff --git a/src/render.zig b/src/render.zig index 12af775..38cd26d 100644 --- a/src/render.zig +++ b/src/render.zig @@ -69,6 +69,61 @@ fn fasterColourBlend(onto: Colour, from: Colour) Colour { }; } +fn hitDistLocalCoords( + ray0: [2]f32, + ray1: [2]f32, + vertices: [][2]f32, +) ?f32 { + const rdy = ray1[1] - ray0[1]; + const rdx = ray1[0] - ray0[0]; + + var vp = vertices[0]; + var crossp: f32 = rdy * (vp[0] - ray0[0]) - rdx * (vp[1] - ray0[1]); + + // TODO: there is currently a bug in the logic, if vp->v is parallel to + // ray0->ray1, then we'll return the distance ray0->vp (even if v is + // closer). This is incorrect. + + if (crossp == 0) { + // hit a vertex exactly + const dx = vp[0] - ray0[0]; + const dy = vp[1] - ray0[1]; + return math.sqrt(dx * dx + dy * dy); + } + + var i: usize = 1; + var v = vertices[i]; + var cross: f32 = rdy * (v[0] - ray0[0]) - rdx * (v[1] - ray0[1]); + while (i < vertices.len) : ({ + i += 1; + vp = v; + v = vertices[i]; + crossp = cross; + cross = rdy * (v[0] - ray0[0]) - rdx * (v[1] - ray0[1]); + }) { + if (cross == 0) { + const dx = v[0] - ray0[0]; + const dy = v[1] - ray0[1]; + return math.sqrt(dx * dx + dy * dy); + } else { + if (crossp * cross < 0) { + // If the segment from ray0->ray1 has vp and v on opposite sides + // of it then it intersects the line segment vp->v. This is not + // true in general, but all coordinates are constrained to be in + // the unit square so it is true here. With that we compute the + // distance to the intersection from ray0 + const vdx = v[0] - vp[0]; + const vdy = v[1] - vp[1]; + + const dx = rdx * cross; // this should really be negative, but we square it... + const dy = rdy * (vdx * (ray0[1] - v[1]) - vdy * (ray0[0] - v[0])); + return math.sqrt(dx * dx + dy * dy) / (rdx * vdy - vdx * rdy); + } + } + } + return null; +} + pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { const FOV: f32 = std.math.pi / 3.0; const PlanePixels = PlaneWidth * PlaneHeight; @@ -294,6 +349,9 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { // Are we drawing vertical surfaces? if (cell.floor_height > 0 or cell.draw_down) { + if (hitDistLocalCoords(ray0, ray1, cell.vertices)) |local_distance| { + + } // project the top of the bottom and the bottom of the top top_of_floor = PlaneHeight / 2 + PlaneDist * (cell.floor_height - pheight) / distance; bottom_of_ceiling = PlaneHeight / 2 + PlaneDist * (cell.ceiling_height - pheight) / distance; |
