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