diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/render.zig | 71 |
1 files changed, 27 insertions, 44 deletions
diff --git a/src/render.zig b/src/render.zig index 2b3aef5..8d2faca 100644 --- a/src/render.zig +++ b/src/render.zig @@ -69,15 +69,22 @@ fn fasterColourBlend(onto: Colour, from: Colour) Colour { }; } +const LocalCoordHit = struct { + local_dist : f32, + frac : f32, +}; + // The primary observation is: if a line segment AB disconnects the unit square, // then it intersects another line segment CD in that square precisely when the // C and D are on opposite sides of AB---cross product! We can calculate the // intersection point using the usual matrix inversion/determinant story. + +// TODO: handle hitting vertices fn hitDistLocalCoords( ray0: [2]f32, ray1: [2]f32, vertices: []const [2]f32, -) ?f32 { +) ?LocalCoordHit { const rdy = ray1[1] - ray0[1]; const rdx = ray1[0] - ray0[0]; const rdist = std.math.sqrt(rdx * rdx + rdy * rdy); @@ -85,14 +92,14 @@ fn hitDistLocalCoords( var vp = vertices[0]; var crossp: f32 = rdy * (vp[0] - ray0[0]) - rdx * (vp[1] - ray0[1]); - if (crossp == 0) { - // hit a vertex exactly - const dx = vp[0] - ray0[0]; - const dy = vp[1] - ray0[1]; - return std.math.sqrt(dx * dx + dy * dy); - } + // if (crossp == 0) { + // // hit a vertex exactly + // const dx = vp[0] - ray0[0]; + // const dy = vp[1] - ray0[1]; + // return .{ std.math.sqrt(dx * dx + dy * dy), 0}; + // } - var return_val: ?f32 = null; + var ret_val: ?LocalCoordHit = null; var v : [2]f32 = undefined; var cross: f32 = 0; var i: usize = 1; @@ -115,30 +122,24 @@ fn hitDistLocalCoords( // } 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 t = (vdx * (ray0[1] - vp[1]) - vdy * (ray0[0] - vp[0])) / (rdx * vdy - vdx * rdy); + // both t and frac here index the intersection point, but t does + // so along ray0->ray1 which we use for fast distance, and frac + // indexes it along vp->v which we use for texture mapping. + const denom = (rdx * vdy - vdx * rdy); + const t = (vdx * (ray0[1] - vp[1]) - vdy * (ray0[0] - vp[0])) / denom; + const frac = crossp / denom; const new_distance = rdist * t; - // const s = cross / (rdx * vdy - vdx * rdy); - // const dx = v[0] + vdx * s - ray0[0]; - // const dy = v[1] + vdy * s - ray0[1]; - // const new_distance = std.math.sqrt(dx * dx + dy * dy); - if (return_val) |local_distance| { - if (new_distance < local_distance) return_val = new_distance; - } else { - return_val = new_distance; + if (ret_val == null or (new_distance < ret_val.?.local_dist)) { + ret_val = LocalCoordHit{.local_dist = new_distance, .frac = frac}; } } } } - return return_val; + return ret_val; } pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { @@ -424,9 +425,9 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { std.math.modf(next_distance * sinra + ppos_y).fpart, }; - if (hitDistLocalCoords(ray0, ray1, cell.vertices)) |local_dist| { + if (hitDistLocalCoords(ray0, ray1, cell.vertices)) |dist_frac| { // TODO: Correct for fisheye? - const adj_distance = distance + local_dist; + const adj_distance = distance + dist_frac.local_dist; // project the top of the bottom and the bottom of the top top_of_floor = PlaneHeight / 2 + PlaneDist * (cell.floor_height - pheight) / adj_distance; @@ -437,25 +438,7 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { // Are we able to see any vertical faces? if (draw_upper or draw_lower) { - // we need the distance to calculate the - // fractional part of the relevant coordinate - // for texture mapping of the walls - - // TODO: Now that walls are polygonal, what - // should texture mapping mean? - var texfrac : f32 = 0.5; - // if (hit_horizontal) { - // texfrac = adj_distance * cosra + ppos_x; - // } else { - // texfrac = adj_distance * sinra + ppos_y; - // } - // texfrac = std.math.modf(texfrac).fpart; - - // we also want to be sure that we're consistently - // orienting textures, in this case clockwise - // if ((hit_horizontal and sinra < 0) or (!hit_horizontal and cosra > 0)) texfrac = 1 - texfrac; - - const texstrip = @floatToInt(c_uint, constants.TextureDim * texfrac); + const texstrip = @floatToInt(c_uint, constants.TextureDim * dist_frac.frac); // height of a unit-height wall at this distance const nominal_length = PlaneDist / adj_distance; |
