- 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:
Christoph Oelckers 2009-01-04 15:00:29 +00:00
commit 78933df10d
21 changed files with 1892 additions and 122 deletions

View file

@ -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));
}