/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * $Source: /cvsroot/dxx-rebirth/d1x-rebirth/main/lighting.c,v $ * $Revision: 1.1.1.1 $ * $Author: zicodxx $ * $Date: 2006/03/17 19:43:15 $ * * Lighting functions. * * $Log: lighting.c,v $ * Revision 1.1.1.1 2006/03/17 19:43:15 zicodxx * initial import * * Revision 1.1.1.1 1999/06/14 22:08:28 donut * Import of d1x 1.37 source. * * Revision 2.1 1995/07/24 13:21:56 john * Added new lighting calculation code to speed things up. * * Revision 2.0 1995/02/27 11:27:33 john * New version 2.0, which has no anonymous unions, builds with * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. * * Revision 1.43 1995/02/22 13:57:10 allender * remove anonymous union from object structure * * Revision 1.42 1995/02/13 20:35:07 john * Lintized * * Revision 1.41 1995/02/04 21:43:40 matt * Changed an assert() to an int3() and deal with the bad case * * Revision 1.40 1995/01/15 20:48:27 mike * support light field for powerups. * * Revision 1.39 1994/12/15 13:04:19 mike * Replace Players[Player_num].time_total references with GameTime. * * Revision 1.38 1994/11/28 21:50:41 mike * optimizations. * * Revision 1.37 1994/11/28 01:32:33 mike * lighting optimization. * * Revision 1.36 1994/11/15 12:01:00 john * Changed a bunch of code that uses timer_get_milliseconds to * timer_get_fixed_Seconds. * * Revision 1.35 1994/10/31 21:56:07 matt * Fixed bug & added error checking * * Revision 1.34 1994/10/21 11:24:57 mike * Trap divide overflows in lighting. * * Revision 1.33 1994/10/08 14:49:11 matt * If viewer changed, don't do smooth lighting hack * * Revision 1.32 1994/09/25 23:41:07 matt * Changed the object load & save code to read/write the structure fields one * at a time (rather than the whole structure at once). This mean that the * object structure can be changed without breaking the load/save functions. * As a result of this change, the local_object data can be and has been * incorporated into the object array. Also, timeleft is now a property * of all objects, and the object structure has been otherwise cleaned up. * * Revision 1.31 1994/09/25 15:45:15 matt * Added OBJ_LIGHT, a type of object that casts light * Added generalized lifeleft, and moved it to local_object * * Revision 1.30 1994/09/11 15:48:27 mike * Use vm_vec_mag_quick in place of vm_vec_mag in point_dist computation. * * Revision 1.29 1994/09/08 21:44:49 matt * Made lighting ramp 4x as fast; made only static (ambient) light ramp * up, but not headlight & dynamic light * * Revision 1.28 1994/09/02 14:00:07 matt * Simplified explode_object() & mutliple-stage explosions * * Revision 1.27 1994/08/29 19:06:44 mike * Make lighting proportional to square of distance, not linear. * * Revision 1.26 1994/08/25 18:08:38 matt * Made muzzle flash cast 3x as much light * * Revision 1.25 1994/08/23 16:38:31 mike * Key weapon light off bitmaps.tbl. * * Revision 1.24 1994/08/13 12:20:44 john * Made the networking uise the Players array. * * Revision 1.23 1994/08/12 22:42:18 john * Took away Player_stats; added Players array. * * Revision 1.22 1994/07/06 10:19:22 matt * Changed include * * Revision 1.21 1994/06/28 13:20:22 mike * Oops, fixed a dumb typo. * * Revision 1.20 1994/06/28 12:53:25 mike * Change lighting function for flares, make brighter and asynchronously flicker. * * Revision 1.19 1994/06/27 18:31:15 mike * Add flares. * * Revision 1.18 1994/06/20 13:41:17 matt * Added time-based gradual lighting hack for objects * Took out strobing robots * * Revision 1.17 1994/06/19 16:25:54 mike * Optimize lighting. * * Revision 1.16 1994/06/17 18:08:08 mike * Make robots cast more and variable light. * * Revision 1.15 1994/06/13 15:15:55 mike * Fix phantom light, every 64K milliseconds, muzzle flash would flash again. * */ #ifdef RCS #pragma off (unreferenced) static char rcsid[] = "$Id: lighting.c,v 1.1.1.1 2006/03/17 19:43:15 zicodxx Exp $"; #pragma on (unreferenced) #endif #include #include // for memset() #include "inferno.h" #include "segment.h" #include "error.h" #include "mono.h" #include "render.h" #include "game.h" #include "vclip.h" #include "lighting.h" #include "3d.h" #include "laser.h" #include "timer.h" #include "player.h" #include "weapon.h" #include "powerup.h" //global saying how bright the light beam is fix Beam_brightness = (F1_0/2); // -- optimized out, mk, 11/28/94 -- fix Face_light_scale = (F1_0/2); int use_beam; //flag for beam effect int Do_dynamic_light=1; fix Dynamic_light[MAX_VERTICES]; // ---------------------------------------------------------------------------------------------- void apply_light(fix obj_intensity, int obj_seg, vms_vector *obj_pos, int n_render_vertices, short *render_vertices) { int vv; if (obj_intensity) { fix obji_64 = obj_intensity*64; // for pretty dim sources, only process vertices in object's own segment. if (obji_64 <= F1_0*8) { short *vp = Segments[obj_seg].verts; for (vv=0; vvHighest_vertex_index) { Int3(); //invalid vertex number continue; //ignore it, and go on to next one } if (!render_vertex_flags[vnum]) { render_vertex_flags[vnum] = 1; render_vertices[n_render_vertices++] = vnum; } //--old way-- for (s=0; s=0 && render_vertices[vertnum]<=Highest_vertex_index); Dynamic_light[render_vertices[vertnum]] = 0; } cast_muzzle_flash_light(n_render_vertices, render_vertices); // Note, starting at 1 to skip player, whose light is handled by a different system, of course. // for (objnum=1; objnum<=Highest_object_index; objnum++) { for (render_seg=0; render_segpos; int objtype = obj->type; fix obj_intensity; switch (objtype) { case OBJ_FIREBALL: if (obj->id != 0xff) { if (obj->lifeleft < F1_0*4) obj_intensity = fixmul(fixdiv(obj->lifeleft, Vclip[obj->id].play_time), Vclip[obj->id].light_value); else obj_intensity = Vclip[obj->id].light_value; } else obj_intensity = 0; break; case OBJ_ROBOT: obj_intensity = F1_0/2; // + (FrameCount & 0x1f)*F1_0/16; break; case OBJ_WEAPON: obj_intensity = Weapon_info[obj->id].light; if (obj->id == FLARE_ID ) obj_intensity = 2* (min(obj_intensity, obj->lifeleft) + ((GameTime ^ Obj_light_xlate[objnum&0x0f]) & 0x3fff)); break; case OBJ_POWERUP: obj_intensity = Powerup_info[obj->id].light; break; case OBJ_DEBRIS: obj_intensity = F1_0/4; break; case OBJ_LIGHT: obj_intensity = obj->ctype.light_info.intensity; break; default: obj_intensity = 0; break; } if (obj_intensity) apply_light(obj_intensity, obj->segnum, objpos, n_render_vertices, render_vertices); objnum = obj->next; } } } // --------------------------------------------------------- //Compute the lighting from the headlight for a given vertex on a face. //Takes: // point - the 3d coords of the point // face_light - a scale factor derived from the surface normal of the face //If no surface normal effect is wanted, pass F1_0 for face_light fix compute_headlight_light(vms_vector *point,fix face_light) { fix light; light = Beam_brightness; if (light) { //if no beam, don't bother with the rest of this fix point_dist; if (face_light < 0) face_light = 0; point_dist = vm_vec_mag_quick(point); //note: beam scale not used if !use_beam if (point_dist >= MAX_DIST) light = 0; else { fix dist_scale,temp_lightval; dist_scale = (MAX_DIST - point_dist) >> MAX_DIST_LOG; temp_lightval = f1_0/4 + face_light/2; light = Beam_brightness; if (use_beam) { fix beam_scale; beam_scale = fixdiv(point->z,point_dist); beam_scale = fixmul(beam_scale,beam_scale); //square it light = fixmul(light,beam_scale); } light = fixmul(light,fixmul(dist_scale,temp_lightval)); } } return light; } //compute the average dynamic light in a segment. Takes the segment number fix compute_seg_dynamic_light(int segnum) { fix sum; segment *seg; short *verts; seg = &Segments[segnum]; verts = seg->verts; sum = 0; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts++]; sum += Dynamic_light[*verts]; return sum >> 3; } fix object_light[MAX_OBJECTS]; int object_id[MAX_OBJECTS]; object *old_viewer; #define LIGHT_RATE i2f(4) //how fast the light ramps up //compute the lighting for an object. Takes a pointer to the object, //and possibly a rotated 3d point. If the point isn't specified, the //object's center point is rotated. fix compute_object_light(object *obj,vms_vector *rotated_pnt) { fix light; g3s_point objpnt; int objnum = obj-Objects; if (!rotated_pnt) { g3_rotate_point(&objpnt,&obj->pos); rotated_pnt = &objpnt.p3_vec; } //First, get static light for this segment light = Segments[obj->segnum].static_light; //return light; //Now, maybe return different value to smooth transitions if (Viewer==old_viewer && object_id[objnum] == obj->id) { fix delta_light,frame_delta; delta_light = light - object_light[objnum]; frame_delta = fixmul(LIGHT_RATE,FrameTime); if (abs(delta_light) <= frame_delta) object_light[objnum] = light; //we've hit the goal else if (delta_light < 0) light = object_light[objnum] -= frame_delta; else light = object_light[objnum] += frame_delta; } else { //new object, initialize object_id[objnum] = obj->id; object_light[objnum] = light; } //Next, add in headlight on this object light += compute_headlight_light(rotated_pnt,f1_0); //Finally, add in dynamic light for this segment light += compute_seg_dynamic_light(obj->segnum); old_viewer = Viewer; return light; }