Guest User

Raycaster with bilinear filtering

a guest
Apr 2nd, 2012
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.73 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <sys/time.h>
  6. #include <SDL.h>
  7. #include <SDL_ttf.h>
  8.  
  9. int scw = 1280;
  10. int sch = 1024;
  11.  
  12. int mapw = 512;
  13. int maph = 512;
  14.  
  15. char* my_itoa(unsigned int val)
  16. {
  17.     static char buf[11];
  18.     short i=10;
  19.     for(;val&&i;--i,val/=10)buf[i]="0123456789"[val%10];
  20.     return &buf[i+1];
  21. }
  22.  
  23. double mygettime()
  24. {
  25.   struct timeval tv;
  26.   if(gettimeofday(&tv, 0) < 0)
  27.   {
  28.     perror("oops");
  29.   }
  30.   return (double)tv.tv_sec + (0.000001 * (double)tv.tv_usec);
  31. }
  32.  
  33. void filldata (int *hei)
  34. {
  35.     int p = 0;
  36.     int x,y;
  37.     for (y=0; y<maph; y++)
  38.     {
  39.         for (x=0; x<mapw; x++)
  40.         {
  41.             double x1 = (x-mapw/2)*0.3;
  42.             double y1 = (y-maph/2)*0.3;
  43. //            col[p] = 3*(cos(x*0.2) + sin (y*0.3)) + 88;
  44.             hei[p] = 1000*sin(sqrt(x1*x1+y1*y1))/(1+sqrt(x1*x1+y1*y1));
  45.            
  46.             p++;
  47.         }
  48.     }
  49. }
  50.  
  51. void fillpalette (SDL_Surface *screen)
  52. {
  53.     SDL_Color colors[256];
  54.     int i;
  55. //     Fill colors with color information
  56.     for(i=0;i<=256;i++)
  57.     {
  58.         colors[i].r=i;
  59.         colors[i].g=i/2;
  60.         colors[i].b=i/2;
  61.     }
  62.     SDL_SetPalette(screen, SDL_LOGPAL|SDL_PHYSPAL, colors, 0, 256);
  63. }
  64.  
  65. void checkevents(double *ang, int *x, int *y, int *k)
  66. {
  67.     SDL_Event event;
  68.     if (SDL_PollEvent(&event))
  69.     {
  70.         switch (event.type) {
  71.         case SDL_QUIT:
  72.             exit(0);
  73.         }
  74.     }
  75.     Uint8 *keystate = SDL_GetKeyState (NULL);
  76.     if (keystate[SDLK_LEFT]) *ang += 0.02;
  77.     if (keystate[SDLK_RIGHT]) *ang -= 0.02;
  78.     if (keystate[SDLK_UP]) *k -= 1;
  79.     if (keystate[SDLK_DOWN]) *k += 1;
  80.     if (keystate[SDLK_a] || keystate[SDLK_d] || keystate[SDLK_w] || keystate[SDLK_s])
  81.     {
  82.         int xd, yd;
  83.         xd = 0;
  84.         yd = 0;
  85.         if (keystate[SDLK_a]) xd = -3;
  86.         if (keystate[SDLK_d]) xd = 3;
  87.         if (keystate[SDLK_w]) yd = 3;
  88.         if (keystate[SDLK_s]) yd = -3;
  89.        
  90.         *x += yd*cos(*ang) + xd*sin(*ang);
  91.         *y += -yd*sin(*ang) + xd*cos(*ang);
  92.     }
  93. }
  94.  
  95. void blacken_screen (SDL_Surface *screen)
  96. {
  97.     SDL_Rect rect;
  98.     rect.x = 0;
  99.     rect.y = 0;
  100.     rect.w = scw;
  101.     rect.h = sch;
  102.  
  103.     SDL_FillRect (screen, &rect, 0);
  104. }
  105.  
  106. double get_filtered_val (int *val, double xf, double yf)
  107. {
  108.     int x = xf;
  109.     int y = yf;
  110.     double diffx = xf - x;
  111.     double diffy = yf - y;
  112.     double oppx = 1 - diffx;
  113.     double oppy = 1 - diffy;
  114.  
  115.     if ((x==511) || (y==511)) return val[mapw*x+y];
  116.  
  117.     return (val[x*mapw+y]*oppx + val[(x+1)*mapw+y]*diffx)*oppy + \
  118.         (val[x*mapw+y+1]*oppx + val[(x+1)*mapw+y+1]*diffx)*diffy;
  119. }
  120.  
  121. double uint8_get_filtered_val (Uint8 *val, double xf, double yf)
  122. {
  123.     int x = xf;
  124.     int y = yf;
  125.     double diffx = xf - x;
  126.     double diffy = yf - y;
  127.     double oppx = 1 - diffx;
  128.     double oppy = 1 - diffy;
  129.  
  130.     if ((x==511) || (y==511)) return val[mapw*x+y];
  131.  
  132.     return (val[x*mapw+y]*oppx + val[(x+1)*mapw+y]*diffx)*oppy + \
  133.         (val[x*mapw+y+1]*oppx + val[(x+1)*mapw+y+1]*diffx)*diffy;
  134. }
  135.  
  136. int main ()
  137. {
  138.     if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
  139.     {
  140.         fprintf(stderr, "Cannot initialize SDL: %s\n", SDL_GetError());
  141.         exit(1);
  142.     }
  143.  
  144.     if (TTF_Init()==-1)
  145.     {
  146.         printf ("Error Init TTF\n");
  147.         exit(1);
  148.     }
  149.    
  150.     TTF_Font *font = TTF_OpenFont ("tahoma.ttf", 24);
  151.     SDL_Color fontcolor;
  152.     fontcolor.r = 255;
  153.     fontcolor.g = 255;
  154.     fontcolor.b = 255;
  155.  
  156.     SDL_Rect dest;
  157.     dest.x = 20;
  158.     dest.y = 20;
  159.     SDL_Surface *textrend = TTF_RenderText_Solid (font, "FPS: ", fontcolor);
  160.    
  161.     SDL_Surface *screen;
  162.     screen = SDL_SetVideoMode(scw, sch, 8, SDL_SWSURFACE);
  163.     if ( screen == NULL )
  164.     {// Если установить разрешение не удалось
  165.         fprintf(stderr, "Cannot set resolution %ix%i: %s\n", scw, sch, SDL_GetError());
  166.         exit(1);
  167.     }
  168.  
  169.     fillpalette (screen);
  170.     int hei[mapw*maph-1];
  171.     //  int col[mapw*maph-1];
  172.     filldata (hei);
  173. //    SDL_Surface *text = SDL_LoadBMP ("./testtexture.bmp");
  174.     SDL_Surface *text = SDL_LoadBMP ("./testtext3.bmp");
  175.     if (!text) printf ("Error\n");
  176.     Uint8 *col = text->pixels;
  177.  
  178.     int posx = 0;
  179.     int posy = 0;
  180.  
  181.     double ang = 0;
  182.     int horiz = -100;
  183.  
  184.     int k = 1;
  185.  
  186.     double dd = 2.0;
  187.     double de = dd * 128;
  188.     double x,y,z;
  189.  
  190.     double amax = M_PI/3.4;
  191.     double a;
  192.     int sx;
  193.  
  194.     int maxh;
  195.  
  196.     int bin1 = mapw*(maph-1);
  197.     int bin2 = maph-1;
  198.  
  199.     double time1 = mygettime();
  200.     double time2;
  201.     int frames = 0;
  202.  
  203.     while (1)
  204.     {
  205.         SDL_LockSurface(screen);
  206.  
  207.         blacken_screen (screen);
  208.  
  209.         int startidx = ((posx*mapw) & bin1) + (posy&bin2);
  210.         int starth = hei[startidx];
  211.         int posz = 250+starth/2;
  212. //        int posz = 400;
  213.  
  214.         double sinang = sin(ang);
  215.         double cosang = cos(ang);
  216.        
  217.         for (sx=0;sx<scw;sx++)
  218.         {
  219.             double d;
  220.  
  221.             a = -amax + (2*amax)*sx/scw;
  222.             //a = amax*sx/scw;
  223.             double tana = tan (a);
  224.             maxh = sch-1;
  225.             for (d=0;d<=de;d+=dd)
  226.             {
  227.                 double y1 = d*/*cos(amax)**/tana;
  228.                 double x1 = d;//*cos(amax);
  229.  
  230.                 x = posx + x1*cosang+y1*sinang;
  231.                 y = posy - x1*sinang+y1*cosang;
  232.                 z = posz - k*d;//*sin(amax);
  233.                
  234.                 int xdiv = x/mapw;
  235.                 int ydiv = y/maph;
  236.                 x = fabs (x - xdiv*mapw);
  237.                 y = fabs (y - ydiv*maph);
  238.                 float h = get_filtered_val (hei, x, y);
  239.  
  240.                 int sy = sch/2 + 40*(z-h)/(d+1);
  241.                 if (sy<0) sy = 0;
  242.                 if (sy>sch-1) sy = sch-1;
  243.  
  244.                 if (sy<maxh)
  245.                 {
  246.                     int startpos = maxh;
  247.                     maxh=sy;
  248.                     int syi;
  249.  
  250.                     Uint8 color = uint8_get_filtered_val (col, x, y);
  251.                     for (syi=startpos; syi>=sy; syi--)
  252.                     {
  253.                         *((Uint8*)screen->pixels+sx+scw*syi) = color;
  254.                     }
  255.                 }
  256.             }
  257.         }
  258.  
  259.         SDL_UnlockSurface(screen);
  260.         SDL_BlitSurface (textrend, NULL, screen, &dest);
  261.         SDL_Flip (screen);
  262.         checkevents (&ang, &posx, &posy, &k);
  263.  
  264.         frames++;
  265.  
  266.         time2 = mygettime() - time1;
  267.         if (time2 > 1.0)
  268.         {
  269.             SDL_FreeSurface (textrend);
  270.             char fpsstring[30] = "FPS: ";
  271.             strcat (fpsstring, my_itoa (frames));
  272.             textrend = TTF_RenderText_Solid (font, fpsstring, fontcolor);
  273.             frames = 0;
  274.             time1 = mygettime();
  275.         }
  276.     }
  277.  
  278.     return atexit(SDL_Quit);
  279. }
Advertisement
Add Comment
Please, Sign In to add comment