LCOV - code coverage report
Current view: top level - engine/world - octacube.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 28.9 % 425 123
Test Date: 2025-02-21 06:59:27 Functions: 55.6 % 18 10

            Line data    Source code
       1              : /**
       2              :  * @brief cube object member functions
       3              :  *
       4              :  * This file implements the methods applying to the cube object, the individual
       5              :  * unit which acts as the nodes in a cubeworld octal tree.
       6              :  */
       7              : 
       8              : #include "../libprimis-headers/cube.h"
       9              : #include "../../shared/geomexts.h"
      10              : 
      11              : #include "light.h"
      12              : #include "octaworld.h"
      13              : #include "raycube.h"
      14              : #include "world.h"
      15              : 
      16              : #include "interface/console.h"
      17              : 
      18              : #include "render/octarender.h"
      19              : #include "render/renderwindow.h"
      20              : 
      21              : VAR(maxmerge, 0, 6, 12); //max gridpower to remip merge
      22              : VAR(minface, 0, 4, 12);
      23              : 
      24            0 : bool touchingface(const cube &c, int orient)
      25              : {
      26            0 :     uint face = c.faces[DIMENSION(orient)];
      27            0 :     return DIM_COORD(orient) ? (face&0xF0F0F0F0)==0x80808080 : (face&0x0F0F0F0F)==0;
      28              : }
      29              : 
      30            0 : bool notouchingface(const cube &c, int orient)
      31              : {
      32            0 :     uint face = c.faces[DIMENSION(orient)];
      33            0 :     return DIM_COORD(orient) ? (face&0x80808080)==0 : ((0x88888888-face)&0x08080808) == 0;
      34              : }
      35              : 
      36            0 : bool cube::mincubeface(const cube &cu, int orient, const ivec &co, int size, facebounds &orig) const
      37              : {
      38            0 :     ivec no;
      39              :     int nsize;
      40            0 :     const cube &nc = rootworld.neighborcube(orient, co, size, no, nsize);
      41              :     facebounds mincf;
      42            0 :     mincf.u1 = orig.u2;
      43            0 :     mincf.u2 = orig.u1;
      44            0 :     mincf.v1 = orig.v2;
      45            0 :     mincf.v2 = orig.v1;
      46            0 :     mincubeface(nc, oppositeorient(orient), no, nsize, orig, mincf, cu.material&Mat_Alpha ? Mat_Air : Mat_Alpha, Mat_Alpha);
      47            0 :     bool smaller = false;
      48            0 :     if(mincf.u1 > orig.u1)
      49              :     {
      50            0 :         orig.u1 = mincf.u1;
      51            0 :         smaller = true;
      52              :     }
      53            0 :     if(mincf.u2 < orig.u2)
      54              :     {
      55            0 :         orig.u2 = mincf.u2;
      56            0 :         smaller = true;
      57              :     }
      58            0 :     if(mincf.v1 > orig.v1)
      59              :     {
      60            0 :         orig.v1 = mincf.v1;
      61            0 :         smaller = true;
      62              :     }
      63            0 :     if(mincf.v2 < orig.v2)
      64              :     {
      65            0 :         orig.v2 = mincf.v2;
      66            0 :         smaller = true;
      67              :     }
      68            0 :     return smaller;
      69              : }
      70              : 
      71              : template <>
      72              : struct std::hash<cube::plink>
      73              : {
      74          372 :     size_t operator()(const cube::plink& x) const
      75              :     {
      76          372 :         return static_cast<size_t>(x.from.x)^(static_cast<size_t>(x.from.y)<<8);
      77              :     }
      78              : };
      79              : 
      80            0 : void cube::freecubeext(cube &c)
      81              : {
      82            0 :     if(c.ext)
      83              :     {
      84            0 :         delete[] reinterpret_cast<uchar *>(c.ext);
      85            0 :         c.ext = nullptr;
      86              :     }
      87            0 : }
      88              : 
      89           16 : void cube::discardchildren(bool fixtex, int depth)
      90              : {
      91           16 :     visible = 0;
      92           16 :     merged = 0;
      93           16 :     if(ext)
      94              :     {
      95            0 :         if(ext->va)
      96              :         {
      97            0 :             destroyva(ext->va);
      98              :         }
      99            0 :         ext->va = nullptr;
     100            0 :         ext->tjoints = -1;
     101            0 :         freeoctaentities(*this);
     102            0 :         freecubeext(*this);
     103              :     }
     104           16 :     if(children)
     105              :     {
     106            1 :         uint filled = faceempty;
     107            9 :         for(int i = 0; i < 8; ++i)
     108              :         {
     109            8 :             (*children)[i].discardchildren(fixtex, depth+1);
     110            8 :             filled |= (*children)[i].faces[0];
     111              :         }
     112            1 :         if(fixtex)
     113              :         {
     114            0 :             for(int i = 0; i < 6; ++i)
     115              :             {
     116            0 :                 texture[i] = getmippedtexture(*this, i);
     117              :             }
     118            0 :             if(depth > 0 && filled != faceempty)
     119              :             {
     120            0 :                 faces[0] = facesolid;
     121              :             }
     122              :         }
     123            1 :         delete children;
     124            1 :         children = nullptr;
     125            1 :         allocnodes--;
     126              :     }
     127           16 : }
     128              : 
     129            0 : bool cube::isvalidcube() const
     130              : {
     131            0 :     clipplanes p;
     132            0 :     genclipbounds(*this, ivec(0, 0, 0), 256, p);
     133            0 :     genclipplanes(*this, ivec(0, 0, 0), 256, p);
     134              :     // test that cube is convex
     135            0 :     for(uchar i = 0; i < 8; ++i)
     136              :     {
     137            0 :         vec v = p.v[i];
     138            0 :         for(uchar j = 0; j < p.size; ++j)
     139              :         {
     140            0 :             if(p.p[j].dist(v)>1e-3f)
     141              :             {
     142            0 :                 return false;
     143              :             }
     144              :         }
     145              :     }
     146            0 :     return true;
     147              : }
     148              : 
     149            0 : bool cube::poly::clippoly(const facebounds &b)
     150              : {
     151            0 :     std::array<pvert, Face_MaxVerts+4> verts1,
     152            0 :                                        verts2;
     153            0 :     int numverts1 = 0,
     154            0 :         numverts2 = 0,
     155            0 :         px = verts[numverts-1].x,
     156            0 :         py = verts[numverts-1].y;
     157            0 :     for(int i = 0; i < numverts; ++i)
     158              :     {
     159            0 :         int x = verts[i].x,
     160            0 :             y = verts[i].y;
     161            0 :         if(x < b.u1)
     162              :         {
     163            0 :             if(px > b.u2)
     164              :             {
     165            0 :                 verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px));
     166              :             }
     167            0 :             if(px > b.u1)
     168              :             {
     169            0 :                 verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px));
     170              :             }
     171              :         }
     172            0 :         else if(x > b.u2)
     173              :         {
     174            0 :             if(px < b.u1)
     175              :             {
     176            0 :                 verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px));
     177              :             }
     178            0 :             if(px < b.u2)
     179              :             {
     180            0 :                 verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px));
     181              :             }
     182              :         }
     183              :         else
     184              :         {
     185            0 :             if(px < b.u1)
     186              :             {
     187            0 :                 if(x > b.u1)
     188              :                 {
     189            0 :                     verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px));
     190              :                 }
     191              :             }
     192            0 :             else if(px > b.u2 && x < b.u2)
     193              :             {
     194            0 :                 verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px));
     195              :             }
     196            0 :             verts1[numverts1++] = pvert(x, y);
     197              :         }
     198            0 :         px = x;
     199            0 :         py = y;
     200              :     }
     201            0 :     if(numverts1 < 3)
     202              :     {
     203            0 :         return false;
     204              :     }
     205            0 :     px = verts1[numverts1-1].x;
     206            0 :     py = verts1[numverts1-1].y;
     207            0 :     for(int i = 0; i < numverts1; ++i)
     208              :     {
     209            0 :         int x = verts1[i].x, y = verts1[i].y;
     210            0 :         if(y < b.v1)
     211              :         {
     212            0 :             if(py > b.v2)
     213              :             {
     214            0 :                 verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2);
     215              :             }
     216            0 :             if(py > b.v1)
     217              :             {
     218            0 :                 verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1);
     219              :             }
     220              :         }
     221            0 :         else if(y > b.v2)
     222              :         {
     223            0 :             if(py < b.v1)
     224              :             {
     225            0 :                 verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1);
     226              :             }
     227            0 :             if(py < b.v2)
     228              :             {
     229            0 :                 verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2);
     230              :             }
     231              :         }
     232              :         else
     233              :         {
     234            0 :             if(py < b.v1)
     235              :             {
     236            0 :                 if(y > b.v1)
     237              :                 {
     238            0 :                     verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1);
     239              :                 }
     240              :             }
     241            0 :             else if(py > b.v2 && y < b.v2)
     242              :             {
     243            0 :                 verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2);
     244              :             }
     245            0 :             verts2[numverts2++] = pvert(x, y);
     246              :         }
     247            0 :         px = x;
     248            0 :         py = y;
     249              :     }
     250            0 :     if(numverts2 < 3)
     251              :     {
     252            0 :         return false;
     253              :     }
     254            0 :     if(numverts2 > Face_MaxVerts)
     255              :     {
     256            0 :         return false;
     257              :     }
     258            0 :     std::memcpy(verts, verts2.data(), numverts2*sizeof(pvert));
     259            0 :     numverts = numverts2;
     260            0 :     return true;
     261              : }
     262              : 
     263           48 : bool cube::genpoly(int orient, const ivec &o, int size, int vis, ivec &n, int &offset, poly &p)
     264              : {
     265           48 :     int dim = DIMENSION(orient),
     266           48 :         coord = DIM_COORD(orient);
     267           48 :     std::array<ivec, 4> v;
     268           48 :     genfaceverts(*this, orient, v);
     269           48 :     if(flataxisface(*this, orient))
     270              :     {
     271           48 :          n = ivec(0, 0, 0);
     272           48 :          n[dim] = coord ? 1 : -1;
     273              :     }
     274              :     else
     275              :     {
     276            0 :         if(faceconvexity(v))
     277              :         {
     278            0 :             return false;
     279              :         }
     280            0 :         n.cross(ivec(v[1]).sub(v[0]), ivec(v[2]).sub(v[0]));
     281            0 :         if(!n)
     282              :         {
     283            0 :             n.cross(ivec(v[2]).sub(v[0]), ivec(v[3]).sub(v[0]));
     284              :         }
     285            0 :         reduceslope(n);
     286              :     }
     287              : 
     288           48 :     ivec po = ivec(o).mask(0xFFF).shl(3);
     289          240 :     for(int k = 0; k < 4; ++k)
     290              :     {
     291          192 :         v[k].mul(size).add(po);
     292              :     }
     293           48 :     offset = -n.dot(v[3]);
     294           48 :     int r = R[dim],
     295           48 :         c = C[dim],
     296           48 :         order = vis&4 ? 1 : 0;
     297           48 :     p.numverts = 0;
     298           48 :     if(coord)
     299              :     {
     300           24 :         const ivec &v0 = v[order];
     301           24 :         p.verts[p.numverts++] = pvert(v0[c], v0[r]);
     302           24 :         if(vis&1)
     303              :         {
     304           24 :             const ivec &v1 = v[order+1];
     305           24 :             p.verts[p.numverts++] = pvert(v1[c], v1[r]);
     306              :         }
     307           24 :         const ivec &v2 = v[order+2];
     308           24 :         p.verts[p.numverts++] = pvert(v2[c], v2[r]);
     309           24 :         if(vis&2)
     310              :         {
     311           24 :             const ivec &v3 = v[(order+3)&3];
     312           24 :             p.verts[p.numverts++] = pvert(v3[c], v3[r]);
     313              :         }
     314              :     }
     315              :     else
     316              :     {
     317              :         //3&1 are checked, 0&2 are not
     318           24 :         if(vis&2)
     319              :         {
     320           24 :             const ivec &v3 = v[(order+3)&3];
     321           24 :             p.verts[p.numverts++] = pvert(v3[c], v3[r]);
     322              :         }
     323           24 :         const ivec &v2 = v[order+2];
     324           24 :         p.verts[p.numverts++] = pvert(v2[c], v2[r]);
     325           24 :         if(vis&1)
     326              :         {
     327           24 :             const ivec &v1 = v[order+1];
     328           24 :             p.verts[p.numverts++] = pvert(v1[c], v1[r]);
     329              :         }
     330           24 :         const ivec &v0 = v[order];
     331           24 :         p.verts[p.numverts++] = pvert(v0[c], v0[r]);
     332              :     }
     333              : 
     334           48 :     if(faceedges(*this, orient) != facesolid)
     335              :     {
     336            0 :         int px = static_cast<int>(p.verts[p.numverts-2].x) - static_cast<int>(p.verts[p.numverts-3].x),
     337            0 :             py = static_cast<int>(p.verts[p.numverts-2].y) - static_cast<int>(p.verts[p.numverts-3].y),
     338            0 :             cx = static_cast<int>(p.verts[p.numverts-1].x) - static_cast<int>(p.verts[p.numverts-2].x),
     339            0 :             cy = static_cast<int>(p.verts[p.numverts-1].y) - static_cast<int>(p.verts[p.numverts-2].y),
     340            0 :             dir = px*cy - py*cx;
     341            0 :         if(dir > 0)
     342              :         {
     343            0 :             return false;
     344              :         }
     345            0 :         if(!dir)
     346              :         {
     347            0 :             if(p.numverts < 4)
     348              :             {
     349            0 :                 return false;
     350              :             }
     351            0 :             p.verts[p.numverts-2] = p.verts[p.numverts-1];
     352            0 :             p.numverts--;
     353              :         }
     354            0 :         px = cx;
     355            0 :         py = cy;
     356            0 :         cx = static_cast<int>(p.verts[0].x) - static_cast<int>(p.verts[p.numverts-1].x);
     357            0 :         cy = static_cast<int>(p.verts[0].y) - static_cast<int>(p.verts[p.numverts-1].y);
     358            0 :         dir = px*cy - py*cx;
     359            0 :         if(dir > 0)
     360              :         {
     361            0 :             return false;
     362              :         }
     363            0 :         if(!dir)
     364              :         {
     365            0 :             if(p.numverts < 4)
     366              :             {
     367            0 :                 return false;
     368              :             }
     369            0 :             p.numverts--;
     370              :         }
     371            0 :         px = cx;
     372            0 :         py = cy;
     373            0 :         cx = static_cast<int>(p.verts[1].x) - static_cast<int>(p.verts[0].x);
     374            0 :         cy = static_cast<int>(p.verts[1].y) - static_cast<int>(p.verts[0].y);
     375            0 :         dir = px*cy - py*cx;
     376            0 :         if(dir > 0)
     377              :         {
     378            0 :             return false;
     379              :         }
     380            0 :         if(!dir)
     381              :         {
     382            0 :             if(p.numverts < 4)
     383              :             {
     384            0 :                 return false;
     385              :             }
     386            0 :             p.verts[0] = p.verts[p.numverts-1];
     387            0 :             p.numverts--;
     388              :         }
     389            0 :         px = cx;
     390            0 :         py = cy;
     391            0 :         cx = static_cast<int>(p.verts[2].x) - static_cast<int>(p.verts[1].x);
     392            0 :         cy = static_cast<int>(p.verts[2].y) - static_cast<int>(p.verts[1].y);
     393            0 :         dir = px*cy - py*cx;
     394            0 :         if(dir > 0)
     395              :         {
     396            0 :             return false;
     397              :         }
     398            0 :         if(!dir)
     399              :         {
     400            0 :             if(p.numverts < 4)
     401              :             {
     402            0 :                 return false;
     403              :             }
     404            0 :             p.verts[1] = p.verts[2];
     405            0 :             p.verts[2] = p.verts[3];
     406            0 :             p.numverts--;
     407              :         }
     408              :     }
     409           48 :     p.c = this;
     410           48 :     p.merged = false;
     411           48 :     if(minface && size >= 1<<minface && touchingface(*this, orient))
     412              :     {
     413              :         facebounds b;
     414            0 :         b.u1 = b.u2 = p.verts[0].x;
     415            0 :         b.v1 = b.v2 = p.verts[0].y;
     416            0 :         for(int i = 1; i < p.numverts; i++)
     417              :         {
     418            0 :             const pvert &v = p.verts[i];
     419            0 :             b.u1 = std::min(b.u1, v.x);
     420            0 :             b.u2 = std::max(b.u2, v.x);
     421            0 :             b.v1 = std::min(b.v1, v.y);
     422            0 :             b.v2 = std::max(b.v2, v.y);
     423              :         }
     424            0 :         if(mincubeface(*this, orient, o, size, b) && p.clippoly(b))
     425              :         {
     426            0 :             p.merged = true;
     427              :         }
     428              :     }
     429           48 :     return true;
     430              : }
     431              : 
     432            0 : bool cube::poly::mergepolys(std::unordered_set<plink> &links, std::deque<const plink *> &queue, int owner, poly &q, const pedge &e)
     433              : {
     434            0 :     int pe = -1,
     435            0 :         qe = -1;
     436            0 :     for(int i = 0; i < numverts; ++i)
     437              :     {
     438            0 :         if(verts[i] == e.from)
     439              :         {
     440            0 :             pe = i;
     441            0 :             break;
     442              :         }
     443              :     }
     444            0 :     for(int i = 0; i < q.numverts; ++i)
     445              :     {
     446            0 :         if(q.verts[i] == e.to)
     447              :         {
     448            0 :             qe = i;
     449            0 :             break;
     450              :         }
     451              :     }
     452            0 :     if(pe < 0 || qe < 0)
     453              :     {
     454            0 :         return false;
     455              :     }
     456            0 :     if(verts[(pe+1)%numverts] != e.to || q.verts[(qe+1)%q.numverts] != e.from)
     457              :     {
     458            0 :         return false;
     459              :     }
     460              :     /*
     461              :      *  c----d
     462              :      *  |    |
     463              :      *  F----T
     464              :      *  |  P |
     465              :      *  b----a
     466              :      */
     467            0 :     pvert mergeverts[2*Face_MaxVerts];
     468            0 :     int nummergeverts = 0,
     469            0 :         index = pe+2; // starts at A = T+1, ends at F = T+this.numverts
     470            0 :     for(int i = 0; i < numverts-1; ++i)
     471              :     {
     472            0 :         if(index >= numverts)
     473              :         {
     474            0 :             index -= numverts;
     475              :         }
     476            0 :         mergeverts[nummergeverts++] = verts[index++];
     477              :     }
     478            0 :     index = qe+2; // starts at C = T+2 = F+1, ends at T = T+q.numverts
     479            0 :     int px = static_cast<int>(mergeverts[nummergeverts-1].x) - static_cast<int>(mergeverts[nummergeverts-2].x),
     480            0 :         py = static_cast<int>(mergeverts[nummergeverts-1].y) - static_cast<int>(mergeverts[nummergeverts-2].y);
     481            0 :     for(int i = 0; i < q.numverts-1; ++i)
     482              :     {
     483            0 :         if(index >= q.numverts)
     484              :         {
     485            0 :             index -= q.numverts;
     486              :         }
     487            0 :         const pvert &src = q.verts[index++];
     488            0 :         int cx = static_cast<int>(src.x) - static_cast<int>(mergeverts[nummergeverts-1].x),
     489            0 :             cy = static_cast<int>(src.y) - static_cast<int>(mergeverts[nummergeverts-1].y),
     490            0 :             dir = px*cy - py*cx;
     491            0 :         if(dir > 0)
     492              :         {
     493            0 :             return false;
     494              :         }
     495            0 :         if(!dir)
     496              :         {
     497            0 :             nummergeverts--;
     498              :         }
     499            0 :         mergeverts[nummergeverts++] = src;
     500            0 :         px = cx;
     501            0 :         py = cy;
     502              :     }
     503            0 :     int cx = static_cast<int>(mergeverts[0].x) - static_cast<int>(mergeverts[nummergeverts-1].x),
     504            0 :         cy = static_cast<int>(mergeverts[0].y) - static_cast<int>(mergeverts[nummergeverts-1].y),
     505            0 :         dir = px*cy - py*cx;
     506            0 :     if(dir > 0)
     507              :     {
     508            0 :         return false;
     509              :     }
     510            0 :     if(!dir)
     511              :     {
     512            0 :         nummergeverts--;
     513              :     }
     514            0 :     if(nummergeverts > Face_MaxVerts)
     515              :     {
     516            0 :         return false;
     517              :     }
     518            0 :     q.merged = true;
     519            0 :     q.numverts = 0;
     520            0 :     merged = true;
     521            0 :     numverts = nummergeverts;
     522            0 :     std::memcpy(verts, mergeverts, nummergeverts*sizeof(pvert));
     523            0 :     int prev = numverts-1;
     524            0 :     for(int j = 0; j < numverts; ++j)
     525              :     {
     526            0 :         pedge e(verts[prev], verts[j]);
     527            0 :         int order = e.from.x > e.to.x || (e.from.x == e.to.x && e.from.y > e.to.y) ? 1 : 0;
     528            0 :         if(order)
     529              :         {
     530            0 :             std::swap(e.from, e.to);
     531              :         }
     532              : 
     533            0 :         plink l;
     534            0 :         auto itr = links.find(e); //search for a plink that looks like the pedge we have
     535            0 :         if(itr != links.end())
     536              :         {
     537            0 :             l = *itr;
     538            0 :             links.erase(e); // we will place an updated verson of this immutable object at the end
     539              :         }
     540              :         else
     541              :         {
     542            0 :             l = e; //even though we searched find(e), l and e are NOT the same because they are of different types (l is derived)
     543              :         }
     544            0 :         bool shouldqueue = l.polys[order] < 0 && l.polys[order^1] >= 0;
     545            0 :         l.polys[order] = owner;
     546            0 :         links.insert(l);
     547            0 :         if(shouldqueue)
     548              :         {
     549            0 :             queue.push_back(&*links.find(l));
     550              :         }
     551            0 :         prev = j;
     552              :     }
     553              : 
     554            0 :     return true;
     555              : }
     556              : 
     557            0 : void cube::addmerge(int orient, const ivec &n, int offset, poly &p)
     558              : {
     559            0 :     merged |= 1<<orient;
     560            0 :     if(!p.numverts)
     561              :     {
     562            0 :         if(ext)
     563              :         {
     564            0 :             ext->surfaces[orient] = surfaceinfo();
     565              :         }
     566            0 :         return;
     567              :     }
     568              :     std::array<vertinfo, Face_MaxVerts> verts;
     569            0 :     surfaceinfo surf = surfaceinfo();
     570            0 :     surf.numverts |= p.numverts;
     571            0 :     int dim = DIMENSION(orient),
     572            0 :         coord = DIM_COORD(orient),
     573            0 :         c = C[dim],
     574            0 :         r = R[dim];
     575            0 :     for(int k = 0; k < p.numverts; ++k)
     576              :     {
     577            0 :         const pvert &src = p.verts[coord ? k : p.numverts-1-k];
     578            0 :         vertinfo &dst = verts[k];
     579            0 :         ivec v;
     580            0 :         v[c] = src.x;
     581            0 :         v[r] = src.y;
     582            0 :         v[dim] = -(offset + n[c]*src.x + n[r]*src.y)/n[dim];
     583            0 :         dst.set(v);
     584              :     }
     585            0 :     if(ext)
     586              :     {
     587            0 :         const surfaceinfo &oldsurf = ext->surfaces[orient];
     588            0 :         int numverts = oldsurf.numverts&Face_MaxVerts;
     589            0 :         if(numverts == p.numverts)
     590              :         {
     591            0 :             ivec v0 = verts[0].getxyz();
     592            0 :             const vertinfo *oldverts = ext->verts() + oldsurf.verts;
     593            0 :             for(int j = 0; j < numverts; ++j)
     594              :             {
     595            0 :                 if(v0 == oldverts[j].getxyz())
     596              :                 {
     597            0 :                     for(int k = 1; k < numverts; ++k)
     598              :                     {
     599            0 :                         if(++j >= numverts)
     600              :                         {
     601            0 :                             j = 0;
     602              :                         }
     603            0 :                         if(verts[k].getxyz() != oldverts[j].getxyz())
     604              :                         {
     605            0 :                             goto nomatch;
     606              :                         }
     607              :                     }
     608            0 :                     return;
     609              :                 }
     610              :             }
     611            0 :         nomatch:;
     612              :         }
     613              :     }
     614            0 :     setsurface(*this, orient, surf, verts.data(), p.numverts);
     615              : }
     616              : 
     617           90 : void cube::clearmerge(int orient)
     618              : {
     619           90 :     if(merged&(1<<orient))
     620              :     {
     621            0 :         merged &= ~(1<<orient);
     622            0 :         if(ext)
     623              :         {
     624            0 :             ext->surfaces[orient] = surfaceinfo();
     625              :         }
     626              :     }
     627           90 : }
     628              : 
     629           12 : void cube::addmerges(int orient, const ivec &n, int offset, std::deque<poly> &polys)
     630              : {
     631           60 :     for(poly &p : polys)
     632              :     {
     633           48 :         if(p.merged)
     634              :         {
     635            0 :             (*(p.c)).addmerge(orient, n, offset, p);
     636              :         }
     637              :         else
     638              :         {
     639           48 :             (*(p.c)).clearmerge(orient);
     640              :         }
     641              :     }
     642           12 : }
     643              : 
     644           12 : void cube::mergepolys(int orient, const ivec &n, int offset, std::deque<poly> &polys)
     645              : {
     646           12 :     if(polys.size() <= 1)
     647              :     {
     648            0 :         addmerges(orient, n, offset, polys);
     649            0 :         return;
     650              :     }
     651           12 :     std::unordered_set<plink> links(polys.size() <= 32 ? 128 : 1024);
     652           12 :     std::deque<const plink *> queue;
     653           60 :     for(size_t i = 0; i < polys.size(); i++)
     654              :     {
     655           48 :         const poly &p = polys[i];
     656           48 :         int prev = p.numverts-1;
     657          240 :         for(int j = 0; j < p.numverts; ++j)
     658              :         {
     659          192 :             pedge e(p.verts[prev], p.verts[j]);
     660          192 :             int order = e.from.x > e.to.x || (e.from.x == e.to.x && e.from.y > e.to.y) ? 1 : 0;
     661          192 :             if(order)
     662              :             {
     663           96 :                 std::swap(e.from, e.to);
     664              :             }
     665          192 :             plink l;
     666          192 :             auto itr = links.find(e);
     667          192 :             if(itr != links.end())
     668              :             {
     669            0 :                 l = *itr;
     670            0 :                 links.erase(e);
     671              :             }
     672          192 :             l.polys[order] = i;
     673          192 :             links.insert(l);
     674          192 :             if(l.polys[0] >= 0 && l.polys[1] >= 0)
     675              :             {
     676            0 :                 queue.push_back(&*links.find(l));
     677              :             }
     678          192 :             prev = j;
     679              :         }
     680              :     }
     681           12 :     std::deque<const plink *> nextqueue;
     682           12 :     while(queue.size())
     683              :     {
     684            0 :         for(const plink *&l : queue)
     685              :         {
     686            0 :             if(l->polys[0] >= 0 && l->polys[1] >= 0)
     687              :             {
     688            0 :                 polys[l->polys[0]].mergepolys(links, nextqueue, l->polys[0], polys[l->polys[1]], *l);
     689              :             }
     690              :         }
     691            0 :         queue.clear();
     692            0 :         queue.insert(queue.end(), nextqueue.begin(), nextqueue.end());
     693            0 :         nextqueue.clear();
     694              :     }
     695           12 :     addmerges(orient, n, offset, polys);
     696           12 : }
     697              : 
     698           36 : bool operator==(const cube::cfkey &x, const cube::cfkey &y)
     699              : {
     700           36 :     return x.orient == y.orient && x.tex == y.tex && x.n == y.n && x.offset == y.offset && x.material==y.material;
     701              : }
     702              : 
     703              : template<>
     704              : struct std::hash<cube::cfkey>
     705              : {
     706           48 :     size_t operator()(const cube::cfkey &k) const
     707              :     {
     708              :         auto ivechash = std::hash<ivec>();
     709           48 :         return ivechash(k.n)^k.offset^k.tex^k.orient^k.material;
     710              :     }
     711              : };
     712              : 
     713              : //recursively goes through children of cube passed and attempts to merge faces together
     714            4 : void cube::genmerges(cube * root, const ivec &o, int size)
     715              : {
     716            4 :     static std::unordered_map<cfkey, cfpolys> cpolys;
     717            4 :     neighborstack[++neighbordepth] = this;
     718           36 :     for(int i = 0; i < 8; ++i)
     719              :     {
     720           32 :         ivec co(i, o, size);
     721              :         int vis;
     722           32 :         if(this[i].children)
     723              :         {
     724            2 :             (this[i]).children->at(0).genmerges(root, co, size>>1);
     725              :         }
     726           30 :         else if(!(this[i].isempty()))
     727              :         {
     728          105 :             for(int j = 0; j < 6; ++j)
     729              :             {
     730           90 :                 if((vis = visibletris(this[i], j, co, size)))
     731              :                 {
     732           90 :                     cfkey k;
     733           90 :                     poly p;
     734           90 :                     if(size < 1<<maxmerge && this != root)
     735              :                     {
     736           48 :                         if(genpoly(j, co, size, vis, k.n, k.offset, p))
     737              :                         {
     738           48 :                             k.orient = j;
     739           48 :                             k.tex = this[i].texture[j];
     740           48 :                             k.material = this[i].material&Mat_Alpha;
     741           48 :                             cpolys[k].polys.push_back(p);
     742           48 :                             continue;
     743              :                         }
     744              :                     }
     745           42 :                     else if(minface && size >= 1<<minface && touchingface(this[i], j))
     746              :                     {
     747            0 :                         if(genpoly(j, co, size, vis, k.n, k.offset, p) && p.merged)
     748              :                         {
     749            0 :                             this[i].addmerge( j, k.n, k.offset, p);
     750            0 :                             continue;
     751              :                         }
     752              :                     }
     753           42 :                     this[i].clearmerge(j);
     754              :                 }
     755              :             }
     756              :         }
     757           32 :         if((size == 1<<maxmerge || this == root) && cpolys.size())
     758              :         {
     759           13 :             for(auto &[k, t] : cpolys)
     760              :             {
     761           12 :                 mergepolys(k.orient, k.n, k.offset, t.polys);
     762              :             }
     763            1 :             cpolys.clear();
     764              :         }
     765              :     }
     766            4 :     --neighbordepth;
     767            4 : }
     768              : 
     769            2 : void cube::calcmerges()
     770              : {
     771            2 :     genmerges(this);
     772            2 : }
        

Generated by: LCOV version 2.0-1