LCOV - code coverage report
Current view: top level - engine/render - octarender.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 3 320 0.9 %
Date: 2024-11-22 05:07:59 Functions: 1 20 5.0 %

          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 1.14