aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/level.zig12
-rw-r--r--src/main.zig19
-rw-r--r--src/render.zig75
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