r_phase1.c (14023B)
1 2 //Renderer phase 1 - BSP traversal 3 4 #include "doomdef.h" 5 #include "r_local.h" 6 7 int checkcoord[12][4] = // 8005B110 8 { 9 { 3, 0, 2, 1 },/* Above,Left */ 10 { 3, 0, 2, 0 },/* Above,Center */ 11 { 3, 1, 2, 0 },/* Above,Right */ 12 { 0, 0, 0, 0 }, 13 { 2, 0, 2, 1 },/* Center,Left */ 14 { 0, 0, 0, 0 },/* Center,Center */ 15 { 3, 1, 3, 0 },/* Center,Right */ 16 { 0, 0, 0, 0 }, 17 { 2, 0, 3, 1 },/* Below,Left */ 18 { 2, 1, 3, 1 },/* Below,Center */ 19 { 2, 1, 3, 0 },/* Below,Right */ 20 { 0, 0, 0, 0 } 21 }; 22 23 void R_RenderBSPNode(int bspnum); 24 boolean R_CheckBBox(fixed_t bspcoord[4]); 25 void R_Subsector(int num); 26 void R_AddLine(seg_t *line); 27 void R_AddSprite(subsector_t *sub); 28 void R_RenderBSPNodeNoClip(int bspnum); 29 30 // 31 // Kick off the rendering process by initializing the solidsubsectors array and then 32 // starting the BSP traversal. 33 // 34 35 void R_BSP(void) // 80023F30 36 { 37 int count; 38 subsector_t **sub; 39 40 validcount++; 41 rendersky = false; 42 43 numdrawsubsectors = 0; 44 numdrawvissprites = 0; 45 46 visspritehead = vissprites; 47 48 endsubsector = solidsubsectors; /* Init the free memory pointer */ 49 D_memset(solidcols, 0, 320); 50 51 if (camviewpitch == 0) 52 { 53 R_RenderBSPNode(numnodes - 1); /* Begin traversing the BSP tree for all walls in render range */ 54 } 55 else 56 { 57 R_RenderBSPNodeNoClip(numnodes - 1); /* Begin traversing the BSP tree for all walls in render range */ 58 rendersky = true; 59 } 60 61 sub = solidsubsectors; 62 count = numdrawsubsectors; 63 while(count) 64 { 65 R_AddSprite(*sub); /* Render each sprite */ 66 sub++; /* Inc the sprite pointer */ 67 count--; 68 } 69 } 70 71 // 72 // Recursively descend through the BSP, classifying nodes according to the 73 // player's point of view, and render subsectors in view. 74 // 75 76 void R_RenderBSPNode(int bspnum) // 80024020 77 { 78 node_t *bsp; 79 int side; 80 fixed_t dx, dy; 81 fixed_t left, right; 82 83 //printf("R_RenderBSPNode\n"); 84 85 while(!(bspnum & NF_SUBSECTOR)) 86 { 87 bsp = &nodes[bspnum]; 88 89 // Decide which side the view point is on. 90 //side = R_PointOnSide(viewx, viewy, bsp); 91 dx = (viewx - bsp->line.x); 92 dy = (viewy - bsp->line.y); 93 94 left = (bsp->line.dy >> 16) * (dx >> 16); 95 right = (dy >> 16) * (bsp->line.dx >> 16); 96 97 if (right < left) 98 side = 0; /* front side */ 99 else 100 side = 1; /* back side */ 101 102 // check the front space 103 if(R_CheckBBox(bsp->bbox[side])) 104 { 105 R_RenderBSPNode(bsp->children[side]); 106 } 107 108 // continue down the back space 109 if(!R_CheckBBox(bsp->bbox[side^1])) 110 { 111 return; 112 } 113 114 bspnum = bsp->children[side^1]; 115 } 116 117 // subsector with contents 118 // add all the drawable elements in the subsector 119 if(bspnum == -1) 120 bspnum = 0; 121 122 R_Subsector(bspnum & ~NF_SUBSECTOR); 123 } 124 125 // 126 // Checks BSP node/subtree bounding box. Returns true if some part of the bbox 127 // might be visible. 128 // 129 130 boolean R_CheckBBox(fixed_t bspcoord[4]) // 80024170 131 { 132 int boxx; 133 int boxy; 134 int boxpos; 135 136 fixed_t x1, y1, x2, y2; 137 byte *solid_cols; 138 int vx1, vy1, vx2, vy2, delta; 139 int Xstart, Xend; 140 141 // find the corners of the box that define the edges from current viewpoint 142 if (viewx < bspcoord[BOXLEFT]) 143 boxx = 0; 144 else if (viewx <= bspcoord[BOXRIGHT]) 145 boxx = 1; 146 else 147 boxx = 2; 148 149 if (viewy > bspcoord[BOXTOP]) 150 boxy = 0; 151 else if (viewy >= bspcoord[BOXBOTTOM]) 152 boxy = 1; 153 else 154 boxy = 2; 155 156 boxpos = (boxy << 2) + boxx; 157 if (boxpos == 5) 158 return true; 159 160 x1 = bspcoord[checkcoord[boxpos][0]]; 161 y1 = bspcoord[checkcoord[boxpos][1]]; 162 x2 = bspcoord[checkcoord[boxpos][2]]; 163 y2 = bspcoord[checkcoord[boxpos][3]]; 164 165 vx1 = FixedMul(viewsin, x1 - viewx) - FixedMul(viewcos, y1 - viewy); 166 vy1 = FixedMul(viewcos, x1 - viewx) + FixedMul(viewsin, y1 - viewy); 167 vx2 = FixedMul(viewsin, x2 - viewx) - FixedMul(viewcos, y2 - viewy); 168 vy2 = FixedMul(viewcos, x2 - viewx) + FixedMul(viewsin, y2 - viewy); 169 170 if ((vx1 < -vy1) && (vx2 < -vy2)) 171 return false; 172 173 if ((vy1 < vx1) && (vy2 < vx2)) 174 return false; 175 176 if ((((vx2 >> 16) * (vy1 >> 16)) - ((vx1 >> 16) * (vy2 >> 16))) < 2) 177 return true; 178 179 if ((vy1 <= 0) && (vy2 <= 0)) 180 return false; 181 182 if (vx1 < -vy1) 183 { 184 delta = (vx1 + vy1); 185 delta = FixedDiv2(delta, ((delta - vx2) - vy2)); 186 delta = FixedMul(delta, (vy2 - vy1)); 187 188 vy1 += delta; 189 vx1 = -vy1; 190 } 191 192 if (vy2 < vx2) 193 { 194 delta = (vx1 - vy1); 195 delta = FixedDiv2(delta, ((delta - vx2) + vy2)); 196 delta = FixedMul(delta, (vy2 - vy1)); 197 vx2 = delta + vy1; 198 vy2 = vx2; 199 } 200 201 Xstart = ((FixedDiv2(vx1, vy1) * 160) >> 16) + 160; 202 Xend = ((FixedDiv2(vx2, vy2) * 160) >> 16) + 160; 203 204 if (Xstart < 0) 205 Xstart = 0; 206 207 if (Xend >= 320) 208 Xend = 320; 209 210 solid_cols = &solidcols[Xstart]; 211 while (Xstart < Xend) 212 { 213 if (*solid_cols == 0) 214 return true; 215 solid_cols++; 216 Xstart++; 217 } 218 219 return false; 220 } 221 222 // 223 // Determine floor/ceiling planes, add sprites of things in sector, 224 // draw one or more segments. 225 // 226 227 void R_Subsector(int num) // 8002451C 228 { 229 subsector_t *sub; 230 seg_t *line; 231 int count; 232 233 if (num >= numsubsectors) 234 { 235 I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); 236 } 237 238 if (numdrawsubsectors < MAXSUBSECTORS) 239 { 240 numdrawsubsectors++; 241 242 sub = &subsectors[num]; 243 sub->drawindex = numdrawsubsectors; 244 245 *endsubsector = sub;//copy subsector 246 endsubsector++; 247 248 frontsector = sub->sector; 249 250 line = &segs[sub->firstline]; 251 count = sub->numlines; 252 do 253 { 254 R_AddLine(line); /* Render each line */ 255 ++line; /* Inc the line pointer */ 256 } while (--count); /* All done? */ 257 } 258 } 259 260 // 261 // Clips the given segment and adds any visible pieces to the line list. 262 // 263 264 void R_AddLine(seg_t *line) // 80024604 265 { 266 sector_t *backsector; 267 vertex_t *vrt, *vrt2; 268 int x1, y1, x2, y2, count; 269 int Xstart, Xend, delta; 270 byte *solid_cols; 271 272 line->flags &= ~1; 273 274 vrt = line->v1; 275 if (vrt->validcount != validcount) 276 { 277 x1 = FixedMul(viewsin, (vrt->x - viewx)) - FixedMul(viewcos,(vrt->y - viewy)); 278 y1 = FixedMul(viewcos, (vrt->x - viewx)) + FixedMul(viewsin,(vrt->y - viewy)); 279 280 vrt->vx = x1; 281 vrt->vy = y1; 282 283 vrt->validcount = validcount; 284 } 285 else 286 { 287 x1 = vrt->vx; 288 y1 = vrt->vy; 289 } 290 291 vrt2 = line->v2; 292 if (vrt2->validcount != validcount) 293 { 294 x2 = FixedMul(viewsin, (vrt2->x - viewx)) - FixedMul(viewcos,(vrt2->y - viewy)); 295 y2 = FixedMul(viewcos, (vrt2->x - viewx)) + FixedMul(viewsin,(vrt2->y - viewy)); 296 297 vrt2->vx = x2; 298 vrt2->vy = y2; 299 300 vrt2->validcount = validcount; 301 } 302 else 303 { 304 x2 = vrt2->vx; 305 y2 = vrt2->vy; 306 } 307 308 if ((x1 < -y1) && (x2 < -y2)) 309 return; 310 311 if ((y1 < x1) && (y2 < x2)) 312 return; 313 314 if ((y1 < ((8*FRACUNIT)+1)) && (y2 < ((8*FRACUNIT)+1))) 315 return; 316 317 if ((((x2 >> 16) * (y1 >> 16)) - ((x1 >> 16) * (y2 >> 16))) <= 0) 318 return; 319 320 if (y1 < (8*FRACUNIT)) 321 { 322 delta = FixedDiv2(((8*FRACUNIT) - y1), (y2 - y1)); 323 delta = FixedMul(delta, (x2 - x1)); 324 x1 += delta; 325 y1 = (8*FRACUNIT); 326 } 327 else if (y2 < (8*FRACUNIT)) 328 { 329 delta = FixedDiv2(((8*FRACUNIT) - y2), (y1 - y2)); 330 delta = FixedMul(delta, (x1 - x2)); 331 x2 += delta; 332 y2 = (8*FRACUNIT); 333 } 334 335 Xstart = ((FixedDiv2(x1, y1) * 160) >> 16) + 160; 336 Xend = ((FixedDiv2(x2, y2) * 160) >> 16) + 160; 337 338 if (Xstart < 0) 339 Xstart = 0; 340 341 if (Xend >= 320) 342 Xend = 320; 343 344 if (Xstart != Xend) 345 { 346 solid_cols = &solidcols[Xstart]; 347 count = Xstart; 348 while (count < Xend) 349 { 350 if (*solid_cols == 0) 351 { 352 line->flags |= 1; 353 line->linedef->flags |= ML_MAPPED; 354 break; 355 } 356 solid_cols++; 357 count++; 358 } 359 360 if (frontsector->ceilingpic == -1) { 361 rendersky = true; 362 } 363 364 if (!(line->linedef->flags & (ML_DONTOCCLUDE|ML_DRAWMASKED))) 365 { 366 backsector = line->backsector; 367 368 if(!backsector || 369 backsector->ceilingheight <= frontsector->floorheight || 370 backsector->floorheight >= frontsector->ceilingheight || 371 backsector->floorheight == backsector->ceilingheight) // New line on Doom 64 372 { 373 solid_cols = &solidcols[Xstart]; 374 while (Xstart < Xend) 375 { 376 *solid_cols = 1; 377 solid_cols++; 378 Xstart += 1; 379 } 380 } 381 } 382 } 383 } 384 385 void R_AddSprite(subsector_t *sub) // 80024A98 386 { 387 byte *data; 388 mobj_t *thing; 389 spritedef_t *sprdef; 390 spriteframe_t *sprframe; 391 392 subsector_t *pSub; 393 subsector_t *CurSub; 394 vissprite_t *VisSrpCur, *VisSrpCurTmp; 395 vissprite_t *VisSrpNew; 396 397 angle_t ang; 398 unsigned int rot; 399 boolean flip; 400 int lump; 401 fixed_t tx, tz; 402 fixed_t x, y; 403 int numdraw; 404 405 sub->vissprite = NULL; 406 407 for (thing = sub->sector->thinglist; thing; thing = thing->snext) 408 { 409 if (thing->subsector != sub) 410 continue; 411 412 if (numdrawvissprites >= MAXVISSPRITES) 413 break; 414 415 if (thing->flags & MF_RENDERLASER) 416 { 417 visspritehead->zdistance = MAXINT; 418 visspritehead->thing = thing; 419 visspritehead->next = sub->vissprite; 420 sub->vissprite = visspritehead; 421 422 visspritehead++; 423 numdrawvissprites++; 424 } 425 else 426 { 427 // transform origin relative to viewpoint 428 x = (thing->x - viewx) >> 16; 429 y = (thing->y - viewy) >> 16; 430 tx = ((viewsin * x) - (viewcos * y)) >> 16; 431 tz = ((viewcos * x) + (viewsin * y)) >> 16; 432 433 // thing is behind view plane? 434 if (tz < MINZ) 435 continue; 436 437 // too far off the side? 438 if (tx > (tz << 1) || tx < -(tz << 1)) 439 continue; 440 441 sprdef = &sprites[thing->sprite]; 442 sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; 443 444 if (sprframe->rotate != 0) 445 { 446 ang = R_PointToAngle2(viewx, viewy, thing->x, thing->y); 447 rot = ((ang - thing->angle) + ((unsigned int)(ANG45 / 2) * 9)) >> 29; 448 lump = sprframe->lump[rot]; 449 flip = (boolean)(sprframe->flip[rot]); 450 } 451 else 452 { 453 lump = sprframe->lump[0]; 454 flip = (boolean)(sprframe->flip[0]); 455 } 456 457 visspritehead->zdistance = tz; 458 visspritehead->thing = thing; 459 visspritehead->lump = lump; 460 visspritehead->flip = flip; 461 visspritehead->next = NULL; 462 visspritehead->sector = sub->sector; 463 464 data = (byte *)W_CacheLumpNum(lump, PU_CACHE, dec_jag); 465 466 CurSub = sub; 467 if (tz < MAXZ) 468 { 469 if (thing->flags & (MF_CORPSE|MF_SHOOTABLE)) 470 { 471 x = ((((spriteN64_t*)data)->width >> 1) * viewsin); 472 y = ((((spriteN64_t*)data)->width >> 1) * viewcos); 473 474 pSub = R_PointInSubsector((thing->x - x), (thing->y + y)); 475 if ((pSub->drawindex) && (pSub->drawindex < sub->drawindex)) { 476 CurSub = pSub; 477 } 478 479 pSub = R_PointInSubsector((thing->x + x), (thing->y - y)); 480 if ((pSub->drawindex) && (pSub->drawindex < CurSub->drawindex)) { 481 CurSub = pSub; 482 } 483 } 484 } 485 486 VisSrpCur = CurSub->vissprite; 487 VisSrpNew = NULL; 488 489 if (VisSrpCur) 490 { 491 VisSrpCurTmp = VisSrpCur; 492 while ((VisSrpCur = VisSrpCurTmp, tz < VisSrpCur->zdistance)) 493 { 494 VisSrpCur = VisSrpCurTmp->next; 495 VisSrpNew = VisSrpCurTmp; 496 497 if (VisSrpCur == NULL) 498 break; 499 500 VisSrpCurTmp = VisSrpCur; 501 } 502 } 503 504 if (VisSrpNew) 505 VisSrpNew->next = visspritehead; 506 else 507 CurSub->vissprite = visspritehead; 508 509 visspritehead->next = VisSrpCur; 510 511 numdrawvissprites++; 512 visspritehead++; 513 } 514 } 515 } 516 517 void R_RenderBSPNodeNoClip(int bspnum) // 80024E64 518 { 519 subsector_t *sub; 520 seg_t *line; 521 int count; 522 node_t *bsp; 523 int side; 524 fixed_t dx, dy; 525 fixed_t left, right; 526 527 while(!(bspnum & NF_SUBSECTOR)) 528 { 529 bsp = &nodes[bspnum]; 530 531 // Decide which side the view point is on. 532 //side = R_PointOnSide(viewx, viewy, bsp); 533 dx = (viewx - bsp->line.x); 534 dy = (viewy - bsp->line.y); 535 536 left = (bsp->line.dy >> 16) * (dx >> 16); 537 right = (dy >> 16) * (bsp->line.dx >> 16); 538 539 if (right < left) 540 side = 1; /* back side */ 541 else 542 side = 0; /* front side */ 543 544 R_RenderBSPNodeNoClip(bsp->children[side ^ 1]); 545 546 bspnum = bsp->children[side]; 547 } 548 549 // subsector with contents 550 // add all the drawable elements in the subsector 551 552 numdrawsubsectors++; 553 554 sub = &subsectors[bspnum & ~NF_SUBSECTOR]; 555 sub->drawindex = numdrawsubsectors; 556 557 *endsubsector = sub;//copy subsector 558 endsubsector++; 559 560 frontsector = sub->sector; 561 562 line = &segs[sub->firstline]; 563 count = sub->numlines; 564 do 565 { 566 line->flags |= 1; /* Render each line */ 567 ++line; /* Inc the line pointer */ 568 } while (--count); /* All done? */ 569 }