]> icculus.org git repositories - btb/d2x.git/blob - main/editor/elight.c
remove rcs tags
[btb/d2x.git] / main / editor / elight.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-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Editor lighting functions.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "conf.h"
22 #endif
23
24 #include <stdio.h>
25 //#include <stdlib.h>
26 //#include <stdarg.h>
27 //#include <math.h>
28 //#include <string.h>
29
30 #include "inferno.h"
31 #include "segment.h"
32 #include "editor.h"
33 #include "seguvs.h"
34
35 #include "wall.h"
36
37 #include "textures.h"
38
39 #include "fix.h"
40 #include "mono.h"
41 #include "error.h"
42 #include "kdefs.h"
43 #include "gameseg.h"
44
45 #include "texmap.h"
46
47 // -----------------------------------------------------------------------------
48 //      Return light intensity at an instance of a vertex on a side in a segment.
49 fix get_light_intensity(segment *segp, int sidenum, int vert)
50 {
51         Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
52         Assert(vert <= 3);
53
54         return segp->sides[sidenum].uvls[vert].l;
55 }
56
57 // -----------------------------------------------------------------------------
58 //      Set light intensity at a vertex, saturating in .5 to 15.5
59 void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
60 {
61         Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
62         Assert(vert <= 3);
63
64         if (intensity < MIN_LIGHTING_VALUE)
65                 intensity = MIN_LIGHTING_VALUE;
66
67         if (intensity > MAX_LIGHTING_VALUE)
68                 intensity = MAX_LIGHTING_VALUE;
69
70         segp->sides[sidenum].uvls[vert].l = intensity;
71
72         Update_flags |= UF_WORLD_CHANGED;
73 }
74
75
76 // -----------------------------------------------------------------------------
77 //      Add light intensity to a vertex, saturating in .5 to 15.5
78 void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
79 {
80 //      fix     new_intensity;
81
82         set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
83 }
84
85
86 // -----------------------------------------------------------------------------
87 //      Recursively apply light to segments.
88 //      If current side is a wall, apply light there.
89 //      If not a wall, apply light to child through that wall.
90 //      Notes:
91 //              It is possible to enter a segment twice by taking different paths.  It is easy
92 //              to prevent this by maintaining a list of visited segments, but it is important
93 //              to reach segments with the greatest light intensity.  This can be done by doing
94 //              a breadth-first-search, or by storing the applied intensity with a visited segment,
95 //              and if the current intensity is brighter, then apply the difference between it and
96 //              the previous intensity.
97 //              Note that it is also possible to visit the original light-casting segment, for example
98 //              going from segment 0 to 2, then from 2 to 0.  This is peculiar and probably not
99 //              desired, but not entirely invalid.  2 reflects some light back to 0.
100 void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth)
101 {
102         int     wid_result;
103
104         if (intensity == 0)
105                 return;
106
107         wid_result = WALL_IS_DOORWAY(segp, sidenum);
108         if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
109                 int     v;
110                 for (v=0; v<4; v++)                                                     // add light to this wall
111                         add_light_intensity(segp, sidenum, v, intensity);
112                 return;                                                                         // we return because there is a wall here, and light does not shine through walls
113         }
114
115         //      No wall here, so apply light recursively
116         if (depth < 3) {
117                 int     s;
118                 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
119                         apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
120         }
121
122 }
123
124 // -----------------------------------------------------------------------------
125 //      Top level recursive function for applying light.
126 //      Calls apply_light_intensity.
127 //      Uses light value on segp:sidenum (tmap_num2 defines light value) and applies
128 //      the associated intensity to segp.  It calls apply_light_intensity to apply intensity/3
129 //      to all neighbors.  apply_light_intensity recursively calls itself to apply light to
130 //      subsequent neighbors (and forming loops, see above).
131 void propagate_light_intensity(segment *segp, int sidenum) 
132 {
133         int             v,s;
134         fix             intensity;
135         short           texmap;
136
137         intensity = 0;
138         texmap = segp->sides[sidenum].tmap_num;
139         intensity += TmapInfo[texmap].lighting;
140         texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff;
141         intensity += TmapInfo[texmap].lighting;
142
143         if (intensity > 0) {
144                 for (v=0; v<4; v++)
145                         add_light_intensity(segp, sidenum, v, intensity);
146         
147                 //      Now, for all sides which are not the same as sidenum (the side casting the light),
148                 //      add a light value to them (if they have no children, ie, they have a wall there).
149                 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
150                         if (s != sidenum)
151                                 apply_light_intensity(segp, s, intensity/2, 1);
152         }
153
154 }
155
156
157 // -----------------------------------------------------------------------------
158 //      Highest level function, bound to a key.  Apply ambient light to all segments based
159 //      on user-defined light sources.
160 int LightAmbientLighting()
161 {
162         int seg, side;
163
164         for (seg=0; seg<=Highest_segment_index; seg++)
165                 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
166                         propagate_light_intensity(&Segments[seg], side);
167         return 0;
168 }
169
170
171 // -----------------------------------------------------------------------------
172 int LightSelectNextVertex(void)
173 {
174         Curvert++;
175         if (Curvert >= 4)
176                 Curvert = 0;
177
178         Update_flags |= UF_WORLD_CHANGED;
179
180         return  1;
181 }
182
183 // -----------------------------------------------------------------------------
184 int LightSelectNextEdge(void)
185 {
186         Curedge++;
187         if (Curedge >= 4)
188                 Curedge = 0;
189
190         Update_flags |= UF_WORLD_CHANGED;
191
192         return  1;
193 }
194
195 // -----------------------------------------------------------------------------
196 //      Copy intensity from current vertex to all other vertices on side.
197 int LightCopyIntensity(void)
198 {
199         int     v,intensity;
200
201         intensity = get_light_intensity(Cursegp, Curside, Curvert);
202
203         for (v=0; v<4; v++)
204                 if (v != Curvert)
205                         set_light_intensity(Cursegp, Curside, v, intensity);
206
207         return  1;
208 }
209
210 // -----------------------------------------------------------------------------
211 //      Copy intensity from current vertex to all other vertices on side.
212 int LightCopyIntensitySegment(void)
213 {
214         int     s,v,intensity;
215
216         intensity = get_light_intensity(Cursegp, Curside, Curvert);
217
218         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
219                 for (v=0; v<4; v++)
220                         if ((s != Curside) || (v != Curvert))
221                                 set_light_intensity(Cursegp, s, v, intensity);
222
223         return  1;
224 }
225
226 // -----------------------------------------------------------------------------
227 int LightDecreaseLightVertex(void)
228 {
229         set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
230
231         return  1;
232 }
233
234 // -----------------------------------------------------------------------------
235 int LightIncreaseLightVertex(void)
236 {
237         set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
238
239         return  1;
240 }
241
242 // -----------------------------------------------------------------------------
243 int LightDecreaseLightSide(void)
244 {
245         int     v;
246
247         for (v=0; v<4; v++)
248                 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
249
250         return  1;
251 }
252
253 // -----------------------------------------------------------------------------
254 int LightIncreaseLightSide(void)
255 {
256         int     v;
257
258         for (v=0; v<4; v++)
259                 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
260
261         return  1;
262 }
263
264 // -----------------------------------------------------------------------------
265 int LightDecreaseLightSegment(void)
266 {
267         int     s,v;
268
269         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
270                 for (v=0; v<4; v++)
271                         set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
272
273         return  1;
274 }
275
276 // -----------------------------------------------------------------------------
277 int LightIncreaseLightSegment(void)
278 {
279         int     s,v;
280
281         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
282                 for (v=0; v<4; v++)
283                         set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
284
285         return  1;
286 }
287
288 // -----------------------------------------------------------------------------
289 int LightSetDefault(void)
290 {
291         int     v;
292
293         for (v=0; v<4; v++)
294                 set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
295
296         return  1;
297 }
298
299
300 // -----------------------------------------------------------------------------
301 int LightSetMaximum(void)
302 {
303         int     v;
304
305         for (v=0; v<4; v++)
306                 set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
307
308         return  1;
309 }
310
311
312 // -----------------------------------------------------------------------------
313 int LightSetDefaultAll(void)
314 {
315
316         assign_default_lighting_all();
317
318         Update_flags |= UF_WORLD_CHANGED;
319
320         return  1;
321 }
322
323
324