Alright been coding this crazy voxel thing for some time now, among other projects. Two or three algo's have stood out.
Both of these algos wrap the ray world coords to the edge of the world, thus the world repeats itself giving a continuous landscape.
The 3D matrix idea does not repeat since all you are doing is drawing vertexes at set points in screen space based on x,y,z of voxel - (x*viewdist)/z+halfvertres; (y*viewdist)/z+halfres; where viewdist is distance you are from the screen - flattens projection.
Floating horizon
First is the floating horizon. Basically start at the player's world coords and raycast through 60 degrees across the world map.
Divide the world coords by the cellsize of the word. Find out how far into the cell we are. Extract 4 values from the height map -x,y; x+1,y; x,y+1, x+1,y+1. Perform a bilinear interpolation to find out altitude for where the ray is inside the cell. Perform the same for the color value. If the height is less than the previous height (in a variable, starts at bottom of screen) then draw a gouraud interpolated line from lasty to currenty. Repeat for distance iterations, increment angle by angle increment for screen (.1875 for 320, .09375 for 640, 60/horzres) and repeat the process through 60 degrees.
Benefits
- Terrain looks excellent
- Cellsize does not matter - bilinear creates hills not blocks
- Color is bilinear and linear from bottom to top which looks great.
- Raylength is not totally accurate since dist is just incremented
- Very fast
Problems
- Does not allow you to 'see' very far into the distance.
- Bi-linears are very slow if not done in assembly (DJGPP flags errors on assembly - REG class not found or something - even on downloaded examples - don't know why?)
- Almost has to be run in 16 or 24 bit mode due to the amount of colors required for blending
Texture-mapped floating horizon
This is the same process except that instead of drawing column by column, you draw one row at a time from left to right. Find leftangle and rightangle, rotate ray into position to get samples of each. Subtract rightray from leftray and divide by screen horzres to find increment value for ray. Find ray distance
COR[i]*(Player.Height*Player.ViewDist)/(Player.ViewDist-RowInvert)
COR[] -> Sine correction for fisheye sin(90-angle) as angle moves from -30 to +30 degrees. Way better than cosine correction.
Player.Height -> Player's height
Player.ViewDist -> How far up the screen we can see
RowInvert -> BottomOfScreen-CurrentRow - so at bottom rowinvert would be 0, bottom-1 would be 1, etc. Increments.
Benefits
- View depth
- Compact algo - less code than above
- Linear interpolation of angles
Problems
- Can cause divide by zero if you are not careful - since dividing by (Player.ViewDist-RowInvert) If ViewDist is 120 then divide by zero will happen at row bottom-120. Not good.
- No bilinear height or color, but w/o is is still far slower than floating horizon algo.
- Way too many divides - Need another way like using a FloorDistance[] table or something instead of (Player.ViewDist-RowInv).
- Very ugly in the distance - extremely ugly in the distance.
- Much harder to do bilinear and to draw linear interpolated heights
- Very slow
Obviously the first choice has more benefits. But it has to have more view depth. Doubleanti, see if you can use the top algo but find a way to get me the correct distance. Notice my distance is just an integer increment, not taking into account the height of the viewer. Really need 6 degrees of freedom, too. Don't think this algo can do it.
The 3D raycasting algo was very slow (using dry=-tan(VFOV/2)).
Not even an option w/o DirectX or something for realtime rendering.
The 3D package - using matrices tracking the point of the voxel. Draw blocks instead of points VoxelSize*ViewDist/VoxelZ is very fast, but you can see where the world ends - don't know how to repeat landscape using 3D methods. Also 6 degrees of freedom is very easy.
I know this is long, but did not know how to post it any different. This will take some time to look at. If you have any questions, just PM me. If you need some code I have it for about 4 algos. Thought it might be more confusing than just explaining algos so did not attach it. Maybe we could come up with an algo that incorporates both of these together - viewdistance, acceptable visual quality, and speed.