LCOV - code coverage report
Current view: top level - engine/world - light.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 6.3 % 364 23
Test Date: 2025-06-27 04:34:40 Functions: 4.5 % 22 1

            Line data    Source code
       1              : /* light.cpp: world light interaction functions
       2              :  *
       3              :  * while renderlights in /render handles the deferred rendering of point lights
       4              :  * on the world, light.cpp handles how lights behave in the world
       5              :  *
       6              :  * includes sunlight variables (direction/color of no-parallax sun lighting)
       7              :  * world light entity packing for the renderer to use
       8              :  */
       9              : #include "../libprimis-headers/cube.h"
      10              : #include "../../shared/geomexts.h"
      11              : #include "../../shared/glexts.h"
      12              : 
      13              : #include "light.h"
      14              : #include "octaworld.h"
      15              : #include "raycube.h"
      16              : #include "world.h"
      17              : 
      18              : #include "interface/console.h"
      19              : #include "interface/input.h"
      20              : 
      21              : #include "render/radiancehints.h"
      22              : #include "render/renderlights.h"
      23              : #include "render/octarender.h"
      24              : #include "render/shaderparam.h"
      25              : #include "render/texture.h"
      26              : 
      27              : namespace
      28              : {
      29            0 :     void setsunlightdir()
      30              :     {
      31            0 :         sunlightdir = vec(sunlightyaw/RAD, sunlightpitch/RAD);
      32            0 :         for(int k = 0; k < 3; ++k)
      33              :         {
      34            0 :             if(std::fabs(sunlightdir[k]) < 1e-5f)
      35              :             {
      36            0 :                 sunlightdir[k] = 0;
      37              :             }
      38              :         }
      39            0 :         sunlightdir.normalize();
      40            0 :         clearradiancehintscache();
      41            0 :     }
      42              : 
      43            0 :     void setsurfaces(cube &c, std::array<surfaceinfo, 6> surfs, const vertinfo *verts, int numverts)
      44              :     {
      45            0 :         if(!c.ext || c.ext->maxverts < numverts)
      46              :         {
      47            0 :             newcubeext(c, numverts, false);
      48              :         }
      49            0 :         std::copy(c.ext->surfaces.begin(), c.ext->surfaces.end(), surfs.begin());
      50            0 :         std::memcpy(c.ext->verts(), verts, numverts*sizeof(vertinfo));
      51            0 :     }
      52              : 
      53            0 :     void clearsurfaces(std::array<cube, 8> &c)
      54              :     {
      55            0 :         for(int i = 0; i < 8; ++i)
      56              :         {
      57            0 :             if(c[i].ext)
      58              :             {
      59            0 :                 for(int j = 0; j < 6; ++j)
      60              :                 {
      61            0 :                     surfaceinfo &surf = c[i].ext->surfaces[j];
      62            0 :                     if(!surf.used())
      63              :                     {
      64            0 :                         continue;
      65              :                     }
      66            0 :                     surf.clear();
      67            0 :                     int numverts = surf.numverts&Face_MaxVerts;
      68            0 :                     if(numverts)
      69              :                     {
      70            0 :                         if(!(c[i].merged&(1<<j)))
      71              :                         {
      72            0 :                             surf.numverts &= ~Face_MaxVerts;
      73            0 :                             continue;
      74              :                         }
      75            0 :                         vertinfo *verts = c[i].ext->verts() + surf.verts;
      76            0 :                         for(int k = 0; k < numverts; ++k)
      77              :                         {
      78            0 :                             vertinfo &v = verts[k];
      79            0 :                             v.norm = 0;
      80              :                         }
      81              :                     }
      82              :                 }
      83              :             }
      84            0 :             if(c[i].children)
      85              :             {
      86            0 :                 clearsurfaces(*(c[i].children));
      87              :             }
      88              :         }
      89            0 :     }
      90              : 
      91              :     constexpr int lightcacheentries = 1024;
      92              : 
      93              :     struct lightcacheentry final
      94              :     {
      95              :         int x, y;
      96              :     } lightcache[lightcacheentries];
      97              : 
      98            0 :     int lightcachehash(int x, int y)
      99              :     {
     100            0 :         return (((((x)^(y))<<5) + (((x)^(y))>>5)) & (lightcacheentries - 1));
     101              :     }
     102              : 
     103              :     //takes a 3d vec3 and transforms it into a packed ushort vector
     104              :     //the output ushort is in base 360 and has yaw in the first place and pitch in the second place
     105              :     //the second place has pitch as a range from 0 to 90
     106              :     //since this is a normal vector, no magnitude needed
     107            0 :     ushort encodenormal(const vec &n)
     108              :     {
     109            0 :         if(n.iszero())
     110              :         {
     111            0 :             return 0;
     112              :         }
     113            0 :         const int yaw = static_cast<int>(-std::atan2(n.x, n.y)*RAD), //arctangent in degrees
     114            0 :                   pitch = static_cast<int>(std::asin(n.z)*RAD); //arcsin in degrees
     115            0 :         return static_cast<ushort>(std::clamp(pitch + 90, 0, 180)*360 + (yaw < 0 ? yaw%360 + 360 : yaw%360) + 1);
     116              :     }
     117              : 
     118            0 :     void calcsurfaces(cube &c, const ivec &co, int size, int usefacemask, int preview = 0)
     119              :     {
     120            0 :         std::array<surfaceinfo, 6> surfaces;
     121              :         vertinfo litverts[6*2*Face_MaxVerts];
     122            0 :         int numlitverts = 0;
     123            0 :         surfaces.fill(surfaceinfo());
     124            0 :         for(int i = 0; i < 6; ++i) //for each face of the cube
     125              :         {
     126            0 :             int usefaces = usefacemask&0xF;
     127            0 :             usefacemask >>= 4;
     128            0 :             if(!usefaces)
     129              :             {
     130            0 :                 if(!c.ext)
     131              :                 {
     132            0 :                     continue;
     133              :                 }
     134            0 :                 surfaceinfo &surf = c.ext->surfaces[i];
     135            0 :                 int numverts = surf.totalverts();
     136            0 :                 if(numverts)
     137              :                 {
     138            0 :                     std::memcpy(&litverts[numlitverts], c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
     139            0 :                     surf.verts = numlitverts;
     140            0 :                     numlitverts += numverts;
     141              :                 }
     142            0 :                 continue;
     143            0 :             }
     144              : 
     145            0 :             VSlot &vslot = lookupvslot(c.texture[i], false),
     146            0 :                  *layer = vslot.layer && !(c.material&Mat_Alpha) ? &lookupvslot(vslot.layer, false) : nullptr;
     147            0 :             Shader *shader = vslot.slot->shader;
     148            0 :             int shadertype = shader->type;
     149            0 :             if(layer)
     150              :             {
     151            0 :                 shadertype |= layer->slot->shader->type;
     152              :             }
     153            0 :             surfaceinfo &surf = surfaces[i];
     154            0 :             vertinfo *curlitverts = &litverts[numlitverts];
     155            0 :             int numverts = c.ext ? c.ext->surfaces[i].numverts&Face_MaxVerts : 0;
     156            0 :             ivec mo(co);
     157            0 :             int msz = size,
     158            0 :                 convex = 0;
     159            0 :             if(numverts)
     160              :             {
     161            0 :                 const vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts;
     162            0 :                 for(int j = 0; j < numverts; ++j)
     163              :                 {
     164            0 :                     curlitverts[j].set(verts[j].getxyz());
     165              :                 }
     166            0 :                 if(c.merged&(1<<i))
     167              :                 {
     168            0 :                     msz = 1<<calcmergedsize(mo, size, verts, numverts);
     169            0 :                     mo.mask(~(msz-1));
     170            0 :                     if(!(surf.numverts&Face_MaxVerts))
     171              :                     {
     172            0 :                         surf.verts = numlitverts;
     173            0 :                         surf.numverts |= numverts;
     174            0 :                         numlitverts += numverts;
     175              :                     }
     176              :                 }
     177            0 :                 else if(!flataxisface(c, i))
     178              :                 {
     179            0 :                     convex = faceconvexity(verts, numverts, size);
     180              :                 }
     181              :             }
     182              :             else
     183              :             {
     184            0 :                 std::array<ivec, 4> v;
     185            0 :                 genfaceverts(c, i, v);
     186            0 :                 if(!flataxisface(c, i))
     187              :                 {
     188            0 :                     convex = faceconvexity(v);
     189              :                 }
     190            0 :                 int order = usefaces&4 || convex < 0 ? 1 : 0;
     191            0 :                 ivec vo = ivec(co).mask(0xFFF).shl(3);
     192            0 :                 curlitverts[numverts++].set(v[order].mul(size).add(vo));
     193            0 :                 if(usefaces&1)
     194              :                 {
     195            0 :                     curlitverts[numverts++].set(v[order+1].mul(size).add(vo));
     196              :                 }
     197            0 :                 curlitverts[numverts++].set(v[order+2].mul(size).add(vo));
     198            0 :                 if(usefaces&2)
     199              :                 {
     200            0 :                     curlitverts[numverts++].set(v[(order+3)&3].mul(size).add(vo));
     201              :                 }
     202              :             }
     203              : 
     204            0 :             vec pos[Face_MaxVerts],
     205            0 :                 n[Face_MaxVerts],
     206            0 :                 po(ivec(co).mask(~0xFFF));
     207            0 :             for(int j = 0; j < numverts; ++j)
     208              :             {
     209            0 :                 pos[j] = vec(curlitverts[j].getxyz()).mul(1.0f/8).add(po);
     210              :             }
     211              : 
     212            0 :             int smooth = vslot.slot->smooth;
     213            0 :             plane planes[2];
     214            0 :             int numplanes = 0;
     215            0 :             planes[numplanes++].toplane(pos[0], pos[1], pos[2]);
     216            0 :             if(numverts < 4 || !convex)
     217              :             {
     218            0 :                 for(int k = 0; k < numverts; ++k)
     219              :                 {
     220            0 :                     findnormal(pos[k], smooth, planes[0], n[k]);
     221              :                 }
     222            0 :             }
     223              :             else
     224              :             {
     225            0 :                 planes[numplanes++].toplane(pos[0], pos[2], pos[3]);
     226            0 :                 vec avg = vec(planes[0]).add(planes[1]).normalize();
     227            0 :                 findnormal(pos[0], smooth, avg, n[0]);
     228            0 :                 findnormal(pos[1], smooth, planes[0], n[1]);
     229            0 :                 findnormal(pos[2], smooth, avg, n[2]);
     230            0 :                 for(int k = 3; k < numverts; k++)
     231              :                 {
     232            0 :                     findnormal(pos[k], smooth, planes[1], n[k]);
     233              :                 }
     234              :             }
     235            0 :             for(int k = 0; k < numverts; ++k)
     236              :             {
     237            0 :                 curlitverts[k].norm = encodenormal(n[k]);
     238              :             }
     239            0 :             if(!(surf.numverts&Face_MaxVerts))
     240              :             {
     241            0 :                 surf.verts = numlitverts;
     242            0 :                 surf.numverts |= numverts;
     243            0 :                 numlitverts += numverts;
     244              :             }
     245            0 :             if(preview)
     246              :             {
     247            0 :                 surf.numverts |= preview;
     248            0 :                 continue;
     249              :             }
     250            0 :             int surflayer = BlendLayer_Top;
     251            0 :             if(vslot.layer)
     252              :             {
     253            0 :                 int x1 = curlitverts[numverts-1].x,
     254            0 :                     y1 = curlitverts[numverts-1].y,
     255            0 :                     x2 = x1,
     256            0 :                     y2 = y1;
     257            0 :                 for(int j = 0; j < numverts-1; ++j)
     258              :                 {
     259            0 :                     const vertinfo &v = curlitverts[j];
     260            0 :                     x1 = std::min(x1, static_cast<int>(v.x));
     261            0 :                     y1 = std::min(y1, static_cast<int>(v.y));
     262            0 :                     x2 = std::max(x2, static_cast<int>(v.x));
     263            0 :                     y2 = std::max(y2, static_cast<int>(v.y));
     264              :                 }
     265            0 :                 x2 = std::max(x2, x1+1);
     266            0 :                 y2 = std::max(y2, y1+1);
     267            0 :                 x1 = (x1>>3) + (co.x&~0xFFF);
     268            0 :                 y1 = (y1>>3) + (co.y&~0xFFF);
     269            0 :                 x2 = ((x2+7)>>3) + (co.x&~0xFFF);
     270            0 :                 y2 = ((y2+7)>>3) + (co.y&~0xFFF);
     271              :             }
     272            0 :             surf.numverts |= surflayer;
     273              :         }
     274            0 :         if(preview)
     275              :         {
     276            0 :             setsurfaces(c, surfaces, litverts, numlitverts);
     277              :         }
     278              :         else
     279              :         {
     280            0 :             for(const surfaceinfo &surf : surfaces)
     281              :             {
     282            0 :                 if(surf.used())
     283              :                 {
     284            0 :                     cubeext *ext = c.ext && c.ext->maxverts >= numlitverts ? c.ext : growcubeext(c.ext, numlitverts);
     285            0 :                     std::memcpy(ext->surfaces.data(), surfaces.data(), sizeof(ext->surfaces));
     286            0 :                     std::memcpy(ext->verts(), litverts, numlitverts*sizeof(vertinfo));
     287            0 :                     if(c.ext != ext)
     288              :                     {
     289            0 :                         setcubeext(c, ext);
     290              :                     }
     291            0 :                     break;
     292              :                 }
     293              :             }
     294              :         }
     295            0 :     }
     296              : 
     297            0 :     void calcsurfaces(std::array<cube, 8> &c, const ivec &co, int size)
     298              :     {
     299            0 :         for(int i = 0; i < 8; ++i)
     300              :         {
     301            0 :             ivec o(i, co, size);
     302            0 :             if(c[i].children)
     303              :             {
     304            0 :                 calcsurfaces(*(c[i].children), o, size >> 1);
     305              :             }
     306            0 :             else if(!(c[i].isempty()))
     307              :             {
     308            0 :                 if(c[i].ext)
     309              :                 {
     310            0 :                     for(surfaceinfo &s : c[i].ext->surfaces)
     311              :                     {
     312            0 :                         s.clear();
     313              :                     }
     314              :                 }
     315            0 :                 int usefacemask = 0;
     316            0 :                 for(int j = 0; j < 6; ++j)
     317              :                 {
     318            0 :                     if(c[i].texture[j] != Default_Sky && (!(c[i].merged & (1 << j)) || (c[i].ext && c[i].ext->surfaces[j].numverts & Face_MaxVerts)))
     319              :                     {
     320            0 :                         usefacemask |= visibletris(c[i], j, o, size)<<(4*j);
     321              :                     }
     322              :                 }
     323            0 :                 if(usefacemask)
     324              :                 {
     325            0 :                     calcsurfaces(c[i], o, size, usefacemask);
     326              :                 }
     327              :             }
     328              :         }
     329            0 :     }
     330              : }
     331              : 
     332              : //external functionality
     333              : 
     334            0 : CVAR1R(ambient, 0x191919);
     335              : FVARR(ambientscale, 0, 1, 16);
     336              : 
     337            0 : CVAR1R(skylight, 0);
     338              : FVARR(skylightscale, 0, 1, 16);
     339              : 
     340            0 : CVAR1FR(sunlight, 0,
     341              : {
     342              :     clearradiancehintscache();
     343              :     cleardeferredlightshaders();
     344              :     clearshadowcache();
     345              : });
     346            0 : FVARFR(sunlightscale, 0, 1, 16, clearradiancehintscache(););
     347              : 
     348              : vec sunlightdir(0, 0, 1);
     349            0 : FVARFR(sunlightyaw, 0, 0, 360, setsunlightdir());
     350            0 : FVARFR(sunlightpitch, -90, 90, 90, setsunlightdir());
     351              : 
     352            0 : void brightencube(cube &c)
     353              : {
     354            0 :     if(!c.ext)
     355              :     {
     356            0 :         newcubeext(c, 0, false);
     357              :     }
     358            0 :     c.ext->surfaces.fill(surfaceinfo());
     359            0 : }
     360              : 
     361            0 : void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *srcverts, int numsrcverts)
     362              : {
     363            0 :     int dstoffset = 0;
     364            0 :     if(!c.ext)
     365              :     {
     366            0 :         newcubeext(c, numsrcverts, true);
     367              :     }
     368              :     else
     369              :     {
     370            0 :         int numbefore = 0,
     371            0 :             beforeoffset = 0;
     372            0 :         for(int i = 0; i < orient; ++i)
     373              :         {
     374            0 :             const surfaceinfo &surf = c.ext->surfaces[i];
     375            0 :             int numverts = surf.totalverts();
     376            0 :             if(!numverts)
     377              :             {
     378            0 :                 continue;
     379              :             }
     380            0 :             numbefore += numverts;
     381            0 :             beforeoffset = surf.verts + numverts;
     382              :         }
     383            0 :         int numafter = 0,
     384            0 :             afteroffset = c.ext->maxverts;
     385            0 :         for(int i = 5; i > orient; i--) //note reverse iteration
     386              :         {
     387            0 :             const surfaceinfo &surf = c.ext->surfaces[i];
     388            0 :             int numverts = surf.totalverts();
     389            0 :             if(!numverts)
     390              :             {
     391            0 :                 continue;
     392              :             }
     393            0 :             numafter += numverts;
     394            0 :             afteroffset = surf.verts;
     395              :         }
     396            0 :         if(afteroffset - beforeoffset >= numsrcverts)
     397              :         {
     398            0 :             dstoffset = beforeoffset;
     399              :         }
     400              :         else
     401              :         {
     402            0 :             cubeext *ext = c.ext;
     403            0 :             if(numbefore + numsrcverts + numafter > c.ext->maxverts)
     404              :             {
     405            0 :                 ext = growcubeext(c.ext, numbefore + numsrcverts + numafter);
     406            0 :                 std::copy(ext->surfaces.begin(), ext->surfaces.end(), c.ext->surfaces.begin());
     407              :             }
     408            0 :             int offset = 0;
     409            0 :             if(numbefore == beforeoffset)
     410              :             {
     411            0 :                 if(numbefore && c.ext != ext)
     412              :                 {
     413            0 :                     std::memcpy(ext->verts(), c.ext->verts(), numbefore*sizeof(vertinfo));
     414              :                 }
     415            0 :                 offset = numbefore;
     416              :             }
     417              :             else
     418              :             {
     419            0 :                 for(int i = 0; i < orient; ++i)
     420              :                 {
     421            0 :                     surfaceinfo &surf = ext->surfaces[i];
     422            0 :                     int numverts = surf.totalverts();
     423            0 :                     if(!numverts)
     424              :                     {
     425            0 :                         continue;
     426              :                     }
     427            0 :                     std::memmove(ext->verts() + offset, c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
     428            0 :                     surf.verts = offset;
     429            0 :                     offset += numverts;
     430              :                 }
     431              :             }
     432            0 :             dstoffset = offset;
     433            0 :             offset += numsrcverts;
     434            0 :             if(numafter && offset > afteroffset)
     435              :             {
     436            0 :                 offset += numafter;
     437            0 :                 for(int i = 5; i > orient; i--) //note reverse iteration
     438              :                 {
     439            0 :                     surfaceinfo &surf = ext->surfaces[i];
     440            0 :                     int numverts = surf.totalverts();
     441            0 :                     if(!numverts)
     442              :                     {
     443            0 :                         continue;
     444              :                     }
     445            0 :                     offset -= numverts;
     446            0 :                     std::memmove(ext->verts() + offset, c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
     447            0 :                     surf.verts = offset;
     448              :                 }
     449              :             }
     450            0 :             if(c.ext != ext)
     451              :             {
     452            0 :                 setcubeext(c, ext);
     453              :             }
     454              :         }
     455              :     }
     456            0 :     surfaceinfo &dst = c.ext->surfaces[orient];
     457            0 :     dst = src;
     458            0 :     dst.verts = dstoffset;
     459            0 :     if(srcverts)
     460              :     {
     461            0 :         std::memcpy(c.ext->verts() + dstoffset, srcverts, numsrcverts*sizeof(vertinfo));
     462              :     }
     463            0 : }
     464              : 
     465           33 : bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th)
     466              : {
     467           33 :     if((available < tw && available < th) || w < tw || h < th)
     468              :     {
     469            9 :         return false;
     470              :     }
     471           24 :     if(child1)
     472              :     {
     473           21 :         bool inserted = child1->insert(tx, ty, tw, th) ||
     474            9 :                         child2->insert(tx, ty, tw, th);
     475           12 :         available = std::max(child1->available, child2->available);
     476           12 :         if(!available)
     477              :         {
     478            3 :             discardchildren();
     479              :         }
     480           12 :         return inserted;
     481              :     }
     482           12 :     if(w == tw && h == th)
     483              :     {
     484            6 :         available = 0;
     485            6 :         tx = x;
     486            6 :         ty = y;
     487            6 :         return true;
     488              :     }
     489              : 
     490            6 :     if(w - tw > h - th)
     491              :     {
     492            4 :         child1 = new PackNode(x, y, tw, h);
     493            4 :         child2 = new PackNode(x + tw, y, w - tw, h);
     494              :     }
     495              :     else
     496              :     {
     497            2 :         child1 = new PackNode(x, y, w, th);
     498            2 :         child2 = new PackNode(x, y + th, w, h - th);
     499              :     }
     500              : 
     501            6 :     bool inserted = child1->insert(tx, ty, tw, th);
     502            6 :     available = std::max(child1->available, child2->available);
     503            6 :     return inserted;
     504              : }
     505              : 
     506            0 : void PackNode::reserve(ushort tx, ushort ty, ushort tw, ushort th)
     507              : {
     508            0 :     if(tx + tw <= x || tx >= x + w || ty + th <= y || ty >= y + h)
     509              :     {
     510            0 :         return;
     511              :     }
     512            0 :     if(child1)
     513              :     {
     514            0 :         child1->reserve(tx, ty, tw, th);
     515            0 :         child2->reserve(tx, ty, tw, th);
     516            0 :         available = std::max(child1->available, child2->available);
     517            0 :         return;
     518              :     }
     519            0 :     int dx1 = tx - x,
     520            0 :         dx2 = x + w - tx - tw,
     521            0 :         dx = std::max(dx1, dx2),
     522            0 :         dy1 = ty - y,
     523            0 :         dy2 = y + h - ty - th,
     524            0 :         dy = std::max(dy1, dy2),
     525              :         split;
     526            0 :     if(dx > dy)
     527              :     {
     528            0 :         if(dx1 > dx2)
     529              :         {
     530            0 :             split = std::min(dx1, static_cast<int>(w));
     531              :         }
     532              :         else
     533              :         {
     534            0 :             split = w - std::max(dx2, 0);
     535              :         }
     536            0 :         if(w - split <= 0)
     537              :         {
     538            0 :             w = split;
     539            0 :             available = std::min(w, h);
     540            0 :             if(dy > 0)
     541              :             {
     542            0 :                 reserve(tx, ty, tw, th);
     543              :             }
     544            0 :             else if(tx <= x && tx + tw >= x + w)
     545              :             {
     546            0 :                 available = 0;
     547              :             }
     548            0 :             return;
     549              :         }
     550            0 :         if(split <= 0)
     551              :         {
     552            0 :             x += split;
     553            0 :             w -= split;
     554            0 :             available = std::min(w, h);
     555            0 :             if(dy > 0)
     556              :             {
     557            0 :                 reserve(tx, ty, tw, th);
     558              :             }
     559            0 :             else if(tx <= x && tx + tw >= x + w)
     560              :             {
     561            0 :                 available = 0;
     562              :             }
     563            0 :             return;
     564              :         }
     565            0 :         child1 = new PackNode(x, y, split, h);
     566            0 :         child2 = new PackNode(x + split, y, w - split, h);
     567              :     }
     568              :     else
     569              :     {
     570            0 :         if(dy1 > dy2)
     571              :         {
     572            0 :             split = std::min(dy1, static_cast<int>(h));
     573              :         }
     574              :         else
     575              :         {
     576            0 :             split = h - std::max(dy2, 0);
     577              :         }
     578            0 :         if(h - split <= 0)
     579              :         {
     580            0 :             h = split;
     581            0 :             available = std::min(w, h);
     582            0 :             if(dx > 0)
     583              :             {
     584            0 :                 reserve(tx, ty, tw, th);
     585              :             }
     586            0 :             else if(ty <= y && ty + th >= y + h)
     587              :             {
     588            0 :                 available = 0;
     589              :             }
     590            0 :             return;
     591              :         }
     592            0 :         if(split <= 0)
     593              :         {
     594            0 :             y += split;
     595            0 :             h -= split;
     596            0 :             available = std::min(w, h);
     597            0 :             if(dx > 0)
     598              :             {
     599            0 :                 reserve(tx, ty, tw, th);
     600              :             }
     601            0 :             else if(ty <= y && ty + th >= y + h)
     602              :             {
     603            0 :                 available = 0;
     604              :             }
     605            0 :             return;
     606              :         }
     607            0 :         child1 = new PackNode(x, y, w, split);
     608            0 :         child2 = new PackNode(x, y + split, w, h - split);
     609              :     }
     610            0 :     child1->reserve(tx, ty, tw, th);
     611            0 :     child2->reserve(tx, ty, tw, th);
     612            0 :     available = std::max(child1->available, child2->available);
     613              : }
     614              : 
     615            0 : VARF(lightcachesize, 4, 6, 12, clearlightcache());
     616              : 
     617            0 : void clearlightcache(int id)
     618              : {
     619            0 :     if(id >= 0)
     620              :     {
     621            0 :         const extentity &light = *entities::getents()[id];
     622            0 :         int radius = light.attr1;
     623            0 :         if(radius <= 0)
     624              :         {
     625            0 :             return;
     626              :         }
     627            0 :         for(int x = static_cast<int>(std::max(light.o.x-radius, 0.0f))>>lightcachesize, ex = static_cast<int>(std::min(light.o.x+radius, rootworld.mapsize()-1.0f))>>lightcachesize; x <= ex; x++)
     628              :         {
     629            0 :             for(int y = static_cast<int>(std::max(light.o.y-radius, 0.0f))>>lightcachesize, ey = static_cast<int>(std::min(light.o.y+radius, rootworld.mapsize()-1.0f))>>lightcachesize; y <= ey; y++)
     630              :             {
     631            0 :                 lightcacheentry &lce = lightcache[lightcachehash(x, y)];
     632            0 :                 if(lce.x != x || lce.y != y)
     633              :                 {
     634            0 :                     continue;
     635              :                 }
     636            0 :                 lce.x = -1;
     637              :             }
     638              :         }
     639            0 :         return;
     640              :     }
     641              : 
     642            0 :     for(lightcacheentry *lce = lightcache; lce < &lightcache[lightcacheentries]; lce++)
     643              :     {
     644            0 :         lce->x = -1;
     645              :     }
     646              : }
     647              : 
     648            0 : void cubeworld::calclight()
     649              : {
     650            0 :     remip();
     651            0 :     clearsurfaces(*worldroot);
     652            0 :     calcnormals(filltjoints > 0);
     653            0 :     calcsurfaces(*worldroot, ivec(0, 0, 0), rootworld.mapsize() >> 1);
     654            0 :     clearnormals();
     655            0 :     allchanged();
     656            0 : }
     657              : 
     658              : VAR(fullbright, 0, 0, 1);           //toggles rendering at fullbrightlevel light
     659              : VAR(fullbrightlevel, 0, 160, 255);  //grayscale shade for lighting when at fullbright
     660              : 
     661            0 : void clearlights()
     662              : {
     663            0 :     clearlightcache();
     664            0 :     clearshadowcache();
     665            0 :     cleardeferredlightshaders();
     666            0 :     resetsmoothgroups();
     667            0 : }
     668              : 
     669            0 : void initlights()
     670              : {
     671            0 :     clearlightcache();
     672            0 :     clearshadowcache();
     673            0 :     loaddeferredlightshaders();
     674            0 : }
        

Generated by: LCOV version 2.0-1