Advertisement
Guest User

Untitled

a guest
Sep 26th, 2016
426
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.80 KB | None | 0 0
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Refresh of things, i.e. objects represented by sprites.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26.  
  27. #include "templates.h"
  28. #include "m_alloc.h"
  29. #include "doomdef.h"
  30. #include "m_swap.h"
  31. #include "m_argv.h"
  32. #include "i_system.h"
  33. #include "z_zone.h"
  34. #include "w_wad.h"
  35. #include "r_local.h"
  36. #include "p_effect.h"
  37. #include "c_console.h"
  38. #include "c_cvars.h"
  39. #include "c_dispatch.h"
  40. #include "doomstat.h"
  41. #include "v_video.h"
  42. #include "sc_man.h"
  43. #include "s_sound.h"
  44. #include "sbar.h"
  45. #include "gi.h"
  46.  
  47. extern fixed_t globaluclip, globaldclip;
  48.  
  49.  
  50. #define MINZ (2048*4)
  51. #define BASEYCENTER (100)
  52.  
  53. EXTERN_CVAR (Bool, st_scale)
  54. CVAR (Bool, r_drawfuzz, true, CVAR_ARCHIVE)
  55.  
  56.  
  57. //
  58. // Sprite rotation 0 is facing the viewer,
  59. // rotation 1 is one angle turn CLOCKWISE around the axis.
  60. // This is not the same as the angle,
  61. // which increases counter clockwise (protractor).
  62. //
  63. fixed_t pspritexscale;
  64. fixed_t pspriteyscale;
  65. fixed_t pspritexiscale;
  66. fixed_t sky1scale; // [RH] Sky 1 scale factor
  67. fixed_t sky2scale; // [RH] Sky 2 scale factor
  68.  
  69. static int spriteshade;
  70.  
  71. TArray<WORD> ParticlesInSubsec;
  72.  
  73. // constant arrays
  74. // used for psprite clipping and initializing clipping
  75. short negonearray[MAXWIDTH];
  76. short screenheightarray[MAXWIDTH];
  77.  
  78. #define MAX_SPRITE_FRAMES 29 // [RH] Macro-ized as in BOOM.
  79.  
  80.  
  81. CVAR (Bool, r_drawplayersprites, true, 0) // [RH] Draw player sprites?
  82.  
  83. //
  84. // INITIALIZATION FUNCTIONS
  85. //
  86.  
  87. // variables used to look up
  88. // and range check thing_t sprites patches
  89. TArray<spritedef_t> sprites;
  90.  
  91. spriteframe_t sprtemp[MAX_SPRITE_FRAMES];
  92. int maxframe;
  93. char* spritename;
  94.  
  95. // [RH] skin globals
  96. FPlayerSkin *skins;
  97. size_t numskins;
  98.  
  99. // [RH] particle globals
  100. int NumParticles;
  101. int ActiveParticles;
  102. int InactiveParticles;
  103. particle_t *Particles;
  104.  
  105. CVAR (Bool, r_particles, true, 0);
  106.  
  107.  
  108. //
  109. // R_InstallSpriteLump
  110. // Local function for R_InitSprites.
  111. //
  112. // [RH] Removed checks for coexistance of rotation 0 with other
  113. // rotations and made it look more like BOOM's version.
  114. //
  115. static void R_InstallSpriteLump (int lump, unsigned frame, char rot, BOOL flipped)
  116. {
  117. unsigned rotation;
  118.  
  119. if (rot >= '0' && rot <= '9')
  120. {
  121. rotation = rot - '0';
  122. }
  123. else if (rot >= 'A')
  124. {
  125. rotation = rot - 'A' + 10;
  126. }
  127. else
  128. {
  129. rotation = 17;
  130. }
  131.  
  132. if (frame >= MAX_SPRITE_FRAMES || rotation > 16)
  133. I_FatalError ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
  134.  
  135. if ((int)frame > maxframe)
  136. maxframe = frame;
  137.  
  138. if (rotation == 0)
  139. {
  140. // the lump should be used for all rotations
  141. // false=0, true=1, but array initialised to -1
  142. // allows doom to have a "no value set yet" boolean value!
  143. int r;
  144.  
  145. for (r = 14; r >= 0; r -= 2)
  146. {
  147. if (sprtemp[frame].lump[r] == -1)
  148. {
  149. sprtemp[frame].lump[r] = (short)(lump);
  150. if (flipped)
  151. {
  152. sprtemp[frame].flip |= 1 << r;
  153. }
  154. sprtemp[frame].rotate = false;
  155. }
  156. }
  157. }
  158. else
  159. {
  160. if (rotation <= 8)
  161. {
  162. rotation = (rotation - 1) * 2;
  163. }
  164. else
  165. {
  166. rotation = (rotation - 9) * 2 + 1;
  167. }
  168.  
  169. if (sprtemp[frame].lump[rotation] == -1)
  170. {
  171. // the lump is only used for one rotation
  172. sprtemp[frame].lump[rotation] = (short)(lump);
  173. if (flipped)
  174. {
  175. sprtemp[frame].flip |= 1 << rotation;
  176. }
  177. sprtemp[frame].rotate = true;
  178. }
  179. }
  180. }
  181.  
  182.  
  183. // [RH] Seperated out of R_InitSpriteDefs()
  184. static void R_InstallSprite (int num)
  185. {
  186. int frame;
  187.  
  188. if (maxframe == -1)
  189. {
  190. sprites[num].numframes = 0;
  191. return;
  192. }
  193.  
  194. maxframe++;
  195.  
  196. for (frame = 0; frame < maxframe; frame++)
  197. {
  198. switch ((int)sprtemp[frame].rotate)
  199. {
  200. case -1:
  201. // no rotations were found for that frame at all
  202. I_FatalError ("R_InstallSprite: No patches found for %s frame %c", sprites[num].name, frame+'A');
  203. break;
  204.  
  205. case 0:
  206. // only the first rotation is needed
  207. break;
  208.  
  209. case 1:
  210. // must have all 8 frame pairs
  211. {
  212. int rot;
  213.  
  214. for (rot = 0; rot < 8; ++rot)
  215. {
  216. if (sprtemp[frame].lump[rot*2+1] == -1)
  217. {
  218. sprtemp[frame].lump[rot*2+1] = sprtemp[frame].lump[rot*2];
  219. if (sprtemp[frame].flip & (1 << (rot*2)))
  220. {
  221. sprtemp[frame].flip |= 1 << (rot*2+1);
  222. }
  223. }
  224. if (sprtemp[frame].lump[rot*2] == -1)
  225. {
  226. sprtemp[frame].lump[rot*2] = sprtemp[frame].lump[rot*2+1];
  227. if (sprtemp[frame].flip & (1 << (rot*2+1)))
  228. {
  229. sprtemp[frame].flip |= 1 << (rot*2);
  230. }
  231. }
  232.  
  233. }
  234. for (rot = 0; rot < 16; ++rot)
  235. {
  236. if (sprtemp[frame].lump[rot] == -1)
  237. I_FatalError ("R_InstallSprite: Sprite %c%c%c%c frame %c is missing rotations",
  238. sprites[num].name[0],
  239. sprites[num].name[1],
  240. sprites[num].name[2],
  241. sprites[num].name[3], frame+'A');
  242. }
  243. }
  244. break;
  245. }
  246. }
  247.  
  248. // allocate space for the frames present and copy sprtemp to it
  249. sprites[num].numframes = maxframe;
  250. sprites[num].spriteframes = (spriteframe_t *)
  251. Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
  252. memcpy (sprites[num].spriteframes, sprtemp, maxframe * sizeof(spriteframe_t));
  253. }
  254.  
  255.  
  256. //
  257. // R_InitSpriteDefs
  258. // Pass a null terminated list of sprite names
  259. // (4 chars exactly) to be used.
  260. // Builds the sprite rotation matrices to account
  261. // for horizontally flipped sprites.
  262. // Will report an error if the lumps are inconsistant.
  263. // Only called at startup.
  264. //
  265. // Sprite lump names are 4 characters for the actor,
  266. // a letter for the frame, and a number for the rotation.
  267. // A sprite that is flippable will have an additional
  268. // letter/number appended.
  269. // The rotation character can be 0 to signify no rotations.
  270. //
  271. void R_InitSpriteDefs ()
  272. {
  273. size_t i;
  274. int l;
  275. int intname;
  276. int start;
  277. int end;
  278.  
  279. start = firstspritelump - 1;
  280. end = lastspritelump + 1;
  281.  
  282. // scan all the lump names for each of the names,
  283. // noting the highest frame letter.
  284. // Just compare 4 characters as ints
  285. for (i = 0; i < sprites.Size (); i++)
  286. {
  287. spritename = sprites[i].name;
  288. memset (sprtemp, -1, sizeof(sprtemp));
  289. for (int j = 0; j < MAX_SPRITE_FRAMES; ++j)
  290. {
  291. sprtemp[j].flip = 0;
  292. }
  293.  
  294. maxframe = -1;
  295. intname = *(int *)spritename;
  296.  
  297. // scan the lumps,
  298. // filling in the frames for whatever is found
  299. for (l = lastspritelump; l >= firstspritelump; l--)
  300. {
  301. if (*(int *)lumpinfo[l].name == intname)
  302. {
  303. R_InstallSpriteLump (l,
  304. lumpinfo[l].name[4] - 'A',
  305. lumpinfo[l].name[5],
  306. false);
  307.  
  308. if (lumpinfo[l].name[6])
  309. R_InstallSpriteLump (l,
  310. lumpinfo[l].name[6] - 'A',
  311. lumpinfo[l].name[7],
  312. true);
  313. }
  314. }
  315.  
  316. R_InstallSprite (i);
  317. }
  318. }
  319.  
  320. // [RH]
  321. // R_InitSkins
  322. // Reads in everything applicable to a skin. The skins should have already
  323. // been counted and had their identifiers assigned to namespaces.
  324. //
  325. #define NUMSKINSOUNDS 9
  326. static const char *skinsoundnames[NUMSKINSOUNDS][2] = {
  327. { "dsplpain", "*pain100" },
  328. { "dspldeth", "*death" },
  329. { "dspdiehi", "*xdeath" },
  330. { "dsoof", "*land" },
  331. { "dsoof", "*grunt" },
  332. { "dsnoway", "*usefail" },
  333. { "dsslop", "*gibbed" },
  334. { "dspunch", "*fist" },
  335. { "dsjump", "*jump" }
  336. };
  337. static const char painname[3][8] = { "*pain25", "*pain50", "*pain75" };
  338. static WORD playersoundrefs[NUMSKINSOUNDS+3];
  339.  
  340. static int STACK_ARGS skinsorter (const void *a, const void *b)
  341. {
  342. return stricmp (((FPlayerSkin *)a)->name, ((FPlayerSkin *)b)->name);
  343. }
  344.  
  345. void R_InitSkins (void)
  346. {
  347. spritedef_t temp;
  348. int sndlumps[NUMSKINSOUNDS];
  349. char key[10];
  350. int intname;
  351. size_t i;
  352. int j, k, base;
  353. int lastlump;
  354.  
  355. key[9] = 0;
  356. i = 0;
  357. lastlump = 0;
  358.  
  359. for (j = 0; j < NUMSKINSOUNDS; ++j)
  360. {
  361. playersoundrefs[j] = S_FindSound (skinsoundnames[j][1]);
  362. }
  363. for (j = 0; j < 3; ++j)
  364. {
  365. playersoundrefs[j+NUMSKINSOUNDS] = S_FindSound (painname[j]);
  366. }
  367.  
  368. while ((base = W_FindLump ("S_SKIN", &lastlump)) != -1)
  369. {
  370. // The player sprite has 23 frames. This means that the S_SKIN
  371. // marker needs a minimum of 23 lumps after it.
  372. if (base >= numlumps - 23 || base == -1)
  373. continue;
  374.  
  375. i++;
  376. for (j = 0; j < NUMSKINSOUNDS; j++)
  377. sndlumps[j] = -1;
  378. skins[i].namespc = lumpinfo[base].namespc;
  379.  
  380. SC_OpenLumpNum (base, "S_SKIN");
  381. intname = 0;
  382.  
  383. // Data is stored as "key = data".
  384. while (SC_GetString ())
  385. {
  386. strncpy (key, sc_String, 9);
  387. if (!SC_GetString() || sc_String[0] != '=')
  388. {
  389. Printf_Bold ("Bad format for skin %d: %s\n", i, key);
  390. break;
  391. }
  392. SC_GetString ();
  393. if (0 == stricmp (key, "name"))
  394. {
  395. strncpy (skins[i].name, sc_String, 16);
  396. for (j = 0; (size_t)j < i; j++)
  397. {
  398. if (stricmp (skins[i].name, skins[j].name) == 0)
  399. {
  400. sprintf (skins[i].name, "skin%d", i);
  401. Printf_Bold ("Skin %s duplicated as %s\n",
  402. skins[j].name, skins[i].name);
  403. break;
  404. }
  405. }
  406. }
  407. else if (0 == stricmp (key, "sprite"))
  408. {
  409. for (j = 3; j >= 0; j--)
  410. sc_String[j] = toupper (sc_String[j]);
  411. intname = *((int *)sc_String);
  412. }
  413. else if (0 == stricmp (key, "face"))
  414. {
  415. for (j = 2; j >= 0; j--)
  416. skins[i].face[j] = toupper (sc_String[j]);
  417. }
  418. else if (0 == stricmp (key, "gender"))
  419. {
  420. skins[i].gender = D_GenderToInt (sc_String);
  421. }
  422. else
  423. {
  424. for (j = 0; j < NUMSKINSOUNDS; j++)
  425. {
  426. if (stricmp (key, skinsoundnames[j][0]) == 0)
  427. {
  428. sndlumps[j] = W_CheckNumForName (sc_String, skins[i].namespc);
  429. if (sndlumps[j] == -1)
  430. { // Replacement not found, try finding it in the global namespace
  431. sndlumps[j] = W_CheckNumForName (sc_String);
  432. }
  433. }
  434. }
  435. //if (j == 8)
  436. // Printf ("Funny info for skin %i: %s = %s\n", i, key, sc_String);
  437. }
  438. }
  439.  
  440. if (skins[i].name[0] == 0)
  441. sprintf (skins[i].name, "skin%d", i);
  442.  
  443. // Now collect the sprite frames for this skin. If the sprite name was not
  444. // specified, use whatever immediately follows the specifier lump.
  445. if (intname == 0)
  446. {
  447. intname = *(int *)(lumpinfo[base+1].name);
  448. }
  449.  
  450. memset (sprtemp, -1, sizeof(sprtemp));
  451. for (k = 0; k < MAX_SPRITE_FRAMES; ++k)
  452. {
  453. sprtemp[k].flip = 0;
  454. }
  455. maxframe = -1;
  456.  
  457. for (k = base + 1; lumpinfo[k].wadnum == lumpinfo[base].wadnum; k++)
  458. {
  459. if (*(int *)lumpinfo[k].name == intname)
  460. {
  461. R_InstallSpriteLump (k,
  462. lumpinfo[k].name[4] - 'A',
  463. lumpinfo[k].name[5],
  464. false);
  465.  
  466. if (lumpinfo[k].name[6])
  467. R_InstallSpriteLump (k,
  468. lumpinfo[k].name[6] - 'A',
  469. lumpinfo[k].name[7],
  470. true);
  471. }
  472. }
  473.  
  474. if (maxframe <= 0)
  475. {
  476. Printf_Bold ("Skin %s (#%d) has no frames. Removing.\n", skins[i].name, i);
  477. if (i < numskins-1)
  478. memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1));
  479. i--;
  480. continue;
  481. }
  482.  
  483. strncpy (temp.name, lumpinfo[base+1].name, 4);
  484. skins[i].sprite = sprites.Push (temp);
  485. R_InstallSprite (skins[i].sprite);
  486.  
  487. // Register any sounds this skin provides
  488. for (j = 0; j < NUMSKINSOUNDS; j++)
  489. {
  490. if (sndlumps[j] != -1)
  491. {
  492. int aliasid;
  493.  
  494. aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender,
  495. playersoundrefs[j], sndlumps[j]);
  496. if (j == 0)
  497. {
  498. for (int l = 3; l > 0; --l)
  499. {
  500. S_AddPlayerSoundExisting (skins[i].name, skins[i].gender,
  501. playersoundrefs[NUMSKINSOUNDS-1+l], aliasid);
  502. }
  503. }
  504. }
  505. }
  506.  
  507. SC_Close ();
  508.  
  509. // Make sure face prefix is a full 3 chars
  510. if (skins[i].face[1] == 0 || skins[i].face[2] == 0)
  511. {
  512. skins[i].face[0] = 0;
  513. }
  514. }
  515.  
  516. if (numskins > 1)
  517. { // The sound table may have changed, so rehash it.
  518. S_HashSounds ();
  519. S_ShrinkPlayerSoundLists ();
  520. }
  521. }
  522.  
  523. // [RH] Find a skin by name
  524. int R_FindSkin (const char *name)
  525. {
  526. int min, max, mid;
  527. int lexx;
  528.  
  529. if (stricmp ("base", name) == 0)
  530. {
  531. return 0;
  532. }
  533.  
  534. min = 1;
  535. max = numskins-1;
  536.  
  537. while (min <= max)
  538. {
  539. mid = (min + max)/2;
  540. lexx = strnicmp (skins[mid].name, name, 16);
  541. if (lexx == 0)
  542. return mid;
  543. else if (lexx < 0)
  544. min = mid + 1;
  545. else
  546. max = mid - 1;
  547. }
  548. return 0;
  549. }
  550.  
  551. // [RH] List the names of all installed skins
  552. CCMD (skins)
  553. {
  554. int i;
  555.  
  556. for (i = 0; i < (int)numskins; i++)
  557. Printf ("%3d %s\n", i, skins[i].name);
  558. }
  559.  
  560. //
  561. // GAME FUNCTIONS
  562. //
  563. int MaxVisSprites;
  564. vissprite_t *vissprites;
  565. vissprite_t *firstvissprite;
  566. vissprite_t *vissprite_p;
  567. vissprite_t *lastvissprite;
  568. int newvissprite;
  569.  
  570.  
  571.  
  572. //
  573. // R_InitSprites
  574. // Called at program start.
  575. //
  576. void R_InitSprites ()
  577. {
  578. byte rangestart, rangeend;
  579. int lump, lastlump;
  580. size_t i;
  581.  
  582. for (i = 0; i < MAXWIDTH; i++)
  583. {
  584. negonearray[i] = 0;
  585. }
  586.  
  587. MaxVisSprites = 128; // [RH] This is the initial default value. It grows as needed.
  588. firstvissprite = vissprites = (vissprite_t *)Malloc (MaxVisSprites * sizeof(vissprite_t));
  589. lastvissprite = &vissprites[MaxVisSprites];
  590.  
  591. if (gameinfo.gametype == GAME_Doom)
  592. {
  593. rangestart = 112;
  594. rangeend = 127;
  595. }
  596. else if (gameinfo.gametype == GAME_Heretic)
  597. {
  598. rangestart = 225;
  599. rangeend = 240;
  600. }
  601. else // Hexen
  602. {
  603. rangestart = 146;
  604. rangeend = 163;
  605. }
  606.  
  607. // [RH] Count the number of skins.
  608. numskins = 1;
  609. lastlump = 0;
  610. while ((lump = W_FindLump ("S_SKIN", &lastlump)) != -1)
  611. {
  612. numskins++;
  613. }
  614.  
  615. // [RH] Do some preliminary setup
  616. skins = (FPlayerSkin *)Z_Malloc (sizeof(*skins) * numskins, PU_STATIC, 0);
  617. memset (skins, 0, sizeof(*skins) * numskins);
  618. for (i = 0; i < numskins; i++)
  619. {
  620. skins[i].range0start = rangestart;
  621. skins[i].range0end = rangeend;
  622. }
  623.  
  624. R_InitSpriteDefs ();
  625. R_InitSkins (); // [RH] Finish loading skin data
  626.  
  627. // [RH] Set up base skin
  628. strcpy (skins[0].name, "Base");
  629. skins[0].face[0] = 'S';
  630. skins[0].face[1] = 'T';
  631. skins[0].face[2] = 'F';
  632. skins[0].namespc = ns_global;
  633.  
  634. for (i = 0; i < sprites.Size (); i++)
  635. {
  636. if (memcmp (sprites[i].name, deh.PlayerSprite, 4) == 0)
  637. {
  638. skins[0].sprite = i;
  639. break;
  640. }
  641. }
  642.  
  643. // [RH] Sort the skins, but leave base as skin 0
  644. qsort (&skins[1], numskins-1, sizeof(FPlayerSkin), skinsorter);
  645. }
  646.  
  647.  
  648.  
  649. //
  650. // R_ClearSprites
  651. // Called at frame start.
  652. //
  653. void R_ClearSprites (void)
  654. {
  655. vissprite_p = firstvissprite;
  656. }
  657.  
  658.  
  659. //
  660. // R_NewVisSprite
  661. //
  662. vissprite_t *R_NewVisSprite (void)
  663. {
  664. if (vissprite_p == lastvissprite)
  665. {
  666. ptrdiff_t firstvisspritenum = firstvissprite - vissprites;
  667. ptrdiff_t prevvisspritenum = vissprite_p - vissprites;
  668.  
  669. MaxVisSprites *= 2;
  670. vissprites = (vissprite_t *)Realloc (vissprites, MaxVisSprites * sizeof(vissprite_t));
  671. lastvissprite = &vissprites[MaxVisSprites];
  672. firstvissprite = &vissprites[firstvisspritenum];
  673. vissprite_p = &vissprites[prevvisspritenum];
  674. DPrintf ("MaxVisSprites increased to %d\n", MaxVisSprites);
  675. }
  676.  
  677. vissprite_p++;
  678. return vissprite_p-1;
  679. }
  680.  
  681.  
  682. //
  683. // R_DrawMaskedColumn
  684. // Used for sprites and masked mid textures.
  685. // Masked means: partly transparent, i.e. stored
  686. // in posts/runs of opaque pixels.
  687. //
  688. short* mfloorclip;
  689. short* mceilingclip;
  690.  
  691. fixed_t spryscale;
  692. fixed_t sprtopscreen;
  693.  
  694. bool sprflipvert;
  695.  
  696. void R_DrawMaskedColumn (column_t *column)
  697. {
  698. int top = -1;
  699.  
  700. while (column->topdelta != 0xff)
  701. {
  702. if (column->topdelta <= top)
  703. {
  704. top += column->topdelta;
  705. }
  706. else
  707. {
  708. top = column->topdelta;
  709. }
  710.  
  711. if (column->length == 0)
  712. {
  713. goto nextpost;
  714. }
  715.  
  716. // calculate unclipped screen coordinates for post
  717. dc_yl = (sprtopscreen + spryscale * top) >> FRACBITS;
  718. dc_yh = (sprtopscreen + spryscale * (top + column->length) - FRACUNIT) >> FRACBITS;
  719.  
  720. if (sprflipvert)
  721. {
  722. swap (dc_yl, dc_yh);
  723. }
  724.  
  725. if (dc_yh >= mfloorclip[dc_x])
  726. {
  727. dc_yh = mfloorclip[dc_x] - 1;
  728. }
  729. if (dc_yl < mceilingclip[dc_x])
  730. {
  731. dc_yl = mceilingclip[dc_x];
  732. }
  733.  
  734. if (dc_yl <= dc_yh)
  735. {
  736. if (sprflipvert)
  737. {
  738. dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
  739. - FixedMul (centeryfrac, dc_iscale) - dc_texturemid;
  740. const fixed_t maxfrac = column->length << FRACBITS;
  741. while (dc_texturefrac >= maxfrac)
  742. {
  743. if (++dc_yl > dc_yh)
  744. goto nextpost;
  745. dc_texturefrac += dc_iscale;
  746. }
  747. fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  748. while (endfrac < 0)
  749. {
  750. if (--dc_yh < dc_yl)
  751. goto nextpost;
  752. endfrac -= dc_iscale;
  753. }
  754. }
  755. else
  756. {
  757. dc_texturefrac = dc_texturemid - (top << FRACBITS)
  758. + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
  759. while (dc_texturefrac < 0)
  760. {
  761. if (++dc_yl > dc_yh)
  762. goto nextpost;
  763. dc_texturefrac += dc_iscale;
  764. }
  765. fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  766. const fixed_t maxfrac = column->length << FRACBITS;
  767. while (endfrac >= maxfrac)
  768. {
  769. if (--dc_yh < dc_yl)
  770. goto nextpost;
  771. endfrac -= dc_iscale;
  772. }
  773. }
  774. dc_source = (byte *)column + 3;
  775. colfunc ();
  776. }
  777. nextpost:
  778. column = (column_t *)((byte *)column + column->length + 4);
  779. }
  780. }
  781.  
  782. void R_DrawMaskedColumn2 (column2_t *column)
  783. {
  784. while (column->Length != 0)
  785. {
  786. const int length = column->Length;
  787. const int top = column->TopDelta;
  788.  
  789. // calculate unclipped screen coordinates for post
  790. dc_yl = (sprtopscreen + spryscale * top) >> FRACBITS;
  791. dc_yh = (sprtopscreen + spryscale * (top + length) - FRACUNIT) >> FRACBITS;
  792.  
  793. if (sprflipvert)
  794. {
  795. swap (dc_yl, dc_yh);
  796. }
  797.  
  798. if (dc_yh >= mfloorclip[dc_x])
  799. {
  800. dc_yh = mfloorclip[dc_x] - 1;
  801. }
  802. if (dc_yl < mceilingclip[dc_x])
  803. {
  804. dc_yl = mceilingclip[dc_x];
  805. }
  806.  
  807. if (dc_yl <= dc_yh)
  808. {
  809. if (sprflipvert)
  810. {
  811. dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
  812. - FixedMul (centeryfrac, dc_iscale) - dc_texturemid;
  813. const fixed_t maxfrac = length << FRACBITS;
  814. while (dc_texturefrac >= maxfrac)
  815. {
  816. if (++dc_yl > dc_yh)
  817. goto nextpost;
  818. dc_texturefrac += dc_iscale;
  819. }
  820. fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  821. while (endfrac < 0)
  822. {
  823. if (--dc_yh < dc_yl)
  824. goto nextpost;
  825. endfrac -= dc_iscale;
  826. }
  827. }
  828. else
  829. {
  830. dc_texturefrac = dc_texturemid - (top << FRACBITS)
  831. + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
  832. while (dc_texturefrac < 0)
  833. {
  834. if (++dc_yl > dc_yh)
  835. goto nextpost;
  836. dc_texturefrac += dc_iscale;
  837. }
  838. fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
  839. const fixed_t maxfrac = length << FRACBITS;
  840. while (endfrac >= maxfrac)
  841. {
  842. if (--dc_yh < dc_yl)
  843. goto nextpost;
  844. endfrac -= dc_iscale;
  845. }
  846. }
  847. dc_source = (byte *)column + 4;
  848. colfunc ();
  849. }
  850. nextpost:
  851. column = (column2_t *)((byte *)column + length + 4);
  852. }
  853. }
  854.  
  855. //
  856. // R_DrawVisSprite
  857. // mfloorclip and mceilingclip should also be set.
  858. //
  859. void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
  860. {
  861. #ifdef RANGECHECK
  862. unsigned int patchwidth;
  863. #endif
  864. fixed_t frac;
  865. patch_t* patch;
  866.  
  867. patch = TileCache[R_CacheTileNum (vis->picnum, PU_CACHE)];
  868.  
  869. dc_colormap = vis->colormap;
  870. spryscale = vis->yscale;
  871. sprflipvert = false;
  872. dc_iscale = 0xffffffffu / (unsigned)vis->yscale;
  873. dc_texturemid = vis->texturemid;
  874. frac = vis->startfrac;
  875.  
  876. sprtopscreen = centeryfrac - FixedMul (dc_texturemid, spryscale);
  877.  
  878. #ifdef RANGECHECK
  879. patchwidth = (unsigned)SHORT(patch->width);
  880. #endif
  881.  
  882. switch (R_SetPatchStyle (vis->RenderStyle, vis->alpha,
  883. vis->Translation, vis->AlphaColor))
  884. {
  885. case DontDraw:
  886. break;
  887.  
  888. case DoDraw0:
  889. // One column at a time
  890. {
  891. int x1 = vis->x1, x2 = vis->x2;
  892. fixed_t xiscale = vis->xiscale;
  893.  
  894. for (dc_x = x1; dc_x <= x2; dc_x++, frac += xiscale)
  895. {
  896. unsigned int texturecolumn = frac>>FRACBITS;
  897.  
  898. #ifdef RANGECHECK
  899. if (texturecolumn >= patchwidth)
  900. {
  901. DPrintf ("R_DrawSpriteRange: bad texturecolumn (%d)\n", texturecolumn);
  902. continue;
  903. }
  904. #endif
  905.  
  906. R_DrawMaskedColumn ((column_t *)((byte *)patch + LONG(patch->columnofs[texturecolumn])));
  907. }
  908. }
  909. break;
  910.  
  911. case DoDraw1:
  912. // Up to four columns at a time
  913. {
  914. int x1 = vis->x1, x2 = vis->x2 + 1;
  915. fixed_t xiscale = vis->xiscale;
  916. int stop = x2 & ~3;
  917.  
  918. if (x1 < x2)
  919. {
  920. dc_x = x1;
  921.  
  922. while ((dc_x < stop) && (dc_x & 3))
  923. {
  924. R_DrawMaskedColumn ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  925. dc_x++;
  926. frac += xiscale;
  927. }
  928.  
  929. while (dc_x < stop)
  930. {
  931. rt_initcols();
  932. R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  933. dc_x++;
  934. frac += xiscale;
  935. R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  936. dc_x++;
  937. frac += xiscale;
  938. R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  939. dc_x++;
  940. frac += xiscale;
  941. R_DrawMaskedColumnHoriz ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  942. rt_draw4cols (dc_x - 3);
  943. dc_x++;
  944. frac += xiscale;
  945. }
  946.  
  947. while (dc_x < x2)
  948. {
  949. R_DrawMaskedColumn ((column_t *)((byte *)patch + LONG(patch->columnofs[frac>>FRACBITS])));
  950. dc_x++;
  951. frac += xiscale;
  952. }
  953. }
  954. }
  955. break;
  956. }
  957.  
  958. R_FinishSetPatchStyle ();
  959. }
  960.  
  961. //
  962. // R_ProjectSprite
  963. // Generates a vissprite for a thing if it might be visible.
  964. //
  965. void R_ProjectSprite (AActor *thing, int fakeside)
  966. {
  967. fixed_t tr_x;
  968. fixed_t tr_y;
  969.  
  970. fixed_t gzt; // killough 3/27/98
  971. fixed_t gzb; // [RH] use bottom of sprite, not actor
  972. fixed_t tx, tx2;
  973. fixed_t tz;
  974.  
  975. fixed_t xscale;
  976.  
  977. int x1;
  978. int x2;
  979.  
  980. spritedef_t* sprdef;
  981. spriteframe_t* sprframe;
  982. int lump;
  983.  
  984. WORD flip;
  985.  
  986. vissprite_t* vis;
  987.  
  988. fixed_t iscale;
  989.  
  990. sector_t* heightsec; // killough 3/27/98
  991.  
  992. if ((thing->renderflags & RF_INVISIBLE) ||
  993. thing->RenderStyle == STYLE_None ||
  994. (thing->RenderStyle >= STYLE_Translucent && thing->alpha == 0))
  995. {
  996. return;
  997. }
  998.  
  999. // [RH] Interpolate the sprite's position to make it look smooth
  1000. /*
  1001. fx = thing->PrevX + FixedMul (r_TicFrac, thing->x - thing->PrevX);
  1002. fy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY);
  1003. fz = thing->PrevZ + FixedMul (r_TicFrac, thing->z - thing->PrevZ);
  1004. */
  1005.  
  1006. // transform the origin point
  1007. tr_x = thing->x - viewx;
  1008. tr_y = thing->y - viewy;
  1009.  
  1010. tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin);
  1011.  
  1012. // thing is behind view plane?
  1013. if (tz < MINZ)
  1014. return;
  1015.  
  1016. tx = DMulScale16 (tr_x, viewsin, -tr_y, viewcos);
  1017.  
  1018. // [RH] Flip for mirrors
  1019. if (MirrorFlags & RF_XFLIP)
  1020. {
  1021. tx = viewwidth - tx - 1;
  1022. }
  1023. tx2 = tx >> 4;
  1024.  
  1025. // too far off the side?
  1026. if ((abs (tx) >> 6) > tz)
  1027. {
  1028. return;
  1029. }
  1030.  
  1031. xscale = Scale (centerxfrac, (thing->xscale+1)<<6, tz);
  1032.  
  1033. // decide which patch to use for sprite relative to player
  1034. #ifdef RANGECHECK
  1035. if ((unsigned)thing->sprite >= (unsigned)sprites.Size ())
  1036. {
  1037. DPrintf ("R_ProjectSprite: invalid sprite number %i\n", thing->sprite);
  1038. return;
  1039. }
  1040. #endif
  1041. sprdef = &sprites[thing->sprite];
  1042. if (thing->frame >= sprdef->numframes)
  1043. {
  1044. DPrintf ("R_ProjectSprite: invalid sprite frame %c%c%c%c: %c (max %c)\n",
  1045. sprdef->name[0], sprdef->name[1], sprdef->name[2], sprdef->name[3],
  1046. thing->frame + 'A', sprdef->numframes + 'A' - 1);
  1047. return;
  1048. }
  1049. sprframe = &sprdef->spriteframes[thing->frame];
  1050.  
  1051. if (sprframe->rotate)
  1052. {
  1053. // choose a different rotation based on player view
  1054. angle_t ang = R_PointToAngle (thing->x, thing->y);
  1055. unsigned rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>28;
  1056. lump = sprframe->lump[rot];
  1057. flip = sprframe->flip & (1 << rot);
  1058. }
  1059. else
  1060. {
  1061. // use single rotation for all views
  1062. lump = sprframe->lump[0];
  1063. flip = sprframe->flip & 1;
  1064. }
  1065.  
  1066. if (TileSizes[lump].Width == 0xffff)
  1067. {
  1068. R_CacheTileNum (lump, PU_CACHE); // [RH] get sprite's size
  1069. }
  1070.  
  1071. // [RH] Added scaling
  1072. gzt = thing->z + (TileSizes[lump].TopOffset << (FRACBITS-6)) * (thing->yscale+1);
  1073. gzb = thing->z + ((TileSizes[lump].TopOffset - TileSizes[lump].Height) << (FRACBITS-6)) * (thing->yscale+1);
  1074.  
  1075. // [RH] Reject sprites that are off the top or bottom of the screen
  1076. if (MulScale12 (globaluclip, tz) > viewz - gzb ||
  1077. MulScale12 (globaldclip, tz) < viewz - gzt)
  1078. {
  1079. return;
  1080. }
  1081.  
  1082. // calculate edges o of the shape
  1083. // There was an issue when sprite got flipped but offsets were not
  1084.  
  1085. if(flip) {
  1086. tx -= (TileSizes[lump].Width - TileSizes[lump].LeftOffset) << 16;
  1087. } else {
  1088. tx -= TileSizes[lump].LeftOffset << 16;
  1089. }
  1090.  
  1091. x1 = (centerxfrac + FixedMul (tx, xscale)) >> FRACBITS;
  1092.  
  1093. // off the right side?
  1094. if (x1 > WindowRight)
  1095. return;
  1096.  
  1097. tx += TileSizes[lump].Width << 16;
  1098. x2 = ((centerxfrac + FixedMul (tx, xscale)) >> FRACBITS) - 1;
  1099.  
  1100. // off the left side or too small?
  1101. if (x2 < WindowLeft || x2 < x1)
  1102. return;
  1103.  
  1104. // killough 3/27/98: exclude things totally separated
  1105. // from the viewer, by either water or fake ceilings
  1106. // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
  1107.  
  1108. heightsec = thing->Sector->heightsec;
  1109.  
  1110. if (heightsec != NULL && heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)
  1111. {
  1112. heightsec = NULL;
  1113. }
  1114.  
  1115. if (heightsec) // only clip things which are in special sectors
  1116. {
  1117. if (fakeside == FAKED_AboveCeiling)
  1118. {
  1119. if (gzt < heightsec->ceilingplane.ZatPoint (thing->x, thing->y))
  1120. return;
  1121. }
  1122. else if (fakeside == FAKED_BelowFloor)
  1123. {
  1124. if (gzb >= heightsec->floorplane.ZatPoint (thing->x, thing->y))
  1125. return;
  1126. }
  1127. else
  1128. {
  1129. if (gzt < heightsec->floorplane.ZatPoint (thing->x, thing->y))
  1130. return;
  1131. if (gzb >= heightsec->ceilingplane.ZatPoint (thing->x, thing->y))
  1132. return;
  1133. }
  1134. }
  1135.  
  1136. // [RH] Flip for mirrors and renderflags
  1137. if ((MirrorFlags ^ thing->renderflags) & RF_XFLIP)
  1138. {
  1139. flip = !flip;
  1140. }
  1141.  
  1142. // store information in a vissprite
  1143. vis = R_NewVisSprite ();
  1144.  
  1145. // killough 3/27/98: save sector for special clipping later
  1146. vis->heightsec = heightsec;
  1147.  
  1148. vis->renderflags = thing->renderflags;
  1149. vis->RenderStyle = thing->RenderStyle;
  1150. vis->AlphaColor = thing->alphacolor;
  1151. vis->xscale = xscale;
  1152. vis->yscale = Scale (InvZtoScale, (thing->yscale+1)<<6, tz);
  1153. vis->depth = tz;
  1154. vis->cx = tx2;
  1155. vis->gx = thing->x;
  1156. vis->gy = thing->y;
  1157. vis->gz = gzb; // [RH] use gzb, not thing->z
  1158. vis->gzt = gzt; // killough 3/27/98
  1159. vis->floorclip = thing->floorclip;
  1160. vis->texturemid = (TileSizes[lump].TopOffset << FRACBITS)
  1161. - SafeDivScale6 (viewz-thing->z, thing->yscale+1) - vis->floorclip;
  1162. vis->x1 = x1 < WindowLeft ? WindowLeft : x1;
  1163. vis->x2 = x2 > WindowRight ? WindowRight : x2;
  1164. vis->Translation = thing->Translation; // [RH] thing translation table
  1165. vis->FakeFlatStat = fakeside;
  1166. vis->alpha = thing->alpha;
  1167. vis->picnum = lump;
  1168. iscale = DivScale32 (1, xscale);
  1169.  
  1170. if (flip)
  1171. {
  1172. vis->startfrac = (TileSizes[lump].Width << FRACBITS) - 1;
  1173. vis->xiscale = -iscale;
  1174. }
  1175. else
  1176. {
  1177. vis->startfrac = 0;
  1178. vis->xiscale = iscale;
  1179. }
  1180.  
  1181. if (vis->x1 > x1)
  1182. vis->startfrac += vis->xiscale*(vis->x1-x1);
  1183.  
  1184. // get light level
  1185. if (fixedlightlev)
  1186. {
  1187. vis->colormap = basecolormap + fixedlightlev;
  1188. }
  1189. else if (fixedcolormap)
  1190. {
  1191. // fixed map
  1192. vis->colormap = fixedcolormap;
  1193. }
  1194. else if (!foggy && (thing->renderflags & RF_FULLBRIGHT))
  1195. {
  1196. // full bright
  1197. vis->colormap = basecolormap; // [RH] Use basecolormap
  1198. }
  1199. else
  1200. {
  1201. // diminished light
  1202. vis->colormap = basecolormap + (GETPALOOKUP (
  1203. (fixed_t)DivScale12 (r_SpriteVisibility, tz), spriteshade) << COLORMAPSHIFT);
  1204. }
  1205. }
  1206.  
  1207.  
  1208. //
  1209. // R_AddSprites
  1210. // During BSP traversal, this adds sprites by sector.
  1211. //
  1212. // killough 9/18/98: add lightlevel as parameter, fixing underwater lighting
  1213. // [RH] Save which side of heightsec sprite is on here.
  1214. void R_AddSprites (sector_t *sec, int lightlevel, int fakeside)
  1215. {
  1216. AActor *thing;
  1217.  
  1218. // BSP is traversed by subsector.
  1219. // A sector might have been split into several
  1220. // subsectors during BSP building.
  1221. // Thus we check whether it was already added.
  1222. if (sec->thinglist == NULL || sec->validcount == validcount)
  1223. return;
  1224.  
  1225. // Well, now it will be done.
  1226. sec->validcount = validcount;
  1227.  
  1228. spriteshade = LIGHT2SHADE(lightlevel + r_actualextralight);
  1229.  
  1230. // Handle all things in sector.
  1231. for (thing = sec->thinglist; thing; thing = thing->snext)
  1232. {
  1233. R_ProjectSprite (thing, fakeside);
  1234. }
  1235. }
  1236.  
  1237.  
  1238. //
  1239. // R_DrawPSprite
  1240. //
  1241. void R_DrawPSprite (pspdef_t* psp, AActor *owner)
  1242. {
  1243. fixed_t tx;
  1244. int x1;
  1245. int x2;
  1246. spritedef_t* sprdef;
  1247. spriteframe_t* sprframe;
  1248. int lump;
  1249. BOOL flip;
  1250. vissprite_t* vis;
  1251. vissprite_t avis;
  1252.  
  1253. // decide which patch to use
  1254. #ifdef RANGECHECK
  1255. if ( (unsigned)psp->state->sprite.index >= (unsigned)sprites.Size ())
  1256. {
  1257. DPrintf ("R_DrawPSprite: invalid sprite number %i\n", psp->state->sprite.index);
  1258. return;
  1259. }
  1260. #endif
  1261. sprdef = &sprites[psp->state->sprite.index];
  1262. #ifdef RANGECHECK
  1263. if (psp->state->GetFrame() >= sprdef->numframes)
  1264. {
  1265. DPrintf ("R_DrawPSprite: invalid sprite frame %i : %i\n", psp->state->sprite.index, psp->state->GetFrame());
  1266. return;
  1267. }
  1268. #endif
  1269. sprframe = &sprdef->spriteframes[psp->state->GetFrame()];
  1270.  
  1271. lump = sprframe->lump[0];
  1272. flip = (BOOL)sprframe->flip & 1;
  1273.  
  1274. if (TileSizes[lump].Width == 0xffff)
  1275. {
  1276. R_CacheTileNum (lump, PU_CACHE);
  1277. }
  1278.  
  1279. // calculate edges of the shape
  1280. tx = psp->sx-((320/2)<<FRACBITS);
  1281.  
  1282. tx -= TileSizes[lump].LeftOffset << FRACBITS;
  1283. x1 = (centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS;
  1284.  
  1285. // off the right side
  1286. if (x1 > viewwidth)
  1287. return;
  1288.  
  1289. tx += TileSizes[lump].Width << FRACBITS;
  1290. x2 = ((centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS) - 1;
  1291.  
  1292. // off the left side
  1293. if (x2 < 0)
  1294. return;
  1295.  
  1296. // store information in a vissprite
  1297. vis = &avis;
  1298. vis->renderflags = owner->renderflags;
  1299. vis->floorclip = 0;
  1300. vis->texturemid = (BASEYCENTER<<FRACBITS) -
  1301. (psp->sy - (TileSizes[lump].TopOffset << FRACBITS));
  1302. if (camera->player && (RenderTarget != screen ||
  1303. realviewheight == RenderTarget->GetHeight() ||
  1304. (RenderTarget->GetWidth() > 320 && !st_scale)))
  1305. { // Adjust PSprite for fullscreen views
  1306. FWeaponInfo *weapon;
  1307. if (camera->player->powers[pw_weaponlevel2])
  1308. weapon = wpnlev2info[camera->player->readyweapon];
  1309. else
  1310. weapon = wpnlev1info[camera->player->readyweapon];
  1311. if (weapon && weapon->yadjust)
  1312. {
  1313. if (RenderTarget != screen || realviewheight == RenderTarget->GetHeight())
  1314. {
  1315. vis->texturemid -= weapon->yadjust;
  1316. }
  1317. else
  1318. {
  1319. vis->texturemid -= FixedMul (StatusBar->GetDisplacement (),
  1320. weapon->yadjust);
  1321. }
  1322. }
  1323. }
  1324. vis->x1 = x1 < 0 ? 0 : x1;
  1325. vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
  1326. vis->xscale = pspritexscale;
  1327. vis->yscale = pspriteyscale;
  1328. vis->Translation = 0; // [RH] Use default colors
  1329. vis->alpha = owner->alpha;
  1330. vis->RenderStyle = owner->RenderStyle;
  1331. vis->picnum = lump;
  1332.  
  1333. if (flip)
  1334. {
  1335. vis->xiscale = -pspritexiscale;
  1336. vis->startfrac = (TileSizes[lump].Width << FRACBITS) - 1;
  1337. }
  1338. else
  1339. {
  1340. vis->xiscale = pspritexiscale;
  1341. vis->startfrac = 0;
  1342. }
  1343.  
  1344. if (vis->x1 > x1)
  1345. vis->startfrac += vis->xiscale*(vis->x1-x1);
  1346.  
  1347. if (fixedlightlev)
  1348. {
  1349. vis->colormap = basecolormap + fixedlightlev;
  1350. }
  1351. else if (fixedcolormap)
  1352. {
  1353. // fixed color
  1354. vis->colormap = fixedcolormap;
  1355. }
  1356. else if (psp->state->GetFullbright())
  1357. {
  1358. // full bright
  1359. vis->colormap = basecolormap; // [RH] use basecolormap
  1360. }
  1361. else
  1362. {
  1363. // local light
  1364. vis->colormap = basecolormap + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT);
  1365. }
  1366. if (camera->player &&
  1367. camera->player->powers[pw_invisibility] < 4*32 &&
  1368. !(camera->player->powers[pw_invisibility] & 8))
  1369. {
  1370. // shadow draw
  1371. vis->RenderStyle = STYLE_Normal;
  1372. }
  1373.  
  1374. R_DrawVisSprite (vis, vis->x1, vis->x2);
  1375. }
  1376.  
  1377.  
  1378.  
  1379. //
  1380. // R_DrawPlayerSprites
  1381. //
  1382. void R_DrawPlayerSprites (void)
  1383. {
  1384. int i;
  1385. int lightnum;
  1386. pspdef_t* psp;
  1387. sector_t* sec;
  1388. static sector_t tempsec;
  1389. int floorlight, ceilinglight;
  1390.  
  1391. if (!r_drawplayersprites ||
  1392. !camera->player ||
  1393. (players[consoleplayer].cheats & CF_CHASECAM))
  1394. return;
  1395.  
  1396. sec = R_FakeFlat (camera->Sector, &tempsec, &floorlight,
  1397. &ceilinglight, false);
  1398.  
  1399. // [RH] set foggy flag
  1400. foggy = (level.fadeto || sec->floorcolormap->Fade || sec->ceilingcolormap->Fade);
  1401. r_actualextralight = foggy ? 0 : extralight << 4;
  1402.  
  1403. // [RH] set basecolormap
  1404. basecolormap = sec->floorcolormap->Maps;
  1405.  
  1406. // get light level
  1407. lightnum = ((floorlight + ceilinglight) >> 1) + r_actualextralight;
  1408. spriteshade = LIGHT2SHADE(lightnum) - 24*FRACUNIT;
  1409.  
  1410. // clip to screen bounds
  1411. mfloorclip = screenheightarray;
  1412. mceilingclip = negonearray;
  1413.  
  1414. if (camera->player != NULL)
  1415. {
  1416. fixed_t centerhack = centeryfrac;
  1417.  
  1418. centery = viewheight >> 1;
  1419. centeryfrac = centery << FRACBITS;
  1420.  
  1421. // add all active psprites
  1422. for (i = 0, psp = camera->player->psprites;
  1423. i < NUMPSPRITES;
  1424. i++, psp++)
  1425. {
  1426. if (psp->state)
  1427. R_DrawPSprite (psp, camera);
  1428. }
  1429.  
  1430. centeryfrac = centerhack;
  1431. centery = centerhack >> FRACBITS;
  1432. }
  1433. }
  1434.  
  1435.  
  1436.  
  1437.  
  1438. //
  1439. // R_SortVisSprites
  1440. //
  1441. // [RH] The old code for this function used a bubble sort, which was far less
  1442. // than optimal with large numbers of sprites. I changed it to use the
  1443. // stdlib qsort() function instead, and now it is a *lot* faster; the
  1444. // more vissprites that need to be sorted, the better the performance
  1445. // gain compared to the old function.
  1446. //
  1447. static vissprite_t **spritesorter;
  1448. static int spritesortersize = 0;
  1449. static int vsprcount;
  1450.  
  1451. static int STACK_ARGS sv_compare (const void *arg1, const void *arg2)
  1452. {
  1453. int diff = (*(vissprite_t **)arg1)->depth - (*(vissprite_t **)arg2)->depth;
  1454. if (diff == 0)
  1455. return (*(vissprite_t **)arg2)->gzt - (*(vissprite_t **)arg1)->gzt;
  1456. return diff;
  1457. }
  1458.  
  1459. void R_SortVisSprites (void)
  1460. {
  1461. int i;
  1462. vissprite_t *spr;
  1463.  
  1464. vsprcount = vissprite_p - firstvissprite;
  1465.  
  1466. if (!vsprcount)
  1467. return;
  1468.  
  1469. if (spritesortersize < MaxVisSprites)
  1470. {
  1471. if (spritesorter != NULL)
  1472. delete[] spritesorter;
  1473. spritesorter = new vissprite_t *[MaxVisSprites];
  1474. spritesortersize = MaxVisSprites;
  1475. }
  1476.  
  1477. for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++)
  1478. {
  1479. spritesorter[i] = spr;
  1480. }
  1481.  
  1482. qsort (spritesorter, vsprcount, sizeof (vissprite_t *), sv_compare);
  1483. }
  1484.  
  1485.  
  1486. //
  1487. // R_DrawSprite
  1488. //
  1489. void R_DrawSprite (vissprite_t *spr)
  1490. {
  1491. static short clipbot[MAXWIDTH];
  1492. static short cliptop[MAXWIDTH];
  1493. drawseg_t *ds;
  1494. int i;
  1495. int r1, r2;
  1496. short topclip, botclip;
  1497. short *clip1, *clip2;
  1498.  
  1499. // [RH] Check for particles
  1500. if (spr->picnum == -1)
  1501. {
  1502. R_DrawParticle (spr);
  1503. return;
  1504. }
  1505.  
  1506. // [RH] Quickly reject sprites with bad x ranges.
  1507. if (spr->x1 > spr->x2)
  1508. return;
  1509.  
  1510. // [RH] Initialize the clipping arrays to their largest possible range
  1511. // instead of using a special "not clipped" value. This eliminates
  1512. // visual anomalies when looking down and should be faster, too.
  1513. topclip = 0;
  1514. botclip = viewheight;
  1515.  
  1516. // killough 3/27/98:
  1517. // Clip the sprite against deep water and/or fake ceilings.
  1518. // [RH] rewrote this to be based on which part of the sector is really visible
  1519.  
  1520. if (spr->heightsec &&
  1521. !(spr->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))
  1522. { // only things in specially marked sectors
  1523. if (spr->FakeFlatStat != FAKED_AboveCeiling)
  1524. {
  1525. fixed_t h = spr->heightsec->floorplane.ZatPoint (spr->gx, spr->gy);
  1526. h = (centeryfrac - FixedMul (h-viewz, spr->yscale)) >> FRACBITS;
  1527.  
  1528. if (spr->FakeFlatStat == FAKED_BelowFloor)
  1529. { // seen below floor: clip top
  1530. if (h > topclip)
  1531. {
  1532. topclip = MIN<short> (h, viewheight);
  1533. }
  1534. }
  1535. else
  1536. { // seen in the middle: clip bottom
  1537. if (h < botclip)
  1538. {
  1539. botclip = MAX<short> (0, h);
  1540. }
  1541. }
  1542. }
  1543. if (spr->FakeFlatStat != FAKED_BelowFloor)
  1544. {
  1545. fixed_t h = spr->heightsec->ceilingplane.ZatPoint (spr->gx, spr->gy);
  1546. h = (centeryfrac - FixedMul (h-viewz, spr->yscale)) >> FRACBITS;
  1547.  
  1548. if (spr->FakeFlatStat == FAKED_AboveCeiling)
  1549. { // seen above ceiling: clip bottom
  1550. if (h < botclip)
  1551. {
  1552. botclip = MAX<short> (0, h);
  1553. }
  1554. }
  1555. else
  1556. { // seen in the middle: clip top
  1557. if (h > topclip)
  1558. {
  1559. topclip = MIN<short> (h, viewheight);
  1560. }
  1561. }
  1562. }
  1563. }
  1564. // killough 3/27/98: end special clipping for deep water / fake ceilings
  1565. else if (spr->floorclip)
  1566. { // [RH] Move floorclip stuff from R_DrawVisSprite to here
  1567. if (TileSizes[spr->picnum].Width == 0xffff)
  1568. {
  1569. R_CacheTileNum (spr->picnum, PU_CACHE);
  1570. }
  1571. int clip = ((centeryfrac - FixedMul (spr->texturemid -
  1572. (TileSizes[spr->picnum].Height<<FRACBITS) +
  1573. spr->floorclip, spr->yscale)) >> FRACBITS);
  1574. if (clip < botclip)
  1575. {
  1576. botclip = MAX<short> (0, clip);
  1577. }
  1578. }
  1579.  
  1580. i = spr->x2 - spr->x1 + 1;
  1581. clip1 = clipbot + spr->x1;
  1582. clip2 = cliptop + spr->x1;
  1583. do
  1584. {
  1585. *clip1++ = botclip;
  1586. *clip2++ = topclip;
  1587. } while (--i);
  1588.  
  1589. // Scan drawsegs from end to start for obscuring segs.
  1590. // The first drawseg that is closer than the sprite is the clip seg.
  1591.  
  1592. // Modified by Lee Killough:
  1593. // (pointer check was originally nonportable
  1594. // and buggy, by going past LEFT end of array):
  1595.  
  1596. // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
  1597.  
  1598. for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough
  1599. {
  1600. // determine if the drawseg obscures the sprite
  1601. if (ds->x1 > spr->x2 || ds->x2 < spr->x1 ||
  1602. (!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == -1 &&
  1603. !ds->bFogBoundary) )
  1604. {
  1605. // does not cover sprite
  1606. continue;
  1607. }
  1608.  
  1609. r1 = MAX<int> (ds->x1, spr->x1);
  1610. r2 = MIN<int> (ds->x2, spr->x2);
  1611.  
  1612. if (ds->neardepth > spr->depth || (ds->fardepth > spr->depth &&
  1613. // Check if sprite is in front of draw seg:
  1614. DMulScale24 (spr->depth - ds->cy, ds->cdx,
  1615. ds->cdy, ds->cx - spr->cx) < 0))
  1616. {
  1617. // seg is behind sprite, so draw the mid texture if it has one
  1618. if (ds->maskedtexturecol != -1 || ds->bFogBoundary)
  1619. R_RenderMaskedSegRange (ds, r1, r2);
  1620. continue;
  1621. }
  1622.  
  1623. // clip this piece of the sprite
  1624. // killough 3/27/98: optimized and made much shorter
  1625. // [RH] Optimized further (at least for VC++;
  1626. // other compilers should be at least as good as before)
  1627.  
  1628. if (ds->silhouette & SIL_BOTTOM) //bottom sil
  1629. {
  1630. clip1 = clipbot + r1;
  1631. clip2 = openings + ds->sprbottomclip + r1 - ds->x1;
  1632. i = r2 - r1 + 1;
  1633. do
  1634. {
  1635. if (*clip1 > *clip2)
  1636. *clip1 = *clip2;
  1637. clip1++;
  1638. clip2++;
  1639. } while (--i);
  1640. }
  1641.  
  1642. if (ds->silhouette & SIL_TOP) // top sil
  1643. {
  1644. clip1 = cliptop + r1;
  1645. clip2 = openings + ds->sprtopclip + r1 - ds->x1;
  1646. i = r2 - r1 + 1;
  1647. do
  1648. {
  1649. if (*clip1 < *clip2)
  1650. *clip1 = *clip2;
  1651. clip1++;
  1652. clip2++;
  1653. } while (--i);
  1654. }
  1655. }
  1656.  
  1657. // all clipping has been performed, so draw the sprite
  1658.  
  1659. mfloorclip = clipbot;
  1660. mceilingclip = cliptop;
  1661. R_DrawVisSprite (spr, spr->x1, spr->x2);
  1662. }
  1663.  
  1664. //
  1665. // R_DrawMasked
  1666. //
  1667. void R_DrawMasked (void)
  1668. {
  1669. drawseg_t *ds;
  1670. int i;
  1671.  
  1672. R_SortVisSprites ();
  1673.  
  1674. for (i = vsprcount; i > 0; i--)
  1675. {
  1676. R_DrawSprite (spritesorter[i-1]);
  1677. }
  1678.  
  1679. // render any remaining masked mid textures
  1680.  
  1681. // Modified by Lee Killough:
  1682. // (pointer check was originally nonportable
  1683. // and buggy, by going past LEFT end of array):
  1684.  
  1685. // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
  1686.  
  1687. for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough
  1688. {
  1689. if (ds->maskedtexturecol != -1 || ds->bFogBoundary)
  1690. {
  1691. R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
  1692. }
  1693. }
  1694.  
  1695. // draw the psprites on top of everything
  1696. // but does not draw on side views
  1697. if (!viewangleoffset)
  1698. {
  1699. R_DrawPlayerSprites ();
  1700. }
  1701. }
  1702.  
  1703.  
  1704. //
  1705. // [RH] Particle functions
  1706. //
  1707.  
  1708. void R_InitParticles ()
  1709. {
  1710. char *i;
  1711.  
  1712. if ((i = Args.CheckValue ("-numparticles")))
  1713. NumParticles = atoi (i);
  1714. if (NumParticles == 0)
  1715. NumParticles = 4000;
  1716. else if (NumParticles < 100)
  1717. NumParticles = 100;
  1718.  
  1719. Particles = new particle_t[NumParticles * sizeof(particle_t)];
  1720. R_ClearParticles ();
  1721. }
  1722.  
  1723. void R_ClearParticles ()
  1724. {
  1725. int i;
  1726.  
  1727. memset (Particles, 0, NumParticles * sizeof(particle_t));
  1728. ActiveParticles = NO_PARTICLE;
  1729. InactiveParticles = 0;
  1730. for (i = 0; i < NumParticles-1; i++)
  1731. Particles[i].tnext = i + 1;
  1732. Particles[i].tnext = NO_PARTICLE;
  1733. }
  1734.  
  1735. // Group particles by subsectors. Because particles are always
  1736. // in motion, there is little benefit to caching this information
  1737. // from one frame to the next.
  1738.  
  1739. WORD filt = 0xffff;
  1740.  
  1741. CCMD (pfilt)
  1742. {
  1743. if (argv.argc() == 1)
  1744. {
  1745. filt = R_PointInSubsector (players[0].mo->x, players[0].mo->y) - subsectors;
  1746. Printf ("filtering %d\n", filt);
  1747. }
  1748. else
  1749. {
  1750. filt = 0xffff;
  1751. }
  1752. }
  1753.  
  1754. void R_FindParticleSubsectors ()
  1755. {
  1756. if (ParticlesInSubsec.Size() < numsubsectors)
  1757. {
  1758. ParticlesInSubsec.Reserve (numsubsectors - ParticlesInSubsec.Size());
  1759. }
  1760.  
  1761. clearbufshort (&ParticlesInSubsec[0], numsubsectors, NO_PARTICLE);
  1762.  
  1763. if (!r_particles)
  1764. {
  1765. return;
  1766. }
  1767. for (WORD i = ActiveParticles; i != NO_PARTICLE; i = Particles[i].tnext)
  1768. {
  1769. subsector_t *ssec = R_PointInSubsector (Particles[i].x, Particles[i].y);
  1770. int ssnum = ssec-subsectors;
  1771. if (filt == 0xffff || ssnum == filt)
  1772. {
  1773. Particles[i].snext = ParticlesInSubsec[ssnum];
  1774. ParticlesInSubsec[ssnum] = i;
  1775. }
  1776. }
  1777. }
  1778.  
  1779. void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, int fakeside)
  1780. {
  1781. fixed_t tr_x;
  1782. fixed_t tr_y;
  1783. fixed_t tx, ty;
  1784. fixed_t tz, tiz;
  1785. fixed_t xscale, yscale;
  1786. int x1, x2, y1, y2;
  1787. vissprite_t* vis;
  1788. sector_t* heightsec = NULL;
  1789. byte* map;
  1790.  
  1791. // transform the origin point
  1792. tr_x = particle->x - viewx;
  1793. tr_y = particle->y - viewy;
  1794.  
  1795. tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin);
  1796.  
  1797. // particle is behind view plane?
  1798. if (tz < MINZ)
  1799. return;
  1800.  
  1801. tx = DMulScale20 (tr_x, viewsin, -tr_y, viewcos);
  1802.  
  1803. // Flip for mirrors
  1804. if (MirrorFlags & RF_XFLIP)
  1805. {
  1806. tx = viewwidth - tx - 1;
  1807. }
  1808.  
  1809. // too far off the side?
  1810. if (tz <= abs (tx))
  1811. return;
  1812.  
  1813. tiz = 268435456 / tz;
  1814. xscale = centerx * tiz;
  1815.  
  1816. // calculate edges of the shape
  1817. int psize = particle->size << (12-3);
  1818.  
  1819. x1 = MAX<int> (WindowLeft, (centerxfrac + MulScale12 (tx-psize, xscale)) >> FRACBITS);
  1820. x2 = MIN<int> (WindowRight, (centerxfrac + MulScale12 (tx+psize, xscale)) >> FRACBITS);
  1821.  
  1822. if (x1 >= x2)
  1823. return;
  1824.  
  1825. yscale = MulScale16 (yaspectmul, xscale);
  1826. ty = particle->z - viewz;
  1827. psize <<= 4;
  1828. y1 = (centeryfrac - FixedMul (ty+psize, yscale)) >> FRACBITS;
  1829. y2 = (centeryfrac - FixedMul (ty-psize, yscale)) >> FRACBITS;
  1830.  
  1831. // Clip the particle now. Because it's a point and projected as its subsector is
  1832. // entered, we don't need to clip it to drawsegs like a normal sprite.
  1833.  
  1834. // Clip particles behind walls.
  1835. if (y1 < ceilingclip[x1]) y1 = ceilingclip[x1];
  1836. if (y1 < ceilingclip[x2-1]) y1 = ceilingclip[x2-1];
  1837. if (y2 >= floorclip[x1]) y2 = floorclip[x1] - 1;
  1838. if (y2 >= floorclip[x2-1]) y2 = floorclip[x2-1] - 1;
  1839.  
  1840. if (y1 >= y2)
  1841. return;
  1842.  
  1843. // Clip particles above the ceiling or below the floor.
  1844. heightsec = sector->heightsec;
  1845.  
  1846. if (heightsec != NULL && heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)
  1847. {
  1848. heightsec = NULL;
  1849. }
  1850.  
  1851. const secplane_t *topplane;
  1852. const secplane_t *botplane;
  1853. int toppic;
  1854. int botpic;
  1855.  
  1856. if (heightsec) // only clip things which are in special sectors
  1857. {
  1858. if (fakeside == FAKED_AboveCeiling)
  1859. {
  1860. topplane = &sector->ceilingplane;
  1861. botplane = &heightsec->ceilingplane;
  1862. toppic = sector->ceilingpic;
  1863. botpic = heightsec->ceilingpic;
  1864. map = heightsec->floorcolormap->Maps;
  1865. }
  1866. else if (fakeside == FAKED_BelowFloor)
  1867. {
  1868. topplane = &heightsec->floorplane;
  1869. botplane = &sector->floorplane;
  1870. toppic = heightsec->floorpic;
  1871. botpic = sector->floorpic;
  1872. map = heightsec->floorcolormap->Maps;
  1873. }
  1874. else
  1875. {
  1876. topplane = &heightsec->ceilingplane;
  1877. botplane = &heightsec->floorplane;
  1878. toppic = heightsec->ceilingpic;
  1879. botpic = heightsec->floorpic;
  1880. map = sector->floorcolormap->Maps;
  1881. }
  1882. }
  1883. else
  1884. {
  1885. topplane = &sector->ceilingplane;
  1886. botplane = &sector->floorplane;
  1887. toppic = sector->ceilingpic;
  1888. botpic = sector->floorpic;
  1889. map = sector->floorcolormap->Maps;
  1890. }
  1891.  
  1892. if (botpic != skyflatnum && particle->z < botplane->ZatPoint (particle->x, particle->y))
  1893. return;
  1894. if (toppic != skyflatnum && particle->z >= topplane->ZatPoint (particle->x, particle->y))
  1895. return;
  1896.  
  1897. // store information in a vissprite
  1898. vis = R_NewVisSprite ();
  1899. vis->heightsec = heightsec;
  1900. vis->xscale = xscale;
  1901. // vis->yscale = FixedMul (xscale, InvZtoScale);
  1902. vis->yscale = xscale;
  1903. vis->depth = tz;
  1904. vis->cx = tx;
  1905. vis->gx = particle->x;
  1906. vis->gy = particle->y;
  1907. vis->gz = y1;
  1908. vis->gzt = y2;
  1909. vis->x1 = x1;
  1910. vis->x2 = x2;
  1911. vis->Translation = 0;
  1912. vis->startfrac = particle->color;
  1913. vis->picnum = -1;
  1914. vis->renderflags = particle->trans;
  1915. vis->FakeFlatStat = fakeside;
  1916. vis->floorclip = 0;
  1917. vis->heightsec = heightsec;
  1918.  
  1919. if (fixedcolormap)
  1920. {
  1921. vis->colormap = fixedcolormap;
  1922. }
  1923. else if (fixedlightlev)
  1924. {
  1925. vis->colormap = map + fixedlightlev;
  1926. }
  1927. else
  1928. {
  1929. vis->colormap = map + (GETPALOOKUP (FixedMul (tiz, r_ParticleVisibility),
  1930. shade) << COLORMAPSHIFT);
  1931. }
  1932. }
  1933.  
  1934. static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis)
  1935. {
  1936. const int x1 = vis->x1;
  1937. const int x2 = vis->x2;
  1938.  
  1939. // Draw any masked textures behind this particle so that when the
  1940. // particle is drawn, it will be in front of them.
  1941. for (int p = InterestingDrawsegs.Size(); p-- > FirstInterestingDrawseg; )
  1942. {
  1943. drawseg_t *ds = &drawsegs[InterestingDrawsegs[p]];
  1944. if (ds->x1 >= x2 || ds->x2 < x1)
  1945. {
  1946. continue;
  1947. }
  1948. if ((//ds->neardepth > vis->depth || (ds->fardepth > vis->depth &&
  1949. DMulScale24 (vis->depth - ds->cy, ds->cdx,
  1950. ds->cdy, ds->cx - vis->cx) < 0))
  1951. {
  1952. R_RenderMaskedSegRange (ds, MAX<int> (ds->x1, x1), MIN<int> (ds->x2, x2-1));
  1953. }
  1954. }
  1955. }
  1956.  
  1957. void R_DrawParticle (vissprite_t *vis)
  1958. {
  1959. DWORD *bg2rgb;
  1960. int spacing;
  1961. byte *dest;
  1962. DWORD fg;
  1963. byte color = vis->colormap[vis->startfrac];
  1964. int yl = vis->gz;
  1965. int ycount = vis->gzt - yl;
  1966. int x1 = vis->x1;
  1967. int countbase = vis->x2 - x1;
  1968.  
  1969. R_DrawMaskedSegsBehindParticle (vis);
  1970.  
  1971. // vis->renderflags holds translucency level (0-255)
  1972. {
  1973. fixed_t fglevel, bglevel;
  1974. DWORD *fg2rgb;
  1975.  
  1976. fglevel = ((vis->renderflags + 1) << 8) & ~0x3ff;
  1977. bglevel = FRACUNIT-fglevel;
  1978. fg2rgb = Col2RGB8[fglevel>>10];
  1979. bg2rgb = Col2RGB8[bglevel>>10];
  1980. fg = fg2rgb[color];
  1981. }
  1982.  
  1983. spacing = (RenderTarget->GetPitch()<<detailyshift) - countbase;
  1984. dest = ylookup[yl] + x1;
  1985.  
  1986. do
  1987. {
  1988. int count = countbase;
  1989. do
  1990. {
  1991. DWORD bg = bg2rgb[*dest];
  1992. bg = (fg+bg) | 0x1f07c1f;
  1993. *dest++ = RGB32k[0][0][bg & (bg>>15)];
  1994. } while (--count);
  1995. dest += spacing;
  1996. } while (--ycount);
  1997. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement