- added GZDoom's 3D floor physics code. This is not active yet so anything compiled from this code won't have any support for it!
SVN r1351 (trunk)
This commit is contained in:
parent
f7148b6b40
commit
78933df10d
21 changed files with 1892 additions and 122 deletions
220
src/p_sight.cpp
220
src/p_sight.cpp
|
|
@ -37,19 +37,47 @@ This uses specialized forms of the maputils routines for optimized performance
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
static TArray<intercept_t> intercepts (128);
|
||||
static divline_t trace;
|
||||
|
||||
static fixed_t sightzstart; // eye z of looker
|
||||
static fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
static int SeePastBlockEverything, SeePastShootableLines;
|
||||
|
||||
// Performance meters
|
||||
static int sightcounts[6];
|
||||
static cycle_t SightCycles;
|
||||
static cycle_t MaxSightCycles;
|
||||
|
||||
static bool P_SightTraverseIntercepts ();
|
||||
static TArray<intercept_t> intercepts (128);
|
||||
|
||||
class SightCheck
|
||||
{
|
||||
fixed_t sightzstart; // eye z of looker
|
||||
const AActor * sightthing;
|
||||
const AActor * seeingthing;
|
||||
fixed_t lastztop; // z at last line
|
||||
fixed_t lastzbottom; // z at last line
|
||||
sector_t * lastsector; // last sector being entered by trace
|
||||
fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
int SeePastBlockEverything, SeePastShootableLines;
|
||||
divline_t trace;
|
||||
int myseethrough;
|
||||
|
||||
bool PTR_SightTraverse (intercept_t *in);
|
||||
bool P_SightCheckLine (line_t *ld);
|
||||
bool P_SightBlockLinesIterator (int x, int y);
|
||||
bool P_SightTraverseIntercepts ();
|
||||
|
||||
public:
|
||||
bool P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
|
||||
|
||||
SightCheck(const AActor * t1, const AActor * t2, int flags)
|
||||
{
|
||||
lastztop = lastzbottom = sightzstart = t1->z + t1->height - (t1->height>>2);
|
||||
lastsector = t1->Sector;
|
||||
sightthing=t1;
|
||||
seeingthing=t2;
|
||||
bottomslope = t2->z - sightzstart;
|
||||
topslope = bottomslope + t2->height;
|
||||
|
||||
SeePastBlockEverything = flags & 6;
|
||||
SeePastShootableLines = flags & 4;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
==============
|
||||
|
|
@ -59,7 +87,10 @@ static bool P_SightTraverseIntercepts ();
|
|||
==============
|
||||
*/
|
||||
|
||||
/*
|
||||
static bool PTR_SightTraverse (intercept_t *in)
|
||||
*/
|
||||
bool SightCheck::PTR_SightTraverse (intercept_t *in)
|
||||
{
|
||||
line_t *li;
|
||||
fixed_t slope;
|
||||
|
|
@ -70,8 +101,9 @@ static bool PTR_SightTraverse (intercept_t *in)
|
|||
//
|
||||
// crosses a two sided line
|
||||
//
|
||||
P_LineOpening (open, NULL, li, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
fixed_t trX=trace.x + FixedMul (trace.dx, in->frac);
|
||||
fixed_t trY=trace.y + FixedMul (trace.dy, in->frac);
|
||||
P_LineOpening (open, NULL, li, trX, trY);
|
||||
|
||||
if (open.range <= 0) // quick test for totally closed doors
|
||||
return false; // stop
|
||||
|
|
@ -89,6 +121,98 @@ static bool PTR_SightTraverse (intercept_t *in)
|
|||
if (topslope <= bottomslope)
|
||||
return false; // stop
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// now handle 3D-floors
|
||||
if(li->frontsector->e->XFloor.ffloors.Size() || li->backsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
int frontflag;
|
||||
|
||||
frontflag = P_PointOnLineSide(sightthing->x, sightthing->y, li);
|
||||
|
||||
//Check 3D FLOORS!
|
||||
for(int i=1;i<=2;i++)
|
||||
{
|
||||
sector_t * s=i==1? li->frontsector:li->backsector;
|
||||
fixed_t highslope, lowslope;
|
||||
|
||||
fixed_t topz= FixedMul (topslope, in->frac) + sightzstart;
|
||||
fixed_t bottomz= FixedMul (bottomslope, in->frac) + sightzstart;
|
||||
|
||||
for(unsigned int j=0;j<s->e->XFloor.ffloors.Size();j++)
|
||||
{
|
||||
F3DFloor* rover=s->e->XFloor.ffloors[j];
|
||||
|
||||
if((rover->flags & FF_SEETHROUGH) == myseethrough || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(trX, trY);
|
||||
|
||||
highslope = FixedDiv (ff_top - sightzstart, in->frac);
|
||||
lowslope = FixedDiv (ff_bottom - sightzstart, in->frac);
|
||||
|
||||
if (highslope>=topslope)
|
||||
{
|
||||
// blocks completely
|
||||
if (lowslope<=bottomslope) return false;
|
||||
// blocks upper edge of view
|
||||
if (lowslope<topslope) topslope=lowslope;
|
||||
}
|
||||
else if (lowslope<=bottomslope)
|
||||
{
|
||||
// blocks lower edge of view
|
||||
if (highslope>bottomslope) bottomslope=highslope;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the 3D-floor is inside the viewing cone but neither clips the top nor the bottom so by
|
||||
// itself it can't be view blocking.
|
||||
// However, if there's a 3D-floor on the other side that obstructs the same vertical range
|
||||
// the 2 together will block sight.
|
||||
sector_t * sb=i==2? li->frontsector:li->backsector;
|
||||
|
||||
for(unsigned int k=0;k<sb->e->XFloor.ffloors.Size();k++)
|
||||
{
|
||||
F3DFloor* rover2=sb->e->XFloor.ffloors[k];
|
||||
|
||||
if((rover2->flags & FF_SEETHROUGH) == myseethrough || !(rover2->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ffb_bottom=rover2->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ffb_top=rover2->top.plane->ZatPoint(trX, trY);
|
||||
|
||||
if (ffb_bottom >= ff_bottom && ffb_bottom<=ff_top ||
|
||||
ffb_top <= ff_top && ffb_top >= ff_bottom ||
|
||||
ffb_top >= ff_top && ffb_bottom <= ff_bottom ||
|
||||
ffb_top <= ff_top && ffb_bottom >= ff_bottom)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// trace is leaving a sector with a 3d-floor
|
||||
if (s==lastsector && frontflag==i-1)
|
||||
{
|
||||
// upper slope intersects with this 3d-floor
|
||||
if (lastztop<=ff_bottom && topz>ff_top)
|
||||
{
|
||||
topslope=lowslope;
|
||||
}
|
||||
// lower slope intersects with this 3d-floor
|
||||
if (lastzbottom>=ff_top && bottomz<ff_top)
|
||||
{
|
||||
bottomslope=highslope;
|
||||
}
|
||||
}
|
||||
if (topslope <= bottomslope) return false; // stop
|
||||
}
|
||||
}
|
||||
lastsector = frontflag==0 ? li->backsector : li->frontsector;
|
||||
}
|
||||
else lastsector=NULL; // don't need it if there are no 3D-floors
|
||||
|
||||
lastztop= FixedMul (topslope, in->frac) + sightzstart;
|
||||
lastzbottom= FixedMul (bottomslope, in->frac) + sightzstart;
|
||||
#endif
|
||||
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +226,7 @@ static bool PTR_SightTraverse (intercept_t *in)
|
|||
===================
|
||||
*/
|
||||
|
||||
static bool P_SightCheckLine (line_t *ld)
|
||||
bool SightCheck::P_SightCheckLine (line_t *ld)
|
||||
{
|
||||
divline_t dl;
|
||||
|
||||
|
|
@ -123,7 +247,7 @@ static bool P_SightCheckLine (line_t *ld)
|
|||
return true; // line isn't crossed
|
||||
}
|
||||
|
||||
// try to early out the check
|
||||
// try to early out the check
|
||||
if (!ld->backsector || !(ld->flags & ML_TWOSIDED))
|
||||
return false; // stop checking
|
||||
|
||||
|
|
@ -156,7 +280,7 @@ static bool P_SightCheckLine (line_t *ld)
|
|||
}
|
||||
|
||||
sightcounts[3]++;
|
||||
// store the line for later intersection testing
|
||||
// store the line for later intersection testing
|
||||
intercept_t newintercept;
|
||||
newintercept.isaline = true;
|
||||
newintercept.d.line = ld;
|
||||
|
|
@ -173,7 +297,7 @@ static bool P_SightCheckLine (line_t *ld)
|
|||
===================
|
||||
*/
|
||||
|
||||
static bool P_SightBlockLinesIterator (int x, int y)
|
||||
bool SightCheck::P_SightBlockLinesIterator (int x, int y)
|
||||
{
|
||||
int offset;
|
||||
int *list;
|
||||
|
|
@ -222,12 +346,12 @@ static bool P_SightBlockLinesIterator (int x, int y)
|
|||
====================
|
||||
*/
|
||||
|
||||
static bool P_SightTraverseIntercepts ()
|
||||
bool SightCheck::P_SightTraverseIntercepts ()
|
||||
{
|
||||
size_t count;
|
||||
unsigned count;
|
||||
fixed_t dist;
|
||||
intercept_t *scan, *in;
|
||||
unsigned int scanpos;
|
||||
unsigned scanpos;
|
||||
divline_t dl;
|
||||
|
||||
count = intercepts.Size ();
|
||||
|
|
@ -269,6 +393,29 @@ static bool P_SightTraverseIntercepts ()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
if (lastsector==seeingthing->Sector && lastsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
// we must do one last check whether the trace has crossed a 3D floor in the last sector
|
||||
|
||||
fixed_t topz= topslope + sightzstart;
|
||||
fixed_t bottomz= bottomslope + sightzstart;
|
||||
|
||||
for(unsigned int i=0;i<lastsector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover = lastsector->e->XFloor.ffloors[i];
|
||||
|
||||
if((rover->flags & FF_SOLID) == myseethrough || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(seeingthing->x, seeingthing->y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(seeingthing->x, seeingthing->y);
|
||||
|
||||
if (lastztop<=ff_bottom && topz>ff_bottom && lastzbottom<=ff_bottom && bottomz>ff_bottom) return false;
|
||||
if (lastzbottom>=ff_top && bottomz<ff_top && lastztop>=ff_top && topz<ff_top) return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
return true; // everything was traversed
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +431,7 @@ static bool P_SightTraverseIntercepts ()
|
|||
==================
|
||||
*/
|
||||
|
||||
static bool P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
bool SightCheck::P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
{
|
||||
fixed_t xt1,yt1,xt2,yt2;
|
||||
fixed_t xstep,ystep;
|
||||
|
|
@ -296,6 +443,27 @@ static bool P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
|||
validcount++;
|
||||
intercepts.Clear ();
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// for FF_SEETHROUGH the following rule applies:
|
||||
// If the viewer is in an area without FF_SEETHROUGH he can only see into areas without this flag
|
||||
// If the viewer is in an area with FF_SEETHROUGH he can only see into areas with this flag
|
||||
for(unsigned int i=0;i<lastsector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover = lastsector->e->XFloor.ffloors[i];
|
||||
|
||||
if(!(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(sightthing->x, sightthing->y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(sightthing->x, sightthing->y);
|
||||
|
||||
if (sightzstart < ff_top && sightzstart >= ff_bottom)
|
||||
{
|
||||
myseethrough = rover->flags & FF_SEETHROUGH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
|
||||
|
|
@ -535,16 +703,10 @@ sightcounts[0]++;
|
|||
// Now look from eyes of t1 to any part of t2.
|
||||
|
||||
validcount++;
|
||||
|
||||
sightzstart = t1->z + t1->height - (t1->height>>2);
|
||||
bottomslope = t2->z - sightzstart;
|
||||
topslope = bottomslope + t2->height;
|
||||
|
||||
SeePastBlockEverything = flags & 6;
|
||||
SeePastShootableLines = flags & 4;
|
||||
res = P_SightPathTraverse (t1->x, t1->y, t2->x, t2->y);
|
||||
SeePastBlockEverything = 0;
|
||||
SeePastShootableLines = 0;
|
||||
{
|
||||
SightCheck s(t1, t2, flags);
|
||||
res = s.P_SightPathTraverse (t1->x, t1->y, t2->x, t2->y);
|
||||
}
|
||||
|
||||
done:
|
||||
SightCycles.Unclock();
|
||||
|
|
@ -573,3 +735,5 @@ void P_ResetSightCounters (bool full)
|
|||
SightCycles.Reset();
|
||||
memset (sightcounts, 0, sizeof(sightcounts));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue