DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

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 }