r_misc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // r_misc.c
  16. #include "r_local.h"
  17. #define NUM_MIPS 4
  18. cvar_t *sw_mipcap;
  19. cvar_t *sw_mipscale;
  20. surfcache_t *d_initial_rover;
  21. qboolean d_roverwrapped;
  22. int d_minmip;
  23. float d_scalemip[NUM_MIPS-1];
  24. static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
  25. extern int d_aflatcolor;
  26. int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
  27. int d_pix_min, d_pix_max, d_pix_shift;
  28. int d_scantable[MAXHEIGHT];
  29. short *zspantable[MAXHEIGHT];
  30. /*
  31. ================
  32. D_Patch
  33. ================
  34. */
  35. void D_Patch (void)
  36. {
  37. #if id386
  38. extern void D_Aff8Patch( void );
  39. static qboolean protectset8 = false;
  40. extern void D_PolysetAff8Start( void );
  41. if (!protectset8)
  42. {
  43. Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
  44. (int)D_Aff8Patch - (int)D_PolysetAff8Start);
  45. Sys_MakeCodeWriteable ((long)R_Surf8Start,
  46. (long)R_Surf8End - (long)R_Surf8Start);
  47. protectset8 = true;
  48. }
  49. colormap = vid.colormap;
  50. R_Surf8Patch ();
  51. D_Aff8Patch();
  52. #endif
  53. }
  54. /*
  55. ================
  56. D_ViewChanged
  57. ================
  58. */
  59. unsigned char *alias_colormap;
  60. void D_ViewChanged (void)
  61. {
  62. int i;
  63. scale_for_mip = xscale;
  64. if (yscale > xscale)
  65. scale_for_mip = yscale;
  66. d_zrowbytes = vid.width * 2;
  67. d_zwidth = vid.width;
  68. d_pix_min = r_refdef.vrect.width / 320;
  69. if (d_pix_min < 1)
  70. d_pix_min = 1;
  71. d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
  72. d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
  73. if (d_pix_max < 1)
  74. d_pix_max = 1;
  75. d_vrectx = r_refdef.vrect.x;
  76. d_vrecty = r_refdef.vrect.y;
  77. d_vrectright_particle = r_refdef.vrectright - d_pix_max;
  78. d_vrectbottom_particle =
  79. r_refdef.vrectbottom - d_pix_max;
  80. for (i=0 ; i<vid.height; i++)
  81. {
  82. d_scantable[i] = i*r_screenwidth;
  83. zspantable[i] = d_pzbuffer + i*d_zwidth;
  84. }
  85. /*
  86. ** clear Z-buffer and color-buffers if we're doing the gallery
  87. */
  88. if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
  89. {
  90. memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) );
  91. Draw_Fill( r_newrefdef.x, r_newrefdef.y, r_newrefdef.width, r_newrefdef.height,( int ) sw_clearcolor->value & 0xff );
  92. }
  93. alias_colormap = vid.colormap;
  94. D_Patch ();
  95. }
  96. /*
  97. =============
  98. R_PrintTimes
  99. =============
  100. */
  101. void R_PrintTimes (void)
  102. {
  103. int r_time2;
  104. int ms;
  105. r_time2 = Sys_Milliseconds ();
  106. ms = r_time2 - r_time1;
  107. ri.Con_Printf (PRINT_ALL,"%5i ms %3i/%3i/%3i poly %3i surf\n",
  108. ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
  109. c_surf = 0;
  110. }
  111. /*
  112. =============
  113. R_PrintDSpeeds
  114. =============
  115. */
  116. void R_PrintDSpeeds (void)
  117. {
  118. int ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, da_time;
  119. r_time2 = Sys_Milliseconds ();
  120. da_time = (da_time2 - da_time1);
  121. dp_time = (dp_time2 - dp_time1);
  122. rw_time = (rw_time2 - rw_time1);
  123. db_time = (db_time2 - db_time1);
  124. se_time = (se_time2 - se_time1);
  125. de_time = (de_time2 - de_time1);
  126. ms = (r_time2 - r_time1);
  127. ri.Con_Printf (PRINT_ALL,"%3i %2ip %2iw %2ib %2is %2ie %2ia\n",
  128. ms, dp_time, rw_time, db_time, se_time, de_time, da_time);
  129. }
  130. /*
  131. =============
  132. R_PrintAliasStats
  133. =============
  134. */
  135. void R_PrintAliasStats (void)
  136. {
  137. ri.Con_Printf (PRINT_ALL,"%3i polygon model drawn\n", r_amodels_drawn);
  138. }
  139. /*
  140. ===================
  141. R_TransformFrustum
  142. ===================
  143. */
  144. void R_TransformFrustum (void)
  145. {
  146. int i;
  147. vec3_t v, v2;
  148. for (i=0 ; i<4 ; i++)
  149. {
  150. v[0] = screenedge[i].normal[2];
  151. v[1] = -screenedge[i].normal[0];
  152. v[2] = screenedge[i].normal[1];
  153. v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
  154. v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
  155. v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
  156. VectorCopy (v2, view_clipplanes[i].normal);
  157. view_clipplanes[i].dist = DotProduct (modelorg, v2);
  158. }
  159. }
  160. #if !(defined __linux__ && defined __i386__)
  161. #if !id386
  162. /*
  163. ================
  164. TransformVector
  165. ================
  166. */
  167. void TransformVector (vec3_t in, vec3_t out)
  168. {
  169. out[0] = DotProduct(in,vright);
  170. out[1] = DotProduct(in,vup);
  171. out[2] = DotProduct(in,vpn);
  172. }
  173. #else
  174. __declspec( naked ) void TransformVector( vec3_t vin, vec3_t vout )
  175. {
  176. __asm mov eax, dword ptr [esp+4]
  177. __asm mov edx, dword ptr [esp+8]
  178. __asm fld dword ptr [eax+0]
  179. __asm fmul dword ptr [vright+0]
  180. __asm fld dword ptr [eax+0]
  181. __asm fmul dword ptr [vup+0]
  182. __asm fld dword ptr [eax+0]
  183. __asm fmul dword ptr [vpn+0]
  184. __asm fld dword ptr [eax+4]
  185. __asm fmul dword ptr [vright+4]
  186. __asm fld dword ptr [eax+4]
  187. __asm fmul dword ptr [vup+4]
  188. __asm fld dword ptr [eax+4]
  189. __asm fmul dword ptr [vpn+4]
  190. __asm fxch st(2)
  191. __asm faddp st(5), st(0)
  192. __asm faddp st(3), st(0)
  193. __asm faddp st(1), st(0)
  194. __asm fld dword ptr [eax+8]
  195. __asm fmul dword ptr [vright+8]
  196. __asm fld dword ptr [eax+8]
  197. __asm fmul dword ptr [vup+8]
  198. __asm fld dword ptr [eax+8]
  199. __asm fmul dword ptr [vpn+8]
  200. __asm fxch st(2)
  201. __asm faddp st(5), st(0)
  202. __asm faddp st(3), st(0)
  203. __asm faddp st(1), st(0)
  204. __asm fstp dword ptr [edx+8]
  205. __asm fstp dword ptr [edx+4]
  206. __asm fstp dword ptr [edx+0]
  207. __asm ret
  208. }
  209. #endif
  210. #endif
  211. /*
  212. ================
  213. R_TransformPlane
  214. ================
  215. */
  216. void R_TransformPlane (mplane_t *p, float *normal, float *dist)
  217. {
  218. float d;
  219. d = DotProduct (r_origin, p->normal);
  220. *dist = p->dist - d;
  221. // TODO: when we have rotating entities, this will need to use the view matrix
  222. TransformVector (p->normal, normal);
  223. }
  224. /*
  225. ===============
  226. R_SetUpFrustumIndexes
  227. ===============
  228. */
  229. void R_SetUpFrustumIndexes (void)
  230. {
  231. int i, j, *pindex;
  232. pindex = r_frustum_indexes;
  233. for (i=0 ; i<4 ; i++)
  234. {
  235. for (j=0 ; j<3 ; j++)
  236. {
  237. if (view_clipplanes[i].normal[j] < 0)
  238. {
  239. pindex[j] = j;
  240. pindex[j+3] = j+3;
  241. }
  242. else
  243. {
  244. pindex[j] = j+3;
  245. pindex[j+3] = j;
  246. }
  247. }
  248. // FIXME: do just once at start
  249. pfrustum_indexes[i] = pindex;
  250. pindex += 6;
  251. }
  252. }
  253. /*
  254. ===============
  255. R_ViewChanged
  256. Called every time the vid structure or r_refdef changes.
  257. Guaranteed to be called before the first refresh
  258. ===============
  259. */
  260. void R_ViewChanged (vrect_t *vr)
  261. {
  262. int i;
  263. r_refdef.vrect = *vr;
  264. r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
  265. verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
  266. r_refdef.fvrectx = (float)r_refdef.vrect.x;
  267. r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
  268. r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
  269. r_refdef.fvrecty = (float)r_refdef.vrect.y;
  270. r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
  271. r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
  272. r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
  273. r_refdef.fvrectright = (float)r_refdef.vrectright;
  274. r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
  275. r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
  276. r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
  277. r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
  278. r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
  279. r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
  280. r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
  281. r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
  282. r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
  283. r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
  284. r_refdef.aliasvrect.width;
  285. r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
  286. r_refdef.aliasvrect.height;
  287. xOrigin = r_refdef.xOrigin;
  288. yOrigin = r_refdef.yOrigin;
  289. // values for perspective projection
  290. // if math were exact, the values would range from 0.5 to to range+0.5
  291. // hopefully they wll be in the 0.000001 to range+.999999 and truncate
  292. // the polygon rasterization will never render in the first row or column
  293. // but will definately render in the [range] row and column, so adjust the
  294. // buffer origin to get an exact edge to edge fill
  295. xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
  296. r_refdef.vrect.x - 0.5;
  297. aliasxcenter = xcenter * r_aliasuvscale;
  298. ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
  299. r_refdef.vrect.y - 0.5;
  300. aliasycenter = ycenter * r_aliasuvscale;
  301. xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
  302. aliasxscale = xscale * r_aliasuvscale;
  303. xscaleinv = 1.0 / xscale;
  304. yscale = xscale;
  305. aliasyscale = yscale * r_aliasuvscale;
  306. yscaleinv = 1.0 / yscale;
  307. xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
  308. yscaleshrink = xscaleshrink;
  309. // left side clip
  310. screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
  311. screenedge[0].normal[1] = 0;
  312. screenedge[0].normal[2] = 1;
  313. screenedge[0].type = PLANE_ANYZ;
  314. // right side clip
  315. screenedge[1].normal[0] =
  316. 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
  317. screenedge[1].normal[1] = 0;
  318. screenedge[1].normal[2] = 1;
  319. screenedge[1].type = PLANE_ANYZ;
  320. // top side clip
  321. screenedge[2].normal[0] = 0;
  322. screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
  323. screenedge[2].normal[2] = 1;
  324. screenedge[2].type = PLANE_ANYZ;
  325. // bottom side clip
  326. screenedge[3].normal[0] = 0;
  327. screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
  328. screenedge[3].normal[2] = 1;
  329. screenedge[3].type = PLANE_ANYZ;
  330. for (i=0 ; i<4 ; i++)
  331. VectorNormalize (screenedge[i].normal);
  332. D_ViewChanged ();
  333. }
  334. /*
  335. ===============
  336. R_SetupFrame
  337. ===============
  338. */
  339. void R_SetupFrame (void)
  340. {
  341. int i;
  342. vrect_t vrect;
  343. if (r_fullbright->modified)
  344. {
  345. r_fullbright->modified = false;
  346. D_FlushCaches (); // so all lighting changes
  347. }
  348. r_framecount++;
  349. // build the transformation matrix for the given view angles
  350. VectorCopy (r_refdef.vieworg, modelorg);
  351. VectorCopy (r_refdef.vieworg, r_origin);
  352. AngleVectors (r_refdef.viewangles, vpn, vright, vup);
  353. // current viewleaf
  354. if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
  355. {
  356. r_viewleaf = Mod_PointInLeaf (r_origin, r_worldmodel);
  357. r_viewcluster = r_viewleaf->cluster;
  358. }
  359. if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
  360. r_dowarp = true;
  361. else
  362. r_dowarp = false;
  363. if (r_dowarp)
  364. { // warp into off screen buffer
  365. vrect.x = 0;
  366. vrect.y = 0;
  367. vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH;
  368. vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT;
  369. d_viewbuffer = r_warpbuffer;
  370. r_screenwidth = WARP_WIDTH;
  371. }
  372. else
  373. {
  374. vrect.x = r_newrefdef.x;
  375. vrect.y = r_newrefdef.y;
  376. vrect.width = r_newrefdef.width;
  377. vrect.height = r_newrefdef.height;
  378. d_viewbuffer = (void *)vid.buffer;
  379. r_screenwidth = vid.rowbytes;
  380. }
  381. R_ViewChanged (&vrect);
  382. // start off with just the four screen edge clip planes
  383. R_TransformFrustum ();
  384. R_SetUpFrustumIndexes ();
  385. // save base values
  386. VectorCopy (vpn, base_vpn);
  387. VectorCopy (vright, base_vright);
  388. VectorCopy (vup, base_vup);
  389. // clear frame counts
  390. c_faceclip = 0;
  391. d_spanpixcount = 0;
  392. r_polycount = 0;
  393. r_drawnpolycount = 0;
  394. r_wholepolycount = 0;
  395. r_amodels_drawn = 0;
  396. r_outofsurfaces = 0;
  397. r_outofedges = 0;
  398. // d_setup
  399. d_roverwrapped = false;
  400. d_initial_rover = sc_rover;
  401. d_minmip = sw_mipcap->value;
  402. if (d_minmip > 3)
  403. d_minmip = 3;
  404. else if (d_minmip < 0)
  405. d_minmip = 0;
  406. for (i=0 ; i<(NUM_MIPS-1) ; i++)
  407. d_scalemip[i] = basemip[i] * sw_mipscale->value;
  408. d_aflatcolor = 0;
  409. }
  410. #if !id386
  411. /*
  412. ================
  413. R_SurfacePatch
  414. ================
  415. */
  416. void R_SurfacePatch (void)
  417. {
  418. // we only patch code on Intel
  419. }
  420. #endif // !id386
  421. /*
  422. ==============================================================================
  423. SCREEN SHOTS
  424. ==============================================================================
  425. */
  426. /*
  427. ==============
  428. WritePCXfile
  429. ==============
  430. */
  431. void WritePCXfile (char *filename, byte *data, int width, int height,
  432. int rowbytes, byte *palette)
  433. {
  434. int i, j, length;
  435. pcx_t *pcx;
  436. byte *pack;
  437. FILE *f;
  438. pcx = (pcx_t *)malloc (width*height*2+1000);
  439. if (!pcx)
  440. return;
  441. pcx->manufacturer = 0x0a; // PCX id
  442. pcx->version = 5; // 256 color
  443. pcx->encoding = 1; // uncompressed
  444. pcx->bits_per_pixel = 8; // 256 color
  445. pcx->xmin = 0;
  446. pcx->ymin = 0;
  447. pcx->xmax = LittleShort((short)(width-1));
  448. pcx->ymax = LittleShort((short)(height-1));
  449. pcx->hres = LittleShort((short)width);
  450. pcx->vres = LittleShort((short)height);
  451. memset (pcx->palette,0,sizeof(pcx->palette));
  452. pcx->color_planes = 1; // chunky image
  453. pcx->bytes_per_line = LittleShort((short)width);
  454. pcx->palette_type = LittleShort(2); // not a grey scale
  455. memset (pcx->filler,0,sizeof(pcx->filler));
  456. // pack the image
  457. pack = &pcx->data;
  458. for (i=0 ; i<height ; i++)
  459. {
  460. for (j=0 ; j<width ; j++)
  461. {
  462. if ( (*data & 0xc0) != 0xc0)
  463. *pack++ = *data++;
  464. else
  465. {
  466. *pack++ = 0xc1;
  467. *pack++ = *data++;
  468. }
  469. }
  470. data += rowbytes - width;
  471. }
  472. // write the palette
  473. *pack++ = 0x0c; // palette ID byte
  474. for (i=0 ; i<768 ; i++)
  475. *pack++ = *palette++;
  476. // write output file
  477. length = pack - (byte *)pcx;
  478. f = fopen (filename, "wb");
  479. if (!f)
  480. ri.Con_Printf (PRINT_ALL, "Failed to open to %s\n", filename);
  481. else
  482. {
  483. fwrite ((void *)pcx, 1, length, f);
  484. fclose (f);
  485. }
  486. free (pcx);
  487. }
  488. /*
  489. ==================
  490. R_ScreenShot_f
  491. ==================
  492. */
  493. void R_ScreenShot_f (void)
  494. {
  495. int i;
  496. char pcxname[80];
  497. char checkname[MAX_OSPATH];
  498. FILE *f;
  499. byte palette[768];
  500. // create the scrnshots directory if it doesn't exist
  501. Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
  502. Sys_Mkdir (checkname);
  503. //
  504. // find a file name to save it to
  505. //
  506. strcpy(pcxname,"quake00.pcx");
  507. for (i=0 ; i<=99 ; i++)
  508. {
  509. pcxname[5] = i/10 + '0';
  510. pcxname[6] = i%10 + '0';
  511. Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
  512. f = fopen (checkname, "r");
  513. if (!f)
  514. break; // file doesn't exist
  515. fclose (f);
  516. }
  517. if (i==100)
  518. {
  519. ri.Con_Printf (PRINT_ALL, "R_ScreenShot_f: Couldn't create a PCX");
  520. return;
  521. }
  522. // turn the current 32 bit palette into a 24 bit palette
  523. for (i=0 ; i<256 ; i++)
  524. {
  525. palette[i*3+0] = sw_state.currentpalette[i*4+0];
  526. palette[i*3+1] = sw_state.currentpalette[i*4+1];
  527. palette[i*3+2] = sw_state.currentpalette[i*4+2];
  528. }
  529. //
  530. // save the pcx file
  531. //
  532. WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes,
  533. palette);
  534. ri.Con_Printf (PRINT_ALL, "Wrote %s\n", checkname);
  535. }