Advertisement
Guest User

NewVox TI-Nspire

a guest
Jun 24th, 2012
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.97 KB | None | 0 0
  1. /*
  2.    Landscape rendering
  3.  
  4.    Ok.. i know that voxel is something else... but a lot of people is using
  5.    the name "voxel" to mean this kind of rendering tecnique.
  6.    I wrote this to explain the basic idea behind the rendering of newvox4;
  7.    newvox4 is very badly written (it's named 4 because is the fourth of
  8.    a sequel of experiments) and is coded in pascal + asm.
  9.    Since i got a few request of an explanation i decided to write the kernel
  10.    of the rendering in C hoping that this will be easier to understand.
  11.    This implements only the base landscape (no sky or floating ball) and
  12.    with keyboard only support but i think you can get the idea of how I
  13.    implemented those other things.
  14.  
  15.    I'm releasing this code to the public domain for free... and as it's
  16.    probably really obvious there's no warranty of any kind on it.
  17.    You can do whatever you want with this source; however a credit in any
  18.    program that uses part of this code would be really appreciated :)
  19.  
  20.    Any comment is welcome :)
  21.  
  22.                                     Andrea "6502" Griffini, programmer
  23.                                            agriff@ix.netcom.com
  24.                                         http://vv.val.net/~agriffini
  25. */  
  26. #include <fdlibm.h>
  27. #include <SDL/SDL.h>
  28.  
  29. #define TWOPI (2.0 * M_PI)
  30.  
  31. typedef unsigned char byte;
  32. float altitude = 30.0f;
  33. const int view_dist = 200;
  34. int auto_height = 1;
  35.  
  36. byte HMap[256*256];      /* Height field */
  37. byte CMap[256*256];      /* Color map */
  38. byte Video[320*240];     /* Off-screen buffer */
  39.  
  40. /* I know this is not the way to efficiently do it, please don't kill me */
  41. #define lookup_size 32768
  42. double cos_table[lookup_size];
  43. double sin_table[lookup_size];
  44. const double luscale = lookup_size / TWOPI;
  45.  
  46. /* Reduces a value to 0..255 (used in height field computation) */
  47. int Clamp(int x)
  48. {
  49.   return (x<0 ? 0 : (x>255 ? 255 : x));
  50. }
  51.  
  52. void calculate_tables(void) {
  53.   int i;
  54.   double angle = 0.0;
  55.   for (i = 0; i < lookup_size; ++i) {
  56.     sin_table[i] = sin(angle);
  57.     cos_table[i] = cos(angle);
  58.     angle += TWOPI / lookup_size;
  59.   }
  60. }
  61.  
  62. double get_sin(double rad) {
  63.   rad = rad - TWOPI * floor(rad / TWOPI);
  64.   return sin_table[(int)(rad * luscale)];
  65. }
  66.  
  67. double get_cos(double rad) {
  68.   rad = rad - TWOPI * floor(rad / TWOPI);
  69.   return cos_table[(int)(rad * luscale)];
  70. }
  71.  
  72. unsigned int lfsr113(void)
  73. {
  74.    static unsigned int z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345;
  75.    unsigned int b;
  76.    b  = ((z1 << 6) ^ z1) >> 13;
  77.    z1 = ((z1 & 4294967294U) << 18) ^ b;
  78.    b  = ((z2 << 2) ^ z2) >> 27;
  79.    z2 = ((z2 & 4294967288U) << 2) ^ b;
  80.    b  = ((z3 << 13) ^ z3) >> 21;
  81.    z3 = ((z3 & 4294967280U) << 7) ^ b;
  82.    b  = ((z4 << 3) ^ z4) >> 12;
  83.    z4 = ((z4 & 4294967168U) << 13) ^ b;
  84.    return (z1 ^ z2 ^ z3 ^ z4);
  85. }
  86.  
  87. /* Heightfield and colormap computation */
  88. void ComputeMap(void)
  89. {
  90.   int p,i,j,k,k2,p2;
  91.  
  92.   /* Start from a plasma clouds fractal */
  93.   HMap[0]=128;
  94.   for ( p=256; p>1; p=p2 )
  95.   {
  96.     p2=p>>1;
  97.     k=p*8+20; k2=k>>1;
  98.     for ( i=0; i<256; i+=p )
  99.     {
  100.       for ( j=0; j<256; j+=p )
  101.       {
  102.     int a,b,c,d;
  103.  
  104.     a=HMap[(i<<8)+j];
  105.     b=HMap[(((i+p)&255)<<8)+j];
  106.     c=HMap[(i<<8)+((j+p)&255)];
  107.     d=HMap[(((i+p)&255)<<8)+((j+p)&255)];
  108.  
  109.     HMap[(i<<8)+((j+p2)&255)]=
  110.       Clamp(((a+c)>>1)+(lfsr113()%k-k2));
  111.     HMap[(((i+p2)&255)<<8)+((j+p2)&255)]=
  112.       Clamp(((a+b+c+d)>>2)+(lfsr113()%k-k2));
  113.     HMap[(((i+p2)&255)<<8)+j]=
  114.       Clamp(((a+b)>>1)+(lfsr113()%k-k2));
  115.       }
  116.     }
  117.   }
  118.  
  119.   /* Smoothing */
  120.   for ( k=0; k<3; k++ )
  121.     for ( i=0; i<256*256; i+=256 )
  122.       for ( j=0; j<256; j++ )
  123.       {
  124.     HMap[i+j]=(HMap[((i+256)&0xFF00)+j]+HMap[i+((j+1)&0xFF)]+
  125.            HMap[((i-256)&0xFF00)+j]+HMap[i+((j-1)&0xFF)])>>2;
  126.       }
  127.  
  128.   /* Color computation (derivative of the height field) */
  129.   for ( i=0; i<256*256; i+=256 )
  130.     for ( j=0; j<256; j++ )
  131.     {
  132.       k=128+(HMap[((i+256)&0xFF00)+((j+1)&255)]-HMap[i+j])*4;
  133.       if ( k<0 ) k=0; if (k>255) k=255;
  134.       CMap[i+j]=k;
  135.     }
  136. }
  137.  
  138. int lasty[320],         /* Last pixel drawn on a given column */
  139.     lastc[320];         /* Color of last pixel on a column */
  140.  
  141. /*
  142.    Draw a "section" of the landscape; x0,y0 and x1,y1 and the xy coordinates
  143.    on the height field, hy is the viewpoint height, s is the scaling factor
  144.    for the distance. x0,y0,x1,y1 are 16.16 fixed point numbers and the
  145.    scaling factor is a 16.8 fixed point value.
  146.  */
  147. void Line(int x0,int y0,int x1,int y1,int hy,int s)
  148. {
  149.   int i,sx,sy;
  150.  
  151.   /* Compute xy speed */
  152.   sx=(x1-x0)/320; sy=(y1-y0)/320;
  153.   for ( i=0; i<320; i++ )
  154.   {
  155.     int c,y,h,u0,v0,u1,v1,a,b,h0,h1,h2,h3;
  156.  
  157.     /* Compute the xy coordinates; a and b will be the position inside the
  158.        single map cell (0..255).
  159.      */
  160.     u0=(x0>>16)&0xFF;    a=(x0>>8)&255;
  161.     v0=((y0>>8)&0xFF00); b=(y0>>8)&255;
  162.     u1=(u0+1)&0xFF;
  163.     v1=(v0+256)&0xFF00;
  164.  
  165.     /* Fetch the height at the four corners of the square the point is in */
  166.     h0=HMap[u0+v0]; h2=HMap[u0+v1];
  167.     h1=HMap[u1+v0]; h3=HMap[u1+v1];
  168.  
  169.     /* Compute the height using bilinear interpolation */
  170.     h0=(h0<<8)+a*(h1-h0);
  171.     h2=(h2<<8)+a*(h3-h2);
  172.     h=((h0<<8)+b*(h2-h0))>>16;
  173.  
  174.     /* Fetch the color at the four corners of the square the point is in */
  175.     h0=CMap[u0+v0]; h2=CMap[u0+v1];
  176.     h1=CMap[u1+v0]; h3=CMap[u1+v1];
  177.  
  178.     /* Compute the color using bilinear interpolation (in 16.16) */
  179.     h0=(h0<<8)+a*(h1-h0);
  180.     h2=(h2<<8)+a*(h3-h2);
  181.     c=((h0<<8)+b*(h2-h0));
  182.  
  183.     /* Compute screen height using the scaling factor */
  184.     y=(((h-hy)*s)>>11)+100;
  185.  
  186.     /* Draw the column */
  187.     if ( y<(a=lasty[i]) )
  188.     {
  189.       unsigned char *b=Video+a*320+i;
  190.       int sc,cc;
  191.  
  192.  
  193.       if ( lastc[i]==-1 )
  194.     lastc[i]=c;
  195.  
  196.       sc=(c-lastc[i])/(a-y);
  197.       cc=lastc[i];
  198.  
  199.       if ( a>239 ) { b-=(a-239)*320; cc+=(a-239)*sc; a=239; }
  200.       if ( y<0 ) y=0;
  201.       while ( y<=a )
  202.       {
  203.     *b=cc>>18; cc+=sc;
  204.     b-=320; a--;
  205.       }
  206.       lasty[i]=y;
  207.  
  208.     }
  209.     lastc[i]=c;
  210.  
  211.     /* Advance to next xy position */
  212.     x0+=sx; y0+=sy;
  213.   }
  214. }
  215.  
  216. float FOV=3.141592654/4;   /* half of the xy field of view */
  217.  
  218. /*
  219. // Draw the view from the point x0,y0 (16.16) looking at angle a
  220. */
  221. void View(int x0,int y0,float aa,SDL_Surface *screen)
  222. {
  223.   int d;
  224.   int a,b,h,u0,v0,u1,v1,h0,h1,h2,h3;
  225.  
  226.   /* Clear offscreen buffer */
  227.   memset(Video,0,320*240);
  228.  
  229.   /* Initialize last-y and last-color arrays */
  230.   for ( d=0; d<320; d++ )
  231.   {
  232.     lasty[d]=240;
  233.     lastc[d]=-1;
  234.   }
  235.  
  236.   /* Compute viewpoint height value */
  237.  
  238.   /* Compute the xy coordinates; a and b will be the position inside the
  239.      single map cell (0..255).
  240.    */
  241.   u0=(x0>>16)&0xFF;    a=(x0>>8)&255;
  242.   v0=((y0>>8)&0xFF00); //b=(y0>>8)&255;
  243.   u1=(u0+1)&0xFF;
  244.   v1=(v0+256)&0xFF00;
  245.  
  246.   /* Fetch the height at the four corners of the square the point is in */
  247.   h0=HMap[u0+v0]; h2=HMap[u0+v1];
  248.   h1=HMap[u1+v0]; h3=HMap[u1+v1];
  249.  
  250.   /* Compute the height using bilinear interpolation */
  251.   h0=(h0<<8)+a*(h1-h0);
  252.   h2=(h2<<8)+a*(h3-h2);
  253.   h=((h0<<8)+b*(h2-h0))>>16;
  254.  
  255.   /* Draw the landscape from near to far without overdraw */
  256.   for ( d=0; d<view_dist; d+=1+(d>>6) )
  257.   {
  258.     Line(x0+d*65536*get_cos(aa-FOV),y0+d*65536*get_sin(aa-FOV),
  259.          x0+d*65536*get_cos(aa+FOV),y0+d*65536*get_sin(aa+FOV),
  260.          auto_height?h-20:altitude,256*256/(d+1));
  261.   }
  262.  
  263.   /* Blit the final image to the screen */
  264.   if ( SDL_LockSurface(screen) == 0 ) {
  265.     int row;
  266.     Uint8 *src, *dst;
  267.  
  268.     src = Video;
  269.     dst = (Uint8 *)screen->pixels;
  270.     for ( row=screen->h; row>0; --row )
  271.     {
  272.       memcpy(dst, src, 320);
  273.       src += 320;
  274.       dst += screen->pitch;
  275.     }
  276.     SDL_UnlockSurface(screen);
  277.   }
  278.   SDL_UpdateRect(screen, 0, 0, 0, 0);
  279. }
  280.  
  281. int main(int argc, char *argv[])
  282. {
  283.   SDL_Surface *screen;
  284.   int done;
  285.   int i,k;
  286.   float ss,sa,a,s,salt;
  287.   int x0,y0;
  288.   SDL_Color colors[64];
  289.   SDL_Event event;
  290.   Uint8 *keystate;
  291.   /* Initialize SDL */
  292.   if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
  293.   {
  294.     fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  295.     exit(1);
  296.   }
  297.   /* Enter 320x240x256 mode */
  298.   screen = SDL_SetVideoMode(320, 240, 8,
  299.             SDL_SWSURFACE);
  300.   if ( screen == NULL )
  301.   {
  302.     fprintf(stderr, "Couldn't init video mode: %s\n", SDL_GetError());
  303.     exit(1);
  304.   }
  305.  
  306.   /* Set up the first 64 colors to a grayscale */
  307.   for ( i=0; i<64; i++ )
  308.   {
  309.     colors[i].r = i*4;//screen->format->palette->colors[i].r*4;
  310.     colors[i].g = i*3;//screen->format->palette->colors[i].g*4;
  311.     colors[i].b = i*3;//screen->format->palette->colors[i].b*4;
  312.   }
  313.   SDL_SetColors(screen, colors, 0, 64);
  314.   /* Compute the height map */
  315.   calculate_tables();
  316.   ComputeMap();
  317.  
  318.   /* Main loop
  319.    
  320.        a     = angle
  321.        x0,y0 = current position
  322.        s     = speed constant
  323.        ss    = current forward/backward speed
  324.        sa    = angular speed
  325.    */
  326.   done=0;
  327.   a=0; k=x0=y0=0;
  328.   s=256; /*s=4096;*/
  329.   ss=0; sa=0; salt=0;
  330.   while(!done)
  331.   {
  332.     /* Draw the frame */
  333.     View(x0,y0,a,screen);
  334.  
  335.     /* Update position/angle */
  336.     x0+=ss*get_cos(a); y0+=ss*get_sin(a);
  337.     a+=sa;
  338.     altitude+=salt;
  339.  
  340.     /* Slowly reset the angle to 0 */
  341.     if ( sa != 0 )
  342.     {
  343.       if ( sa < 0 )
  344.         sa += 0.001;
  345.       else
  346.         sa -= 0.001;
  347.     }
  348.  
  349.     if ( salt != 0 )
  350.     {
  351.       if ( salt < 0 )
  352.         salt += 0.05;
  353.       else
  354.         salt -= 0.05;
  355.     }
  356.  
  357.     /* User input */
  358.     while ( SDL_PollEvent(&event) )
  359.     {
  360.       if ( event.type == SDL_QUIT )
  361.       {
  362.           done = 1;
  363.       }
  364.     }
  365.     keystate = SDL_GetKeyState(NULL);
  366.     if ( keystate[SDLK_ESCAPE] ) {
  367.       done = 1;
  368.     }
  369.     if ( keystate[SDLK_UP] ) {
  370.       ss+=s;
  371.     }
  372.     if ( keystate[SDLK_DOWN] ) {
  373.       ss-=s;
  374.     }
  375.     if ( keystate[SDLK_RIGHT] ) {
  376.       sa+=0.003;
  377.     }
  378.     if ( keystate[SDLK_LEFT] ) {
  379.       sa-=0.003;
  380.     }
  381.     if ( keystate[SDLK_MINUS] ) {
  382.       salt+=0.2;
  383.     }
  384.     if ( keystate[SDLK_PLUS] ) {
  385.       salt-=0.2;
  386.     }
  387.     if ( keystate[SDLK_5] ) {
  388.       auto_height = !auto_height;
  389.     }
  390.   }
  391.  
  392.   /* Exit to text mode */
  393.   SDL_Quit();
  394.   return 0;
  395. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement