# comp.graphics.algorithms

## Subject: Re: Understanding raytracing code

On Mon, 15 May 2006 19:54:12 GMT, john wrote:

>This code will generate a "hole" that is mapped with a texture.
>The resolution is 320x200. And I see that the code loops through
>every pixel, and calculates some map that will be stored in
>textcoord. But I don't understand how the hole is created. So
>I would really appreciate if someone could explain this for me.
>Thanks!

Starting at beginning of the loop:

float dx = (float)i / 200;
float dy = (float)-j / 200;
float dz = 1;

Here it computes the direction of a ray originating somewhere behind
the image, centered in the x, y plane. Imagine if you could look at
each pixel of the screen, this code gets the direction towards each
pixel (in turn). I'll call this the view vector.

float d = 20 / sqrt(dx*dx + dy*dy + 1);
dx *= d;
dy *= d;
dz *= d;

The comment for the above code is a bit missleading, as it does not
normalize the view vector to unit length, but to a length of 20. More
on that in a bit.

// continue until we hit a wall
while (((x-get_x_pos(z))*(x-get_x_pos(z))+(y-get_y_pos(z))*
(y-get_y_pos(z)) < get_radius(z)) && (z<1024)) {
x += dx;
y += dy;
z += dz;
}

Here's the meat of the thing. It starts out in the origin (ala the
position of you eyes), and then moves in the direction of the view
vector, each step the same length as the length of the view vector.

Now, the assumtion here is that the origin is located inside the
cylinder you're viewing, and that the cylinder is aligned along the z
direction. Now, this cylinder is basically a bunch of circles stacked
on top of each other. The walls of the cylinder is defined by the
circle.

Now, to find out if you're inside a circle, all you need to do is
compute the distance from you to the center of the circle, basic
pythagoras: sqrt(sqr(px-cx)+sqr(py-cy)) if (px, py) is your current
position and (cx, cy) is the center of the circle. If this distance is
less than the radius of the circle, you're inside.

This is what the above code does. The code allows for the center of
the circle to vary as a function of z, so it gets the center for the
current z value. Then it subtracts the current (x, y) position from
this and squares.

Now, since it doesnt actually USE the distance to the center directly,
only to compare, it doesn't have to compute the square root. If
sqrt(a) < b, square both sides and you get a < b^2 (since a is always
positive).

It then gets the radius for the current z value (which would then
actually be the radius squared), and checks if the current position is
inside the circle at the current z position. It also makes sure that
the z value is not larger than the length of the cylinder.

The pseudo code for the above block would be something like:

while (inside circle at this z && not beyond length of cylinder) {
move in the direction of the view vector,
by the lenght of the view vector
}

Now, once this while loop is done, its either outside the cylinder
walls or beyond the end of the cylinder.

x -= dx; dx /= 2;
y -= dy; dy /= 2;
z -= dz; dz /= 2;
d -= 1;

So what it does then is to undo the last step by moving back, and then
make the view vector length half of its previous value. This makes it
move half the distance in the while loop above. It also decreases a
counter which keeps track of how many such undo's it's allowed to
make. This is to prevent it from going on forever (as the dx/2 etc
could eventually become 0 and it wouldn't go anywhere, becomming stuck
outside the walls).

Once it has done this 16 times, it's bound to be fairly close to the
cylinder wall (as you started out with a steplength of 20, and it has
been halved 16 times, the last steps would be about 0.0003)

x -= get_x_pos(z);
y -= get_y_pos(z);
float ang = atan2(y, x) * 256 / M_PI;
unsigned char u = (unsigned char)ang;
unsigned char v = (unsigned char)z;

Here it makes (x, y) relative to the center of the circle for the
current z value, and uses trigonometry to compute the angle to the
current position. The angle is used as one texture coordinate and the
z as the other. The result is as if you had wrapped a picture around
the cylinder.

It then stores the texture coordinates for each pixel in an array,
which i presume it uses later to draw the texture onto the screen.

Hope it helps

- Asbjørn