Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <math.h>
- #include <stdio.h>
- #include <time.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/resource.h>
- #include <SDL.h>
- #include <SDL_ttf.h>
- unsigned int scw = 800;
- unsigned int sch = 600;
- unsigned long mapw = 4096;
- unsigned long maph = 4096;
- unsigned int mapw_pow = 12;
- unsigned long bin1;
- unsigned long bin2;
- long dd;
- float *a;
- long *dx, *dy;
- char* my_itoa(unsigned int val)
- {
- static char buf[11];
- short i=10;
- for(;val&&i;--i,val/=10)buf[i]="0123456789"[val%10];
- return &buf[i+1];
- }
- double mygettime()
- {
- struct timeval tv;
- if(gettimeofday(&tv, 0) < 0)
- {
- perror("oops");
- }
- return (double)tv.tv_sec + (0.000001 * (double)tv.tv_usec);
- }
- inline void fillarray_long (long *a, long val, long num)
- {
- int i;
- for (i=0; i<num; i++) a[i] = val;
- }
- inline void fillarray_float (float *a, float val, int num)
- {
- int i;
- for (i=0; i<num; i++) a[i] = val;
- }
- void print_time (struct timeval time)
- {
- printf ("%ld s, %ld us ", time.tv_sec, time.tv_usec);
- }
- void print_statistics ()
- {
- struct rusage rusage;
- getrusage (RUSAGE_SELF, &rusage);
- printf ("Demo was working ");
- print_time (rusage.ru_utime);
- printf ("of user time; ");
- print_time (rusage.ru_stime);
- printf ("of system time;\n");
- printf ("With %ld page faults and %ld page reclaims\n",
- rusage.ru_majflt, rusage.ru_minflt);
- }
- void calc_ray_deltas (float ang)
- {
- unsigned int sx;
- float cosang = cos(ang);
- float sinang = sin(ang);
- for (sx=0; sx<scw; sx++)
- {
- dx[sx] = dd*(cosang - a[sx]*sinang);
- dy[sx] = dd*(cosang*a[sx] + sinang);
- }
- }
- void checkevents(float *ang, long *x, long *y, long *dz, long sdz)
- {
- SDL_Event event;
- if (SDL_PollEvent(&event))
- {
- switch (event.type) {
- case SDL_QUIT:
- print_statistics();
- free (a); free (dx); free (dy);
- SDL_Quit();
- exit(0);
- }
- }
- Uint8 *keystate = SDL_GetKeyState (NULL);
- if ((keystate[SDLK_LEFT]) || (keystate[SDLK_RIGHT]))
- {
- if (keystate[SDLK_LEFT]) *ang -= 0.02;
- else if (keystate[SDLK_RIGHT]) *ang += 0.02;
- calc_ray_deltas (*ang);
- }
- if (keystate[SDLK_UP]) *dz -= sdz;
- else if (keystate[SDLK_DOWN]) *dz += sdz;
- if (keystate[SDLK_a] || keystate[SDLK_d] || keystate[SDLK_w] || keystate[SDLK_s])
- {
- long xd, yd;
- xd = 0;
- yd = 0;
- if (keystate[SDLK_a]) yd = -3<<16;
- else if (keystate[SDLK_d]) yd = 3<<16;
- if (keystate[SDLK_w]) xd = 3<<16;
- else if (keystate[SDLK_s]) xd = -3<<16;
- *x += xd*cos(*ang) - yd*sin(*ang);
- *y += yd*cos(*ang) + xd*sin(*ang);
- }
- }
- void blacken_screen (SDL_Surface *screen)
- {
- SDL_Rect rect;
- rect.x = 0;
- rect.y = 0;
- rect.w = scw;
- rect.h = sch;
- SDL_FillRect (screen, &rect, 0);
- }
- inline int get_idx (long x, long y)
- {
- return (((x<<mapw_pow)&bin1) + (y&bin2))>>16;
- }
- inline Uint32 tex_bilinear_filter (SDL_PixelFormat *fmt, Uint32 *tex, long x, long y)
- {
- Uint32 colxy = tex[get_idx(x, y)];
- Uint8 rxy, gxy, bxy;
- SDL_GetRGB (colxy, fmt, &rxy, &gxy, &bxy);
- Uint32 colx_y = tex[get_idx(x+65536, y)];
- Uint8 rx_y, gx_y, bx_y;
- SDL_GetRGB (colx_y, fmt, &rx_y, &gx_y, &bx_y);
- Uint32 colxy_ = tex[get_idx(x, y+65536)];
- Uint8 rxy_, gxy_, bxy_;
- SDL_GetRGB (colxy_, fmt, &rxy_, &gxy_, &bxy_);
- Uint32 colx_y_ = tex[get_idx(x+65536, y+65536)];
- Uint8 rx_y_, gx_y_, bx_y_;
- SDL_GetRGB (colx_y_, fmt, &rx_y_, &gx_y_, &bx_y_);
- Uint32 r, g, b;
- // Integer variant
- long delta = 1<<16;
- long mask = delta - 1;
- long diffx = x&mask;
- long diffy = y&mask;
- long oppx = delta - diffx;
- long oppy = delta - diffy;
- r = ((rxy*oppx + rx_y*diffx)*oppy)>>32;
- r += ((rxy_*oppx + rx_y_*diffx)*diffy)>>32;
- g = ((gxy*oppx + gx_y*diffx)*oppy)>>32;
- g += ((gxy_*oppx + gx_y_*diffx)*diffy)>>32;
- b = ((bxy*oppx + bx_y*diffx)*oppy)>>32;
- b += ((bxy_*oppx + bx_y_*diffx)*diffy)>>32;
- #if 0
- float diffx = (float)(x&mask)/65536.0;
- float diffy = (float)(y&mask)/65536.0;
- float oppx = 1 - diffx;
- float oppy = 1 - diffy;
- r = (rxy*oppx + rx_y*diffx)*oppx + (rxy_*oppx + rx_y_*diffx)*diffy;
- g = (gxy*oppx + gx_y*diffx)*oppy + (gxy_*oppx + gx_y_*diffx)*diffy;
- b = (bxy*oppx + bx_y*diffx)*oppy + (bxy_*oppx + bx_y_*diffx)*diffy;
- #endif
- return SDL_MapRGB (fmt, r, g, b);
- }
- inline long hm_bilinear_filter (Uint8 *map, long x, long y)
- {
- // Integer variant
- long delta = 1<<16;
- long mask = delta - 1;
- long diffx = x&mask;
- long diffy = y&mask;
- long oppx = delta - diffx;
- long oppy = delta - diffy;
- long res = ((map[get_idx(x, y)]*oppx + map[get_idx(x+delta, y)]*diffx)*oppy)>>16;
- res += ((map[get_idx(x, y+delta)]*oppx + map[get_idx(x+delta, y+delta)]*diffx)*diffy)>>16;
- return res;
- // Floating point variant
- #if 0
- long delta = 1<<16;
- long mask = delta - 1;
- float diffx = (float)(x&mask)/65536.0;
- float diffy = (float)(y&mask)/65536.0;
- float oppx = 1 - diffx;
- float oppy = 1 - diffy;
- float res = (map[get_idx(x, y)]*oppx + map[get_idx(x+delta, y)]*diffx)*oppy;
- res += (map[get_idx(x, y+delta)]*oppx + map[get_idx(x+delta, y+delta)]*diffx)*diffy;
- return (long)(res*65536);
- #endif
- }
- int main (int argc, char *argv[])
- {
- if (argc != 4)
- {
- printf ("Usage: ./test heightmap.bmp texture.bmp scale_factor\n");
- printf ("Textures must be 4096x4096\n");
- exit(0);
- }
- if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
- {
- fprintf(stderr, "Cannot initialize SDL: %s\n", SDL_GetError());
- exit(1);
- }
- if (TTF_Init()==-1)
- {
- printf ("Error Init TTF\n");
- exit(1);
- }
- TTF_Font *font = TTF_OpenFont ("tahoma.ttf", 24);
- SDL_Color fontcolor;
- fontcolor.r = 255;
- fontcolor.g = 255;
- fontcolor.b = 255;
- SDL_Rect dest;
- dest.x = 20;
- dest.y = 20;
- SDL_Surface *textrend = TTF_RenderText_Solid (font, "FPS: ", fontcolor);
- SDL_Surface *screen;
- screen = SDL_SetVideoMode(scw, sch, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
- if ( screen == NULL )
- {// ЕÑли уÑтановить разрешение не удалоÑÑŒ
- fprintf(stderr, "Cannot set resolution %ix%i: %s\n", scw, sch, SDL_GetError());
- exit(1);
- }
- SDL_Surface *hm = SDL_LoadBMP (argv[1]);
- if (!hm)
- {
- printf ("Error loading heightmap\n");
- return -1;
- }
- Uint8 *hei = hm->pixels;
- SDL_Surface *text = SDL_LoadBMP (argv[2]);
- if (!text)
- {
- printf ("Error loading texture\n");
- exit(1);
- }
- Uint32 *col = text->pixels;
- long posx = 0;
- long posy = 0;
- long posz;
- float ang = 0;
- dd = 2<<16;
- long de = dd * 228; // 228 is the max "distance"
- long startdz = 3<<16;
- long sdz = 30<<16;
- int sx;
- bin1 = (mapw*(maph-1))<<16;
- bin2 = (maph-1)<<16;
- double time1 = mygettime();
- double time2;
- unsigned int frames = 0;
- unsigned int again;
- long d[scw];
- long h[scw];
- Uint32 color[scw];
- a = malloc (sizeof (float)*scw);
- float amax = 3.1415/2.9;
- float da = 2*amax/scw;
- a[0] = -amax;
- for (sx=1; sx<scw; sx++) a[sx] = a[sx-1]+da;
- dx = malloc (sizeof (long)*scw);
- dy = malloc (sizeof (long)*scw);
- long x[scw];
- long y[scw];
- long z[scw];
- long dz[scw];
- int scale;
- sscanf (argv[3], "%i", &scale);
- calc_ray_deltas (ang);
- long zbuf[scw*sch];
- while (1)
- {
- SDL_LockSurface(screen);
- blacken_screen (screen);
- int standing_at_idx = get_idx (posx, posy);
- posz = (400<<16) + (hei[standing_at_idx]<<(16+scale));
- fillarray_long (h, posz, scw);
- fillarray_long (d, 0, scw);
- fillarray_long (x, posx, scw);
- fillarray_long (y, posy, scw);
- fillarray_long (z, posz, scw);
- fillarray_long (dz, sdz, scw);
- int p = scw*sch-1;
- do
- {
- again = 0;
- for (sx=scw-1; sx>=0; sx--)
- {
- int newdata = 0;
- while (h[sx] <= z[sx])
- {
- long curd;
- curd = d[sx];
- if (curd>=de)
- {
- again++;
- zbuf[p] = de;
- goto label2;
- }
- x[sx] += dx[sx];
- y[sx] += dy[sx];
- z[sx] -= dz[sx];
- #ifdef HEIGHTMAP_BILINEAR
- h[sx] = hm_bilinear_filter (hei, x[sx], y[sx])<<scale;
- #else
- h[sx] = hei[get_idx(x[sx], y[sx])]<<(16+scale);
- #endif
- d[sx] += dd;
- newdata = 1;
- }
- if (newdata)
- {
- newdata = 0;
- #ifdef TEX_BILINEAR
- color[sx] = tex_bilinear_filter (screen->format, col, x[sx], y[sx]);
- #else
- color[sx] = col[get_idx(x[sx], y[sx])];
- #endif
- }
- if (p < 0) goto label1;
- zbuf[p] = d[sx];
- *((Uint32*)screen->pixels+p) = color[sx];
- dz[sx] -= dd>>4;
- z[sx] += d[sx]>>4; // >>4 is internal scale factor
- label2: p--;
- }
- }
- while (again<scw);
- label1: ;
- SDL_UnlockSurface(screen);
- SDL_BlitSurface (textrend, NULL, screen, &dest);
- SDL_Flip (screen);
- checkevents (&ang, &posx, &posy, &sdz, startdz);
- frames++;
- time2 = mygettime() - time1;
- if (time2 > 1.0)
- {
- SDL_FreeSurface (textrend);
- char fpsstring[30] = "FPS: ";
- strcat (fpsstring, my_itoa (frames));
- textrend = TTF_RenderText_Solid (font, fpsstring, fontcolor);
- frames = 0;
- time1 = mygettime();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement