]> icculus.org git repositories - btb/d2x.git/blob - main/editor/elight.c
don't use hardcoded descriptions of joystick buttons/axes
[btb/d2x.git] / main / editor / elight.c
1 /* $Id: elight.c,v 1.3 2004-12-19 15:21:11 btb Exp $ */
2 /*
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.
13 */
14
15 /*
16  *
17  * Editor lighting functions.
18  *
19  */
20
21 #ifdef RCS
22 static char rcsid[] = "$Id: elight.c,v 1.3 2004-12-19 15:21:11 btb Exp $";
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 #include "conf.h"
27 #endif
28
29 #include <stdio.h>
30 //#include <stdlib.h>
31 //#include <stdarg.h>
32 //#include <math.h>
33 //#include <string.h>
34
35 #include "inferno.h"
36 #include "segment.h"
37 #include "editor.h"
38 #include "seguvs.h"
39
40 #include "wall.h"
41
42 #include "textures.h"
43
44 #include "fix.h"
45 #include "mono.h"
46 #include "error.h"
47 #include "kdefs.h"
48 #include "gameseg.h"
49
50 #include "texmap.h"
51
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)
55 {
56         Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
57         Assert(vert <= 3);
58
59         return segp->sides[sidenum].uvls[vert].l;
60 }
61
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)
65 {
66         Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
67         Assert(vert <= 3);
68
69         if (intensity < MIN_LIGHTING_VALUE)
70                 intensity = MIN_LIGHTING_VALUE;
71
72         if (intensity > MAX_LIGHTING_VALUE)
73                 intensity = MAX_LIGHTING_VALUE;
74
75         segp->sides[sidenum].uvls[vert].l = intensity;
76
77         Update_flags |= UF_WORLD_CHANGED;
78 }
79
80
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)
84 {
85 //      fix     new_intensity;
86
87         set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
88 }
89
90
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.
95 //      Notes:
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)
106 {
107         int     wid_result;
108
109         if (intensity == 0)
110                 return;
111
112         wid_result = WALL_IS_DOORWAY(segp, sidenum);
113         if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
114                 int     v;
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
118         }
119
120         //      No wall here, so apply light recursively
121         if (depth < 3) {
122                 int     s;
123                 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
124                         apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
125         }
126
127 }
128
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) 
137 {
138         int             v,s;
139         fix             intensity;
140         short           texmap;
141
142         intensity = 0;
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;
147
148         if (intensity > 0) {
149                 for (v=0; v<4; v++)
150                         add_light_intensity(segp, sidenum, v, intensity);
151         
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++)
155                         if (s != sidenum)
156                                 apply_light_intensity(segp, s, intensity/2, 1);
157         }
158
159 }
160
161
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()
166 {
167         int seg, side;
168
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);
172         return 0;
173 }
174
175
176 // -----------------------------------------------------------------------------
177 int LightSelectNextVertex(void)
178 {
179         Curvert++;
180         if (Curvert >= 4)
181                 Curvert = 0;
182
183         Update_flags |= UF_WORLD_CHANGED;
184
185         return  1;
186 }
187
188 // -----------------------------------------------------------------------------
189 int LightSelectNextEdge(void)
190 {
191         Curedge++;
192         if (Curedge >= 4)
193                 Curedge = 0;
194
195         Update_flags |= UF_WORLD_CHANGED;
196
197         return  1;
198 }
199
200 // -----------------------------------------------------------------------------
201 //      Copy intensity from current vertex to all other vertices on side.
202 int LightCopyIntensity(void)
203 {
204         int     v,intensity;
205
206         intensity = get_light_intensity(Cursegp, Curside, Curvert);
207
208         for (v=0; v<4; v++)
209                 if (v != Curvert)
210                         set_light_intensity(Cursegp, Curside, v, intensity);
211
212         return  1;
213 }
214
215 // -----------------------------------------------------------------------------
216 //      Copy intensity from current vertex to all other vertices on side.
217 int LightCopyIntensitySegment(void)
218 {
219         int     s,v,intensity;
220
221         intensity = get_light_intensity(Cursegp, Curside, Curvert);
222
223         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
224                 for (v=0; v<4; v++)
225                         if ((s != Curside) || (v != Curvert))
226                                 set_light_intensity(Cursegp, s, v, intensity);
227
228         return  1;
229 }
230
231 // -----------------------------------------------------------------------------
232 int LightDecreaseLightVertex(void)
233 {
234         set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
235
236         return  1;
237 }
238
239 // -----------------------------------------------------------------------------
240 int LightIncreaseLightVertex(void)
241 {
242         set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
243
244         return  1;
245 }
246
247 // -----------------------------------------------------------------------------
248 int LightDecreaseLightSide(void)
249 {
250         int     v;
251
252         for (v=0; v<4; v++)
253                 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
254
255         return  1;
256 }
257
258 // -----------------------------------------------------------------------------
259 int LightIncreaseLightSide(void)
260 {
261         int     v;
262
263         for (v=0; v<4; v++)
264                 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
265
266         return  1;
267 }
268
269 // -----------------------------------------------------------------------------
270 int LightDecreaseLightSegment(void)
271 {
272         int     s,v;
273
274         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
275                 for (v=0; v<4; v++)
276                         set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
277
278         return  1;
279 }
280
281 // -----------------------------------------------------------------------------
282 int LightIncreaseLightSegment(void)
283 {
284         int     s,v;
285
286         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
287                 for (v=0; v<4; v++)
288                         set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
289
290         return  1;
291 }
292
293 // -----------------------------------------------------------------------------
294 int LightSetDefault(void)
295 {
296         int     v;
297
298         for (v=0; v<4; v++)
299                 set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
300
301         return  1;
302 }
303
304
305 // -----------------------------------------------------------------------------
306 int LightSetMaximum(void)
307 {
308         int     v;
309
310         for (v=0; v<4; v++)
311                 set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
312
313         return  1;
314 }
315
316
317 // -----------------------------------------------------------------------------
318 int LightSetDefaultAll(void)
319 {
320
321         assign_default_lighting_all();
322
323         Update_flags |= UF_WORLD_CHANGED;
324
325         return  1;
326 }
327
328
329