NTMAP.C 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  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. #pragma off (unreferenced)
  123. static char rcsid[] = "$Id: ntmap.c 1.52 1995/03/14 15:13:06 john Exp $";
  124. #pragma on (unreferenced)
  125. #define VESA 0
  126. #define NUM_TMAPS 16
  127. #define HEADLIGHT_LIGHTING 0
  128. #define WIREFRAME 0
  129. #define PERSPECTIVE 1
  130. #include <math.h>
  131. #include <limits.h>
  132. #include <stdio.h>
  133. #include <conio.h>
  134. #include <stdlib.h>
  135. #include "mono.h"
  136. #include "fix.h"
  137. #include "3d.h"
  138. #include "gr.h"
  139. #include "error.h"
  140. #include "key.h"
  141. #include "texmap.h"
  142. #include "texmapl.h"
  143. #include "rle.h"
  144. #include "scanline.h"
  145. #include "..\main\textures.h"
  146. #define EDITOR_TMAP 1 //if in, include extra stuff
  147. #define F15_5 (F1_0*15 + F0_5)
  148. // 1 means enable special sc2000 code, else enable only for Descent
  149. #define SC2000K 0
  150. int SC2000 = SC2000K;
  151. // Temporary texture map, interface from Matt's 3d system to Mike's texture mapper.
  152. g3ds_tmap Tmap1;
  153. grs_bitmap Texmap_ptrs[NUM_TMAPS];
  154. grs_bitmap Texmap4_ptrs[NUM_TMAPS];
  155. fix Range_max=0; // debug, kill me
  156. int Interpolation_method=0; // 0 = choose best method
  157. int Lighting_on; // initialize to no lighting
  158. int Tmap_flat_flag = 0; // 1 = render texture maps as flat shaded polygons.
  159. int Current_seg_depth; // HACK INTERFACE: how far away the current segment (& thus texture) is
  160. int Max_perspective_depth;
  161. int Max_linear_depth;
  162. int Max_flat_depth;
  163. extern int Window_clip_left, Window_clip_bot, Window_clip_right, Window_clip_top;
  164. // These variables are the interface to assembler. They get set for each texture map, which is a real waste of time.
  165. // They should be set only when they change, which is generally when the window bounds change. And, even still, it's
  166. // a pretty bad interface.
  167. int bytes_per_row=-1;
  168. int write_buffer;
  169. int window_left;
  170. int window_right;
  171. int window_top;
  172. int window_bottom;
  173. int window_width;
  174. int window_height;
  175. int write_buffer;
  176. #ifdef EDITOR_TMAP
  177. #define MAX_Y_POINTERS 480
  178. #else
  179. #define MAX_Y_POINTERS 480
  180. #endif
  181. int y_pointers[MAX_Y_POINTERS];
  182. short pixel_data_selector; // selector for current pixel data for texture mapper
  183. fix fix_recip[FIX_RECIP_TABLE_SIZE];
  184. int Lighting_enabled;
  185. int Fix_recip_table_computed=0;
  186. fix fx_l, fx_u, fx_v, fx_z, fx_du_dx, fx_dv_dx, fx_dz_dx, fx_dl_dx;
  187. int fx_xleft, fx_xright, fx_y;
  188. unsigned char * pixptr;
  189. int per2_flag = 0;
  190. int Transparency_on = 0;
  191. int dither_intensity_lighting = 0;
  192. ubyte * tmap_flat_cthru_table;
  193. ubyte tmap_flat_color;
  194. ubyte tmap_flat_shade_value;
  195. // -------------------------------------------------------------------------------------
  196. void init_fix_recip_table(void)
  197. {
  198. int i;
  199. fix_recip[0] = F1_0;
  200. for (i=1; i<FIX_RECIP_TABLE_SIZE; i++)
  201. fix_recip[i] = F1_0/i;
  202. Fix_recip_table_computed = 1;
  203. }
  204. // -------------------------------------------------------------------------------------
  205. // Initialize interface variables to assembler.
  206. // These things used to be constants. This routine is now (10/6/93) getting called for
  207. // every texture map. It should get called whenever the window changes, or, preferably,
  208. // not at all. I'm pretty sure these variables are only being used for range checking.
  209. void init_interface_vars_to_assembler(void)
  210. {
  211. grs_bitmap *bp;
  212. bp = &grd_curcanv->cv_bitmap;
  213. Assert(bp!=NULL);
  214. Assert(bp->bm_data!=NULL);
  215. Assert(bp->bm_h <= MAX_Y_POINTERS);
  216. // If bytes_per_row has changed, create new table of pointers.
  217. if (bytes_per_row != (int) bp->bm_rowsize) {
  218. int y_val, i;
  219. bytes_per_row = (int) bp->bm_rowsize;
  220. y_val = 0;
  221. for (i=0; i<MAX_Y_POINTERS; i++) {
  222. y_pointers[i] = y_val;
  223. y_val += bytes_per_row;
  224. }
  225. }
  226. write_buffer = (int) bp->bm_data;
  227. window_left = 0;
  228. window_right = (int) bp->bm_w-1;
  229. window_top = 0;
  230. window_bottom = (int) bp->bm_h-1;
  231. Window_clip_left = window_left;
  232. Window_clip_right = window_right;
  233. Window_clip_top = window_top;
  234. Window_clip_bot = window_bottom;
  235. window_width = bp->bm_w;
  236. window_height = bp->bm_h;
  237. if (!Fix_recip_table_computed)
  238. init_fix_recip_table();
  239. }
  240. int tmap_set_selector(int selector, void *buffer, unsigned int size);
  241. // -------------------------------------------------------------------------------------
  242. // VARIABLES
  243. extern short pixel_data_selector; // selector for current pixel data for texture mapper
  244. extern g3ds_tmap Tmap1;
  245. // -------------------------------------------------------------------------------------
  246. // Returns number preceding val modulo modulus.
  247. // prevmod(3,4) = 2
  248. // prevmod(0,4) = 3
  249. int prevmod(int val,int modulus)
  250. {
  251. if (val > 0)
  252. return val-1;
  253. else
  254. return modulus-1;
  255. // return (val + modulus - 1) % modulus;
  256. }
  257. // Returns number succeeding val modulo modulus.
  258. // succmod(3,4) = 0
  259. // succmod(0,4) = 1
  260. int succmod(int val,int modulus)
  261. {
  262. if (val < modulus-1)
  263. return val+1;
  264. else
  265. return 0;
  266. // return (val + 1) % modulus;
  267. }
  268. // -------------------------------------------------------------------------------------
  269. // Select topmost vertex (minimum y coordinate) and bottommost (maximum y coordinate) in
  270. // texture map. If either is part of a horizontal edge, then select leftmost vertex for
  271. // top, rightmost vertex for bottom.
  272. // Important: Vertex is selected with integer precision. So, if there are vertices at
  273. // (0.0,0.7) and (0.5,0.3), the first vertex is selected, because they y coordinates are
  274. // considered the same, so the smaller x is favored.
  275. // Parameters:
  276. // nv number of vertices
  277. // v3d pointer to 3d vertices containing u,v,x2d,y2d coordinates
  278. // Results in:
  279. // *min_y_ind
  280. // *max_y_ind
  281. // -------------------------------------------------------------------------------------
  282. void compute_y_bounds(g3ds_tmap *t, int *vlt, int *vlb, int *vrt, int *vrb,int *bottom_y_ind)
  283. {
  284. int i;
  285. int min_y,max_y;
  286. int min_y_ind;
  287. int original_vrt;
  288. fix min_x;
  289. // Scan all vertices, set min_y_ind to vertex with smallest y coordinate.
  290. min_y = f2i(t->verts[0].y2d);
  291. max_y = min_y;
  292. min_y_ind = 0;
  293. min_x = f2i(t->verts[0].x2d);
  294. *bottom_y_ind = 0;
  295. for (i=1; i<t->nv; i++) {
  296. if (f2i(t->verts[i].y2d) < min_y) {
  297. min_y = f2i(t->verts[i].y2d);
  298. min_y_ind = i;
  299. min_x = f2i(t->verts[i].x2d);
  300. } else if (f2i(t->verts[i].y2d) == min_y) {
  301. if (f2i(t->verts[i].x2d) < min_x) {
  302. min_y_ind = i;
  303. min_x = f2i(t->verts[i].x2d);
  304. }
  305. }
  306. if (f2i(t->verts[i].y2d) > max_y) {
  307. max_y = f2i(t->verts[i].y2d);
  308. *bottom_y_ind = i;
  309. }
  310. }
  311. //--removed mk, 11/27/94-- // Check for a non-upright-hourglass polygon and fix, if necessary, by bashing a y coordinate.
  312. //--removed mk, 11/27/94-- // min_y_ind = index of minimum y coordinate, *bottom_y_ind = index of maximum y coordinate
  313. //--removed mk, 11/27/94--{
  314. //--removed mk, 11/27/94-- int max_temp, min_temp;
  315. //--removed mk, 11/27/94--
  316. //--removed mk, 11/27/94-- max_temp = *bottom_y_ind;
  317. //--removed mk, 11/27/94-- if (*bottom_y_ind < min_y_ind)
  318. //--removed mk, 11/27/94-- max_temp += t->nv;
  319. //--removed mk, 11/27/94--
  320. //--removed mk, 11/27/94-- for (i=min_y_ind; i<max_temp; i++) {
  321. //--removed mk, 11/27/94-- if (f2i(t->verts[i%t->nv].y2d) > f2i(t->verts[(i+1)%t->nv].y2d)) {
  322. //--removed mk, 11/27/94-- Int3();
  323. //--removed mk, 11/27/94-- t->verts[(i+1)%t->nv].y2d = t->verts[i%t->nv].y2d;
  324. //--removed mk, 11/27/94-- }
  325. //--removed mk, 11/27/94-- }
  326. //--removed mk, 11/27/94--
  327. //--removed mk, 11/27/94-- min_temp = min_y_ind;
  328. //--removed mk, 11/27/94-- if (min_y_ind < *bottom_y_ind)
  329. //--removed mk, 11/27/94-- min_temp += t->nv;
  330. //--removed mk, 11/27/94--
  331. //--removed mk, 11/27/94-- for (i=*bottom_y_ind; i<min_temp; i++) {
  332. //--removed mk, 11/27/94-- if (f2i(t->verts[i%t->nv].y2d) < f2i(t->verts[(i+1)%t->nv].y2d)) {
  333. //--removed mk, 11/27/94-- Int3();
  334. //--removed mk, 11/27/94-- t->verts[(i+1)%t->nv].y2d = t->verts[i%t->nv].y2d;
  335. //--removed mk, 11/27/94-- }
  336. //--removed mk, 11/27/94-- }
  337. //--removed mk, 11/27/94--}
  338. // Set "vertex left top", etc. based on vertex with topmost y coordinate
  339. *vlt = min_y_ind;
  340. *vrt = *vlt;
  341. *vlb = prevmod(*vlt,t->nv);
  342. *vrb = succmod(*vrt,t->nv);
  343. // If right edge is horizontal, then advance along polygon bound until it no longer is or until all
  344. // vertices have been examined.
  345. // (Left edge cannot be horizontal, because *vlt is set to leftmost point with highest y coordinate.)
  346. original_vrt = *vrt;
  347. while (f2i(t->verts[*vrt].y2d) == f2i(t->verts[*vrb].y2d)) {
  348. if (succmod(*vrt,t->nv) == original_vrt) {
  349. break;
  350. }
  351. *vrt = succmod(*vrt,t->nv);
  352. *vrb = succmod(*vrt,t->nv);
  353. }
  354. }
  355. // -------------------------------------------------------------------------------------
  356. // Returns dx/dy given two vertices.
  357. // If dy == 0, returns 0.0
  358. // -------------------------------------------------------------------------------------
  359. //--fix compute_dx_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  360. //--{
  361. //-- int dy;
  362. //--
  363. //-- // compute delta x with respect to y for any edge
  364. //-- dy = f2i(t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) + 1;
  365. //-- if (dy)
  366. //-- return (t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d) / dy;
  367. //-- else
  368. //-- return 0;
  369. //--
  370. //--}
  371. fix compute_du_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  372. {
  373. return fixmul(t->verts[bottom_vertex].u - t->verts[top_vertex].u, recip_dy);
  374. }
  375. fix compute_dv_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  376. {
  377. return fixmul(t->verts[bottom_vertex].v - t->verts[top_vertex].v, recip_dy);
  378. }
  379. fix compute_dl_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  380. {
  381. return fixmul(t->verts[bottom_vertex].l - t->verts[top_vertex].l, recip_dy);
  382. }
  383. fix compute_dx_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  384. {
  385. return fixmul(t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d, recip_dy);
  386. }
  387. fix compute_du_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  388. {
  389. 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);
  390. }
  391. fix compute_dv_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  392. {
  393. 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);
  394. }
  395. fix compute_dz_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  396. {
  397. return fixmul(t->verts[bottom_vertex].z - t->verts[top_vertex].z, recip_dy);
  398. }
  399. int Skip_short_flag=0;
  400. // -------------------------------------------------------------------------------------
  401. // Texture map current scanline in perspective.
  402. // -------------------------------------------------------------------------------------
  403. 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)
  404. {
  405. fix u,v,l;
  406. fix dx,recip_dx;
  407. fix du_dx,dv_dx,dz_dx,z;
  408. u = uleft;
  409. v = vleft;
  410. l = lleft;
  411. fx_xright = f2i(xright);
  412. fx_xleft = f2i(xleft);
  413. dx = fx_xright - fx_xleft;
  414. if ((dx < 0) || (xright < 0) || (xleft > xright)) // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  415. return;
  416. // setup to call assembler scanline renderer
  417. if (dx < FIX_RECIP_TABLE_SIZE)
  418. recip_dx = fix_recip[dx];
  419. else
  420. recip_dx = F1_0/dx;
  421. du_dx = fixmul(uright - uleft,recip_dx);
  422. dv_dx = fixmul(vright - vleft,recip_dx);
  423. dz_dx = fixmul(zright - zleft,recip_dx);
  424. z = zleft;
  425. fx_u = uleft;
  426. fx_v = vleft;
  427. fx_z = zleft;
  428. fx_du_dx = du_dx;
  429. fx_dv_dx = dv_dx;
  430. fx_dz_dx = dz_dx;
  431. fx_y = y;
  432. pixptr = srcb->bm_data;
  433. switch (Lighting_enabled) {
  434. case 0:
  435. if (fx_xleft > Window_clip_right)
  436. return;
  437. if (fx_xright < Window_clip_left)
  438. return;
  439. if (fx_xright > Window_clip_right)
  440. fx_xright = Window_clip_right;
  441. #ifdef NASM
  442. c_tmap_scanline_per_nolight();
  443. #else
  444. asm_tmap_scanline_per();
  445. #endif
  446. break;
  447. case 1: {
  448. fix mul_thing;
  449. if (lleft < 0) lleft = 0;
  450. if (lright < 0) lright = 0;
  451. if (lleft > (NUM_LIGHTING_LEVELS*F1_0-F1_0/2)) lleft = (NUM_LIGHTING_LEVELS*F1_0-F1_0/2);
  452. if (lright > (NUM_LIGHTING_LEVELS*F1_0-F1_0/2)) lright = (NUM_LIGHTING_LEVELS*F1_0-F1_0/2);
  453. fx_l = lleft;
  454. fx_dl_dx = fixmul(lright - lleft,recip_dx);
  455. // This is a pretty ugly hack to prevent lighting overflows.
  456. mul_thing = dx * fx_dl_dx;
  457. if (lleft + mul_thing < 0)
  458. fx_dl_dx += 12;
  459. else if (lleft + mul_thing > (NUM_LIGHTING_LEVELS*F1_0-F1_0/2))
  460. fx_dl_dx -= 12;
  461. if (fx_xleft > Window_clip_right)
  462. return;
  463. if (fx_xright < Window_clip_left)
  464. return;
  465. if (fx_xright > Window_clip_right)
  466. fx_xright = Window_clip_right;
  467. #ifdef NASM
  468. c_tmap_scanline_per();
  469. #else
  470. asm_tmap_scanline_per();
  471. #endif
  472. break;
  473. }
  474. case 2:
  475. #ifdef EDITOR_TMAP
  476. fx_xright = f2i(xright);
  477. fx_xleft = f2i(xleft);
  478. asm_tmap_scanline_matt();
  479. #else
  480. Int3(); // Illegal, called an editor only routine!
  481. #endif
  482. break;
  483. }
  484. }
  485. int Do_vertical_scan=0;
  486. int Break_on_flat=0;
  487. // -------------------------------------------------------------------------------------
  488. // Render a texture map with lighting using perspective interpolation in inner and outer loops.
  489. // -------------------------------------------------------------------------------------
  490. void ntexture_map_lighted(grs_bitmap *srcb, g3ds_tmap *t)
  491. {
  492. int vlt,vrt,vlb,vrb; // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  493. int topy,boty,y, dy;
  494. fix dx_dy_left,dx_dy_right;
  495. fix du_dy_left,du_dy_right;
  496. fix dv_dy_left,dv_dy_right;
  497. fix dz_dy_left,dz_dy_right;
  498. fix dl_dy_left,dl_dy_right;
  499. fix recip_dyl, recip_dyr;
  500. int max_y_vertex;
  501. fix xleft,xright,uleft,vleft,uright,vright,zleft,zright,lleft,lright;
  502. int next_break_left, next_break_right;
  503. g3ds_vertex *v3d;
  504. v3d = t->verts;
  505. #if SC2000K
  506. if (Do_vertical_scan) {
  507. texture_map_hyp_lin_v(srcb, t);
  508. return;
  509. }
  510. #endif
  511. // Determine top and bottom y coords.
  512. compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex);
  513. // Set top and bottom (of entire texture map) y coordinates.
  514. topy = f2i(v3d[vlt].y2d);
  515. boty = f2i(v3d[max_y_vertex].y2d);
  516. if (topy > Window_clip_bot)
  517. return;
  518. if (boty > Window_clip_bot)
  519. boty = Window_clip_bot;
  520. // Set amount to change x coordinate for each advance to next scanline.
  521. dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  522. if (dy < FIX_RECIP_TABLE_SIZE)
  523. recip_dyl = fix_recip[dy];
  524. else
  525. recip_dyl = F1_0/dy;
  526. dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dyl);
  527. du_dy_left = compute_du_dy(t,vlt,vlb, recip_dyl);
  528. dv_dy_left = compute_dv_dy(t,vlt,vlb, recip_dyl);
  529. dz_dy_left = compute_dz_dy(t,vlt,vlb, recip_dyl);
  530. dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  531. if (dy < FIX_RECIP_TABLE_SIZE)
  532. recip_dyr = fix_recip[dy];
  533. else
  534. recip_dyr = F1_0/dy;
  535. du_dy_right = compute_du_dy(t,vrt,vrb, recip_dyr);
  536. dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dyr);
  537. dv_dy_right = compute_dv_dy(t,vrt,vrb, recip_dyr);
  538. dz_dy_right = compute_dz_dy(t,vrt,vrb, recip_dyr);
  539. if (Lighting_enabled) {
  540. dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dyl);
  541. dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dyr);
  542. lleft = v3d[vlt].l;
  543. lright = v3d[vrt].l;
  544. }
  545. // Set initial values for x, u, v
  546. xleft = v3d[vlt].x2d;
  547. xright = v3d[vrt].x2d;
  548. zleft = v3d[vlt].z;
  549. zright = v3d[vrt].z;
  550. uleft = fixmul(v3d[vlt].u,zleft);
  551. uright = fixmul(v3d[vrt].u,zright);
  552. vleft = fixmul(v3d[vlt].v,zleft);
  553. vright = fixmul(v3d[vrt].v,zright);
  554. // scan all rows in texture map from top through first break.
  555. next_break_left = f2i(v3d[vlb].y2d);
  556. next_break_right = f2i(v3d[vrb].y2d);
  557. for (y = topy; y < boty; y++) {
  558. // See if we have reached the end of the current left edge, and if so, set
  559. // new values for dx_dy and x,u,v
  560. if (y == next_break_left) {
  561. fix recip_dy;
  562. // Handle problem of double points. Search until y coord is different. Cannot get
  563. // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  564. // because in the for loop, we don't scan all spanlines.
  565. while (y == f2i(v3d[vlb].y2d)) {
  566. vlt = vlb;
  567. vlb = prevmod(vlb,t->nv);
  568. }
  569. next_break_left = f2i(v3d[vlb].y2d);
  570. dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  571. if (dy < FIX_RECIP_TABLE_SIZE)
  572. recip_dy = fix_recip[dy];
  573. else
  574. recip_dy = F1_0/dy;
  575. dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
  576. xleft = v3d[vlt].x2d;
  577. zleft = v3d[vlt].z;
  578. uleft = fixmul(v3d[vlt].u,zleft);
  579. vleft = fixmul(v3d[vlt].v,zleft);
  580. lleft = v3d[vlt].l;
  581. du_dy_left = compute_du_dy(t,vlt,vlb, recip_dy);
  582. dv_dy_left = compute_dv_dy(t,vlt,vlb, recip_dy);
  583. dz_dy_left = compute_dz_dy(t,vlt,vlb, recip_dy);
  584. if (Lighting_enabled) {
  585. dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dy);
  586. lleft = v3d[vlt].l;
  587. }
  588. }
  589. // See if we have reached the end of the current left edge, and if so, set
  590. // new values for dx_dy and x. Not necessary to set new values for u,v.
  591. if (y == next_break_right) {
  592. fix recip_dy;
  593. while (y == f2i(v3d[vrb].y2d)) {
  594. vrt = vrb;
  595. vrb = succmod(vrb,t->nv);
  596. }
  597. next_break_right = f2i(v3d[vrb].y2d);
  598. dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  599. if (dy < FIX_RECIP_TABLE_SIZE)
  600. recip_dy = fix_recip[dy];
  601. else
  602. recip_dy = F1_0/dy;
  603. dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
  604. xright = v3d[vrt].x2d;
  605. zright = v3d[vrt].z;
  606. uright = fixmul(v3d[vrt].u,zright);
  607. vright = fixmul(v3d[vrt].v,zright);
  608. du_dy_right = compute_du_dy(t,vrt,vrb, recip_dy);
  609. dv_dy_right = compute_dv_dy(t,vrt,vrb, recip_dy);
  610. dz_dy_right = compute_dz_dy(t,vrt,vrb, recip_dy);
  611. if (Lighting_enabled) {
  612. dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dy);
  613. lright = v3d[vrt].l;
  614. }
  615. }
  616. if (Lighting_enabled) {
  617. if (y >= Window_clip_top)
  618. ntmap_scanline_lighted(srcb,y,xleft,xright,uleft,uright,vleft,vright,zleft,zright,lleft,lright);
  619. lleft += dl_dy_left;
  620. lright += dl_dy_right;
  621. } else
  622. if (y >= Window_clip_top)
  623. ntmap_scanline_lighted(srcb,y,xleft,xright,uleft,uright,vleft,vright,zleft,zright,lleft,lright);
  624. uleft += du_dy_left;
  625. vleft += dv_dy_left;
  626. uright += du_dy_right;
  627. vright += dv_dy_right;
  628. xleft += dx_dy_left;
  629. xright += dx_dy_right;
  630. zleft += dz_dy_left;
  631. zright += dz_dy_right;
  632. }
  633. // We can get lleft or lright out of bounds here because we compute dl_dy using fixed point values,
  634. // but we plot an integer number of scanlines, therefore doing an integer number of additions of the delta.
  635. //if (Break_on_flat)
  636. // mprintf(0, "[%i %i %i] ", y, f2i(xleft), f2i(xright));
  637. ntmap_scanline_lighted(srcb,y,xleft,xright,uleft,uright,vleft,vright,zleft,zright,lleft,lright);
  638. }
  639. // -------------------------------------------------------------------------------------
  640. // Texture map current scanline using linear interpolation.
  641. // -------------------------------------------------------------------------------------
  642. 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)
  643. {
  644. fix u,v,l;
  645. fix dx,recip_dx;
  646. fix du_dx,dv_dx,dl_dx;
  647. u = uleft;
  648. v = vleft;
  649. l = lleft;
  650. dx = f2i(xright) - f2i(xleft);
  651. if ((dx < 0) || (xright < 0) || (xleft > xright)) // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  652. return;
  653. // setup to call assembler scanline renderer
  654. if (dx < FIX_RECIP_TABLE_SIZE)
  655. recip_dx = fix_recip[dx];
  656. else
  657. recip_dx = F1_0/dx;
  658. du_dx = fixmul(uright - uleft,recip_dx);
  659. dv_dx = fixmul(vright - vleft,recip_dx);
  660. fx_u = uleft;
  661. fx_v = vleft;
  662. fx_du_dx = du_dx;
  663. fx_dv_dx = dv_dx;
  664. fx_y = y;
  665. fx_xright = f2i(xright);
  666. fx_xleft = f2i(xleft);
  667. pixptr = srcb->bm_data;
  668. switch (Lighting_enabled) {
  669. case 0:
  670. #ifdef NASM
  671. c_tmap_scanline_lin_nolight();
  672. #else
  673. asm_tmap_scanline_lin();
  674. #endif
  675. break;
  676. case 1:
  677. if (lleft < F1_0/2)
  678. lleft = F1_0/2;
  679. if (lright < F1_0/2)
  680. lright = F1_0/2;
  681. if (lleft > MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS)
  682. lleft = MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS;
  683. if (lright > MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS)
  684. lright = MAX_LIGHTING_VALUE*NUM_LIGHTING_LEVELS;
  685. fx_l = lleft;
  686. dl_dx = fixmul(lright - lleft,recip_dx);
  687. fx_dl_dx = dl_dx;
  688. #ifdef NASM
  689. c_tmap_scanline_lin();
  690. #else
  691. asm_tmap_scanline_lin_lighted();
  692. #endif
  693. break;
  694. case 2:
  695. #ifdef EDITOR_TMAP
  696. fx_xright = f2i(xright);
  697. fx_xleft = f2i(xleft);
  698. asm_tmap_scanline_matt();
  699. #else
  700. Int3(); // Illegal, called an editor only routine!
  701. #endif
  702. break;
  703. }
  704. }
  705. // -------------------------------------------------------------------------------------
  706. // Render a texture map with lighting using perspective interpolation in inner and outer loops.
  707. // -------------------------------------------------------------------------------------
  708. void ntexture_map_lighted_linear(grs_bitmap *srcb, g3ds_tmap *t)
  709. {
  710. int vlt,vrt,vlb,vrb; // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  711. int topy,boty,y, dy;
  712. fix dx_dy_left,dx_dy_right;
  713. fix du_dy_left,du_dy_right;
  714. fix dv_dy_left,dv_dy_right;
  715. fix dl_dy_left,dl_dy_right;
  716. int max_y_vertex;
  717. fix xleft,xright,uleft,vleft,uright,vright,lleft,lright;
  718. int next_break_left, next_break_right;
  719. fix recip_dyl, recip_dyr;
  720. g3ds_vertex *v3d;
  721. v3d = t->verts;
  722. // Determine top and bottom y coords.
  723. compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex);
  724. // Set top and bottom (of entire texture map) y coordinates.
  725. topy = f2i(v3d[vlt].y2d);
  726. boty = f2i(v3d[max_y_vertex].y2d);
  727. if (topy > Window_clip_bot)
  728. return;
  729. if (boty > Window_clip_bot)
  730. boty = Window_clip_bot;
  731. dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  732. if (dy < FIX_RECIP_TABLE_SIZE)
  733. recip_dyl = fix_recip[dy];
  734. else
  735. recip_dyl = F1_0/dy;
  736. dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  737. if (dy < FIX_RECIP_TABLE_SIZE)
  738. recip_dyr = fix_recip[dy];
  739. else
  740. recip_dyr = F1_0/dy;
  741. // Set amount to change x coordinate for each advance to next scanline.
  742. dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dyl);
  743. dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dyr);
  744. du_dy_left = compute_du_dy_lin(t,vlt,vlb, recip_dyl);
  745. du_dy_right = compute_du_dy_lin(t,vrt,vrb, recip_dyr);
  746. dv_dy_left = compute_dv_dy_lin(t,vlt,vlb, recip_dyl);
  747. dv_dy_right = compute_dv_dy_lin(t,vrt,vrb, recip_dyr);
  748. if (Lighting_enabled) {
  749. dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dyl);
  750. dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dyr);
  751. lleft = v3d[vlt].l;
  752. lright = v3d[vrt].l;
  753. }
  754. // Set initial values for x, u, v
  755. xleft = v3d[vlt].x2d;
  756. xright = v3d[vrt].x2d;
  757. uleft = v3d[vlt].u;
  758. uright = v3d[vrt].u;
  759. vleft = v3d[vlt].v;
  760. vright = v3d[vrt].v;
  761. // scan all rows in texture map from top through first break.
  762. next_break_left = f2i(v3d[vlb].y2d);
  763. next_break_right = f2i(v3d[vrb].y2d);
  764. for (y = topy; y < boty; y++) {
  765. // See if we have reached the end of the current left edge, and if so, set
  766. // new values for dx_dy and x,u,v
  767. if (y == next_break_left) {
  768. fix recip_dy;
  769. // Handle problem of double points. Search until y coord is different. Cannot get
  770. // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  771. // because in the for loop, we don't scan all spanlines.
  772. while (y == f2i(v3d[vlb].y2d)) {
  773. vlt = vlb;
  774. vlb = prevmod(vlb,t->nv);
  775. }
  776. next_break_left = f2i(v3d[vlb].y2d);
  777. dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
  778. if (dy < FIX_RECIP_TABLE_SIZE)
  779. recip_dy = fix_recip[dy];
  780. else
  781. recip_dy = F1_0/dy;
  782. dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
  783. xleft = v3d[vlt].x2d;
  784. uleft = v3d[vlt].u;
  785. vleft = v3d[vlt].v;
  786. lleft = v3d[vlt].l;
  787. du_dy_left = compute_du_dy_lin(t,vlt,vlb, recip_dy);
  788. dv_dy_left = compute_dv_dy_lin(t,vlt,vlb, recip_dy);
  789. if (Lighting_enabled) {
  790. dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dy);
  791. lleft = v3d[vlt].l;
  792. }
  793. }
  794. // See if we have reached the end of the current left edge, and if so, set
  795. // new values for dx_dy and x. Not necessary to set new values for u,v.
  796. if (y == next_break_right) {
  797. fix recip_dy;
  798. while (y == f2i(v3d[vrb].y2d)) {
  799. vrt = vrb;
  800. vrb = succmod(vrb,t->nv);
  801. }
  802. dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
  803. if (dy < FIX_RECIP_TABLE_SIZE)
  804. recip_dy = fix_recip[dy];
  805. else
  806. recip_dy = F1_0/dy;
  807. next_break_right = f2i(v3d[vrb].y2d);
  808. dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
  809. xright = v3d[vrt].x2d;
  810. uright = v3d[vrt].u;
  811. vright = v3d[vrt].v;
  812. du_dy_right = compute_du_dy_lin(t,vrt,vrb, recip_dy);
  813. dv_dy_right = compute_dv_dy_lin(t,vrt,vrb, recip_dy);
  814. if (Lighting_enabled) {
  815. dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dy);
  816. lright = v3d[vrt].l;
  817. }
  818. }
  819. if (Lighting_enabled) {
  820. ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright);
  821. lleft += dl_dy_left;
  822. lright += dl_dy_right;
  823. } else
  824. ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright);
  825. uleft += du_dy_left;
  826. vleft += dv_dy_left;
  827. uright += du_dy_right;
  828. vright += dv_dy_right;
  829. xleft += dx_dy_left;
  830. xright += dx_dy_right;
  831. }
  832. // We can get lleft or lright out of bounds here because we compute dl_dy using fixed point values,
  833. // but we plot an integer number of scanlines, therefore doing an integer number of additions of the delta.
  834. ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright);
  835. }
  836. // fix DivNum = F1_0*12;
  837. extern void draw_tmap_flat(grs_bitmap *bp,int nverts,g3s_point **vertbuf);
  838. // -------------------------------------------------------------------------------------
  839. // Interface from Matt's data structures to Mike's texture mapper.
  840. // -------------------------------------------------------------------------------------
  841. void draw_tmap(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
  842. {
  843. int i;
  844. // These variables are used in system which renders texture maps which lie on one scanline as a line.
  845. #if SC2000K
  846. int flat_flag; // Set to 1 and remains 1 so long as all y coords are the same (in integer portion).
  847. int last_y; // Y coordinate of previous vertex.
  848. fix min_x = 0xfff0000, max_x = 0; // Minimum and maximum bounds of line to render in place of flat texture map.
  849. #endif
  850. // fix div_numerator;
  851. int lighting_on_save = Lighting_on;
  852. Assert(nverts <= MAX_TMAP_VERTS);
  853. #ifdef USE_MULT_CODE
  854. if ( !divide_table_filled ) fill_divide_table();
  855. #endif
  856. // -- now called from g3_start_frame -- init_interface_vars_to_assembler();
  857. // If no transparency and seg depth is large, render as flat shaded.
  858. if ((Current_seg_depth > Max_linear_depth) && ((bp->bm_flags & 3) == 0)) {
  859. draw_tmap_flat(bp, nverts, vertbuf);
  860. return;
  861. }
  862. if ( bp->bm_flags & BM_FLAG_RLE )
  863. bp = rle_expand_texture( bp ); // Expand if rle'd
  864. Transparency_on = bp->bm_flags & BM_FLAG_TRANSPARENT;
  865. if (bp->bm_flags & BM_FLAG_NO_LIGHTING)
  866. Lighting_on = 0;
  867. // Set selector for current texture map.
  868. if ( bp->bm_selector == 0 ) {
  869. if (gr_bitmap_assign_selector( bp ) )
  870. Error( "Couldn't assign selector in ntmap.c!\n" );
  871. }
  872. pixel_data_selector = bp->bm_selector;
  873. // Setup texture map in Tmap1
  874. Tmap1.nv = nverts; // Initialize number of vertices
  875. #if SC2000K
  876. last_y = f2i(vertbuf[0]->p3_sy);
  877. flat_flag = 1; // Says so far, this texture map exists all on one scan line
  878. #endif
  879. // div_numerator = DivNum; //f1_0*3;
  880. for (i=0; i<nverts; i++) {
  881. g3ds_vertex *tvp = &Tmap1.verts[i];
  882. g3s_point *vp = vertbuf[i];
  883. tvp->x2d = vp->p3_sx;
  884. tvp->y2d = vp->p3_sy;
  885. #if SC2000K
  886. // If y coordinates are not the same (in integer portion), then this texture map is not all on one scan line
  887. if (f2i(tvp->y2d) != last_y)
  888. flat_flag = 0;
  889. // If everything is flat so far, set minimum x and y for rendering a scanline
  890. if (flat_flag) {
  891. if (tvp->x2d < min_x)
  892. min_x = tvp->x2d;
  893. if (tvp->x2d > max_x)
  894. max_x = tvp->x2d;
  895. }
  896. #endif
  897. // Check for overflow on fixdiv. Will overflow on vp->z <= something small. Allow only as low as 256.
  898. if (vp->z < 256) {
  899. vp->z = 256;
  900. // Int3(); // we would overflow if we divided!
  901. }
  902. tvp->z = fixdiv(F1_0*12, vp->z);
  903. tvp->u = vp->p3_u << 6; //* bp->bm_w;
  904. tvp->v = vp->p3_v << 6; //* bp->bm_h;
  905. Assert(Lighting_on < 3);
  906. if (Lighting_on)
  907. tvp->l = vp->p3_l * NUM_LIGHTING_LEVELS;
  908. }
  909. #if SC2000K
  910. // Render a horizontal line instead of a texture map if flat_flag still set (all vertices on one scanline).
  911. if (SC2000 && flat_flag) {
  912. fix y,cvw;
  913. Int3();
  914. y = Tmap1.verts[0].y2d;
  915. cvw = i2f(grd_curcanv->cv_bitmap.bm_w-1);
  916. if (y<0 || y>i2f(grd_curcanv->cv_bitmap.bm_h-1)) { Lighting_on = lighting_on_save; return; }
  917. //if (min_x < 0) min_x = 0;
  918. //if (max_x > cvw) max_x = cvw;
  919. gr_setcolor(*(bp->bm_data+32*32+32)); // Read center pixel of 64x64 bitmap, use as line color.
  920. gr_line(min_x, Tmap1.verts[0].y2d, max_x, Tmap1.verts[0].y2d);
  921. Lighting_on = lighting_on_save;
  922. return;
  923. }
  924. #endif
  925. Lighting_enabled = Lighting_on;
  926. // Now, call my texture mapper.
  927. if (Lighting_on) {
  928. switch (Interpolation_method) { // 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
  929. case 0: // choose best interpolation
  930. per2_flag = 1;
  931. if (Current_seg_depth > Max_perspective_depth)
  932. ntexture_map_lighted_linear(bp, &Tmap1);
  933. else
  934. ntexture_map_lighted(bp, &Tmap1);
  935. break;
  936. case 1: // linear interpolation
  937. per2_flag = 1;
  938. ntexture_map_lighted_linear(bp, &Tmap1);
  939. break;
  940. case 2: // perspective every 8th pixel interpolation
  941. per2_flag = 1;
  942. ntexture_map_lighted(bp, &Tmap1);
  943. break;
  944. case 3: // perspective every pixel interpolation
  945. per2_flag = 0; // this hack means do divide every pixel
  946. ntexture_map_lighted(bp, &Tmap1);
  947. break;
  948. default:
  949. Assert(0); // Illegal value for Interpolation_method, must be 0,1,2,3
  950. }
  951. } else {
  952. switch (Interpolation_method) { // 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
  953. case 0: // choose best interpolation
  954. per2_flag = 1;
  955. if (Current_seg_depth > Max_perspective_depth)
  956. ntexture_map_lighted_linear(bp, &Tmap1);
  957. else
  958. ntexture_map_lighted(bp, &Tmap1);
  959. break;
  960. case 1: // linear interpolation
  961. per2_flag = 1;
  962. ntexture_map_lighted_linear(bp, &Tmap1);
  963. break;
  964. case 2: // perspective every 8th pixel interpolation
  965. per2_flag = 1;
  966. ntexture_map_lighted(bp, &Tmap1);
  967. break;
  968. case 3: // perspective every pixel interpolation
  969. per2_flag = 0; // this hack means do divide every pixel
  970. ntexture_map_lighted(bp, &Tmap1);
  971. break;
  972. default:
  973. Assert(0); // Illegal value for Interpolation_method, must be 0,1,2,3
  974. }
  975. }
  976. Lighting_on = lighting_on_save;
  977. }
  978.