r_things.c (13830B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #include "doomdef.h" 5 #include "i_system.h" 6 #include "z_zone.h" 7 #include "w_wad.h" 8 #include "m_swap.h" 9 #include "r_local.h" 10 #include "doomstat.h" 11 12 #define MINZ (FRACUNIT*4) 13 #define BASEYCENTER 100 14 15 typedef struct { 16 int x1; 17 int x2; 18 int column; 19 int topclip; 20 int bottomclip; 21 } maskdraw_t; 22 23 fixed_t pspritescale; 24 fixed_t pspriteiscale; 25 lighttable_t** spritelights; 26 short negonearray[SCREENWIDTH]; 27 short screenheightarray[SCREENWIDTH]; 28 spritedef_t* sprites; 29 int numsprites; 30 spriteframe_t sprtemp[29]; 31 int maxframe; 32 char* spritename; 33 34 void 35 R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, boolean flipped) 36 { 37 int r; 38 39 if (frame >= 29 || rotation > 8) 40 I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); 41 if ((int)frame > maxframe) 42 maxframe = frame; 43 if (rotation == 0) { 44 if (sprtemp[frame].rotate == false) 45 I_Error ("R_InitSprites: Sprite %s frame %c has multip rot=0 lump", spritename, 'A'+frame); 46 if (sprtemp[frame].rotate == true) 47 I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", spritename, 'A'+frame); 48 sprtemp[frame].rotate = false; 49 for (r = 0; r < 8; ++r) { 50 sprtemp[frame].lump[r] = lump - firstspritelump; 51 sprtemp[frame].flip[r] = (byte)flipped; 52 } 53 return; 54 } 55 if (sprtemp[frame].rotate == false) 56 I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", spritename, 'A'+frame); 57 sprtemp[frame].rotate = true; 58 --rotation; 59 if (sprtemp[frame].lump[rotation] != -1) 60 I_Error("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it", spritename, 'A'+frame, '1'+rotation); 61 sprtemp[frame].lump[rotation] = lump - firstspritelump; 62 sprtemp[frame].flip[rotation] = (byte)flipped; 63 } 64 65 void 66 R_InitSpriteDefs(char** namelist) 67 { 68 int i, l, intname, frame, rotation, start, end, patched; 69 70 numsprites = LENGTH(sprnames); 71 if (!numsprites) 72 return; 73 sprites = Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); 74 start = firstspritelump - 1; 75 end = lastspritelump + 1; 76 for (i = 0; i < numsprites; ++i) { 77 spritename = namelist[i]; 78 memset(sprtemp, -1, sizeof(sprtemp)); 79 maxframe = -1; 80 intname = *(int*)namelist[i]; 81 for (l = start + 1; l < end; ++l) { 82 if (*(int*)lumpinfo_g[l].name == intname) { 83 frame = lumpinfo_g[l].name[4] - 'A'; 84 rotation = lumpinfo_g[l].name[5] - '0'; 85 if (modifiedgame) 86 patched = W_GetNumForName(lumpinfo_g[l].name); 87 else 88 patched = l; 89 R_InstallSpriteLump(patched, frame, rotation, false); 90 if (lumpinfo_g[l].name[6]) { 91 frame = lumpinfo_g[l].name[6] - 'A'; 92 rotation = lumpinfo_g[l].name[7] - '0'; 93 R_InstallSpriteLump(l, frame, rotation, true); 94 } 95 } 96 } 97 if (maxframe == -1) { 98 sprites[i].numframes = 0; 99 continue; 100 } 101 ++maxframe; 102 103 for (frame = 0; frame < maxframe; ++frame) { 104 switch ((int)sprtemp[frame].rotate) { 105 case -1: 106 I_Error ("R_InitSprites: No patches found for %s frame %c", namelist[i], frame+'A'); 107 break; 108 case 0: 109 break; 110 case 1: 111 for (rotation = 0; rotation < 8; ++rotation) 112 if (sprtemp[frame].lump[rotation] == -1) 113 I_Error("R_InitSprites: Sprite %s frame %c is missing rotations", namelist[i], frame+'A'); 114 break; 115 } 116 } 117 sprites[i].numframes = maxframe; 118 sprites[i].spriteframes = Z_Malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); 119 memcpy(sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); 120 } 121 } 122 123 vissprite_t vissprites[MAXVISSPRITES]; 124 vissprite_t* vissprite_p; 125 int newvissprite; 126 127 void 128 R_InitSprites(char** namelist) 129 { 130 int i; 131 132 for (i = 0; i < SCREENWIDTH; ++i) 133 negonearray[i] = -1; 134 R_InitSpriteDefs(namelist); 135 } 136 137 void 138 R_ClearSprites() 139 { 140 vissprite_p = vissprites; 141 } 142 143 vissprite_t overflowsprite; 144 145 vissprite_t* 146 R_NewVisSprite() 147 { 148 if (vissprite_p == &vissprites[MAXVISSPRITES]) 149 return &overflowsprite; 150 ++vissprite_p; 151 return vissprite_p - 1; 152 } 153 154 155 short* mfloorclip; 156 short* mceilingclip; 157 fixed_t spryscale; 158 fixed_t sprtopscreen; 159 160 void 161 R_DrawMaskedColumn(column_t* column) 162 { 163 fixed_t basetexturemid; 164 int topscreen, bottomscreen; 165 166 basetexturemid = dc_texturemid; 167 for (; column->topdelta != 0xff;) { 168 topscreen = sprtopscreen + spryscale*column->topdelta; 169 bottomscreen = topscreen + spryscale*column->length; 170 dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; 171 dc_yh = (bottomscreen-1)>>FRACBITS; 172 if (dc_yh >= mfloorclip[dc_x]) 173 dc_yh = mfloorclip[dc_x]-1; 174 if (dc_yl <= mceilingclip[dc_x]) 175 dc_yl = mceilingclip[dc_x]+1; 176 if (dc_yl <= dc_yh) { 177 dc_source = (byte *)column + 3; 178 dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS); 179 colfunc (); 180 } 181 column = (column_t *)( (byte *)column + column->length + 4); 182 } 183 dc_texturemid = basetexturemid; 184 } 185 186 void 187 R_DrawVisSprite(vissprite_t* vis, int x1, int x2) 188 { 189 column_t* column; 190 patch_t* patch; 191 fixed_t frac; 192 int texturecolumn; 193 194 patch = W_CacheLumpNum(vis->patch + firstspritelump, PU_CACHE); 195 dc_colormap = vis->colormap; 196 if (!dc_colormap) 197 colfunc = fuzzcolfunc; 198 if (vis->mobjflags & MF_TRANSLATION) { 199 colfunc = R_DrawTranslatedColumn; 200 dc_translation = translationtables - 256 + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8)); 201 } 202 dc_iscale = abs(vis->xiscale)>>detailshift; 203 dc_texturemid = vis->texturemid; 204 frac = vis->startfrac; 205 spryscale = vis->scale; 206 sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); 207 for (dc_x = vis->x1; dc_x <= vis->x2; ++dc_x, frac += vis->xiscale) { 208 texturecolumn = frac>>FRACBITS; 209 #ifdef RANGECHECK 210 if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) 211 I_Error ("R_DrawSpriteRange: bad texturecolumn"); 212 #endif 213 column = (column_t*)((byte*)patch + LONG(patch->columnofs[texturecolumn])); 214 R_DrawMaskedColumn (column); 215 } 216 colfunc = basecolfunc; 217 } 218 219 void 220 R_ProjectSprite(mobj_t* thing) 221 { 222 spriteframe_t* sprframe; 223 spritedef_t* sprdef; 224 vissprite_t* vis; 225 angle_t ang; 226 fixed_t tr_x, tr_y, gxt, gyt, tx, tz, xscale, iscale; 227 int x1, x2, lump, index; 228 uint rot; 229 boolean flip; 230 231 tr_x = thing->x - viewx; 232 tr_y = thing->y - viewy; 233 gxt = FixedMul(tr_x,viewcos); 234 gyt = -FixedMul(tr_y,viewsin); 235 tz = gxt - gyt; 236 if (tz < MINZ) 237 return; 238 xscale = FixedDiv(projection, tz); 239 gxt = -FixedMul(tr_x,viewsin); 240 gyt = FixedMul(tr_y,viewcos); 241 tx = -(gyt+gxt); 242 if (abs(tx)>(tz<<2)) 243 return; 244 #ifdef RANGECHECK 245 if ((unsigned)thing->sprite >= numsprites) 246 I_Error ("R_ProjectSprite: invalid sprite number %i ", thing->sprite); 247 #endif 248 sprdef = &sprites[thing->sprite]; 249 #ifdef RANGECHECK 250 if ((thing->frame&FF_FRAMEMASK) >= sprdef->numframes) 251 I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", thing->sprite, thing->frame); 252 #endif 253 sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; 254 if (sprframe->rotate) { 255 ang = R_PointToAngle (thing->x, thing->y); 256 rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; 257 lump = sprframe->lump[rot]; 258 flip = (boolean)sprframe->flip[rot]; 259 } else { 260 lump = sprframe->lump[0]; 261 flip = (boolean)sprframe->flip[0]; 262 } 263 tx -= spriteoffset[lump]; 264 x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; 265 if (x1 > viewwidth) 266 return; 267 tx += spritewidth[lump]; 268 x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; 269 if (x2 < 0) 270 return; 271 vis = R_NewVisSprite(); 272 vis->mobjflags = thing->flags; 273 vis->scale = xscale<<detailshift; 274 vis->gx = thing->x; 275 vis->gy = thing->y; 276 vis->gz = thing->z; 277 vis->gzt = thing->z + spritetopoffset[lump]; 278 vis->texturemid = vis->gzt - viewz; 279 vis->x1 = x1 < 0 ? 0 : x1; 280 vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; 281 iscale = FixedDiv(FRACUNIT, xscale); 282 if (flip) { 283 vis->startfrac = spritewidth[lump]-1; 284 vis->xiscale = -iscale; 285 } else { 286 vis->startfrac = 0; 287 vis->xiscale = iscale; 288 } 289 if (vis->x1 > x1) 290 vis->startfrac += vis->xiscale*(vis->x1-x1); 291 vis->patch = lump; 292 if (thing->flags & MF_SHADOW) 293 vis->colormap = NULL; 294 else if (fixedcolormap) 295 vis->colormap = fixedcolormap; 296 else if (thing->frame & FF_FULLBRIGHT) 297 vis->colormap = colormaps; 298 else { 299 index = xscale>>(LIGHTSCALESHIFT-detailshift); 300 if (index >= MAXLIGHTSCALE) 301 index = MAXLIGHTSCALE-1; 302 vis->colormap = spritelights[index]; 303 } 304 } 305 306 void 307 R_AddSprites(sector_t* sec) 308 { 309 mobj_t* thing; 310 int lightnum; 311 312 if (sec->validcount == validcount) 313 return; 314 sec->validcount = validcount; 315 lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; 316 if (lightnum < 0) 317 spritelights = scalelight[0]; 318 else if (lightnum >= LIGHTLEVELS) 319 spritelights = scalelight[LIGHTLEVELS-1]; 320 else 321 spritelights = scalelight[lightnum]; 322 for (thing = sec->thinglist; thing; thing = thing->snext) 323 R_ProjectSprite (thing); 324 } 325 326 void 327 R_DrawPSprite(pspdef_t* psp) 328 { 329 spriteframe_t* sprframe; 330 spritedef_t* sprdef; 331 vissprite_t avis, *vis; 332 fixed_t tx; 333 int x1, x2, lump; 334 boolean flip; 335 #ifdef RANGECHECK 336 if ( (unsigned)psp->state->sprite >= numsprites) 337 I_Error ("R_ProjectSprite: invalid sprite number %i ", psp->state->sprite); 338 #endif 339 sprdef = &sprites[psp->state->sprite]; 340 #ifdef RANGECHECK 341 if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) 342 I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", psp->state->sprite, psp->state->frame); 343 #endif 344 sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; 345 lump = sprframe->lump[0]; 346 flip = (boolean)sprframe->flip[0]; 347 tx = psp->sx-160*FRACUNIT; 348 tx -= spriteoffset[lump]; 349 x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; 350 if (x1 > viewwidth) 351 return; 352 tx += spritewidth[lump]; 353 x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; 354 if (x2 < 0) 355 return; 356 vis = &avis; 357 vis->mobjflags = 0; 358 vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]); 359 vis->x1 = x1 < 0 ? 0 : x1; 360 vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; 361 vis->scale = pspritescale<<detailshift; 362 if (flip) { 363 vis->xiscale = -pspriteiscale; 364 vis->startfrac = spritewidth[lump]-1; 365 } else { 366 vis->xiscale = pspriteiscale; 367 vis->startfrac = 0; 368 } 369 if (vis->x1 > x1) 370 vis->startfrac += vis->xiscale*(vis->x1-x1); 371 vis->patch = lump; 372 if (viewplayer->powers[pw_invisibility] > 4*32 || viewplayer->powers[pw_invisibility] & 8) 373 vis->colormap = NULL; 374 else if (fixedcolormap) 375 vis->colormap = fixedcolormap; 376 else if (psp->state->frame & FF_FULLBRIGHT) 377 vis->colormap = colormaps; 378 else 379 vis->colormap = spritelights[MAXLIGHTSCALE-1]; 380 R_DrawVisSprite (vis, vis->x1, vis->x2); 381 } 382 383 void 384 R_DrawPlayerSprites() 385 { 386 int i, lightnum; 387 pspdef_t* psp; 388 389 lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + extralight; 390 if (lightnum < 0) 391 spritelights = scalelight[0]; 392 else if (lightnum >= LIGHTLEVELS) 393 spritelights = scalelight[LIGHTLEVELS-1]; 394 else 395 spritelights = scalelight[lightnum]; 396 mfloorclip = screenheightarray; 397 mceilingclip = negonearray; 398 for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; ++i, ++psp) 399 if (psp->state) 400 R_DrawPSprite(psp); 401 } 402 403 vissprite_t vsprsortedhead; 404 405 void 406 R_SortVisSprites() 407 { 408 vissprite_t* best, *ds; 409 vissprite_t unsorted; 410 fixed_t bestscale; 411 int i, count; 412 413 count = vissprite_p - vissprites; 414 unsorted.next = unsorted.prev = &unsorted; 415 if (!count) 416 return; 417 for (ds = vissprites; ds < vissprite_p; ++ds) { 418 ds->next = ds+1; 419 ds->prev = ds-1; 420 } 421 vissprites[0].prev = &unsorted; 422 unsorted.next = &vissprites[0]; 423 (vissprite_p-1)->next = &unsorted; 424 unsorted.prev = vissprite_p-1; 425 vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; 426 for (i = 0; i < count; ++i) { 427 bestscale = INT_MAX; 428 for (best = ds = unsorted.next; ds != &unsorted; ds = ds->next) { 429 if (ds->scale < bestscale) { 430 bestscale = ds->scale; 431 best = ds; 432 } 433 } 434 best->next->prev = best->prev; 435 best->prev->next = best->next; 436 best->next = &vsprsortedhead; 437 best->prev = vsprsortedhead.prev; 438 vsprsortedhead.prev->next = best; 439 vsprsortedhead.prev = best; 440 } 441 } 442 443 void 444 R_DrawSprite(vissprite_t* spr) 445 { 446 drawseg_t* ds; 447 short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH]; 448 fixed_t scale, lowscale; 449 int x, r1, r2, silhouette; 450 451 for (x = spr->x1; x <= spr->x2; ++x) 452 clipbot[x] = cliptop[x] = -2; 453 for (ds = ds_p-1; ds >= drawsegs; --ds) { 454 if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || (!ds->silhouette && !ds->maskedtexturecol) ) 455 continue; 456 r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; 457 r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; 458 if (ds->scale1 > ds->scale2) { 459 lowscale = ds->scale2; 460 scale = ds->scale1; 461 } else { 462 lowscale = ds->scale1; 463 scale = ds->scale2; 464 } 465 if (scale < spr->scale || ( lowscale < spr->scale && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) { 466 if (ds->maskedtexturecol) 467 R_RenderMaskedSegRange (ds, r1, r2); 468 continue; 469 } 470 silhouette = ds->silhouette; 471 if (spr->gz >= ds->bsilheight) 472 silhouette &= ~SIL_BOTTOM; 473 if (spr->gzt <= ds->tsilheight) 474 silhouette &= ~SIL_TOP; 475 if (silhouette == 1) { 476 for (x = r1; x <= r2; ++x) 477 if (clipbot[x] == -2) 478 clipbot[x] = ds->sprbottomclip[x]; 479 } 480 if (silhouette == 2) { 481 for (x = r1; x <= r2; ++x) 482 if (cliptop[x] == -2) 483 cliptop[x] = ds->sprtopclip[x]; 484 } 485 if (silhouette == 3) { 486 for (x = r1; x <= r2; ++x) { 487 if (clipbot[x] == -2) 488 clipbot[x] = ds->sprbottomclip[x]; 489 if (cliptop[x] == -2) 490 cliptop[x] = ds->sprtopclip[x]; 491 } 492 } 493 } 494 for (x = spr->x1; x <= spr->x2; ++x) { 495 if (clipbot[x] == -2) 496 clipbot[x] = viewheight; 497 if (cliptop[x] == -2) 498 cliptop[x] = -1; 499 } 500 mfloorclip = clipbot; 501 mceilingclip = cliptop; 502 R_DrawVisSprite(spr, spr->x1, spr->x2); 503 } 504 505 void 506 R_DrawMasked() 507 { 508 vissprite_t* spr; 509 drawseg_t* ds; 510 511 R_SortVisSprites(); 512 if (vissprite_p > vissprites) { 513 for (spr = vsprsortedhead.next; spr != &vsprsortedhead; spr=spr->next) 514 R_DrawSprite(spr); 515 } 516 for (ds = ds_p-1; ds >= drawsegs; --ds) 517 if (ds->maskedtexturecol) 518 R_RenderMaskedSegRange(ds, ds->x1, ds->x2); 519 if (!viewangleoffset) 520 R_DrawPlayerSprites(); 521 }