Sign in to follow this  

Raycasting

This topic is 3777 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all I am a complete rookie and this question is probably gonna confirm that beyond doubt! But it's been bugging me and I'm sure you all know the answer so here goes (please forgive the clumsy wording): I'm trying to code a simple raycasting game but can't seem to get it right. I have my grid-map set up and I cast the rays for wall boundaries, no problem. My rays return the perpendicular distance to any wall slices hit, no problem. My problem comes when I display the slices on the screen. The top of my walls to the side of the viewer don't appear straight, they start to curve. Now, I'm thinking that this makes sense since I'm using trig to calculate the distance to wall slices and trig functions are not linear. I have a couple of raycasting books and they don't seem to mention this. Am I missing something because I can't find anything on the web that mentions this? By the way, this has nothing to do with what they call the 'fisheye effect' as far as I can tell. The walls directly in front of the viewer are fine, it's just the walls to the left and right of the viewer. I can sense you all laughing at this question already (or am I just paranoid?!) since I've probably missed something basic, but please put me out of my misery as I can't see an easy solution apart from linear interpolating across a whole wall! many thanks for your time, jimi

Share this post


Link to post
Share on other sites
I'm no ray-casting master but AFAIK yuo cast your rays, get the texture for that
wall slice and draw a vertical line with the length depending on the distance.
That's how I see raycasting.
So I'm not sure how you got your walls curved...

Share this post


Link to post
Share on other sites
The fishbowl effect that you're seeing is normal with straight-forward trig calculations and needs to be corrected for.

If you think about it for a second, you'll see why this is: Imagine you are standing directly in front of a wall, say 5 feet away. now, imagine that you take a measuring tape and measure to a point on the wall 3 feet off-center from the portion of the wall directly in front of you. The distance to this point is just short of 6 feet, hence, that sliver of the wall is drawn smaller because it is believed to be further away. The distance you want to calculate is the distance from the wall to the plane perpendicular to the view vector.

If you use this distance, everything should appear fine, unless I've misunderstood and you are already accounting for this -- I'm not sure if thats what you mean by perpendicular distance or not.

Share this post


Link to post
Share on other sites
CableGuy

Thanks for replying.
It's the top of the walls that appear curved, not the individual vertical columns. Each column is vertical but the overall effect after displaying lots of them is that the top of the wall appears curved. I can see why this is but I don't know what to do about it.

Thanks
jimi

Share this post


Link to post
Share on other sites
Hi avyne2001

Thanks for reply.
I think I understand the fisheye effect and I'm pretty certain that my problem is not that. The walls directly in front of the viewer appear fine. It's only the walls off to the left and right side of the viewer that appear distorted.

Thanks
jimi

Share this post


Link to post
Share on other sites
Virtual,

Yes, it is one of the best tutorials I've seen. However, it doesn't address the issue I'm talking about. When it comes to displaying the wall columns, this, as do all the others I've seen, skims over the process. I'll try and explain my problem more clearly.

|
|
|
| x

Let's say that my viewer is as marked x in the above and the line to the left of him is a wall. Now, I cast out rays from the viewer to the wall, using a FOV of 120 deg (-60 deg to 60 deg). Let's say one of the rays is as below (the ray is the sloped line):

|/
| /
| /
----/x

Now, the distance from the viewer to the point of interception of the ray and the wall is (ray length) * cos (ray angle). I now divide the actual wall height with this distance to get the height of the column I need to display on the screen. Okay, so far so good. I need to cast out 800 of these rays, as my screen resolution is 800x600. This means that, with my FOV of 120 deg, I start with an angle of -60 deg and increment the angle by 0.15 deg in a loop until it reaches +60 deg. My problem is this: the angle is going up in equal steps (0.15 deg), i.e. linear, but the cosine function isn't, it's a curve. This means that the distribution of wall slice heights is not linear, and that as the angle gets bigger, the distance to the wall gets proportionally even bigger. This, of course, is gradual to begin with but does become noticeable after about sweeping rays for 20 deg. As I said earlier, this makes sense to me and I was just wondering if I am missing something. I've read over a number of tutorials on the topic but can't seem to find anything that addresses this issue. Maybe it only appears ok for smaller resolutions? Maybe it's only okay for a smaller FOV? I don't know. It is not the fisheye effect, which I have read about a lot.
Any help would be greatly appreciated.
Thanks for your time.

jimi

Share this post


Link to post
Share on other sites
This is quite hard to visualise using ASCII art, is there any chance you could take a screenshot of the problem and mark on it the areas that seem strange to you? Use some free hosting to upload the picture of course ;)

It's just that visual problems are usually best diagnosed visually :-D

Andy

Share this post


Link to post
Share on other sites
NineYearCycle

http://img3.freeimagehosting.net/image.php?0c1ba39539.jpg

The screenshot shows the wall to the left of the viewer and the wall in front. Notice the bottom and top of the wall to the left are curving slightly. This is my problem.

thanks
jimi

Share this post


Link to post
Share on other sites
I ran into a problem like this too. In my code, once I computed a ray/wall intersection point, I contructed a displacement vector from the wall back to the player. Then I took the length of that vector and used it to compute the height of the wall.

That was not the correct way to do it - the relevant length is the projection of displacement vector onto the camera heading normal (which, for a single frame, is a fixed vector and not dependent upon the ray angle. Just the camera angle). When I used that distance to compute the height, the walls popped out with straight lines.

Maybe you have a similar problem... just something to try out.

Share this post


Link to post
Share on other sites
Quote:
Original post by hendrix7
NineYearCycle

http://img3.freeimagehosting.net/image.php?0c1ba39539.jpg

The screenshot shows the wall to the left of the viewer and the wall in front. Notice the bottom and top of the wall to the left are curving slightly. This is my problem.

thanks
jimi


That's quite bizarre, it actually looks as though rays cast are coming from a point in front of your camera. Have you verified that the rays origin is correct?

Andy

Share this post


Link to post
Share on other sites
Quote:
Original post by ravyne2001The distance you want to calculate is the distance from the wall to the plane perpendicular to the view vector.


Quote:
Original post by hendrix7Let's say that my viewer is as marked x in the above and the line to the left of him is a wall. Now, I cast out rays from the viewer to the wall, using a FOV of 120 deg (-60 deg to 60 deg). Let's say one of the rays is as below (the ray is the sloped line):

Now, the distance from the viewer to the point of interception of the ray and the wall is (ray length) * cos (ray angle).


It sounds like you are calculating your Ray from the camera position to the object. As Ravyne pointed out, that is incorrect, and probably what is causing your round walls. Your Ray should be cast through an image plane perpendicular to your camera.

Like this:


image
plane
|
| |------|
camera-> |>-----ray------->|object|
| |------|
|


So basically:

- pixel 0,0 is calculated by Ray sent through the top corner of your image plane
- for each successive pixel X,Y you increment the position on the image plane though which the ray is cast by image_width/x and image_height/y.

Quote:
Original post by hendrix7I now divide the actual wall height with this distance to get the height of the column I need to display on the screen.


In normal ray-traying each pixel is handled separately, not sure what you mean by columns of vertical pixels. Usually you:

- cast ray through pixel X,Y of the image plane
- intersect ray with all world objects
- if it intersects with something, get the position of intersection with the object, normal, color, texture, etc.

I suppose the vertical column thing would work in a world where all surfaces were flat, perpendicular to the camera, and nothing occluded any other object.

Share this post


Link to post
Share on other sites
Flippy, the OP is ray-casting, not ray-tracing. Ray-casting is the 3D technique used in early 3D PC games such as Wolfenstien, and later in more advanced forms such as Doom or Duke Nukem 3D. Drawing is based on vertical slivers, rather than individual pixels.


hendrix, there are a few things that concern me. Firstly, a viewing angle of 120 degrees is really, really wide for this sort of thing. Something in the 60-90 degree range is more typical.

Secondly, I remain 95% certain that you are indeed seeing the fishbowl effect I've described after looking at your screen-shot. However, there is something else at hand as well -- because the wall slivers should be getting *smaller* near the edges, rather than larger. I suspect that you have an unintended negative (or positive that should be negative) somewhere in your calculation, your math is definitely wrong.

As has been said, and as I tried to explain before, the distance you want to use is the projection of the casted vector onto the view vector. A quick thought exercise should confirm this in your mind -- if we have a casted ray, given as a vector from the point of origin, and the view vector given as a vector perpendicular to the plain of origin, then the projection of any ray to a point on a plain (the wall) that is parallel the plain of origin (eg - you're looking at the wall straight-on) onto the view vector has the same magnitude (gives the same projected distance) and hence, will scale the same (the top and bottom edges of your walls will be straight).

Share this post


Link to post
Share on other sites
It's the fisheye effect. Try adjusting the length of the ray by multiplying it by the cosine of the angle it was cast after you've cast it. You should change nothing about how you're calculating anything so far; just add the cosine adjustment to your wall height.

* Edit : maybe that's wall height * (1 + cos(angle)) ...

Share this post


Link to post
Share on other sites
Thanks everyone for your replies, really appreciate you trying to help me out.
I believe the raycasting process only works well within a certain range of FOV, as you say ravyne, because trig functions are not linear. This has nothing to do with the fisheye effect as I am adjusting for this distortion already. I've changed my FOV from 120 deg to 60 deg and my walls now appear ok.

screenshot:
http://img3.freeimagehosting.net/image.php?9535f9487b.jpg

I think I'll stick to this FOV from now on!
Thanks again everyone for your help.

jimi

Share this post


Link to post
Share on other sites

This topic is 3777 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this