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