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 :
|