1 /* $Id: elight.c,v 1.2 2004-12-19 14:52:48 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.
23 static char rcsid[] = "$Id: elight.c,v 1.2 2004-12-19 14:52:48 btb Exp $";
49 // -----------------------------------------------------------------------------
50 // Return light intensity at an instance of a vertex on a side in a segment.
51 fix get_light_intensity(segment *segp, int sidenum, int vert)
53 Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
56 return segp->sides[sidenum].uvls[vert].l;
59 // -----------------------------------------------------------------------------
60 // Set light intensity at a vertex, saturating in .5 to 15.5
61 void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
63 Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
66 if (intensity < MIN_LIGHTING_VALUE)
67 intensity = MIN_LIGHTING_VALUE;
69 if (intensity > MAX_LIGHTING_VALUE)
70 intensity = MAX_LIGHTING_VALUE;
72 segp->sides[sidenum].uvls[vert].l = intensity;
74 Update_flags |= UF_WORLD_CHANGED;
78 // -----------------------------------------------------------------------------
79 // Add light intensity to a vertex, saturating in .5 to 15.5
80 void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
84 set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
88 // -----------------------------------------------------------------------------
89 // Recursively apply light to segments.
90 // If current side is a wall, apply light there.
91 // If not a wall, apply light to child through that wall.
93 // It is possible to enter a segment twice by taking different paths. It is easy
94 // to prevent this by maintaining a list of visited segments, but it is important
95 // to reach segments with the greatest light intensity. This can be done by doing
96 // a breadth-first-search, or by storing the applied intensity with a visited segment,
97 // and if the current intensity is brighter, then apply the difference between it and
98 // the previous intensity.
99 // Note that it is also possible to visit the original light-casting segment, for example
100 // going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not
101 // desired, but not entirely invalid. 2 reflects some light back to 0.
102 void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth)
109 wid_result = WALL_IS_DOORWAY(segp, sidenum);
110 if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
112 for (v=0; v<4; v++) // add light to this wall
113 add_light_intensity(segp, sidenum, v, intensity);
114 return; // we return because there is a wall here, and light does not shine through walls
117 // No wall here, so apply light recursively
120 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
121 apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
126 // -----------------------------------------------------------------------------
127 // Top level recursive function for applying light.
128 // Calls apply_light_intensity.
129 // Uses light value on segp:sidenum (tmap_num2 defines light value) and applies
130 // the associated intensity to segp. It calls apply_light_intensity to apply intensity/3
131 // to all neighbors. apply_light_intensity recursively calls itself to apply light to
132 // subsequent neighbors (and forming loops, see above).
133 void propagate_light_intensity(segment *segp, int sidenum)
140 texmap = segp->sides[sidenum].tmap_num;
141 intensity += TmapInfo[texmap].lighting;
142 texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff;
143 intensity += TmapInfo[texmap].lighting;
147 add_light_intensity(segp, sidenum, v, intensity);
149 // Now, for all sides which are not the same as sidenum (the side casting the light),
150 // add a light value to them (if they have no children, ie, they have a wall there).
151 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
153 apply_light_intensity(segp, s, intensity/2, 1);
159 // -----------------------------------------------------------------------------
160 // Highest level function, bound to a key. Apply ambient light to all segments based
161 // on user-defined light sources.
162 int LightAmbientLighting()
166 for (seg=0; seg<=Highest_segment_index; seg++)
167 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
168 propagate_light_intensity(&Segments[seg], side);
173 // -----------------------------------------------------------------------------
174 int LightSelectNextVertex(void)
180 Update_flags |= UF_WORLD_CHANGED;
185 // -----------------------------------------------------------------------------
186 int LightSelectNextEdge(void)
192 Update_flags |= UF_WORLD_CHANGED;
197 // -----------------------------------------------------------------------------
198 // Copy intensity from current vertex to all other vertices on side.
199 int LightCopyIntensity(void)
203 intensity = get_light_intensity(Cursegp, Curside, Curvert);
207 set_light_intensity(Cursegp, Curside, v, intensity);
212 // -----------------------------------------------------------------------------
213 // Copy intensity from current vertex to all other vertices on side.
214 int LightCopyIntensitySegment(void)
218 intensity = get_light_intensity(Cursegp, Curside, Curvert);
220 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
222 if ((s != Curside) || (v != Curvert))
223 set_light_intensity(Cursegp, s, v, intensity);
228 // -----------------------------------------------------------------------------
229 int LightDecreaseLightVertex(void)
231 set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
236 // -----------------------------------------------------------------------------
237 int LightIncreaseLightVertex(void)
239 set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
244 // -----------------------------------------------------------------------------
245 int LightDecreaseLightSide(void)
250 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
255 // -----------------------------------------------------------------------------
256 int LightIncreaseLightSide(void)
261 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
266 // -----------------------------------------------------------------------------
267 int LightDecreaseLightSegment(void)
271 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
273 set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
278 // -----------------------------------------------------------------------------
279 int LightIncreaseLightSegment(void)
283 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
285 set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
290 // -----------------------------------------------------------------------------
291 int LightSetDefault(void)
296 set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
302 // -----------------------------------------------------------------------------
303 int LightSetMaximum(void)
308 set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
314 // -----------------------------------------------------------------------------
315 int LightSetDefaultAll(void)
318 assign_default_lighting_all();
320 Update_flags |= UF_WORLD_CHANGED;