r_things.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  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. static const char
  24. rcsid[] = "$Id: r_things.c,v 1.5 1997/02/03 16:47:56 b1 Exp $";
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include "doomdef.h"
  28. #include "m_swap.h"
  29. #include "i_system.h"
  30. #include "z_zone.h"
  31. #include "w_wad.h"
  32. #include "r_local.h"
  33. #include "doomstat.h"
  34. #define MINZ (FRACUNIT*4)
  35. #define BASEYCENTER 100
  36. //void R_DrawColumn (void);
  37. //void R_DrawFuzzColumn (void);
  38. typedef struct
  39. {
  40. int x1;
  41. int x2;
  42. int column;
  43. int topclip;
  44. int bottomclip;
  45. } maskdraw_t;
  46. //
  47. // Sprite rotation 0 is facing the viewer,
  48. // rotation 1 is one angle turn CLOCKWISE around the axis.
  49. // This is not the same as the angle,
  50. // which increases counter clockwise (protractor).
  51. // There was a lot of stuff grabbed wrong, so I changed it...
  52. //
  53. fixed_t pspritescale;
  54. fixed_t pspriteiscale;
  55. lighttable_t** spritelights;
  56. // constant arrays
  57. // used for psprite clipping and initializing clipping
  58. short negonearray[SCREENWIDTH];
  59. short screenheightarray[SCREENWIDTH];
  60. //
  61. // INITIALIZATION FUNCTIONS
  62. //
  63. // variables used to look up
  64. // and range check thing_t sprites patches
  65. spritedef_t* sprites;
  66. int numsprites;
  67. spriteframe_t sprtemp[29];
  68. int maxframe;
  69. char* spritename;
  70. //
  71. // R_InstallSpriteLump
  72. // Local function for R_InitSprites.
  73. //
  74. void
  75. R_InstallSpriteLump
  76. ( int lump,
  77. unsigned frame,
  78. unsigned rotation,
  79. boolean flipped )
  80. {
  81. int r;
  82. if (frame >= 29 || rotation > 8)
  83. I_Error("R_InstallSpriteLump: "
  84. "Bad frame characters in lump %i", lump);
  85. if ((int)frame > maxframe)
  86. maxframe = frame;
  87. if (rotation == 0)
  88. {
  89. // the lump should be used for all rotations
  90. if (sprtemp[frame].rotate == false)
  91. I_Error ("R_InitSprites: Sprite %s frame %c has "
  92. "multip rot=0 lump", spritename, 'A'+frame);
  93. if (sprtemp[frame].rotate == true)
  94. I_Error ("R_InitSprites: Sprite %s frame %c has rotations "
  95. "and a rot=0 lump", spritename, 'A'+frame);
  96. sprtemp[frame].rotate = false;
  97. for (r=0 ; r<8 ; r++)
  98. {
  99. sprtemp[frame].lump[r] = lump - firstspritelump;
  100. sprtemp[frame].flip[r] = (byte)flipped;
  101. }
  102. return;
  103. }
  104. // the lump is only used for one rotation
  105. if (sprtemp[frame].rotate == false)
  106. I_Error ("R_InitSprites: Sprite %s frame %c has rotations "
  107. "and a rot=0 lump", spritename, 'A'+frame);
  108. sprtemp[frame].rotate = true;
  109. // make 0 based
  110. rotation--;
  111. if (sprtemp[frame].lump[rotation] != -1)
  112. I_Error ("R_InitSprites: Sprite %s : %c : %c "
  113. "has two lumps mapped to it",
  114. spritename, 'A'+frame, '1'+rotation);
  115. sprtemp[frame].lump[rotation] = lump - firstspritelump;
  116. sprtemp[frame].flip[rotation] = (byte)flipped;
  117. }
  118. //
  119. // R_InitSpriteDefs
  120. // Pass a null terminated list of sprite names
  121. // (4 chars exactly) to be used.
  122. // Builds the sprite rotation matrixes to account
  123. // for horizontally flipped sprites.
  124. // Will report an error if the lumps are inconsistant.
  125. // Only called at startup.
  126. //
  127. // Sprite lump names are 4 characters for the actor,
  128. // a letter for the frame, and a number for the rotation.
  129. // A sprite that is flippable will have an additional
  130. // letter/number appended.
  131. // The rotation character can be 0 to signify no rotations.
  132. //
  133. void R_InitSpriteDefs (char** namelist)
  134. {
  135. char** check;
  136. int i;
  137. int l;
  138. int intname;
  139. int frame;
  140. int rotation;
  141. int start;
  142. int end;
  143. int patched;
  144. // count the number of sprite names
  145. check = namelist;
  146. while (*check != NULL)
  147. check++;
  148. numsprites = check-namelist;
  149. if (!numsprites)
  150. return;
  151. sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
  152. start = firstspritelump-1;
  153. end = lastspritelump+1;
  154. // scan all the lump names for each of the names,
  155. // noting the highest frame letter.
  156. // Just compare 4 characters as ints
  157. for (i=0 ; i<numsprites ; i++)
  158. {
  159. spritename = namelist[i];
  160. memset (sprtemp,-1, sizeof(sprtemp));
  161. maxframe = -1;
  162. intname = *(int *)namelist[i];
  163. // scan the lumps,
  164. // filling in the frames for whatever is found
  165. for (l=start+1 ; l<end ; l++)
  166. {
  167. if (*(int *)lumpinfo[l].name == intname)
  168. {
  169. frame = lumpinfo[l].name[4] - 'A';
  170. rotation = lumpinfo[l].name[5] - '0';
  171. if (modifiedgame)
  172. patched = W_GetNumForName (lumpinfo[l].name);
  173. else
  174. patched = l;
  175. R_InstallSpriteLump (patched, frame, rotation, false);
  176. if (lumpinfo[l].name[6])
  177. {
  178. frame = lumpinfo[l].name[6] - 'A';
  179. rotation = lumpinfo[l].name[7] - '0';
  180. R_InstallSpriteLump (l, frame, rotation, true);
  181. }
  182. }
  183. }
  184. // check the frames that were found for completeness
  185. if (maxframe == -1)
  186. {
  187. sprites[i].numframes = 0;
  188. continue;
  189. }
  190. maxframe++;
  191. for (frame = 0 ; frame < maxframe ; frame++)
  192. {
  193. switch ((int)sprtemp[frame].rotate)
  194. {
  195. case -1:
  196. // no rotations were found for that frame at all
  197. I_Error ("R_InitSprites: No patches found "
  198. "for %s frame %c", namelist[i], frame+'A');
  199. break;
  200. case 0:
  201. // only the first rotation is needed
  202. break;
  203. case 1:
  204. // must have all 8 frames
  205. for (rotation=0 ; rotation<8 ; rotation++)
  206. if (sprtemp[frame].lump[rotation] == -1)
  207. I_Error ("R_InitSprites: Sprite %s frame %c "
  208. "is missing rotations",
  209. namelist[i], frame+'A');
  210. break;
  211. }
  212. }
  213. // allocate space for the frames present and copy sprtemp to it
  214. sprites[i].numframes = maxframe;
  215. sprites[i].spriteframes =
  216. Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
  217. memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
  218. }
  219. }
  220. //
  221. // GAME FUNCTIONS
  222. //
  223. vissprite_t vissprites[MAXVISSPRITES];
  224. vissprite_t* vissprite_p;
  225. int newvissprite;
  226. //
  227. // R_InitSprites
  228. // Called at program start.
  229. //
  230. void R_InitSprites (char** namelist)
  231. {
  232. int i;
  233. for (i=0 ; i<SCREENWIDTH ; i++)
  234. {
  235. negonearray[i] = -1;
  236. }
  237. R_InitSpriteDefs (namelist);
  238. }
  239. //
  240. // R_ClearSprites
  241. // Called at frame start.
  242. //
  243. void R_ClearSprites (void)
  244. {
  245. vissprite_p = vissprites;
  246. }
  247. //
  248. // R_NewVisSprite
  249. //
  250. vissprite_t overflowsprite;
  251. vissprite_t* R_NewVisSprite (void)
  252. {
  253. if (vissprite_p == &vissprites[MAXVISSPRITES])
  254. return &overflowsprite;
  255. vissprite_p++;
  256. return vissprite_p-1;
  257. }
  258. //
  259. // R_DrawMaskedColumn
  260. // Used for sprites and masked mid textures.
  261. // Masked means: partly transparent, i.e. stored
  262. // in posts/runs of opaque pixels.
  263. //
  264. short* mfloorclip;
  265. short* mceilingclip;
  266. fixed_t spryscale;
  267. fixed_t sprtopscreen;
  268. void R_DrawMaskedColumn (column_t* column)
  269. {
  270. int topscreen;
  271. int bottomscreen;
  272. fixed_t basetexturemid;
  273. basetexturemid = dc_texturemid;
  274. for ( ; column->topdelta != 0xff ; )
  275. {
  276. // calculate unclipped screen coordinates
  277. // for post
  278. topscreen = sprtopscreen + spryscale*column->topdelta;
  279. bottomscreen = topscreen + spryscale*column->length;
  280. dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
  281. dc_yh = (bottomscreen-1)>>FRACBITS;
  282. if (dc_yh >= mfloorclip[dc_x])
  283. dc_yh = mfloorclip[dc_x]-1;
  284. if (dc_yl <= mceilingclip[dc_x])
  285. dc_yl = mceilingclip[dc_x]+1;
  286. if (dc_yl <= dc_yh)
  287. {
  288. dc_source = (byte *)column + 3;
  289. dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
  290. // dc_source = (byte *)column + 3 - column->topdelta;
  291. // Drawn by either R_DrawColumn
  292. // or (SHADOW) R_DrawFuzzColumn.
  293. colfunc ();
  294. }
  295. column = (column_t *)( (byte *)column + column->length + 4);
  296. }
  297. dc_texturemid = basetexturemid;
  298. }
  299. //
  300. // R_DrawVisSprite
  301. // mfloorclip and mceilingclip should also be set.
  302. //
  303. void
  304. R_DrawVisSprite
  305. ( vissprite_t* vis,
  306. int x1,
  307. int x2 )
  308. {
  309. column_t* column;
  310. int texturecolumn;
  311. fixed_t frac;
  312. patch_t* patch;
  313. patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE);
  314. dc_colormap = vis->colormap;
  315. if (!dc_colormap)
  316. {
  317. // NULL colormap = shadow draw
  318. colfunc = fuzzcolfunc;
  319. }
  320. else if (vis->mobjflags & MF_TRANSLATION)
  321. {
  322. colfunc = R_DrawTranslatedColumn;
  323. dc_translation = translationtables - 256 +
  324. ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) );
  325. }
  326. dc_iscale = abs(vis->xiscale)>>detailshift;
  327. dc_texturemid = vis->texturemid;
  328. frac = vis->startfrac;
  329. spryscale = vis->scale;
  330. sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
  331. for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
  332. {
  333. texturecolumn = frac>>FRACBITS;
  334. #ifdef RANGECHECK
  335. if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
  336. I_Error ("R_DrawSpriteRange: bad texturecolumn");
  337. #endif
  338. column = (column_t *) ((byte *)patch +
  339. LONG(patch->columnofs[texturecolumn]));
  340. R_DrawMaskedColumn (column);
  341. }
  342. colfunc = basecolfunc;
  343. }
  344. //
  345. // R_ProjectSprite
  346. // Generates a vissprite for a thing
  347. // if it might be visible.
  348. //
  349. void R_ProjectSprite (mobj_t* thing)
  350. {
  351. fixed_t tr_x;
  352. fixed_t tr_y;
  353. fixed_t gxt;
  354. fixed_t gyt;
  355. fixed_t tx;
  356. fixed_t tz;
  357. fixed_t xscale;
  358. int x1;
  359. int x2;
  360. spritedef_t* sprdef;
  361. spriteframe_t* sprframe;
  362. int lump;
  363. unsigned rot;
  364. boolean flip;
  365. int index;
  366. vissprite_t* vis;
  367. angle_t ang;
  368. fixed_t iscale;
  369. // transform the origin point
  370. tr_x = thing->x - viewx;
  371. tr_y = thing->y - viewy;
  372. gxt = FixedMul(tr_x,viewcos);
  373. gyt = -FixedMul(tr_y,viewsin);
  374. tz = gxt-gyt;
  375. // thing is behind view plane?
  376. if (tz < MINZ)
  377. return;
  378. xscale = FixedDiv(projection, tz);
  379. gxt = -FixedMul(tr_x,viewsin);
  380. gyt = FixedMul(tr_y,viewcos);
  381. tx = -(gyt+gxt);
  382. // too far off the side?
  383. if (abs(tx)>(tz<<2))
  384. return;
  385. // decide which patch to use for sprite relative to player
  386. #ifdef RANGECHECK
  387. if ((unsigned)thing->sprite >= numsprites)
  388. I_Error ("R_ProjectSprite: invalid sprite number %i ",
  389. thing->sprite);
  390. #endif
  391. sprdef = &sprites[thing->sprite];
  392. #ifdef RANGECHECK
  393. if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
  394. I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
  395. thing->sprite, thing->frame);
  396. #endif
  397. sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
  398. if (sprframe->rotate)
  399. {
  400. // choose a different rotation based on player view
  401. ang = R_PointToAngle (thing->x, thing->y);
  402. rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
  403. lump = sprframe->lump[rot];
  404. flip = (boolean)sprframe->flip[rot];
  405. }
  406. else
  407. {
  408. // use single rotation for all views
  409. lump = sprframe->lump[0];
  410. flip = (boolean)sprframe->flip[0];
  411. }
  412. // calculate edges of the shape
  413. tx -= spriteoffset[lump];
  414. x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
  415. // off the right side?
  416. if (x1 > viewwidth)
  417. return;
  418. tx += spritewidth[lump];
  419. x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
  420. // off the left side
  421. if (x2 < 0)
  422. return;
  423. // store information in a vissprite
  424. vis = R_NewVisSprite ();
  425. vis->mobjflags = thing->flags;
  426. vis->scale = xscale<<detailshift;
  427. vis->gx = thing->x;
  428. vis->gy = thing->y;
  429. vis->gz = thing->z;
  430. vis->gzt = thing->z + spritetopoffset[lump];
  431. vis->texturemid = vis->gzt - viewz;
  432. vis->x1 = x1 < 0 ? 0 : x1;
  433. vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
  434. iscale = FixedDiv (FRACUNIT, xscale);
  435. if (flip)
  436. {
  437. vis->startfrac = spritewidth[lump]-1;
  438. vis->xiscale = -iscale;
  439. }
  440. else
  441. {
  442. vis->startfrac = 0;
  443. vis->xiscale = iscale;
  444. }
  445. if (vis->x1 > x1)
  446. vis->startfrac += vis->xiscale*(vis->x1-x1);
  447. vis->patch = lump;
  448. // get light level
  449. if (thing->flags & MF_SHADOW)
  450. {
  451. // shadow draw
  452. vis->colormap = NULL;
  453. }
  454. else if (fixedcolormap)
  455. {
  456. // fixed map
  457. vis->colormap = fixedcolormap;
  458. }
  459. else if (thing->frame & FF_FULLBRIGHT)
  460. {
  461. // full bright
  462. vis->colormap = colormaps;
  463. }
  464. else
  465. {
  466. // diminished light
  467. index = xscale>>(LIGHTSCALESHIFT-detailshift);
  468. if (index >= MAXLIGHTSCALE)
  469. index = MAXLIGHTSCALE-1;
  470. vis->colormap = spritelights[index];
  471. }
  472. }
  473. //
  474. // R_AddSprites
  475. // During BSP traversal, this adds sprites by sector.
  476. //
  477. void R_AddSprites (sector_t* sec)
  478. {
  479. mobj_t* thing;
  480. int lightnum;
  481. // BSP is traversed by subsector.
  482. // A sector might have been split into several
  483. // subsectors during BSP building.
  484. // Thus we check whether its already added.
  485. if (sec->validcount == validcount)
  486. return;
  487. // Well, now it will be done.
  488. sec->validcount = validcount;
  489. lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
  490. if (lightnum < 0)
  491. spritelights = scalelight[0];
  492. else if (lightnum >= LIGHTLEVELS)
  493. spritelights = scalelight[LIGHTLEVELS-1];
  494. else
  495. spritelights = scalelight[lightnum];
  496. // Handle all things in sector.
  497. for (thing = sec->thinglist ; thing ; thing = thing->snext)
  498. R_ProjectSprite (thing);
  499. }
  500. //
  501. // R_DrawPSprite
  502. //
  503. void R_DrawPSprite (pspdef_t* psp)
  504. {
  505. fixed_t tx;
  506. int x1;
  507. int x2;
  508. spritedef_t* sprdef;
  509. spriteframe_t* sprframe;
  510. int lump;
  511. boolean flip;
  512. vissprite_t* vis;
  513. vissprite_t avis;
  514. // decide which patch to use
  515. #ifdef RANGECHECK
  516. if ( (unsigned)psp->state->sprite >= numsprites)
  517. I_Error ("R_ProjectSprite: invalid sprite number %i ",
  518. psp->state->sprite);
  519. #endif
  520. sprdef = &sprites[psp->state->sprite];
  521. #ifdef RANGECHECK
  522. if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes)
  523. I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
  524. psp->state->sprite, psp->state->frame);
  525. #endif
  526. sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
  527. lump = sprframe->lump[0];
  528. flip = (boolean)sprframe->flip[0];
  529. // calculate edges of the shape
  530. tx = psp->sx-160*FRACUNIT;
  531. tx -= spriteoffset[lump];
  532. x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS;
  533. // off the right side
  534. if (x1 > viewwidth)
  535. return;
  536. tx += spritewidth[lump];
  537. x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
  538. // off the left side
  539. if (x2 < 0)
  540. return;
  541. // store information in a vissprite
  542. vis = &avis;
  543. vis->mobjflags = 0;
  544. vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
  545. vis->x1 = x1 < 0 ? 0 : x1;
  546. vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
  547. vis->scale = pspritescale<<detailshift;
  548. if (flip)
  549. {
  550. vis->xiscale = -pspriteiscale;
  551. vis->startfrac = spritewidth[lump]-1;
  552. }
  553. else
  554. {
  555. vis->xiscale = pspriteiscale;
  556. vis->startfrac = 0;
  557. }
  558. if (vis->x1 > x1)
  559. vis->startfrac += vis->xiscale*(vis->x1-x1);
  560. vis->patch = lump;
  561. if (viewplayer->powers[pw_invisibility] > 4*32
  562. || viewplayer->powers[pw_invisibility] & 8)
  563. {
  564. // shadow draw
  565. vis->colormap = NULL;
  566. }
  567. else if (fixedcolormap)
  568. {
  569. // fixed color
  570. vis->colormap = fixedcolormap;
  571. }
  572. else if (psp->state->frame & FF_FULLBRIGHT)
  573. {
  574. // full bright
  575. vis->colormap = colormaps;
  576. }
  577. else
  578. {
  579. // local light
  580. vis->colormap = spritelights[MAXLIGHTSCALE-1];
  581. }
  582. R_DrawVisSprite (vis, vis->x1, vis->x2);
  583. }
  584. //
  585. // R_DrawPlayerSprites
  586. //
  587. void R_DrawPlayerSprites (void)
  588. {
  589. int i;
  590. int lightnum;
  591. pspdef_t* psp;
  592. // get light level
  593. lightnum =
  594. (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
  595. +extralight;
  596. if (lightnum < 0)
  597. spritelights = scalelight[0];
  598. else if (lightnum >= LIGHTLEVELS)
  599. spritelights = scalelight[LIGHTLEVELS-1];
  600. else
  601. spritelights = scalelight[lightnum];
  602. // clip to screen bounds
  603. mfloorclip = screenheightarray;
  604. mceilingclip = negonearray;
  605. // add all active psprites
  606. for (i=0, psp=viewplayer->psprites;
  607. i<NUMPSPRITES;
  608. i++,psp++)
  609. {
  610. if (psp->state)
  611. R_DrawPSprite (psp);
  612. }
  613. }
  614. //
  615. // R_SortVisSprites
  616. //
  617. vissprite_t vsprsortedhead;
  618. void R_SortVisSprites (void)
  619. {
  620. int i;
  621. int count;
  622. vissprite_t* ds;
  623. vissprite_t* best;
  624. vissprite_t unsorted;
  625. fixed_t bestscale;
  626. count = vissprite_p - vissprites;
  627. unsorted.next = unsorted.prev = &unsorted;
  628. if (!count)
  629. return;
  630. for (ds=vissprites ; ds<vissprite_p ; ds++)
  631. {
  632. ds->next = ds+1;
  633. ds->prev = ds-1;
  634. }
  635. vissprites[0].prev = &unsorted;
  636. unsorted.next = &vissprites[0];
  637. (vissprite_p-1)->next = &unsorted;
  638. unsorted.prev = vissprite_p-1;
  639. // pull the vissprites out by scale
  640. //best = 0; // shut up the compiler warning
  641. vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
  642. for (i=0 ; i<count ; i++)
  643. {
  644. bestscale = MAXINT;
  645. for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
  646. {
  647. if (ds->scale < bestscale)
  648. {
  649. bestscale = ds->scale;
  650. best = ds;
  651. }
  652. }
  653. best->next->prev = best->prev;
  654. best->prev->next = best->next;
  655. best->next = &vsprsortedhead;
  656. best->prev = vsprsortedhead.prev;
  657. vsprsortedhead.prev->next = best;
  658. vsprsortedhead.prev = best;
  659. }
  660. }
  661. //
  662. // R_DrawSprite
  663. //
  664. void R_DrawSprite (vissprite_t* spr)
  665. {
  666. drawseg_t* ds;
  667. short clipbot[SCREENWIDTH];
  668. short cliptop[SCREENWIDTH];
  669. int x;
  670. int r1;
  671. int r2;
  672. fixed_t scale;
  673. fixed_t lowscale;
  674. int silhouette;
  675. for (x = spr->x1 ; x<=spr->x2 ; x++)
  676. clipbot[x] = cliptop[x] = -2;
  677. // Scan drawsegs from end to start for obscuring segs.
  678. // The first drawseg that has a greater scale
  679. // is the clip seg.
  680. for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
  681. {
  682. // determine if the drawseg obscures the sprite
  683. if (ds->x1 > spr->x2
  684. || ds->x2 < spr->x1
  685. || (!ds->silhouette
  686. && !ds->maskedtexturecol) )
  687. {
  688. // does not cover sprite
  689. continue;
  690. }
  691. r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
  692. r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
  693. if (ds->scale1 > ds->scale2)
  694. {
  695. lowscale = ds->scale2;
  696. scale = ds->scale1;
  697. }
  698. else
  699. {
  700. lowscale = ds->scale1;
  701. scale = ds->scale2;
  702. }
  703. if (scale < spr->scale
  704. || ( lowscale < spr->scale
  705. && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) )
  706. {
  707. // masked mid texture?
  708. if (ds->maskedtexturecol)
  709. R_RenderMaskedSegRange (ds, r1, r2);
  710. // seg is behind sprite
  711. continue;
  712. }
  713. // clip this piece of the sprite
  714. silhouette = ds->silhouette;
  715. if (spr->gz >= ds->bsilheight)
  716. silhouette &= ~SIL_BOTTOM;
  717. if (spr->gzt <= ds->tsilheight)
  718. silhouette &= ~SIL_TOP;
  719. if (silhouette == 1)
  720. {
  721. // bottom sil
  722. for (x=r1 ; x<=r2 ; x++)
  723. if (clipbot[x] == -2)
  724. clipbot[x] = ds->sprbottomclip[x];
  725. }
  726. else if (silhouette == 2)
  727. {
  728. // top sil
  729. for (x=r1 ; x<=r2 ; x++)
  730. if (cliptop[x] == -2)
  731. cliptop[x] = ds->sprtopclip[x];
  732. }
  733. else if (silhouette == 3)
  734. {
  735. // both
  736. for (x=r1 ; x<=r2 ; x++)
  737. {
  738. if (clipbot[x] == -2)
  739. clipbot[x] = ds->sprbottomclip[x];
  740. if (cliptop[x] == -2)
  741. cliptop[x] = ds->sprtopclip[x];
  742. }
  743. }
  744. }
  745. // all clipping has been performed, so draw the sprite
  746. // check for unclipped columns
  747. for (x = spr->x1 ; x<=spr->x2 ; x++)
  748. {
  749. if (clipbot[x] == -2)
  750. clipbot[x] = viewheight;
  751. if (cliptop[x] == -2)
  752. cliptop[x] = -1;
  753. }
  754. mfloorclip = clipbot;
  755. mceilingclip = cliptop;
  756. R_DrawVisSprite (spr, spr->x1, spr->x2);
  757. }
  758. //
  759. // R_DrawMasked
  760. //
  761. void R_DrawMasked (void)
  762. {
  763. vissprite_t* spr;
  764. drawseg_t* ds;
  765. R_SortVisSprites ();
  766. if (vissprite_p > vissprites)
  767. {
  768. // draw all vissprites back to front
  769. for (spr = vsprsortedhead.next ;
  770. spr != &vsprsortedhead ;
  771. spr=spr->next)
  772. {
  773. R_DrawSprite (spr);
  774. }
  775. }
  776. // render any remaining masked mid textures
  777. for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
  778. if (ds->maskedtexturecol)
  779. R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
  780. // draw the psprites on top of everything
  781. // but does not draw on side views
  782. if (!viewangleoffset)
  783. R_DrawPlayerSprites ();
  784. }