home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / worldlight.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-05-18  |  6.2 KB  |  215 lines

  1. // worldlight.cpp
  2.  
  3. #include "cube.h"
  4.  
  5. VAR(lightscale,1,4,100);
  6.  
  7. void lightray(float bx, float by, persistent_entity &light)     // done in realtime, needs to be fast
  8. {
  9.     float lx = light.x+(rnd(21)-10)*0.1f;
  10.     float ly = light.y+(rnd(21)-10)*0.1f;
  11.     float dx = bx-lx;
  12.     float dy = by-ly; 
  13.     float dist = (float)sqrt(dx*dx+dy*dy);
  14.     if(dist<1.0f) return;
  15.     int reach = light.attr1;
  16.     int steps = (int)(reach*reach*1.6f/dist); // can change this for speedup/quality?
  17.     const int PRECBITS = 12;
  18.     const float PRECF = 4096.0f;
  19.     int x = (int)(lx*PRECF); 
  20.     int y = (int)(ly*PRECF); 
  21.     int l = light.attr2<<PRECBITS;
  22.     int stepx = (int)(dx/(float)steps*PRECF);
  23.     int stepy = (int)(dy/(float)steps*PRECF);
  24.     int stepl = (int)(l/(float)steps); // incorrect: light will fade quicker if near edge of the world
  25.  
  26.     if(maxtmus)
  27.     {
  28.         l /= lightscale;
  29.         stepl /= lightscale;
  30.         
  31.         if(light.attr3 || light.attr4)      // coloured light version, special case because most lights are white
  32.         {
  33.             int dimness = rnd((255-(light.attr2+light.attr3+light.attr4)/3)/16+1);  
  34.             x += stepx*dimness;
  35.             y += stepy*dimness;
  36.  
  37.             if(OUTBORD(x>>PRECBITS, y>>PRECBITS)) return;
  38.  
  39.             int g = light.attr3<<PRECBITS;
  40.             int stepg = (int)(g/(float)steps);
  41.             int b = light.attr4<<PRECBITS;
  42.             int stepb = (int)(b/(float)steps);
  43.             g /= lightscale;
  44.             stepg /= lightscale;
  45.             b /= lightscale;
  46.             stepb /= lightscale;
  47.             loopi(steps)
  48.             {
  49.                 sqr *s = S(x>>PRECBITS, y>>PRECBITS); 
  50.                 int tl = (l>>PRECBITS)+s->r;
  51.                 s->r = tl>255 ? 255 : tl;
  52.                 tl = (g>>PRECBITS)+s->g;
  53.                 s->g = tl>255 ? 255 : tl;
  54.                 tl = (b>>PRECBITS)+s->b;
  55.                 s->b = tl>255 ? 255 : tl;
  56.                 if(SOLID(s)) return;
  57.                 x += stepx;
  58.                 y += stepy;
  59.                 l -= stepl;
  60.                 g -= stepg;
  61.                 b -= stepb;
  62.                 stepl -= 25;
  63.                 stepg -= 25;
  64.                 stepb -= 25;
  65.             }
  66.         }
  67.         else        // white light, special optimized version
  68.         {
  69.             int dimness = rnd((255-light.attr2)/16+1);  
  70.             x += stepx*dimness;
  71.             y += stepy*dimness;
  72.  
  73.             if(OUTBORD(x>>PRECBITS, y>>PRECBITS)) return;
  74.  
  75.             loopi(steps)
  76.             {
  77.                 sqr *s = S(x>>PRECBITS, y>>PRECBITS); 
  78.                 int tl = (l>>PRECBITS)+s->r;
  79.                 s->r = s->g = s->b = tl>255 ? 255 : tl;       
  80.                 if(SOLID(s)) return;
  81.                 x += stepx;
  82.                 y += stepy;
  83.                 l -= stepl;
  84.                 stepl -= 25;
  85.             }
  86.         }
  87.     }
  88.     else        // the old (white) light code, here for the few people with old video cards that don't support overbright
  89.     {
  90.         loopi(steps)
  91.         {
  92.             sqr *s = S(x>>PRECBITS, y>>PRECBITS); 
  93.             int light = l>>PRECBITS;
  94.             if(light>s->r) s->r = s->g = s->b = (uchar)light;
  95.             if(SOLID(s)) return;
  96.             x += stepx;
  97.             y += stepy;
  98.             l -= stepl;
  99.         }
  100.     }
  101.     
  102. }
  103.  
  104. void calclightsource(persistent_entity &l)
  105. {
  106.     int reach = l.attr1;
  107.     int sx = l.x-reach;
  108.     int ex = l.x+reach;
  109.     int sy = l.y-reach;
  110.     int ey = l.y+reach;
  111.     
  112.     rndreset();
  113.     
  114.     const float s = 0.8f;
  115.  
  116.     for(float sx2 = (float)sx; sx2<=ex; sx2+=s*2) { lightray(sx2, (float)sy, l); lightray(sx2, (float)ey, l); }
  117.     for(float sy2 = sy+s; sy2<=ey-s; sy2+=s*2)    { lightray((float)sx, sy2, l); lightray((float)ex, sy2, l); }
  118.     
  119.     rndtime();
  120. }
  121.  
  122. void postlightarea(block &a)    // median filter, smooths out random noise in light and makes it more mipable
  123. {
  124.     loop(x,a.xs) loop(y,a.ys)   // assumes area not on edge of world
  125.     {
  126.         sqr *s = S(x+a.x,y+a.y);
  127.         #define median(m) s->m = (s->m*2 + SW(s,1,0)->m*2  + SW(s,0,1)->m*2 \
  128.                                          + SW(s,-1,0)->m*2 + SW(s,0,-1)->m*2 \
  129.                                          + SW(s,1,1)->m    + SW(s,1,-1)->m \
  130.                                          + SW(s,-1,1)->m   + SW(s,-1,-1)->m)/14;  // median is 4/2/1 instead
  131.         median(r);
  132.         median(g);
  133.         median(b);
  134.     }
  135.  
  136.     remip(a);
  137. }
  138.  
  139. void calclight()
  140. {
  141.     loop(x,ssize) loop(y,ssize)
  142.     {
  143.         sqr *s = S(x,y);
  144.         s->r = s->g = s->b = 10;
  145.     }
  146.  
  147.     loopv(ents)
  148.     {
  149.         entity &e = ents[i];
  150.         if(e.type==LIGHT) calclightsource(e);
  151.     }
  152.     
  153.     block b = { 1, 1, ssize-2, ssize-2 };
  154.     postlightarea(b);
  155.     setvar("fullbright", 0);
  156. }
  157.  
  158. VARP(dynlight, 0, 16, 32);
  159.  
  160. vector<block *> dlights;
  161.  
  162. void cleardlights()
  163. {
  164.     while(!dlights.empty())
  165.     {
  166.         block *backup = dlights.pop();
  167.         blockpaste(*backup);
  168.         freeblock(backup);    
  169.     }
  170. }
  171.  
  172. void dodynlight(vec &vold, vec &v, int reach, int strength, dynent *owner)
  173. {
  174.     if(!reach) reach = dynlight;
  175.     if(!reach) return;
  176.     
  177.     int creach = reach+16;  // dependant on lightray random offsets!
  178.     block b = { (int)v.x-creach, (int)v.y-creach, creach*2+1, creach*2+1 };
  179.  
  180.     if(b.x<1) b.x = 1;   
  181.     if(b.y<1) b.y = 1;
  182.     if(b.xs+b.x>ssize-2) b.xs = ssize-2-b.x;
  183.     if(b.ys+b.y>ssize-2) b.ys = ssize-2-b.y;
  184.  
  185.     dlights.add(blockcopy(b));      // backup area before rendering in dynlight
  186.  
  187.     persistent_entity l = { (int)v.x, (int)v.y, (int)v.z, reach, LIGHT, strength, 0, 0 };
  188.     calclightsource(l);
  189.     postlightarea(b);
  190. }
  191.  
  192. // utility functions also used by editing code
  193.  
  194. block *blockcopy(block &s)
  195. {
  196.     block *b = (block *)new uchar[sizeof(block)+s.xs*s.ys*sizeof(sqr)];
  197.     *b = s;
  198.     sqr *q = (sqr *)(b+1);
  199.     for(int x = s.x; x<s.xs+s.x; x++) for(int y = s.y; y<s.ys+s.y; y++) *q++ = *S(x,y);
  200.     return b;
  201. }
  202.  
  203. void blockpaste(block &b)
  204. {
  205.     sqr *q = (sqr *)((&b)+1);
  206.     for(int x = b.x; x<b.xs+b.x; x++) for(int y = b.y; y<b.ys+b.y; y++) *S(x,y) = *q++;
  207.     remipmore(b);
  208. }
  209.  
  210. void freeblock(block *&b)
  211. {
  212.     if(b) { delete[] (uchar *)b; b = NULL; }
  213. }
  214.  
  215.