r_surf.c 14 KB

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