diff options
| -rw-r--r-- | src/raycast.zig | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/src/raycast.zig b/src/raycast.zig index 20597e9..1f1fd7f 100644 --- a/src/raycast.zig +++ b/src/raycast.zig @@ -54,7 +54,8 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { const PlanePixels = PlaneWidth * PlaneHeight; // given the desired width of the image, how far away must // the projection plane be from the camera? - const PlaneDist = PlaneWidth / (2 * std.math.tan(FOV / 2)); + const FOV_SCALE = 2 * std.math.tan(FOV / 2); + const PlaneDist = PlaneWidth / FOV_SCALE; // standing still at the given location, looking in direction ang, pub fn new(pos_x: f32, pos_y: f32, ang: f32) !@This() { @@ -131,25 +132,34 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { for (map.objects.items) |obj| { const ox = obj.pos_x - self.pos_x; const oy = obj.pos_y - self.pos_y; - // we compute the two coordinates of rotating by -self.ang, the + + // We compute the two coordinates of rotating by -self.ang, the // first of which gives the perpendicular distance to the plane // of projection, and the second of which gives the // (unprojected) centre of the object. const perp_distance = self_cos * ox + self_sin * oy; const centre = self_sin * ox - self_cos * oy; + + // NOTE: in the below we have applied the magic scaling factor + // of FOV_SCALE. I don't understand how this compensates for the + // linear interpolation incorrectness we do elsewhere, but + // somehow it scales the *correct* values we compute above into + // whatever agrees with the wall and floor rendering voodoo. + + // This quantity is independent of FOV_SCALE because it enters + // both via centre and perp_distance const proj_centre = PlaneWidth / 2 + PlaneDist * centre / perp_distance; - const width = PlaneDist * obj.width / perp_distance; + // Here's the magic adjustment + const scaled_perp_distance = FOV_SCALE * perp_distance; + const width = PlaneDist * obj.width / scaled_perp_distance; const left = proj_centre - width / 2; // TODO: prune before this? if (left + width < 0 or left >= PlaneWidth) continue; - // TODO: Here's another fudge factor. I think this is something - // like the floors and walls aren't actually distance correct, - // so we have to toy with these exact calculations to fix it. - const height = PlaneDist * obj.height / perp_distance; - const top = PlaneHeight / 2 + PlaneDist * (obj.height + 0.2 - self.height) / perp_distance; + const height = PlaneDist * obj.height / scaled_perp_distance; + const top = PlaneHeight / 2 + PlaneDist * (obj.height - self.height) / scaled_perp_distance; // TODO: likewise? if (top < 0 or top - height >= PlaneHeight) continue; @@ -166,12 +176,9 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { tex_frac += tex_frac_step; }) { var bottom = std.math.min(top, PlaneHeight); - while (bottom > 0 and bottom > top - height) : (bottom -= 1) { + while (bottom >= 0 and bottom >= top - height) : (bottom -= 1) { const index = @intCast(usize, col * @floatToInt(i32, PlaneHeight) + @floatToInt(i32, bottom)); - // TODO: what is this fudge factor? Is this again - // because distances aren't actually correct in the - // z_buffer but they are in this computation? - if (self.z_buffer.get(index) < perp_distance + 1) { + if (self.z_buffer.get(index) < scaled_perp_distance) { bottom += 1; break; } |
