// ----------------------------------------------------------------------------- // Recursively apply light to segments. // If current side is a wall, apply light there. // If not a wall, apply light to child through that wall. // Notes: // It is possible to enter a segment twice by taking different paths. It is easy // to prevent this by maintaining a list of visited segments, but it is important // to reach segments with the greatest light intensity. This can be done by doing // a breadth-first-search, or by storing the applied intensity with a visited segment, // and if the current intensity is brighter, then apply the difference between it and // the previous intensity. // Note that it is also possible to visit the original light-casting segment, for example // going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not // desired, but not entirely invalid. 2 reflects some light back to 0. void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth) { int wid_result; if (intensity == 0) return; wid_result = WALL_IS_DOORWAY(segp, sidenum); if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) { int v; for (v=0; v<4; v++) // add light to this wall add_light_intensity(segp, sidenum, v, intensity); return; // we return because there is a wall here, and light does not shine through walls } // No wall here, so apply light recursively if (depth < 3) { int s; for (s=0; s<MAX_SIDES_PER_SEGMENT; s++) apply_light_intensity(&Segments[segp->children[sidenum]], s, intensity/3, depth+1); } }
// ----------------------------------------------------------------------------- // Top level recursive function for applying light. // Calls apply_light_intensity. // Uses light value on segp:sidenum (tmap_num2 defines light value) and applies // the associated intensity to segp. It calls apply_light_intensity to apply intensity/3 // to all neighbors. apply_light_intensity recursively calls itself to apply light to // subsequent neighbors (and forming loops, see above). static void propagate_light_intensity(const vmsegptr_t segp, int sidenum) { fix intensity; short texmap; intensity = 0; auto &us = segp->unique_segment::sides[sidenum]; auto &TmapInfo = LevelUniqueTmapInfoState.TmapInfo; texmap = us.tmap_num; intensity += TmapInfo[texmap].lighting; texmap = us.tmap_num2 & 0x3fff; intensity += TmapInfo[texmap].lighting; if (intensity > 0) { add_light_intensity_all_verts(us, intensity); // Now, for all sides which are not the same as sidenum (the side casting the light), // add a light value to them (if they have no children, ie, they have a wall there). for (int s=0; s<MAX_SIDES_PER_SEGMENT; s++) if (s != sidenum) apply_light_intensity(segp, s, intensity/2, 1); } }
// ----------------------------------------------------------------------------- // Top level recursive function for applying light. // Calls apply_light_intensity. // Uses light value on segp:sidenum (tmap_num2 defines light value) and applies // the associated intensity to segp. It calls apply_light_intensity to apply intensity/3 // to all neighbors. apply_light_intensity recursively calls itself to apply light to // subsequent neighbors (and forming loops, see above). void propagate_light_intensity(segment *segp, int sidenum) { int v,s; fix intensity; short texmap; intensity = 0; texmap = segp->sides[sidenum].tmap_num; intensity += TmapInfo[texmap].lighting; texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff; intensity += TmapInfo[texmap].lighting; if (intensity > 0) { for (v=0; v<4; v++) add_light_intensity(segp, sidenum, v, intensity); // Now, for all sides which are not the same as sidenum (the side casting the light), // add a light value to them (if they have no children, ie, they have a wall there). for (s=0; s<MAX_SIDES_PER_SEGMENT; s++) if (s != sidenum) apply_light_intensity(segp, s, intensity/2, 1); } }
// ----------------------------------------------------------------------------- // Recursively apply light to segments. // If current side is a wall, apply light there. // If not a wall, apply light to child through that wall. // Notes: // It is possible to enter a segment twice by taking different paths. It is easy // to prevent this by maintaining a list of visited segments, but it is important // to reach segments with the greatest light intensity. This can be done by doing // a breadth-first-search, or by storing the applied intensity with a visited segment, // and if the current intensity is brighter, then apply the difference between it and // the previous intensity. // Note that it is also possible to visit the original light-casting segment, for example // going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not // desired, but not entirely invalid. 2 reflects some light back to 0. static void apply_light_intensity(const vmsegptr_t segp, const unsigned sidenum, fix intensity, const unsigned depth) { if (intensity == 0) return; auto &Walls = LevelUniqueWallSubsystemState.Walls; auto &vcwallptr = Walls.vcptr; const auto wid_result = WALL_IS_DOORWAY(GameBitmaps, Textures, vcwallptr, segp, segp, sidenum); if (!(wid_result & WID_RENDPAST_FLAG)) { add_light_intensity_all_verts(segp->unique_segment::sides[sidenum], intensity); return; // we return because there is a wall here, and light does not shine through walls } // No wall here, so apply light recursively if (depth < 3) { intensity /= 3; if (!intensity) return; const auto &&csegp = vmsegptr(segp->children[sidenum]); for (int s=0; s<MAX_SIDES_PER_SEGMENT; s++) apply_light_intensity(csegp, s, intensity, depth+1); } }