Raycasting Fisheye Error

For a bit of fun I decided to create a 2.5D raycasting engine, it works well, however when I attempt to remove the fisheye effect with Math.cos in this line of code:

dist * Math.cos(Math.toRadians((angleOfRay * angleBetweenRays) - (fov / 2.0)));

It causes a weird distortion in the height of the walls, it appears to slightly over compensate for the fisheye effect.

The entire class is accessible here: https://www.dropbox.com/s/nuhol52mm95lm7p/Source.txt

Screenshots:

If this error is totally unsolvable from the information provided, would anyone be able to show me any good raycasting tutorials besides this one http://www.permadi.com/tutorial/raycast/ ?

there is a great write up on why this happends in raycasting…

the good news is you are doing it correctly if your getting this.
the bad news is you need to implement a correction prior to drawing if you want a nice square image.

If i find the write up ill post it here later tonight.

If i recall properly you need to adjust the height of everything to a constant to correct the fisheye effect.

Thanks for your help, it would be great if you were able to find that article.

I found the error, it was actually due to the inaccurate method in which I detected the collision of a ray with a wall
Just in case any one else encounters the same error, here is the corrected code snippet, (it’ll probably be incomprehensible, but it’s better than nothing).

boolean rayHitHorizontalSide= hitHorizontalSide(x2, y2, sourceX, sourceY);
				if (rayHitHorizontalSide) {
					double rise =(Math.floor(y2/wallSize)*wallSize - sourceY);
					double run = rise/vy * vx;
					dist = Math.sqrt(run*run + rise*rise);
					
					rise =(Math.floor(y2/wallSize)*wallSize+wallSize - sourceY);
					run = rise/vy * vx;
					if(Math.sqrt(run*run + rise*rise) < dist)
						dist = Math.sqrt(run*run + rise*rise);
				} else {
					double run = (Math.floor(x2/wallSize)*wallSize - sourceX);
					double rise = run/vx * vy;
					dist = Math.sqrt(run*run + rise*rise);
					
					run = (Math.floor(x2/wallSize)*wallSize+wallSize - sourceX);
					rise = run/vx * vy;
					if(Math.sqrt(run*run + rise*rise) < dist)
						dist = Math.sqrt(run*run + rise*rise);
				}
 				boolean rayHitHorizontalSide= hitHorizontalSide(x2, y2, sourceX, sourceY);
 				if (rayHitHorizontalSide) {
 					double rise =(Math.floor(y2/wallSize)*wallSize - sourceY);
 					double run = rise/vy * vx;
-					dist = Math.sqrt(run*run + rise*rise);
+					dist2 = (run*run + rise*rise);
 					
-					rise =(Math.floor(y2/wallSize)*wallSize+wallSize - sourceY);
+					rise += wallSize;
 					run = rise/vy * vx;
-					if(Math.sqrt(run*run + rise*rise) < dist)
+					if((run*run + rise*rise) < dist2)
 						dist2 = (run*run + rise*rise);
 				} else {
 					double run = (Math.floor(x2/wallSize)*wallSize - sourceX);
 					double rise = run/vx * vy;
-					dist = Math.sqrt(run*run + rise*rise);
+					dist2 = (run*run + rise*rise);
 					
-					run = (Math.floor(x2/wallSize)*wallSize+wallSize - sourceX);
+					run += wallSize;
 					rise = run/vx * vy;
-					if(Math.sqrt(run*run + rise*rise) < dist)
+					if((run*run + rise*rise) < dist2)
 						dist2 = (run*run + rise*rise);
 				}
+				dist = Math.sqrt(dist2);

You might very well get rid of most, if not all square root calculations.

Thanks, I’ll remember to do that in future projects too.