diff --git a/src/g_shared/a_dynlight.cpp b/src/g_shared/a_dynlight.cpp index e8dc871bf1..8f5c3ec1a0 100644 --- a/src/g_shared/a_dynlight.cpp +++ b/src/g_shared/a_dynlight.cpp @@ -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 seg_dx = segment->end->fX() - segment->start->fX(); - double seg_dy = segment->end->fY() - segment->start->fY(); + double seg_dx = end->fX() - start->fX(); + double seg_dy = end->fY() - start->fY(); 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 else if (u > 1.) u = 1.; - px = segment->start->fX() + (u * seg_dx); - py = segment->start->fY() + (u * seg_dy); + px = start->fX() + (u * seg_dx); + py = start->fY() + (u * seg_dy); px -= pos.X; py -= pos.Y; @@ -572,53 +572,58 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, bool hitonesidedback = false; for (unsigned i = 0; i < collected_ss.Size(); i++) { + auto &pos = collected_ss[i].pos; section = collected_ss[i].sect; 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) { - 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) // 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; - 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) }); - } - } - } - } + processSide(sidedef, segment.start, segment.end); } 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; if (!sec->PortalBlocksSight(sector_t::ceiling)) { diff --git a/src/g_shared/a_dynlight.h b/src/g_shared/a_dynlight.h index d28b787b1b..369b826e31 100644 --- a/src/g_shared/a_dynlight.h +++ b/src/g_shared/a_dynlight.h @@ -210,7 +210,7 @@ public: FLightNode * touching_sector; 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); protected: diff --git a/src/hwrenderer/data/hw_sections.cpp b/src/hwrenderer/data/hw_sections.cpp index c43a22eeb3..3ef6502c6a 100644 --- a/src/hwrenderer/data/hw_sections.cpp +++ b/src/hwrenderer/data/hw_sections.cpp @@ -658,7 +658,9 @@ public: } 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();