]> icculus.org git repositories - btb/d2x.git/blob - main/lighting.c
remove rcs tags
[btb/d2x.git] / main / lighting.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Lighting functions.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>     // for memset()
26
27 #include "fix.h"
28 #include "vecmat.h"
29 #include "gr.h"
30 #include "inferno.h"
31 #include "segment.h"
32 #include "error.h"
33 #include "mono.h"
34 #include "render.h"
35 #include "game.h"
36 #include "vclip.h"
37 #include "lighting.h"
38 #include "3d.h"
39 #include "laser.h"
40 #include "timer.h"
41 #include "player.h"
42 #include "weapon.h"
43 #include "powerup.h"
44 #include "fvi.h"
45 #include "robot.h"
46 #include "multi.h"
47
48 int     Do_dynamic_light=1;
49 //int   Use_fvi_lighting = 0;
50
51 fix     Dynamic_light[MAX_VERTICES];
52
53 #define LIGHTING_CACHE_SIZE     4096    //      Must be power of 2!
54 #define LIGHTING_FRAME_DELTA    256     //      Recompute cache value every 8 frames.
55 #define LIGHTING_CACHE_SHIFT    8
56
57 int     Lighting_frame_delta = 1;
58
59 int     Lighting_cache[LIGHTING_CACHE_SIZE];
60
61 int Cache_hits=0, Cache_lookups=1;
62
63 //      Return true if we think vertex vertnum is visible from segment segnum.
64 //      If some amount of time has gone by, then recompute, else use cached value.
65 int lighting_cache_visible(int vertnum, int segnum, int objnum, vms_vector *obj_pos, int obj_seg, vms_vector *vertpos)
66 {
67         int     cache_val, cache_frame, cache_vis;
68
69         cache_val = Lighting_cache[((segnum << LIGHTING_CACHE_SHIFT) ^ vertnum) & (LIGHTING_CACHE_SIZE-1)];
70
71         cache_frame = cache_val >> 1;
72         cache_vis = cache_val & 1;
73
74 //mprintf((0, "%i %i %5i %i ", vertnum, segnum, cache_frame, cache_vis));
75
76 Cache_lookups++;
77         if ((cache_frame == 0) || (cache_frame + Lighting_frame_delta <= FrameCount)) {
78                 int                     apply_light=0;
79                 fvi_query       fq;
80                 fvi_info                hit_data;
81                 int                     segnum, hit_type;
82
83                 segnum = -1;
84
85                 #ifndef NDEBUG
86                 segnum = find_point_seg(obj_pos, obj_seg);
87                 if (segnum == -1) {
88                         Int3();         //      Obj_pos is not in obj_seg!
89                         return 0;               //      Done processing this object.
90                 }
91                 #endif
92
93                 fq.p0                                           = obj_pos;
94                 fq.startseg                             = obj_seg;
95                 fq.p1                                           = vertpos;
96                 fq.rad                                  = 0;
97                 fq.thisobjnum                   = objnum;
98                 fq.ignore_obj_list      = NULL;
99                 fq.flags                                        = FQ_TRANSWALL;
100
101                 hit_type = find_vector_intersection(&fq, &hit_data);
102
103                 // Hit_pos = Hit_data.hit_pnt;
104                 // Hit_seg = Hit_data.hit_seg;
105
106                 if (hit_type == HIT_OBJECT)
107                         Int3(); //      Hey, we're not supposed to be checking objects!
108
109                 if (hit_type == HIT_NONE)
110                         apply_light = 1;
111                 else if (hit_type == HIT_WALL) {
112                         fix     dist_dist;
113                         dist_dist = vm_vec_dist_quick(&hit_data.hit_pnt, obj_pos);
114                         if (dist_dist < F1_0/4) {
115                                 apply_light = 1;
116                                 // -- Int3();   //      Curious, did fvi detect intersection with wall containing vertex?
117                         }
118                 }
119                 Lighting_cache[((segnum << LIGHTING_CACHE_SHIFT) ^ vertnum) & (LIGHTING_CACHE_SIZE-1)] = apply_light + (FrameCount << 1);
120 //mprintf((0, "%i\n", apply_light));
121                 return apply_light;
122         } else {
123 //mprintf((0, "\n"));
124 Cache_hits++;
125                 return cache_vis;
126         }       
127 }
128
129 #define HEADLIGHT_CONE_DOT      (F1_0*9/10)
130 #define HEADLIGHT_SCALE         (F1_0*10)
131
132 // ----------------------------------------------------------------------------------------------
133 void apply_light(fix obj_intensity, int obj_seg, vms_vector *obj_pos, int n_render_vertices, short *render_vertices, int objnum)
134 {
135         int     vv;
136
137         if (obj_intensity) {
138                 fix     obji_64 = obj_intensity*64;
139
140                 // for pretty dim sources, only process vertices in object's own segment.
141                 //      12/04/95, MK, markers only cast light in own segment.
142                 if ((abs(obji_64) <= F1_0*8) || (Objects[objnum].type == OBJ_MARKER)) {
143                         short *vp = Segments[obj_seg].verts;
144
145                         for (vv=0; vv<MAX_VERTICES_PER_SEGMENT; vv++) {
146                                 int                     vertnum;
147                                 vms_vector      *vertpos;
148                                 fix                     dist;
149
150                                 vertnum = vp[vv];
151                                 if ((vertnum ^ FrameCount) & 1) {
152                                         vertpos = &Vertices[vertnum];
153                                         dist = vm_vec_dist_quick(obj_pos, vertpos);
154                                         dist = fixmul(dist/4, dist/4);
155                                         if (dist < abs(obji_64)) {
156                                                 if (dist < MIN_LIGHT_DIST)
157                                                         dist = MIN_LIGHT_DIST;
158         
159                                                 Dynamic_light[vertnum] += fixdiv(obj_intensity, dist);
160                                         }
161                                 }
162                         }
163                 } else {
164                         int     headlight_shift = 0;
165                         fix     max_headlight_dist = F1_0*200;
166
167                         if (Objects[objnum].type == OBJ_PLAYER)
168                                 if (Players[Objects[objnum].id].flags & PLAYER_FLAGS_HEADLIGHT_ON) {
169                                         headlight_shift = 3;
170                                         if (Objects[objnum].id != Player_num) {
171                                                 vms_vector      tvec;
172                                                 fvi_query       fq;
173                                                 fvi_info                hit_data;
174                                                 int                     fate;
175
176                                                 vm_vec_scale_add(&tvec, &Objects[objnum].pos, &Objects[objnum].orient.fvec, F1_0*200);
177
178                                                 fq.startseg                             = Objects[objnum].segnum;
179                                                 fq.p0                                           = &Objects[objnum].pos;
180                                                 fq.p1                                           = &tvec;
181                                                 fq.rad                                  = 0;
182                                                 fq.thisobjnum                   = objnum;
183                                                 fq.ignore_obj_list      = NULL;
184                                                 fq.flags                                        = FQ_TRANSWALL;
185
186                                                 fate = find_vector_intersection(&fq, &hit_data);
187                                                 if (fate != HIT_NONE)
188                                                         max_headlight_dist = vm_vec_mag_quick(vm_vec_sub(&tvec, &hit_data.hit_pnt, &Objects[objnum].pos)) + F1_0*4;
189                                         }
190                                 }
191                         // -- for (vv=FrameCount&1; vv<n_render_vertices; vv+=2) {
192                         for (vv=0; vv<n_render_vertices; vv++) {
193                                 int                     vertnum;
194                                 vms_vector      *vertpos;
195                                 fix                     dist;
196                                 int                     apply_light;
197
198                                 vertnum = render_vertices[vv];
199                                 if ((vertnum ^ FrameCount) & 1) {
200                                         vertpos = &Vertices[vertnum];
201                                         dist = vm_vec_dist_quick(obj_pos, vertpos);
202                                         apply_light = 0;
203
204                                         if ((dist >> headlight_shift) < abs(obji_64)) {
205
206                                                 if (dist < MIN_LIGHT_DIST)
207                                                         dist = MIN_LIGHT_DIST;
208
209                                                 //if (Use_fvi_lighting) {
210                                                 //      if (lighting_cache_visible(vertnum, obj_seg, objnum, obj_pos, obj_seg, vertpos)) {
211                                                 //              apply_light = 1;
212                                                 //      }
213                                                 //} else
214                                                         apply_light = 1;
215
216                                                 if (apply_light) {
217                                                         if (headlight_shift) {
218                                                                 fix                     dot;
219                                                                 vms_vector      vec_to_point;
220
221                                                                 vm_vec_sub(&vec_to_point, vertpos, obj_pos);
222                                                                 vm_vec_normalize_quick(&vec_to_point);          //      MK, Optimization note: You compute distance about 15 lines up, this is partially redundant
223                                                                 dot = vm_vec_dot(&vec_to_point, &Objects[objnum].orient.fvec);
224                                                                 if (dot < F1_0/2)
225                                                                         Dynamic_light[vertnum] += fixdiv(obj_intensity, fixmul(HEADLIGHT_SCALE, dist)); //      Do the normal thing, but darken around headlight.
226                                                                 else {
227                                                                         if (Game_mode & GM_MULTI) {
228                                                                                 if (dist < max_headlight_dist)
229                                                                                         Dynamic_light[vertnum] += fixmul(fixmul(dot, dot), obj_intensity)/8;
230                                                                         } else
231                                                                                 Dynamic_light[vertnum] += fixmul(fixmul(dot, dot), obj_intensity)/8;
232                                                                 }
233                                                         } else
234                                                                 Dynamic_light[vertnum] += fixdiv(obj_intensity, dist);
235                                                 }
236                                         }
237                                 }
238                         }
239                 }
240         }
241 }
242
243 #define FLASH_LEN_FIXED_SECONDS (F1_0/3)
244 #define FLASH_SCALE                                     (3*F1_0/FLASH_LEN_FIXED_SECONDS)
245
246 // ----------------------------------------------------------------------------------------------
247 void cast_muzzle_flash_light(int n_render_vertices, short *render_vertices)
248 {
249         fix current_time;
250         int     i;
251         short   time_since_flash;
252
253         current_time = timer_get_fixed_seconds();
254
255         for (i=0; i<MUZZLE_QUEUE_MAX; i++) {
256                 if (Muzzle_data[i].create_time) {
257                         time_since_flash = current_time - Muzzle_data[i].create_time;
258                         if (time_since_flash < FLASH_LEN_FIXED_SECONDS)
259                                 apply_light((FLASH_LEN_FIXED_SECONDS - time_since_flash) * FLASH_SCALE, Muzzle_data[i].segnum, &Muzzle_data[i].pos, n_render_vertices, render_vertices, -1);
260                         else
261                                 Muzzle_data[i].create_time = 0;         // turn off this muzzle flash
262                 }
263         }
264 }
265
266 //      Translation table to make flares flicker at different rates
267 fix     Obj_light_xlate[16] =
268         {0x1234, 0x3321, 0x2468, 0x1735,
269          0x0123, 0x19af, 0x3f03, 0x232a,
270          0x2123, 0x39af, 0x0f03, 0x132a,
271          0x3123, 0x29af, 0x1f03, 0x032a};
272
273 //      Flag array of objects lit last frame.  Guaranteed to process this frame if lit last frame.
274 sbyte   Lighting_objects[MAX_OBJECTS];
275
276 #define MAX_HEADLIGHTS  8
277 object  *Headlights[MAX_HEADLIGHTS];
278 int             Num_headlights;
279
280 // ---------------------------------------------------------
281 fix compute_light_intensity(int objnum)
282 {
283         object          *obj = &Objects[objnum];
284         int                     objtype = obj->type;
285    fix hoardlight,s;
286         
287         switch (objtype) {
288                 case OBJ_PLAYER:
289                          if (Players[obj->id].flags & PLAYER_FLAGS_HEADLIGHT_ON) {
290                                 if (Num_headlights < MAX_HEADLIGHTS)
291                                         Headlights[Num_headlights++] = obj;
292                                 return HEADLIGHT_SCALE;
293                          } else if ((Game_mode & GM_HOARD) && Players[obj->id].secondary_ammo[PROXIMITY_INDEX]) {
294                         
295                    // If hoard game and player, add extra light based on how many orbs you have
296                         // Pulse as well.
297
298                            hoardlight=i2f(Players[obj->id].secondary_ammo[PROXIMITY_INDEX])/2; //i2f(12));
299                                 hoardlight++;
300                       fix_sincos ((GameTime/2) & 0xFFFF,&s,NULL); // probably a bad way to do it
301                            s+=F1_0; 
302                                 s>>=1;
303                            hoardlight=fixmul (s,hoardlight);
304                  //     mprintf ((0,"Hoardlight is %f!\n",f2fl(hoardlight)));
305                       return (hoardlight);
306                           }
307                         else
308                                 return max(vm_vec_mag_quick(&obj->mtype.phys_info.thrust)/4, F1_0*2) + F1_0/2;
309                         break;
310                 case OBJ_FIREBALL:
311                         if (obj->id != 0xff) {
312                                 if (obj->lifeleft < F1_0*4)
313                                         return fixmul(fixdiv(obj->lifeleft, Vclip[obj->id].play_time), Vclip[obj->id].light_value);
314                                 else
315                                         return Vclip[obj->id].light_value;
316                         } else
317                                  return 0;
318                         break;
319                 case OBJ_ROBOT:
320                         return F1_0*Robot_info[obj->id].lightcast;
321                         break;
322                 case OBJ_WEAPON: {
323                         fix tval = Weapon_info[obj->id].light;
324                         if (Game_mode & GM_MULTI)
325                                 if (obj->id == OMEGA_ID)
326                                         if (d_rand() > 8192)
327                                                 return 0;               //      3/4 of time, omega blobs will cast 0 light!
328
329                         if (obj->id == FLARE_ID )
330                                 return 2* (min(tval, obj->lifeleft) + ((GameTime ^ Obj_light_xlate[objnum&0x0f]) & 0x3fff));
331                         else
332                                 return tval;
333                 }
334
335                 case OBJ_MARKER: {
336                         fix     lightval = obj->lifeleft;
337
338                         lightval &= 0xffff;
339
340                         lightval = 8 * abs(F1_0/2 - lightval);
341
342                         if (obj->lifeleft < F1_0*1000)
343                                 obj->lifeleft += F1_0;  //      Make sure this object doesn't go out.
344
345                         return lightval;
346                 }
347
348                 case OBJ_POWERUP:
349                         return Powerup_info[obj->id].light;
350                         break;
351                 case OBJ_DEBRIS:
352                         return F1_0/4;
353                         break;
354                 case OBJ_LIGHT:
355                         return obj->ctype.light_info.intensity;
356                         break;
357                 default:
358                         return 0;
359                         break;
360         }
361 }
362
363 // ----------------------------------------------------------------------------------------------
364 void set_dynamic_light(void)
365 {
366         int     vv;
367         int     objnum;
368         int     n_render_vertices;
369         short   render_vertices[MAX_VERTICES];
370         sbyte   render_vertex_flags[MAX_VERTICES];
371         int     render_seg,segnum, v;
372         sbyte   new_lighting_objects[MAX_OBJECTS];
373
374         Num_headlights = 0;
375
376         if (!Do_dynamic_light)
377                 return;
378
379 //if (Use_fvi_lighting)
380 //      mprintf((0, "hits = %8i, misses = %8i, lookups = %8i, hit ratio = %7.4f\n", Cache_hits, Cache_lookups - Cache_hits, Cache_lookups, (float) Cache_hits / Cache_lookups));
381
382         memset(render_vertex_flags, 0, Highest_vertex_index+1);
383
384         //      Create list of vertices that need to be looked at for setting of ambient light.
385         n_render_vertices = 0;
386         for (render_seg=0; render_seg<N_render_segs; render_seg++) {
387                 segnum = Render_list[render_seg];
388                 if (segnum != -1) {
389                         short   *vp = Segments[segnum].verts;
390                         for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++) {
391                                 int     vnum = vp[v];
392                                 if (vnum<0 || vnum>Highest_vertex_index) {
393                                         Int3();         //invalid vertex number
394                                         continue;       //ignore it, and go on to next one
395                                 }
396                                 if (!render_vertex_flags[vnum]) {
397                                         render_vertex_flags[vnum] = 1;
398                                         render_vertices[n_render_vertices++] = vnum;
399                                 }
400                                 //--old way-- for (s=0; s<n_render_vertices; s++)
401                                 //--old way--   if (render_vertices[s] == vnum)
402                                 //--old way--           break;
403                                 //--old way-- if (s == n_render_vertices)
404                                 //--old way--   render_vertices[n_render_vertices++] = vnum;
405                         }
406                 }
407         }
408
409         // -- for (vertnum=FrameCount&1; vertnum<n_render_vertices; vertnum+=2) {
410         for (vv=0; vv<n_render_vertices; vv++) {
411                 int     vertnum;
412
413                 vertnum = render_vertices[vv];
414                 Assert(vertnum >= 0 && vertnum <= Highest_vertex_index);
415                 if ((vertnum ^ FrameCount) & 1)
416                         Dynamic_light[vertnum] = 0;
417         }
418
419         cast_muzzle_flash_light(n_render_vertices, render_vertices);
420
421         for (objnum=0; objnum<=Highest_object_index; objnum++)
422                 new_lighting_objects[objnum] = 0;
423
424         //      July 5, 1995: New faster dynamic lighting code.  About 5% faster on the PC (un-optimized).
425         //      Only objects which are in rendered segments cast dynamic light.  We might wad6 to extend this
426         //      one or two segments if we notice light changing as objects go offscreen.  I couldn't see any
427         //      serious visual degradation.  In fact, I could see no humorous degradation, either. --MK
428         for (render_seg=0; render_seg<N_render_segs; render_seg++) {
429                 int     segnum = Render_list[render_seg];
430
431                 objnum = Segments[segnum].objects;
432
433                 while (objnum != -1) {
434                         object          *obj = &Objects[objnum];
435                         vms_vector      *objpos = &obj->pos;
436                         fix                     obj_intensity;
437
438                         obj_intensity = compute_light_intensity(objnum);
439
440                         if (obj_intensity) {
441                                 apply_light(obj_intensity, obj->segnum, objpos, n_render_vertices, render_vertices, OBJECT_NUMBER(obj));
442                                 new_lighting_objects[objnum] = 1;
443                         }
444
445                         objnum = obj->next;
446                 }
447         }
448
449         //      Now, process all lights from last frame which haven't been processed this frame.
450         for (objnum=0; objnum<=Highest_object_index; objnum++) {
451                 //      In multiplayer games, process even unprocessed objects every 4th frame, else don't know about player sneaking up.
452                 if ((Lighting_objects[objnum]) || ((Game_mode & GM_MULTI) && (((objnum ^ FrameCount) & 3) == 0))) {
453                         if (!new_lighting_objects[objnum]) {
454                                 //      Lighted last frame, but not this frame.  Get intensity...
455                                 object          *obj = &Objects[objnum];
456                                 vms_vector      *objpos = &obj->pos;
457                                 fix                     obj_intensity;
458
459                                 obj_intensity = compute_light_intensity(objnum);
460
461                                 if (obj_intensity) {
462                                         apply_light(obj_intensity, obj->segnum, objpos, n_render_vertices, render_vertices, objnum);
463                                         Lighting_objects[objnum] = 1;
464                                 } else
465                                         Lighting_objects[objnum] = 0;
466                         }
467                 } else {
468                         //      Not lighted last frame, so we don't need to light it.  (Already lit if casting light this frame.)
469                         //      But copy value from new_lighting_objects to update Lighting_objects array.
470                         Lighting_objects[objnum] = new_lighting_objects[objnum];
471                 }
472         }
473 }
474
475 // ---------------------------------------------------------
476
477 void toggle_headlight_active()
478 {
479         if (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT) {
480                 Players[Player_num].flags ^= PLAYER_FLAGS_HEADLIGHT_ON;                 
481 #ifdef NETWORK
482                 if (Game_mode & GM_MULTI)
483                         multi_send_flags(Player_num);           
484 #endif
485         }
486 }
487
488 #define HEADLIGHT_BOOST_SCALE 8         //how much to scale light when have headlight boost
489
490 fix     Beam_brightness = (F1_0/2);     //global saying how bright the light beam is
491
492 #define MAX_DIST_LOG    6                                                       //log(MAX_DIST-expressed-as-integer)
493 #define MAX_DIST                (f1_0<<MAX_DIST_LOG)    //no light beyond this dist
494
495 fix compute_headlight_light_on_object(object *objp)
496 {
497         int     i;
498         fix     light;
499
500         //      Let's just illuminate players and robots for speed reasons, ok?
501         if ((objp->type != OBJ_ROBOT) && (objp->type    != OBJ_PLAYER))
502                 return 0;
503
504         light = 0;
505
506         for (i=0; i<Num_headlights; i++) {
507                 fix                     dot, dist;
508                 vms_vector      vec_to_obj;
509                 object          *light_objp;
510
511                 light_objp = Headlights[i];
512
513                 vm_vec_sub(&vec_to_obj, &objp->pos, &light_objp->pos);
514                 dist = vm_vec_normalize_quick(&vec_to_obj);
515                 if (dist > 0) {
516                         dot = vm_vec_dot(&light_objp->orient.fvec, &vec_to_obj);
517
518                         if (dot < F1_0/2)
519                                 light += fixdiv(HEADLIGHT_SCALE, fixmul(HEADLIGHT_SCALE, dist));        //      Do the normal thing, but darken around headlight.
520                         else
521                                 light += fixmul(fixmul(dot, dot), HEADLIGHT_SCALE)/8;
522                 }
523         }
524
525         return light;
526 }
527
528
529 // -- Unused -- //Compute the lighting from the headlight for a given vertex on a face.
530 // -- Unused -- //Takes:
531 // -- Unused -- //  point - the 3d coords of the point
532 // -- Unused -- //  face_light - a scale factor derived from the surface normal of the face
533 // -- Unused -- //If no surface normal effect is wanted, pass F1_0 for face_light
534 // -- Unused -- fix compute_headlight_light(vms_vector *point,fix face_light)
535 // -- Unused -- {
536 // -- Unused --         fix light;
537 // -- Unused --         int use_beam = 0;               //flag for beam effect
538 // -- Unused --
539 // -- Unused --         light = Beam_brightness;
540 // -- Unused --
541 // -- Unused --         if ((Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT) && (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT_ON) && Viewer==&Objects[Players[Player_num].objnum] && Players[Player_num].energy > 0) {
542 // -- Unused --                 light *= HEADLIGHT_BOOST_SCALE;
543 // -- Unused --                 use_beam = 1;   //give us beam effect
544 // -- Unused --         }
545 // -- Unused --
546 // -- Unused --         if (light) {                            //if no beam, don't bother with the rest of this
547 // -- Unused --                 fix point_dist;
548 // -- Unused --
549 // -- Unused --                 point_dist = vm_vec_mag_quick(point);
550 // -- Unused --
551 // -- Unused --                 if (point_dist >= MAX_DIST)
552 // -- Unused --
553 // -- Unused --                         light = 0;
554 // -- Unused --
555 // -- Unused --                 else {
556 // -- Unused --                         fix dist_scale,face_scale;
557 // -- Unused --
558 // -- Unused --                         dist_scale = (MAX_DIST - point_dist) >> MAX_DIST_LOG;
559 // -- Unused --                         light = fixmul(light,dist_scale);
560 // -- Unused --
561 // -- Unused --                         if (face_light < 0)
562 // -- Unused --                                 face_light = 0;
563 // -- Unused --
564 // -- Unused --                         face_scale = f1_0/4 + face_light/2;
565 // -- Unused --                         light = fixmul(light,face_scale);
566 // -- Unused --
567 // -- Unused --                         if (use_beam) {
568 // -- Unused --                                 fix beam_scale;
569 // -- Unused --
570 // -- Unused --                                 if (face_light > f1_0*3/4 && point->z > i2f(12)) {
571 // -- Unused --                                         beam_scale = fixdiv(point->z,point_dist);
572 // -- Unused --                                         beam_scale = fixmul(beam_scale,beam_scale);     //square it
573 // -- Unused --                                         light = fixmul(light,beam_scale);
574 // -- Unused --                                 }
575 // -- Unused --                         }
576 // -- Unused --                 }
577 // -- Unused --         }
578 // -- Unused --
579 // -- Unused --         return light;
580 // -- Unused -- }
581
582 //compute the average dynamic light in a segment.  Takes the segment number
583 fix compute_seg_dynamic_light(int segnum)
584 {
585         fix sum;
586         segment *seg;
587         short *verts;
588
589         seg = &Segments[segnum];
590
591         verts = seg->verts;
592         sum = 0;
593
594         sum += Dynamic_light[*verts++];
595         sum += Dynamic_light[*verts++];
596         sum += Dynamic_light[*verts++];
597         sum += Dynamic_light[*verts++];
598         sum += Dynamic_light[*verts++];
599         sum += Dynamic_light[*verts++];
600         sum += Dynamic_light[*verts++];
601         sum += Dynamic_light[*verts];
602
603         return sum >> 3;
604
605 }
606
607 fix object_light[MAX_OBJECTS];
608 int object_sig[MAX_OBJECTS];
609 object *old_viewer;
610 int reset_lighting_hack;
611
612 #define LIGHT_RATE i2f(4)               //how fast the light ramps up
613
614 void start_lighting_frame(object *viewer)
615 {
616         reset_lighting_hack = (viewer != old_viewer);
617
618         old_viewer = viewer;
619 }
620
621 //compute the lighting for an object.  Takes a pointer to the object,
622 //and possibly a rotated 3d point.  If the point isn't specified, the
623 //object's center point is rotated.
624 fix compute_object_light(object *obj,vms_vector *rotated_pnt)
625 {
626         fix light;
627         g3s_point objpnt;
628         int objnum = OBJECT_NUMBER(obj);
629
630         if (!rotated_pnt) {
631                 g3_rotate_point(&objpnt,&obj->pos);
632                 rotated_pnt = &objpnt.p3_vec;
633         }
634
635         //First, get static light for this segment
636
637         light = Segment2s[obj->segnum].static_light;
638
639         //return light;
640
641
642         //Now, maybe return different value to smooth transitions
643
644         if (!reset_lighting_hack && object_sig[objnum] == obj->signature) {
645                 fix delta_light,frame_delta;
646
647                 delta_light = light - object_light[objnum];
648
649                 frame_delta = fixmul(LIGHT_RATE,FrameTime);
650
651                 if (abs(delta_light) <= frame_delta)
652
653                         object_light[objnum] = light;           //we've hit the goal
654
655                 else
656
657                         if (delta_light < 0)
658                                 light = object_light[objnum] -= frame_delta;
659                         else
660                                 light = object_light[objnum] += frame_delta;
661
662         }
663         else {          //new object, initialize
664
665                 object_sig[objnum] = obj->signature;
666                 object_light[objnum] = light;
667         }
668
669
670
671         //Next, add in headlight on this object
672
673         // -- Matt code: light += compute_headlight_light(rotated_pnt,f1_0);
674         light += compute_headlight_light_on_object(obj);
675  
676         //Finally, add in dynamic light for this segment
677
678         light += compute_seg_dynamic_light(obj->segnum);
679
680
681         return light;
682 }
683
684