LCOV - code coverage report
Current view: top level - engine/world - material.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.5 % 811 4
Test Date: 2026-02-16 07:02:41 Functions: 2.4 % 42 1

            Line data    Source code
       1              : /**
       2              :  * @file octree handled volume-based region flagging
       3              :  *
       4              :  * the material system in libprimis relies on the octree system; as a result all
       5              :  * material volumes are compositions of rectangular prisms
       6              :  *
       7              :  * regions of the octree world can be flagged as containing specific "materials"
       8              :  * some of these are rendered and visible (glass, water) while some are not visible
       9              :  * to users directly
      10              :  *
      11              :  * nonvisible materials influence how actors interact with the world: for example,
      12              :  * clipping and noclipping materials affect collision (by either creating invisible
      13              :  * walls or causing the engine to ignore collision with surfaces).
      14              :  *
      15              :  * the material data is saved in world files along with the octree geometry (see
      16              :  * worldio.cpp)
      17              :  */
      18              : 
      19              : #include "../libprimis-headers/cube.h"
      20              : #include "../../shared/geomexts.h"
      21              : #include "../../shared/glemu.h"
      22              : #include "../../shared/glexts.h"
      23              : 
      24              : #include "material.h"
      25              : #include "octaedit.h"
      26              : #include "octaworld.h"
      27              : #include "world.h"
      28              : 
      29              : #include "render/octarender.h"
      30              : #include "render/rendergl.h"
      31              : #include "render/renderlights.h"
      32              : #include "render/renderva.h"
      33              : #include "render/water.h"
      34              : #include "render/shader.h"
      35              : #include "render/shaderparam.h"
      36              : #include "render/texture.h"
      37              : 
      38              : std::array<std::vector<materialsurface>, 4> watersurfs, waterfallsurfs, glasssurfs;
      39              : 
      40              : //internally relevant functionality
      41              : 
      42              : namespace
      43              : {
      44              :     std::vector<materialsurface> editsurfs;
      45              : 
      46              :     class QuadNode final
      47              :     {
      48              :         public:
      49            0 :             QuadNode(int x, int y, int size) : x(x), y(y), size(size), filled(0)
      50              :             {
      51            0 :                 for(int i = 0; i < 4; ++i)
      52              :                 {
      53            0 :                     child[i] = 0;
      54              :                 }
      55            0 :             }
      56              : 
      57            0 :             ~QuadNode()
      58              :             {
      59            0 :                 clear();
      60            0 :             }
      61              : 
      62            0 :             void insert(int mx, int my, int msize)
      63              :             {
      64            0 :                 if(size == msize)
      65              :                 {
      66            0 :                     filled = 0xF;
      67            0 :                     return;
      68              :                 }
      69            0 :                 int csize = size>>1,
      70            0 :                     i = 0;
      71            0 :                 if(mx >= x+csize)
      72              :                 {
      73            0 :                     i |= 1;
      74              :                 }
      75            0 :                 if(my >= y+csize)
      76              :                 {
      77            0 :                     i |= 2;
      78              :                 }
      79            0 :                 if(csize == msize)
      80              :                 {
      81            0 :                     filled |= (1 << i);
      82            0 :                     return;
      83              :                 }
      84            0 :                 if(!child[i])
      85              :                 {
      86            0 :                     child[i] = new QuadNode(i&1 ? x+csize : x, i&2 ? y+csize : y, csize);
      87              :                 }
      88            0 :                 child[i]->insert(mx, my, msize);
      89            0 :                 for(int j = 0; j < 4; ++j)
      90              :                 {
      91            0 :                     if(child[j])
      92              :                     {
      93            0 :                         if(child[j]->filled == 0xF)
      94              :                         {
      95            0 :                             if(child[j])
      96              :                             {
      97            0 :                                 delete child[j];
      98            0 :                                 child[j] = nullptr;
      99              :                             }
     100            0 :                             filled |= (1 << j);
     101              :                         }
     102              :                     }
     103              :                 }
     104              :             }
     105              : 
     106            0 :             void genmatsurfs(ushort mat, uchar orient, uchar visible, int z, materialsurface *&matbuf)
     107              :             {
     108            0 :                 if(filled == 0xF)
     109              :                 {
     110            0 :                     genmatsurf(mat, orient, visible, x, y, z, size, matbuf);
     111              :                 }
     112            0 :                 else if(filled)
     113              :                 {
     114            0 :                     int csize = size>>1;
     115            0 :                     for(int i = 0; i < 4; ++i)
     116              :                     {
     117            0 :                         if(filled & (1 << i))
     118              :                         {
     119            0 :                             genmatsurf(mat, orient, visible, i&1 ? x+csize : x, i&2 ? y+csize : y, z, csize, matbuf);
     120              :                         }
     121              : 
     122              :                     }
     123              :                 }
     124            0 :                 for(int i = 0; i < 4; ++i)
     125              :                 {
     126            0 :                     if(child[i])
     127              :                     {
     128            0 :                         child[i]->genmatsurfs(mat, orient, visible, z, matbuf);
     129              :                     }
     130              :                 }
     131            0 :             }
     132              :         private:
     133              :             int x, y, size;
     134              :             uint filled;
     135              :             std::array<QuadNode *, 4> child;
     136              : 
     137            0 :             void clear()
     138              :             {
     139            0 :                 for(int i = 0; i < 4; ++i)
     140              :                 {
     141            0 :                     if(child[i])
     142              :                     {
     143            0 :                         delete child[i];
     144            0 :                         child[i] = nullptr;
     145              :                     }
     146              :                 }
     147            0 :             }
     148              : 
     149            0 :             void genmatsurf(ushort mat, uchar orient, uchar visible, int x, int y, int z, int size, materialsurface *&matbuf)
     150              :             {
     151            0 :                 materialsurface &m = *matbuf++;
     152            0 :                 m.material = mat;
     153            0 :                 m.orient = orient;
     154            0 :                 m.visible = visible;
     155            0 :                 m.csize = size;
     156            0 :                 m.rsize = size;
     157            0 :                 int dim = DIMENSION(orient);
     158            0 :                 m.o[C[dim]] = x;
     159            0 :                 m.o[R[dim]] = y;
     160            0 :                 m.o[dim] = z;
     161            0 :             }
     162              :     };
     163              : 
     164            0 :     static void drawmaterial(const materialsurface &m, float offset)
     165              :     {
     166            0 :         if(gle::attribbuf.empty())
     167              :         {
     168            0 :             gle::defvertex();
     169            0 :             gle::begin(GL_TRIANGLE_FAN);
     170              :         }
     171            0 :         float x = m.o.x,
     172            0 :               y = m.o.y,
     173            0 :               z = m.o.z,
     174            0 :               csize = m.csize,
     175            0 :               rsize = m.rsize;
     176            0 :         switch(m.orient)
     177              :         {
     178            0 :             case 0:
     179              :             {
     180            0 :                 gle::attribf(x + offset, y + rsize, z + csize);
     181            0 :                 gle::attribf(x + offset, y + rsize, z);
     182            0 :                 gle::attribf(x + offset, y, z);
     183            0 :                 gle::attribf(x + offset, y, z + csize);
     184            0 :                 break;
     185              :             }
     186            0 :             case 1:
     187              :             {
     188            0 :                 gle::attribf(x - offset, y + rsize, z + csize);
     189            0 :                 gle::attribf(x - offset, y, z + csize);
     190            0 :                 gle::attribf(x - offset, y, z);
     191            0 :                 gle::attribf(x - offset, y + rsize, z);
     192            0 :                 break;
     193              :             }
     194            0 :             case 2:
     195              :             {
     196            0 :                 gle::attribf(x + csize, y + offset, z + rsize);
     197            0 :                 gle::attribf(x, y + offset, z + rsize);
     198            0 :                 gle::attribf(x, y + offset, z);
     199            0 :                 gle::attribf(x + csize, y + offset, z);
     200            0 :                 break;
     201              :             }
     202            0 :             case 3:
     203              :             {
     204            0 :                 gle::attribf(x, y - offset, z);
     205            0 :                 gle::attribf(x, y - offset, z + rsize);
     206            0 :                 gle::attribf(x + csize, y - offset, z + rsize);
     207            0 :                 gle::attribf(x + csize, y - offset, z);
     208            0 :                 break;
     209              :             }
     210            0 :             case 4:
     211              :             {
     212            0 :                 gle::attribf(x, y, z + offset);
     213            0 :                 gle::attribf(x, y + csize, z + offset);
     214            0 :                 gle::attribf(x + rsize, y + csize, z + offset);
     215            0 :                 gle::attribf(x + rsize, y, z + offset);
     216            0 :                 break;
     217              :             }
     218            0 :             case 5:
     219              :             {
     220            0 :                 gle::attribf(x, y, z - offset);
     221            0 :                 gle::attribf(x + rsize, y, z - offset);
     222            0 :                 gle::attribf(x + rsize, y + csize, z - offset);
     223            0 :                 gle::attribf(x, y + csize, z - offset);
     224            0 :                 break;
     225              :             }
     226              :         }
     227            0 :         gle::end();
     228            0 :     }
     229              : 
     230              :     const struct material final
     231              :     {
     232              :         const char *name;
     233              :         ushort id;
     234              :     } materials[] =
     235              :     {
     236              :         {"air", Mat_Air},
     237              :         {"water", Mat_Water}, {"water1", Mat_Water}, {"water2", Mat_Water+1}, {"water3", Mat_Water+2}, {"water4", Mat_Water+3},
     238              :         {"glass", Mat_Glass}, {"glass1", Mat_Glass}, {"glass2", Mat_Glass+1}, {"glass3", Mat_Glass+2}, {"glass4", Mat_Glass+3},
     239              :         {"clip", Mat_Clip},
     240              :         {"noclip", Mat_NoClip},
     241              :         {"gameclip", Mat_GameClip},
     242              :         {"death", Mat_Death},
     243              :         {"alpha", Mat_Alpha}
     244              :     };
     245              : 
     246            0 :     int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask = MatFlag_Volume)
     247              :     {
     248            0 :         ushort mat = c.material&matmask;
     249            0 :         switch(mat)
     250              :         {
     251            0 :             case Mat_Air:
     252              :             {
     253            0 :                  break;
     254              :             }
     255            0 :             case Mat_Water:
     256              :             {
     257            0 :                 if(visibleface(c, orient, co, size, mat, Mat_Air, matmask))
     258              :                 {
     259            0 :                     return (orient != Orient_Bottom ? MatSurf_Visible : MatSurf_EditOnly);
     260              :                 }
     261            0 :                 break;
     262              :             }
     263            0 :             case Mat_Glass:
     264              :             {
     265            0 :                 if(visibleface(c, orient, co, size, Mat_Glass, Mat_Air, matmask))
     266              :                 {
     267            0 :                     return MatSurf_Visible;
     268              :                 }
     269            0 :                 break;
     270              :             }
     271            0 :             default:
     272              :             {
     273            0 :                 if(visibleface(c, orient, co, size, mat, Mat_Air, matmask))
     274              :                 {
     275            0 :                     return MatSurf_EditOnly;
     276              :                 }
     277            0 :                 break;
     278              :             }
     279              :         }
     280            0 :         return MatSurf_NotVisible;
     281              :     }
     282              : 
     283            0 :     bool mergematcmp(const materialsurface &x, const materialsurface &y)
     284              :     {
     285            0 :         const int dim = DIMENSION(x.orient),
     286            0 :                   c   = C[dim],
     287            0 :                   r   = R[dim];
     288            0 :         if(x.o[r] + x.rsize < y.o[r] + y.rsize)
     289              :         {
     290            0 :             return true;
     291              :         }
     292            0 :         if(x.o[r] + x.rsize > y.o[r] + y.rsize)
     293              :         {
     294            0 :             return false;
     295              :         }
     296            0 :         return x.o[c] < y.o[c];
     297              :     }
     298              : 
     299              :     //m: pointer to array of materialsurfaces
     300              :     //sz: size of the array passed
     301            0 :     int mergematr(materialsurface *m, int sz, materialsurface &n)
     302              :     {
     303            0 :         const int dim = DIMENSION(n.orient),
     304            0 :                     c = C[dim],
     305            0 :                     r = R[dim];
     306            0 :         for(int i = sz-1; i >= 0; --i)
     307              :         {
     308            0 :             if(m[i].o[r] + m[i].rsize < n.o[r])
     309              :             {
     310            0 :                 break;
     311              :             }
     312            0 :             if(m[i].o[r] + m[i].rsize == n.o[r] && m[i].o[c] == n.o[c] && m[i].csize == n.csize)
     313              :             {
     314            0 :                 n.o[r] = m[i].o[r];
     315            0 :                 n.rsize += m[i].rsize;
     316            0 :                 std::memmove(&m[i], &m[i+1], (sz - (i+1)) * sizeof(materialsurface));
     317            0 :                 return 1;
     318              :             }
     319              :         }
     320            0 :         return 0;
     321              :     }
     322              : 
     323            0 :     int mergematc(const materialsurface &m, materialsurface &n)
     324              :     {
     325            0 :         const int dim = DIMENSION(n.orient),
     326            0 :                   c   = C[dim],
     327            0 :                   r   = R[dim];
     328            0 :         if(m.o[r] == n.o[r] && m.rsize == n.rsize && m.o[c] + m.csize == n.o[c])
     329              :         {
     330            0 :             n.o[c] = m.o[c];
     331            0 :             n.csize += m.csize;
     332            0 :             return 1;
     333              :         }
     334            0 :         return 0;
     335              :     }
     336              : 
     337              :     //m: pointer to array of materialsurfaces
     338              :     //sz: size of the array passed
     339            0 :     int mergemat(materialsurface *m, int sz, materialsurface &n)
     340              :     {
     341            0 :         for(bool merged = false; sz; merged = true)
     342              :         {
     343            0 :             int rmerged = mergematr(m, sz, n);
     344            0 :             sz -= rmerged;
     345            0 :             if(!rmerged && merged)
     346              :             {
     347            0 :                 break;
     348              :             }
     349            0 :             if(!sz)
     350              :             {
     351            0 :                 break;
     352              :             }
     353            0 :             int cmerged = mergematc(m[sz-1], n);
     354            0 :             sz -= cmerged;
     355            0 :             if(!cmerged)
     356              :             {
     357            0 :                 break;
     358              :             }
     359              :         }
     360            0 :         m[sz++] = n;
     361            0 :         return sz;
     362              :     }
     363              : 
     364              :     //m: pointer to array of materialsurfaces
     365              :     //sz: size of the array passed
     366            0 :     int mergemats(materialsurface *m, int sz)
     367              :     {
     368            0 :         std::sort(m, m+sz, mergematcmp);
     369              : 
     370            0 :         int nsz = 0;
     371            0 :         for(int i = 0; i < sz; ++i)
     372              :         {
     373            0 :             nsz = mergemat(m, nsz, m[i]);
     374              :         }
     375            0 :         return nsz;
     376              :     }
     377              : 
     378            0 :     bool optmatcmp(const materialsurface &x, const materialsurface &y)
     379              :     {
     380            0 :         if(x.material < y.material)
     381              :         {
     382            0 :             return true;
     383              :         }
     384            0 :         if(x.material > y.material)
     385              :         {
     386            0 :             return false;
     387              :         }
     388            0 :         if(x.orient > y.orient)
     389              :         {
     390            0 :             return true;
     391              :         }
     392            0 :         if(x.orient < y.orient)
     393              :         {
     394            0 :             return false;
     395              :         }
     396            0 :         int dim = DIMENSION(x.orient);
     397            0 :         return x.o[dim] < y.o[dim];
     398              :     }
     399              : 
     400            0 :     void preloadglassshaders(bool force = false)
     401              :     {
     402              :         static bool needglass = false;
     403            0 :         if(force)
     404              :         {
     405            0 :             needglass = true;
     406              :         }
     407            0 :         if(!needglass)
     408              :         {
     409            0 :             return;
     410              :         }
     411            0 :         useshaderbyname("glass");
     412              :     }
     413              : 
     414            0 :     void sorteditmaterials()
     415              :     {
     416              : 
     417            0 :         std::array<int, 3> sortdim {0, 1, 2};
     418            0 :         ivec sortorigin;
     419              : 
     420              :         //allows for sorting of materialsurface objects
     421              :         //intended to meet the standards of c++ stl `Compare`
     422            0 :         auto editmatcmp = [&sortdim, &sortorigin] (const materialsurface &x, const materialsurface &y)
     423              :         {
     424            0 :             int xdim = DIMENSION(x.orient),
     425            0 :                 ydim = DIMENSION(y.orient);
     426            0 :             for(const int &i : sortdim)
     427              :             {
     428              :                 int xmin, xmax, ymin, ymax;
     429            0 :                 xmin = xmax = x.o[i];
     430            0 :                 if(i==C[xdim])
     431              :                 {
     432            0 :                     xmax += x.csize;
     433              :                 }
     434            0 :                 else if(i==R[i])
     435              :                 {
     436            0 :                     xmax += x.rsize;
     437              :                 }
     438            0 :                 ymin = ymax = y.o[i];
     439            0 :                 if(i==C[ydim])
     440              :                 {
     441            0 :                     ymax += y.csize;
     442              :                 }
     443            0 :                 else if(i==R[ydim])
     444              :                 {
     445            0 :                     ymax += y.rsize;
     446              :                 }
     447            0 :                 if(xmax > ymin && ymax > xmin)
     448              :                 {
     449            0 :                     continue;
     450              :                 }
     451            0 :                 int c = sortorigin[i];
     452            0 :                 if(c > xmin && c < xmax)
     453              :                 {
     454            0 :                     return true;
     455              :                 }
     456            0 :                 if(c > ymin && c < ymax)
     457              :                 {
     458            0 :                     return false;
     459              :                 }
     460            0 :                 xmin = std::abs(xmin - c);
     461            0 :                 xmax = std::abs(xmax - c);
     462            0 :                 ymin = std::abs(ymin - c);
     463            0 :                 ymax = std::abs(ymax - c);
     464            0 :                 if(std::max(xmin, xmax) < std::min(ymin, ymax))
     465              :                 {
     466            0 :                     return true;
     467              :                 }
     468            0 :                 else if(std::max(ymin, ymax) <= std::min(xmin, xmax))
     469              :                 {
     470            0 :                     return false;
     471              :                 }
     472              :             }
     473            0 :             if(x.material != y.material)
     474              :             {
     475            0 :                 return x.material < y.material;
     476              :             }
     477            0 :             return false;
     478            0 :         };
     479              : 
     480            0 :         sortorigin = ivec(camera1->o);
     481            0 :         vec dir = camdir().abs();
     482            0 :         if(dir[sortdim[2]] > dir[sortdim[1]])
     483              :         {
     484            0 :             std::swap(sortdim[2], sortdim[1]);
     485              :         }
     486            0 :         if(dir[sortdim[1]] > dir[sortdim[0]])
     487              :         {
     488            0 :             std::swap(sortdim[1], sortdim[0]);
     489              :         }
     490            0 :         if(dir[sortdim[2]] > dir[sortdim[1]])
     491              :         {
     492            0 :             std::swap(sortdim[2], sortdim[1]);
     493              :         }
     494            0 :         std::sort(editsurfs.begin(), editsurfs.end(), editmatcmp);
     495            0 :     }
     496              : 
     497            0 :     void rendermatgrid()
     498              :     {
     499            0 :         enablepolygonoffset(GL_POLYGON_OFFSET_LINE);
     500            0 :         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     501            0 :         int lastmat = -1;
     502            0 :         for(int i = static_cast<int>(editsurfs.size()); --i >=0;) //note reverse iteration
     503              :         {
     504            0 :             const materialsurface &m = editsurfs[i];
     505            0 :             if(m.material != lastmat)
     506              :             {
     507            0 :                 xtraverts += gle::end();
     508            0 :                 bvec color;
     509            0 :                 switch(m.material&~MatFlag_Index)
     510              :                 {   //colors of materials lines in edit mode
     511            0 :                     case Mat_Water:
     512              :                     {
     513            0 :                         color = bvec( 0,  0, 85);
     514            0 :                         break; // blue
     515              :                     }
     516            0 :                     case Mat_Clip:
     517              :                     {
     518            0 :                         color = bvec(85,  0,  0);
     519            0 :                         break; // red
     520              :                     }
     521            0 :                     case Mat_Glass:
     522              :                     {
     523            0 :                         color = bvec( 0, 85, 85);
     524            0 :                         break; // cyan
     525              :                     }
     526            0 :                     case Mat_NoClip:
     527              :                     {
     528            0 :                         color = bvec( 0, 85,  0);
     529            0 :                         break; // green
     530              :                     }
     531            0 :                     case Mat_GameClip:
     532              :                     {
     533            0 :                         color = bvec(85, 85,  0);
     534            0 :                         break; // yellow
     535              :                     }
     536            0 :                     case Mat_Death:
     537              :                     {
     538            0 :                         color = bvec(40, 40, 40);
     539            0 :                         break; // black
     540              :                     }
     541            0 :                     case Mat_Alpha:
     542              :                     {
     543            0 :                         color = bvec(85,  0, 85);
     544            0 :                         break; // pink
     545              :                     }
     546            0 :                     default:
     547              :                     {
     548            0 :                         continue;
     549              :                     }
     550              :                 }
     551            0 :                 gle::colorf(color.x*ldrscaleb(), color.y*ldrscaleb(), color.z*ldrscaleb());
     552            0 :                 lastmat = m.material;
     553              :             }
     554            0 :             drawmaterial(m, -0.1f);
     555              :         }
     556            0 :         xtraverts += gle::end();
     557            0 :         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     558            0 :         disablepolygonoffset(GL_POLYGON_OFFSET_LINE);
     559            0 :     }
     560              : 
     561            0 :     void drawglass(const materialsurface &m, float offset, float glassxscale, float glassyscale, const vec normal = vec(0,0,0))
     562              :     {
     563            0 :         if(gle::attribbuf.empty())
     564              :         {
     565            0 :             gle::defvertex();
     566            0 :             if(normal != vec(0,0,0))
     567              :             {
     568            0 :                 gle::defnormal();
     569              :             }
     570            0 :             gle::deftexcoord0();
     571              :         }
     572            0 :         float x = m.o.x,
     573            0 :               y = m.o.y,
     574            0 :               z = m.o.z,
     575            0 :               csize = m.csize,
     576            0 :               rsize = m.rsize;
     577            0 :         gle::begin(GL_TRIANGLE_FAN);
     578            0 :         if(normal != vec(0, 0, 0))
     579              :         {
     580            0 :             vec n = normal;
     581            0 :             switch (m.orient)
     582              :             {
     583            0 :                 case 0:
     584              :                     {
     585            0 :                         vec v(x + offset, y + rsize, z + csize);
     586            0 :                         gle::attribf(v.x, v.y, v.z);
     587            0 :                         gle::attribf(n.x, n.y, n.z);
     588            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     589              :                     }
     590              :                     {
     591            0 :                         vec v(x + offset, y + rsize, z);
     592            0 :                         gle::attribf(v.x, v.y, v.z);
     593            0 :                         gle::attribf(n.x, n.y, n.z);
     594            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     595              :                     }
     596              :                     {
     597            0 :                         vec v(x + offset, y, z);
     598            0 :                         gle::attribf(v.x, v.y, v.z);
     599            0 :                         gle::attribf(n.x, n.y, n.z);
     600            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     601              :                     }
     602              :                     {
     603            0 :                         vec v(x + offset, y, z + csize);
     604            0 :                         gle::attribf(v.x, v.y, v.z);
     605            0 :                         gle::attribf(n.x, n.y, n.z);
     606            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     607              :                     }
     608            0 :                     break;
     609            0 :                 case 1:
     610              :                     {
     611            0 :                         vec v(x - offset, y + rsize, z + csize);
     612            0 :                         gle::attribf(v.x, v.y, v.z);
     613            0 :                         gle::attribf(n.x, n.y, n.z);
     614            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     615              :                     }
     616              :                     {
     617            0 :                         vec v(x - offset, y, z + csize);
     618            0 :                         gle::attribf(v.x, v.y, v.z);
     619            0 :                         gle::attribf(n.x, n.y, n.z);
     620            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     621              :                     }
     622              :                     {
     623            0 :                         vec v(x - offset, y, z);
     624            0 :                         gle::attribf(v.x, v.y, v.z);
     625            0 :                         gle::attribf(n.x, n.y, n.z);
     626            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     627              :                     }
     628              :                     {
     629            0 :                         vec v(x - offset, y + rsize, z);
     630            0 :                         gle::attribf(v.x, v.y, v.z);
     631            0 :                         gle::attribf(n.x, n.y, n.z);
     632            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     633              :                     }
     634            0 :                     break;
     635            0 :                 case 2:
     636              :                     {
     637            0 :                         vec v(x + csize, y + offset, z + rsize);
     638            0 :                         gle::attribf(v.x, v.y, v.z);
     639            0 :                         gle::attribf(n.x, n.y, n.z);
     640            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     641              :                     }
     642              :                     {
     643            0 :                         vec v(x, y + offset, z + rsize);
     644            0 :                         gle::attribf(v.x, v.y, v.z);
     645            0 :                         gle::attribf(n.x, n.y, n.z);
     646            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     647              :                     }
     648              :                     {
     649            0 :                         vec v(x, y + offset, z);
     650            0 :                         gle::attribf(v.x, v.y, v.z);
     651            0 :                         gle::attribf(n.x, n.y, n.z);
     652            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     653              :                     }
     654              :                     {
     655            0 :                         vec v(x + csize, y + offset, z);
     656            0 :                         gle::attribf(v.x, v.y, v.z);
     657            0 :                         gle::attribf(n.x, n.y, n.z);
     658            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     659              :                     }
     660            0 :                     break;
     661            0 :                 case 3:
     662              :                     {
     663            0 :                         vec v(x, y - offset, z);
     664            0 :                         gle::attribf(v.x, v.y, v.z);
     665            0 :                         gle::attribf(n.x, n.y, n.z);
     666            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     667              :                     }
     668              :                     {
     669            0 :                         vec v(x, y - offset, z + rsize);
     670            0 :                         gle::attribf(v.x, v.y, v.z);
     671            0 :                         gle::attribf(n.x, n.y, n.z);
     672            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     673              :                     }
     674              :                     {
     675            0 :                         vec v(x + csize, y - offset, z + rsize);
     676            0 :                         gle::attribf(v.x, v.y, v.z);
     677            0 :                         gle::attribf(n.x, n.y, n.z);
     678            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     679              :                     }
     680              :                     {
     681            0 :                         vec v(x + csize, y - offset, z);
     682            0 :                         gle::attribf(v.x, v.y, v.z);
     683            0 :                         gle::attribf(n.x, n.y, n.z);
     684            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     685              :                     }
     686            0 :                     break;
     687            0 :                 case 4:
     688              :                     {
     689            0 :                         vec v(x, y, z + offset);
     690            0 :                         gle::attribf(v.x, v.y, v.z);
     691            0 :                         gle::attribf(n.x, n.y, n.z);
     692            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     693              :                     }
     694              :                     {
     695            0 :                         vec v(x, y + csize, z + offset);
     696            0 :                         gle::attribf(v.x, v.y, v.z);
     697            0 :                         gle::attribf(n.x, n.y, n.z);
     698            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     699              :                     }
     700              :                     {
     701            0 :                         vec v(x + rsize, y + csize, z + offset);
     702            0 :                         gle::attribf(v.x, v.y, v.z);
     703            0 :                         gle::attribf(n.x, n.y, n.z);
     704            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     705              :                     }
     706              :                     {
     707            0 :                         vec v(x + rsize, y, z + offset);
     708            0 :                         gle::attribf(v.x, v.y, v.z);
     709            0 :                         gle::attribf(n.x, n.y, n.z);
     710            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     711              :                     }
     712            0 :                     break;
     713            0 :                 case 5:
     714              :                     {
     715            0 :                         vec v(x, y, z - offset);
     716            0 :                         gle::attribf(v.x, v.y, v.z);
     717            0 :                         gle::attribf(n.x, n.y, n.z);
     718            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     719              :                     }
     720              :                     {
     721            0 :                         vec v(x + rsize, y, z - offset);
     722            0 :                         gle::attribf(v.x, v.y, v.z);
     723            0 :                         gle::attribf(n.x, n.y, n.z);
     724            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     725              :                     }
     726              :                     {
     727            0 :                         vec v(x + rsize, y + csize, z - offset);
     728            0 :                         gle::attribf(v.x, v.y, v.z);
     729            0 :                         gle::attribf(n.x, n.y, n.z);
     730            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     731              :                     }
     732              :                     {
     733            0 :                         vec v(x, y + csize, z - offset);
     734            0 :                         gle::attribf(v.x, v.y, v.z);
     735            0 :                         gle::attribf(n.x, n.y, n.z);
     736            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     737              :                     }
     738            0 :                     break;
     739              :                 }
     740              :             }
     741              :         else
     742              :         {
     743            0 :             switch (m.orient)
     744              :             {
     745            0 :                 case 0:
     746              :                     {
     747            0 :                         vec v(x + offset, y + rsize, z + csize);
     748            0 :                         gle::attribf(v.x, v.y, v.z);
     749            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     750              :                     }
     751              :                     {
     752            0 :                         vec v(x + offset, y + rsize, z);
     753            0 :                         gle::attribf(v.x, v.y, v.z);
     754            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     755              :                     }
     756              :                     {
     757            0 :                         vec v(x + offset, y, z);
     758            0 :                         gle::attribf(v.x, v.y, v.z);
     759            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     760              :                     }
     761              :                     {
     762            0 :                         vec v(x + offset, y, z + csize);
     763            0 :                         gle::attribf(v.x, v.y, v.z);
     764            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     765              :                     }
     766            0 :                     break;
     767            0 :                 case 1:
     768              :                     {
     769            0 :                         vec v(x - offset, y + rsize, z + csize);
     770            0 :                         gle::attribf(v.x, v.y, v.z);
     771            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     772              :                     }
     773              :                     {
     774            0 :                         vec v(x - offset, y, z + csize);
     775            0 :                         gle::attribf(v.x, v.y, v.z);
     776            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     777              :                     }
     778              :                     {
     779            0 :                         vec v(x - offset, y, z);
     780            0 :                         gle::attribf(v.x, v.y, v.z);
     781            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     782              :                     }
     783              :                     {
     784            0 :                         vec v(x - offset, y + rsize, z);
     785            0 :                         gle::attribf(v.x, v.y, v.z);
     786            0 :                         gle::attribf(glassxscale * v.y, -glassyscale * v.z);
     787              :                     }
     788            0 :                     break;
     789            0 :                 case 2:
     790              :                     {
     791            0 :                         vec v(x + csize, y + offset, z + rsize);
     792            0 :                         gle::attribf(v.x, v.y, v.z);
     793            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     794              :                     }
     795              :                     {
     796            0 :                         vec v(x, y + offset, z + rsize);
     797            0 :                         gle::attribf(v.x, v.y, v.z);
     798            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     799              :                     }
     800              :                     {
     801            0 :                         vec v(x, y + offset, z);
     802            0 :                         gle::attribf(v.x, v.y, v.z);
     803            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     804              :                     }
     805              :                     {
     806            0 :                         vec v(x + csize, y + offset, z);
     807            0 :                         gle::attribf(v.x, v.y, v.z);
     808            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     809              :                     }
     810            0 :                     break;
     811            0 :                 case 3:
     812              :                     {
     813            0 :                         vec v(x, y - offset, z);
     814            0 :                         gle::attribf(v.x, v.y, v.z);
     815            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     816              :                     }
     817              :                     {
     818            0 :                         vec v(x, y - offset, z + rsize);
     819            0 :                         gle::attribf(v.x, v.y, v.z);
     820            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     821              :                     }
     822              :                     {
     823            0 :                         vec v(x + csize, y - offset, z + rsize);
     824            0 :                         gle::attribf(v.x, v.y, v.z);
     825            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     826              :                     }
     827              :                     {
     828            0 :                         vec v(x + csize, y - offset, z);
     829            0 :                         gle::attribf(v.x, v.y, v.z);
     830            0 :                         gle::attribf(glassxscale * v.x, -glassyscale * v.z);
     831              :                     }
     832            0 :                     break;
     833            0 :                 case 4:
     834              :                     {
     835            0 :                         vec v(x, y, z + offset);
     836            0 :                         gle::attribf(v.x, v.y, v.z);
     837            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     838              :                     }
     839              :                     {
     840            0 :                         vec v(x, y + csize, z + offset);
     841            0 :                         gle::attribf(v.x, v.y, v.z);
     842            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     843              :                     }
     844              :                     {
     845            0 :                         vec v(x + rsize, y + csize, z + offset);
     846            0 :                         gle::attribf(v.x, v.y, v.z);
     847            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     848              :                     }
     849              :                     {
     850            0 :                         vec v(x + rsize, y, z + offset);
     851            0 :                         gle::attribf(v.x, v.y, v.z);
     852            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     853              :                     }
     854            0 :                     break;
     855            0 :                 case 5:
     856              :                     {
     857            0 :                         vec v(x, y, z - offset);
     858            0 :                         gle::attribf(v.x, v.y, v.z);
     859            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     860              :                     }
     861              :                     {
     862            0 :                         vec v(x + rsize, y, z - offset);
     863            0 :                         gle::attribf(v.x, v.y, v.z);
     864            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     865              :                     }
     866              :                     {
     867            0 :                         vec v(x + rsize, y + csize, z - offset);
     868            0 :                         gle::attribf(v.x, v.y, v.z);
     869            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     870              :                     }
     871              :                     {
     872            0 :                         vec v(x, y + csize, z - offset);
     873            0 :                         gle::attribf(v.x, v.y, v.z);
     874            0 :                         gle::attribf(glassxscale * v.x, glassyscale * v.y);
     875              :                     }
     876            0 :                     break;
     877              :             }
     878              :         }
     879            0 :         gle::end();
     880            0 :     }
     881              : 
     882              :     //these are the variables defined for each specific glass material (there are 4)
     883              :     #define GLASSVARS(name) \
     884              :         CVAR0R(name##color, 0xB0D8FF); \
     885              :         FVARR(name##refract, 0, 0.1f, 1e3f); \
     886              :         VARR(name##spec, 0, 150, 200);
     887              : 
     888            0 :     GLASSVARS(glass)
     889            0 :     GLASSVARS(glass2)
     890            0 :     GLASSVARS(glass3)
     891            0 :     GLASSVARS(glass4)
     892              : 
     893              :     #undef GLASSVARS
     894              : 
     895            0 :     GETMATIDXVAR(glass, color, const bvec &) //this is the getglasscolor() function
     896            0 :     GETMATIDXVAR(glass, refract, float)// this is the getglassrefract() function
     897            0 :     GETMATIDXVAR(glass, spec, int)// this is the getglassspec() function
     898              : 
     899            0 :     void renderglass()
     900              :     {
     901            0 :         for(int k = 0; k < 4; ++k)
     902              :         {
     903            0 :             const std::vector<materialsurface> &surfs = glasssurfs[k];
     904            0 :             if(surfs.empty())
     905              :             {
     906            0 :                 continue;
     907              :             }
     908              : 
     909            0 :             MatSlot &gslot = lookupmaterialslot(Mat_Glass+k);
     910              : 
     911            0 :             Texture *tex = gslot.sts.size() ? gslot.sts[0].t : notexture;
     912            0 :             float glassxscale = defaulttexscale/(tex->xs*gslot.scale),
     913            0 :                   glassyscale = defaulttexscale/(tex->ys*gslot.scale);
     914              : 
     915            0 :             glActiveTexture(GL_TEXTURE1);
     916            0 :             glBindTexture(GL_TEXTURE_2D, tex->id);
     917            0 :             glActiveTexture(GL_TEXTURE0);
     918              : 
     919            0 :             float refractscale = (0.5f/255)/ldrscale;
     920            0 :             const bvec &col = getglasscolor(k);
     921            0 :             float refract = getglassrefract(k);
     922            0 :             int spec = getglassspec(k);
     923            0 :             GLOBALPARAMF(glassrefract, col.x*refractscale, col.y*refractscale, col.z*refractscale, refract*viewh);
     924            0 :             GLOBALPARAMF(glassspec, spec/100.0f);
     925              : 
     926            0 :             for(const materialsurface &m: surfs)
     927              :             {
     928            0 :                 drawglass(m, 0.1f, glassxscale, glassyscale, matnormals(m.orient));
     929              :             }
     930            0 :             xtraverts += gle::end();
     931              :         }
     932            0 :     }
     933              : 
     934              :     //sets the given material bounding vectors using the provided materialsurface
     935              :     //used by calcmatbb to set vertex array glass/water min/max fields
     936            0 :     void addmatbb(ivec &matmin, ivec &matmax, const materialsurface &m)
     937              :     {
     938            0 :         int dim = DIMENSION(m.orient);
     939            0 :         ivec mmin(m.o),
     940            0 :              mmax(m.o);
     941            0 :         if(DIM_COORD(m.orient))
     942              :         {
     943            0 :             mmin[dim] -= 2;
     944              :         }
     945              :         else
     946              :         {
     947            0 :             mmax[dim] += 2;
     948              :         }
     949            0 :         mmax[R[dim]] += m.rsize;
     950            0 :         mmax[C[dim]] += m.csize;
     951            0 :         matmin.min(mmin);
     952            0 :         matmax.max(mmax);
     953            0 :     }
     954              : }
     955              : 
     956              : // externally relevant functionality
     957              : 
     958            0 : vec matnormals(int i)
     959              : {
     960              :     static const std::array<vec, 6> matnormals =
     961              :     {
     962              :         vec(-1, 0, 0),
     963              :         vec( 1, 0, 0),
     964              :         vec(0, -1, 0),
     965              :         vec(0,  1, 0),
     966              :         vec(0, 0, -1),
     967              :         vec(0, 0,  1)
     968            0 :     };
     969              : 
     970            0 :     if(i < 0 || i > 6)
     971              :     {
     972            0 :         return vec(0,0,0);
     973              :     }
     974              :     else
     975              :     {
     976            0 :         return matnormals[i];
     977              :     }
     978              : }
     979              : 
     980            1 : int findmaterial(const char *name)
     981              : {
     982           17 :     for(int i = 0; i < static_cast<int>(sizeof(materials)/sizeof(material)); ++i)
     983              :     {
     984           16 :         if(!std::strcmp(materials[i].name, name))
     985              :         {
     986            0 :             return materials[i].id;
     987              :         }
     988              :     }
     989            1 :     return -1;
     990              : }
     991              : 
     992            0 : const char *findmaterialname(int mat)
     993              : {
     994            0 :     for(int i = 0; i < static_cast<int>(sizeof(materials)/sizeof(materials[0])); ++i)
     995              :     {
     996            0 :         if(materials[i].id == mat)
     997              :         {
     998            0 :             return materials[i].name;
     999              :         }
    1000              :     }
    1001            0 :     return nullptr;
    1002              : }
    1003              : 
    1004              : /* getmaterialdesc
    1005              :  *
    1006              :  * given a material id, returns the description of the material (char *)
    1007              :  */
    1008            0 : const char *getmaterialdesc(int mat, const char *prefix)
    1009              : {
    1010              :     static const std::array<ushort, 4> matmasks = { MatFlag_Volume|MatFlag_Index, MatFlag_Clip, Mat_Death, Mat_Alpha };
    1011              :     static string desc;
    1012            0 :     desc[0] = '\0';
    1013            0 :     for(int i = 0; i < static_cast<int>(sizeof(matmasks)/sizeof(matmasks[0])); ++i)
    1014              :     {
    1015            0 :         if(mat&matmasks[i])
    1016              :         {
    1017            0 :             const char *matname = findmaterialname(mat&matmasks[i]);
    1018            0 :             if(matname)
    1019              :             {
    1020            0 :                 concatstring(desc, desc[0] ? ", " : prefix);
    1021            0 :                 concatstring(desc, matname);
    1022              :             }
    1023              :         }
    1024              :     }
    1025            0 :     return desc;
    1026              : }
    1027              : 
    1028            0 : void genmatsurfs(const cube &c, const ivec &co, int size, std::vector<materialsurface> &matsurfs)
    1029              : {
    1030              :     static const std::array<ushort, 4> matmasks =
    1031              :     {
    1032              :         MatFlag_Volume|MatFlag_Index,
    1033              :         MatFlag_Clip,
    1034              :         Mat_Death,
    1035              :         Mat_Alpha
    1036              :     };
    1037            0 :     for(int i = 0; i < 6; ++i)
    1038              :     {
    1039            0 :         for(const ushort &matmask : matmasks)
    1040              :         {
    1041            0 :             int vis = visiblematerial(c, i, co, size, matmask&~MatFlag_Index);
    1042            0 :             if(vis != MatSurf_NotVisible)
    1043              :             {
    1044            0 :                 materialsurface m;
    1045            0 :                 m.material = c.material&matmask;
    1046            0 :                 m.orient = i;
    1047            0 :                 m.visible = vis;
    1048            0 :                 m.o = co;
    1049            0 :                 m.csize = m.rsize = size;
    1050            0 :                 if(DIM_COORD(i))
    1051              :                 {
    1052            0 :                     m.o[DIMENSION(i)] += size;
    1053              :                 }
    1054            0 :                 matsurfs.push_back(m);
    1055            0 :                 break;
    1056              :             }
    1057              :         }
    1058              :     }
    1059            0 : }
    1060              : 
    1061              : //sets the vertex array's material bounding box depending upon the material surfaces given
    1062            0 : void calcmatbb(vtxarray *va, const ivec &co, int size, const std::vector<materialsurface> &matsurfs)
    1063              : {
    1064            0 :     va->watermax = va->glassmax = co;
    1065            0 :     va->watermin = va->glassmin = ivec(co).add(size);
    1066            0 :     for(const materialsurface &m : matsurfs)
    1067              :     {
    1068            0 :         switch(m.material&MatFlag_Volume)
    1069              :         {
    1070            0 :             case Mat_Water:
    1071              :             {
    1072            0 :                 if(m.visible == MatSurf_EditOnly)
    1073              :                 {
    1074            0 :                     continue;
    1075              :                 }
    1076            0 :                 addmatbb(va->watermin, va->watermax, m);
    1077            0 :                 break;
    1078              :             }
    1079            0 :             case Mat_Glass:
    1080              :             {
    1081            0 :                 addmatbb(va->glassmin, va->glassmax, m);
    1082            0 :                 break;
    1083              :             }
    1084            0 :             default:
    1085              :             {
    1086            0 :                 continue;
    1087              :             }
    1088              :         }
    1089              :     }
    1090            0 : }
    1091              : 
    1092            0 : int optimizematsurfs(materialsurface *matbuf, int matsurfs)
    1093              : {
    1094            0 :     std::sort(matbuf, matbuf+matsurfs, optmatcmp);
    1095            0 :     const materialsurface *cur = matbuf,
    1096            0 :                           *end = matbuf+matsurfs;
    1097            0 :     while(cur < end)
    1098              :     {
    1099            0 :          const materialsurface *start = cur++;
    1100            0 :          int dim = DIMENSION(start->orient);
    1101            0 :          while(cur < end &&
    1102            0 :                cur->material == start->material &&
    1103            0 :                cur->orient == start->orient &&
    1104            0 :                cur->visible == start->visible &&
    1105            0 :                cur->o[dim] == start->o[dim])
    1106              :         {
    1107            0 :             ++cur;
    1108              :         }
    1109            0 :         if(!IS_LIQUID(start->material&MatFlag_Volume) || start->orient != Orient_Top || !vertwater)
    1110              :         {
    1111            0 :             if(start!=matbuf)
    1112              :             {
    1113            0 :                 std::memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
    1114              :             }
    1115            0 :             matbuf += mergemats(matbuf, cur-start);
    1116              :         }
    1117            0 :         else if(cur-start>=4)
    1118              :         {
    1119            0 :             QuadNode vmats(0, 0, rootworld.mapsize());
    1120            0 :             for(int i = 0; i < cur-start; ++i)
    1121              :             {
    1122            0 :                 vmats.insert(start[i].o[C[dim]], start[i].o[R[dim]], start[i].csize);
    1123              :             }
    1124            0 :             vmats.genmatsurfs(start->material, start->orient, start->visible, start->o[dim], matbuf);
    1125            0 :         }
    1126              :         else
    1127              :         {
    1128            0 :             if(start!=matbuf)
    1129              :             {
    1130            0 :                 std::memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
    1131              :             }
    1132            0 :             matbuf += cur-start;
    1133              :         }
    1134              :     }
    1135            0 :     return matsurfs - (end-matbuf);
    1136              : }
    1137              : 
    1138              : //treats `rootworld` as const
    1139            0 : void setupmaterials(int start, int len)
    1140              : {
    1141            0 :     int hasmat = 0;
    1142            0 :     if(!len)
    1143              :     {
    1144            0 :         len = valist.size();
    1145              :     }
    1146            0 :     for(int i = start; i < len; i++)
    1147              :     {
    1148            0 :         vtxarray *va = valist[i]; //only modifies va->matbuf entries of valist
    1149            0 :         materialsurface *skip = nullptr;
    1150            0 :         for(int j = 0; j < va -> matsurfs; ++j)
    1151              :         {
    1152            0 :             materialsurface &m = va->matbuf[j];
    1153            0 :             int matvol = m.material&MatFlag_Volume;
    1154            0 :             if(IS_LIQUID(matvol) && m.orient!=Orient_Bottom && m.orient!=Orient_Top)
    1155              :             {
    1156            0 :                 m.ends = 0;
    1157            0 :                 int dim = DIMENSION(m.orient),
    1158            0 :                     coord = DIM_COORD(m.orient);
    1159            0 :                 ivec o(m.o);
    1160            0 :                 o.z -= 1;
    1161            0 :                 o[dim] += coord ? 1 : -1;
    1162            0 :                 int minc = o[dim^1],
    1163            0 :                     maxc = minc + (C[dim]==2 ? m.rsize : m.csize);
    1164            0 :                 ivec co;
    1165              :                 int csize;
    1166            0 :                 while(o[dim^1] < maxc)
    1167              :                 {
    1168            0 :                     const cube &c = rootworld.lookupcube(o, 0, co, csize);
    1169            0 :                     if(IS_LIQUID(c.material&MatFlag_Volume))
    1170              :                     {
    1171            0 :                         m.ends |= 1;
    1172            0 :                         break;
    1173              :                     }
    1174            0 :                     o[dim^1] += csize;
    1175              :                 }
    1176            0 :                 o[dim^1] = minc;
    1177            0 :                 o.z += R[dim]==2 ? m.rsize : m.csize;
    1178            0 :                 o[dim] -= coord ? 2 : -2;
    1179            0 :                 while(o[dim^1] < maxc)
    1180              :                 {
    1181            0 :                     const cube &c = rootworld.lookupcube(o, 0, co, csize);
    1182            0 :                     if(visiblematerial(c, Orient_Top, co, csize))
    1183              :                     {
    1184            0 :                         m.ends |= 2;
    1185            0 :                         break;
    1186              :                     }
    1187            0 :                     o[dim^1] += csize;
    1188              :                 }
    1189            0 :             }
    1190            0 :             else if(matvol==Mat_Glass)
    1191              :             {
    1192            0 :                 int dim = DIMENSION(m.orient);
    1193            0 :                 vec center(m.o);
    1194            0 :                 center[R[dim]] += m.rsize/2;
    1195            0 :                 center[C[dim]] += m.csize/2;
    1196              :             }
    1197            0 :             if(matvol)
    1198              :             {
    1199            0 :                 hasmat |= 1<<m.material;
    1200              :             }
    1201            0 :             m.skip = 0;
    1202            0 :             if(skip && m.material == skip->material && m.orient == skip->orient && skip->skip < 0xFFFF)
    1203              :             {
    1204            0 :                 skip->skip++;
    1205              :             }
    1206              :             else
    1207              :             {
    1208            0 :                 skip = &m;
    1209              :             }
    1210              :         }
    1211              :     }
    1212            0 :     if(hasmat&(0xF<<Mat_Water))
    1213              :     {
    1214            0 :         loadcaustics(true);
    1215            0 :         preloadwatershaders(true);
    1216            0 :         for(int i = 0; i < 4; ++i)
    1217              :         {
    1218            0 :             if(hasmat&(1<<(Mat_Water+i)))
    1219              :             {
    1220            0 :                 lookupmaterialslot(Mat_Water+i);
    1221              :             }
    1222              :         }
    1223              :     }
    1224            0 :     if(hasmat&(0xF<<Mat_Glass))
    1225              :     {
    1226            0 :         preloadglassshaders(true);
    1227            0 :         for(int i = 0; i < 4; ++i)
    1228              :         {
    1229            0 :             if(hasmat&(1<<(Mat_Glass+i)))
    1230              :             {
    1231            0 :                 lookupmaterialslot(Mat_Glass+i);
    1232              :             }
    1233              :         }
    1234              :     }
    1235            0 : }
    1236              : 
    1237              : VARP(showmat, 0, 1, 1); //toggles rendering material faces, used in iengine
    1238              : 
    1239            0 : GBuffer::MaterialInfo GBuffer::findmaterials() const
    1240              : {
    1241              :     MaterialInfo mi;
    1242            0 :     editsurfs.clear();
    1243            0 :     for(int i = 0; i < 4; ++i)
    1244              :     {
    1245            0 :         glasssurfs[i].clear();
    1246            0 :         watersurfs[i].clear();
    1247            0 :         waterfallsurfs[i].clear();
    1248              :     }
    1249            0 :     mi.matliquidsx1 = mi.matliquidsy1 = mi.matsolidsx1 = mi.matsolidsy1 = mi.matrefractsx1 = mi.matrefractsy1 = 1;
    1250            0 :     mi.matliquidsx2 = mi.matliquidsy2 = mi.matsolidsx2 = mi.matsolidsy2 = mi.matrefractsx2 = mi.matrefractsy2 = -1;
    1251            0 :     mi.matliquidtiles.fill(0);
    1252            0 :     mi.matsolidtiles.fill(0);
    1253            0 :     int hasmats = 0;
    1254            0 :     for(const vtxarray *va = visibleva; va; va = va->next)
    1255              :     {
    1256            0 :         if(!va->matsurfs || va->occluded >= Occlude_BB || va->curvfc >= ViewFrustumCull_Fogged)
    1257              :         {
    1258            0 :             continue;
    1259              :         }
    1260            0 :         if(editmode && showmat && !drawtex)
    1261              :         {
    1262            0 :             for(int i = 0; i < va->matsurfs; ++i)
    1263              :             {
    1264            0 :                 editsurfs.push_back(va->matbuf[i]);
    1265              :             }
    1266            0 :             continue;
    1267            0 :         }
    1268              :         float sx1, sy1, sx2, sy2;
    1269            0 :         if(va->watermin.x <= va->watermax.x && calcbbscissor(va->watermin, va->watermax, sx1, sy1, sx2, sy2))
    1270              :         {
    1271            0 :             mi.matliquidsx1 = std::min(mi.matliquidsx1, sx1);
    1272            0 :             mi.matliquidsy1 = std::min(mi.matliquidsy1, sy1);
    1273            0 :             mi.matliquidsx2 = std::max(mi.matliquidsx2, sx2);
    1274            0 :             mi.matliquidsy2 = std::max(mi.matliquidsy2, sy2);
    1275            0 :             masktiles(mi.matliquidtiles.data(), sx1, sy1, sx2, sy2);
    1276            0 :             mi.matrefractsx1 = std::min(mi.matrefractsx1, sx1);
    1277            0 :             mi.matrefractsy1 = std::min(mi.matrefractsy1, sy1);
    1278            0 :             mi.matrefractsx2 = std::max(mi.matrefractsx2, sx2);
    1279            0 :             mi.matrefractsy2 = std::max(mi.matrefractsy2, sy2);
    1280            0 :             for(int i = 0; i < va->matsurfs; ++i)
    1281              :             {
    1282            0 :                 const materialsurface &m = va->matbuf[i];
    1283              :                 //skip if only rendering edit mat boxes or non-water mat
    1284            0 :                 if((m.material&MatFlag_Volume) != Mat_Water || m.visible == MatSurf_EditOnly)
    1285              :                 {
    1286            0 :                     i += m.skip;
    1287            0 :                     continue;
    1288              :                 }
    1289            0 :                 hasmats |= 4|1;
    1290            0 :                 if(m.orient == Orient_Top)
    1291              :                 {
    1292            0 :                     for(int i = 0; i < 1 + m.skip; ++i)
    1293              :                     {
    1294            0 :                         watersurfs[m.material&MatFlag_Index].push_back((&m)[i]);
    1295              :                     }
    1296              :                 }
    1297              :                 else
    1298              :                 {
    1299            0 :                     for(int i = 0; i < 1 + m.skip; ++i)
    1300              :                     {
    1301            0 :                         waterfallsurfs[m.material&MatFlag_Index].push_back((&m)[i]);
    1302              :                     }
    1303              :                 }
    1304            0 :                 i += m.skip;
    1305              :             }
    1306              :         }
    1307            0 :         if(va->glassmin.x <= va->glassmax.x && calcbbscissor(va->glassmin, va->glassmax, sx1, sy1, sx2, sy2))
    1308              :         {
    1309            0 :             mi.matsolidsx1 = std::min(mi.matsolidsx1, sx1);
    1310            0 :             mi.matsolidsy1 = std::min(mi.matsolidsy1, sy1);
    1311            0 :             mi.matsolidsx2 = std::max(mi.matsolidsx2, sx2);
    1312            0 :             mi.matsolidsy2 = std::max(mi.matsolidsy2, sy2);
    1313            0 :             masktiles(mi.matsolidtiles.data(), sx1, sy1, sx2, sy2);
    1314            0 :             mi.matrefractsx1 = std::min(mi.matrefractsx1, sx1);
    1315            0 :             mi.matrefractsy1 = std::min(mi.matrefractsy1, sy1);
    1316            0 :             mi.matrefractsx2 = std::max(mi.matrefractsx2, sx2);
    1317            0 :             mi.matrefractsy2 = std::max(mi.matrefractsy2, sy2);
    1318            0 :             for(int i = 0; i < va->matsurfs; ++i)
    1319              :             {
    1320            0 :                 const materialsurface &m = va->matbuf[i];
    1321            0 :                 if((m.material&MatFlag_Volume) != Mat_Glass)
    1322              :                 {
    1323            0 :                     i += m.skip;
    1324            0 :                     continue;
    1325              :                 }
    1326            0 :                 hasmats |= 4|2;
    1327            0 :                 for(int i = 0; i < 1 + m.skip; ++i)
    1328              :                 {
    1329            0 :                     glasssurfs[m.material&MatFlag_Index].push_back((&m)[i]);
    1330              :                 }
    1331            0 :                 i += m.skip;
    1332              :             }
    1333              :         }
    1334              :     }
    1335            0 :     mi.hasmats = hasmats;
    1336            0 :     return mi;
    1337              : }
    1338              : 
    1339            0 : void GBuffer::rendermaterialmask() const
    1340              : {
    1341            0 :     glDisable(GL_CULL_FACE);
    1342            0 :     for(const std::vector<materialsurface> &k : glasssurfs)
    1343              :     {
    1344            0 :         for(const materialsurface &i : k)
    1345              :         {
    1346            0 :             drawmaterial(i, 0.1f);
    1347              :         }
    1348              :     }
    1349            0 :     for(const std::vector<materialsurface> &k : watersurfs)
    1350              :     {
    1351            0 :         for(const materialsurface &i : k)
    1352              :         {
    1353            0 :             drawmaterial(i, wateroffset);
    1354              :         }
    1355              :     }
    1356            0 :     for(const std::vector<materialsurface> &k : waterfallsurfs)
    1357              :     {
    1358            0 :         for(const materialsurface &i : k)
    1359              :         {
    1360            0 :             drawmaterial(i, 0.1f);
    1361              :         }
    1362              :     }
    1363            0 :     xtraverts += gle::end();
    1364            0 :     glEnable(GL_CULL_FACE);
    1365            0 : }
    1366              : 
    1367            0 : void GBuffer::renderliquidmaterials() const
    1368              : {
    1369            0 :     glDisable(GL_CULL_FACE);
    1370              : 
    1371            0 :     renderwater();
    1372            0 :     renderwaterfalls();
    1373              : 
    1374            0 :     glEnable(GL_CULL_FACE);
    1375            0 : }
    1376              : 
    1377            0 : void rendersolidmaterials()
    1378              : {
    1379            0 :     glDisable(GL_CULL_FACE);
    1380              : 
    1381            0 :     renderglass();
    1382              : 
    1383            0 :     glEnable(GL_CULL_FACE);
    1384            0 : }
    1385              : 
    1386            0 : void rendereditmaterials()
    1387              : {
    1388            0 :     if(editsurfs.empty())
    1389              :     {
    1390            0 :         return;
    1391              :     }
    1392            0 :     sorteditmaterials();
    1393              : 
    1394            0 :     glDisable(GL_CULL_FACE);
    1395              : 
    1396            0 :     zerofogcolor();
    1397              : 
    1398            0 :     foggednotextureshader->set();
    1399              : 
    1400            0 :     glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
    1401            0 :     glEnable(GL_BLEND);
    1402              : 
    1403            0 :     int lastmat = -1;
    1404            0 :     for(const materialsurface &m : editsurfs)
    1405              :     {
    1406            0 :         if(lastmat!=m.material)
    1407              :         {
    1408            0 :             xtraverts += gle::end();
    1409            0 :             bvec color;
    1410            0 :             switch(m.material&~MatFlag_Index)
    1411              :             {
    1412              :                 //note inverted colors
    1413            0 :                 case Mat_Water:
    1414              :                 {
    1415            0 :                     color = bvec(255, 128,   0);
    1416            0 :                     break; // blue
    1417              :                 }
    1418            0 :                 case Mat_Clip:
    1419              :                 {
    1420            0 :                     color = bvec(  0, 255, 255);
    1421            0 :                     break; // red
    1422              :                 }
    1423            0 :                 case Mat_Glass:
    1424              :                 {
    1425            0 :                     color = bvec(255,   0,   0);
    1426            0 :                     break; // cyan
    1427              :                 }
    1428            0 :                 case Mat_NoClip:
    1429              :                 {
    1430            0 :                     color = bvec(255,   0, 255);
    1431            0 :                     break; // green
    1432              :                 }
    1433            0 :                 case Mat_GameClip:
    1434              :                 {
    1435            0 :                     color = bvec(  0,   0, 255);
    1436            0 :                     break; // yellow
    1437              :                 }
    1438            0 :                 case Mat_Death:
    1439              :                 {
    1440            0 :                     color = bvec(192, 192, 192);
    1441            0 :                     break; // black
    1442              :                 }
    1443            0 :                 case Mat_Alpha:
    1444              :                 {
    1445            0 :                     color = bvec(  0, 255,   0);
    1446            0 :                     break; // pink
    1447              :                 }
    1448            0 :                 default:
    1449              :                 {
    1450            0 :                     continue;
    1451              :                 }
    1452              :             }
    1453            0 :             gle::color(color);
    1454            0 :             lastmat = m.material;
    1455              :         }
    1456            0 :         drawmaterial(m, -0.1f);
    1457              :     }
    1458              : 
    1459            0 :     xtraverts += gle::end();
    1460            0 :     glDisable(GL_BLEND);
    1461            0 :     resetfogcolor();
    1462            0 :     rendermatgrid();
    1463            0 :     glEnable(GL_CULL_FACE);
    1464              : }
    1465              : 
    1466            0 : void renderminimapmaterials()
    1467              : {
    1468            0 :     glDisable(GL_CULL_FACE);
    1469            0 :     renderwater();
    1470            0 :     glEnable(GL_CULL_FACE);
    1471            0 : }
    1472              : 
        

Generated by: LCOV version 2.0-1