TMAPV.C 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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/tmapv.c $
  15. * $Revision: 1.5 $
  16. * $Author: mike $
  17. * $Date: 1994/11/28 13:34:30 $
  18. *
  19. * Vertical scanning in inner loop analogue to tmap.c
  20. *
  21. * $Log: tmapv.c $
  22. * Revision 1.5 1994/11/28 13:34:30 mike
  23. * optimizations.
  24. *
  25. * Revision 1.4 1994/05/24 17:31:01 mike
  26. * Vertical scanning texture mapper, hyperbolic in outer loop, linear in inner.
  27. *
  28. * Revision 1.3 1994/05/24 11:02:54 mike
  29. * Fix bugs in vertically scanning texture mapper, hack in Do_vertical_scan.
  30. *
  31. * Revision 1.2 1994/01/31 15:42:02 mike
  32. * Vertical scanning version of texture mapper.
  33. *
  34. * Revision 1.1 1994/01/30 13:56:44 mike
  35. * Initial revision
  36. *
  37. *
  38. */
  39. #pragma off (unreferenced)
  40. static char rcsid[] = "$Id: tmapv.c 1.5 1994/11/28 13:34:30 mike Exp $";
  41. #pragma on (unreferenced)
  42. #include <math.h>
  43. #include <limits.h>
  44. #include <stdio.h>
  45. #include <conio.h>
  46. #include <stdlib.h>
  47. #include "mono.h"
  48. #include "fix.h"
  49. #include "3d.h"
  50. #include "gr.h"
  51. #include "error.h"
  52. #include "texmap.h"
  53. #include "texmapl.h"
  54. int Is_sky_flag;
  55. // ------------------------------------------------------------------------------------------
  56. void compute_x_bounds(g3ds_tmap *t, int *vlt, int *vlb, int *vrt, int *vrb, int *left_x_ind)
  57. {
  58. int i;
  59. int min_y,max_y;
  60. int min_x_ind;
  61. int original_vrt;
  62. fix min_x,max_x;
  63. min_y = 9999;
  64. max_y = -9999;
  65. min_x = 9999;
  66. max_x = -9999;
  67. // Scan all vertices, set min_y_ind to vertex with smallest y coordinate.
  68. for (i=0; i<t->nv; i++) {
  69. if (f2i(t->verts[i].x2d) < min_x) {
  70. min_x = f2i(t->verts[i].x2d);
  71. min_x_ind = i;
  72. min_y = f2i(t->verts[i].y2d);
  73. } else if (f2i(t->verts[i].x2d) == min_x) {
  74. if (f2i(t->verts[i].y2d) < min_y) {
  75. min_x_ind = i;
  76. min_y = f2i(t->verts[i].y2d);
  77. }
  78. }
  79. if (f2i(t->verts[i].x2d) > max_x) {
  80. max_x = f2i(t->verts[i].x2d);
  81. *left_x_ind = i;
  82. }
  83. }
  84. // Set "vertex left top", etc. based on vertex with topmost y coordinate
  85. *vlt = min_x_ind;
  86. *vrt = *vlt;
  87. *vlb = succmod(*vlt,t->nv);
  88. *vrb = prevmod(*vrt,t->nv);
  89. // If right edge is vertical, then advance along polygon bound until it no longer is or until all
  90. // vertices have been examined.
  91. // (Left edge cannot be horizontal, because *vlt is set to leftmost point with highest y coordinate.)
  92. original_vrt = *vrt;
  93. while (f2i(t->verts[*vrt].x2d) == f2i(t->verts[*vrb].x2d)) {
  94. if (succmod(*vrt,t->nv) == original_vrt) {
  95. break;
  96. }
  97. *vrt = prevmod(*vrt,t->nv);
  98. *vrb = prevmod(*vrt,t->nv);
  99. }
  100. }
  101. // -------------------------------------------------------------------------------------
  102. // Render a texture map.
  103. // Linear in outer loop, linear in inner loop.
  104. // Scan horizontally in outer loop, vertically in inner loop.
  105. fix compute_dy_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  106. {
  107. int dx;
  108. // compute delta x with respect to y for any edge
  109. dx = f2i(t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d) + 1;
  110. if (dx)
  111. return (t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) / dx;
  112. else
  113. return 0;
  114. }
  115. fix compute_dy_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  116. {
  117. int dx;
  118. // compute delta y with respect to y for any edge
  119. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  120. if (dx)
  121. return (t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) / dx;
  122. else
  123. return 0;
  124. }
  125. fix compute_du_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  126. {
  127. int dx;
  128. // compute delta u with respect to y for any edge
  129. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  130. if (dx)
  131. return (fixmul(t->verts[bottom_vertex].u,t->verts[bottom_vertex].z) - fixmul(t->verts[top_vertex].u,t->verts[top_vertex].z)) / dx;
  132. else
  133. return 0;
  134. }
  135. fix compute_dv_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  136. {
  137. int dx;
  138. // compute delta v with respect to y for any edge
  139. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  140. if (dx)
  141. return (fixmul(t->verts[bottom_vertex].v,t->verts[bottom_vertex].z) - fixmul(t->verts[top_vertex].v,t->verts[top_vertex].z)) / dx;
  142. else
  143. return 0;
  144. }
  145. fix compute_dz_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  146. {
  147. int dx;
  148. // compute delta x with respect to y for the any edge
  149. // this is used in computing the x coordinate on the next row and in
  150. // scaling the add of Du_dx to the uleft and vleft coordinates.
  151. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  152. if (dx)
  153. return (t->verts[bottom_vertex].z - t->verts[top_vertex].z) / dx;
  154. else
  155. return 0;
  156. }
  157. fix compute_dl_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  158. {
  159. int dx;
  160. // compute delta l with respect to y for any edge
  161. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d) + 1;
  162. if (dx)
  163. return (t->verts[bottom_vertex].l - t->verts[top_vertex].l) / dx;
  164. else
  165. return 0;
  166. }
  167. fix compute_du_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  168. {
  169. int dx;
  170. // compute delta u with respect to y for any edge
  171. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d) + 1;
  172. if (dx)
  173. return (t->verts[bottom_vertex].u - t->verts[top_vertex].u) / dx;
  174. else
  175. return 0;
  176. }
  177. fix compute_dv_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  178. {
  179. int dx;
  180. // compute delta v with respect to y for any edge
  181. dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d) + 1;
  182. if (dx)
  183. return (t->verts[bottom_vertex].v - t->verts[top_vertex].v) / dx;
  184. else
  185. return 0;
  186. }
  187. // -------------------------------------------------------------------------------------
  188. void tmap_scanline_lin_sky_v(grs_bitmap *srcb, int x, fix yleft, fix yright, fix uleft, fix uright, fix vleft, fix vright)
  189. {
  190. fix dy;
  191. dy = f2i(yright) - f2i(yleft);
  192. if ((dy < 0) || (yright < 0) || (yleft > yright)) // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  193. return;
  194. // setup to call assembler scanline renderer
  195. fx_u = uleft;
  196. fx_v = vleft;
  197. if (dy < f1_0) {
  198. fx_du_dx = uright-uleft;
  199. fx_dv_dx = vright-vleft;
  200. } else {
  201. fx_du_dx = fixdiv(uright - fx_u,dy);
  202. fx_dv_dx = fixdiv(vright - fx_v,dy);
  203. }
  204. fx_y = x;
  205. fx_xleft = yleft;
  206. fx_xright = yright;
  207. pixptr = srcb->bm_data;
  208. if (Is_sky_flag)
  209. asm_tmap_scanline_lin_sky_v();
  210. else
  211. asm_tmap_scanline_lin_v();
  212. }
  213. // -------------------------------------------------------------------------------------
  214. void tmap_scanline_hyp_lin_v(grs_bitmap *srcb, int x, fix yleft, fix yright, fix uleft, fix uright, fix vleft, fix vright, fix zleft, fix zright)
  215. {
  216. // fix dy, recip_dy, z;
  217. int dy;
  218. dy = f2i(yright) - f2i(yleft);
  219. if ((dy < 0) || (yright < 0) || (yleft > yright)) // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  220. return;
  221. // setup to call assembler scanline renderer
  222. // if (dy < FIX_RECIP_TABLE_SIZE)
  223. // recip_dy = fix_recip[dy];
  224. // else
  225. // recip_dy = F1_0/dy;
  226. uleft = fixdiv(uleft, zleft);
  227. uright = fixdiv(uright, zright);
  228. vleft = fixdiv(vleft, zleft);
  229. vright = fixdiv(vright, zright);
  230. if (dy > 0) {
  231. fx_du_dx = (uright - uleft)/dy;
  232. fx_dv_dx = (vright - vleft)/dy;
  233. } else {
  234. fx_du_dx = 0;
  235. fx_dv_dx = 0;
  236. }
  237. // fx_dz_dx = fixmul(zright - zleft,recip_dy);
  238. fx_u = uleft;
  239. fx_v = vleft;
  240. fx_z = zleft;
  241. fx_y = x;
  242. fx_xleft = yleft;
  243. fx_xright = yright;
  244. pixptr = srcb->bm_data;
  245. if (Is_sky_flag)
  246. asm_tmap_scanline_lin_sky_v();
  247. else
  248. asm_tmap_scanline_lin_v();
  249. }
  250. // -------------------------------------------------------------------------------------
  251. void texture_map_hyp_lin_v(grs_bitmap *srcb, g3ds_tmap *t)
  252. {
  253. int vlt,vrt,vlb,vrb; // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  254. int topy,boty,x;
  255. int left_break,right_break;
  256. fix dx_dy_left,dx_dy_right;
  257. fix du_dy_left,du_dy_right;
  258. fix dv_dy_left,dv_dy_right;
  259. fix dz_dy_left,dz_dy_right;
  260. fix zleft, zright;
  261. int max_x_vertex;
  262. fix yleft,yright,uleft,vleft,uright,vright;
  263. g3ds_vertex *v3d;
  264. // mprintf(0, "width = %i, height = %i\n", srcb->bm_w, srcb->bm_h);
  265. Is_sky_flag = 0;
  266. if ((srcb->bm_w == 1024) && (srcb->bm_h == 128))
  267. Is_sky_flag = 1;
  268. //--now called from g3_start_frame-- init_interface_vars_to_assembler();
  269. v3d = t->verts;
  270. // Determine top and bottom y coords.
  271. compute_x_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_x_vertex);
  272. // Set top and bottom (of entire texture map) y coordinates.
  273. topy = f2i(v3d[vlt].x2d);
  274. boty = f2i(v3d[max_x_vertex].x2d);
  275. // Set amount to change x coordinate for each advance to next scanline.
  276. dx_dy_left = compute_dy_dx(t,vlt,vlb);
  277. dx_dy_right = compute_dy_dx(t,vrt,vrb);
  278. du_dy_left = compute_du_dx(t,vlt,vlb);
  279. du_dy_right = compute_du_dx(t,vrt,vrb);
  280. dv_dy_left = compute_dv_dx(t,vlt,vlb);
  281. dv_dy_right = compute_dv_dx(t,vrt,vrb);
  282. dz_dy_left = compute_dz_dx(t,vlt,vlb);
  283. dz_dy_right = compute_dz_dx(t,vrt,vrb);
  284. // Set initial values for x, u, v
  285. yleft = v3d[vlt].y2d;
  286. yright = v3d[vrt].y2d;
  287. zleft = v3d[vlt].z;
  288. zright = v3d[vrt].z;
  289. uleft = fixmul(v3d[vlt].u,zleft);
  290. uright = fixmul(v3d[vrt].u,zright);
  291. vleft = fixmul(v3d[vlt].v,zleft);
  292. vright = fixmul(v3d[vrt].v,zright);
  293. // scan all rows in texture map from top through first break.
  294. // @mk: Should we render the scanline for y==boty? This violates Matt's spec.
  295. left_break = f2i(v3d[vlb].x2d);
  296. right_break = f2i(v3d[vrb].x2d);
  297. for (x = topy; x < boty; x++) {
  298. // See if we have reached the end of the current left edge, and if so, set
  299. // new values for dx_dy and x,u,v
  300. if (x == left_break) {
  301. // Handle problem of double points. Search until y coord is different. Cannot get
  302. // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  303. // because in the for loop, we don't scan all spanlines.
  304. while (x == f2i(v3d[vlb].x2d)) {
  305. vlt = vlb;
  306. vlb = succmod(vlb,t->nv);
  307. }
  308. left_break = f2i(v3d[vlb].x2d);
  309. dx_dy_left = compute_dy_dx(t,vlt,vlb);
  310. yleft = v3d[vlt].y2d;
  311. zleft = v3d[vlt].z;
  312. uleft = fixmul(v3d[vlt].u,zleft);
  313. vleft = fixmul(v3d[vlt].v,zleft);
  314. du_dy_left = compute_du_dx(t,vlt,vlb);
  315. dv_dy_left = compute_dv_dx(t,vlt,vlb);
  316. dz_dy_left = compute_dz_dx(t,vlt,vlb);
  317. }
  318. // See if we have reached the end of the current left edge, and if so, set
  319. // new values for dx_dy and x. Not necessary to set new values for u,v.
  320. if (x == right_break) {
  321. while (x == f2i(v3d[vrb].x2d)) {
  322. vrt = vrb;
  323. vrb = prevmod(vrb,t->nv);
  324. }
  325. right_break = f2i(v3d[vrb].x2d);
  326. dx_dy_right = compute_dy_dx(t,vrt,vrb);
  327. yright = v3d[vrt].y2d;
  328. zright = v3d[vrt].z;
  329. uright = fixmul(v3d[vrt].u,zright);
  330. vright = fixmul(v3d[vrt].v,zright);
  331. du_dy_right = compute_du_dx(t,vrt,vrb);
  332. dv_dy_right = compute_dv_dx(t,vrt,vrb);
  333. dz_dy_right = compute_dz_dx(t,vrt,vrb);
  334. }
  335. tmap_scanline_hyp_lin_v(srcb,x,yleft,yright,uleft,uright,vleft,vright, zleft, zright);
  336. uleft += du_dy_left;
  337. vleft += dv_dy_left;
  338. uright += du_dy_right;
  339. vright += dv_dy_right;
  340. yleft += dx_dy_left;
  341. yright += dx_dy_right;
  342. zleft += dz_dy_left;
  343. zright += dz_dy_right;
  344. }
  345. tmap_scanline_hyp_lin_v(srcb,x,yleft,yright,uleft,uright,vleft,vright, zleft, zright);
  346. }
  347. // -------------------------------------------------------------------------------------
  348. void texture_map_lin_lin_sky_v(grs_bitmap *srcb, g3ds_tmap *t)
  349. {
  350. int vlt,vrt,vlb,vrb; // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  351. int topy,boty,x;
  352. int left_break,right_break;
  353. fix dx_dy_left,dx_dy_right;
  354. fix du_dy_left,du_dy_right;
  355. fix dv_dy_left,dv_dy_right;
  356. int max_x_vertex;
  357. fix yleft,yright,uleft,vleft,uright,vright;
  358. g3ds_vertex *v3d;
  359. // mprintf(0, "width = %i, height = %i\n", srcb->bm_w, srcb->bm_h);
  360. Is_sky_flag = 0;
  361. if ((srcb->bm_w == 1024) && (srcb->bm_h == 128))
  362. Is_sky_flag = 1;
  363. //--now called from g3_start_frame-- init_interface_vars_to_assembler();
  364. v3d = t->verts;
  365. // Determine top and bottom y coords.
  366. compute_x_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_x_vertex);
  367. // Set top and bottom (of entire texture map) y coordinates.
  368. topy = f2i(v3d[vlt].x2d);
  369. boty = f2i(v3d[max_x_vertex].x2d);
  370. // Set amount to change x coordinate for each advance to next scanline.
  371. dx_dy_left = compute_dy_dx_lin(t,vlt,vlb);
  372. dx_dy_right = compute_dy_dx_lin(t,vrt,vrb);
  373. du_dy_left = compute_du_dx_lin(t,vlt,vlb);
  374. du_dy_right = compute_du_dx_lin(t,vrt,vrb);
  375. dv_dy_left = compute_dv_dx_lin(t,vlt,vlb);
  376. dv_dy_right = compute_dv_dx_lin(t,vrt,vrb);
  377. // Set initial values for x, u, v
  378. yleft = v3d[vlt].y2d;
  379. yright = v3d[vrt].y2d;
  380. uleft = v3d[vlt].u;
  381. uright = v3d[vrt].u;
  382. vleft = v3d[vlt].v;
  383. vright = v3d[vrt].v;
  384. // scan all rows in texture map from top through first break.
  385. // @mk: Should we render the scanline for y==boty? This violates Matt's spec.
  386. left_break = f2i(v3d[vlb].x2d);
  387. right_break = f2i(v3d[vrb].x2d);
  388. for (x = topy; x < boty; x++) {
  389. // See if we have reached the end of the current left edge, and if so, set
  390. // new values for dx_dy and x,u,v
  391. if (x == left_break) {
  392. // Handle problem of double points. Search until y coord is different. Cannot get
  393. // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  394. // because in the for loop, we don't scan all spanlines.
  395. while (x == f2i(v3d[vlb].x2d)) {
  396. vlt = vlb;
  397. vlb = succmod(vlb,t->nv);
  398. }
  399. left_break = f2i(v3d[vlb].x2d);
  400. dx_dy_left = compute_dy_dx_lin(t,vlt,vlb);
  401. yleft = v3d[vlt].y2d;
  402. uleft = v3d[vlt].u;
  403. vleft = v3d[vlt].v;
  404. du_dy_left = compute_du_dx_lin(t,vlt,vlb);
  405. dv_dy_left = compute_dv_dx_lin(t,vlt,vlb);
  406. }
  407. // See if we have reached the end of the current left edge, and if so, set
  408. // new values for dx_dy and x. Not necessary to set new values for u,v.
  409. if (x == right_break) {
  410. while (x == f2i(v3d[vrb].x2d)) {
  411. vrt = vrb;
  412. vrb = prevmod(vrb,t->nv);
  413. }
  414. right_break = f2i(v3d[vrb].x2d);
  415. dx_dy_right = compute_dy_dx_lin(t,vrt,vrb);
  416. yright = v3d[vrt].y2d;
  417. uright = v3d[vrt].u;
  418. vright = v3d[vrt].v;
  419. du_dy_right = compute_du_dx_lin(t,vrt,vrb);
  420. dv_dy_right = compute_dv_dx_lin(t,vrt,vrb);
  421. }
  422. tmap_scanline_lin_sky_v(srcb,x,yleft,yright,uleft,uright,vleft,vright);
  423. uleft += du_dy_left;
  424. vleft += dv_dy_left;
  425. uright += du_dy_right;
  426. vright += dv_dy_right;
  427. yleft += dx_dy_left;
  428. yright += dx_dy_right;
  429. }
  430. tmap_scanline_lin_sky_v(srcb,x,yleft,yright,uleft,uright,vleft,vright);
  431. }