LCOV - code coverage report
Current view: top level - engine/render - octarender.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 1.0 % 314 3
Test Date: 2025-10-13 07:05:02 Functions: 5.3 % 19 1

            Line data    Source code
       1              : // octarender.cpp: fill vertex arrays with different cube surfaces.
       2              : #include "../libprimis-headers/cube.h"
       3              : #include "../../shared/geomexts.h"
       4              : #include "../../shared/glemu.h"
       5              : #include "../../shared/glexts.h"
       6              : 
       7              : #include "grass.h"
       8              : #include "octarender.h"
       9              : #include "rendergl.h"
      10              : #include "renderlights.h"
      11              : #include "renderparticles.h"
      12              : #include "rendersky.h"
      13              : #include "renderva.h"
      14              : #include "shader.h"
      15              : #include "shaderparam.h"
      16              : #include "texture.h"
      17              : #include "vacollect.h"
      18              : 
      19              : #include "interface/menus.h"
      20              : 
      21              : #include "world/entities.h"
      22              : #include "world/light.h"
      23              : #include "world/material.h"
      24              : #include "world/octaworld.h"
      25              : #include "world/world.h"
      26              : 
      27              : 
      28              : /* global variables */
      29              : //////////////////////
      30              : 
      31              : int allocva  = 0,
      32              :     wtris    = 0,
      33              :     wverts   = 0,
      34              :     vtris    = 0,
      35              :     vverts   = 0,
      36              :     glde     = 0,
      37              :     gbatches = 0;
      38              : 
      39              : 
      40              : /**
      41              :  * @brief List of all vertex arrays
      42              :  *
      43              :  *  A vector that carries identically all elements also in the various varoot objects.
      44              :  * The entries in the vector will first be the children of varoot[0] followed by
      45              :  * varoot[0] itself, followed by the same for the other VAs in varoot. The last
      46              :  * element should always be `varoot[7]`.
      47              :  */
      48              : std::vector<vtxarray *> valist;
      49              : 
      50              : /**
      51              :  * @brief List of top level vertex arrays
      52              :  *
      53              :  * A vector containing the highest-level vertex array objects.
      54              :  * There will always be at least eight VAs in varoot, corresponding to the eight
      55              :  * subdivisions of the worldroot cube.
      56              :  *
      57              :  * If the eight subdivisions of the worldroot cube are larger than `vamaxsize`,
      58              :  * these cubes will not host the root VA; children of these cubes will be assigned
      59              :  * the root VAs by dropping through child nodes until the cube is no larger than
      60              :  * `vamaxsize`. For a worldroot 4x the linear size of `vamaxsize` this will yield 64
      61              :  * entries in varoot; for a worldroot 8x the linear size, this will yield 512 entries
      62              :  * and so on.
      63              :  */
      64              : std::vector<vtxarray *> varoot;
      65              : 
      66              : ivec worldmin(0, 0, 0),
      67              :      worldmax(0, 0, 0);
      68              : 
      69              : std::vector<tjoint> tjoints;
      70              : 
      71            0 : VARFP(filltjoints, 0, 1, 1, rootworld.allchanged()); //eliminate "sparklies" by filling in geom t-joints
      72              : 
      73              : /* internally relevant functionality */
      74              : ///////////////////////////////////////
      75              : 
      76              : //edgegroup: struct used for tjoint joining (to reduce sparklies between geom faces)
      77              : struct EdgeGroup final
      78              : {
      79              :     ivec slope, origin;
      80              :     int axis;
      81              : 
      82              :     EdgeGroup();
      83              : 
      84            0 :     bool operator==(const EdgeGroup &y) const
      85              :     {
      86            0 :         return slope==y.slope && origin==y.origin;
      87              :     }
      88              : };
      89              : 
      90            0 : EdgeGroup::EdgeGroup()
      91              : {
      92            0 :     axis = 0;
      93            0 : }
      94              : 
      95              : template<>
      96              : struct std::hash<EdgeGroup> final
      97              : {
      98            0 :     size_t operator()(const EdgeGroup &g) const
      99              :     {
     100            0 :         return g.slope.x^g.slope.y^g.slope.z^g.origin.x^g.origin.y^g.origin.z;
     101              :     }
     102              : };
     103              : 
     104              : namespace
     105              : {
     106              :     enum
     107              :     {
     108              :         CubeEdge_Start = 1<<0,
     109              :         CubeEdge_End   = 1<<1,
     110              :         CubeEdge_Flip  = 1<<2,
     111              :         CubeEdge_Dup   = 1<<3
     112              :     };
     113              : 
     114              :     struct CubeEdge final
     115              :     {
     116              :         cube *c;
     117              :         int next, offset;
     118              :         ushort size;
     119              :         uchar index, flags;
     120              :     };
     121              : 
     122              :     std::vector<CubeEdge> cubeedges;
     123              :     std::unordered_map<EdgeGroup, int> edgegroups;
     124              : 
     125            0 :     void gencubeedges(cube &c, const ivec &co, int size)
     126              :     {
     127            0 :         std::array<ivec, Face_MaxVerts> pos;
     128              :         int vis;
     129            0 :         for(int i = 0; i < 6; ++i)
     130              :         {
     131            0 :             if((vis = visibletris(c, i, co, size)))
     132              :             {
     133            0 :                 int numverts = c.ext ? c.ext->surfaces[i].numverts&Face_MaxVerts : 0;
     134            0 :                 if(numverts)
     135              :                 {
     136            0 :                     const vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts;
     137            0 :                     ivec vo = ivec(co).mask(~0xFFF).shl(3);
     138            0 :                     for(int j = 0; j < numverts; ++j)
     139              :                     {
     140            0 :                         const vertinfo &v = verts[j];
     141            0 :                         pos[j] = ivec(v.x, v.y, v.z).add(vo);
     142              :                     }
     143              :                 }
     144            0 :                 else if(c.merged&(1<<i))
     145              :                 {
     146            0 :                     continue;
     147              :                 }
     148              :                 else
     149              :                 {
     150            0 :                     std::array <ivec, 4> v;
     151            0 :                     genfaceverts(c, i, v);
     152            0 :                     int order = vis&4 || (!flataxisface(c, i) && faceconvexity(v) < 0) ? 1 : 0;
     153            0 :                     ivec vo = ivec(co).shl(3);
     154            0 :                     pos[numverts++] = v[order].mul(size).add(vo);
     155            0 :                     if(vis&1)
     156              :                     {
     157            0 :                         pos[numverts++] = v[order+1].mul(size).add(vo);
     158              :                     }
     159            0 :                     pos[numverts++] = v[order+2].mul(size).add(vo);
     160            0 :                     if(vis&2)
     161              :                     {
     162            0 :                         pos[numverts++] = v[(order+3)&3].mul(size).add(vo);
     163              :                     }
     164              :                 }
     165            0 :                 for(int j = 0; j < numverts; ++j)
     166              :                 {
     167            0 :                     int e1 = j,
     168            0 :                         e2 = j+1 < numverts ? j+1 : 0;
     169            0 :                     ivec d = pos[e2];
     170            0 :                     d.sub(pos[e1]);
     171            0 :                     if(!d)
     172              :                     {
     173            0 :                         continue;
     174              :                     }
     175              :                     //axistemp1/2 used in `axis` only
     176              :                     // x = 0, y = 1, z = 2, `int axis` is the largest component of `d` using
     177              :                     // axistemp1/2 to determine if x,y > z and then if x > y
     178            0 :                     int axistemp1 = std::abs(d.x) > std::abs(d.z) ? 0 : 2,
     179            0 :                         axistemp2 = std::abs(d.y) > std::abs(d.z) ? 1 : 2,
     180            0 :                         axis = std::abs(d.x) > std::abs(d.y) ? axistemp1 : axistemp2;
     181            0 :                     if(d[axis] < 0)
     182              :                     {
     183            0 :                         d.neg();
     184            0 :                         std::swap(e1, e2);
     185              :                     }
     186            0 :                     reduceslope(d);
     187            0 :                     int t1 = pos[e1][axis]/d[axis],
     188            0 :                         t2 = pos[e2][axis]/d[axis];
     189            0 :                     EdgeGroup g;
     190            0 :                     g.origin = ivec(pos[e1]).sub(ivec(d).mul(t1));
     191            0 :                     g.slope = d;
     192            0 :                     g.axis = axis;
     193              :                     CubeEdge ce;
     194            0 :                     ce.c = &c;
     195            0 :                     ce.offset = t1;
     196            0 :                     ce.size = t2 - t1;
     197            0 :                     ce.index = i*(Face_MaxVerts+1)+j;
     198            0 :                     ce.flags = CubeEdge_Start | CubeEdge_End | (e1!=j ? CubeEdge_Flip : 0);
     199            0 :                     ce.next = -1;
     200            0 :                     bool insert = true;
     201            0 :                     std::unordered_map<EdgeGroup, int>::iterator exists = edgegroups.find(g);
     202            0 :                     if(exists != edgegroups.end())
     203              :                     {
     204            0 :                         int prev = -1,
     205            0 :                             cur  = (*exists).second;
     206            0 :                         while(cur >= 0)
     207              :                         {
     208            0 :                             CubeEdge &p = cubeedges[cur];
     209            0 :                             if(p.flags&CubeEdge_Dup ?
     210            0 :                                 ce.offset>=p.offset && ce.offset+ce.size<=p.offset+p.size :
     211            0 :                                 ce.offset==p.offset && ce.size==p.size)
     212              :                             {
     213            0 :                                 p.flags |= CubeEdge_Dup;
     214            0 :                                 insert = false;
     215            0 :                                 break;
     216              :                             }
     217            0 :                             else if(ce.offset >= p.offset)
     218              :                             {
     219            0 :                                 if(ce.offset == p.offset+p.size)
     220              :                                 {
     221            0 :                                     ce.flags &= ~CubeEdge_Start;
     222              :                                 }
     223            0 :                                 prev = cur;
     224            0 :                                 cur = p.next;
     225              :                             }
     226              :                             else
     227              :                             {
     228            0 :                                 break;
     229              :                             }
     230              :                         }
     231            0 :                         if(insert)
     232              :                         {
     233            0 :                             ce.next = cur;
     234            0 :                             while(cur >= 0)
     235              :                             {
     236            0 :                                 const CubeEdge &p = cubeedges[cur];
     237            0 :                                 if(ce.offset+ce.size==p.offset)
     238              :                                 {
     239            0 :                                     ce.flags &= ~CubeEdge_End;
     240            0 :                                     break;
     241              :                                 }
     242            0 :                                 cur = p.next;
     243              :                             }
     244            0 :                             if(prev>=0)
     245              :                             {
     246            0 :                                 cubeedges[prev].next = cubeedges.size();
     247              :                             }
     248              :                             else
     249              :                             {
     250            0 :                                 (*exists).second = cubeedges.size();
     251              :                             }
     252              :                         }
     253              :                     }
     254              :                     else
     255              :                     {
     256            0 :                         edgegroups[g] = cubeedges.size();
     257              :                     }
     258            0 :                     if(insert)
     259              :                     {
     260            0 :                         cubeedges.push_back(ce);
     261              :                     }
     262              :                 }
     263              :             }
     264              :         }
     265            0 :     }
     266              : 
     267            0 :     void gencubeedges(std::array<cube, 8> &c, const ivec &co = ivec(0, 0, 0), int size = rootworld.mapsize()>>1)
     268              :     {
     269            0 :         neighborstack[++neighbordepth] = &c[0];
     270            0 :         for(int i = 0; i < 8; ++i)
     271              :         {
     272            0 :             ivec o(i, co, size);
     273            0 :             if(c[i].ext)
     274              :             {
     275            0 :                 c[i].ext->tjoints = -1;
     276              :             }
     277            0 :             if(c[i].children)
     278              :             {
     279            0 :                 gencubeedges(*(c[i].children), o, size>>1);
     280              :             }
     281            0 :             else if(!(c[i].isempty()))
     282              :             {
     283            0 :                 gencubeedges(c[i], o, size);
     284              :             }
     285              :         }
     286            0 :         --neighbordepth;
     287            0 :     }
     288              : 
     289            0 :     void addtjoint(const EdgeGroup &g, const CubeEdge &e, int offset)
     290              :     {
     291            0 :         const int vcoord = (g.slope[g.axis]*offset + g.origin[g.axis]) & 0x7FFF;
     292            0 :         tjoint tj = tjoint();
     293            0 :         tj.offset = vcoord / g.slope[g.axis];
     294            0 :         tj.edge = e.index;
     295            0 :         int prev = -1,
     296            0 :             cur  = ext(*e.c).tjoints;
     297            0 :         while(cur >= 0)
     298              :         {
     299            0 :             const tjoint &o = tjoints[cur];
     300            0 :             if(tj.edge < o.edge || (tj.edge==o.edge && (e.flags&CubeEdge_Flip ? tj.offset > o.offset : tj.offset < o.offset)))
     301              :             {
     302              :                 break;
     303              :             }
     304            0 :             prev = cur;
     305            0 :             cur = o.next;
     306              :         }
     307            0 :         tj.next = cur;
     308            0 :         tjoints.push_back(tj);
     309            0 :         if(prev < 0)
     310              :         {
     311            0 :             e.c->ext->tjoints = tjoints.size()-1;
     312              :         }
     313              :         else
     314              :         {
     315            0 :             tjoints[prev].next = tjoints.size()-1;
     316              :         }
     317            0 :     }
     318              : 
     319              : 
     320              :     /**
     321              :      * @brief Calls lookupvslot for textures associated with the VA list
     322              :      *
     323              :      * Searches the VA list for all associated texture indices and calls lookupvslot
     324              :      * for each one found. Only calls once even if multiple VAs share the same
     325              :      * texture.
     326              :      */
     327            0 :     void precachetextures()
     328              :     {
     329            0 :         std::vector<int> texs;
     330            0 :         for(size_t i = 0; i < valist.size(); i++)
     331              :         {
     332            0 :             const vtxarray *va = valist[i];
     333            0 :             for(int j = 0; j < va->texs; ++j)
     334              :             {
     335            0 :                 int tex = va->texelems[j].texture;
     336            0 :                 if(std::find(texs.begin(), texs.end(), tex) == texs.end())
     337              :                 {
     338            0 :                     texs.push_back(tex);
     339              :                 }
     340              :             }
     341              :         }
     342            0 :         for(size_t i = 0; i < texs.size(); i++)
     343              :         {
     344            0 :             lookupvslot(texs[i]);
     345              :         }
     346            0 :     }
     347              : }
     348              : 
     349              : /* externally relevant functionality */
     350              : ///////////////////////////////////////
     351              : 
     352            0 : void findtjoints(int cur, const EdgeGroup &g)
     353              : {
     354            0 :     int active = -1;
     355            0 :     while(cur >= 0)
     356              :     {
     357            0 :         CubeEdge &e = cubeedges[cur];
     358            0 :         int prevactive = -1,
     359            0 :             curactive  = active;
     360            0 :         while(curactive >= 0)
     361              :         {
     362            0 :             const CubeEdge &a = cubeedges[curactive];
     363            0 :             if(a.offset+a.size <= e.offset)
     364              :             {
     365            0 :                 if(prevactive >= 0)
     366              :                 {
     367            0 :                     cubeedges[prevactive].next = a.next;
     368              :                 }
     369              :                 else
     370              :                 {
     371            0 :                     active = a.next;
     372              :                 }
     373              :             }
     374              :             else
     375              :             {
     376            0 :                 prevactive = curactive;
     377            0 :                 if(!(a.flags&CubeEdge_Dup))
     378              :                 {
     379            0 :                     if(e.flags&CubeEdge_Start && e.offset > a.offset && e.offset < a.offset+a.size)
     380              :                     {
     381            0 :                         addtjoint(g, a, e.offset);
     382              :                     }
     383            0 :                     if(e.flags&CubeEdge_End && e.offset+e.size > a.offset && e.offset+e.size < a.offset+a.size)
     384              :                     {
     385            0 :                         addtjoint(g, a, e.offset+e.size);
     386              :                     }
     387              :                 }
     388            0 :                 if(!(e.flags&CubeEdge_Dup))
     389              :                 {
     390            0 :                     if(a.flags&CubeEdge_Start && a.offset > e.offset && a.offset < e.offset+e.size)
     391              :                     {
     392            0 :                         addtjoint(g, e, a.offset);
     393              :                     }
     394            0 :                     if(a.flags&CubeEdge_End && a.offset+a.size > e.offset && a.offset+a.size < e.offset+e.size)
     395              :                     {
     396            0 :                         addtjoint(g, e, a.offset+a.size);
     397              :                     }
     398              :                 }
     399              :             }
     400            0 :             curactive = a.next;
     401              :         }
     402            0 :         int next = e.next;
     403            0 :         e.next = active;
     404            0 :         active = cur;
     405            0 :         cur = next;
     406              :     }
     407            0 : }
     408              : 
     409            0 : void reduceslope(ivec &n)
     410              : {
     411            0 :     int mindim = -1,
     412            0 :         minval = 64;
     413            0 :     for(int i = 0; i < 3; ++i)
     414              :     {
     415            0 :         if(n[i])
     416              :         {
     417            0 :             int val = std::abs(n[i]);
     418            0 :             if(mindim < 0 || val < minval)
     419              :             {
     420            0 :                 mindim = i;
     421            0 :                 minval = val;
     422              :             }
     423              :         }
     424              :     }
     425            0 :     if(!(n[R[mindim]]%minval) && !(n[C[mindim]]%minval))
     426              :     {
     427            0 :         n.div(minval);
     428              :     }
     429            0 :     while(!((n.x|n.y|n.z)&1))
     430              :     {
     431            0 :         n.shr(1); //shift right 1 to reduce slope
     432              :     }
     433            0 : }
     434              : 
     435            0 : void guessnormals(const vec *pos, int numverts, vec *normals)
     436              : {
     437            0 :     vec n1, n2;
     438            0 :     n1.cross(pos[0], pos[1], pos[2]);
     439            0 :     if(numverts != 4)
     440              :     {
     441            0 :         n1.normalize();
     442            0 :         for(int k = 0; k < numverts; ++k)
     443              :         {
     444            0 :             normals[k] = n1;
     445              :         }
     446            0 :         return;
     447              :     }
     448            0 :     n2.cross(pos[0], pos[2], pos[3]);
     449            0 :     if(n1.iszero())
     450              :     {
     451            0 :         n2.normalize();
     452            0 :         for(int k = 0; k < 4; ++k)
     453              :         {
     454            0 :             normals[k] = n2;
     455              :         }
     456            0 :         return;
     457              :     }
     458              :     else
     459              :     {
     460            0 :         n1.normalize();
     461              :     }
     462            0 :     if(n2.iszero())
     463              :     {
     464            0 :         for(int k = 0; k < 4; ++k)
     465              :         {
     466            0 :             normals[k] = n1;
     467              :         }
     468            0 :         return;
     469              :     }
     470              :     else
     471              :     {
     472            0 :         n2.normalize();
     473              :     }
     474            0 :     vec avg = vec(n1).add(n2).normalize();
     475            0 :     normals[0] = avg;
     476            0 :     normals[1] = n1;
     477            0 :     normals[2] = avg;
     478            0 :     normals[3] = n2;
     479              : }
     480              : 
     481              : //va external fxns
     482              : 
     483            0 : void destroyva(vtxarray *va, bool reparent)
     484              : {
     485            0 :     wverts -= va->verts;
     486            0 :     wtris -= va->tris + va->alphabacktris + va->alphafronttris + va->refracttris + va->decaltris;
     487            0 :     allocva--;
     488            0 :     std::vector<vtxarray *>::iterator itr = std::find(valist.begin(), valist.end(), va);
     489            0 :     if(itr != valist.end())
     490              :     {
     491            0 :         valist.erase(itr);
     492              :     }
     493            0 :     if(!va->parent)
     494              :     {
     495            0 :         std::vector<vtxarray *>::iterator itr2 = std::find(valist.begin(), valist.end(), va);
     496            0 :         if(itr2 != valist.end())
     497              :         {
     498            0 :             valist.erase(itr2);
     499              :         }
     500              :     }
     501            0 :     if(reparent)
     502              :     {
     503            0 :         if(va->parent)
     504              :         {
     505            0 :             std::vector<vtxarray *>::iterator itr = std::find(va->parent->children.begin(), va->parent->children.end(), va);
     506            0 :             if(itr != va->parent->children.end())
     507              :             {
     508            0 :                 va->parent->children.erase(itr);
     509              :             }
     510              :         }
     511            0 :         for(size_t i = 0; i < va->children.size(); i++)
     512              :         {
     513            0 :             vtxarray *child = va->children[i];
     514            0 :             child->parent = va->parent;
     515            0 :             if(child->parent)
     516              :             {
     517            0 :                 child->parent->children.push_back(child);
     518              :             }
     519              :         }
     520              :     }
     521            0 :     if(va->vbuf)
     522              :     {
     523            0 :         destroyvbo(va->vbuf);
     524              :     }
     525            0 :     if(va->ebuf)
     526              :     {
     527            0 :         destroyvbo(va->ebuf);
     528              :     }
     529            0 :     if(va->skybuf)
     530              :     {
     531            0 :         destroyvbo(va->skybuf);
     532              :     }
     533            0 :     if(va->decalbuf)
     534              :     {
     535            0 :         destroyvbo(va->decalbuf);
     536              :     }
     537            0 :     if(va->texelems)
     538              :     {
     539            0 :         delete[] va->texelems;
     540              :     }
     541            0 :     if(va->decalelems)
     542              :     {
     543            0 :         delete[] va->decalelems;
     544              :     }
     545            0 :     delete va;
     546            0 : }
     547              : 
     548            0 : void clearvas(std::array<cube, 8> &c)
     549              : {
     550            0 :     for(int i = 0; i < 8; ++i)
     551              :     {
     552            0 :         if(c[i].ext)
     553              :         {
     554            0 :             if(c[i].ext->va)
     555              :             {
     556            0 :                 destroyva(c[i].ext->va, false);
     557              :             }
     558            0 :             c[i].ext->va = nullptr;
     559            0 :             c[i].ext->tjoints = -1;
     560              :         }
     561            0 :         if(c[i].children)
     562              :         {
     563            0 :             clearvas(*c[i].children);
     564              :         }
     565              :     }
     566            0 : }
     567              : 
     568            0 : void vtxarray::updatevabb(bool force)
     569              : {
     570            0 :     if(!force && bbmin.x >= 0)
     571              :     {
     572            0 :         return;
     573              :     }
     574            0 :     bbmin = geommin;
     575            0 :     bbmax = geommax;
     576            0 :     bbmin.min(watermin);
     577            0 :     bbmax.max(watermax);
     578            0 :     bbmin.min(glassmin);
     579            0 :     bbmax.max(glassmax);
     580            0 :     for(vtxarray *child : children)
     581              :     {
     582            0 :         child->updatevabb(force);
     583            0 :         bbmin.min(child->bbmin);
     584            0 :         bbmax.max(child->bbmax);
     585              :     }
     586            0 :     for(const octaentities *oe : mapmodels)
     587              :     {
     588            0 :         bbmin.min(oe->bbmin);
     589            0 :         bbmax.max(oe->bbmax);
     590              :     }
     591            0 :     for(const octaentities *oe : decals)
     592              :     {
     593            0 :         bbmin.min(oe->bbmin);
     594            0 :         bbmax.max(oe->bbmax);
     595              :     }
     596            0 :     bbmin.max(o);
     597            0 :     bbmax.min(ivec(o).add(size));
     598            0 :     worldmin.min(bbmin);
     599            0 :     worldmax.max(bbmax);
     600              : }
     601              : 
     602              : //update vertex array bounding boxes recursively from the root va object down to all children
     603            0 : void updatevabbs(bool force)
     604              : {
     605            0 :     if(force)
     606              :     {
     607            0 :         worldmin = ivec(rootworld.mapsize(), rootworld.mapsize(), rootworld.mapsize());
     608            0 :         worldmax = ivec(0, 0, 0);
     609            0 :         for(size_t i = 0; i < varoot.size(); i++)
     610              :         {
     611            0 :             varoot[i]->updatevabb(true);
     612              :         }
     613            0 :         if(worldmin.x >= worldmax.x)
     614              :         {
     615            0 :             worldmin = ivec(0, 0, 0);
     616            0 :             worldmax = ivec(rootworld.mapsize(), rootworld.mapsize(), rootworld.mapsize());
     617              :         }
     618              :     }
     619              :     else
     620              :     {
     621            0 :         for(size_t i = 0; i < varoot.size(); i++)
     622              :         {
     623            0 :             varoot[i]->updatevabb();
     624              :         }
     625              :     }
     626            0 : }
     627              : 
     628            0 : void cubeworld::findtjoints()
     629              : {
     630            0 :     gencubeedges(*worldroot);
     631            0 :     tjoints.clear();
     632            0 :     for(auto &[k, t] : edgegroups)
     633              :     {
     634            0 :         ::findtjoints(t, k);
     635              :     }
     636            0 :     cubeedges.clear();
     637            0 :     edgegroups.clear();
     638            0 : }
     639              : 
     640            1 : void cubeworld::allchanged(bool load)
     641              : {
     642            1 :     if(!worldroot)
     643              :     {
     644            1 :         return;
     645              :     }
     646            0 :     if(mainmenu)
     647              :     {
     648            0 :         load = false;
     649              :     }
     650            0 :     if(load)
     651              :     {
     652            0 :         initlights();
     653              :     }
     654            0 :     clearvas(*worldroot);
     655            0 :     occlusionengine.resetqueries();
     656            0 :     resetclipplanes();
     657            0 :     entitiesinoctanodes();
     658            0 :     tjoints.clear();
     659            0 :     if(filltjoints)
     660              :     {
     661            0 :         findtjoints();
     662              :     }
     663            0 :     octarender();
     664            0 :     if(load)
     665              :     {
     666            0 :         precachetextures();
     667              :     }
     668            0 :     setupmaterials();
     669            0 :     clearshadowcache();
     670            0 :     updatevabbs(true);
     671            0 :     if(load)
     672              :     {
     673            0 :         genshadowmeshes();
     674            0 :         seedparticles();
     675              :     }
     676              : }
     677              : 
     678            0 : void initoctarendercmds()
     679              : {
     680            0 :     addcommand("recalc", reinterpret_cast<identfun>(+[](){rootworld.allchanged(true);}), "", Id_Command);
     681            0 : }
        

Generated by: LCOV version 2.0-1