This commit is contained in:
Rachael Alexanderson 2016-12-08 07:47:33 -05:00
commit dc07c2075f
6 changed files with 96 additions and 72 deletions

View file

@ -582,81 +582,107 @@ double ADynamicLight::DistToSeg(const DVector3 &pos, seg_t *seg)
// to sidedefs and sector parts. // to sidedefs and sector parts.
// //
//========================================================================== //==========================================================================
struct LightLinkEntry
{
subsector_t *sub;
DVector3 pos;
};
static TArray<LightLinkEntry> collected_ss;
void ADynamicLight::CollectWithinRadius(const DVector3 &pos, subsector_t *subSec, float radius) void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSec, float radius)
{ {
if (!subSec) return; if (!subSec) return;
collected_ss.Clear();
collected_ss.Push({ subSec, opos });
subSec->validcount = ::validcount; subSec->validcount = ::validcount;
touching_subsectors = AddLightNode(&subSec->lighthead, subSec, this, touching_subsectors); for (unsigned i = 0; i < collected_ss.Size(); i++)
if (subSec->sector->validcount != ::validcount)
{ {
touching_sector = AddLightNode(&subSec->render_sector->lighthead, subSec->sector, this, touching_sector); subSec = collected_ss[i].sub;
subSec->sector->validcount = ::validcount; auto &pos = collected_ss[i].pos;
}
for (unsigned int i = 0; i < subSec->numlines; i++) touching_subsectors = AddLightNode(&subSec->lighthead, subSec, this, touching_subsectors);
{ if (subSec->sector->validcount != ::validcount)
seg_t * seg = subSec->firstline + i;
// check distance from x/y to seg and if within radius add this seg and, if present the opposing subsector (lather/rinse/repeat)
// If out of range we do not need to bother with this seg.
if (DistToSeg(pos, seg) <= radius)
{ {
if (seg->sidedef && seg->linedef && seg->linedef->validcount != ::validcount) touching_sector = AddLightNode(&subSec->render_sector->lighthead, subSec->sector, this, touching_sector);
subSec->sector->validcount = ::validcount;
}
for (unsigned int i = 0; i < subSec->numlines; i++)
{
seg_t * seg = subSec->firstline + i;
// check distance from x/y to seg and if within radius add this seg and, if present the opposing subsector (lather/rinse/repeat)
// If out of range we do not need to bother with this seg.
if (DistToSeg(pos, seg) <= radius)
{ {
// light is in front of the seg if (seg->sidedef && seg->linedef && seg->linedef->validcount != ::validcount)
if ((pos.Y - seg->v1->fY()) * (seg->v2->fX() - seg->v1->fX()) + (seg->v1->fX() - pos.X) * (seg->v2->fY() - seg->v1->fY()) <= 0)
{ {
seg->linedef->validcount = validcount; // light is in front of the seg
touching_sides = AddLightNode(&seg->sidedef->lighthead, seg->sidedef, this, touching_sides); if ((pos.Y - seg->v1->fY()) * (seg->v2->fX() - seg->v1->fX()) + (seg->v1->fX() - pos.X) * (seg->v2->fY() - seg->v1->fY()) <= 0)
}
}
if (seg->linedef)
{
FLinePortal *port = seg->linedef->getPortal();
if (port && port->mType == PORTT_LINKED)
{
line_t *other = port->mDestination;
if (other->validcount != ::validcount)
{ {
subsector_t *othersub = R_PointInSubsector(other->v1->fPos() + other->Delta() / 2); seg->linedef->validcount = validcount;
if (othersub->validcount != ::validcount) CollectWithinRadius(PosRelative(other), othersub, radius); touching_sides = AddLightNode(&seg->sidedef->lighthead, seg->sidedef, this, touching_sides);
}
}
if (seg->linedef)
{
FLinePortal *port = seg->linedef->getPortal();
if (port && port->mType == PORTT_LINKED)
{
line_t *other = port->mDestination;
if (other->validcount != ::validcount)
{
subsector_t *othersub = R_PointInSubsector(other->v1->fPos() + other->Delta() / 2);
if (othersub->validcount != ::validcount)
{
othersub->validcount = ::validcount;
collected_ss.Push({ othersub, PosRelative(other) });
}
}
}
}
seg_t *partner = seg->PartnerSeg;
if (partner)
{
subsector_t *sub = partner->Subsector;
if (sub != NULL && sub->validcount != ::validcount)
{
sub->validcount = ::validcount;
collected_ss.Push({ sub, pos });
} }
} }
} }
}
seg_t *partner = seg->PartnerSeg; sector_t *sec = subSec->sector;
if (partner) if (!sec->PortalBlocksSight(sector_t::ceiling))
{
line_t *other = subSec->firstline->linedef;
if (sec->GetPortalPlaneZ(sector_t::ceiling) < Z() + radius)
{ {
subsector_t *sub = partner->Subsector; DVector2 refpos = other->v1->fPos() + other->Delta() / 2 + sec->GetPortalDisplacement(sector_t::ceiling);
if (sub != NULL && sub->validcount != ::validcount) subsector_t *othersub = R_PointInSubsector(refpos);
if (othersub->validcount != ::validcount)
{ {
CollectWithinRadius(pos, sub, radius); othersub->validcount = ::validcount;
collected_ss.Push({ othersub, PosRelative(othersub->sector) });
} }
} }
} }
} if (!sec->PortalBlocksSight(sector_t::floor))
sector_t *sec = subSec->sector;
if (!sec->PortalBlocksSight(sector_t::ceiling))
{
line_t *other = subSec->firstline->linedef;
if (sec->GetPortalPlaneZ(sector_t::ceiling) < Z() + radius)
{ {
DVector2 refpos = other->v1->fPos() + other->Delta() / 2 + sec->GetPortalDisplacement(sector_t::ceiling); line_t *other = subSec->firstline->linedef;
subsector_t *othersub = R_PointInSubsector(refpos); if (sec->GetPortalPlaneZ(sector_t::floor) > Z() - radius)
if (othersub->validcount != ::validcount) CollectWithinRadius(PosRelative(othersub->sector), othersub, radius); {
} DVector2 refpos = other->v1->fPos() + other->Delta() / 2 + sec->GetPortalDisplacement(sector_t::floor);
} subsector_t *othersub = R_PointInSubsector(refpos);
if (!sec->PortalBlocksSight(sector_t::floor)) if (othersub->validcount != ::validcount)
{ {
line_t *other = subSec->firstline->linedef; othersub->validcount = ::validcount;
if (sec->GetPortalPlaneZ(sector_t::floor) > Z() - radius) collected_ss.Push({ othersub, PosRelative(othersub->sector) });
{ }
DVector2 refpos = other->v1->fPos() + other->Delta() / 2 + sec->GetPortalDisplacement(sector_t::floor); }
subsector_t *othersub = R_PointInSubsector(refpos);
if (othersub->validcount != ::validcount) CollectWithinRadius(PosRelative(othersub->sector), othersub, radius);
} }
} }
} }

View file

@ -102,9 +102,10 @@ void GLWall::SetupLights()
Vector fn, pos; Vector fn, pos;
float x = node->lightsource->X(); DVector3 posrel = node->lightsource->PosRelative(seg->frontsector);
float y = node->lightsource->Y(); float x = posrel.X;
float z = node->lightsource->Z(); float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y)); float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius(); float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist); float scale = 1.0f / ((2.f * radius) - dist);

View file

@ -869,12 +869,6 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz) if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz)
{ {
// Actor is stepping through a portal. // Actor is stepping through a portal.
/*
tm.floorz = portz;
tm.floorsector = oppsec;
tm.floorpic = cres.line->sidedef[0]->GetTexture(side_t::mid);
tm.floorterrain = 0;
*/
tm.portalstep = true; tm.portalstep = true;
return true; return true;
} }
@ -2150,7 +2144,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
goto pushline; goto pushline;
} }
else if (BlockingMobj->Top() - thing->Z() > thing->MaxStepHeight else if (BlockingMobj->Top() - thing->Z() > thing->MaxStepHeight
|| (BlockingMobj->Sector->ceilingplane.ZatPoint(pos) - (BlockingMobj->Top()) < thing->Height) || ((BlockingMobj->Sector->ceilingplane.ZatPoint(pos) - (BlockingMobj->Top()) < thing->Height) && BlockingMobj->Sector->PortalBlocksMovement(sector_t::ceiling))
|| (tm.ceilingz - (BlockingMobj->Top()) < thing->Height)) || (tm.ceilingz - (BlockingMobj->Top()) < thing->Height))
{ {
goto pushline; goto pushline;

View file

@ -716,6 +716,7 @@ bool SightCheck::P_SightPathTraverse ()
// step through map blocks // step through map blocks
// Count is present to prevent a round off error from skipping the break // Count is present to prevent a round off error from skipping the break
int itres;
for (count = 0 ; count < 1000 ; count++) for (count = 0 ; count < 1000 ; count++)
{ {
// end traversing when reaching the end of the blockmap // end traversing when reaching the end of the blockmap
@ -724,15 +725,15 @@ bool SightCheck::P_SightPathTraverse ()
{ {
break; break;
} }
int res = P_SightBlockLinesIterator(mapx, mapy); itres = P_SightBlockLinesIterator(mapx, mapy);
if (res == 0) if (itres == 0)
{ {
sightcounts[1]++; sightcounts[1]++;
return false; // early out return false; // early out
} }
// either reached the end or had an early-out condition with portals left to check, // either reached the end or had an early-out condition with portals left to check,
if (res == -1 || (mapxstep | mapystep) == 0) if (itres == -1 || (mapxstep | mapystep) == 0)
break; break;
switch (((xs_FloorToInt(yintercept) == mapy) << 1) | (xs_FloorToInt(xintercept) == mapx)) switch (((xs_FloorToInt(yintercept) == mapy) << 1) | (xs_FloorToInt(xintercept) == mapx))
@ -787,7 +788,9 @@ sightcounts[1]++;
// //
sightcounts[2]++; sightcounts[2]++;
return P_SightTraverseIntercepts ( ); bool traverseres = P_SightTraverseIntercepts ( );
if (itres == -1) return false; // if the iterator had an early out there was no line of sight. The traverser was only called to collect more portals.
return traverseres;
} }
/* /*

View file

@ -57,7 +57,7 @@ CLERW0, 37, 53, iwad
CLERX0, 37, 43, iwad CLERX0, 37, 43, iwad
CLERY0, 38, 30, iwad CLERY0, 38, 30, iwad
CLERZ0, 38, 18, iwad CLERZ0, 38, 18, iwad
CLER[0, 38, 12, iwad "CLER[0", 38, 12, iwad
CPB1A0, 8, 7, iwad CPB1A0, 8, 7, iwad
CPB2A0, 7, 6, iwad CPB2A0, 7, 6, iwad
CPB3A0, 12, 4, iwad CPB3A0, 12, 4, iwad

View file

@ -200,8 +200,8 @@ PGRDW0, 35, 28, iwad
PGRDX0, 35, 28, iwad PGRDX0, 35, 28, iwad
PGRDY0, 35, 28, iwad PGRDY0, 35, 28, iwad
PGRDZ0, 35, 28, iwad PGRDZ0, 35, 28, iwad
PGRD[0, 35, 28, iwad "PGRD[0", 35, 28, iwad
PGRD\0, 35, 28, iwad "PGRD\0", 35, 28, iwad
PDEDE0, 22, 20, iwad PDEDE0, 22, 20, iwad
PDEDF0, 23, 16, iwad PDEDF0, 23, 16, iwad
PDEDG0, 23, 15, iwad PDEDG0, 23, 15, iwad