scene.org File Archive

File download

<root>­/­mirrors­/­the_scene_archives­/­The_Scene_Archives_Vol_05­/­Disks_are_in_Here­/­Disks_4801_To_4851­/­4806-No_Sense_2­/­Articles/voxel.txt

File size:
3 971 bytes (3.88K)
File date:
2005-01-22 23:20:16
Download count:
all-time: 579

Preview

\I[Voxel Landscapes - 2D and 3D|By Scout/C-Lous|Section: Coders Pool]

\F2\4\MVoxel Landscapes
\M- Flying around...
\F1\2
\C[ClipArts/pinnen.Chnk]

This text assumes that a normal coordinate system has the X axis going to the right, the Y axis going up, and the Z axis going into the screen. It also assumes that the screen used is a LORES 320x256 one with 2x2 C2P conversion, yielding an effective resolution of 160x128.

The basic idea of a voxel landscape is having a world built up of a lot of vertical bars, where each bar begins very far down and has its height stored in a table. Each bar also has its own, unique colour (preferably stored in a colour-table). You have the bars ordered along a quadratic grid. Another way of thinking of this is that you have laid a grid over a perfect, super-resolution original world and read one 'sample' from every square in the grid and stored them in the y-array and the c-array. 

Now you have the height and colour of every vertical bar. If you want to display the voxel landscape on an SGI, you 3d-rotate, perspective project and draw all the bars.

Unfortunately 99% of the readers of this mag do not have enough cash for the SGI, so it is time to develop simplified, approximative, maybe more restricted models of the 3d voxelspace that even run smoothly on our beloved Amigas...

One of the favourite approaches is called 'raycasting'. It is used in most Wolfenstein clones as well. The idea behind raycasting is to determine the contents of the screen by casting rays and checking what they hit, thus calculating "which bar(s) will I see on these pixels?" for all pixels (or groups of pixels), as opposed to rotating/projecting/drawing all bars, thus calculating "which pixel(s) will this bar cover?" for all bars.

\F2\1\MY-rotating landscape
\F1\2We begin with a rotating voxelspace where you can rotate around the Y axis but you always look horizontally.

When drawing the voxelspace, you will consider the screen a set of vertical stripes. Every stripe is a screen-high and extremely narrow "window" into the world. You shoot one ray (horizontally) through every stripe and draw the bars they hit. 

In what direction(s) shall you shoot the ray(s)? You have an FOV (Field of Vision) of approx. 180 degrees. That means you can see things in an 180 degree field in front of you (From -90 to +90 degrees relative to your current facing angle). The screen acts like a 'window' into the world and it therefore looks good with an FOV of about 60 degrees in the
voxelspace. Therefore you should fire the rays, evenly distributed, in the field -30 to +30
degrees relative to your current facing angle.

When you fire a ray, start from your current position and set the value of a "last Y-coord"-variable to the Y-coord at the bottom of the screen. Then repeat this process "Z-depth of landscape" number of times: Move 1 unit in the direction of the ray, read the Y and C of the bar you are currently on and perspective project the Y-coord (remember that Z increases 1 per step along the ray). Check if this Y-coord is less than "last Y-coord". If it is not, the current bar is not visible, so skip to the beginning of the loop. If it is, draw a vertical line from Y-coord to "last Y-coord" using colour C, set "last Y-coord" to the value of Y-coord and skip to the beginning of the loop.

If we name the XY axes in the voxeltables 'UV' to avoid confusion with screen XY coordinates, pseudocode for the voxelrout could look like this:

\F3\2;eyeU, eyeV and eyedir are variables containing current UV and direction
;persp is perspective-constant. 30 or so may look good
\3raydir = eyedir + 30
raydirinc = -60 / scrwidth
for X = 0 to scrwidth do
{
  lastY = scrheight
\2;lastY = bottom of screen
\3  U = eyeU;
\2;Start at eye position
\3  V = eyeV;
  Uinc = cos(raydir)
\2;Stepsize along U
\3  Vinc = -sin(raydir)
\2;Stepsize along V
\3  For Z = 1 to zdepth do

\F1\3\M \S[Articles/voxel2.txt]\2\3Press this line to continue!