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