Line data Source code
1 : /**
2 : * @file world light interaction functions
3 : *
4 : * while renderlights in /render handles the deferred rendering of point lights
5 : * on the world, light.cpp handles how lights behave in the world
6 : *
7 : * includes sunlight variables (direction/color of no-parallax sun lighting)
8 : * world light entity packing for the renderer to use
9 : */
10 : #include "../libprimis-headers/cube.h"
11 : #include "../../shared/geomexts.h"
12 : #include "../../shared/glexts.h"
13 :
14 : #include "light.h"
15 : #include "octaworld.h"
16 : #include "raycube.h"
17 : #include "world.h"
18 :
19 : #include "interface/console.h"
20 : #include "interface/input.h"
21 :
22 : #include "render/radiancehints.h"
23 : #include "render/renderlights.h"
24 : #include "render/normal.h"
25 : #include "render/octarender.h"
26 : #include "render/shaderparam.h"
27 : #include "render/texture.h"
28 :
29 : namespace
30 : {
31 : /**
32 : * @brief Sets the sunlight direction from the sunlightyaw/pitch variables.
33 : *
34 : * Clears the radiance hints cache after resetting the sunlight directory, so
35 : * old GI buffers are cleared and new dynamic sunlight can be calculated
36 : */
37 0 : void setsunlightdir()
38 : {
39 0 : sunlightdir = vec(sunlightyaw/RAD, sunlightpitch/RAD);
40 0 : for(int k = 0; k < 3; ++k)
41 : {
42 0 : if(std::fabs(sunlightdir[k]) < 1e-5f)
43 : {
44 0 : sunlightdir[k] = 0;
45 : }
46 : }
47 0 : sunlightdir.normalize();
48 0 : clearradiancehintscache();
49 0 : }
50 :
51 0 : void setsurfaces(cube &c, std::array<surfaceinfo, 6> surfs, const vertinfo *verts, int numverts)
52 : {
53 0 : if(!c.ext || c.ext->maxverts < numverts)
54 : {
55 0 : newcubeext(c, numverts, false);
56 : }
57 0 : std::copy(c.ext->surfaces.begin(), c.ext->surfaces.end(), surfs.begin());
58 0 : std::memcpy(c.ext->verts(), verts, numverts*sizeof(vertinfo));
59 0 : }
60 :
61 0 : void clearsurfaces(std::array<cube, 8> &c)
62 : {
63 0 : for(int i = 0; i < 8; ++i)
64 : {
65 0 : if(c[i].ext)
66 : {
67 0 : for(int j = 0; j < 6; ++j)
68 : {
69 0 : surfaceinfo &surf = c[i].ext->surfaces[j];
70 0 : if(!surf.used())
71 : {
72 0 : continue;
73 : }
74 0 : surf.clear();
75 0 : int numverts = surf.numverts&Face_MaxVerts;
76 0 : if(numverts)
77 : {
78 0 : if(!(c[i].merged&(1<<j)))
79 : {
80 0 : surf.numverts &= ~Face_MaxVerts;
81 0 : continue;
82 : }
83 0 : vertinfo *verts = c[i].ext->verts() + surf.verts;
84 0 : for(int k = 0; k < numverts; ++k)
85 : {
86 0 : vertinfo &v = verts[k];
87 0 : v.norm = 0;
88 : }
89 : }
90 : }
91 : }
92 0 : if(c[i].children)
93 : {
94 0 : clearsurfaces(*(c[i].children));
95 : }
96 : }
97 0 : }
98 :
99 : constexpr int lightcacheentries = 1024;
100 :
101 : struct lightcacheentry final
102 : {
103 : int x, y;
104 : };
105 :
106 : std::array<lightcacheentry, lightcacheentries> lightcache;
107 :
108 0 : int lightcachehash(int x, int y)
109 : {
110 0 : return (((((x)^(y))<<5) + (((x)^(y))>>5)) & (lightcacheentries - 1));
111 : }
112 :
113 : /**
114 : * @brief Takes a 3d vec3 and transforms it into a packed ushort vector
115 : *
116 : * The output ushort is in base 360 and has yaw in the first place and pitch in the second place.
117 : * The second place has pitch as a range from 0 to 90; since this is a normal
118 : * vector, no magnitude is needed.
119 : *
120 : * @param n the normal to encode
121 : *
122 : * @return the packed normal vector
123 : */
124 0 : ushort encodenormal(const vec &n)
125 : {
126 0 : if(n.iszero())
127 : {
128 0 : return 0;
129 : }
130 0 : const int yaw = static_cast<int>(-std::atan2(n.x, n.y)*RAD), //arctangent in degrees
131 0 : pitch = static_cast<int>(std::asin(n.z)*RAD); //arcsin in degrees
132 0 : return static_cast<ushort>(std::clamp(pitch + 90, 0, 180)*360 + (yaw < 0 ? yaw%360 + 360 : yaw%360) + 1);
133 : }
134 :
135 0 : void calcsurfaces(cube &c, const ivec &co, int size, int usefacemask, int preview = 0)
136 : {
137 0 : std::array<surfaceinfo, 6> surfaces;
138 : std::array<vertinfo, 6*2*Face_MaxVerts> litverts;
139 0 : int numlitverts = 0;
140 0 : surfaces.fill(surfaceinfo());
141 0 : for(int i = 0; i < 6; ++i) //for each face of the cube
142 : {
143 0 : int usefaces = usefacemask&0xF;
144 0 : usefacemask >>= 4;
145 0 : if(!usefaces)
146 : {
147 0 : if(!c.ext)
148 : {
149 0 : continue;
150 : }
151 0 : surfaceinfo &surf = c.ext->surfaces[i];
152 0 : int numverts = surf.totalverts();
153 0 : if(numverts)
154 : {
155 0 : std::memcpy(&litverts[numlitverts], c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
156 0 : surf.verts = numlitverts;
157 0 : numlitverts += numverts;
158 : }
159 0 : continue;
160 0 : }
161 :
162 0 : VSlot &vslot = lookupvslot(c.texture[i], false),
163 0 : *layer = vslot.layer && !(c.material&Mat_Alpha) ? &lookupvslot(vslot.layer, false) : nullptr;
164 0 : Shader *shader = vslot.slot->shader;
165 0 : int shadertype = shader->type;
166 0 : if(layer)
167 : {
168 0 : shadertype |= layer->slot->shader->type;
169 : }
170 0 : surfaceinfo &surf = surfaces[i];
171 0 : vertinfo *curlitverts = &litverts[numlitverts];
172 0 : int numverts = c.ext ? c.ext->surfaces[i].numverts&Face_MaxVerts : 0;
173 0 : ivec mo(co);
174 0 : int msz = size,
175 0 : convex = 0;
176 0 : if(numverts)
177 : {
178 0 : const vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts;
179 0 : for(int j = 0; j < numverts; ++j)
180 : {
181 0 : curlitverts[j].set(verts[j].getxyz());
182 : }
183 0 : if(c.merged&(1<<i))
184 : {
185 0 : msz = 1<<calcmergedsize(mo, size, verts, numverts);
186 0 : mo.mask(~(msz-1));
187 0 : if(!(surf.numverts&Face_MaxVerts))
188 : {
189 0 : surf.verts = numlitverts;
190 0 : surf.numverts |= numverts;
191 0 : numlitverts += numverts;
192 : }
193 : }
194 0 : else if(!flataxisface(c, i))
195 : {
196 0 : convex = faceconvexity(verts, numverts, size);
197 : }
198 : }
199 : else
200 : {
201 0 : std::array<ivec, 4> v;
202 0 : genfaceverts(c, i, v);
203 0 : if(!flataxisface(c, i))
204 : {
205 0 : convex = faceconvexity(v);
206 : }
207 0 : int order = usefaces&4 || convex < 0 ? 1 : 0;
208 0 : ivec vo = ivec(co).mask(0xFFF).shl(3);
209 0 : curlitverts[numverts++].set(v[order].mul(size).add(vo));
210 0 : if(usefaces&1)
211 : {
212 0 : curlitverts[numverts++].set(v[order+1].mul(size).add(vo));
213 : }
214 0 : curlitverts[numverts++].set(v[order+2].mul(size).add(vo));
215 0 : if(usefaces&2)
216 : {
217 0 : curlitverts[numverts++].set(v[(order+3)&3].mul(size).add(vo));
218 : }
219 : }
220 :
221 0 : std::array<vec, Face_MaxVerts> pos,
222 0 : n;
223 0 : vec po(ivec(co).mask(~0xFFF));
224 0 : for(int j = 0; j < numverts; ++j)
225 : {
226 0 : pos[j] = vec(curlitverts[j].getxyz()).mul(1.0f/8).add(po);
227 : }
228 :
229 0 : int smooth = vslot.slot->smooth;
230 0 : std::array<plane, 2> planes;
231 0 : int numplanes = 0;
232 0 : planes[numplanes++].toplane(pos[0], pos[1], pos[2]);
233 0 : if(numverts < 4 || !convex)
234 : {
235 0 : for(int k = 0; k < numverts; ++k)
236 : {
237 0 : findnormal(pos[k], smooth, planes[0], n[k]);
238 : }
239 0 : }
240 : else
241 : {
242 0 : planes[numplanes++].toplane(pos[0], pos[2], pos[3]);
243 0 : vec avg = vec(planes[0]).add(planes[1]).normalize();
244 0 : findnormal(pos[0], smooth, avg, n[0]);
245 0 : findnormal(pos[1], smooth, planes[0], n[1]);
246 0 : findnormal(pos[2], smooth, avg, n[2]);
247 0 : for(int k = 3; k < numverts; k++)
248 : {
249 0 : findnormal(pos[k], smooth, planes[1], n[k]);
250 : }
251 : }
252 0 : for(int k = 0; k < numverts; ++k)
253 : {
254 0 : curlitverts[k].norm = encodenormal(n[k]);
255 : }
256 0 : if(!(surf.numverts&Face_MaxVerts))
257 : {
258 0 : surf.verts = numlitverts;
259 0 : surf.numverts |= numverts;
260 0 : numlitverts += numverts;
261 : }
262 0 : if(preview)
263 : {
264 0 : surf.numverts |= preview;
265 0 : continue;
266 : }
267 0 : int surflayer = BlendLayer_Top;
268 0 : if(vslot.layer)
269 : {
270 0 : int x1 = curlitverts[numverts-1].x,
271 0 : y1 = curlitverts[numverts-1].y,
272 0 : x2 = x1,
273 0 : y2 = y1;
274 0 : for(int j = 0; j < numverts-1; ++j)
275 : {
276 0 : const vertinfo &v = curlitverts[j];
277 0 : x1 = std::min(x1, static_cast<int>(v.x));
278 0 : y1 = std::min(y1, static_cast<int>(v.y));
279 0 : x2 = std::max(x2, static_cast<int>(v.x));
280 0 : y2 = std::max(y2, static_cast<int>(v.y));
281 : }
282 0 : x2 = std::max(x2, x1+1);
283 0 : y2 = std::max(y2, y1+1);
284 0 : x1 = (x1>>3) + (co.x&~0xFFF);
285 0 : y1 = (y1>>3) + (co.y&~0xFFF);
286 0 : x2 = ((x2+7)>>3) + (co.x&~0xFFF);
287 0 : y2 = ((y2+7)>>3) + (co.y&~0xFFF);
288 : }
289 0 : surf.numverts |= surflayer;
290 : }
291 0 : if(preview)
292 : {
293 0 : setsurfaces(c, surfaces, litverts.data(), numlitverts);
294 : }
295 : else
296 : {
297 0 : for(const surfaceinfo &surf : surfaces)
298 : {
299 0 : if(surf.used())
300 : {
301 0 : cubeext *ext = c.ext && c.ext->maxverts >= numlitverts ? c.ext : growcubeext(c.ext, numlitverts);
302 0 : std::memcpy(ext->surfaces.data(), surfaces.data(), sizeof(ext->surfaces));
303 0 : std::memcpy(ext->verts(), litverts.data(), numlitverts*sizeof(vertinfo));
304 0 : if(c.ext != ext)
305 : {
306 0 : setcubeext(c, ext);
307 : }
308 0 : break;
309 : }
310 : }
311 : }
312 0 : }
313 :
314 0 : void calcsurfaces(std::array<cube, 8> &c, const ivec &co, int size)
315 : {
316 0 : for(int i = 0; i < 8; ++i)
317 : {
318 0 : ivec o(i, co, size);
319 0 : if(c[i].children)
320 : {
321 0 : calcsurfaces(*(c[i].children), o, size >> 1);
322 : }
323 0 : else if(!(c[i].isempty()))
324 : {
325 0 : if(c[i].ext)
326 : {
327 0 : for(surfaceinfo &s : c[i].ext->surfaces)
328 : {
329 0 : s.clear();
330 : }
331 : }
332 0 : int usefacemask = 0;
333 0 : for(int j = 0; j < 6; ++j)
334 : {
335 0 : if(c[i].texture[j] != Default_Sky && (!(c[i].merged & (1 << j)) || (c[i].ext && c[i].ext->surfaces[j].numverts & Face_MaxVerts)))
336 : {
337 0 : usefacemask |= visibletris(c[i], j, o, size)<<(4*j);
338 : }
339 : }
340 0 : if(usefacemask)
341 : {
342 0 : calcsurfaces(c[i], o, size, usefacemask);
343 : }
344 : }
345 : }
346 0 : }
347 : }
348 :
349 : //external functionality
350 :
351 0 : CVAR1R(ambient, 0x191919);
352 : FVARR(ambientscale, 0, 1, 16);
353 :
354 0 : CVAR1R(skylight, 0);
355 : FVARR(skylightscale, 0, 1, 16);
356 :
357 0 : CVAR1FR(sunlight, 0,
358 : {
359 : clearradiancehintscache();
360 : cleardeferredlightshaders();
361 : clearshadowcache();
362 : });
363 0 : FVARFR(sunlightscale, 0, 1, 16, clearradiancehintscache(););
364 :
365 : vec sunlightdir(0, 0, 1);
366 0 : FVARFR(sunlightyaw, 0, 0, 360, setsunlightdir());
367 0 : FVARFR(sunlightpitch, -90, 90, 90, setsunlightdir());
368 :
369 0 : void brightencube(cube &c)
370 : {
371 0 : if(!c.ext)
372 : {
373 0 : newcubeext(c, 0, false);
374 : }
375 0 : c.ext->surfaces.fill(surfaceinfo());
376 0 : }
377 :
378 0 : void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *srcverts, int numsrcverts)
379 : {
380 0 : int dstoffset = 0;
381 0 : if(!c.ext)
382 : {
383 0 : newcubeext(c, numsrcverts, true);
384 : }
385 : else
386 : {
387 0 : int numbefore = 0,
388 0 : beforeoffset = 0;
389 0 : for(int i = 0; i < orient; ++i)
390 : {
391 0 : const surfaceinfo &surf = c.ext->surfaces[i];
392 0 : int numverts = surf.totalverts();
393 0 : if(!numverts)
394 : {
395 0 : continue;
396 : }
397 0 : numbefore += numverts;
398 0 : beforeoffset = surf.verts + numverts;
399 : }
400 0 : int numafter = 0,
401 0 : afteroffset = c.ext->maxverts;
402 0 : for(int i = 5; i > orient; i--) //note reverse iteration
403 : {
404 0 : const surfaceinfo &surf = c.ext->surfaces[i];
405 0 : int numverts = surf.totalverts();
406 0 : if(!numverts)
407 : {
408 0 : continue;
409 : }
410 0 : numafter += numverts;
411 0 : afteroffset = surf.verts;
412 : }
413 0 : if(afteroffset - beforeoffset >= numsrcverts)
414 : {
415 0 : dstoffset = beforeoffset;
416 : }
417 : else
418 : {
419 0 : cubeext *ext = c.ext;
420 0 : if(numbefore + numsrcverts + numafter > c.ext->maxverts)
421 : {
422 0 : ext = growcubeext(c.ext, numbefore + numsrcverts + numafter);
423 0 : std::copy(ext->surfaces.begin(), ext->surfaces.end(), c.ext->surfaces.begin());
424 : }
425 0 : int offset = 0;
426 0 : if(numbefore == beforeoffset)
427 : {
428 0 : if(numbefore && c.ext != ext)
429 : {
430 0 : std::memcpy(ext->verts(), c.ext->verts(), numbefore*sizeof(vertinfo));
431 : }
432 0 : offset = numbefore;
433 : }
434 : else
435 : {
436 0 : for(int i = 0; i < orient; ++i)
437 : {
438 0 : surfaceinfo &surf = ext->surfaces[i];
439 0 : int numverts = surf.totalverts();
440 0 : if(!numverts)
441 : {
442 0 : continue;
443 : }
444 0 : std::memmove(ext->verts() + offset, c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
445 0 : surf.verts = offset;
446 0 : offset += numverts;
447 : }
448 : }
449 0 : dstoffset = offset;
450 0 : offset += numsrcverts;
451 0 : if(numafter && offset > afteroffset)
452 : {
453 0 : offset += numafter;
454 0 : for(int i = 5; i > orient; i--) //note reverse iteration
455 : {
456 0 : surfaceinfo &surf = ext->surfaces[i];
457 0 : int numverts = surf.totalverts();
458 0 : if(!numverts)
459 : {
460 0 : continue;
461 : }
462 0 : offset -= numverts;
463 0 : std::memmove(ext->verts() + offset, c.ext->verts() + surf.verts, numverts*sizeof(vertinfo));
464 0 : surf.verts = offset;
465 : }
466 : }
467 0 : if(c.ext != ext)
468 : {
469 0 : setcubeext(c, ext);
470 : }
471 : }
472 : }
473 0 : surfaceinfo &dst = c.ext->surfaces[orient];
474 0 : dst = src;
475 0 : dst.verts = dstoffset;
476 0 : if(srcverts)
477 : {
478 0 : std::memcpy(c.ext->verts() + dstoffset, srcverts, numsrcverts*sizeof(vertinfo));
479 : }
480 0 : }
481 :
482 14 : PackNode::PackNode(ushort x, ushort y, ushort w, ushort h) : w(w), h(h), child1(0), child2(0), x(x), y(y), available(std::min(w, h))
483 : {
484 14 : }
485 :
486 1 : void PackNode::reset()
487 : {
488 1 : discardchildren();
489 1 : available = std::min(w, h);
490 1 : }
491 :
492 1 : bool PackNode::resize(int nw, int nh)
493 : {
494 1 : if(w == nw && h == nw)
495 : {
496 0 : return false;
497 : }
498 1 : discardchildren();
499 1 : w = nw;
500 1 : h = nh;
501 1 : available = std::min(w, h);
502 1 : return true;
503 : }
504 :
505 14 : PackNode::~PackNode()
506 : {
507 14 : discardchildren();
508 14 : }
509 :
510 33 : bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th)
511 : {
512 33 : if((available < tw && available < th) || w < tw || h < th)
513 : {
514 9 : return false;
515 : }
516 24 : if(child1)
517 : {
518 21 : bool inserted = child1->insert(tx, ty, tw, th) ||
519 9 : child2->insert(tx, ty, tw, th);
520 12 : available = std::max(child1->available, child2->available);
521 12 : if(!available)
522 : {
523 3 : discardchildren();
524 : }
525 12 : return inserted;
526 : }
527 12 : if(w == tw && h == th)
528 : {
529 6 : available = 0;
530 6 : tx = x;
531 6 : ty = y;
532 6 : return true;
533 : }
534 :
535 6 : if(w - tw > h - th)
536 : {
537 4 : child1 = new PackNode(x, y, tw, h);
538 4 : child2 = new PackNode(x + tw, y, w - tw, h);
539 : }
540 : else
541 : {
542 2 : child1 = new PackNode(x, y, w, th);
543 2 : child2 = new PackNode(x, y + th, w, h - th);
544 : }
545 :
546 6 : bool inserted = child1->insert(tx, ty, tw, th);
547 6 : available = std::max(child1->available, child2->available);
548 6 : return inserted;
549 : }
550 :
551 0 : void PackNode::reserve(ushort tx, ushort ty, ushort tw, ushort th)
552 : {
553 0 : if(tx + tw <= x || tx >= x + w || ty + th <= y || ty >= y + h)
554 : {
555 0 : return;
556 : }
557 0 : if(child1)
558 : {
559 0 : child1->reserve(tx, ty, tw, th);
560 0 : child2->reserve(tx, ty, tw, th);
561 0 : available = std::max(child1->available, child2->available);
562 0 : return;
563 : }
564 0 : int dx1 = tx - x,
565 0 : dx2 = x + w - tx - tw,
566 0 : dx = std::max(dx1, dx2),
567 0 : dy1 = ty - y,
568 0 : dy2 = y + h - ty - th,
569 0 : dy = std::max(dy1, dy2),
570 : split;
571 0 : if(dx > dy)
572 : {
573 0 : if(dx1 > dx2)
574 : {
575 0 : split = std::min(dx1, static_cast<int>(w));
576 : }
577 : else
578 : {
579 0 : split = w - std::max(dx2, 0);
580 : }
581 0 : if(w - split <= 0)
582 : {
583 0 : w = split;
584 0 : available = std::min(w, h);
585 0 : if(dy > 0)
586 : {
587 0 : reserve(tx, ty, tw, th);
588 : }
589 0 : else if(tx <= x && tx + tw >= x + w)
590 : {
591 0 : available = 0;
592 : }
593 0 : return;
594 : }
595 0 : if(split <= 0)
596 : {
597 0 : x += split;
598 0 : w -= split;
599 0 : available = std::min(w, h);
600 0 : if(dy > 0)
601 : {
602 0 : reserve(tx, ty, tw, th);
603 : }
604 0 : else if(tx <= x && tx + tw >= x + w)
605 : {
606 0 : available = 0;
607 : }
608 0 : return;
609 : }
610 0 : child1 = new PackNode(x, y, split, h);
611 0 : child2 = new PackNode(x + split, y, w - split, h);
612 : }
613 : else
614 : {
615 0 : if(dy1 > dy2)
616 : {
617 0 : split = std::min(dy1, static_cast<int>(h));
618 : }
619 : else
620 : {
621 0 : split = h - std::max(dy2, 0);
622 : }
623 0 : if(h - split <= 0)
624 : {
625 0 : h = split;
626 0 : available = std::min(w, h);
627 0 : if(dx > 0)
628 : {
629 0 : reserve(tx, ty, tw, th);
630 : }
631 0 : else if(ty <= y && ty + th >= y + h)
632 : {
633 0 : available = 0;
634 : }
635 0 : return;
636 : }
637 0 : if(split <= 0)
638 : {
639 0 : y += split;
640 0 : h -= split;
641 0 : available = std::min(w, h);
642 0 : if(dx > 0)
643 : {
644 0 : reserve(tx, ty, tw, th);
645 : }
646 0 : else if(ty <= y && ty + th >= y + h)
647 : {
648 0 : available = 0;
649 : }
650 0 : return;
651 : }
652 0 : child1 = new PackNode(x, y, w, split);
653 0 : child2 = new PackNode(x, y + split, w, h - split);
654 : }
655 0 : child1->reserve(tx, ty, tw, th);
656 0 : child2->reserve(tx, ty, tw, th);
657 0 : available = std::max(child1->available, child2->available);
658 : }
659 :
660 3 : int PackNode::availablespace() const
661 : {
662 3 : return available;
663 : }
664 :
665 2 : vec2 PackNode::dimensions() const
666 : {
667 2 : return {static_cast<float>(w), static_cast<float>(h)};
668 : }
669 :
670 7 : void PackNode::printchildren(int i) const
671 : {
672 7 : print(i);
673 :
674 7 : if(child1)
675 : {
676 3 : child1->printchildren(i+1);
677 : }
678 7 : if(child2)
679 : {
680 3 : child2->printchildren(i+1);
681 : }
682 7 : }
683 :
684 7 : void PackNode::print(int i) const
685 : {
686 7 : std::printf("%d: %d %d\n", i, w, h);
687 7 : }
688 :
689 19 : void PackNode::discardchildren()
690 : {
691 19 : if(child1)
692 : {
693 6 : delete child1;
694 6 : child1 = nullptr;
695 : }
696 19 : if(child2)
697 : {
698 6 : delete child2;
699 6 : child2 = nullptr;
700 : }
701 19 : }
702 :
703 0 : static VARF(lightcachesize, 4, 6, 12, clearlightcache());
704 :
705 0 : void clearlightcache(int id)
706 : {
707 0 : if(id >= 0)
708 : {
709 0 : const extentity &light = *entities::getents()[id];
710 0 : int radius = light.attr1;
711 0 : if(radius <= 0)
712 : {
713 0 : return;
714 : }
715 0 : for(int x = static_cast<int>(std::max(light.o.x-radius, 0.0f))>>lightcachesize, ex = static_cast<int>(std::min(light.o.x+radius, rootworld.mapsize()-1.0f))>>lightcachesize; x <= ex; x++)
716 : {
717 0 : for(int y = static_cast<int>(std::max(light.o.y-radius, 0.0f))>>lightcachesize, ey = static_cast<int>(std::min(light.o.y+radius, rootworld.mapsize()-1.0f))>>lightcachesize; y <= ey; y++)
718 : {
719 0 : lightcacheentry &lce = lightcache[lightcachehash(x, y)];
720 0 : if(lce.x != x || lce.y != y)
721 : {
722 0 : continue;
723 : }
724 0 : lce.x = -1;
725 : }
726 : }
727 0 : return;
728 : }
729 :
730 0 : for(lightcacheentry &lce : lightcache)
731 : {
732 0 : lce.x = -1;
733 : }
734 : }
735 :
736 0 : void cubeworld::calclight()
737 : {
738 0 : remip();
739 0 : clearsurfaces(*worldroot);
740 0 : calcnormals(filltjoints > 0);
741 0 : calcsurfaces(*worldroot, ivec(0, 0, 0), rootworld.mapsize() >> 1);
742 0 : clearnormals();
743 0 : allchanged();
744 0 : }
745 :
746 0 : void clearlights()
747 : {
748 0 : clearlightcache();
749 0 : clearshadowcache();
750 0 : cleardeferredlightshaders();
751 0 : resetsmoothgroups();
752 0 : }
753 :
754 0 : void initlights()
755 : {
756 0 : clearlightcache();
757 0 : clearshadowcache();
758 0 : loaddeferredlightshaders();
759 0 : }
|