synkro
0xdeadbeef
Hi there!
I am am currently working on a voxel renderer but I have serious problems, I
hope someone can help me. The point is that I don't see what I espect to see,
on the top left is a topview map of the height map(8bit). Black is low and
bright blue is high; the height is negative;
y
| /Z
| /
|/
------ X
I cast a ray for every screen coloumn (0<=x
20); The Field Of View is 60°
so 60/320 degree per ray. the increments of the ray are:
x-axis inc_x = 1*cos(angle of ray) z-axis inc_z = 1*sin(angle of ray)
with those i can calculate the current voxel on the height map.
I draw the highest voxel from bottom to top (remember height is negative).
The redpoint is the ViewPoint position
movement un the map : Stick
rotate left/right: L and R
move up and down: A and B
simulate look up/down: Start and Select
at the moment it is not optimized (fixed math, LUTs...) and runs with ~1fps.
anyway I expect to see a small hill/pyramid like thing on the right, but it's
not. maybe some can find the error. Any comment, critics, speed up ideas are
welcome, an already compiled FXE and full source is in the ZIP. THX!
I am am currently working on a voxel renderer but I have serious problems, I
hope someone can help me. The point is that I don't see what I espect to see,
on the top left is a topview map of the height map(8bit). Black is low and
bright blue is high; the height is negative;
y
| /Z
| /
|/
------ X
I cast a ray for every screen coloumn (0<=x
so 60/320 degree per ray. the increments of the ray are:
x-axis inc_x = 1*cos(angle of ray) z-axis inc_z = 1*sin(angle of ray)
with those i can calculate the current voxel on the height map.
I draw the highest voxel from bottom to top (remember height is negative).
The redpoint is the ViewPoint position
movement un the map : Stick
rotate left/right: L and R
move up and down: A and B
simulate look up/down: Start and Select
at the moment it is not optimized (fixed math, LUTs...) and runs with ~1fps.
anyway I expect to see a small hill/pyramid like thing on the right, but it's
not. maybe some can find the error. Any comment, critics, speed up ideas are
welcome, an already compiled FXE and full source is in the ZIP. THX!
Code:
/****************************************
* Voxel Demo
* MirkoSDK 0.8.5
* 24.07.2004 10:53:52 by synkro
*/
#include "gp32.h"
#include "math.h"
#include "voxel.h"
#define WIDTH 320 // screen resolution
#define HEIGHT 240
#define MAP_H 100 // size of the height map
#define MAP_W 100
extern const unsigned char hmap[];
int main(void) {
// init viewpoint
float vp_x = 0, // viewpoint position (x,y,z)
vp_y = -250,
vp_z = 50,
vp_angle = 0.0, // direction (y axis)
vp_FOV = 1.04719755; // Field of View 60°
// init renderer
int ray; // ray to cast
float ray_angle, // angel of the current ray
inc_ray_angle, //
inc_x, inc_z, // ray increment steps
pos_x, pos_z, // position of the current voxel at map
screen_dist; // distance from vp to screen
int vx_height, // height of the currenz voxel
vx_highest; // heighest voxel
float vx_dist, // distance from the vp to the voxel
inc_vx_dist; //
int out_mid; // middle of the output
int i;
// show mao
float px, pz, py;
int highest = HEIGHT;
// init gp32
initGp(GP32RGB(16,16,16), 133, 50);
// precalc render
inc_ray_angle = vp_FOV / WIDTH; // angle between every ray
out_mid = HEIGHT/2; // middle of the screen at 120
//out_mid = -100;
//screen_dist = (int)((WIDTH/2) * tan(vp_FOV/2));
screen_dist = 50; // shorter distance makes you see more
// main loop
while(1)
{
gp_clearFramebuffer16(framebuffer[nflip], GP32RGB(16,16,16));
// ray cast
ray_angle = (vp_angle - (vp_FOV/2)); // first ray at 0 (left)
for(ray=0; ray<WIDTH; ray++)
{
inc_x = cos(ray_angle); inc_z = sin(ray_angle); // step on the grid (polar ->cart)
pos_x = vp_x; pos_z = vp_z; // starting point is viewpoint position
vx_dist = inc_vx_dist = cos(ray_angle - vp_angle); // distance from the first voxel to the viewpoint
vx_highest = HEIGHT; // start at ground = 240
while(pos_x>=0 && pos_x<MAP_W && pos_z>=0 && pos_z<MAP_H)
{
i = (int) pos_x + pos_z * MAP_W; // index on the heightmap
// vx on screen = ((vx height - vp height) * screen distance / vx distance)) + middle of screen
vx_height = ((-hmap[i] - vp_y) * screen_dist / vx_dist) + out_mid;
if(vx_height<vx_highest) // if current vx is higher draw it
{
gp_drawLine16(ray, vx_height, ray, vx_highest, (u16)hmap[i], framebuffer[nflip]);
if(vx_height<0) break;
vx_highest = vx_height - 1;
}
pos_x += inc_x; pos_z += inc_z; // next voxel
vx_dist += inc_vx_dist;
}
ray_angle += inc_ray_angle; // next ray
}
// draw map (top view)
for(px=0; px<100; px++)
{
for(pz=0; pz<100; pz++)
{
i = (int) px + pz * 100;
py = hmap[i];
gp_drawPixel16 ((int)px, (int)pz, (u16)hmap[i], framebuffer[nflip]);
}
}
// vp posizion on map
gp_drawPixel16 ((int)vp_x, (int)vp_z, GP32RGB(30,0,0), framebuffer[nflip]);
// button input
if(gp_getButton() & BUTTON_RIGHT) vp_x += 5;
if(gp_getButton() & BUTTON_LEFT) vp_x -= 5;
if(gp_getButton() & BUTTON_UP) vp_z -= 5;
if(gp_getButton() & BUTTON_DOWN) vp_z += 5;
if(gp_getButton() & BUTTON_A) vp_y += 5;
if(gp_getButton() & BUTTON_B) vp_y -= 5;
if(gp_getButton() & BUTTON_L) vp_angle -= 0.04;
if(gp_getButton() & BUTTON_R) vp_angle += 0.04;
if(gp_getButton() & BUTTON_START) out_mid += 5;
if(gp_getButton() & BUTTON_SELECT)out_mid -= 5;
if(vp_x<0) vp_x = 0;
if(vp_z<0) vp_z = 0;
if(vp_x>100) vp_x = 100;
if(vp_z>100) vp_z = 100;
// info on screen
char string[33];
sprintf(string, "VP: x %.2f y %.2f z %.2f ", vp_x, vp_y, vp_z);
gp_drawString (1, 232, 33, string, GP32RGB(30,30,30), framebuffer[nflip]);
sprintf(string, "VP: angle %.2f (y) outMid %i (x)", vp_angle, out_mid);
gp_drawString (1, 224, 33, string, GP32RGB(30,30,30), framebuffer[nflip]);
// flip between work and show framebuffer
FLIP_BUFFER
}
}