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 final
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 final
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 : const 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 : const 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 : const 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 : static const std::array<vec, 6> matnormals =
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 1 : int findmaterial(const char *name)
980 : {
981 17 : for(int i = 0; i < static_cast<int>(sizeof(materials)/sizeof(material)); ++i)
982 : {
983 16 : if(!std::strcmp(materials[i].name, name))
984 : {
985 0 : return materials[i].id;
986 : }
987 : }
988 1 : return -1;
989 : }
990 :
991 : /* findmaterialname
992 : *
993 : * given a material id, returns the name of the material as a string (char *)
994 : */
995 0 : const char *findmaterialname(int mat)
996 : {
997 0 : for(int i = 0; i < static_cast<int>(sizeof(materials)/sizeof(materials[0])); ++i)
998 : {
999 0 : if(materials[i].id == mat)
1000 : {
1001 0 : return materials[i].name;
1002 : }
1003 : }
1004 0 : return nullptr;
1005 : }
1006 :
1007 : /* getmaterialdesc
1008 : *
1009 : * given a material id, returns the description of the material (char *)
1010 : */
1011 0 : const char *getmaterialdesc(int mat, const char *prefix)
1012 : {
1013 : static const std::array<ushort, 4> matmasks = { MatFlag_Volume|MatFlag_Index, MatFlag_Clip, Mat_Death, Mat_Alpha };
1014 : static string desc;
1015 0 : desc[0] = '\0';
1016 0 : for(int i = 0; i < static_cast<int>(sizeof(matmasks)/sizeof(matmasks[0])); ++i)
1017 : {
1018 0 : if(mat&matmasks[i])
1019 : {
1020 0 : const char *matname = findmaterialname(mat&matmasks[i]);
1021 0 : if(matname)
1022 : {
1023 0 : concatstring(desc, desc[0] ? ", " : prefix);
1024 0 : concatstring(desc, matname);
1025 : }
1026 : }
1027 : }
1028 0 : return desc;
1029 : }
1030 :
1031 0 : void genmatsurfs(const cube &c, const ivec &co, int size, std::vector<materialsurface> &matsurfs)
1032 : {
1033 : static const std::array<ushort, 4> matmasks =
1034 : {
1035 : MatFlag_Volume|MatFlag_Index,
1036 : MatFlag_Clip,
1037 : Mat_Death,
1038 : Mat_Alpha
1039 : };
1040 0 : for(int i = 0; i < 6; ++i)
1041 : {
1042 0 : for(const ushort &matmask : matmasks)
1043 : {
1044 0 : int vis = visiblematerial(c, i, co, size, matmask&~MatFlag_Index);
1045 0 : if(vis != MatSurf_NotVisible)
1046 : {
1047 0 : materialsurface m;
1048 0 : m.material = c.material&matmask;
1049 0 : m.orient = i;
1050 0 : m.visible = vis;
1051 0 : m.o = co;
1052 0 : m.csize = m.rsize = size;
1053 0 : if(DIM_COORD(i))
1054 : {
1055 0 : m.o[DIMENSION(i)] += size;
1056 : }
1057 0 : matsurfs.push_back(m);
1058 0 : break;
1059 : }
1060 : }
1061 : }
1062 0 : }
1063 :
1064 : //sets the vertex array's material bounding box depending upon the material surfaces given
1065 0 : void calcmatbb(vtxarray *va, const ivec &co, int size, const std::vector<materialsurface> &matsurfs)
1066 : {
1067 0 : va->watermax = va->glassmax = co;
1068 0 : va->watermin = va->glassmin = ivec(co).add(size);
1069 0 : for(const materialsurface &m : matsurfs)
1070 : {
1071 0 : switch(m.material&MatFlag_Volume)
1072 : {
1073 0 : case Mat_Water:
1074 : {
1075 0 : if(m.visible == MatSurf_EditOnly)
1076 : {
1077 0 : continue;
1078 : }
1079 0 : addmatbb(va->watermin, va->watermax, m);
1080 0 : break;
1081 : }
1082 0 : case Mat_Glass:
1083 : {
1084 0 : addmatbb(va->glassmin, va->glassmax, m);
1085 0 : break;
1086 : }
1087 0 : default:
1088 : {
1089 0 : continue;
1090 : }
1091 : }
1092 : }
1093 0 : }
1094 :
1095 0 : int optimizematsurfs(materialsurface *matbuf, int matsurfs)
1096 : {
1097 0 : std::sort(matbuf, matbuf+matsurfs, optmatcmp);
1098 0 : const materialsurface *cur = matbuf,
1099 0 : *end = matbuf+matsurfs;
1100 0 : while(cur < end)
1101 : {
1102 0 : const materialsurface *start = cur++;
1103 0 : int dim = DIMENSION(start->orient);
1104 0 : while(cur < end &&
1105 0 : cur->material == start->material &&
1106 0 : cur->orient == start->orient &&
1107 0 : cur->visible == start->visible &&
1108 0 : cur->o[dim] == start->o[dim])
1109 : {
1110 0 : ++cur;
1111 : }
1112 0 : if(!IS_LIQUID(start->material&MatFlag_Volume) || start->orient != Orient_Top || !vertwater)
1113 : {
1114 0 : if(start!=matbuf)
1115 : {
1116 0 : std::memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
1117 : }
1118 0 : matbuf += mergemats(matbuf, cur-start);
1119 : }
1120 0 : else if(cur-start>=4)
1121 : {
1122 0 : QuadNode vmats(0, 0, rootworld.mapsize());
1123 0 : for(int i = 0; i < cur-start; ++i)
1124 : {
1125 0 : vmats.insert(start[i].o[C[dim]], start[i].o[R[dim]], start[i].csize);
1126 : }
1127 0 : vmats.genmatsurfs(start->material, start->orient, start->visible, start->o[dim], matbuf);
1128 0 : }
1129 : else
1130 : {
1131 0 : if(start!=matbuf)
1132 : {
1133 0 : std::memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
1134 : }
1135 0 : matbuf += cur-start;
1136 : }
1137 : }
1138 0 : return matsurfs - (end-matbuf);
1139 : }
1140 :
1141 : //treats `rootworld` as const
1142 0 : void setupmaterials(int start, int len)
1143 : {
1144 0 : int hasmat = 0;
1145 0 : if(!len)
1146 : {
1147 0 : len = valist.size();
1148 : }
1149 0 : for(int i = start; i < len; i++)
1150 : {
1151 0 : vtxarray *va = valist[i]; //only modifies va->matbuf entries of valist
1152 0 : materialsurface *skip = nullptr;
1153 0 : for(int j = 0; j < va -> matsurfs; ++j)
1154 : {
1155 0 : materialsurface &m = va->matbuf[j];
1156 0 : int matvol = m.material&MatFlag_Volume;
1157 0 : if(IS_LIQUID(matvol) && m.orient!=Orient_Bottom && m.orient!=Orient_Top)
1158 : {
1159 0 : m.ends = 0;
1160 0 : int dim = DIMENSION(m.orient),
1161 0 : coord = DIM_COORD(m.orient);
1162 0 : ivec o(m.o);
1163 0 : o.z -= 1;
1164 0 : o[dim] += coord ? 1 : -1;
1165 0 : int minc = o[dim^1],
1166 0 : maxc = minc + (C[dim]==2 ? m.rsize : m.csize);
1167 0 : ivec co;
1168 : int csize;
1169 0 : while(o[dim^1] < maxc)
1170 : {
1171 0 : const cube &c = rootworld.lookupcube(o, 0, co, csize);
1172 0 : if(IS_LIQUID(c.material&MatFlag_Volume))
1173 : {
1174 0 : m.ends |= 1;
1175 0 : break;
1176 : }
1177 0 : o[dim^1] += csize;
1178 : }
1179 0 : o[dim^1] = minc;
1180 0 : o.z += R[dim]==2 ? m.rsize : m.csize;
1181 0 : o[dim] -= coord ? 2 : -2;
1182 0 : while(o[dim^1] < maxc)
1183 : {
1184 0 : const cube &c = rootworld.lookupcube(o, 0, co, csize);
1185 0 : if(visiblematerial(c, Orient_Top, co, csize))
1186 : {
1187 0 : m.ends |= 2;
1188 0 : break;
1189 : }
1190 0 : o[dim^1] += csize;
1191 : }
1192 0 : }
1193 0 : else if(matvol==Mat_Glass)
1194 : {
1195 0 : int dim = DIMENSION(m.orient);
1196 0 : vec center(m.o);
1197 0 : center[R[dim]] += m.rsize/2;
1198 0 : center[C[dim]] += m.csize/2;
1199 : }
1200 0 : if(matvol)
1201 : {
1202 0 : hasmat |= 1<<m.material;
1203 : }
1204 0 : m.skip = 0;
1205 0 : if(skip && m.material == skip->material && m.orient == skip->orient && skip->skip < 0xFFFF)
1206 : {
1207 0 : skip->skip++;
1208 : }
1209 : else
1210 : {
1211 0 : skip = &m;
1212 : }
1213 : }
1214 : }
1215 0 : if(hasmat&(0xF<<Mat_Water))
1216 : {
1217 0 : loadcaustics(true);
1218 0 : preloadwatershaders(true);
1219 0 : for(int i = 0; i < 4; ++i)
1220 : {
1221 0 : if(hasmat&(1<<(Mat_Water+i)))
1222 : {
1223 0 : lookupmaterialslot(Mat_Water+i);
1224 : }
1225 : }
1226 : }
1227 0 : if(hasmat&(0xF<<Mat_Glass))
1228 : {
1229 0 : preloadglassshaders(true);
1230 0 : for(int i = 0; i < 4; ++i)
1231 : {
1232 0 : if(hasmat&(1<<(Mat_Glass+i)))
1233 : {
1234 0 : lookupmaterialslot(Mat_Glass+i);
1235 : }
1236 : }
1237 : }
1238 0 : }
1239 :
1240 : VARP(showmat, 0, 1, 1); //toggles rendering material faces, used in iengine
1241 :
1242 0 : GBuffer::MaterialInfo GBuffer::findmaterials() const
1243 : {
1244 : MaterialInfo mi;
1245 0 : editsurfs.clear();
1246 0 : for(int i = 0; i < 4; ++i)
1247 : {
1248 0 : glasssurfs[i].clear();
1249 0 : watersurfs[i].clear();
1250 0 : waterfallsurfs[i].clear();
1251 : }
1252 0 : mi.matliquidsx1 = mi.matliquidsy1 = mi.matsolidsx1 = mi.matsolidsy1 = mi.matrefractsx1 = mi.matrefractsy1 = 1;
1253 0 : mi.matliquidsx2 = mi.matliquidsy2 = mi.matsolidsx2 = mi.matsolidsy2 = mi.matrefractsx2 = mi.matrefractsy2 = -1;
1254 0 : std::memset(mi.matliquidtiles, 0, sizeof(mi.matliquidtiles));
1255 0 : std::memset(mi.matsolidtiles, 0, sizeof(mi.matsolidtiles));
1256 0 : int hasmats = 0;
1257 0 : for(const vtxarray *va = visibleva; va; va = va->next)
1258 : {
1259 0 : if(!va->matsurfs || va->occluded >= Occlude_BB || va->curvfc >= ViewFrustumCull_Fogged)
1260 : {
1261 0 : continue;
1262 : }
1263 0 : if(editmode && showmat && !drawtex)
1264 : {
1265 0 : for(int i = 0; i < va->matsurfs; ++i)
1266 : {
1267 0 : editsurfs.push_back(va->matbuf[i]);
1268 : }
1269 0 : continue;
1270 0 : }
1271 : float sx1, sy1, sx2, sy2;
1272 0 : if(va->watermin.x <= va->watermax.x && calcbbscissor(va->watermin, va->watermax, sx1, sy1, sx2, sy2))
1273 : {
1274 0 : mi.matliquidsx1 = std::min(mi.matliquidsx1, sx1);
1275 0 : mi.matliquidsy1 = std::min(mi.matliquidsy1, sy1);
1276 0 : mi.matliquidsx2 = std::max(mi.matliquidsx2, sx2);
1277 0 : mi.matliquidsy2 = std::max(mi.matliquidsy2, sy2);
1278 0 : masktiles(mi.matliquidtiles, sx1, sy1, sx2, sy2);
1279 0 : mi.matrefractsx1 = std::min(mi.matrefractsx1, sx1);
1280 0 : mi.matrefractsy1 = std::min(mi.matrefractsy1, sy1);
1281 0 : mi.matrefractsx2 = std::max(mi.matrefractsx2, sx2);
1282 0 : mi.matrefractsy2 = std::max(mi.matrefractsy2, sy2);
1283 0 : for(int i = 0; i < va->matsurfs; ++i)
1284 : {
1285 0 : const materialsurface &m = va->matbuf[i];
1286 : //skip if only rendering edit mat boxes or non-water mat
1287 0 : if((m.material&MatFlag_Volume) != Mat_Water || m.visible == MatSurf_EditOnly)
1288 : {
1289 0 : i += m.skip;
1290 0 : continue;
1291 : }
1292 0 : hasmats |= 4|1;
1293 0 : if(m.orient == Orient_Top)
1294 : {
1295 0 : for(int i = 0; i < 1 + m.skip; ++i)
1296 : {
1297 0 : watersurfs[m.material&MatFlag_Index].push_back((&m)[i]);
1298 : }
1299 : }
1300 : else
1301 : {
1302 0 : for(int i = 0; i < 1 + m.skip; ++i)
1303 : {
1304 0 : waterfallsurfs[m.material&MatFlag_Index].push_back((&m)[i]);
1305 : }
1306 : }
1307 0 : i += m.skip;
1308 : }
1309 : }
1310 0 : if(va->glassmin.x <= va->glassmax.x && calcbbscissor(va->glassmin, va->glassmax, sx1, sy1, sx2, sy2))
1311 : {
1312 0 : mi.matsolidsx1 = std::min(mi.matsolidsx1, sx1);
1313 0 : mi.matsolidsy1 = std::min(mi.matsolidsy1, sy1);
1314 0 : mi.matsolidsx2 = std::max(mi.matsolidsx2, sx2);
1315 0 : mi.matsolidsy2 = std::max(mi.matsolidsy2, sy2);
1316 0 : masktiles(mi.matsolidtiles, sx1, sy1, sx2, sy2);
1317 0 : mi.matrefractsx1 = std::min(mi.matrefractsx1, sx1);
1318 0 : mi.matrefractsy1 = std::min(mi.matrefractsy1, sy1);
1319 0 : mi.matrefractsx2 = std::max(mi.matrefractsx2, sx2);
1320 0 : mi.matrefractsy2 = std::max(mi.matrefractsy2, sy2);
1321 0 : for(int i = 0; i < va->matsurfs; ++i)
1322 : {
1323 0 : const materialsurface &m = va->matbuf[i];
1324 0 : if((m.material&MatFlag_Volume) != Mat_Glass)
1325 : {
1326 0 : i += m.skip;
1327 0 : continue;
1328 : }
1329 0 : hasmats |= 4|2;
1330 0 : for(int i = 0; i < 1 + m.skip; ++i)
1331 : {
1332 0 : glasssurfs[m.material&MatFlag_Index].push_back((&m)[i]);
1333 : }
1334 0 : i += m.skip;
1335 : }
1336 : }
1337 : }
1338 0 : mi.hasmats = hasmats;
1339 0 : return mi;
1340 : }
1341 :
1342 0 : void GBuffer::rendermaterialmask() const
1343 : {
1344 0 : glDisable(GL_CULL_FACE);
1345 0 : for(const std::vector<materialsurface> &k : glasssurfs)
1346 : {
1347 0 : for(const materialsurface &i : k)
1348 : {
1349 0 : drawmaterial(i, 0.1f);
1350 : }
1351 : }
1352 0 : for(const std::vector<materialsurface> &k : watersurfs)
1353 : {
1354 0 : for(const materialsurface &i : k)
1355 : {
1356 0 : drawmaterial(i, wateroffset);
1357 : }
1358 : }
1359 0 : for(const std::vector<materialsurface> &k : waterfallsurfs)
1360 : {
1361 0 : for(const materialsurface &i : k)
1362 : {
1363 0 : drawmaterial(i, 0.1f);
1364 : }
1365 : }
1366 0 : xtraverts += gle::end();
1367 0 : glEnable(GL_CULL_FACE);
1368 0 : }
1369 :
1370 0 : void GBuffer::renderliquidmaterials() const
1371 : {
1372 0 : glDisable(GL_CULL_FACE);
1373 :
1374 0 : renderwater();
1375 0 : renderwaterfalls();
1376 :
1377 0 : glEnable(GL_CULL_FACE);
1378 0 : }
1379 :
1380 0 : void rendersolidmaterials()
1381 : {
1382 0 : glDisable(GL_CULL_FACE);
1383 :
1384 0 : renderglass();
1385 :
1386 0 : glEnable(GL_CULL_FACE);
1387 0 : }
1388 :
1389 0 : void rendereditmaterials()
1390 : {
1391 0 : if(editsurfs.empty())
1392 : {
1393 0 : return;
1394 : }
1395 0 : sorteditmaterials();
1396 :
1397 0 : glDisable(GL_CULL_FACE);
1398 :
1399 0 : zerofogcolor();
1400 :
1401 0 : foggednotextureshader->set();
1402 :
1403 0 : glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
1404 0 : glEnable(GL_BLEND);
1405 :
1406 0 : int lastmat = -1;
1407 0 : for(const materialsurface &m : editsurfs)
1408 : {
1409 0 : if(lastmat!=m.material)
1410 : {
1411 0 : xtraverts += gle::end();
1412 0 : bvec color;
1413 0 : switch(m.material&~MatFlag_Index)
1414 : {
1415 : //note inverted colors
1416 0 : case Mat_Water:
1417 : {
1418 0 : color = bvec(255, 128, 0);
1419 0 : break; // blue
1420 : }
1421 0 : case Mat_Clip:
1422 : {
1423 0 : color = bvec( 0, 255, 255);
1424 0 : break; // red
1425 : }
1426 0 : case Mat_Glass:
1427 : {
1428 0 : color = bvec(255, 0, 0);
1429 0 : break; // cyan
1430 : }
1431 0 : case Mat_NoClip:
1432 : {
1433 0 : color = bvec(255, 0, 255);
1434 0 : break; // green
1435 : }
1436 0 : case Mat_GameClip:
1437 : {
1438 0 : color = bvec( 0, 0, 255);
1439 0 : break; // yellow
1440 : }
1441 0 : case Mat_Death:
1442 : {
1443 0 : color = bvec(192, 192, 192);
1444 0 : break; // black
1445 : }
1446 0 : case Mat_Alpha:
1447 : {
1448 0 : color = bvec( 0, 255, 0);
1449 0 : break; // pink
1450 : }
1451 0 : default:
1452 : {
1453 0 : continue;
1454 : }
1455 : }
1456 0 : gle::color(color);
1457 0 : lastmat = m.material;
1458 : }
1459 0 : drawmaterial(m, -0.1f);
1460 : }
1461 :
1462 0 : xtraverts += gle::end();
1463 0 : glDisable(GL_BLEND);
1464 0 : resetfogcolor();
1465 0 : rendermatgrid();
1466 0 : glEnable(GL_CULL_FACE);
1467 : }
1468 :
1469 0 : void renderminimapmaterials()
1470 : {
1471 0 : glDisable(GL_CULL_FACE);
1472 0 : renderwater();
1473 0 : glEnable(GL_CULL_FACE);
1474 0 : }
1475 :
|