diff options
| author | tslil clingman <> | 2021-10-13 23:00:33 -0400 |
|---|---|---|
| committer | tslil clingman <> | 2021-10-13 23:01:36 -0400 |
| commit | 502d41dbd98595b78ca4f80b07a7b91e28163447 (patch) | |
| tree | a9987ddf767d2a9f452bbe076c8f85db6abf42ad | |
| parent | 7fa4ae345c8c8483c0513b21eda7b612315c1a4c (diff) | |
Polygonal walls!
It was essentially working before, just some indexing bug.
| -rw-r--r-- | src/level.zig | 12 | ||||
| -rw-r--r-- | src/main.zig | 19 | ||||
| -rw-r--r-- | src/render.zig | 75 |
3 files changed, 70 insertions, 36 deletions
diff --git a/src/level.zig b/src/level.zig index 9f5217d..87c3e80 100644 --- a/src/level.zig +++ b/src/level.zig @@ -35,12 +35,12 @@ pub const Cell = struct { floor_texture: u8 = 0, ceiling_texture: u8 = 2, - vertices: [5][2]f32 = [5][2]f32{ - .{ 0, 0 }, - .{ 0.5, 0 }, - .{ 0.5, 0.5 }, - .{ 0, 0.5 }, - .{ 0, 0 }, + vertices: []const [2]f32 = &[_][2]f32{ + .{ 0.25, 0.25 }, + .{ 0.75, 0.25 }, + .{ 0.75, 0.75 }, + .{ 0.25, 0.75 }, + .{ 0.25, 0.25 }, }, pub const floor = Cell{}; diff --git a/src/main.zig b/src/main.zig index 01a021c..3d74daa 100644 --- a/src/main.zig +++ b/src/main.zig @@ -66,13 +66,28 @@ pub fn main() !void { } map.cells.items[16 * 7 + 7] = level.Cell{ - .floor_height = 0.5, - .ceiling_height = 2.2, + .floor_height = 0.2, + .ceiling_height = 2, .lower_texture = 1, .upper_texture = 1, .floor_texture = 1, .ceiling_texture = 2, .draw_down = true, + .vertices = &[_][2]f32{ + .{ 0.00, 0.50 }, + .{ 0.25, 0.66 }, + .{ 0.25, 1.00 }, + .{ 0.50, 0.66 }, + .{ 0.75, 1.00 }, + .{ 0.75, 0.66 }, + .{ 1.00, 0.50 }, + .{ 0.75, 0.33 }, + .{ 0.75, 0.00 }, + .{ 0.50, 0.33 }, + .{ 0.25, 0.00 }, + .{ 0.25, 0.33 }, + .{ 0.00, 0.50 }, + }, }; try map.objects.append(level.Object{ .pos_x = 1.5, .pos_y = 7.5, .pos_z = 2, .texture = 2, .height = 1, .width = 1 }); diff --git a/src/render.zig b/src/render.zig index 0e68a93..2b3aef5 100644 --- a/src/render.zig +++ b/src/render.zig @@ -69,6 +69,10 @@ fn fasterColourBlend(onto: Colour, from: Colour) Colour { }; } +// 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. fn hitDistLocalCoords( ray0: [2]f32, ray1: [2]f32, @@ -76,10 +80,10 @@ fn hitDistLocalCoords( ) ?f32 { const rdy = ray1[1] - ray0[1]; const rdx = ray1[0] - ray0[0]; + const rdist = std.math.sqrt(rdx * rdx + rdy * rdy); var vp = vertices[0]; var crossp: f32 = rdy * (vp[0] - ray0[0]) - rdx * (vp[1] - ray0[1]); - var return_val: ?f32 = null; if (crossp == 0) { // hit a vertex exactly @@ -88,26 +92,28 @@ fn hitDistLocalCoords( return std.math.sqrt(dx * dx + dy * dy); } + var return_val: ?f32 = null; + var v : [2]f32 = undefined; + var cross: f32 = 0; var i: usize = 1; - var v = vertices[i]; - var cross: f32 = rdy * (v[0] - ray0[0]) - rdx * (v[1] - ray0[1]); - while (i + 1< vertices.len) : ({ - i += 1; + while (i < vertices.len) : ({ vp = v; - v = vertices[i]; crossp = cross; - cross = rdy * (v[0] - ray0[0]) - rdx * (v[1] - ray0[1]); + i += 1; }) { - if (cross == 0) { - const dx = v[0] - ray0[0]; - const dy = v[1] - 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; - } - } else { + v = vertices[i]; + 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]; + // 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; + // } + // } 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 @@ -117,8 +123,9 @@ fn hitDistLocalCoords( const vdx = v[0] - vp[0]; const vdy = v[1] - vp[1]; - const t = (vdx * (ray0[1] - v[1]) - vdy * (ray0[0] - v[0])) / (rdx * vdy - vdx * rdy); - const new_distance = std.math.sqrt(rdx * rdx + rdy * rdy) * t; + const t = (vdx * (ray0[1] - vp[1]) - vdy * (ray0[0] - vp[0])) / (rdx * vdy - vdx * rdy); + 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]; @@ -262,6 +269,7 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { }) { if (self.z_buffer[pix_index] > scaled_perp_distance) { const ty = @floatToInt(c_uint, texel_y); + // TODO: There's an out of bounds in the pixel access here ... const texel = objects_image.getPixel(.{ .x = toff + tx, .y = ty }); // TODO: Decide whether being accurate is as important as being fast pixels[pix_index] = fasterColourBlend(pixels[pix_index], texel); @@ -416,8 +424,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_distance| { - const adj_distance = distance + local_distance; + if (hitDistLocalCoords(ray0, ray1, cell.vertices)) |local_dist| { + // TODO: Correct for fisheye? + const adj_distance = distance + 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; @@ -428,14 +437,24 @@ 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 - var texfrac = if (hit_horizontal) ray0[0] else ray0[1]; + // 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; - // 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); // height of a unit-height wall at this distance |
