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: 2026-02-16 07:02:41 Functions: 4.5 % 22 1

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

Generated by: LCOV version 2.0-1