doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

p_sight.c (4774B)


      1 #include "doomdef.h"
      2 
      3 #include "i_system.h"
      4 #include "p_local.h"
      5 
      6 
      7 #include "r_state.h"
      8 
      9 
     10 
     11 
     12 fixed_t		sightzstart;		
     13 fixed_t		topslope;
     14 fixed_t		bottomslope;		
     15 
     16 divline_t	strace;			
     17 fixed_t		t2x;
     18 fixed_t		t2y;
     19 
     20 int		sightcounts[2];
     21 
     22 
     23 
     24 
     25 
     26 
     27 int
     28 P_DivlineSide
     29 ( fixed_t	x,
     30   fixed_t	y,
     31   divline_t*	node )
     32 {
     33     fixed_t	dx;
     34     fixed_t	dy;
     35     fixed_t	left;
     36     fixed_t	right;
     37 
     38     if (!node->dx)
     39     {
     40 	if (x==node->x)
     41 	    return 2;
     42 	
     43 	if (x <= node->x)
     44 	    return node->dy > 0;
     45 
     46 	return node->dy < 0;
     47     }
     48     
     49     if (!node->dy)
     50     {
     51 	if (x==node->y)
     52 	    return 2;
     53 
     54 	if (y <= node->y)
     55 	    return node->dx < 0;
     56 
     57 	return node->dx > 0;
     58     }
     59 	
     60     dx = (x - node->x);
     61     dy = (y - node->y);
     62 
     63     left =  (node->dy>>FRACBITS) * (dx>>FRACBITS);
     64     right = (dy>>FRACBITS) * (node->dx>>FRACBITS);
     65 	
     66     if (right < left)
     67 	return 0;	
     68     
     69     if (left == right)
     70 	return 2;
     71     return 1;		
     72 }
     73 
     74 
     75 
     76 
     77 
     78 
     79 
     80 
     81 fixed_t
     82 P_InterceptVector2
     83 ( divline_t*	v2,
     84   divline_t*	v1 )
     85 {
     86     fixed_t	frac;
     87     fixed_t	num;
     88     fixed_t	den;
     89 	
     90     den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
     91 
     92     if (den == 0)
     93 	return 0;
     94     
     95     
     96     num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + 
     97 	FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
     98     frac = FixedDiv (num , den);
     99 
    100     return frac;
    101 }
    102 
    103 
    104 
    105 
    106 
    107 
    108 boolean P_CrossSubsector (int num)
    109 {
    110     seg_t*		seg;
    111     line_t*		line;
    112     int			s1;
    113     int			s2;
    114     int			count;
    115     subsector_t*	sub;
    116     sector_t*		front;
    117     sector_t*		back;
    118     fixed_t		opentop;
    119     fixed_t		openbottom;
    120     divline_t		divl;
    121     vertex_t*		v1;
    122     vertex_t*		v2;
    123     fixed_t		frac;
    124     fixed_t		slope;
    125 	
    126 #ifdef RANGECHECK
    127     if (num>=numsubsectors)
    128 	I_Error ("P_CrossSubsector: ss %i with numss = %i",
    129 		 num,
    130 		 numsubsectors);
    131 #endif
    132 
    133     sub = &subsectors[num];
    134     
    135     
    136     count = sub->numlines;
    137     seg = &segs[sub->firstline];
    138 
    139     for ( ; count ; seg++, count--)
    140     {
    141 	line = seg->linedef;
    142 
    143 	
    144 	if (line->validcount == validcount)
    145 	    continue;
    146 	
    147 	line->validcount = validcount;
    148 		
    149 	v1 = line->v1;
    150 	v2 = line->v2;
    151 	s1 = P_DivlineSide (v1->x,v1->y, &strace);
    152 	s2 = P_DivlineSide (v2->x, v2->y, &strace);
    153 
    154 	
    155 	if (s1 == s2)
    156 	    continue;
    157 	
    158 	divl.x = v1->x;
    159 	divl.y = v1->y;
    160 	divl.dx = v2->x - v1->x;
    161 	divl.dy = v2->y - v1->y;
    162 	s1 = P_DivlineSide (strace.x, strace.y, &divl);
    163 	s2 = P_DivlineSide (t2x, t2y, &divl);
    164 
    165 	
    166 	if (s1 == s2)
    167 	    continue;	
    168 
    169 	
    170 	
    171 	if ( !(line->flags & ML_TWOSIDED) )
    172 	    return false;
    173 	
    174 	
    175 	front = seg->frontsector;
    176 	back = seg->backsector;
    177 
    178 	
    179 	if (front->floorheight == back->floorheight
    180 	    && front->ceilingheight == back->ceilingheight)
    181 	    continue;	
    182 
    183 	
    184 	
    185 	if (front->ceilingheight < back->ceilingheight)
    186 	    opentop = front->ceilingheight;
    187 	else
    188 	    opentop = back->ceilingheight;
    189 
    190 	
    191 	if (front->floorheight > back->floorheight)
    192 	    openbottom = front->floorheight;
    193 	else
    194 	    openbottom = back->floorheight;
    195 		
    196 	
    197 	if (openbottom >= opentop)	
    198 	    return false;		
    199 	
    200 	frac = P_InterceptVector2 (&strace, &divl);
    201 		
    202 	if (front->floorheight != back->floorheight)
    203 	{
    204 	    slope = FixedDiv (openbottom - sightzstart , frac);
    205 	    if (slope > bottomslope)
    206 		bottomslope = slope;
    207 	}
    208 		
    209 	if (front->ceilingheight != back->ceilingheight)
    210 	{
    211 	    slope = FixedDiv (opentop - sightzstart , frac);
    212 	    if (slope < topslope)
    213 		topslope = slope;
    214 	}
    215 		
    216 	if (topslope <= bottomslope)
    217 	    return false;		
    218     }
    219     
    220     return true;		
    221 }
    222 
    223 
    224 
    225 
    226 
    227 
    228 
    229 
    230 boolean P_CrossBSPNode (int bspnum)
    231 {
    232     node_t*	bsp;
    233     int		side;
    234 
    235     if (bspnum & NF_SUBSECTOR)
    236     {
    237 	if (bspnum == -1)
    238 	    return P_CrossSubsector (0);
    239 	else
    240 	    return P_CrossSubsector (bspnum&(~NF_SUBSECTOR));
    241     }
    242 		
    243     bsp = &nodes[bspnum];
    244     
    245     
    246     side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp);
    247     if (side == 2)
    248 	side = 0;	
    249 
    250     
    251     if (!P_CrossBSPNode (bsp->children[side]) )
    252 	return false;
    253 	
    254     
    255     if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp))
    256     {
    257 	
    258 	return true;
    259     }
    260     
    261     
    262     return P_CrossBSPNode (bsp->children[side^1]);
    263 }
    264 
    265 
    266 
    267 
    268 
    269 
    270 
    271 
    272 boolean
    273 P_CheckSight
    274 ( mobj_t*	t1,
    275   mobj_t*	t2 )
    276 {
    277     int		s1;
    278     int		s2;
    279     int		pnum;
    280     int		bytenum;
    281     int		bitnum;
    282     
    283     
    284 
    285     
    286     s1 = (t1->subsector->sector - sectors);
    287     s2 = (t2->subsector->sector - sectors);
    288     pnum = s1*numsectors + s2;
    289     bytenum = pnum>>3;
    290     bitnum = 1 << (pnum&7);
    291 
    292     
    293     if (rejectmatrix[bytenum]&bitnum)
    294     {
    295 	sightcounts[0]++;
    296 
    297 	
    298 	return false;	
    299     }
    300 
    301     
    302     
    303     sightcounts[1]++;
    304 
    305     validcount++;
    306 	
    307     sightzstart = t1->z + t1->height - (t1->height>>2);
    308     topslope = (t2->z+t2->height) - sightzstart;
    309     bottomslope = (t2->z) - sightzstart;
    310 	
    311     strace.x = t1->x;
    312     strace.y = t1->y;
    313     t2x = t2->x;
    314     t2y = t2->y;
    315     strace.dx = t2->x - t1->x;
    316     strace.dy = t2->y - t1->y;
    317 
    318     
    319     return P_CrossBSPNode (numnodes-1);	
    320 }
    321 
    322