]> icculus.org git repositories - btb/d2x.git/blob - main/editor/elight.c
imported missing editor files from d1x
[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  * $Source: /cvs/cvsroot/d2x/main/editor/elight.c,v $
15  * $Revision: 1.1 $
16  * $Author: btb $
17  * $Date: 2004-12-19 13:54:27 $
18  * 
19  * Editor lighting functions.
20  * 
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.
24  *
25  * Revision 2.0  1995/02/27  11:35:16  john
26  * Version 2.0! No anonymous unions, Watcom 10.0, with no need
27  * for bitmaps.tbl.
28  * 
29  * Revision 1.21  1994/06/14  16:59:23  mike
30  * Fix references to tmap_num2, must strip off orientation bits.
31  * 
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.
35  * 
36  * Revision 1.19  1994/05/19  23:35:12  mike
37  * Support uv coordinates in range 0..1.0.
38  * 
39  * Revision 1.18  1994/05/16  12:05:29  john
40  * Made texturemap light be a fix from 0 to 1.
41  * 
42  * Revision 1.17  1994/05/14  18:00:38  matt
43  * Got rid of externs in source (non-header) files
44  * 
45  * Revision 1.16  1994/05/03  11:04:27  mike
46  * Add function to select edge.
47  * 
48  * Revision 1.15  1994/04/20  17:29:11  yuan
49  * Fixed bug where tmaps above 256 don't light properly.
50  * (duh!)
51  * 
52  * Revision 1.14  1994/03/22  14:20:46  yuan
53  * Made texture map 1 also cast light.  (Cumulative with tmap_num2)
54  * 
55  * Revision 1.13  1994/03/15  16:34:14  yuan
56  * Fixed bm loader (might have some changes in walls and switches)
57  * 
58  * Revision 1.12  1994/02/22  18:55:10  yuan
59  * Ambient lighting "shines" on doors too!
60  * 
61  * Revision 1.11  1994/02/17  12:05:55  matt
62  * Got rid of warnings
63  * 
64  * Revision 1.10  1994/02/16  22:28:03  mike
65  * fix ambient lighting and smoothing.
66  * 
67  * Revision 1.9  1994/02/14  12:05:42  mike
68  * change segment data structure.
69  * 
70  * Revision 1.8  1994/01/26  17:27:45  yuan
71  * Still not perfected ambient lighting
72  * 
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
76  * check out seguvs.c
77  * 
78  * Revision 1.6  1994/01/24  11:46:10  yuan
79  * *** empty log message ***
80  * 
81  * Revision 1.5  1994/01/24  11:03:05  yuan
82  * Set lgiht maximum added... Changes are still in progress
83  * 
84  * Revision 1.4  1994/01/18  19:16:07  yuan
85  * Added assign default to lighting pad.
86  * 
87  * Revision 1.3  1993/12/17  12:26:00  mike
88  * Add functions for setting light values on whole segment at once.
89  * 
90  * Revision 1.2  1993/12/16  16:56:12  mike
91  * Add new texture map lighting control functions.
92  * 
93  * Revision 1.1  1993/12/16  13:21:50  mike
94  * Initial revision
95  * 
96  * 
97  */
98
99
100 #ifdef RCS
101 static char rcsid[] = "$Id: elight.c,v 1.1 2004-12-19 13:54:27 btb Exp $";
102 #endif
103
104 #include <stdio.h>
105 //#include <stdlib.h>
106 //#include <stdarg.h>
107 //#include <math.h>
108 //#include <string.h>
109
110 #include "inferno.h"
111 #include "segment.h"
112 #include "editor.h"
113 #include "seguvs.h"
114
115 #include "wall.h"
116
117 #include "textures.h"
118
119 #include "fix.h"
120 #include "mono.h"
121 #include "error.h"
122 #include "kdefs.h"
123 #include "gameseg.h"
124
125 #include "texmap.h"
126
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)
130 {
131         Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
132         Assert(vert <= 3);
133
134         return segp->sides[sidenum].uvls[vert].l;
135 }
136
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)
140 {
141         Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
142         Assert(vert <= 3);
143
144         if (intensity < MIN_LIGHTING_VALUE)
145                 intensity = MIN_LIGHTING_VALUE;
146
147         if (intensity > MAX_LIGHTING_VALUE)
148                 intensity = MAX_LIGHTING_VALUE;
149
150         segp->sides[sidenum].uvls[vert].l = intensity;
151
152         Update_flags |= UF_WORLD_CHANGED;
153 }
154
155
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)
159 {
160 //      fix     new_intensity;
161
162         set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
163 }
164
165
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.
170 //      Notes:
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)
181 {
182         int     wid_result;
183
184         if (intensity == 0)
185                 return;
186
187         wid_result = WALL_IS_DOORWAY(segp, sidenum);
188         if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
189                 int     v;
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
193         }
194
195         //      No wall here, so apply light recursively
196         if (depth < 3) {
197                 int     s;
198                 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
199                         apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
200         }
201
202 }
203
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) 
212 {
213         int             v,s;
214         fix             intensity;
215         short           texmap;
216
217         intensity = 0;
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;
222
223         if (intensity > 0) {
224                 for (v=0; v<4; v++)
225                         add_light_intensity(segp, sidenum, v, intensity);
226         
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++)
230                         if (s != sidenum)
231                                 apply_light_intensity(segp, s, intensity/2, 1);
232         }
233
234 }
235
236
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()
241 {
242         int seg, side;
243
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);
247         return 0;
248 }
249
250
251 // -----------------------------------------------------------------------------
252 int LightSelectNextVertex(void)
253 {
254         Curvert++;
255         if (Curvert >= 4)
256                 Curvert = 0;
257
258         Update_flags |= UF_WORLD_CHANGED;
259
260         return  1;
261 }
262
263 // -----------------------------------------------------------------------------
264 int LightSelectNextEdge(void)
265 {
266         Curedge++;
267         if (Curedge >= 4)
268                 Curedge = 0;
269
270         Update_flags |= UF_WORLD_CHANGED;
271
272         return  1;
273 }
274
275 // -----------------------------------------------------------------------------
276 //      Copy intensity from current vertex to all other vertices on side.
277 int LightCopyIntensity(void)
278 {
279         int     v,intensity;
280
281         intensity = get_light_intensity(Cursegp, Curside, Curvert);
282
283         for (v=0; v<4; v++)
284                 if (v != Curvert)
285                         set_light_intensity(Cursegp, Curside, v, intensity);
286
287         return  1;
288 }
289
290 // -----------------------------------------------------------------------------
291 //      Copy intensity from current vertex to all other vertices on side.
292 int LightCopyIntensitySegment(void)
293 {
294         int     s,v,intensity;
295
296         intensity = get_light_intensity(Cursegp, Curside, Curvert);
297
298         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
299                 for (v=0; v<4; v++)
300                         if ((s != Curside) || (v != Curvert))
301                                 set_light_intensity(Cursegp, s, v, intensity);
302
303         return  1;
304 }
305
306 // -----------------------------------------------------------------------------
307 int LightDecreaseLightVertex(void)
308 {
309         set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
310
311         return  1;
312 }
313
314 // -----------------------------------------------------------------------------
315 int LightIncreaseLightVertex(void)
316 {
317         set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
318
319         return  1;
320 }
321
322 // -----------------------------------------------------------------------------
323 int LightDecreaseLightSide(void)
324 {
325         int     v;
326
327         for (v=0; v<4; v++)
328                 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
329
330         return  1;
331 }
332
333 // -----------------------------------------------------------------------------
334 int LightIncreaseLightSide(void)
335 {
336         int     v;
337
338         for (v=0; v<4; v++)
339                 set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
340
341         return  1;
342 }
343
344 // -----------------------------------------------------------------------------
345 int LightDecreaseLightSegment(void)
346 {
347         int     s,v;
348
349         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
350                 for (v=0; v<4; v++)
351                         set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
352
353         return  1;
354 }
355
356 // -----------------------------------------------------------------------------
357 int LightIncreaseLightSegment(void)
358 {
359         int     s,v;
360
361         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
362                 for (v=0; v<4; v++)
363                         set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
364
365         return  1;
366 }
367
368 // -----------------------------------------------------------------------------
369 int LightSetDefault(void)
370 {
371         int     v;
372
373         for (v=0; v<4; v++)
374                 set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
375
376         return  1;
377 }
378
379
380 // -----------------------------------------------------------------------------
381 int LightSetMaximum(void)
382 {
383         int     v;
384
385         for (v=0; v<4; v++)
386                 set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
387
388         return  1;
389 }
390
391
392 // -----------------------------------------------------------------------------
393 int LightSetDefaultAll(void)
394 {
395
396         assign_default_lighting_all();
397
398         Update_flags |= UF_WORLD_CHANGED;
399
400         return  1;
401 }
402
403
404