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-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
14 * $Source: /cvs/cvsroot/d2x/main/editor/elight.c,v $
17 * $Date: 2004-12-19 13:54:27 $
19 * Editor lighting functions.
21 * $Log: not supported by cvs2svn $
22 * Revision 1.1.1.1 1999/06/14 22:02:55 donut
23 * Import of d1x 1.37 source.
25 * Revision 2.0 1995/02/27 11:35:16 john
26 * Version 2.0! No anonymous unions, Watcom 10.0, with no need
29 * Revision 1.21 1994/06/14 16:59:23 mike
30 * Fix references to tmap_num2, must strip off orientation bits.
32 * Revision 1.20 1994/05/31 12:31:57 mike
33 * fix bug in lighting -- WALL_IS_DOORWAY return value getting ignored,
34 * almost never recursively propagated light.
36 * Revision 1.19 1994/05/19 23:35:12 mike
37 * Support uv coordinates in range 0..1.0.
39 * Revision 1.18 1994/05/16 12:05:29 john
40 * Made texturemap light be a fix from 0 to 1.
42 * Revision 1.17 1994/05/14 18:00:38 matt
43 * Got rid of externs in source (non-header) files
45 * Revision 1.16 1994/05/03 11:04:27 mike
46 * Add function to select edge.
48 * Revision 1.15 1994/04/20 17:29:11 yuan
49 * Fixed bug where tmaps above 256 don't light properly.
52 * Revision 1.14 1994/03/22 14:20:46 yuan
53 * Made texture map 1 also cast light. (Cumulative with tmap_num2)
55 * Revision 1.13 1994/03/15 16:34:14 yuan
56 * Fixed bm loader (might have some changes in walls and switches)
58 * Revision 1.12 1994/02/22 18:55:10 yuan
59 * Ambient lighting "shines" on doors too!
61 * Revision 1.11 1994/02/17 12:05:55 matt
64 * Revision 1.10 1994/02/16 22:28:03 mike
65 * fix ambient lighting and smoothing.
67 * Revision 1.9 1994/02/14 12:05:42 mike
68 * change segment data structure.
70 * Revision 1.8 1994/01/26 17:27:45 yuan
71 * Still not perfected ambient lighting
73 * Revision 1.7 1994/01/25 17:58:08 yuan
74 * Added ambient lighting, and also added fixing bogus segments
75 * functions to the editor... (they don't work fully... need to
78 * Revision 1.6 1994/01/24 11:46:10 yuan
79 * *** empty log message ***
81 * Revision 1.5 1994/01/24 11:03:05 yuan
82 * Set lgiht maximum added... Changes are still in progress
84 * Revision 1.4 1994/01/18 19:16:07 yuan
85 * Added assign default to lighting pad.
87 * Revision 1.3 1993/12/17 12:26:00 mike
88 * Add functions for setting light values on whole segment at once.
90 * Revision 1.2 1993/12/16 16:56:12 mike
91 * Add new texture map lighting control functions.
93 * Revision 1.1 1993/12/16 13:21:50 mike
101 static char rcsid[] = "$Id: elight.c,v 1.1 2004-12-19 13:54:27 btb Exp $";
105 //#include <stdlib.h>
106 //#include <stdarg.h>
108 //#include <string.h>
117 #include "textures.h"
127 // -----------------------------------------------------------------------------
128 // Return light intensity at an instance of a vertex on a side in a segment.
129 fix get_light_intensity(segment *segp, int sidenum, int vert)
131 Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
134 return segp->sides[sidenum].uvls[vert].l;
137 // -----------------------------------------------------------------------------
138 // Set light intensity at a vertex, saturating in .5 to 15.5
139 void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
141 Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
144 if (intensity < MIN_LIGHTING_VALUE)
145 intensity = MIN_LIGHTING_VALUE;
147 if (intensity > MAX_LIGHTING_VALUE)
148 intensity = MAX_LIGHTING_VALUE;
150 segp->sides[sidenum].uvls[vert].l = intensity;
152 Update_flags |= UF_WORLD_CHANGED;
156 // -----------------------------------------------------------------------------
157 // Add light intensity to a vertex, saturating in .5 to 15.5
158 void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
160 // fix new_intensity;
162 set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
166 // -----------------------------------------------------------------------------
167 // Recursively apply light to segments.
168 // If current side is a wall, apply light there.
169 // If not a wall, apply light to child through that wall.
171 // It is possible to enter a segment twice by taking different paths. It is easy
172 // to prevent this by maintaining a list of visited segments, but it is important
173 // to reach segments with the greatest light intensity. This can be done by doing
174 // a breadth-first-search, or by storing the applied intensity with a visited segment,
175 // and if the current intensity is brighter, then apply the difference between it and
176 // the previous intensity.
177 // Note that it is also possible to visit the original light-casting segment, for example
178 // going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not
179 // desired, but not entirely invalid. 2 reflects some light back to 0.
180 void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth)
187 wid_result = WALL_IS_DOORWAY(segp, sidenum);
188 if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
190 for (v=0; v<4; v++) // add light to this wall
191 add_light_intensity(segp, sidenum, v, intensity);
192 return; // we return because there is a wall here, and light does not shine through walls
195 // No wall here, so apply light recursively
198 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
199 apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
204 // -----------------------------------------------------------------------------
205 // Top level recursive function for applying light.
206 // Calls apply_light_intensity.
207 // Uses light value on segp:sidenum (tmap_num2 defines light value) and applies
208 // the associated intensity to segp. It calls apply_light_intensity to apply intensity/3
209 // to all neighbors. apply_light_intensity recursively calls itself to apply light to
210 // subsequent neighbors (and forming loops, see above).
211 void propagate_light_intensity(segment *segp, int sidenum)
218 texmap = segp->sides[sidenum].tmap_num;
219 intensity += TmapInfo[texmap].lighting;
220 texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff;
221 intensity += TmapInfo[texmap].lighting;
225 add_light_intensity(segp, sidenum, v, intensity);
227 // Now, for all sides which are not the same as sidenum (the side casting the light),
228 // add a light value to them (if they have no children, ie, they have a wall there).
229 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
231 apply_light_intensity(segp, s, intensity/2, 1);
237 // -----------------------------------------------------------------------------
238 // Highest level function, bound to a key. Apply ambient light to all segments based
239 // on user-defined light sources.
240 int LightAmbientLighting()
244 for (seg=0; seg<=Highest_segment_index; seg++)
245 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
246 propagate_light_intensity(&Segments[seg], side);
251 // -----------------------------------------------------------------------------
252 int LightSelectNextVertex(void)
258 Update_flags |= UF_WORLD_CHANGED;
263 // -----------------------------------------------------------------------------
264 int LightSelectNextEdge(void)
270 Update_flags |= UF_WORLD_CHANGED;
275 // -----------------------------------------------------------------------------
276 // Copy intensity from current vertex to all other vertices on side.
277 int LightCopyIntensity(void)
281 intensity = get_light_intensity(Cursegp, Curside, Curvert);
285 set_light_intensity(Cursegp, Curside, v, intensity);
290 // -----------------------------------------------------------------------------
291 // Copy intensity from current vertex to all other vertices on side.
292 int LightCopyIntensitySegment(void)
296 intensity = get_light_intensity(Cursegp, Curside, Curvert);
298 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
300 if ((s != Curside) || (v != Curvert))
301 set_light_intensity(Cursegp, s, v, intensity);
306 // -----------------------------------------------------------------------------
307 int LightDecreaseLightVertex(void)
309 set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
314 // -----------------------------------------------------------------------------
315 int LightIncreaseLightVertex(void)
317 set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
322 // -----------------------------------------------------------------------------
323 int LightDecreaseLightSide(void)
328 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
333 // -----------------------------------------------------------------------------
334 int LightIncreaseLightSide(void)
339 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
344 // -----------------------------------------------------------------------------
345 int LightDecreaseLightSegment(void)
349 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
351 set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
356 // -----------------------------------------------------------------------------
357 int LightIncreaseLightSegment(void)
361 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
363 set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
368 // -----------------------------------------------------------------------------
369 int LightSetDefault(void)
374 set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
380 // -----------------------------------------------------------------------------
381 int LightSetMaximum(void)
386 set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
392 // -----------------------------------------------------------------------------
393 int LightSetDefaultAll(void)
396 assign_default_lighting_all();
398 Update_flags |= UF_WORLD_CHANGED;