GP32 Voxel Render!


synkro

0xdeadbeef
Joined
Aug 26, 2003
Messages
823
Location
Germany
Website
Visit site
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<320); 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!

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
  }
}
 
ok it wokr snow for me... the weird picture ist because of the missinh scaling.. the inly thing that bugs me are some single line on the right.. must be rounding issues...
 
Back
Top