Skip to content

Fisheye fix

Vinicius Reif Biavatti edited this page Apr 15, 2021 · 20 revisions

Distorted view

After we implemented the RayCasting and ran the code, we could check that the walls of the projection were distorted. This occurs because the method to throw the ray that we used starts from player, so the side rays will be more distant then the middle rays. This effect is called Fisheye. To corret it, we need to translate the distance of the rays removing the distorted distance in relation of the player. Check the image below for understand:

Coparing of the fisheye and normal view

Based of the first example, we can see the right triangle between player position and wall position. The value of the angles needs to be processed to get the correction of the distorted distance. To make it, we can use trigonometry to find the value. Looks the image below:

SOH CAH TOA trigonometry formulas

The view to the wall collision is a right triangle. The wrong distance is the "hypotenuse", the angle is the angle ray, and the correct distance is the adjacent side (that we need to discover). We have the hypotenuse value and the angle, so we can check the trygonometry formulas to try to find the value we want. Checking the SOH CAH TOA formulas, we conclude that we can use the CAH (cosine) formula). For this example, I used some fictitious values.`

hypotenuse = 10
angle = 30
adjacent_side = x

// Formula
COS(angle) = adjacent_side / hypotenuse

// Changing formula to solve the problem
COS(angle) = adjacent_side / hypotenuse
COS(angle) * hypotenuse = adjacent_side / hypotenuse * hypotenuse // (Add multiplier)
COS(angle) * hypotenuse = adjacent_side // (Remove redundant)
adjacent_side = hypotenuse * COS(angle) // Right!

NOTE: Remmember to use angles as radians, not arcs (degrees)!

Demonstration of ray casting with distorted view and correct view

For it, we can use this formula:

Formula: distance = distorted distance * Math.cos(ray angle - player angle)

This formula will be applied after get the distance in rayCasting() function. The code will be:

// ...

// Pythagoras theorem
let distance = Math.sqrt(Math.pow(data.player.x - ray.x, 2) + Math.pow(data.player.y - ray.y, 2));

// Fish eye fix
distance = distance * Math.cos(degreeToRadians(rayAngle - data.player.angle));

// Wall height
let wallHeight = Math.floor(data.projection.halfHeight / distance);

// ...

After this fix, you can check the result running the code fixed.

Clone this wiki locally