1 /* $Id: elight.c,v 1.3 2004-12-19 15:21:11 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Editor lighting functions.
22 static char rcsid[] = "$Id: elight.c,v 1.3 2004-12-19 15:21:11 btb Exp $";
52 // -----------------------------------------------------------------------------
53 // Return light intensity at an instance of a vertex on a side in a segment.
54 fix get_light_intensity(segment *segp, int sidenum, int vert)
56 Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
59 return segp->sides[sidenum].uvls[vert].l;
62 // -----------------------------------------------------------------------------
63 // Set light intensity at a vertex, saturating in .5 to 15.5
64 void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
66 Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
69 if (intensity < MIN_LIGHTING_VALUE)
70 intensity = MIN_LIGHTING_VALUE;
72 if (intensity > MAX_LIGHTING_VALUE)
73 intensity = MAX_LIGHTING_VALUE;
75 segp->sides[sidenum].uvls[vert].l = intensity;
77 Update_flags |= UF_WORLD_CHANGED;
81 // -----------------------------------------------------------------------------
82 // Add light intensity to a vertex, saturating in .5 to 15.5
83 void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
87 set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
91 // -----------------------------------------------------------------------------
92 // Recursively apply light to segments.
93 // If current side is a wall, apply light there.
94 // If not a wall, apply light to child through that wall.
96 // It is possible to enter a segment twice by taking different paths. It is easy
97 // to prevent this by maintaining a list of visited segments, but it is important
98 // to reach segments with the greatest light intensity. This can be done by doing
99 // a breadth-first-search, or by storing the applied intensity with a visited segment,
100 // and if the current intensity is brighter, then apply the difference between it and
101 // the previous intensity.
102 // Note that it is also possible to visit the original light-casting segment, for example
103 // going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not
104 // desired, but not entirely invalid. 2 reflects some light back to 0.
105 void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth)
112 wid_result = WALL_IS_DOORWAY(segp, sidenum);
113 if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
115 for (v=0; v<4; v++) // add light to this wall
116 add_light_intensity(segp, sidenum, v, intensity);
117 return; // we return because there is a wall here, and light does not shine through walls
120 // No wall here, so apply light recursively
123 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
124 apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
129 // -----------------------------------------------------------------------------
130 // Top level recursive function for applying light.
131 // Calls apply_light_intensity.
132 // Uses light value on segp:sidenum (tmap_num2 defines light value) and applies
133 // the associated intensity to segp. It calls apply_light_intensity to apply intensity/3
134 // to all neighbors. apply_light_intensity recursively calls itself to apply light to
135 // subsequent neighbors (and forming loops, see above).
136 void propagate_light_intensity(segment *segp, int sidenum)
143 texmap = segp->sides[sidenum].tmap_num;
144 intensity += TmapInfo[texmap].lighting;
145 texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff;
146 intensity += TmapInfo[texmap].lighting;
150 add_light_intensity(segp, sidenum, v, intensity);
152 // Now, for all sides which are not the same as sidenum (the side casting the light),
153 // add a light value to them (if they have no children, ie, they have a wall there).
154 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
156 apply_light_intensity(segp, s, intensity/2, 1);
162 // -----------------------------------------------------------------------------
163 // Highest level function, bound to a key. Apply ambient light to all segments based
164 // on user-defined light sources.
165 int LightAmbientLighting()
169 for (seg=0; seg<=Highest_segment_index; seg++)
170 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
171 propagate_light_intensity(&Segments[seg], side);
176 // -----------------------------------------------------------------------------
177 int LightSelectNextVertex(void)
183 Update_flags |= UF_WORLD_CHANGED;
188 // -----------------------------------------------------------------------------
189 int LightSelectNextEdge(void)
195 Update_flags |= UF_WORLD_CHANGED;
200 // -----------------------------------------------------------------------------
201 // Copy intensity from current vertex to all other vertices on side.
202 int LightCopyIntensity(void)
206 intensity = get_light_intensity(Cursegp, Curside, Curvert);
210 set_light_intensity(Cursegp, Curside, v, intensity);
215 // -----------------------------------------------------------------------------
216 // Copy intensity from current vertex to all other vertices on side.
217 int LightCopyIntensitySegment(void)
221 intensity = get_light_intensity(Cursegp, Curside, Curvert);
223 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
225 if ((s != Curside) || (v != Curvert))
226 set_light_intensity(Cursegp, s, v, intensity);
231 // -----------------------------------------------------------------------------
232 int LightDecreaseLightVertex(void)
234 set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
239 // -----------------------------------------------------------------------------
240 int LightIncreaseLightVertex(void)
242 set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
247 // -----------------------------------------------------------------------------
248 int LightDecreaseLightSide(void)
253 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
258 // -----------------------------------------------------------------------------
259 int LightIncreaseLightSide(void)
264 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
269 // -----------------------------------------------------------------------------
270 int LightDecreaseLightSegment(void)
274 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
276 set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
281 // -----------------------------------------------------------------------------
282 int LightIncreaseLightSegment(void)
286 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
288 set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
293 // -----------------------------------------------------------------------------
294 int LightSetDefault(void)
299 set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
305 // -----------------------------------------------------------------------------
306 int LightSetMaximum(void)
311 set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
317 // -----------------------------------------------------------------------------
318 int LightSetDefaultAll(void)
321 assign_default_lighting_all();
323 Update_flags |= UF_WORLD_CHANGED;