home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / editor / elight.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  12KB  |  401 lines

  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: f:/miner/source/main/editor/rcs/elight.c $
  15.  * $Revision: 2.0 $
  16.  * $Author: john $
  17.  * $Date: 1995/02/27 11:35:16 $
  18.  * 
  19.  * Editor lighting functions.
  20.  * 
  21.  * $Log: elight.c $
  22.  * Revision 2.0  1995/02/27  11:35:16  john
  23.  * Version 2.0! No anonymous unions, Watcom 10.0, with no need
  24.  * for bitmaps.tbl.
  25.  * 
  26.  * Revision 1.21  1994/06/14  16:59:23  mike
  27.  * Fix references to tmap_num2, must strip off orientation bits.
  28.  * 
  29.  * Revision 1.20  1994/05/31  12:31:57  mike
  30.  * fix bug in lighting -- WALL_IS_DOORWAY return value getting ignored,
  31.  * almost never recursively propagated light.
  32.  * 
  33.  * Revision 1.19  1994/05/19  23:35:12  mike
  34.  * Support uv coordinates in range 0..1.0.
  35.  * 
  36.  * Revision 1.18  1994/05/16  12:05:29  john
  37.  * Made texturemap light be a fix from 0 to 1.
  38.  * 
  39.  * Revision 1.17  1994/05/14  18:00:38  matt
  40.  * Got rid of externs in source (non-header) files
  41.  * 
  42.  * Revision 1.16  1994/05/03  11:04:27  mike
  43.  * Add function to select edge.
  44.  * 
  45.  * Revision 1.15  1994/04/20  17:29:11  yuan
  46.  * Fixed bug where tmaps above 256 don't light properly.
  47.  * (duh!)
  48.  * 
  49.  * Revision 1.14  1994/03/22  14:20:46  yuan
  50.  * Made texture map 1 also cast light.  (Cumulative with tmap_num2)
  51.  * 
  52.  * Revision 1.13  1994/03/15  16:34:14  yuan
  53.  * Fixed bm loader (might have some changes in walls and switches)
  54.  * 
  55.  * Revision 1.12  1994/02/22  18:55:10  yuan
  56.  * Ambient lighting "shines" on doors too!
  57.  * 
  58.  * Revision 1.11  1994/02/17  12:05:55  matt
  59.  * Got rid of warnings
  60.  * 
  61.  * Revision 1.10  1994/02/16  22:28:03  mike
  62.  * fix ambient lighting and smoothing.
  63.  * 
  64.  * Revision 1.9  1994/02/14  12:05:42  mike
  65.  * change segment data structure.
  66.  * 
  67.  * Revision 1.8  1994/01/26  17:27:45  yuan
  68.  * Still not perfected ambient lighting
  69.  * 
  70.  * Revision 1.7  1994/01/25  17:58:08  yuan
  71.  * Added ambient lighting, and also added fixing bogus segments
  72.  * functions to the editor... (they don't work fully... need to
  73.  * check out seguvs.c
  74.  * 
  75.  * Revision 1.6  1994/01/24  11:46:10  yuan
  76.  * *** empty log message ***
  77.  * 
  78.  * Revision 1.5  1994/01/24  11:03:05  yuan
  79.  * Set lgiht maximum added... Changes are still in progress
  80.  * 
  81.  * Revision 1.4  1994/01/18  19:16:07  yuan
  82.  * Added assign default to lighting pad.
  83.  * 
  84.  * Revision 1.3  1993/12/17  12:26:00  mike
  85.  * Add functions for setting light values on whole segment at once.
  86.  * 
  87.  * Revision 1.2  1993/12/16  16:56:12  mike
  88.  * Add new texture map lighting control functions.
  89.  * 
  90.  * Revision 1.1  1993/12/16  13:21:50  mike
  91.  * Initial revision
  92.  * 
  93.  * 
  94.  */
  95.  
  96.  
  97. #pragma off (unreferenced)
  98. static char rcsid[] = "$Id: elight.c 2.0 1995/02/27 11:35:16 john Exp $";
  99. #pragma on (unreferenced)
  100.  
  101. #include <stdio.h>
  102. //#include <stdlib.h>
  103. //#include <stdarg.h>
  104. //#include <math.h>
  105. //#include <string.h>
  106.  
  107. #include "inferno.h"
  108. #include "segment.h"
  109. #include "editor.h"
  110. #include "seguvs.h"
  111.  
  112. #include "wall.h"
  113.  
  114. #include "textures.h"
  115.  
  116. #include "fix.h"
  117. #include "mono.h"
  118. #include "error.h"
  119. #include "kdefs.h"
  120. #include "gameseg.h"
  121.  
  122. #include "texmap.h"
  123.  
  124. // -----------------------------------------------------------------------------
  125. //    Return light intensity at an instance of a vertex on a side in a segment.
  126. fix get_light_intensity(segment *segp, int sidenum, int vert)
  127. {
  128.     Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
  129.     Assert(vert <= 3);
  130.  
  131.     return segp->sides[sidenum].uvls[vert].l;
  132. }
  133.  
  134. // -----------------------------------------------------------------------------
  135. //    Set light intensity at a vertex, saturating in .5 to 15.5
  136. void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
  137. {
  138.     Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
  139.     Assert(vert <= 3);
  140.  
  141.     if (intensity < MIN_LIGHTING_VALUE)
  142.         intensity = MIN_LIGHTING_VALUE;
  143.  
  144.     if (intensity > MAX_LIGHTING_VALUE)
  145.         intensity = MAX_LIGHTING_VALUE;
  146.  
  147.     segp->sides[sidenum].uvls[vert].l = intensity;
  148.  
  149.     Update_flags |= UF_WORLD_CHANGED;
  150. }
  151.  
  152.  
  153. // -----------------------------------------------------------------------------
  154. //    Add light intensity to a vertex, saturating in .5 to 15.5
  155. void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity)
  156. {
  157. //    fix    new_intensity;
  158.  
  159.     set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity);
  160. }
  161.  
  162.  
  163. // -----------------------------------------------------------------------------
  164. //    Recursively apply light to segments.
  165. //    If current side is a wall, apply light there.
  166. //    If not a wall, apply light to child through that wall.
  167. //    Notes:
  168. //        It is possible to enter a segment twice by taking different paths.  It is easy
  169. //        to prevent this by maintaining a list of visited segments, but it is important
  170. //        to reach segments with the greatest light intensity.  This can be done by doing
  171. //        a breadth-first-search, or by storing the applied intensity with a visited segment,
  172. //        and if the current intensity is brighter, then apply the difference between it and
  173. //        the previous intensity.
  174. //        Note that it is also possible to visit the original light-casting segment, for example
  175. //        going from segment 0 to 2, then from 2 to 0.  This is peculiar and probably not
  176. //        desired, but not entirely invalid.  2 reflects some light back to 0.
  177. void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth)
  178. {
  179.     int    wid_result;
  180.  
  181.     if (intensity == 0)
  182.         return;
  183.  
  184.     wid_result = WALL_IS_DOORWAY(segp, sidenum);
  185.     if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) {
  186.         int    v;
  187.         for (v=0; v<4; v++)                            // add light to this wall
  188.             add_light_intensity(segp, sidenum, v, intensity);
  189.         return;                                        // we return because there is a wall here, and light does not shine through walls
  190.     }
  191.  
  192.     //    No wall here, so apply light recursively
  193.     if (depth < 3) {
  194.         int    s;
  195.         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
  196.             apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1);
  197.     }
  198.  
  199. }
  200.  
  201. // -----------------------------------------------------------------------------
  202. //    Top level recursive function for applying light.
  203. //    Calls apply_light_intensity.
  204. //    Uses light value on segp:sidenum (tmap_num2 defines light value) and applies
  205. //    the associated intensity to segp.  It calls apply_light_intensity to apply intensity/3
  206. //    to all neighbors.  apply_light_intensity recursively calls itself to apply light to
  207. //    subsequent neighbors (and forming loops, see above).
  208. void propagate_light_intensity(segment *segp, int sidenum) 
  209. {
  210.     int        v,s;
  211.     fix        intensity;
  212.     short        texmap;
  213.  
  214.     intensity = 0;
  215.     texmap = segp->sides[sidenum].tmap_num;
  216.     intensity += TmapInfo[texmap].lighting;
  217.     texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff;
  218.     intensity += TmapInfo[texmap].lighting;
  219.  
  220.     if (intensity > 0) {
  221.         for (v=0; v<4; v++)
  222.             add_light_intensity(segp, sidenum, v, intensity);
  223.     
  224.         //    Now, for all sides which are not the same as sidenum (the side casting the light),
  225.         //    add a light value to them (if they have no children, ie, they have a wall there).
  226.         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
  227.             if (s != sidenum)
  228.                 apply_light_intensity(segp, s, intensity/2, 1);
  229.     }
  230.  
  231. }
  232.  
  233.  
  234. // -----------------------------------------------------------------------------
  235. //    Highest level function, bound to a key.  Apply ambient light to all segments based
  236. //    on user-defined light sources.
  237. void LightAmbientLighting()
  238. {
  239.     int seg, side;
  240.  
  241.     for (seg=0; seg<=Highest_segment_index; seg++)
  242.         for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
  243.             propagate_light_intensity(&Segments[seg], side);
  244. }
  245.  
  246.  
  247. // -----------------------------------------------------------------------------
  248. int LightSelectNextVertex(void)
  249. {
  250.     Curvert++;
  251.     if (Curvert >= 4)
  252.         Curvert = 0;
  253.  
  254.     Update_flags |= UF_WORLD_CHANGED;
  255.  
  256.     return    1;
  257. }
  258.  
  259. // -----------------------------------------------------------------------------
  260. int LightSelectNextEdge(void)
  261. {
  262.     Curedge++;
  263.     if (Curedge >= 4)
  264.         Curedge = 0;
  265.  
  266.     Update_flags |= UF_WORLD_CHANGED;
  267.  
  268.     return    1;
  269. }
  270.  
  271. // -----------------------------------------------------------------------------
  272. //    Copy intensity from current vertex to all other vertices on side.
  273. int LightCopyIntensity(void)
  274. {
  275.     int    v,intensity;
  276.  
  277.     intensity = get_light_intensity(Cursegp, Curside, Curvert);
  278.  
  279.     for (v=0; v<4; v++)
  280.         if (v != Curvert)
  281.             set_light_intensity(Cursegp, Curside, v, intensity);
  282.  
  283.     return    1;
  284. }
  285.  
  286. // -----------------------------------------------------------------------------
  287. //    Copy intensity from current vertex to all other vertices on side.
  288. int LightCopyIntensitySegment(void)
  289. {
  290.     int    s,v,intensity;
  291.  
  292.     intensity = get_light_intensity(Cursegp, Curside, Curvert);
  293.  
  294.     for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
  295.         for (v=0; v<4; v++)
  296.             if ((s != Curside) || (v != Curvert))
  297.                 set_light_intensity(Cursegp, s, v, intensity);
  298.  
  299.     return    1;
  300. }
  301.  
  302. // -----------------------------------------------------------------------------
  303. int LightDecreaseLightVertex(void)
  304. {
  305.     set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)-F1_0/NUM_LIGHTING_LEVELS);
  306.  
  307.     return    1;
  308. }
  309.  
  310. // -----------------------------------------------------------------------------
  311. int LightIncreaseLightVertex(void)
  312. {
  313.     set_light_intensity(Cursegp, Curside, Curvert, get_light_intensity(Cursegp, Curside, Curvert)+F1_0/NUM_LIGHTING_LEVELS);
  314.  
  315.     return    1;
  316. }
  317.  
  318. // -----------------------------------------------------------------------------
  319. int LightDecreaseLightSide(void)
  320. {
  321.     int    v;
  322.  
  323.     for (v=0; v<4; v++)
  324.         set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)-F1_0/NUM_LIGHTING_LEVELS);
  325.  
  326.     return    1;
  327. }
  328.  
  329. // -----------------------------------------------------------------------------
  330. int LightIncreaseLightSide(void)
  331. {
  332.     int    v;
  333.  
  334.     for (v=0; v<4; v++)
  335.         set_light_intensity(Cursegp, Curside, v, get_light_intensity(Cursegp, Curside, v)+F1_0/NUM_LIGHTING_LEVELS);
  336.  
  337.     return    1;
  338. }
  339.  
  340. // -----------------------------------------------------------------------------
  341. int LightDecreaseLightSegment(void)
  342. {
  343.     int    s,v;
  344.  
  345.     for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
  346.         for (v=0; v<4; v++)
  347.             set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)-F1_0/NUM_LIGHTING_LEVELS);
  348.  
  349.     return    1;
  350. }
  351.  
  352. // -----------------------------------------------------------------------------
  353. int LightIncreaseLightSegment(void)
  354. {
  355.     int    s,v;
  356.  
  357.     for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
  358.         for (v=0; v<4; v++)
  359.             set_light_intensity(Cursegp, s, v, get_light_intensity(Cursegp, s, v)+F1_0/NUM_LIGHTING_LEVELS);
  360.  
  361.     return    1;
  362. }
  363.  
  364. // -----------------------------------------------------------------------------
  365. int LightSetDefault(void)
  366. {
  367.     int    v;
  368.  
  369.     for (v=0; v<4; v++)
  370.         set_light_intensity(Cursegp, Curside, v, DEFAULT_LIGHTING);
  371.  
  372.     return    1;
  373. }
  374.  
  375.  
  376. // -----------------------------------------------------------------------------
  377. int LightSetMaximum(void)
  378. {
  379.     int    v;
  380.  
  381.     for (v=0; v<4; v++)
  382.         set_light_intensity(Cursegp, Curside, v, (NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS);
  383.  
  384.     return    1;
  385. }
  386.  
  387.  
  388. // -----------------------------------------------------------------------------
  389. int LightSetDefaultAll(void)
  390. {
  391.  
  392.     assign_default_lighting_all();
  393.  
  394.     Update_flags |= UF_WORLD_CHANGED;
  395.  
  396.     return    1;
  397. }
  398.  
  399.  
  400.  
  401.