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

Generated by: LCOV version 2.0-1