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: 2025-02-18 06:21:28 Functions: 2.4 % 42 1

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

Generated by: LCOV version 2.0-1