R_DATA.C 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. //**************************************************************************
  2. //**
  3. //** r_data.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: r_data.c,v $
  6. //** $Revision: 1.8 $
  7. //** $Date: 96/03/12 12:04:04 $
  8. //** $Author: bgokey $
  9. //**
  10. //**************************************************************************
  11. #include "h2def.h"
  12. #include "r_local.h"
  13. #include "p_local.h"
  14. typedef struct
  15. {
  16. int originx; // block origin (allways UL), which has allready
  17. int originy; // accounted for the patch's internal origin
  18. int patch;
  19. } texpatch_t;
  20. // a maptexturedef_t describes a rectangular texture, which is composed of one
  21. // or more mappatch_t structures that arrange graphic patches
  22. typedef struct
  23. {
  24. char name[8]; // for switch changing, etc
  25. short width;
  26. short height;
  27. short patchcount;
  28. texpatch_t patches[1]; // [patchcount] drawn back to front
  29. // into the cached texture
  30. } texture_t;
  31. int firstflat, lastflat, numflats;
  32. int firstpatch, lastpatch, numpatches;
  33. int firstspritelump, lastspritelump, numspritelumps;
  34. int numtextures;
  35. texture_t **textures;
  36. int *texturewidthmask;
  37. fixed_t *textureheight; // needed for texture pegging
  38. int *texturecompositesize;
  39. short **texturecolumnlump;
  40. unsigned short **texturecolumnofs;
  41. byte **texturecomposite;
  42. int *flattranslation; // for global animation
  43. int *texturetranslation; // for global animation
  44. fixed_t *spritewidth; // needed for pre rendering
  45. fixed_t *spriteoffset;
  46. fixed_t *spritetopoffset;
  47. lighttable_t *colormaps;
  48. /*
  49. ==============================================================================
  50. MAPTEXTURE_T CACHING
  51. when a texture is first needed, it counts the number of composite columns
  52. required in the texture and allocates space for a column directory and any
  53. new columns. The directory will simply point inside other patches if there
  54. is only one patch in a given column, but any columns with multiple patches
  55. will have new column_ts generated.
  56. ==============================================================================
  57. */
  58. /*
  59. ===================
  60. =
  61. = R_DrawColumnInCache
  62. =
  63. = Clip and draw a column from a patch into a cached post
  64. =
  65. ===================
  66. */
  67. void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight)
  68. {
  69. int count, position;
  70. byte *source, *dest;
  71. dest = (byte *)cache + 3;
  72. while (patch->topdelta != 0xff)
  73. {
  74. source = (byte *)patch + 3;
  75. count = patch->length;
  76. position = originy + patch->topdelta;
  77. if (position < 0)
  78. {
  79. count += position;
  80. position = 0;
  81. }
  82. if (position + count > cacheheight)
  83. count = cacheheight - position;
  84. if (count > 0)
  85. memcpy (cache + position, source, count);
  86. patch = (column_t *)( (byte *)patch + patch->length + 4);
  87. }
  88. }
  89. /*
  90. ===================
  91. =
  92. = R_GenerateComposite
  93. =
  94. ===================
  95. */
  96. void R_GenerateComposite (int texnum)
  97. {
  98. byte *block;
  99. texture_t *texture;
  100. texpatch_t *patch;
  101. patch_t *realpatch;
  102. int x, x1, x2;
  103. int i;
  104. column_t *patchcol;
  105. short *collump;
  106. unsigned short *colofs;
  107. texture = textures[texnum];
  108. block = Z_Malloc (texturecompositesize[texnum], PU_STATIC,
  109. &texturecomposite[texnum]);
  110. collump = texturecolumnlump[texnum];
  111. colofs = texturecolumnofs[texnum];
  112. //
  113. // composite the columns together
  114. //
  115. patch = texture->patches;
  116. for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
  117. {
  118. realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  119. x1 = patch->originx;
  120. x2 = x1 + SHORT(realpatch->width);
  121. if (x1<0)
  122. x = 0;
  123. else
  124. x = x1;
  125. if (x2 > texture->width)
  126. x2 = texture->width;
  127. for ( ; x<x2 ; x++)
  128. {
  129. if (collump[x] >= 0)
  130. continue; // column does not have multiple patches
  131. patchcol = (column_t *)((byte *)realpatch +
  132. LONG(realpatch->columnofs[x-x1]));
  133. R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy,
  134. texture->height);
  135. }
  136. }
  137. // now that the texture has been built, it is purgable
  138. Z_ChangeTag (block, PU_CACHE);
  139. }
  140. /*
  141. ===================
  142. =
  143. = R_GenerateLookup
  144. =
  145. ===================
  146. */
  147. void R_GenerateLookup (int texnum)
  148. {
  149. texture_t *texture;
  150. byte *patchcount; // [texture->width]
  151. texpatch_t *patch;
  152. patch_t *realpatch;
  153. int x, x1, x2;
  154. int i;
  155. short *collump;
  156. unsigned short *colofs;
  157. texture = textures[texnum];
  158. texturecomposite[texnum] = 0; // composited not created yet
  159. texturecompositesize[texnum] = 0;
  160. collump = texturecolumnlump[texnum];
  161. colofs = texturecolumnofs[texnum];
  162. //
  163. // count the number of columns that are covered by more than one patch
  164. // fill in the lump / offset, so columns with only a single patch are
  165. // all done
  166. //
  167. patchcount = (byte *)alloca (texture->width);
  168. memset (patchcount, 0, texture->width);
  169. patch = texture->patches;
  170. for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
  171. {
  172. realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  173. x1 = patch->originx;
  174. x2 = x1 + SHORT(realpatch->width);
  175. if (x1 < 0)
  176. x = 0;
  177. else
  178. x = x1;
  179. if (x2 > texture->width)
  180. x2 = texture->width;
  181. for ( ; x<x2 ; x++)
  182. {
  183. patchcount[x]++;
  184. collump[x] = patch->patch;
  185. colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
  186. }
  187. }
  188. for (x=0 ; x<texture->width ; x++)
  189. {
  190. if (!patchcount[x])
  191. {
  192. ST_Message ("R_GenerateLookup: column without a patch (%s)\n", texture->name);
  193. return;
  194. }
  195. // I_Error ("R_GenerateLookup: column without a patch");
  196. if (patchcount[x] > 1)
  197. {
  198. collump[x] = -1; // use the cached block
  199. colofs[x] = texturecompositesize[texnum];
  200. if (texturecompositesize[texnum] > 0x10000-texture->height)
  201. I_Error ("R_GenerateLookup: texture %i is >64k",texnum);
  202. texturecompositesize[texnum] += texture->height;
  203. }
  204. }
  205. }
  206. /*
  207. ================
  208. =
  209. = R_GetColumn
  210. =
  211. ================
  212. */
  213. byte *R_GetColumn (int tex, int col)
  214. {
  215. int lump, ofs;
  216. col &= texturewidthmask[tex];
  217. lump = texturecolumnlump[tex][col];
  218. ofs = texturecolumnofs[tex][col];
  219. if (lump > 0)
  220. return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
  221. if (!texturecomposite[tex])
  222. R_GenerateComposite (tex);
  223. return texturecomposite[tex] + ofs;
  224. }
  225. /*
  226. ==================
  227. =
  228. = R_InitTextures
  229. =
  230. = Initializes the texture list with the textures from the world map
  231. =
  232. ==================
  233. */
  234. void R_InitTextures (void)
  235. {
  236. maptexture_t *mtexture;
  237. texture_t *texture;
  238. mappatch_t *mpatch;
  239. texpatch_t *patch;
  240. int i,j;
  241. int *maptex, *maptex2, *maptex1;
  242. char name[9], *names, *name_p;
  243. int *patchlookup;
  244. int totalwidth;
  245. int nummappatches;
  246. int offset, maxoff, maxoff2;
  247. int numtextures1, numtextures2;
  248. int *directory;
  249. //
  250. // load the patch names from pnames.lmp
  251. //
  252. name[8] = 0;
  253. names = W_CacheLumpName ("PNAMES", PU_STATIC);
  254. nummappatches = LONG ( *((int *)names) );
  255. name_p = names+4;
  256. patchlookup = alloca (nummappatches*sizeof(*patchlookup));
  257. for (i=0 ; i<nummappatches ; i++)
  258. {
  259. strncpy (name,name_p+i*8, 8);
  260. patchlookup[i] = W_CheckNumForName (name);
  261. }
  262. Z_Free (names);
  263. //
  264. // load the map texture definitions from textures.lmp
  265. //
  266. maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
  267. numtextures1 = LONG(*maptex);
  268. maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
  269. directory = maptex+1;
  270. if (W_CheckNumForName ("TEXTURE2") != -1)
  271. {
  272. maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
  273. numtextures2 = LONG(*maptex2);
  274. maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
  275. }
  276. else
  277. {
  278. maptex2 = NULL;
  279. numtextures2 = 0;
  280. maxoff2 = 0;
  281. }
  282. numtextures = numtextures1 + numtextures2;
  283. textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
  284. texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
  285. texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
  286. texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
  287. texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
  288. texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
  289. textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
  290. totalwidth = 0;
  291. for (i=0 ; i<numtextures ; i++, directory++)
  292. {
  293. if (i == numtextures1)
  294. { // start looking in second texture file
  295. maptex = maptex2;
  296. maxoff = maxoff2;
  297. directory = maptex+1;
  298. }
  299. offset = LONG(*directory);
  300. if (offset > maxoff)
  301. I_Error ("R_InitTextures: bad texture directory");
  302. mtexture = (maptexture_t *) ( (byte *)maptex + offset);
  303. texture = textures[i] = Z_Malloc (sizeof(texture_t)
  304. + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), PU_STATIC,
  305. 0);
  306. texture->width = SHORT(mtexture->width);
  307. texture->height = SHORT(mtexture->height);
  308. texture->patchcount = SHORT(mtexture->patchcount);
  309. memcpy (texture->name, mtexture->name, sizeof(texture->name));
  310. mpatch = &mtexture->patches[0];
  311. patch = &texture->patches[0];
  312. for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
  313. {
  314. patch->originx = SHORT(mpatch->originx);
  315. patch->originy = SHORT(mpatch->originy);
  316. patch->patch = patchlookup[SHORT(mpatch->patch)];
  317. if (patch->patch == -1)
  318. I_Error (
  319. "R_InitTextures: Missing patch in texture %s",texture->name);
  320. }
  321. texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  322. texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  323. j = 1;
  324. while (j*2 <= texture->width)
  325. j<<=1;
  326. texturewidthmask[i] = j-1;
  327. textureheight[i] = texture->height<<FRACBITS;
  328. totalwidth += texture->width;
  329. }
  330. Z_Free (maptex1);
  331. if (maptex2)
  332. Z_Free (maptex2);
  333. //
  334. // precalculate whatever possible
  335. //
  336. for (i=0 ; i<numtextures ; i++)
  337. {
  338. R_GenerateLookup (i);
  339. if(!(i&31)) ST_Progress();
  340. }
  341. //
  342. // translation table for global animation
  343. //
  344. texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
  345. for (i=0 ; i<numtextures ; i++)
  346. texturetranslation[i] = i;
  347. }
  348. /*
  349. ================
  350. =
  351. = R_InitFlats
  352. =
  353. =================
  354. */
  355. void R_InitFlats (void)
  356. {
  357. int i;
  358. firstflat = W_GetNumForName ("F_START") + 1;
  359. lastflat = W_GetNumForName ("F_END") - 1;
  360. numflats = lastflat - firstflat + 1;
  361. // translation table for global animation
  362. flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
  363. for (i=0 ; i<numflats ; i++)
  364. flattranslation[i] = i;
  365. }
  366. /*
  367. ================
  368. =
  369. = R_InitSpriteLumps
  370. =
  371. = Finds the width and hoffset of all sprites in the wad, so the sprite doesn't
  372. = need to be cached just for the header during rendering
  373. =================
  374. */
  375. void R_InitSpriteLumps (void)
  376. {
  377. int i;
  378. patch_t *patch;
  379. firstspritelump = W_GetNumForName ("S_START") + 1;
  380. lastspritelump = W_GetNumForName ("S_END") - 1;
  381. numspritelumps = lastspritelump - firstspritelump + 1;
  382. spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  383. spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  384. spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  385. for (i=0 ; i< numspritelumps ; i++)
  386. {
  387. if (!(i&127)) ST_Progress();
  388. patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
  389. spritewidth[i] = SHORT(patch->width)<<FRACBITS;
  390. spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
  391. spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
  392. }
  393. }
  394. /*
  395. ================
  396. =
  397. = R_InitColormaps
  398. =
  399. =================
  400. */
  401. void R_InitColormaps (void)
  402. {
  403. int lump, length;
  404. //
  405. // load in the light tables
  406. // 256 byte align tables
  407. //
  408. lump = W_GetNumForName("COLORMAP");
  409. length = W_LumpLength (lump) + 255;
  410. colormaps = Z_Malloc (length, PU_STATIC, 0);
  411. colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
  412. W_ReadLump (lump,colormaps);
  413. }
  414. /*
  415. ================
  416. =
  417. = R_InitData
  418. =
  419. = Locates all the lumps that will be used by all views
  420. = Must be called after W_Init
  421. =================
  422. */
  423. void R_InitData (void)
  424. {
  425. R_InitTextures();
  426. R_InitFlats();
  427. R_InitSpriteLumps();
  428. R_InitColormaps();
  429. }
  430. //=============================================================================
  431. /*
  432. ================
  433. =
  434. = R_FlatNumForName
  435. =
  436. ================
  437. */
  438. int R_FlatNumForName (char *name)
  439. {
  440. int i;
  441. char namet[9];
  442. i = W_CheckNumForName (name);
  443. if (i == -1)
  444. {
  445. namet[8] = 0;
  446. memcpy (namet, name,8);
  447. I_Error ("R_FlatNumForName: %s not found",namet);
  448. }
  449. return i - firstflat;
  450. }
  451. /*
  452. ================
  453. =
  454. = R_CheckTextureNumForName
  455. =
  456. ================
  457. */
  458. int R_CheckTextureNumForName (char *name)
  459. {
  460. int i;
  461. if (name[0] == '-') // no texture marker
  462. return 0;
  463. for (i=0 ; i<numtextures ; i++)
  464. if (!strncasecmp (textures[i]->name, name, 8) )
  465. return i;
  466. return -1;
  467. }
  468. /*
  469. ================
  470. =
  471. = R_TextureNumForName
  472. =
  473. ================
  474. */
  475. int R_TextureNumForName (char *name)
  476. {
  477. int i;
  478. //char namet[9];
  479. i = R_CheckTextureNumForName (name);
  480. if (i==-1)
  481. I_Error ("R_TextureNumForName: %s not found",name);
  482. return i;
  483. }
  484. /*
  485. =================
  486. =
  487. = R_PrecacheLevel
  488. =
  489. = Preloads all relevent graphics for the level
  490. =================
  491. */
  492. int flatmemory, texturememory, spritememory;
  493. void R_PrecacheLevel (void)
  494. {
  495. char *flatpresent;
  496. char *texturepresent;
  497. char *spritepresent;
  498. int i,j,k, lump;
  499. texture_t *texture;
  500. thinker_t *th;
  501. spriteframe_t *sf;
  502. if (demoplayback)
  503. return;
  504. //
  505. // precache flats
  506. //
  507. flatpresent = alloca(numflats);
  508. memset (flatpresent,0,numflats);
  509. for (i=0 ; i<numsectors ; i++)
  510. {
  511. flatpresent[sectors[i].floorpic] = 1;
  512. flatpresent[sectors[i].ceilingpic] = 1;
  513. }
  514. flatmemory = 0;
  515. for (i=0 ; i<numflats ; i++)
  516. if (flatpresent[i])
  517. {
  518. lump = firstflat + i;
  519. flatmemory += lumpinfo[lump].size;
  520. W_CacheLumpNum(lump, PU_CACHE);
  521. }
  522. //
  523. // precache textures
  524. //
  525. texturepresent = alloca(numtextures);
  526. memset (texturepresent,0, numtextures);
  527. for (i=0 ; i<numsides ; i++)
  528. {
  529. texturepresent[sides[i].toptexture] = 1;
  530. texturepresent[sides[i].midtexture] = 1;
  531. texturepresent[sides[i].bottomtexture] = 1;
  532. }
  533. texturepresent[Sky1Texture] = 1;
  534. texturepresent[Sky2Texture] = 1;
  535. texturememory = 0;
  536. for (i=0 ; i<numtextures ; i++)
  537. {
  538. if (!texturepresent[i])
  539. continue;
  540. texture = textures[i];
  541. for (j=0 ; j<texture->patchcount ; j++)
  542. {
  543. lump = texture->patches[j].patch;
  544. texturememory += lumpinfo[lump].size;
  545. W_CacheLumpNum(lump , PU_CACHE);
  546. }
  547. }
  548. //
  549. // precache sprites
  550. //
  551. spritepresent = alloca(numsprites);
  552. memset (spritepresent,0, numsprites);
  553. for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  554. {
  555. if (th->function == P_MobjThinker)
  556. spritepresent[((mobj_t *)th)->sprite] = 1;
  557. }
  558. spritememory = 0;
  559. for (i=0 ; i<numsprites ; i++)
  560. {
  561. if (!spritepresent[i])
  562. continue;
  563. for (j=0 ; j<sprites[i].numframes ; j++)
  564. {
  565. sf = &sprites[i].spriteframes[j];
  566. for (k=0 ; k<8 ; k++)
  567. {
  568. lump = firstspritelump + sf->lump[k];
  569. spritememory += lumpinfo[lump].size;
  570. W_CacheLumpNum(lump , PU_CACHE);
  571. }
  572. }
  573. }
  574. }