aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/render.zig71
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;