LCOV - code coverage report
Current view: top level - engine/world - light.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 15.0 % 407 61
Test Date: 2026-03-06 06:39:57 Functions: 31.2 % 32 10

            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           14 : PackNode::PackNode(ushort x, ushort y, ushort w, ushort h) :  w(w), h(h), child1(0), child2(0), x(x), y(y), available(std::min(w, h))
     477              : {
     478           14 : }
     479              : 
     480            1 : void PackNode::reset()
     481              : {
     482            1 :     discardchildren();
     483            1 :     available = std::min(w, h);
     484            1 : }
     485              : 
     486            1 : bool PackNode::resize(int nw, int nh)
     487              : {
     488            1 :     if(w == nw && h == nw)
     489              :     {
     490            0 :         return false;
     491              :     }
     492            1 :     discardchildren();
     493            1 :     w = nw;
     494            1 :     h = nh;
     495            1 :     available = std::min(w, h);
     496            1 :     return true;
     497              : }
     498              : 
     499           14 : PackNode::~PackNode()
     500              : {
     501           14 :     discardchildren();
     502           14 : }
     503              : 
     504           33 : bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th)
     505              : {
     506           33 :     if((available < tw && available < th) || w < tw || h < th)
     507              :     {
     508            9 :         return false;
     509              :     }
     510           24 :     if(child1)
     511              :     {
     512           21 :         bool inserted = child1->insert(tx, ty, tw, th) ||
     513            9 :                         child2->insert(tx, ty, tw, th);
     514           12 :         available = std::max(child1->available, child2->available);
     515           12 :         if(!available)
     516              :         {
     517            3 :             discardchildren();
     518              :         }
     519           12 :         return inserted;
     520              :     }
     521           12 :     if(w == tw && h == th)
     522              :     {
     523            6 :         available = 0;
     524            6 :         tx = x;
     525            6 :         ty = y;
     526            6 :         return true;
     527              :     }
     528              : 
     529            6 :     if(w - tw > h - th)
     530              :     {
     531            4 :         child1 = new PackNode(x, y, tw, h);
     532            4 :         child2 = new PackNode(x + tw, y, w - tw, h);
     533              :     }
     534              :     else
     535              :     {
     536            2 :         child1 = new PackNode(x, y, w, th);
     537            2 :         child2 = new PackNode(x, y + th, w, h - th);
     538              :     }
     539              : 
     540            6 :     bool inserted = child1->insert(tx, ty, tw, th);
     541            6 :     available = std::max(child1->available, child2->available);
     542            6 :     return inserted;
     543              : }
     544              : 
     545            0 : void PackNode::reserve(ushort tx, ushort ty, ushort tw, ushort th)
     546              : {
     547            0 :     if(tx + tw <= x || tx >= x + w || ty + th <= y || ty >= y + h)
     548              :     {
     549            0 :         return;
     550              :     }
     551            0 :     if(child1)
     552              :     {
     553            0 :         child1->reserve(tx, ty, tw, th);
     554            0 :         child2->reserve(tx, ty, tw, th);
     555            0 :         available = std::max(child1->available, child2->available);
     556            0 :         return;
     557              :     }
     558            0 :     int dx1 = tx - x,
     559            0 :         dx2 = x + w - tx - tw,
     560            0 :         dx = std::max(dx1, dx2),
     561            0 :         dy1 = ty - y,
     562            0 :         dy2 = y + h - ty - th,
     563            0 :         dy = std::max(dy1, dy2),
     564              :         split;
     565            0 :     if(dx > dy)
     566              :     {
     567            0 :         if(dx1 > dx2)
     568              :         {
     569            0 :             split = std::min(dx1, static_cast<int>(w));
     570              :         }
     571              :         else
     572              :         {
     573            0 :             split = w - std::max(dx2, 0);
     574              :         }
     575            0 :         if(w - split <= 0)
     576              :         {
     577            0 :             w = split;
     578            0 :             available = std::min(w, h);
     579            0 :             if(dy > 0)
     580              :             {
     581            0 :                 reserve(tx, ty, tw, th);
     582              :             }
     583            0 :             else if(tx <= x && tx + tw >= x + w)
     584              :             {
     585            0 :                 available = 0;
     586              :             }
     587            0 :             return;
     588              :         }
     589            0 :         if(split <= 0)
     590              :         {
     591            0 :             x += split;
     592            0 :             w -= split;
     593            0 :             available = std::min(w, h);
     594            0 :             if(dy > 0)
     595              :             {
     596            0 :                 reserve(tx, ty, tw, th);
     597              :             }
     598            0 :             else if(tx <= x && tx + tw >= x + w)
     599              :             {
     600            0 :                 available = 0;
     601              :             }
     602            0 :             return;
     603              :         }
     604            0 :         child1 = new PackNode(x, y, split, h);
     605            0 :         child2 = new PackNode(x + split, y, w - split, h);
     606              :     }
     607              :     else
     608              :     {
     609            0 :         if(dy1 > dy2)
     610              :         {
     611            0 :             split = std::min(dy1, static_cast<int>(h));
     612              :         }
     613              :         else
     614              :         {
     615            0 :             split = h - std::max(dy2, 0);
     616              :         }
     617            0 :         if(h - split <= 0)
     618              :         {
     619            0 :             h = split;
     620            0 :             available = std::min(w, h);
     621            0 :             if(dx > 0)
     622              :             {
     623            0 :                 reserve(tx, ty, tw, th);
     624              :             }
     625            0 :             else if(ty <= y && ty + th >= y + h)
     626              :             {
     627            0 :                 available = 0;
     628              :             }
     629            0 :             return;
     630              :         }
     631            0 :         if(split <= 0)
     632              :         {
     633            0 :             y += split;
     634            0 :             h -= split;
     635            0 :             available = std::min(w, h);
     636            0 :             if(dx > 0)
     637              :             {
     638            0 :                 reserve(tx, ty, tw, th);
     639              :             }
     640            0 :             else if(ty <= y && ty + th >= y + h)
     641              :             {
     642            0 :                 available = 0;
     643              :             }
     644            0 :             return;
     645              :         }
     646            0 :         child1 = new PackNode(x, y, w, split);
     647            0 :         child2 = new PackNode(x, y + split, w, h - split);
     648              :     }
     649            0 :     child1->reserve(tx, ty, tw, th);
     650            0 :     child2->reserve(tx, ty, tw, th);
     651            0 :     available = std::max(child1->available, child2->available);
     652              : }
     653              : 
     654            3 : int PackNode::availablespace() const
     655              : {
     656            3 :     return available;
     657              : }
     658              : 
     659            2 : vec2 PackNode::dimensions() const
     660              : {
     661            2 :     return {static_cast<float>(w), static_cast<float>(h)};
     662              : }
     663              : 
     664            7 : void PackNode::printchildren(int i) const
     665              : {
     666            7 :     print(i);
     667              : 
     668            7 :     if(child1)
     669              :     {
     670            3 :         child1->printchildren(i+1);
     671              :     }
     672            7 :     if(child2)
     673              :     {
     674            3 :         child2->printchildren(i+1);
     675              :     }
     676            7 : }
     677              : 
     678            7 : void PackNode::print(int i) const
     679              : {
     680            7 :     std::printf("%d: %d %d\n", i, w, h);
     681            7 : }
     682              : 
     683           19 : void PackNode::discardchildren()
     684              : {
     685           19 :     if(child1)
     686              :     {
     687            6 :         delete child1;
     688            6 :         child1 = nullptr;
     689              :     }
     690           19 :     if(child2)
     691              :     {
     692            6 :         delete child2;
     693            6 :         child2 = nullptr;
     694              :     }
     695           19 : }
     696              : 
     697            0 : void PackNode::forceempty()
     698              : {
     699            0 :     discardchildren();
     700            0 :     available = 0;
     701            0 : }
     702              : 
     703            0 : static VARF(lightcachesize, 4, 6, 12, clearlightcache());
     704              : 
     705            0 : void clearlightcache(int id)
     706              : {
     707            0 :     if(id >= 0)
     708              :     {
     709            0 :         const extentity &light = *entities::getents()[id];
     710            0 :         int radius = light.attr1;
     711            0 :         if(radius <= 0)
     712              :         {
     713            0 :             return;
     714              :         }
     715            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++)
     716              :         {
     717            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++)
     718              :             {
     719            0 :                 lightcacheentry &lce = lightcache[lightcachehash(x, y)];
     720            0 :                 if(lce.x != x || lce.y != y)
     721              :                 {
     722            0 :                     continue;
     723              :                 }
     724            0 :                 lce.x = -1;
     725              :             }
     726              :         }
     727            0 :         return;
     728              :     }
     729              : 
     730            0 :     for(lightcacheentry &lce : lightcache)
     731              :     {
     732            0 :         lce.x = -1;
     733              :     }
     734              : }
     735              : 
     736            0 : void cubeworld::calclight()
     737              : {
     738            0 :     remip();
     739            0 :     clearsurfaces(*worldroot);
     740            0 :     calcnormals(filltjoints > 0);
     741            0 :     calcsurfaces(*worldroot, ivec(0, 0, 0), rootworld.mapsize() >> 1);
     742            0 :     clearnormals();
     743            0 :     allchanged();
     744            0 : }
     745              : 
     746            0 : void clearlights()
     747              : {
     748            0 :     clearlightcache();
     749            0 :     clearshadowcache();
     750            0 :     cleardeferredlightshaders();
     751            0 :     resetsmoothgroups();
     752            0 : }
     753              : 
     754            0 : void initlights()
     755              : {
     756            0 :     clearlightcache();
     757            0 :     clearshadowcache();
     758            0 :     loaddeferredlightshaders();
     759            0 : }
        

Generated by: LCOV version 2.0-1