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