1 /*
2 * Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
3 *
4 * This file is part of Arx Libertatis.
5 *
6 * Arx Libertatis is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Arx Libertatis is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
18 */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
33 <http://www.gnu.org/licenses/>.
34
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43 // Copyright (c) 1999-2000 ARKANE Studios SA. All rights reserved
44
45 #include "scene/Light.h"
46
47 #include "core/Application.h"
48 #include "core/GameTime.h"
49 #include "core/Core.h"
50 #include "game/Entity.h"
51 #include "game/EntityManager.h"
52 #include "game/Inventory.h"
53 #include "graphics/Math.h"
54 #include "graphics/Draw.h"
55 #include "scene/Object.h"
56 #include "scene/GameSound.h"
57 #include "scene/Interactive.h"
58
59 extern float GLOBAL_LIGHT_FACTOR;
60 EERIE_LIGHT * GLight[MAX_LIGHTS];
61 EERIE_LIGHT DynLight[MAX_DYNLIGHTS];
62
63 EERIE_LIGHT * PDL[MAX_DYNLIGHTS];
64 long TOTPDL = 0;
65
66 EERIE_LIGHT * IO_PDL[MAX_DYNLIGHTS];
67 long TOTIOPDL = 0;
68
69 static void ARX_EERIE_LIGHT_Make(EERIEPOLY * ep, float * epr, float * epg, float * epb, EERIE_LIGHT * light);
70
ValidDynLight(long num)71 bool ValidDynLight(long num)
72 {
73 if ( (num >= 0)
74 && ((size_t)num < MAX_DYNLIGHTS)
75 && DynLight[num].exist)
76 return true;
77
78 return false;
79 }
80
PrecalcIOLighting(const Vec3f * pos,float radius,long flags)81 void PrecalcIOLighting(const Vec3f * pos, float radius, long flags) {
82
83 static Vec3f lastpos;
84 if(flags & 1) {
85 lastpos = Vec3f::repeat(99999.f) + lastpos;
86 return;
87 }
88
89 // Lastpos optim
90 if(closerThan(*pos, lastpos, 100.f)) {
91 return;
92 }
93
94 lastpos = *pos;
95
96 TOTIOPDL = 0;
97
98 for(size_t i = 0; i < MAX_LIGHTS; i++) {
99
100 EERIE_LIGHT * el = GLight[i];
101
102 if ((el) && (el->exist) && (el->status)
103 && !(el->extras & EXTRAS_SEMIDYNAMIC))
104 {
105 if ((el->pos.x >= pos->x - radius) && (el->pos.x <= pos->x + radius)
106 && (el->pos.z >= pos->z - radius) && (el->pos.z <= pos->z + radius))
107 {
108
109 el->rgb255 = el->rgb * 255.f;
110 el->falldiff = el->fallend - el->fallstart;
111 el->falldiffmul = 1.f / el->falldiff;
112 el->precalc = el->intensity * GLOBAL_LIGHT_FACTOR;
113 IO_PDL[TOTIOPDL] = el;
114
115 TOTIOPDL++;
116
117 if ((size_t)TOTIOPDL >= MAX_DYNLIGHTS) TOTIOPDL--;
118 }
119 }
120 }
121 }
122
EERIE_LIGHT_Apply(EERIEPOLY * ep)123 void EERIE_LIGHT_Apply(EERIEPOLY * ep) {
124
125 if (ep->type & POLY_IGNORE) return;
126
127 float epr[4];
128 float epg[4];
129 float epb[4];
130
131 epr[3] = epr[2] = epr[1] = epr[0] = 0;
132 epg[3] = epg[2] = epg[1] = epg[0] = 0;
133 epb[3] = epb[2] = epb[1] = epb[0] = 0;
134
135 for(size_t i = 0; i < MAX_LIGHTS; i++) {
136
137 EERIE_LIGHT * el = GLight[i];
138
139 if ((el) && (el->treat) && (el->exist) && (el->status)
140 && !(el->extras & EXTRAS_SEMIDYNAMIC))
141 {
142 if(closerThan(el->pos, ep->center, el->fallend + 100.f)) {
143 ARX_EERIE_LIGHT_Make(ep, epr, epg, epb, el);
144 }
145 }
146 }
147
148 for (size_t i = 0; i < MAX_ACTIONS; i++)
149 {
150 if ((actions[i].exist) && ((actions[i].type == ACT_FIRE2) || (actions[i].type == ACT_FIRE)))
151 {
152 if(closerThan(actions[i].light.pos, ep->center, actions[i].light.fallend + 100.f)) {
153 ARX_EERIE_LIGHT_Make(ep, epr, epg, epb, &actions[i].light);
154 }
155 }
156 }
157
158 long nbvert;
159
160 if (ep->type & POLY_QUAD) nbvert = 4;
161 else nbvert = 3;
162
163 for(long i = 0; i < nbvert; i++) {
164 epr[i] = clamp(epr[i], ACTIVEBKG->ambient.r, 1.f);
165 epg[i] = clamp(epg[i], ACTIVEBKG->ambient.g, 1.f);
166 epb[i] = clamp(epb[i], ACTIVEBKG->ambient.b, 1.f);
167 ep->v[i].color = Color3f(epr[i], epg[i], epb[i]).toBGR();
168 }
169 }
170
EERIE_LIGHT_TranslateSelected(const Vec3f * trans)171 void EERIE_LIGHT_TranslateSelected(const Vec3f * trans) {
172 for(size_t i = 0; i < MAX_LIGHTS; i++) {
173 if(GLight[i] && GLight[i]->selected) {
174 if(GLight[i]->tl > 0) {
175 DynLight[GLight[i]->tl].exist = 0;
176 }
177 GLight[i]->tl = -1;
178 GLight[i]->pos += *trans;
179 }
180 }
181 }
182
EERIE_LIGHT_UnselectAll()183 void EERIE_LIGHT_UnselectAll() {
184 for(size_t i = 0; i < MAX_LIGHTS; i++) {
185 if(GLight[i] && GLight[i]->exist && GLight[i]->treat) {
186 GLight[i]->selected = 0;
187 }
188 }
189 }
190
EERIE_LIGHT_ClearByIndex(long num)191 void EERIE_LIGHT_ClearByIndex(long num)
192 {
193 if ((num >= 0) && ((size_t)num < MAX_LIGHTS))
194 {
195 if (GLight[num] != NULL)
196 {
197 if (GLight[num]->tl != -1) DynLight[GLight[num]->tl].exist = 0;
198
199 free(GLight[num]);
200 GLight[num] = NULL;
201 }
202 }
203 }
204
EERIE_LIGHT_ClearAll()205 void EERIE_LIGHT_ClearAll() {
206 for(size_t i = 0; i < MAX_LIGHTS; i++) {
207 EERIE_LIGHT_ClearByIndex(i);
208 }
209 }
210
EERIE_LIGHT_ClearSelected()211 void EERIE_LIGHT_ClearSelected() {
212 for(size_t i = 0; i < MAX_LIGHTS; i++) {
213 if(GLight[i] && GLight[i]->selected) {
214 EERIE_LIGHT_ClearByIndex(i);
215 }
216 }
217 }
218
EERIE_LIGHT_GlobalInit()219 void EERIE_LIGHT_GlobalInit() {
220
221 static long init = 0;
222
223 if(!init) {
224 memset(GLight, 0, sizeof(*GLight) * MAX_LIGHTS);
225 init = 1;
226 return;
227 }
228
229 for(size_t i = 0; i < MAX_LIGHTS; i++) {
230 if(GLight[i]) {
231 if(GLight[i]->tl > 0) {
232 DynLight[GLight[i]->tl].exist = 0;
233 }
234 free(GLight[i]);
235 GLight[i] = NULL;
236 }
237 }
238 }
239
EERIE_LIGHT_GetFree()240 long EERIE_LIGHT_GetFree() {
241
242 for(size_t i = 0; i < MAX_LIGHTS; i++) {
243 if(!GLight[i]) {
244 return i;
245 }
246 }
247
248 return -1;
249 }
250
EERIE_LIGHT_Create()251 long EERIE_LIGHT_Create() {
252
253 for (size_t i = 0; i < MAX_LIGHTS; i++) {
254 if(!GLight[i]) {
255
256 GLight[i] = (EERIE_LIGHT *)malloc(sizeof(EERIE_LIGHT));
257 if(!GLight[i]) {
258 return -1;
259 }
260
261 memset(GLight[i], 0, sizeof(EERIE_LIGHT));
262 GLight[i]->sample = audio::INVALID_ID;
263 GLight[i]->tl = -1;
264 return i;
265 }
266 }
267
268 return -1;
269 }
270
271
EERIE_LIGHT_Count()272 long EERIE_LIGHT_Count() {
273
274 long count = 0;
275 for(size_t i = 0; i < MAX_LIGHTS; i++) {
276 if(GLight[i] && !(GLight[i]->type & TYP_SPECIAL1)) {
277 count++;
278 }
279 }
280
281 return count;
282 }
283
EERIE_LIGHT_GlobalAdd(const EERIE_LIGHT * el)284 void EERIE_LIGHT_GlobalAdd(const EERIE_LIGHT * el)
285 {
286 long num = EERIE_LIGHT_GetFree();
287
288 if (num > -1)
289 {
290 GLight[num] = (EERIE_LIGHT *)malloc(sizeof(EERIE_LIGHT));
291 memcpy(GLight[num], el, sizeof(EERIE_LIGHT));
292 GLight[num]->tl = -1;
293 GLight[num]->sample = audio::INVALID_ID;
294 }
295 }
296
EERIE_LIGHT_MoveAll(const Vec3f * trans)297 void EERIE_LIGHT_MoveAll(const Vec3f * trans) {
298 for(size_t i = 0; i < MAX_LIGHTS; i++) {
299 if(GLight[i]) {
300 GLight[i]->pos += *trans;
301 }
302 }
303 }
304
305 //*************************************************************************************
306 //*************************************************************************************
my_CheckInPoly(float x,float y,float z,EERIEPOLY * mon_ep,EERIE_LIGHT * light)307 float my_CheckInPoly(float x, float y, float z, EERIEPOLY * mon_ep, EERIE_LIGHT * light)
308 {
309 long px, pz;
310 px = x * ACTIVEBKG->Xmul;
311
312
313 if (px > ACTIVEBKG->Xsize - 3)
314 {
315 return 0;
316 }
317
318 if (px < 2)
319 {
320 return 0;
321 }
322
323 pz = z * ACTIVEBKG->Zmul;
324
325 if (pz > ACTIVEBKG->Zsize - 3)
326 {
327 return 0;
328 }
329
330 if (pz < 2)
331 {
332 return 0;
333 }
334
335 float nb_shadowvertexinpoly = 0.0f;
336 float nb_totalvertexinpoly = 0.0f;
337
338 EERIEPOLY * ep;
339 EERIE_BKG_INFO * eg;
340
341 Vec3f dest;
342 Vec3f hit;
343
344 Vec3f orgn = light->pos;
345
346 for (long j = pz - 2; j <= pz + 2; j++)
347 for (long i = px - 2; i <= px + 2; i++)
348 {
349 eg = &ACTIVEBKG->Backg[i+j*ACTIVEBKG->Xsize];
350
351 for (long k = 0; k < eg->nbpoly; k++)
352 {
353 ep = &eg->polydata[k];
354
355 if (!(ep->type & POLY_WATER) && !(ep->type & POLY_TRANS))
356 {
357
358 long nbvert;
359 (ep->type & POLY_QUAD) ? nbvert = 4 : nbvert = 3;
360
361 long a, b;
362
363 for (a = 0; a < nbvert; a++)
364 {
365 float fDiff = 5.f;
366
367 if ((fabs(ep->v[a].p.x - x) <= fDiff) &&
368 (fabs(ep->v[a].p.y - y) <= fDiff) &&
369 (fabs(ep->v[a].p.z - z) <= fDiff))
370 {
371
372 if(dot(*mon_ep->nrml, *ep->nrml) > 0.0f) {
373 nb_totalvertexinpoly += nbvert;
374 for(b = 0; b < nbvert; b++) {
375 dest = ep->v[b].p;
376 if(Visible(&orgn, &dest, ep, &hit)) {
377 nb_shadowvertexinpoly ++;
378 }
379 }
380 }
381 }
382 }
383 }
384 }
385 }
386
387 return nb_shadowvertexinpoly / nb_totalvertexinpoly;
388 }
389
ARX_EERIE_LIGHT_Make(EERIEPOLY * ep,float * epr,float * epg,float * epb,EERIE_LIGHT * light)390 static void ARX_EERIE_LIGHT_Make(EERIEPOLY * ep, float * epr, float * epg, float * epb, EERIE_LIGHT * light)
391 {
392 int i; // iterator
393 int nbvert; // number or vertices per face (3 or 4)
394 float distance[4]; // distance from light to each vertex
395 float fRes; // value of light intensity for a given vertex
396
397 if (ep->type & POLY_IGNORE)
398 return;
399
400 (ep->type & POLY_QUAD) ? nbvert = 4 : nbvert = 3;
401
402 // compute light - vertex distance
403 for(i = 0; i < nbvert; i++) {
404 distance[i] = dist(light->pos, ep->v[i].p);
405 }
406
407 for (i = 0; i < nbvert; i++)
408 {
409 fRes = 1.0f;
410
411 if (distance[i] < light->fallend)
412 {
413 //---------------------- start MODE_NORMALS
414 if (ModeLight & MODE_NORMALS)
415 {
416 Vec3f vLight = (light->pos - ep->v[i].p).getNormalized(); // vector (light to vertex)
417
418 fRes = dot(vLight, ep->nrml[i]);
419
420 if (fRes < 0.0f)
421 {
422 fRes = 0.0f;
423 }
424 }
425
426 //---------------------- end MODE_NORMALS
427
428 //---------------------- start MODE_RAYLAUNCH
429 if ((ModeLight & MODE_RAYLAUNCH) && !(light->extras & EXTRAS_NOCASTED))
430 {
431 Vec3f orgn = light->pos, dest = ep->v[i].p, hit;
432
433 if (ModeLight & MODE_SMOOTH)
434 fRes *= my_CheckInPoly(ep->v[i].p.x, ep->v[i].p.y, ep->v[i].p.z, ep, light);
435 else
436 fRes *= Visible(&orgn, &dest, ep, &hit);
437 }
438
439 //---------------------- fin MODE_RAYLAUNCH
440
441 float fTemp1 = light->intensity * fRes * GLOBAL_LIGHT_FACTOR;
442 float fr, fg, fb;
443
444 if (distance[i] <= light->fallstart)
445 {
446 fr = light->rgb.r * fTemp1;
447 fg = light->rgb.g * fTemp1;
448 fb = light->rgb.b * fTemp1;
449 }
450 else
451 {
452 float intensity = (light->falldiff - (distance[i] - light->fallstart)) * light->falldiffmul;
453 float fTemp2 = fTemp1 * intensity;
454 fr = light->rgb.r * fTemp2;
455 fg = light->rgb.g * fTemp2;
456 fb = light->rgb.b * fTemp2;
457 }
458
459 epr[i] += fr;
460 epg[i] += fg;
461 epb[i] += fb;
462 }
463 }
464 }
465
ComputeLight2DPos(EERIE_LIGHT * _pL)466 void ComputeLight2DPos(EERIE_LIGHT * _pL) {
467
468 TexturedVertex in, out;
469 in.p = _pL->pos;
470 EERIETreatPoint(&in, &out);
471
472 if ((out.p.z > 0.f) && (out.p.z < 1000.f) && (out.rhw > 0))
473 {
474 float t;
475 float siz = 50;
476 float fMaxdist = 300;
477
478 if (Project.telekinesis) fMaxdist = 850;
479
480 t = siz * (1.0f - 1.0f / (out.rhw * fMaxdist)) + 10;
481
482 _pL->maxs.x = out.p.x + t;
483 _pL->mins.x = out.p.x - t;
484 _pL->maxs.y = out.p.y + t;
485 _pL->mins.y = out.p.y - t;
486
487
488 if (0)
489 if ((_pL->mins.x >= -200.f) && (_pL->mins.x <= 1000.f))
490 if ((_pL->mins.y >= -200.f) && (_pL->mins.y <= 1000.f))
491 {
492
493 EERIEDraw2DLine(_pL->mins.x, _pL->mins.y, _pL->maxs.x, _pL->mins.y, 0.00001f, Color::white);
494 EERIEDraw2DLine(_pL->maxs.x, _pL->mins.y, _pL->maxs.x, _pL->maxs.y, 0.00001f, Color::white);
495 EERIEDraw2DLine(_pL->maxs.x, _pL->maxs.y, _pL->mins.x, _pL->maxs.y, 0.00001f, Color::white);
496 EERIEDraw2DLine(_pL->mins.x, _pL->maxs.y, _pL->mins.x, _pL->mins.y, 0.00001f, Color::white);
497 }
498 }
499 }
500
501 //*************************************************************************************
502 //*************************************************************************************
TreatBackgroundDynlights()503 void TreatBackgroundDynlights()
504 {
505 long n;
506
507 for (size_t i = 0; i < MAX_LIGHTS; i++)
508 {
509 if ((GLight[i] != NULL) && (GLight[i]->extras & EXTRAS_SEMIDYNAMIC))
510 {
511 float fMaxdist = 300;
512
513 if (Project.telekinesis) fMaxdist = 850;
514
515 if(!fartherThan(GLight[i]->pos, ACTIVECAM->pos, fMaxdist)) {
516 ComputeLight2DPos(GLight[i]);
517 }
518
519 if (GLight[i]->status == 0)
520 {
521 // vient de s'éteindre
522 if (GLight[i]->tl > 0)
523 {
524 DynLight[GLight[i]->tl].exist = 0;
525 GLight[i]->tl = -1;
526 Vec3f _pos2;
527
528 for(size_t l = 0; l < entities.size(); l++) {
529 if(entities[l] && (entities[l]->ioflags & IO_MARKER)) {
530 GetItemWorldPosition(entities[l], &_pos2);
531 if(!fartherThan(GLight[i]->pos, _pos2, 300.f)) {
532 SendIOScriptEvent(entities[l], SM_CUSTOM, "douse");
533 }
534 }
535 }
536 }
537 }
538 else
539 {
540 // vient de s'allumer
541 if (GLight[i]->tl <= 0)
542 {
543 Vec3f _pos2;
544
545 for(size_t l = 0; l < entities.size(); l++) {
546 if(entities[l] && (entities[l]->ioflags & IO_MARKER)) {
547 GetItemWorldPosition(entities[l], &_pos2);
548 if(!fartherThan(GLight[i]->pos, _pos2, 300.f)) {
549 SendIOScriptEvent(entities[l], SM_CUSTOM, "fire");
550 }
551 }
552 }
553
554 GLight[i]->tl = GetFreeDynLight();
555 }
556
557 n = GLight[i]->tl;
558 if(n != -1) {
559 DynLight[n].pos = GLight[i]->pos;
560 DynLight[n].exist = 1;
561 DynLight[n].fallstart = GLight[i]->fallstart;
562 DynLight[n].fallend = GLight[i]->fallend;
563 DynLight[n].type = TYP_SPECIAL1;
564 DynLight[n].intensity = GLight[i]->intensity;
565 DynLight[n].ex_flaresize = GLight[i]->ex_flaresize;
566 DynLight[n].extras = GLight[i]->extras;
567 DynLight[n].duration = std::numeric_limits<long>::max();
568
569 DynLight[n].rgb.r = GLight[i]->rgb.r - GLight[i]->rgb.r * GLight[i]->ex_flicker.r * rnd() * ( 1.0f / 2 );
570 DynLight[n].rgb.g = GLight[i]->rgb.g - GLight[i]->rgb.g * GLight[i]->ex_flicker.g * rnd() * ( 1.0f / 2 );
571 DynLight[n].rgb.b = GLight[i]->rgb.b - GLight[i]->rgb.b * GLight[i]->ex_flicker.b * rnd() * ( 1.0f / 2 );
572
573 DynLight[n].rgb = componentwise_max(DynLight[n].rgb, Color3f::black);
574 DynLight[n].rgb255 = DynLight[n].rgb * 255.f;
575 DynLight[n].falldiff = DynLight[n].fallend - DynLight[n].fallstart;
576 DynLight[n].falldiffmul = 1.f / DynLight[n].falldiff;
577 DynLight[n].precalc = DynLight[n].intensity * GLOBAL_LIGHT_FACTOR;
578 }
579 }
580 }
581
582 }
583 }
584
585
PrecalcDynamicLighting(long x0,long z0,long x1,long z1)586 void PrecalcDynamicLighting(long x0, long z0, long x1, long z1) {
587
588 TreatBackgroundDynlights();
589 TOTPDL = 0;
590
591 float fx0 = ACTIVEBKG->Xdiv * (float)x0;
592 float fz0 = ACTIVEBKG->Zdiv * (float)z0;
593 float fx1 = ACTIVEBKG->Xdiv * (float)x1;
594 float fz1 = ACTIVEBKG->Zdiv * (float)z1;
595
596 for (size_t i = 0; i < MAX_DYNLIGHTS; i++)
597 {
598 EERIE_LIGHT * el = &DynLight[i];
599
600 if ((el->exist) && (el->rgb.r >= 0.f))
601 {
602
603 bool bDist = (distSqr(el->pos, ACTIVECAM->pos) < square(ACTIVECAM->cdepth));
604
605 if ((el->pos.x >= fx0) && (el->pos.x <= fx1)
606 && (el->pos.z >= fz0) && (el->pos.z <= fz1)
607 && bDist)
608 {
609 el->treat = 1;
610 el->rgb255 = el->rgb * 255.f;
611 el->falldiff = el->fallend - el->fallstart;
612 el->falldiffmul = 1.f / el->falldiff;
613 el->precalc = el->intensity * GLOBAL_LIGHT_FACTOR;
614 PDL[TOTPDL] = el;
615 TOTPDL++;
616
617 if ((size_t)TOTPDL >= MAX_DYNLIGHTS) TOTPDL--;
618 }
619 else if (el->treat) el->treat = 0;
620
621 if (el->duration)
622 {
623 float tim = ((float)float(arxtime) - (float)el->time_creation);
624 float duration = (float)el->duration;
625
626 if (tim >= duration)
627 {
628
629
630 float sub = framedelay * 0.001f;
631 el->rgb.r -= sub;
632
633 if (el->rgb.r < 0) el->rgb.r = 0.f;
634
635 el->rgb.g -= sub;
636
637 if (el->rgb.g < 0) el->rgb.g = 0.f;
638
639 el->rgb.b -= sub;
640
641 if (el->rgb.b < 0) el->rgb.b = 0.f;
642
643 if (el->rgb.r + el->rgb.g + el->rgb.b == 0)
644 {
645 el->exist = 0;
646 el->duration = 0;
647 }
648 }
649 }
650 }
651 }
652 }
653
EERIE_LIGHT_ChangeLighting()654 void EERIE_LIGHT_ChangeLighting()
655 {
656 long i, j;
657 EERIEPOLY * ep;
658 EERIE_BKG_INFO * eg;
659
660 for (j = 0; j < ACTIVEBKG->Zsize; j++)
661 for (i = 0; i < ACTIVEBKG->Xsize; i++)
662 {
663 eg = &ACTIVEBKG->Backg[i+j*ACTIVEBKG->Xsize];
664
665 for (long k = 0; k < eg->nbpoly; k++)
666 {
667 ep = &eg->polydata[k];
668 ep->tv[0].color = ep->v[0].color;
669 ep->tv[1].color = ep->v[1].color;
670 ep->tv[2].color = ep->v[2].color;
671
672 if (ep->type & POLY_QUAD) ep->tv[3].color = ep->v[3].color;
673 }
674 }
675 }
676
677 //*************************************************************************************
678 //*************************************************************************************
679
EERIEPrecalcLights(long minx,long minz,long maxx,long maxz)680 void EERIEPrecalcLights(long minx, long minz, long maxx, long maxz)
681 {
682 EERIE_BKG_INFO * eg;
683
684 if (minx < 0) minx = 0;
685 else if (minx >= ACTIVEBKG->Xsize) minx = ACTIVEBKG->Xsize - 1;
686
687 if (maxx < 0) maxx = 0;
688 else if (maxx >= ACTIVEBKG->Xsize) maxx = ACTIVEBKG->Xsize - 1;
689
690 if (minz < 0) minz = 0;
691 else if (minz >= ACTIVEBKG->Zsize) minz = ACTIVEBKG->Zsize - 1;
692
693 if (maxz < 0) maxz = 0;
694 else if (maxz >= ACTIVEBKG->Zsize) maxz = ACTIVEBKG->Zsize - 1;
695
696 for (size_t i = 0; i < MAX_LIGHTS; i++)
697 {
698 if (GLight[i] != NULL)
699 {
700 if ((GLight[i]->extras & EXTRAS_SEMIDYNAMIC))
701 {
702 GLight[i]->treat = 0;
703 }
704 else if (!GLight[i]->treat)
705 {
706 GLight[i]->treat = 1;
707 }
708
709 GLight[i]->falldiff = GLight[i]->fallend - GLight[i]->fallstart;
710 GLight[i]->falldiffmul = 1.f / GLight[i]->falldiff;
711 GLight[i]->rgb255 = GLight[i]->rgb * 255.f;
712 GLight[i]->precalc = GLight[i]->intensity * GLOBAL_LIGHT_FACTOR;
713 }
714 }
715
716 for (long j = minz; j <= maxz; j++)
717 {
718 for (long i = minx; i <= maxx; i++)
719 {
720 eg = &ACTIVEBKG->Backg[i+j*ACTIVEBKG->Xsize];
721
722 for (long k = 0; k < eg->nbpoly; k++)
723 {
724 EERIEPOLY * ep = &eg->polydata[k];
725
726 if(ep) {
727 ep->type &= ~POLY_IGNORE;
728 EERIE_LIGHT_Apply(ep);
729 }
730 }
731 }
732 }
733 }
734
RecalcLightZone(float x,float z,long siz)735 void RecalcLightZone(float x, float z, long siz) {
736
737 long i, j, x0, x1, z0, z1;
738
739 i = x * ACTIVEBKG->Xmul;
740 j = z * ACTIVEBKG->Zmul;
741
742 x0 = i - siz;
743 x1 = i + siz;
744 z0 = j - siz;
745 z1 = j + siz;
746
747 if (x0 < 2) x0 = 2;
748 else if (x0 >= ACTIVEBKG->Xsize - 2) x0 = ACTIVEBKG->Xsize - 3;
749
750 if (x1 < 2) x1 = 0;
751 else if (x1 >= ACTIVEBKG->Xsize - 2) x1 = ACTIVEBKG->Xsize - 3;
752
753 if (z0 < 2) z0 = 0;
754 else if (z0 >= ACTIVEBKG->Zsize - 2) z0 = ACTIVEBKG->Zsize - 3;
755
756 if (z1 < 2) z1 = 0;
757 else if (z1 >= ACTIVEBKG->Zsize - 2) z1 = ACTIVEBKG->Zsize - 3;
758
759 LightMode oldml = ModeLight;
760 ModeLight &= ~MODE_RAYLAUNCH;
761 EERIEPrecalcLights(x0, z0, x1, z1);
762 ModeLight = oldml;
763 }
764
EERIERemovePrecalcLights()765 void EERIERemovePrecalcLights() {
766
767 EERIEPOLY * ep;
768 EERIE_BKG_INFO * eg;
769
770 for(size_t i = 0; i < MAX_LIGHTS; i++) {
771 if (GLight[i] != NULL) GLight[i]->treat = 1;
772 }
773
774 for(int j = 0; j < ACTIVEBKG->Zsize; j++) {
775 for(int i = 0; i < ACTIVEBKG->Xsize; i++) {
776
777 eg = &ACTIVEBKG->Backg[i+j*ACTIVEBKG->Xsize];
778
779 for (long k = 0; k < eg->nbpoly; k++) {
780 ep = &eg->polydata[k];
781 ep->v[3].color = ep->v[2].color = ep->v[1].color = ep->v[0].color = Color::white.toBGR();
782 }
783 }
784 }
785 }
786