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

Generated by: LCOV version 2.0-1