r_surf.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /*
  2. Copyright (C) 1996-1997 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_surf.c: surface-related refresh code
  16. #include "quakedef.h"
  17. #include "r_local.h"
  18. drawsurf_t r_drawsurf;
  19. int lightleft, sourcesstep, blocksize, sourcetstep;
  20. int lightdelta, lightdeltastep;
  21. int lightright, lightleftstep, lightrightstep, blockdivshift;
  22. unsigned blockdivmask;
  23. void *prowdestbase;
  24. unsigned char *pbasesource;
  25. int surfrowbytes; // used by ASM files
  26. unsigned *r_lightptr;
  27. int r_stepback;
  28. int r_lightwidth;
  29. int r_numhblocks, r_numvblocks;
  30. unsigned char *r_source, *r_sourcemax;
  31. void R_DrawSurfaceBlock8_mip0 (void);
  32. void R_DrawSurfaceBlock8_mip1 (void);
  33. void R_DrawSurfaceBlock8_mip2 (void);
  34. void R_DrawSurfaceBlock8_mip3 (void);
  35. static void (*surfmiptable[4])(void) = {
  36. R_DrawSurfaceBlock8_mip0,
  37. R_DrawSurfaceBlock8_mip1,
  38. R_DrawSurfaceBlock8_mip2,
  39. R_DrawSurfaceBlock8_mip3
  40. };
  41. unsigned blocklights[18*18];
  42. /*
  43. ===============
  44. R_AddDynamicLights
  45. ===============
  46. */
  47. void R_AddDynamicLights (void)
  48. {
  49. msurface_t *surf;
  50. int lnum;
  51. int sd, td;
  52. float dist, rad, minlight;
  53. vec3_t impact, local;
  54. int s, t;
  55. int i;
  56. int smax, tmax;
  57. mtexinfo_t *tex;
  58. surf = r_drawsurf.surf;
  59. smax = (surf->extents[0]>>4)+1;
  60. tmax = (surf->extents[1]>>4)+1;
  61. tex = surf->texinfo;
  62. for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
  63. {
  64. if ( !(surf->dlightbits & (1<<lnum) ) )
  65. continue; // not lit by this light
  66. rad = cl_dlights[lnum].radius;
  67. dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
  68. surf->plane->dist;
  69. rad -= fabs(dist);
  70. minlight = cl_dlights[lnum].minlight;
  71. if (rad < minlight)
  72. continue;
  73. minlight = rad - minlight;
  74. for (i=0 ; i<3 ; i++)
  75. {
  76. impact[i] = cl_dlights[lnum].origin[i] -
  77. surf->plane->normal[i]*dist;
  78. }
  79. local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
  80. local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
  81. local[0] -= surf->texturemins[0];
  82. local[1] -= surf->texturemins[1];
  83. for (t = 0 ; t<tmax ; t++)
  84. {
  85. td = local[1] - t*16;
  86. if (td < 0)
  87. td = -td;
  88. for (s=0 ; s<smax ; s++)
  89. {
  90. sd = local[0] - s*16;
  91. if (sd < 0)
  92. sd = -sd;
  93. if (sd > td)
  94. dist = sd + (td>>1);
  95. else
  96. dist = td + (sd>>1);
  97. if (dist < minlight)
  98. blocklights[t*smax + s] += (rad - dist)*256;
  99. }
  100. }
  101. }
  102. }
  103. /*
  104. ===============
  105. R_BuildLightMap
  106. Combine and scale multiple lightmaps into the 8.8 format in blocklights
  107. ===============
  108. */
  109. void R_BuildLightMap (void)
  110. {
  111. int smax, tmax;
  112. int t;
  113. int i, size;
  114. byte *lightmap;
  115. unsigned scale;
  116. int maps;
  117. msurface_t *surf;
  118. surf = r_drawsurf.surf;
  119. smax = (surf->extents[0]>>4)+1;
  120. tmax = (surf->extents[1]>>4)+1;
  121. size = smax*tmax;
  122. lightmap = surf->samples;
  123. if (/* r_fullbright.value || */ !cl.worldmodel->lightdata)
  124. {
  125. for (i=0 ; i<size ; i++)
  126. blocklights[i] = 0;
  127. return;
  128. }
  129. // clear to ambient
  130. for (i=0 ; i<size ; i++)
  131. blocklights[i] = r_refdef.ambientlight<<8;
  132. // add all the lightmaps
  133. if (lightmap)
  134. for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  135. maps++)
  136. {
  137. scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
  138. for (i=0 ; i<size ; i++)
  139. blocklights[i] += lightmap[i] * scale;
  140. lightmap += size; // skip to next lightmap
  141. }
  142. // add all the dynamic lights
  143. if (surf->dlightframe == r_framecount)
  144. R_AddDynamicLights ();
  145. // bound, invert, and shift
  146. for (i=0 ; i<size ; i++)
  147. {
  148. t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
  149. if (t < (1 << 6))
  150. t = (1 << 6);
  151. blocklights[i] = t;
  152. }
  153. }
  154. /*
  155. ===============
  156. R_TextureAnimation
  157. Returns the proper texture for a given time and base texture
  158. ===============
  159. */
  160. texture_t *R_TextureAnimation (texture_t *base)
  161. {
  162. int reletive;
  163. int count;
  164. if (currententity->frame)
  165. {
  166. if (base->alternate_anims)
  167. base = base->alternate_anims;
  168. }
  169. if (!base->anim_total)
  170. return base;
  171. reletive = (int)(cl.time*10) % base->anim_total;
  172. count = 0;
  173. while (base->anim_min > reletive || base->anim_max <= reletive)
  174. {
  175. base = base->anim_next;
  176. if (!base)
  177. Sys_Error ("R_TextureAnimation: broken cycle");
  178. if (++count > 100)
  179. Sys_Error ("R_TextureAnimation: infinite cycle");
  180. }
  181. return base;
  182. }
  183. /*
  184. ===============
  185. R_DrawSurface
  186. ===============
  187. */
  188. void R_DrawSurface (void)
  189. {
  190. unsigned char *basetptr;
  191. int smax, tmax, twidth;
  192. int u;
  193. int soffset, basetoffset, texwidth;
  194. int horzblockstep;
  195. unsigned char *pcolumndest;
  196. void (*pblockdrawer)(void);
  197. texture_t *mt;
  198. // calculate the lightings
  199. R_BuildLightMap ();
  200. surfrowbytes = r_drawsurf.rowbytes;
  201. mt = r_drawsurf.texture;
  202. r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
  203. // the fractional light values should range from 0 to (VID_GRADES - 1) << 16
  204. // from a source range of 0 - 255
  205. texwidth = mt->width >> r_drawsurf.surfmip;
  206. blocksize = 16 >> r_drawsurf.surfmip;
  207. blockdivshift = 4 - r_drawsurf.surfmip;
  208. blockdivmask = (1 << blockdivshift) - 1;
  209. r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
  210. r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
  211. r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
  212. //==============================
  213. if (r_pixbytes == 1)
  214. {
  215. pblockdrawer = surfmiptable[r_drawsurf.surfmip];
  216. // TODO: only needs to be set when there is a display settings change
  217. horzblockstep = blocksize;
  218. }
  219. else
  220. {
  221. pblockdrawer = R_DrawSurfaceBlock16;
  222. // TODO: only needs to be set when there is a display settings change
  223. horzblockstep = blocksize << 1;
  224. }
  225. smax = mt->width >> r_drawsurf.surfmip;
  226. twidth = texwidth;
  227. tmax = mt->height >> r_drawsurf.surfmip;
  228. sourcetstep = texwidth;
  229. r_stepback = tmax * twidth;
  230. r_sourcemax = r_source + (tmax * smax);
  231. soffset = r_drawsurf.surf->texturemins[0];
  232. basetoffset = r_drawsurf.surf->texturemins[1];
  233. // << 16 components are to guarantee positive values for %
  234. soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
  235. basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
  236. + (tmax << 16)) % tmax) * twidth)];
  237. pcolumndest = r_drawsurf.surfdat;
  238. for (u=0 ; u<r_numhblocks; u++)
  239. {
  240. r_lightptr = blocklights + u;
  241. prowdestbase = pcolumndest;
  242. pbasesource = basetptr + soffset;
  243. (*pblockdrawer)();
  244. soffset = soffset + blocksize;
  245. if (soffset >= smax)
  246. soffset = 0;
  247. pcolumndest += horzblockstep;
  248. }
  249. }
  250. //=============================================================================
  251. #if !id386
  252. /*
  253. ================
  254. R_DrawSurfaceBlock8_mip0
  255. ================
  256. */
  257. void R_DrawSurfaceBlock8_mip0 (void)
  258. {
  259. int v, i, b, lightstep, lighttemp, light;
  260. unsigned char pix, *psource, *prowdest;
  261. psource = pbasesource;
  262. prowdest = prowdestbase;
  263. for (v=0 ; v<r_numvblocks ; v++)
  264. {
  265. // FIXME: make these locals?
  266. // FIXME: use delta rather than both right and left, like ASM?
  267. lightleft = r_lightptr[0];
  268. lightright = r_lightptr[1];
  269. r_lightptr += r_lightwidth;
  270. lightleftstep = (r_lightptr[0] - lightleft) >> 4;
  271. lightrightstep = (r_lightptr[1] - lightright) >> 4;
  272. for (i=0 ; i<16 ; i++)
  273. {
  274. lighttemp = lightleft - lightright;
  275. lightstep = lighttemp >> 4;
  276. light = lightright;
  277. for (b=15; b>=0; b--)
  278. {
  279. pix = psource[b];
  280. prowdest[b] = ((unsigned char *)vid.colormap)
  281. [(light & 0xFF00) + pix];
  282. light += lightstep;
  283. }
  284. psource += sourcetstep;
  285. lightright += lightrightstep;
  286. lightleft += lightleftstep;
  287. prowdest += surfrowbytes;
  288. }
  289. if (psource >= r_sourcemax)
  290. psource -= r_stepback;
  291. }
  292. }
  293. /*
  294. ================
  295. R_DrawSurfaceBlock8_mip1
  296. ================
  297. */
  298. void R_DrawSurfaceBlock8_mip1 (void)
  299. {
  300. int v, i, b, lightstep, lighttemp, light;
  301. unsigned char pix, *psource, *prowdest;
  302. psource = pbasesource;
  303. prowdest = prowdestbase;
  304. for (v=0 ; v<r_numvblocks ; v++)
  305. {
  306. // FIXME: make these locals?
  307. // FIXME: use delta rather than both right and left, like ASM?
  308. lightleft = r_lightptr[0];
  309. lightright = r_lightptr[1];
  310. r_lightptr += r_lightwidth;
  311. lightleftstep = (r_lightptr[0] - lightleft) >> 3;
  312. lightrightstep = (r_lightptr[1] - lightright) >> 3;
  313. for (i=0 ; i<8 ; i++)
  314. {
  315. lighttemp = lightleft - lightright;
  316. lightstep = lighttemp >> 3;
  317. light = lightright;
  318. for (b=7; b>=0; b--)
  319. {
  320. pix = psource[b];
  321. prowdest[b] = ((unsigned char *)vid.colormap)
  322. [(light & 0xFF00) + pix];
  323. light += lightstep;
  324. }
  325. psource += sourcetstep;
  326. lightright += lightrightstep;
  327. lightleft += lightleftstep;
  328. prowdest += surfrowbytes;
  329. }
  330. if (psource >= r_sourcemax)
  331. psource -= r_stepback;
  332. }
  333. }
  334. /*
  335. ================
  336. R_DrawSurfaceBlock8_mip2
  337. ================
  338. */
  339. void R_DrawSurfaceBlock8_mip2 (void)
  340. {
  341. int v, i, b, lightstep, lighttemp, light;
  342. unsigned char pix, *psource, *prowdest;
  343. psource = pbasesource;
  344. prowdest = prowdestbase;
  345. for (v=0 ; v<r_numvblocks ; v++)
  346. {
  347. // FIXME: make these locals?
  348. // FIXME: use delta rather than both right and left, like ASM?
  349. lightleft = r_lightptr[0];
  350. lightright = r_lightptr[1];
  351. r_lightptr += r_lightwidth;
  352. lightleftstep = (r_lightptr[0] - lightleft) >> 2;
  353. lightrightstep = (r_lightptr[1] - lightright) >> 2;
  354. for (i=0 ; i<4 ; i++)
  355. {
  356. lighttemp = lightleft - lightright;
  357. lightstep = lighttemp >> 2;
  358. light = lightright;
  359. for (b=3; b>=0; b--)
  360. {
  361. pix = psource[b];
  362. prowdest[b] = ((unsigned char *)vid.colormap)
  363. [(light & 0xFF00) + pix];
  364. light += lightstep;
  365. }
  366. psource += sourcetstep;
  367. lightright += lightrightstep;
  368. lightleft += lightleftstep;
  369. prowdest += surfrowbytes;
  370. }
  371. if (psource >= r_sourcemax)
  372. psource -= r_stepback;
  373. }
  374. }
  375. /*
  376. ================
  377. R_DrawSurfaceBlock8_mip3
  378. ================
  379. */
  380. void R_DrawSurfaceBlock8_mip3 (void)
  381. {
  382. int v, i, b, lightstep, lighttemp, light;
  383. unsigned char pix, *psource, *prowdest;
  384. psource = pbasesource;
  385. prowdest = prowdestbase;
  386. for (v=0 ; v<r_numvblocks ; v++)
  387. {
  388. // FIXME: make these locals?
  389. // FIXME: use delta rather than both right and left, like ASM?
  390. lightleft = r_lightptr[0];
  391. lightright = r_lightptr[1];
  392. r_lightptr += r_lightwidth;
  393. lightleftstep = (r_lightptr[0] - lightleft) >> 1;
  394. lightrightstep = (r_lightptr[1] - lightright) >> 1;
  395. for (i=0 ; i<2 ; i++)
  396. {
  397. lighttemp = lightleft - lightright;
  398. lightstep = lighttemp >> 1;
  399. light = lightright;
  400. for (b=1; b>=0; b--)
  401. {
  402. pix = psource[b];
  403. prowdest[b] = ((unsigned char *)vid.colormap)
  404. [(light & 0xFF00) + pix];
  405. light += lightstep;
  406. }
  407. psource += sourcetstep;
  408. lightright += lightrightstep;
  409. lightleft += lightleftstep;
  410. prowdest += surfrowbytes;
  411. }
  412. if (psource >= r_sourcemax)
  413. psource -= r_stepback;
  414. }
  415. }
  416. /*
  417. ================
  418. R_DrawSurfaceBlock16
  419. FIXME: make this work
  420. ================
  421. */
  422. void R_DrawSurfaceBlock16 (void)
  423. {
  424. int k;
  425. unsigned char *psource;
  426. int lighttemp, lightstep, light;
  427. unsigned short *prowdest;
  428. prowdest = (unsigned short *)prowdestbase;
  429. for (k=0 ; k<blocksize ; k++)
  430. {
  431. unsigned short *pdest;
  432. unsigned char pix;
  433. int b;
  434. psource = pbasesource;
  435. lighttemp = lightright - lightleft;
  436. lightstep = lighttemp >> blockdivshift;
  437. light = lightleft;
  438. pdest = prowdest;
  439. for (b=0; b<blocksize; b++)
  440. {
  441. pix = *psource;
  442. *pdest = vid.colormap16[(light & 0xFF00) + pix];
  443. psource += sourcesstep;
  444. pdest++;
  445. light += lightstep;
  446. }
  447. pbasesource += sourcetstep;
  448. lightright += lightrightstep;
  449. lightleft += lightleftstep;
  450. prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
  451. }
  452. prowdestbase = prowdest;
  453. }
  454. #endif
  455. //============================================================================
  456. /*
  457. ================
  458. R_GenTurbTile
  459. ================
  460. */
  461. void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
  462. {
  463. int *turb;
  464. int i, j, s, t;
  465. byte *pd;
  466. turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  467. pd = (byte *)pdest;
  468. for (i=0 ; i<TILE_SIZE ; i++)
  469. {
  470. for (j=0 ; j<TILE_SIZE ; j++)
  471. {
  472. s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
  473. t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
  474. *pd++ = *(pbasetex + (t<<6) + s);
  475. }
  476. }
  477. }
  478. /*
  479. ================
  480. R_GenTurbTile16
  481. ================
  482. */
  483. void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
  484. {
  485. int *turb;
  486. int i, j, s, t;
  487. unsigned short *pd;
  488. turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  489. pd = (unsigned short *)pdest;
  490. for (i=0 ; i<TILE_SIZE ; i++)
  491. {
  492. for (j=0 ; j<TILE_SIZE ; j++)
  493. {
  494. s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
  495. t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
  496. *pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
  497. }
  498. }
  499. }
  500. /*
  501. ================
  502. R_GenTile
  503. ================
  504. */
  505. void R_GenTile (msurface_t *psurf, void *pdest)
  506. {
  507. if (psurf->flags & SURF_DRAWTURB)
  508. {
  509. if (r_pixbytes == 1)
  510. {
  511. R_GenTurbTile ((pixel_t *)
  512. ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
  513. }
  514. else
  515. {
  516. R_GenTurbTile16 ((pixel_t *)
  517. ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
  518. }
  519. }
  520. else if (psurf->flags & SURF_DRAWSKY)
  521. {
  522. if (r_pixbytes == 1)
  523. {
  524. R_GenSkyTile (pdest);
  525. }
  526. else
  527. {
  528. R_GenSkyTile16 (pdest);
  529. }
  530. }
  531. else
  532. {
  533. Sys_Error ("Unknown tile type");
  534. }
  535. }