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

          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 1.14