diff options
Diffstat (limited to 'src/render.zig')
| -rw-r--r-- | src/render.zig | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/render.zig b/src/render.zig index 47753f0..5879b31 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; @@ -296,6 +351,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; |
