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