NTMAP.C 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  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-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. #pragma off (unreferenced)
  14. static char rcsid[] = "$Id: ntmap.c 1.66 1996/12/04 19:27:55 matt Exp $";
  15. #pragma on (unreferenced)
  16. #define VESA 0
  17. #define NUM_TMAPS 16
  18. #define HEADLIGHT_LIGHTING 0
  19. #define WIREFRAME 0
  20. #define PERSPECTIVE 1
  21. #include <math.h>
  22. #include <limits.h>
  23. #include <stdio.h>
  24. #include <conio.h>
  25. #include <stdlib.h>
  26. #include "pa_enabl.h" //$$POLY_ACC
  27. #include "mono.h"
  28. #include "fix.h"
  29. #include "3d.h"
  30. #include "gr.h"
  31. #include "error.h"
  32. #include "key.h"
  33. #include "texmap.h"
  34. #include "texmapl.h"
  35. #include "rle.h"
  36. #include "scanline.h"
  37. #if defined(POLY_ACC)
  38. #include "poly_acc.h"
  39. #endif
  40. #define EDITOR_TMAP 1 //if in, include extra stuff
  41. #define F15_5 (F1_0*15 + F0_5)
  42. // 1 means enable special sc2000 code, else enable only for Descent
  43. #define SC2000K 0
  44. int SC2000 = SC2000K;
  45. // Temporary texture map, interface from Matt's 3d system to Mike's texture mapper.
  46. g3ds_tmap Tmap1;
  47. grs_bitmap Texmap_ptrs[NUM_TMAPS];
  48. grs_bitmap Texmap4_ptrs[NUM_TMAPS];
  49. fix Range_max=0; // debug, kill me
  50. int Interpolation_method=0; // 0 = choose best method
  51. int Lighting_on; // initialize to no lighting
  52. int Tmap_flat_flag = 0; // 1 = render texture maps as flat shaded polygons.
  53. int Current_seg_depth; // HACK INTERFACE: how far away the current segment (& thus texture) is
  54. int Max_perspective_depth;
  55. int Max_linear_depth;
  56. int Max_flat_depth;
  57. //variables for clipping the texture-mapper to screen region
  58. int Window_clip_left, Window_clip_bot, Window_clip_right, Window_clip_top;
  59. // These variables are the interface to assembler. They get set for each texture map, which is a real waste of time.
  60. // They should be set only when they change, which is generally when the window bounds change. And, even still, it's
  61. // a pretty bad interface.
  62. int bytes_per_row=-1;
  63. int write_buffer;
  64. int window_left;
  65. int window_right;
  66. int window_top;
  67. int window_bottom;
  68. int window_width;
  69. int window_height;
  70. uint dest_row_data;
  71. int loop_count;
  72. #define MAX_Y_POINTERS 1024
  73. int y_pointers[MAX_Y_POINTERS];
  74. #ifdef USE_SELECTORS
  75. short pixel_data_selector; // selector for current pixel data for texture mapper
  76. #endif
  77. fix fix_recip[FIX_RECIP_TABLE_SIZE];
  78. int Fix_recip_table_computed=0;
  79. fix fx_l, fx_u, fx_v, fx_z, fx_du_dx, fx_dv_dx, fx_dz_dx, fx_dl_dx;
  80. int fx_xleft, fx_xright, fx_y, fx_u_right, fx_v_right, fx_z_right;
  81. unsigned char * pixptr;
  82. int Transparency_on = 0;
  83. int dither_intensity_lighting = 0;
  84. ubyte * tmap_flat_cthru_table;
  85. ubyte tmap_flat_color;
  86. ubyte tmap_flat_shade_value;
  87. // F1_0/Z LOOKUP TABLE:
  88. // Sig bits... 10 looks fuzzy, but only uses 4K
  89. // 11 breaks up when close, but quite acceptable, Uses 8K
  90. // 12 looks good,except when very close. Can be used for game. Uses 16K. Recommended by John.
  91. #define DIVIDE_SIG_BITS 12
  92. #define Z_SHIFTER (30-DIVIDE_SIG_BITS)
  93. #define DIVIDE_TABLE_SIZE (1<<DIVIDE_SIG_BITS)
  94. ubyte divide_table_filled = 0;
  95. fix divide_table[1<<DIVIDE_SIG_BITS]; // Can use 16 bits if we divide by the greator of Z0 or Z1, instead of always Z0.
  96. void fill_divide_table()
  97. {
  98. int i;
  99. divide_table_filled = 1;
  100. divide_table[0]=f1_0;
  101. divide_table[1]=f1_0;
  102. for (i=2; i<DIVIDE_TABLE_SIZE; i++ ) {
  103. // entry[i] = 1.0 / i+0.5;
  104. divide_table[i] = fixdiv( F1_0*2, 2*i+1 );
  105. }
  106. }
  107. // -------------------------------------------------------------------------------------
  108. void init_fix_recip_table(void)
  109. {
  110. int i;
  111. fix_recip[0] = F1_0;
  112. for (i=1; i<FIX_RECIP_TABLE_SIZE; i++)
  113. fix_recip[i] = F1_0/i;
  114. Fix_recip_table_computed = 1;
  115. }
  116. // -------------------------------------------------------------------------------------
  117. // Initialize interface variables to assembler.
  118. // These things used to be constants. This routine is now (10/6/93) getting called for
  119. // every texture map. It should get called whenever the window changes, or, preferably,
  120. // not at all. I'm pretty sure these variables are only being used for range checking.
  121. void init_interface_vars_to_assembler(void)
  122. {
  123. grs_bitmap *bp;
  124. bp = &grd_curcanv->cv_bitmap;
  125. Assert(bp!=NULL);
  126. Assert(bp->bm_data!=NULL);
  127. Assert(bp->bm_h <= MAX_Y_POINTERS);
  128. // If bytes_per_row has changed, create new table of pointers.
  129. if (bytes_per_row != (int) bp->bm_rowsize) {
  130. int y_val, i;
  131. bytes_per_row = (int) bp->bm_rowsize;
  132. y_val = 0;
  133. for (i=0; i<MAX_Y_POINTERS; i++) {
  134. y_pointers[i] = y_val;
  135. y_val += bytes_per_row;
  136. }
  137. }
  138. write_buffer = (int) bp->bm_data;
  139. window_left = 0;
  140. window_right = (int) bp->bm_w-1;
  141. window_top = 0;
  142. window_bottom = (int) bp->bm_h-1;
  143. Window_clip_left = window_left;
  144. Window_clip_right = window_right;
  145. Window_clip_top = window_top;
  146. Window_clip_bot = window_bottom;
  147. window_width = bp->bm_w;
  148. window_height = bp->bm_h;
  149. if (!Fix_recip_table_computed)
  150. init_fix_recip_table();
  151. #if defined(POLY_ACC)
  152. pa_set_3d_offset(bp->bm_x, bp->bm_y);
  153. #endif
  154. if ( !divide_table_filled ) fill_divide_table();
  155. }
  156. // -------------------------------------------------------------------------------------
  157. // VARIABLES
  158. extern g3ds_tmap Tmap1;
  159. // -------------------------------------------------------------------------------------
  160. // Returns number preceding val modulo modulus.
  161. // prevmod(3,4) = 2
  162. // prevmod(0,4) = 3
  163. int prevmod(int val,int modulus)
  164. {
  165. if (val > 0)
  166. return val-1;
  167. else
  168. return modulus-1;
  169. // return (val + modulus - 1) % modulus;
  170. }
  171. // Returns number succeeding val modulo modulus.
  172. // succmod(3,4) = 0
  173. // succmod(0,4) = 1
  174. int succmod(int val,int modulus)
  175. {
  176. if (val < modulus-1)
  177. return val+1;
  178. else
  179. return 0;
  180. // return (val + 1) % modulus;
  181. }
  182. // -------------------------------------------------------------------------------------
  183. // Select topmost vertex (minimum y coordinate) and bottommost (maximum y coordinate) in
  184. // texture map. If either is part of a horizontal edge, then select leftmost vertex for
  185. // top, rightmost vertex for bottom.
  186. // Important: Vertex is selected with integer precision. So, if there are vertices at
  187. // (0.0,0.7) and (0.5,0.3), the first vertex is selected, because they y coordinates are
  188. // considered the same, so the smaller x is favored.
  189. // Parameters:
  190. // nv number of vertices
  191. // v3d pointer to 3d vertices containing u,v,x2d,y2d coordinates
  192. // Results in:
  193. // *min_y_ind
  194. // *max_y_ind
  195. // -------------------------------------------------------------------------------------
  196. void compute_y_bounds(g3ds_tmap *t, int *vlt, int *vlb, int *vrt, int *vrb,int *bottom_y_ind)
  197. {
  198. int i;
  199. int min_y,max_y;
  200. int min_y_ind;
  201. int original_vrt;
  202. fix min_x;
  203. // Scan all vertices, set min_y_ind to vertex with smallest y coordinate.
  204. min_y = f2i(t->verts[0].y2d);
  205. max_y = min_y;
  206. min_y_ind = 0;
  207. min_x = f2i(t->verts[0].x2d);
  208. *bottom_y_ind = 0;
  209. for (i=1; i<t->nv; i++) {
  210. if (f2i(t->verts[i].y2d) < min_y) {
  211. min_y = f2i(t->verts[i].y2d);
  212. min_y_ind = i;
  213. min_x = f2i(t->verts[i].x2d);
  214. } else if (f2i(t->verts[i].y2d) == min_y) {
  215. if (f2i(t->verts[i].x2d) < min_x) {
  216. min_y_ind = i;
  217. min_x = f2i(t->verts[i].x2d);
  218. }
  219. }
  220. if (f2i(t->verts[i].y2d) > max_y) {
  221. max_y = f2i(t->verts[i].y2d);
  222. *bottom_y_ind = i;
  223. }
  224. }
  225. //--removed mk, 11/27/94-- // Check for a non-upright-hourglass polygon and fix, if necessary, by bashing a y coordinate.
  226. //--removed mk, 11/27/94-- // min_y_ind = index of minimum y coordinate, *bottom_y_ind = index of maximum y coordinate
  227. //--removed mk, 11/27/94--{
  228. //--removed mk, 11/27/94-- int max_temp, min_temp;
  229. //--removed mk, 11/27/94--
  230. //--removed mk, 11/27/94-- max_temp = *bottom_y_ind;
  231. //--removed mk, 11/27/94-- if (*bottom_y_ind < min_y_ind)
  232. //--removed mk, 11/27/94-- max_temp += t->nv;
  233. //--removed mk, 11/27/94--
  234. //--removed mk, 11/27/94-- for (i=min_y_ind; i<max_temp; i++) {
  235. //--removed mk, 11/27/94-- if (f2i(t->verts[i%t->nv].y2d) > f2i(t->verts[(i+1)%t->nv].y2d)) {
  236. //--removed mk, 11/27/94-- Int3();
  237. //--removed mk, 11/27/94-- t->verts[(i+1)%t->nv].y2d = t->verts[i%t->nv].y2d;
  238. //--removed mk, 11/27/94-- }
  239. //--removed mk, 11/27/94-- }
  240. //--removed mk, 11/27/94--
  241. //--removed mk, 11/27/94-- min_temp = min_y_ind;
  242. //--removed mk, 11/27/94-- if (min_y_ind < *bottom_y_ind)
  243. //--removed mk, 11/27/94-- min_temp += t->nv;
  244. //--removed mk, 11/27/94--
  245. //--removed mk, 11/27/94-- for (i=*bottom_y_ind; i<min_temp; i++) {
  246. //--removed mk, 11/27/94-- if (f2i(t->verts[i%t->nv].y2d) < f2i(t->verts[(i+1)%t->nv].y2d)) {
  247. //--removed mk, 11/27/94-- Int3();
  248. //--removed mk, 11/27/94-- t->verts[(i+1)%t->nv].y2d = t->verts[i%t->nv].y2d;
  249. //--removed mk, 11/27/94-- }
  250. //--removed mk, 11/27/94-- }
  251. //--removed mk, 11/27/94--}
  252. // Set "vertex left top", etc. based on vertex with topmost y coordinate
  253. *vlt = min_y_ind;
  254. *vrt = *vlt;
  255. *vlb = prevmod(*vlt,t->nv);
  256. *vrb = succmod(*vrt,t->nv);
  257. // If right edge is horizontal, then advance along polygon bound until it no longer is or until all
  258. // vertices have been examined.
  259. // (Left edge cannot be horizontal, because *vlt is set to leftmost point with highest y coordinate.)
  260. original_vrt = *vrt;
  261. while (f2i(t->verts[*vrt].y2d) == f2i(t->verts[*vrb].y2d)) {
  262. if (succmod(*vrt,t->nv) == original_vrt) {
  263. break;
  264. }
  265. *vrt = succmod(*vrt,t->nv);
  266. *vrb = succmod(*vrt,t->nv);
  267. }
  268. }
  269. // -------------------------------------------------------------------------------------
  270. // Returns dx/dy given two vertices.
  271. // If dy == 0, returns 0.0
  272. // -------------------------------------------------------------------------------------
  273. //--fix compute_dx_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  274. //--{
  275. //-- int dy;
  276. //--
  277. //-- // compute delta x with respect to y for any edge
  278. //-- dy = f2i(t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) + 1;
  279. //-- if (dy)
  280. //-- return (t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d) / dy;
  281. //-- else
  282. //-- return 0;
  283. //--
  284. //--}
  285. fix compute_du_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  286. {
  287. return fixmul(t->verts[bottom_vertex].u - t->verts[top_vertex].u, recip_dy);
  288. }
  289. fix compute_dv_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  290. {
  291. return fixmul(t->verts[bottom_vertex].v - t->verts[top_vertex].v, recip_dy);
  292. }
  293. fix compute_dl_dy_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  294. {
  295. return fixmul(t->verts[bottom_vertex].l - t->verts[top_vertex].l, recip_dy);
  296. }
  297. fix compute_dx_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  298. {
  299. return fixmul(t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d, recip_dy);
  300. }
  301. fix compute_du_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  302. {
  303. 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);
  304. }
  305. fix compute_dv_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  306. {
  307. 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);
  308. }
  309. fix compute_dz_dy(g3ds_tmap *t, int top_vertex,int bottom_vertex, fix recip_dy)
  310. {
  311. return fixmul(t->verts[bottom_vertex].z - t->verts[top_vertex].z, recip_dy);
  312. }
  313. int Skip_short_flag=0;
  314. // -------------------------------------------------------------------------------------
  315. // Texture map current scanline in perspective.
  316. // -------------------------------------------------------------------------------------
  317. int Do_vertical_scan=0;
  318. int Break_on_flat=0;
  319. // -------------------------------------------------------------------------------------
  320. // Render a texture map with lighting using perspective interpolation in inner and outer loops.
  321. // -------------------------------------------------------------------------------------
  322. void ntmap_outerloop_correct_lighted( g3ds_tmap *t )
  323. {
  324. #define LINEAR 0 // 0=Perspective, 1=Linear
  325. #define LIGHTING 1 // 0=No lighting, 1=Use lighting
  326. #ifdef NASM
  327. #define INNER_LOOP c_tmap_scanline_per // Function to be called when ready to draw.
  328. #else
  329. #define INNER_LOOP asm_tmap_scanline_per // Function to be called when ready to draw.
  330. #endif
  331. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  332. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  333. #include "ntmapout.h"
  334. }
  335. void ntmap_outerloop_correct_nolight( g3ds_tmap *t )
  336. {
  337. #define LINEAR 0 // 0=Perspective, 1=Linear
  338. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  339. #ifdef NASM
  340. #define INNER_LOOP c_tmap_scanline_per_nolight // Function to be called when ready to draw.
  341. #else
  342. #define INNER_LOOP asm_tmap_scanline_per // Function to be called when ready to draw.
  343. #endif
  344. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  345. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  346. #include "ntmapout.h"
  347. }
  348. extern void asm_tmap_scanline_llt();
  349. void ntmap_outerloop_lin_lighted_trans( g3ds_tmap *t )
  350. {
  351. #define LINEAR 1 // 0=Perspective, 1=Linear
  352. #define LIGHTING 1 // 0=No lighting, 1=Use lighting
  353. #ifdef NASM
  354. #define INNER_LOOP c_tmap_scanline_lin // Function to be called when ready to draw.
  355. #else
  356. #define INNER_LOOP asm_tmap_scanline_llt // Function to be called when ready to draw.
  357. #endif
  358. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  359. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  360. #include "ntmapout.h"
  361. }
  362. extern void asm_tmap_scanline_lln();
  363. void ntmap_outerloop_lin_lighted_notrans( g3ds_tmap *t )
  364. {
  365. #define LINEAR 1 // 0=Perspective, 1=Linear
  366. #define LIGHTING 1 // 0=No lighting, 1=Use lighting
  367. #ifdef NASM
  368. #define INNER_LOOP c_tmap_scanline_lin // Function to be called when ready to draw.
  369. #else
  370. #define INNER_LOOP asm_tmap_scanline_lln // Function to be called when ready to draw.
  371. #endif
  372. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  373. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  374. #include "ntmapout.h"
  375. }
  376. extern void asm_tmap_scanline_plt();
  377. void ntmap_outerloop_per_lighted_trans( g3ds_tmap *t )
  378. {
  379. #define LINEAR 0 // 0=Perspective, 1=Linear
  380. #define LIGHTING 1 // 0=No lighting, 1=Use lighting
  381. #ifdef NASM
  382. #define INNER_LOOP c_tmap_scanline_per // Function to be called when ready to draw.
  383. #else
  384. #define INNER_LOOP asm_tmap_scanline_plt // Function to be called when ready to draw.
  385. #endif
  386. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  387. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  388. #include "ntmapout.h"
  389. }
  390. extern void asm_tmap_scanline_pln();
  391. void ntmap_outerloop_per_lighted_notrans( g3ds_tmap *t )
  392. {
  393. #define LINEAR 0 // 0=Perspective, 1=Linear
  394. #define LIGHTING 1 // 0=No lighting, 1=Use lighting
  395. #ifdef NASM
  396. #define INNER_LOOP c_tmap_scanline_per // Function to be called when ready to draw.
  397. #else
  398. #define INNER_LOOP asm_tmap_scanline_pln // Function to be called when ready to draw.
  399. #endif
  400. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  401. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  402. #include "ntmapout.h"
  403. }
  404. extern void asm_tmap_scanline_lnt();
  405. void ntmap_outerloop_lin_nolight_trans( g3ds_tmap *t )
  406. {
  407. #define LINEAR 1 // 0=Perspective, 1=Linear
  408. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  409. #ifdef NASM
  410. #define INNER_LOOP c_tmap_scanline_lin_nolight // Function to be called when ready to draw.
  411. #else
  412. #define INNER_LOOP asm_tmap_scanline_lnt // Function to be called when ready to draw.
  413. #endif
  414. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  415. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  416. #include "ntmapout.h"
  417. }
  418. extern void asm_tmap_scanline_lnn();
  419. void ntmap_outerloop_lin_nolight_notrans( g3ds_tmap *t )
  420. {
  421. #define LINEAR 1 // 0=Perspective, 1=Linear
  422. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  423. #ifdef NASM
  424. #define INNER_LOOP c_tmap_scanline_lin_nolight // Function to be called when ready to draw.
  425. #else
  426. #define INNER_LOOP asm_tmap_scanline_lnn // Function to be called when ready to draw.
  427. #endif
  428. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  429. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  430. #include "ntmapout.h"
  431. }
  432. extern void asm_tmap_scanline_pnt();
  433. void ntmap_outerloop_per_nolight_trans( g3ds_tmap *t )
  434. {
  435. #define LINEAR 0 // 0=Perspective, 1=Linear
  436. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  437. #ifdef NASM
  438. #define INNER_LOOP c_tmap_scanline_per_nolight // Function to be called when ready to draw.
  439. #else
  440. #define INNER_LOOP asm_tmap_scanline_pnt // Function to be called when ready to draw.
  441. #endif
  442. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  443. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  444. #include "ntmapout.h"
  445. }
  446. extern void asm_tmap_scanline_pnn();
  447. void ntmap_outerloop_per_nolight_notrans( g3ds_tmap *t )
  448. {
  449. #define LINEAR 0 // 0=Perspective, 1=Linear
  450. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  451. #ifdef NASM
  452. #define INNER_LOOP c_tmap_scanline_per_nolight // Function to be called when ready to draw.
  453. #else
  454. #define INNER_LOOP asm_tmap_scanline_pnn // Function to be called when ready to draw.
  455. #endif
  456. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  457. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  458. #include "ntmapout.h"
  459. }
  460. extern void asm_tmap_scanline_editor();
  461. extern void c_tmap_scanline_editor();
  462. void ntmap_outerloop_editor( g3ds_tmap *t )
  463. {
  464. #define LINEAR 0 // 0=Perspective, 1=Linear
  465. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  466. #ifdef NASM
  467. #define INNER_LOOP c_tmap_scanline_editor // Function to be called when ready to draw.
  468. #else
  469. #define INNER_LOOP asm_tmap_scanline_editor // Function to be called when ready to draw.
  470. #endif
  471. #define CHECK_WINDOW 0 // Set to 1 to check window clip
  472. #define USE_UVS 1 // Set to 1 to enable U,V interpolation
  473. #include "ntmapout.h"
  474. }
  475. // -------------------------------------------------------------------------------------
  476. // Render a texture map.
  477. // Linear in outer loop, linear in inner loop.
  478. // -------------------------------------------------------------------------------------
  479. void texture_map_flat(g3ds_tmap *t)
  480. {
  481. #define LINEAR 1 // 0=Perspective, 1=Linear
  482. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  483. #ifdef NASM
  484. #define INNER_LOOP c_tmap_scanline_flat // Function to be called when ready to draw.
  485. #else
  486. #define INNER_LOOP asm_tmap_scanline_flat // Function to be called when ready to draw.
  487. #endif
  488. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  489. #define USE_UVS 0 // Set to 1 to enable U,V interpolation
  490. #include "ntmapout.h"
  491. }
  492. extern void asm_tmap_scanline_shaded(); // In tmapfade.asm
  493. void texture_map_flat_faded(g3ds_tmap *t)
  494. {
  495. #define LINEAR 1 // 0=Perspective, 1=Linear
  496. #define LIGHTING 0 // 0=No lighting, 1=Use lighting
  497. #ifdef NASM
  498. #define INNER_LOOP c_tmap_scanline_shaded // Function to be called when ready to draw.
  499. #else
  500. #define INNER_LOOP asm_tmap_scanline_shaded // Function to be called when ready to draw.
  501. #endif
  502. #define CHECK_WINDOW 1 // Set to 1 to check window clip
  503. #define USE_UVS 0 // Set to 1 to enable U,V interpolation
  504. #include "ntmapout.h"
  505. }
  506. // fix DivNum = F1_0*12;
  507. extern void draw_tmap_flat(grs_bitmap *bp,int nverts,g3s_point **vertbuf);
  508. // -------------------------------------------------------------------------------------
  509. // Interface from Matt's data structures to Mike's texture mapper.
  510. // -------------------------------------------------------------------------------------
  511. void draw_tmap(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
  512. {
  513. int i;
  514. int lighting_mode = Lighting_on;
  515. int render_method;
  516. fix min_z;
  517. #ifdef _3DFX
  518. int bm_index = bp->bm_handle;
  519. #endif
  520. Assert(nverts <= MAX_TMAP_VERTS);
  521. Assert(bp->bm_w == 64);
  522. Assert(Lighting_on < 3);
  523. // If no transparency and seg depth is large, render as flat shaded.
  524. if ((Current_seg_depth > Max_linear_depth) && ((bp->bm_flags & 3) == 0)) {
  525. draw_tmap_flat(bp, nverts, vertbuf);
  526. return;
  527. }
  528. if ( bp->bm_flags & BM_FLAG_RLE )
  529. {
  530. bp = rle_expand_texture( bp ); // Expand if rle'd
  531. #ifdef _3DFX
  532. bp->bm_handle = bm_index;
  533. #endif
  534. }
  535. Transparency_on = bp->bm_flags & BM_FLAG_TRANSPARENT;
  536. if (bp->bm_flags & BM_FLAG_NO_LIGHTING)
  537. lighting_mode = 0;
  538. pixptr = bp->bm_data;
  539. render_method = Interpolation_method;
  540. if (render_method==0) {
  541. if (Current_seg_depth > Max_perspective_depth)
  542. render_method = 1; // use linear
  543. else
  544. render_method = 2; // use perspective
  545. }
  546. // Setup texture map in Tmap1
  547. Tmap1.nv = nverts; // Initialize number of vertices
  548. for (i=0; i<nverts; i++) {
  549. g3ds_vertex *tvp = &Tmap1.verts[i];
  550. g3s_point *vp = vertbuf[i];
  551. tvp->x2d = vp->p3_sx;
  552. tvp->y2d = vp->p3_sy;
  553. tvp->u = vp->p3_u << 6; //* bp->bm_w;
  554. tvp->v = vp->p3_v << 6; //* bp->bm_h;
  555. // Perspective stuff:
  556. if ( render_method > 1 )
  557. {
  558. //Check for overflow on fixdiv. Will overflow on vp->z <= something small. Allow only as low as 256.
  559. if (vp->p3_z < 256) {
  560. vp->p3_z = 256;
  561. // Int3(); // we would overflow if we divided!
  562. }
  563. tvp->z = vp->p3_z; //fixdiv(F1_0*12, vp->p3_z);
  564. if ( (i==0) || (tvp->z < min_z) )
  565. min_z = tvp->z;
  566. }
  567. #ifdef _3DFX
  568. tvp->z = vp->p3_z;
  569. #endif
  570. #if defined(POLY_ACC)
  571. #ifdef PA_3DFX_VOODOO
  572. tvp->z = vp->p3_z;
  573. #endif
  574. #endif
  575. // Lighting stuff:
  576. if (lighting_mode)
  577. tvp->l = vp->p3_l * NUM_LIGHTING_LEVELS;
  578. }
  579. #if defined(POLY_ACC)
  580. #ifdef PA_3DFX_VOODOO
  581. switch (render_method)
  582. {
  583. case 1: // linear interpolation
  584. pa_draw_tmap(bp, &Tmap1, Transparency_on, lighting_mode, 0, min_z); // linear
  585. break;
  586. case 2:
  587. case 3: // perspective every pixel interpolation
  588. pa_draw_tmap(bp, &Tmap1, Transparency_on, lighting_mode, 1, min_z); // persp.
  589. break;
  590. default:
  591. Assert(0); // Illegal value for Interpolation_method, must be 0,1,2,3
  592. }
  593. return;
  594. #endif
  595. #endif
  596. #ifdef _3DFX
  597. if ( _3dfx_available )
  598. {
  599. if ( _3dfx_rendering_poly_obj )
  600. {
  601. _3dfx_DownloadAndUseTexture( bp->bm_handle );
  602. }
  603. if ( Lighting_on )
  604. {
  605. guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB );
  606. _3dfxDrawTmap( bp, &Tmap1 );
  607. }
  608. else
  609. {
  610. guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );
  611. _3dfxDrawTmap( bp, &Tmap1 );
  612. }
  613. }
  614. _3dfx_triangles_rendered_post_clip += Tmap1.nv - 2;
  615. if ( _3dfx_skip_ddraw )
  616. goto done;
  617. #endif
  618. // Calculate 1/Z for perspective
  619. if ( render_method > 1 ) {
  620. g3ds_vertex *tvp = Tmap1.verts;
  621. for (i=0; i<nverts; i++, tvp++) {
  622. tvp->z = fixdiv( min_z, tvp->z );
  623. // Z is now in the range 0-F1_0 (17 bits)
  624. // So, in the next line, we need to
  625. // scale Z down so that it fits in the available
  626. // number of significant bits (12 bits now). But, at the
  627. // same time, we're scaling it up by Z_SHIFTER amount so
  628. // that it use 30 bits for Z interpolation, which keeps the
  629. // dz_dx values from becoming so small that they go to zero.
  630. tvp->z <<= Z_SHIFTER-(17-DIVIDE_SIG_BITS);
  631. }
  632. }
  633. // render_method:
  634. // 1 = linear, 2 = subdivided perspective, 3 = full perspective
  635. // lighting_mode:
  636. // 0 = no lighting, 1=lighting, 2=editor
  637. #if defined(POLY_ACC)
  638. switch (render_method)
  639. {
  640. /* obsolete 3/5/96.
  641. case 0: // choose best interpolation
  642. if (Current_seg_depth > Max_perspective_depth)
  643. pa_draw_tmap(bp, &Tmap1, Transparency_on, lighting_mode, 0); // linear
  644. else
  645. pa_draw_tmap(bp, &Tmap1, Transparency_on, lighting_mode, 1); // persp.
  646. break;
  647. */
  648. case 1: // linear interpolation
  649. pa_draw_tmap(bp, &Tmap1, Transparency_on, lighting_mode, 0, min_z); // linear
  650. break;
  651. case 2:
  652. case 3: // perspective every pixel interpolation
  653. pa_draw_tmap(bp, &Tmap1, Transparency_on, lighting_mode, 1, min_z); // persp.
  654. break;
  655. default:
  656. Assert(0); // Illegal value for Interpolation_method, must be 0,1,2,3
  657. }
  658. #else
  659. switch( lighting_mode ) {
  660. case 0:
  661. switch (render_method) {
  662. case 1: // linear interpolation
  663. if (Transparency_on)
  664. ntmap_outerloop_lin_nolight_trans(&Tmap1);
  665. else
  666. ntmap_outerloop_lin_nolight_notrans(&Tmap1);
  667. break;
  668. case 2: // subdivided perspective
  669. if (Transparency_on)
  670. ntmap_outerloop_per_nolight_trans( &Tmap1 );
  671. else
  672. ntmap_outerloop_per_nolight_notrans( &Tmap1 );
  673. break;
  674. case 3: // perspective every pixel interpolation
  675. ntmap_outerloop_correct_nolight( &Tmap1 );
  676. break;
  677. default:
  678. Assert(0); // Illegal value for Interpolation_method, must be 0,1,2,3
  679. }
  680. break;
  681. case 1:
  682. switch (render_method) {
  683. case 1: // linear interpolation
  684. if (Transparency_on)
  685. ntmap_outerloop_lin_lighted_trans(&Tmap1);
  686. else
  687. ntmap_outerloop_lin_lighted_notrans(&Tmap1);
  688. break;
  689. case 2: // subdivided perspective
  690. if (Transparency_on)
  691. ntmap_outerloop_per_lighted_trans( &Tmap1 );
  692. else
  693. ntmap_outerloop_per_lighted_notrans( &Tmap1 );
  694. break;
  695. case 3: // perspective every pixel interpolation
  696. ntmap_outerloop_correct_lighted( &Tmap1 );
  697. break;
  698. default:
  699. Assert(0); // Illegal value for Interpolation_method, must be 0,1,2,3
  700. }
  701. break;
  702. #ifdef EDITOR_TMAP
  703. case 2:
  704. ntmap_outerloop_editor( &Tmap1 );
  705. break;
  706. #endif
  707. }
  708. #endif //POLY_ACC
  709. #ifdef _3DFX
  710. done:
  711. return;
  712. #endif
  713. }
  714. #ifdef _3DFX
  715. #define SNAP( a ) ( ( fix ) ( (a) & ( 0xFFFFF000L ) ) )
  716. void _3dfxDrawTmap( grs_bitmap *bp, g3ds_tmap *Tmap1 )
  717. {
  718. GrVertex a, b, c;
  719. int i;
  720. if ( _3dfx_no_texture )
  721. guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
  722. a.r = a.g = a.b = Tmap1->verts[0].l * fix_to_rgb;
  723. a.tmuvtx[0].oow = a.oow = 1.0 / ( Tmap1->verts[0].z * fix_to_float );
  724. a.tmuvtx[0].sow = Tmap1->verts[0].u * fix_to_st * a.oow;
  725. a.tmuvtx[0].tow = Tmap1->verts[0].v * fix_to_st * a.oow;
  726. a.x = SNAP( Tmap1->verts[0].x2d ) * fix_to_float;
  727. a.y = SNAP( Tmap1->verts[0].y2d ) * fix_to_float;
  728. for ( i = 1; i < Tmap1->nv - 1; i++ )
  729. {
  730. b.r = b.g = b.b = Tmap1->verts[i].l * fix_to_rgb;
  731. b.tmuvtx[0].oow = b.oow = 1.0 / ( Tmap1->verts[i].z * fix_to_float );
  732. b.tmuvtx[0].sow = Tmap1->verts[i].u * fix_to_st * b.oow;
  733. b.tmuvtx[0].tow = Tmap1->verts[i].v * fix_to_st * b.oow;
  734. b.x = SNAP( Tmap1->verts[i].x2d ) * fix_to_float;
  735. b.y = SNAP( Tmap1->verts[i].y2d ) * fix_to_float;
  736. c.r = c.g = c.b = Tmap1->verts[i+1].l * fix_to_rgb;
  737. c.tmuvtx[0].oow = c.oow = 1.0 / ( Tmap1->verts[i+1].z * fix_to_float );
  738. c.tmuvtx[0].sow = Tmap1->verts[i+1].u * fix_to_st * c.oow;
  739. c.tmuvtx[0].tow = Tmap1->verts[i+1].v * fix_to_st * c.oow;
  740. c.x = SNAP( Tmap1->verts[i+1].x2d ) * fix_to_float;
  741. c.y = SNAP( Tmap1->verts[i+1].y2d ) * fix_to_float;
  742. grDrawTriangle( &a, &b, &c );
  743. }
  744. }
  745. #endif