mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-24 04:51:41 +00:00
- added handling for intra-sector lines to lighting code.
This commit is contained in:
parent
ba66c0c889
commit
87973ff504
3 changed files with 56 additions and 45 deletions
|
@ -527,20 +527,20 @@ static FLightNode * DeleteLightNode(FLightNode * node)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
double ADynamicLight::DistToSeg(const DVector3 &pos, FSectionLine *segment)
|
double ADynamicLight::DistToSeg(const DVector3 &pos, vertex_t *start, vertex_t *end)
|
||||||
{
|
{
|
||||||
double u, px, py;
|
double u, px, py;
|
||||||
|
|
||||||
double seg_dx = segment->end->fX() - segment->start->fX();
|
double seg_dx = end->fX() - start->fX();
|
||||||
double seg_dy = segment->end->fY() - segment->start->fY();
|
double seg_dy = end->fY() - start->fY();
|
||||||
double seg_length_sq = seg_dx * seg_dx + seg_dy * seg_dy;
|
double seg_length_sq = seg_dx * seg_dx + seg_dy * seg_dy;
|
||||||
|
|
||||||
u = (((pos.X - segment->start->fX()) * seg_dx) + (pos.Y - segment->start->fY()) * seg_dy) / seg_length_sq;
|
u = (((pos.X - start->fX()) * seg_dx) + (pos.Y - start->fY()) * seg_dy) / seg_length_sq;
|
||||||
if (u < 0.) u = 0.; // clamp the test point to the line segment
|
if (u < 0.) u = 0.; // clamp the test point to the line segment
|
||||||
else if (u > 1.) u = 1.;
|
else if (u > 1.) u = 1.;
|
||||||
|
|
||||||
px = segment->start->fX() + (u * seg_dx);
|
px = start->fX() + (u * seg_dx);
|
||||||
py = segment->start->fY() + (u * seg_dy);
|
py = start->fY() + (u * seg_dy);
|
||||||
|
|
||||||
px -= pos.X;
|
px -= pos.X;
|
||||||
py -= pos.Y;
|
py -= pos.Y;
|
||||||
|
@ -572,53 +572,58 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
|
||||||
bool hitonesidedback = false;
|
bool hitonesidedback = false;
|
||||||
for (unsigned i = 0; i < collected_ss.Size(); i++)
|
for (unsigned i = 0; i < collected_ss.Size(); i++)
|
||||||
{
|
{
|
||||||
|
auto &pos = collected_ss[i].pos;
|
||||||
section = collected_ss[i].sect;
|
section = collected_ss[i].sect;
|
||||||
|
|
||||||
touching_sector = AddLightNode(§ion->lighthead, section, this, touching_sector);
|
touching_sector = AddLightNode(§ion->lighthead, section, this, touching_sector);
|
||||||
|
|
||||||
|
|
||||||
|
auto processSide = [&](side_t *sidedef, vertex_t *v1, vertex_t *v2)
|
||||||
|
{
|
||||||
|
auto linedef = sidedef->linedef;
|
||||||
|
if (linedef && linedef->validcount != ::validcount)
|
||||||
|
{
|
||||||
|
// light is in front of the seg
|
||||||
|
if ((pos.Y - v1->fY()) * (v2->fX() - v1->fX()) + (v1->fX() - pos.X) * (v2->fY() - v1->fY()) <= 0)
|
||||||
|
{
|
||||||
|
linedef->validcount = ::validcount;
|
||||||
|
touching_sides = AddLightNode(&sidedef->lighthead, sidedef, this, touching_sides);
|
||||||
|
}
|
||||||
|
else if (linedef->sidedef[0] == sidedef && linedef->sidedef[1] == nullptr)
|
||||||
|
{
|
||||||
|
hitonesidedback = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (linedef)
|
||||||
|
{
|
||||||
|
FLinePortal *port = 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);
|
||||||
|
FSection *othersect = othersub->section;
|
||||||
|
if (othersect->validcount != ::validcount)
|
||||||
|
{
|
||||||
|
othersect->validcount = ::validcount;
|
||||||
|
collected_ss.Push({ othersect, PosRelative(other) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for (auto &segment : section->segments)
|
for (auto &segment : section->segments)
|
||||||
{
|
{
|
||||||
auto &pos = collected_ss[i].pos;
|
|
||||||
|
|
||||||
// check distance from x/y to seg and if within radius add this seg and, if present the opposing subsector (lather/rinse/repeat)
|
// 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 out of range we do not need to bother with this seg.
|
||||||
if (DistToSeg(pos, &segment) <= radius)
|
if (DistToSeg(pos, segment.start, segment.end) <= radius)
|
||||||
{
|
{
|
||||||
if (segment.sidedef)
|
auto sidedef = segment.sidedef;
|
||||||
|
if (sidedef)
|
||||||
{
|
{
|
||||||
auto sidedef = segment.sidedef;
|
processSide(sidedef, segment.start, segment.end);
|
||||||
auto linedef = sidedef->linedef;
|
|
||||||
if (linedef && linedef->validcount != ::validcount)
|
|
||||||
{
|
|
||||||
// light is in front of the seg
|
|
||||||
if ((pos.Y - segment.start->fY()) * (segment.end->fX() - segment.start->fX()) + (segment.start->fX() - pos.X) * (segment.end->fY() - segment.start->fY()) <= 0)
|
|
||||||
{
|
|
||||||
linedef->validcount = ::validcount;
|
|
||||||
touching_sides = AddLightNode(&sidedef->lighthead, sidedef, this, touching_sides);
|
|
||||||
}
|
|
||||||
else if (linedef->sidedef[0] == sidedef && linedef->sidedef[1] == nullptr)
|
|
||||||
{
|
|
||||||
hitonesidedback = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (linedef)
|
|
||||||
{
|
|
||||||
FLinePortal *port = 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);
|
|
||||||
FSection *othersect = othersub->section;
|
|
||||||
if (othersect->validcount != ::validcount)
|
|
||||||
{
|
|
||||||
othersect->validcount = ::validcount;
|
|
||||||
collected_ss.Push({ othersect, PosRelative(other) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto partner = segment.partner;
|
auto partner = segment.partner;
|
||||||
|
@ -633,6 +638,10 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto side : section->sides)
|
||||||
|
{
|
||||||
|
processSide(side, side->V1(), side->V2());
|
||||||
|
}
|
||||||
sector_t *sec = section->sector;
|
sector_t *sec = section->sector;
|
||||||
if (!sec->PortalBlocksSight(sector_t::ceiling))
|
if (!sec->PortalBlocksSight(sector_t::ceiling))
|
||||||
{
|
{
|
||||||
|
|
|
@ -210,7 +210,7 @@ public:
|
||||||
FLightNode * touching_sector;
|
FLightNode * touching_sector;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double DistToSeg(const DVector3 &pos, FSectionLine *seg);
|
double DistToSeg(const DVector3 &pos, vertex_t *start, vertex_t *end);
|
||||||
void CollectWithinRadius(const DVector3 &pos, FSection *section, float radius);
|
void CollectWithinRadius(const DVector3 &pos, FSection *section, float radius);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -658,7 +658,9 @@ public:
|
||||||
}
|
}
|
||||||
for (auto side : section.originalSides)
|
for (auto side : section.originalSides)
|
||||||
{
|
{
|
||||||
group.sideMap[side->Index()] = true;
|
// This is only used for attaching lights to those sidedefs which are not part of the outline.
|
||||||
|
if (side->linedef && side->linedef->sidedef[1] && side->linedef->sidedef[0]->sector == side->linedef->sidedef[1]->sector)
|
||||||
|
group.sideMap[side->Index()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numsides += group.sideMap.CountUsed();
|
numsides += group.sideMap.CountUsed();
|
||||||
|
|
Loading…
Reference in a new issue