home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / texmap / ntmap.c < prev    next >
Text File  |  1998-06-08  |  36KB  |  1,189 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/texmap/rcs/ntmap.c $
  15.  * $Revision: 1.52 $
  16.  * $Author: john $
  17.  * $Date: 1995/03/14 15:13:06 $
  18.  * 
  19.  * Start of conversion to new texture mapper.
  20.  * 
  21.  * $Log: ntmap.c $
  22.  * Revision 1.52  1995/03/14  15:13:06  john
  23.  * Increased MAX_Y_Pointers to 480.
  24.  * 
  25.  * Revision 1.51  1995/02/23  14:25:09  john
  26.  * Added editor tmap.
  27.  * 
  28.  * Revision 1.50  1995/02/20  18:22:58  john
  29.  * Put all the externs in the assembly modules into tmap_inc.asm.
  30.  * Also, moved all the C versions of the inner loops into a new module, 
  31.  * scanline.c.
  32.  * 
  33.  * Revision 1.49  1995/02/20  17:09:11  john
  34.  * Added code so that you can build the tmapper with no assembly!
  35.  * 
  36.  * Revision 1.48  1995/01/06  11:11:30  mike
  37.  * even when not in editor, have 400 lines in texture map scanline table.
  38.  * 
  39.  * Revision 1.47  1994/12/15  16:43:25  matt
  40.  * Took out code only needed by editor
  41.  * 
  42.  * Revision 1.46  1994/12/09  22:35:37  mike
  43.  * fix bug in before call to asm_tmap_scanline_per causing write of pixel onto past right border onto left.
  44.  * 
  45.  * Revision 1.45  1994/12/06  16:31:06  mike
  46.  * fix bug in asm_tmap_scanline_matt interface.
  47.  * 
  48.  * Revision 1.44  1994/12/04  20:37:18  mike
  49.  * *** empty log message ***
  50.  * 
  51.  * Revision 1.43  1994/12/02  23:30:04  mike
  52.  * optimizations.
  53.  * 
  54.  * Revision 1.42  1994/11/30  00:57:43  mike
  55.  * optimizations.
  56.  * 
  57.  * Revision 1.41  1994/11/28  13:34:27  mike
  58.  * optimizations.
  59.  * 
  60.  * Revision 1.40  1994/11/28  01:30:01  mike
  61.  * kill warning.
  62.  * 
  63.  * Revision 1.39  1994/11/28  01:28:59  mike
  64.  * optimizations.
  65.  * 
  66.  * Revision 1.38  1994/11/21  14:08:07  john
  67.  * Took out all multiple instead of divide code.
  68.  * 
  69.  * Revision 1.37  1994/11/19  15:21:52  mike
  70.  * rip out unused code.
  71.  * 
  72.  * Revision 1.36  1994/11/14  11:42:51  mike
  73.  * optimization.
  74.  * 
  75.  * Revision 1.35  1994/11/12  16:41:36  mike
  76.  * *** empty log message ***
  77.  * 
  78.  * Revision 1.34  1994/11/10  21:28:41  mike
  79.  * remove call to init_interface_vars_to_assembler.
  80.  * 
  81.  * Revision 1.33  1994/11/10  11:08:59  mike
  82.  * detail level stuff.
  83.  * 
  84.  * Revision 1.32  1994/11/09  22:55:52  matt
  85.  * Added variable Current_seg_depth for detail level optimization
  86.  * 
  87.  * Revision 1.31  1994/11/09  19:57:31  john
  88.  * Added texture rle caching.
  89.  * 
  90.  * Revision 1.30  1994/11/09  19:54:48  mike
  91.  * Call flat shader if Tmap_flat_flag set.
  92.  * 
  93.  * Revision 1.29  1994/11/02  21:33:31  john
  94.  * Added Burger Bill's optimization, ie.. 2 muls per 8 pixels.
  95.  * 
  96.  * Revision 1.28  1994/11/02  11:32:16  john
  97.  * Added code for c callable inner loop and code to 
  98.  * test dividing out z0.
  99.  * 
  100.  * Revision 1.27  1994/10/28  20:54:32  matt
  101.  * Added error checking
  102.  * 
  103.  * Revision 1.26  1994/10/25  11:20:20  mike
  104.  * fix bug in lighting overflow checking for one scanline tall linear texture maps.
  105.  * 
  106.  * Revision 1.25  1994/08/03  15:40:33  mike
  107.  * Prevent divide overflows, decrease occurrence of precision-caused glitches.
  108.  * 
  109.  * Revision 1.24  1994/07/27  09:31:16  mike
  110.  * Fix concave texture map problem, decrease occurrence of unimportant int 3.
  111.  * 
  112.  * Revision 1.23  1994/06/17  12:23:31  mike
  113.  * Support non-lighted texture maps.
  114.  * 
  115.  * Revision 1.22  1994/06/11  08:10:24  mike
  116.  * Fix mysterious hang bug, lighting value was out of range.
  117.  * 
  118.  * Revision 1.21  1994/06/09  16:10:16  mike
  119.  * Change SC2000 from constant to variable.
  120.  * 
  121.  */
  122.  
  123.  
  124. #pragma off (unreferenced)
  125. static char rcsid[] = "$Id: ntmap.c 1.52 1995/03/14 15:13:06 john Exp $";
  126. #pragma on (unreferenced)
  127.  
  128. #define VESA 0
  129. #define NUM_TMAPS 16
  130.  
  131. #define HEADLIGHT_LIGHTING 0
  132.  
  133. #define WIREFRAME 0
  134. #define PERSPECTIVE 1
  135.  
  136. #include <math.h>
  137. #include <limits.h>
  138. #include <stdio.h>
  139. #include <conio.h>
  140. #include <stdlib.h>
  141.  
  142. #include "mono.h"
  143. #include "fix.h"
  144. #include "3d.h"
  145. #include "gr.h"
  146. #include "error.h"
  147. #include "key.h"
  148.  
  149. #include "texmap.h"
  150. #include "texmapl.h"
  151. #include "rle.h"
  152. #include "scanline.h"
  153.  
  154. #include "..\main\textures.h"
  155.  
  156. #define    EDITOR_TMAP    1        //if in, include extra stuff
  157.  
  158. #define F15_5 (F1_0*15 + F0_5)
  159.  
  160. // 1 means enable special sc2000 code, else enable only for Descent
  161. #define    SC2000K    0
  162. int    SC2000 = SC2000K;
  163.  
  164. // Temporary texture map, interface from Matt's 3d system to Mike's texture mapper.
  165. g3ds_tmap Tmap1;
  166.  
  167. grs_bitmap Texmap_ptrs[NUM_TMAPS];
  168. grs_bitmap Texmap4_ptrs[NUM_TMAPS];
  169.  
  170. fix Range_max=0; // debug, kill me
  171.  
  172. int    Interpolation_method=0;    // 0 = choose best method
  173. int    Lighting_on;                // initialize to no lighting
  174. int    Tmap_flat_flag = 0;        //    1 = render texture maps as flat shaded polygons.
  175. int    Current_seg_depth;        // HACK INTERFACE: how far away the current segment (& thus texture) is
  176. int    Max_perspective_depth;
  177. int    Max_linear_depth;
  178. int    Max_flat_depth;
  179.  
  180. extern int Window_clip_left, Window_clip_bot, Window_clip_right, Window_clip_top;
  181.  
  182. // These variables are the interface to assembler.  They get set for each texture map, which is a real waste of time.
  183. //    They should be set only when they change, which is generally when the window bounds change.  And, even still, it's
  184. //    a pretty bad interface.
  185. int    bytes_per_row=-1;
  186. int    write_buffer;
  187. int      window_left;
  188. int    window_right;
  189. int    window_top;
  190. int    window_bottom;
  191. int      window_width;
  192. int      window_height;
  193. int    write_buffer;
  194. #ifdef EDITOR_TMAP
  195. #define    MAX_Y_POINTERS    480
  196. #else
  197. #define    MAX_Y_POINTERS    480
  198. #endif
  199. int    y_pointers[MAX_Y_POINTERS];
  200.  
  201. short    pixel_data_selector;        // selector for current pixel data for texture mapper
  202.  
  203. fix fix_recip[FIX_RECIP_TABLE_SIZE];
  204.  
  205. int    Lighting_enabled;
  206. int    Fix_recip_table_computed=0;
  207.  
  208. fix fx_l, fx_u, fx_v, fx_z, fx_du_dx, fx_dv_dx, fx_dz_dx, fx_dl_dx;
  209. int fx_xleft, fx_xright, fx_y;
  210. unsigned char * pixptr;
  211. int per2_flag = 0;
  212. int Transparency_on = 0;
  213. int dither_intensity_lighting = 0;
  214.  
  215. ubyte * tmap_flat_cthru_table;
  216. ubyte tmap_flat_color;
  217. ubyte tmap_flat_shade_value;
  218.  
  219.  
  220.  
  221. // -------------------------------------------------------------------------------------
  222. void init_fix_recip_table(void)
  223. {
  224.     int    i;
  225.  
  226.     fix_recip[0] = F1_0;
  227.  
  228.     for (i=1; i<FIX_RECIP_TABLE_SIZE; i++)
  229.         fix_recip[i] = F1_0/i;
  230.  
  231.     Fix_recip_table_computed = 1;
  232. }
  233.  
  234. // -------------------------------------------------------------------------------------
  235. //    Initialize interface variables to assembler.
  236. //    These things used to be constants.  This routine is now (10/6/93) getting called for
  237. //    every texture map.  It should get called whenever the window changes, or, preferably,
  238. //    not at all.  I'm pretty sure these variables are only being used for range checking.
  239. void init_interface_vars_to_assembler(void)
  240. {
  241.     grs_bitmap    *bp;
  242.  
  243.     bp = &grd_curcanv->cv_bitmap;
  244.  
  245.     Assert(bp!=NULL);
  246.     Assert(bp->bm_data!=NULL);
  247.     Assert(bp->bm_h <= MAX_Y_POINTERS);
  248.  
  249.     //    If bytes_per_row has changed, create new table of pointers.
  250.     if (bytes_per_row != (int) bp->bm_rowsize) {
  251.         int    y_val, i;
  252.  
  253.         bytes_per_row = (int) bp->bm_rowsize;
  254.  
  255.         y_val = 0;
  256.         for (i=0; i<MAX_Y_POINTERS; i++) {
  257.             y_pointers[i] = y_val;
  258.             y_val += bytes_per_row;
  259.         }
  260.     }
  261.  
  262.     write_buffer = (int) bp->bm_data;
  263.  
  264.     window_left = 0;
  265.     window_right = (int) bp->bm_w-1;
  266.     window_top = 0;
  267.     window_bottom = (int) bp->bm_h-1;
  268.  
  269.     Window_clip_left = window_left;
  270.     Window_clip_right = window_right;
  271.     Window_clip_top = window_top;
  272.     Window_clip_bot = window_bottom;
  273.  
  274.     window_width = bp->bm_w;
  275.     window_height = bp->bm_h;
  276.  
  277.     if (!Fix_recip_table_computed)
  278.         init_fix_recip_table();
  279. }
  280.  
  281. int tmap_set_selector(int selector, void *buffer, unsigned int size);
  282.  
  283. // -------------------------------------------------------------------------------------
  284. //                             VARIABLES
  285. extern short    pixel_data_selector;        // selector for current pixel data for texture mapper
  286. extern g3ds_tmap Tmap1;
  287.  
  288. // -------------------------------------------------------------------------------------
  289. //    Returns number preceding val modulo modulus.
  290. //    prevmod(3,4) = 2
  291. //    prevmod(0,4) = 3
  292. int prevmod(int val,int modulus)
  293. {
  294.     if (val > 0)
  295.         return val-1;
  296.     else
  297.         return modulus-1;
  298. //    return (val + modulus - 1) % modulus;
  299. }
  300.  
  301.  
  302. //    Returns number succeeding val modulo modulus.
  303. //    succmod(3,4) = 0
  304. //    succmod(0,4) = 1
  305. int succmod(int val,int modulus)
  306. {
  307.     if (val < modulus-1)
  308.         return val+1;
  309.     else
  310.         return 0;
  311.  
  312. //    return (val + 1) % modulus;
  313. }
  314.  
  315. // -------------------------------------------------------------------------------------
  316. //    Select topmost vertex (minimum y coordinate) and bottommost (maximum y coordinate) in
  317. //    texture map.  If either is part of a horizontal edge, then select leftmost vertex for
  318. //    top, rightmost vertex for bottom.
  319. //    Important: Vertex is selected with integer precision.  So, if there are vertices at
  320. //    (0.0,0.7) and (0.5,0.3), the first vertex is selected, because they y coordinates are
  321. //    considered the same, so the smaller x is favored.
  322. //    Parameters:
  323. //        nv        number of vertices
  324. //        v3d    pointer to 3d vertices containing u,v,x2d,y2d coordinates
  325. //    Results in:
  326. //        *min_y_ind
  327. //        *max_y_ind
  328. // -------------------------------------------------------------------------------------
  329. void compute_y_bounds(g3ds_tmap *t, int *vlt, int *vlb, int *vrt, int *vrb,int *bottom_y_ind)
  330. {
  331.     int    i;
  332.     int    min_y,max_y;
  333.     int    min_y_ind;
  334.     int    original_vrt;
  335.     fix    min_x;
  336.  
  337.     // Scan all vertices, set min_y_ind to vertex with smallest y coordinate.
  338.     min_y = f2i(t->verts[0].y2d);
  339.     max_y = min_y;
  340.     min_y_ind = 0;
  341.     min_x = f2i(t->verts[0].x2d);
  342.     *bottom_y_ind = 0;
  343.  
  344.     for (i=1; i<t->nv; i++) {
  345.         if (f2i(t->verts[i].y2d) < min_y) {
  346.             min_y = f2i(t->verts[i].y2d);
  347.             min_y_ind = i;
  348.             min_x = f2i(t->verts[i].x2d);
  349.         } else if (f2i(t->verts[i].y2d) == min_y) {
  350.             if (f2i(t->verts[i].x2d) < min_x) {
  351.                 min_y_ind = i;
  352.                 min_x = f2i(t->verts[i].x2d);
  353.             }
  354.         }
  355.         if (f2i(t->verts[i].y2d) > max_y) {
  356.             max_y = f2i(t->verts[i].y2d);
  357.             *bottom_y_ind = i;
  358.         }
  359.     }
  360.  
  361. //--removed mk, 11/27/94--    //    Check for a non-upright-hourglass polygon and fix, if necessary, by bashing a y coordinate.
  362. //--removed mk, 11/27/94--    //    min_y_ind = index of minimum y coordinate, *bottom_y_ind = index of maximum y coordinate
  363. //--removed mk, 11/27/94--{
  364. //--removed mk, 11/27/94--    int    max_temp, min_temp;
  365. //--removed mk, 11/27/94--
  366. //--removed mk, 11/27/94--    max_temp = *bottom_y_ind;
  367. //--removed mk, 11/27/94--    if (*bottom_y_ind < min_y_ind)
  368. //--removed mk, 11/27/94--        max_temp += t->nv;
  369. //--removed mk, 11/27/94--
  370. //--removed mk, 11/27/94--    for (i=min_y_ind; i<max_temp; i++) {
  371. //--removed mk, 11/27/94--        if (f2i(t->verts[i%t->nv].y2d) > f2i(t->verts[(i+1)%t->nv].y2d)) {
  372. //--removed mk, 11/27/94--            Int3();
  373. //--removed mk, 11/27/94--            t->verts[(i+1)%t->nv].y2d = t->verts[i%t->nv].y2d;
  374. //--removed mk, 11/27/94--        }
  375. //--removed mk, 11/27/94--    }
  376. //--removed mk, 11/27/94--
  377. //--removed mk, 11/27/94--    min_temp = min_y_ind;
  378. //--removed mk, 11/27/94--    if (min_y_ind < *bottom_y_ind)
  379. //--removed mk, 11/27/94--        min_temp += t->nv;
  380. //--removed mk, 11/27/94--
  381. //--removed mk, 11/27/94--    for (i=*bottom_y_ind; i<min_temp; i++) {
  382. //--removed mk, 11/27/94--        if (f2i(t->verts[i%t->nv].y2d) < f2i(t->verts[(i+1)%t->nv].y2d)) {
  383. //--removed mk, 11/27/94--            Int3();
  384. //--removed mk, 11/27/94--            t->verts[(i+1)%t->nv].y2d = t->verts[i%t->nv].y2d;
  385. //--removed mk, 11/27/94--        }
  386. //--removed mk, 11/27/94--    }
  387. //--removed mk, 11/27/94--}
  388.  
  389.     // Set "vertex left top", etc. based on vertex with topmost y coordinate
  390.     *vlt = min_y_ind;
  391.     *vrt = *vlt;
  392.     *vlb = prevmod(*vlt,t->nv);
  393.     *vrb = succmod(*vrt,t->nv);
  394.  
  395.     // If right edge is horizontal, then advance along polygon bound until it no longer is or until all
  396.     // vertices have been examined.
  397.     // (Left edge cannot be horizontal, because *vlt is set to leftmost point with highest y coordinate.)
  398.  
  399.     original_vrt = *vrt;
  400.  
  401.     while (f2i(t->verts[*vrt].y2d) == f2i(t->verts[*vrb].y2d)) {
  402.         if (succmod(*vrt,t->nv) == original_vrt) {
  403.             break;
  404.         }
  405.         *vrt = succmod(*vrt,t->nv);
  406.         *vrb = succmod(*vrt,t->nv);
  407.     }
  408. }
  409.  
  410. // -------------------------------------------------------------------------------------
  411. //    Returns dx/dy given two vertices.
  412. //    If dy == 0, returns 0.0
  413. // -------------------------------------------------------------------------------------
  414. //--fix compute_dx_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  415. //--{
  416. //--    int    dy;
  417. //--
  418. //--    // compute delta x with respect to y for any edge
  419. //--    dy = f2i(t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) + 1;
  420. //--    if (dy)
  421. //--        return (t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d) / dy;
  422. //--    else
  423. //--        return 0;
  424. //--
  425. //--}
  426.  
  427. fix compute_du_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  428. {
  429.     return fixmul(t->verts[bottom_vertex].u - t->verts[top_vertex].u, recip_dy);
  430. }
  431.  
  432.  
  433. fix compute_dv_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  434. {
  435.     return fixmul(t->verts[bottom_vertex].v - t->verts[top_vertex].v, recip_dy);
  436. }
  437.  
  438. fix compute_dl_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  439. {
  440.     return fixmul(t->verts[bottom_vertex].l - t->verts[top_vertex].l, recip_dy);
  441.  
  442. }
  443.  
  444. fix compute_dx_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  445. {
  446.     return fixmul(t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d, recip_dy);
  447. }
  448.  
  449. fix compute_du_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  450. {
  451.     return fixmul(fixmul(t->verts[bottom_vertex].u,t->verts[bottom_vertex].z) - fixmul(t->verts[top_vertex].u,t->verts[top_vertex].z), recip_dy);
  452. }
  453.  
  454.  
  455. fix compute_dv_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  456. {
  457.     return fixmul(fixmul(t->verts[bottom_vertex].v,t->verts[bottom_vertex].z) - fixmul(t->verts[top_vertex].v,t->verts[top_vertex].z), recip_dy);
  458.  
  459. }
  460.  
  461. fix compute_dz_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  462. {
  463.     return fixmul(t->verts[bottom_vertex].z - t->verts[top_vertex].z, recip_dy);
  464.  
  465. }
  466. int Skip_short_flag=0;
  467.  
  468. // -------------------------------------------------------------------------------------
  469. //    Texture map current scanline in perspective.
  470. // -------------------------------------------------------------------------------------
  471. void ntmap_scanline_lighted(grs_bitmap *srcb, int y, fix xleft, fix xright, fix uleft, fix uright, fix vleft, fix vright, fix zleft, fix zright, fix lleft, fix lright)
  472. {
  473.     fix    u,v,l;
  474.     fix    dx,recip_dx;
  475.  
  476.     fix    du_dx,dv_dx,dz_dx,z;
  477.  
  478.     u = uleft;
  479.     v = vleft;
  480.     l = lleft;
  481.  
  482.     fx_xright = f2i(xright);
  483.     fx_xleft = f2i(xleft);
  484.  
  485.     dx = fx_xright - fx_xleft;
  486.     if ((dx < 0) || (xright < 0) || (xleft > xright))        // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  487.         return;
  488.  
  489.     // setup to call assembler scanline renderer
  490.     if (dx < FIX_RECIP_TABLE_SIZE)
  491.         recip_dx = fix_recip[dx];
  492.     else
  493.         recip_dx = F1_0/dx;
  494.  
  495.     du_dx = fixmul(uright - uleft,recip_dx);
  496.     dv_dx = fixmul(vright - vleft,recip_dx);
  497.     dz_dx = fixmul(zright - zleft,recip_dx);
  498.  
  499.     z = zleft;
  500.  
  501.     fx_u = uleft;
  502.     fx_v = vleft;
  503.     fx_z = zleft;
  504.     fx_du_dx = du_dx;
  505.     fx_dv_dx = dv_dx;
  506.     fx_dz_dx = dz_dx;
  507.     fx_y = y;
  508.     pixptr = srcb->bm_data;
  509.  
  510.     switch (Lighting_enabled) {
  511.         case 0:
  512.             if (fx_xleft > Window_clip_right)
  513.                 return;
  514.             if (fx_xright < Window_clip_left)
  515.                 return;
  516.             if (fx_xright > Window_clip_right)
  517.                 fx_xright = Window_clip_right;
  518.             
  519.             #ifdef NASM
  520.                 c_tmap_scanline_per_nolight();
  521.             #else
  522.                 asm_tmap_scanline_per();
  523.             #endif
  524.             break;
  525.         case 1: {
  526.             fix    mul_thing;
  527.  
  528.             if (lleft < 0) lleft = 0;
  529.             if (lright < 0) lright = 0;
  530.             if (lleft > (NUM_LIGHTING_LEVELS*F1_0-F1_0/2)) lleft = (NUM_LIGHTING_LEVELS*F1_0-F1_0/2);
  531.             if (lright > (NUM_LIGHTING_LEVELS*F1_0-F1_0/2)) lright = (NUM_LIGHTING_LEVELS*F1_0-F1_0/2);
  532.  
  533.             fx_l = lleft;
  534.             fx_dl_dx = fixmul(lright - lleft,recip_dx);
  535.  
  536.             //    This is a pretty ugly hack to prevent lighting overflows.
  537.             mul_thing = dx * fx_dl_dx;
  538.             if (lleft + mul_thing < 0)
  539.                 fx_dl_dx += 12;
  540.             else if (lleft + mul_thing > (NUM_LIGHTING_LEVELS*F1_0-F1_0/2))
  541.                 fx_dl_dx -= 12;
  542.  
  543.             if (fx_xleft > Window_clip_right)
  544.                 return;
  545.             if (fx_xright < Window_clip_left)
  546.                 return;
  547.             if (fx_xright > Window_clip_right)
  548.                 fx_xright = Window_clip_right;
  549.  
  550.             #ifdef NASM
  551.                 c_tmap_scanline_per();
  552.             #else
  553.                 asm_tmap_scanline_per();
  554.             #endif
  555.             break;
  556.         }
  557.         case 2:
  558. #ifdef EDITOR_TMAP
  559.             fx_xright = f2i(xright);
  560.             fx_xleft = f2i(xleft);
  561.  
  562.             asm_tmap_scanline_matt();
  563. #else
  564.             Int3();    //    Illegal, called an editor only routine!
  565. #endif
  566.             break;
  567.     }
  568.  
  569. }
  570.  
  571. int Do_vertical_scan=0;
  572.  
  573. int    Break_on_flat=0;
  574.  
  575. // -------------------------------------------------------------------------------------
  576. //    Render a texture map with lighting using perspective interpolation in inner and outer loops.
  577. // -------------------------------------------------------------------------------------
  578. void ntexture_map_lighted(grs_bitmap *srcb, g3ds_tmap *t)
  579. {
  580.     int    vlt,vrt,vlb,vrb;    // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  581.     int    topy,boty,y, dy;
  582.     fix    dx_dy_left,dx_dy_right;
  583.     fix    du_dy_left,du_dy_right;
  584.     fix    dv_dy_left,dv_dy_right;
  585.     fix    dz_dy_left,dz_dy_right;
  586.     fix    dl_dy_left,dl_dy_right;
  587.     fix    recip_dyl, recip_dyr;
  588.     int    max_y_vertex;
  589.     fix    xleft,xright,uleft,vleft,uright,vright,zleft,zright,lleft,lright;
  590.     int    next_break_left, next_break_right;
  591.  
  592.     g3ds_vertex *v3d;
  593.  
  594.     v3d = t->verts;
  595.  
  596. #if SC2000K
  597. if (Do_vertical_scan) {
  598.     texture_map_hyp_lin_v(srcb, t);
  599.     return;
  600. }
  601. #endif
  602.  
  603.     // Determine top and bottom y coords.
  604.     compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex);
  605.  
  606.     // Set top and bottom (of entire texture map) y coordinates.
  607.     topy = f2i(v3d[vlt].y2d);
  608.     boty = f2i(v3d[max_y_vertex].y2d);
  609.     if (topy > Window_clip_bot)
  610.         return;
  611.     if (boty > Window_clip_bot)
  612.         boty = Window_clip_bot;
  613.  
  614.     // Set amount to change x coordinate for each advance to next scanline.
  615.     dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  616.     if (dy < FIX_RECIP_TABLE_SIZE)
  617.         recip_dyl = fix_recip[dy];
  618.     else
  619.         recip_dyl = F1_0/dy;
  620.  
  621.     dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dyl);
  622.     du_dy_left = compute_du_dy(t,vlt,vlb, recip_dyl);
  623.     dv_dy_left = compute_dv_dy(t,vlt,vlb, recip_dyl);
  624.     dz_dy_left = compute_dz_dy(t,vlt,vlb, recip_dyl);
  625.  
  626.     dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  627.     if (dy < FIX_RECIP_TABLE_SIZE)
  628.         recip_dyr = fix_recip[dy];
  629.     else
  630.         recip_dyr = F1_0/dy;
  631.  
  632.     du_dy_right = compute_du_dy(t,vrt,vrb, recip_dyr);
  633.     dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dyr);
  634.     dv_dy_right = compute_dv_dy(t,vrt,vrb, recip_dyr);
  635.     dz_dy_right = compute_dz_dy(t,vrt,vrb, recip_dyr);
  636.  
  637.     if (Lighting_enabled) {
  638.         dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dyl);
  639.         dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dyr);
  640.  
  641.         lleft = v3d[vlt].l;
  642.         lright = v3d[vrt].l;
  643.     }
  644.  
  645.      // Set initial values for x, u, v
  646.     xleft = v3d[vlt].x2d;
  647.     xright = v3d[vrt].x2d;
  648.  
  649.     zleft = v3d[vlt].z;
  650.     zright = v3d[vrt].z;
  651.  
  652.     uleft = fixmul(v3d[vlt].u,zleft);
  653.     uright = fixmul(v3d[vrt].u,zright);
  654.     vleft = fixmul(v3d[vlt].v,zleft);
  655.     vright = fixmul(v3d[vrt].v,zright);
  656.  
  657.     // scan all rows in texture map from top through first break.
  658.     next_break_left = f2i(v3d[vlb].y2d);
  659.     next_break_right = f2i(v3d[vrb].y2d);
  660.  
  661.     for (y = topy; y < boty; y++) {
  662.  
  663.         // See if we have reached the end of the current left edge, and if so, set
  664.         // new values for dx_dy and x,u,v
  665.         if (y == next_break_left) {
  666.             fix    recip_dy;
  667.  
  668.             // Handle problem of double points.  Search until y coord is different.  Cannot get
  669.             // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  670.             // because in the for loop, we don't scan all spanlines.
  671.             while (y == f2i(v3d[vlb].y2d)) {
  672.                 vlt = vlb;
  673.                 vlb = prevmod(vlb,t->nv);
  674.             }
  675.             next_break_left = f2i(v3d[vlb].y2d);
  676.  
  677.             dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  678.             if (dy < FIX_RECIP_TABLE_SIZE)
  679.                 recip_dy = fix_recip[dy];
  680.             else
  681.                 recip_dy = F1_0/dy;
  682.  
  683.             dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
  684.  
  685.             xleft = v3d[vlt].x2d;
  686.             zleft = v3d[vlt].z;
  687.             uleft = fixmul(v3d[vlt].u,zleft);
  688.             vleft = fixmul(v3d[vlt].v,zleft);
  689.             lleft = v3d[vlt].l;
  690.  
  691.             du_dy_left = compute_du_dy(t,vlt,vlb, recip_dy);
  692.             dv_dy_left = compute_dv_dy(t,vlt,vlb, recip_dy);
  693.             dz_dy_left = compute_dz_dy(t,vlt,vlb, recip_dy);
  694.  
  695.             if (Lighting_enabled) {
  696.                 dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dy);
  697.                 lleft = v3d[vlt].l;
  698.             }
  699.         }
  700.  
  701.         // See if we have reached the end of the current left edge, and if so, set
  702.         // new values for dx_dy and x.  Not necessary to set new values for u,v.
  703.         if (y == next_break_right) {
  704.             fix    recip_dy;
  705.  
  706.             while (y == f2i(v3d[vrb].y2d)) {
  707.                 vrt = vrb;
  708.                 vrb = succmod(vrb,t->nv);
  709.             }
  710.  
  711.             next_break_right = f2i(v3d[vrb].y2d);
  712.  
  713.             dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  714.             if (dy < FIX_RECIP_TABLE_SIZE)
  715.                 recip_dy = fix_recip[dy];
  716.             else
  717.                 recip_dy = F1_0/dy;
  718.  
  719.             dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
  720.  
  721.             xright = v3d[vrt].x2d;
  722.             zright = v3d[vrt].z;
  723.             uright = fixmul(v3d[vrt].u,zright);
  724.             vright = fixmul(v3d[vrt].v,zright);
  725.  
  726.             du_dy_right = compute_du_dy(t,vrt,vrb, recip_dy);
  727.             dv_dy_right = compute_dv_dy(t,vrt,vrb, recip_dy);
  728.             dz_dy_right = compute_dz_dy(t,vrt,vrb, recip_dy);
  729.  
  730.             if (Lighting_enabled) {
  731.                 dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dy);
  732.                 lright = v3d[vrt].l;
  733.             }
  734.         }
  735.  
  736.         if (Lighting_enabled) {
  737.             if (y >= Window_clip_top)
  738.                 ntmap_scanline_lighted(srcb,y,xleft,xright,uleft,uright,vleft,vright,zleft,zright,lleft,lright);
  739.             lleft += dl_dy_left;
  740.             lright += dl_dy_right;
  741.         } else
  742.             if (y >= Window_clip_top)
  743.                 ntmap_scanline_lighted(srcb,y,xleft,xright,uleft,uright,vleft,vright,zleft,zright,lleft,lright);
  744.  
  745.         uleft += du_dy_left;
  746.         vleft += dv_dy_left;
  747.  
  748.         uright += du_dy_right;
  749.         vright += dv_dy_right;
  750.  
  751.         xleft += dx_dy_left;
  752.         xright += dx_dy_right;
  753.  
  754.         zleft += dz_dy_left;
  755.         zright += dz_dy_right;
  756.  
  757.     }
  758.  
  759.     // We can get lleft or lright out of bounds here because we compute dl_dy using fixed point values,
  760.     //    but we plot an integer number of scanlines, therefore doing an integer number of additions of the delta.
  761.  
  762. //if (Break_on_flat)
  763. //    mprintf(0, "[%i %i %i] ", y, f2i(xleft), f2i(xright));
  764.  
  765.     ntmap_scanline_lighted(srcb,y,xleft,xright,uleft,uright,vleft,vright,zleft,zright,lleft,lright);
  766. }
  767.  
  768.  
  769. // -------------------------------------------------------------------------------------
  770. //    Texture map current scanline using linear interpolation.
  771. // -------------------------------------------------------------------------------------
  772. void ntmap_scanline_lighted_linear(grs_bitmap *srcb, int y, fix xleft, fix xright, fix uleft, fix uright, fix vleft, fix vright, fix lleft, fix lright)
  773. {
  774.     fix    u,v,l;
  775.     fix    dx,recip_dx;
  776.  
  777.     fix    du_dx,dv_dx,dl_dx;
  778.  
  779.     u = uleft;
  780.     v = vleft;
  781.     l = lleft;
  782.  
  783.     dx = f2i(xright) - f2i(xleft);
  784.     if ((dx < 0) || (xright < 0) || (xleft > xright))        // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  785.         return;
  786.  
  787.         // setup to call assembler scanline renderer
  788.         if (dx < FIX_RECIP_TABLE_SIZE)
  789.             recip_dx = fix_recip[dx];
  790.         else
  791.             recip_dx = F1_0/dx;
  792.  
  793.         du_dx = fixmul(uright - uleft,recip_dx);
  794.         dv_dx = fixmul(vright - vleft,recip_dx);
  795.  
  796.         fx_u = uleft;
  797.         fx_v = vleft;
  798.         fx_du_dx = du_dx;
  799.         fx_dv_dx = dv_dx;
  800.         fx_y = y;
  801.         fx_xright = f2i(xright);
  802.         fx_xleft = f2i(xleft);
  803.         pixptr = srcb->bm_data;
  804.  
  805.         switch (Lighting_enabled) {
  806.             case 0:
  807.                 #ifdef NASM
  808.                     c_tmap_scanline_lin_nolight();
  809.                 #else
  810.                     asm_tmap_scanline_lin();
  811.                 #endif
  812.                 break;
  813.             case 1:
  814.                 if (lleft < F1_0/2)
  815.                     lleft = F1_0/2;
  816.                 if (lright < F1_0/2)
  817.                     lright = F1_0/2;
  818.  
  819.                 if (lleft > MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS)
  820.                     lleft = MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS;
  821.                 if (lright > MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS)
  822.                     lright = MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS;
  823.  
  824.                 fx_l = lleft;
  825.                 dl_dx = fixmul(lright - lleft,recip_dx);
  826.                 fx_dl_dx = dl_dx;
  827.                 #ifdef NASM
  828.                     c_tmap_scanline_lin();
  829.                 #else
  830.                     asm_tmap_scanline_lin_lighted();
  831.                 #endif
  832.                 break;
  833.             case 2:
  834. #ifdef EDITOR_TMAP
  835.                 fx_xright = f2i(xright);
  836.                 fx_xleft = f2i(xleft);
  837.                 asm_tmap_scanline_matt();
  838. #else
  839.                 Int3();    //    Illegal, called an editor only routine!
  840. #endif
  841.                 break;
  842.         }
  843. }
  844.  
  845. // -------------------------------------------------------------------------------------
  846. //    Render a texture map with lighting using perspective interpolation in inner and outer loops.
  847. // -------------------------------------------------------------------------------------
  848. void ntexture_map_lighted_linear(grs_bitmap *srcb, g3ds_tmap *t)
  849. {
  850.     int    vlt,vrt,vlb,vrb;    // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  851.     int    topy,boty,y, dy;
  852.     fix    dx_dy_left,dx_dy_right;
  853.     fix    du_dy_left,du_dy_right;
  854.     fix    dv_dy_left,dv_dy_right;
  855.     fix    dl_dy_left,dl_dy_right;
  856.     int    max_y_vertex;
  857.     fix    xleft,xright,uleft,vleft,uright,vright,lleft,lright;
  858.     int    next_break_left, next_break_right;
  859.     fix    recip_dyl, recip_dyr;
  860.  
  861.     g3ds_vertex *v3d;
  862.  
  863.     v3d = t->verts;
  864.  
  865.     // Determine top and bottom y coords.
  866.     compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex);
  867.  
  868.     // Set top and bottom (of entire texture map) y coordinates.
  869.     topy = f2i(v3d[vlt].y2d);
  870.     boty = f2i(v3d[max_y_vertex].y2d);
  871.  
  872.     if (topy > Window_clip_bot)
  873.         return;
  874.     if (boty > Window_clip_bot)
  875.         boty = Window_clip_bot;
  876.  
  877.     dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  878.     if (dy < FIX_RECIP_TABLE_SIZE)
  879.         recip_dyl = fix_recip[dy];
  880.     else
  881.         recip_dyl = F1_0/dy;
  882.  
  883.     dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  884.     if (dy < FIX_RECIP_TABLE_SIZE)
  885.         recip_dyr = fix_recip[dy];
  886.     else
  887.         recip_dyr = F1_0/dy;
  888.  
  889.     // Set amount to change x coordinate for each advance to next scanline.
  890.     dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dyl);
  891.     dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dyr);
  892.  
  893.     du_dy_left = compute_du_dy_lin(t,vlt,vlb, recip_dyl);
  894.     du_dy_right = compute_du_dy_lin(t,vrt,vrb, recip_dyr);
  895.  
  896.     dv_dy_left = compute_dv_dy_lin(t,vlt,vlb, recip_dyl);
  897.     dv_dy_right = compute_dv_dy_lin(t,vrt,vrb, recip_dyr);
  898.  
  899.     if (Lighting_enabled) {
  900.         dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dyl);
  901.         dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dyr);
  902.  
  903.         lleft = v3d[vlt].l;
  904.         lright = v3d[vrt].l;
  905.     }
  906.  
  907.      // Set initial values for x, u, v
  908.     xleft = v3d[vlt].x2d;
  909.     xright = v3d[vrt].x2d;
  910.  
  911.     uleft = v3d[vlt].u;
  912.     uright = v3d[vrt].u;
  913.     vleft = v3d[vlt].v;
  914.     vright = v3d[vrt].v;
  915.  
  916.     // scan all rows in texture map from top through first break.
  917.     next_break_left = f2i(v3d[vlb].y2d);
  918.     next_break_right = f2i(v3d[vrb].y2d);
  919.  
  920.     for (y = topy; y < boty; y++) {
  921.  
  922.         // See if we have reached the end of the current left edge, and if so, set
  923.         // new values for dx_dy and x,u,v
  924.         if (y == next_break_left) {
  925.             fix    recip_dy;
  926.  
  927.             // Handle problem of double points.  Search until y coord is different.  Cannot get
  928.             // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  929.             // because in the for loop, we don't scan all spanlines.
  930.             while (y == f2i(v3d[vlb].y2d)) {
  931.                 vlt = vlb;
  932.                 vlb = prevmod(vlb,t->nv);
  933.             }
  934.             next_break_left = f2i(v3d[vlb].y2d);
  935.  
  936.             dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  937.             if (dy < FIX_RECIP_TABLE_SIZE)
  938.                 recip_dy = fix_recip[dy];
  939.             else
  940.                 recip_dy = F1_0/dy;
  941.  
  942.             dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
  943.  
  944.             xleft = v3d[vlt].x2d;
  945.             uleft = v3d[vlt].u;
  946.             vleft = v3d[vlt].v;
  947.             lleft = v3d[vlt].l;
  948.  
  949.             du_dy_left = compute_du_dy_lin(t,vlt,vlb, recip_dy);
  950.             dv_dy_left = compute_dv_dy_lin(t,vlt,vlb, recip_dy);
  951.  
  952.             if (Lighting_enabled) {
  953.                 dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dy);
  954.                 lleft = v3d[vlt].l;
  955.             }
  956.         }
  957.  
  958.         // See if we have reached the end of the current left edge, and if so, set
  959.         // new values for dx_dy and x.  Not necessary to set new values for u,v.
  960.         if (y == next_break_right) {
  961.             fix    recip_dy;
  962.  
  963.             while (y == f2i(v3d[vrb].y2d)) {
  964.                 vrt = vrb;
  965.                 vrb = succmod(vrb,t->nv);
  966.             }
  967.  
  968.             dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  969.             if (dy < FIX_RECIP_TABLE_SIZE)
  970.                 recip_dy = fix_recip[dy];
  971.             else
  972.                 recip_dy = F1_0/dy;
  973.  
  974.             next_break_right = f2i(v3d[vrb].y2d);
  975.             dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
  976.  
  977.             xright = v3d[vrt].x2d;
  978.             uright = v3d[vrt].u;
  979.             vright = v3d[vrt].v;
  980.  
  981.             du_dy_right = compute_du_dy_lin(t,vrt,vrb, recip_dy);
  982.             dv_dy_right = compute_dv_dy_lin(t,vrt,vrb, recip_dy);
  983.  
  984.             if (Lighting_enabled) {
  985.                 dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dy);
  986.                 lright = v3d[vrt].l;
  987.             }
  988.         }
  989.  
  990.         if (Lighting_enabled) {
  991.             ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright);
  992.             lleft += dl_dy_left;
  993.             lright += dl_dy_right;
  994.         } else
  995.             ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright);
  996.  
  997.         uleft += du_dy_left;
  998.         vleft += dv_dy_left;
  999.  
  1000.         uright += du_dy_right;
  1001.         vright += dv_dy_right;
  1002.  
  1003.         xleft += dx_dy_left;
  1004.         xright += dx_dy_right;
  1005.  
  1006.     }
  1007.  
  1008.     // We can get lleft or lright out of bounds here because we compute dl_dy using fixed point values,
  1009.     //    but we plot an integer number of scanlines, therefore doing an integer number of additions of the delta.
  1010.  
  1011.     ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright);
  1012. }
  1013.  
  1014. // fix    DivNum = F1_0*12;
  1015.  
  1016. extern void draw_tmap_flat(grs_bitmap *bp,int nverts,g3s_point **vertbuf);
  1017.  
  1018. // -------------------------------------------------------------------------------------
  1019. // Interface from Matt's data structures to Mike's texture mapper.
  1020. // -------------------------------------------------------------------------------------
  1021. void draw_tmap(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
  1022. {
  1023.     int    i;
  1024.  
  1025.     //    These variables are used in system which renders texture maps which lie on one scanline as a line.
  1026. #if SC2000K
  1027.     int    flat_flag;                            // Set to 1 and remains 1 so long as all y coords are the same (in integer portion).
  1028.     int    last_y;                                // Y coordinate of previous vertex.
  1029.     fix    min_x = 0xfff0000, max_x = 0;    // Minimum and maximum bounds of line to render in place of flat texture map.
  1030. #endif
  1031.     // fix    div_numerator;
  1032.     int    lighting_on_save = Lighting_on;
  1033.  
  1034.     Assert(nverts <= MAX_TMAP_VERTS);
  1035.  
  1036.  
  1037. #ifdef USE_MULT_CODE
  1038.     if ( !divide_table_filled ) fill_divide_table();
  1039. #endif
  1040.  
  1041.     // -- now called from g3_start_frame -- init_interface_vars_to_assembler();
  1042.  
  1043.     //    If no transparency and seg depth is large, render as flat shaded.
  1044.     if ((Current_seg_depth > Max_linear_depth) && ((bp->bm_flags & 3) == 0)) {
  1045.         draw_tmap_flat(bp, nverts, vertbuf);
  1046.         return;
  1047.     }
  1048.  
  1049.     if ( bp->bm_flags & BM_FLAG_RLE )
  1050.         bp = rle_expand_texture( bp );        // Expand if rle'd
  1051.  
  1052.     Transparency_on = bp->bm_flags & BM_FLAG_TRANSPARENT;
  1053.     if (bp->bm_flags & BM_FLAG_NO_LIGHTING)
  1054.         Lighting_on = 0;
  1055.  
  1056.     //    Set selector for current texture map.
  1057.     if ( bp->bm_selector == 0 )    {
  1058.         if (gr_bitmap_assign_selector( bp ) )
  1059.             Error( "Couldn't assign selector in ntmap.c!\n" );
  1060.     }
  1061.     pixel_data_selector = bp->bm_selector;
  1062.  
  1063.     // Setup texture map in Tmap1
  1064.     Tmap1.nv = nverts;                        // Initialize number of vertices
  1065.  
  1066. #if SC2000K
  1067.     last_y = f2i(vertbuf[0]->p3_sy);
  1068.     flat_flag = 1;                                // Says so far, this texture map exists all on one scan line
  1069. #endif
  1070. //     div_numerator = DivNum;    //f1_0*3;
  1071.  
  1072.     for (i=0; i<nverts; i++) {
  1073.         g3ds_vertex    *tvp = &Tmap1.verts[i];
  1074.         g3s_point    *vp = vertbuf[i];
  1075.  
  1076.         tvp->x2d = vp->p3_sx;
  1077.         tvp->y2d = vp->p3_sy;
  1078.  
  1079. #if SC2000K
  1080.         //    If y coordinates are not the same (in integer portion), then this texture map is not all on one scan line
  1081.         if (f2i(tvp->y2d) != last_y)
  1082.             flat_flag = 0;
  1083.  
  1084.         // If everything is flat so far, set minimum x and y for rendering a scanline
  1085.         if (flat_flag) {
  1086.             if (tvp->x2d < min_x)
  1087.                 min_x = tvp->x2d;
  1088.  
  1089.             if (tvp->x2d > max_x)
  1090.                 max_x = tvp->x2d;
  1091.         }
  1092. #endif
  1093.         //    Check for overflow on fixdiv.  Will overflow on vp->z <= something small.  Allow only as low as 256.
  1094.         if (vp->z < 256) {
  1095.             vp->z = 256;
  1096.             // Int3();        // we would overflow if we divided!
  1097.         }
  1098.  
  1099.         tvp->z = fixdiv(F1_0*12, vp->z);
  1100.          tvp->u = vp->p3_u << 6; //* bp->bm_w;
  1101.         tvp->v = vp->p3_v << 6; //* bp->bm_h;
  1102.  
  1103.         Assert(Lighting_on < 3);
  1104.  
  1105.         if (Lighting_on)
  1106.             tvp->l = vp->p3_l * NUM_LIGHTING_LEVELS;
  1107.     }
  1108.  
  1109. #if SC2000K
  1110.     // Render a horizontal line instead of a texture map if flat_flag still set (all vertices on one scanline).
  1111.     if (SC2000 && flat_flag) {
  1112.         fix y,cvw;
  1113.  
  1114.         Int3();
  1115.         y = Tmap1.verts[0].y2d;
  1116.         cvw = i2f(grd_curcanv->cv_bitmap.bm_w-1);
  1117.  
  1118.         if (y<0 || y>i2f(grd_curcanv->cv_bitmap.bm_h-1)) { Lighting_on = lighting_on_save; return; }
  1119.  
  1120.         //if (min_x < 0) min_x = 0;
  1121.         //if (max_x > cvw) max_x = cvw;
  1122.  
  1123.         gr_setcolor(*(bp->bm_data+32*32+32));                // Read center pixel of 64x64 bitmap, use as line color.
  1124.         gr_line(min_x, Tmap1.verts[0].y2d, max_x, Tmap1.verts[0].y2d);
  1125.  
  1126.         Lighting_on = lighting_on_save;
  1127.         return;
  1128.     }
  1129. #endif
  1130.  
  1131.     Lighting_enabled = Lighting_on;
  1132.  
  1133.     // Now, call my texture mapper.
  1134.     if (Lighting_on) {
  1135.         switch (Interpolation_method) {    // 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
  1136.             case 0:                                // choose best interpolation
  1137.                 per2_flag = 1;
  1138.                 if (Current_seg_depth > Max_perspective_depth)
  1139.                     ntexture_map_lighted_linear(bp, &Tmap1);
  1140.                 else
  1141.                     ntexture_map_lighted(bp, &Tmap1);
  1142.                 break;
  1143.             case 1:                                // linear interpolation
  1144.                 per2_flag = 1;
  1145.                 ntexture_map_lighted_linear(bp, &Tmap1);
  1146.                 break;
  1147.             case 2:                                // perspective every 8th pixel interpolation
  1148.                 per2_flag = 1;
  1149.                 ntexture_map_lighted(bp, &Tmap1);
  1150.                 break;
  1151.             case 3:                                // perspective every pixel interpolation
  1152.                 per2_flag = 0;                    // this hack means do divide every pixel
  1153.                 ntexture_map_lighted(bp, &Tmap1);
  1154.                 break;
  1155.             default:
  1156.                 Assert(0);                // Illegal value for Interpolation_method, must be 0,1,2,3
  1157.         }
  1158.     } else {
  1159.         switch (Interpolation_method) {    // 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
  1160.             case 0:                                // choose best interpolation
  1161.                 per2_flag = 1;
  1162.                 if (Current_seg_depth > Max_perspective_depth)
  1163.                     ntexture_map_lighted_linear(bp, &Tmap1);
  1164.                 else
  1165.                     ntexture_map_lighted(bp, &Tmap1);
  1166.                 break;
  1167.             case 1:                                // linear interpolation
  1168.                 per2_flag = 1;
  1169.                 ntexture_map_lighted_linear(bp, &Tmap1);
  1170.                 break;
  1171.             case 2:                                // perspective every 8th pixel interpolation
  1172.                 per2_flag = 1;
  1173.                 ntexture_map_lighted(bp, &Tmap1);
  1174.                 break;
  1175.             case 3:                                // perspective every pixel interpolation
  1176.                 per2_flag = 0;                    // this hack means do divide every pixel
  1177.                 ntexture_map_lighted(bp, &Tmap1);
  1178.                 break;
  1179.             default:
  1180.                 Assert(0);                // Illegal value for Interpolation_method, must be 0,1,2,3
  1181.         }
  1182.     }
  1183.  
  1184.     Lighting_on = lighting_on_save;
  1185.  
  1186. }
  1187.  
  1188. 
  1189.