/** * Same as @ref R_OpenRange() but works with the "visual" (i.e., smoothed) plane * height coordinates rather than the "sharp" coordinates. * * @param side Line side to find the open range for. * * Return values: * @param bottom Bottom Z height is written here. Can be @c 0. * @param top Top Z height is written here. Can be @c 0. * * @return Height of the open range. * * @todo fixme: Should use the visual plane heights of sector clusters. */ static coord_t visOpenRange(LineSide const &side, coord_t *retBottom = 0, coord_t *retTop = 0) { Sector const *frontSec = side.sectorPtr(); Sector const *backSec = side.back().sectorPtr(); coord_t bottom; if(backSec && backSec->floor().heightSmoothed() > frontSec->floor().heightSmoothed()) { bottom = backSec->floor().heightSmoothed(); } else { bottom = frontSec->floor().heightSmoothed(); } coord_t top; if(backSec && backSec->ceiling().heightSmoothed() < frontSec->ceiling().heightSmoothed()) { top = backSec->ceiling().heightSmoothed(); } else { top = frontSec->ceiling().heightSmoothed(); } if(retBottom) *retBottom = bottom; if(retTop) *retTop = top; return top - bottom; }
/// @todo fixme: Should use the visual plane heights of sector clusters. static bool middleMaterialCoversOpening(LineSide const &side) { if(!side.hasSector()) return false; // Never. if(!side.hasSections()) return false; if(!side.middle().hasMaterial()) return false; MaterialAnimator &matAnimator = side.middle().material().getAnimator(Rend_MapSurfaceMaterialSpec()); // Ensure we have up to date info about the material. matAnimator.prepare(); // Might the material cover the opening? if(matAnimator.isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1) { // Stretched middles always cover the opening. if(side.isFlagged(SDF_MIDDLE_STRETCH)) return true; Sector const &frontSec = side.sector(); Sector const *backSec = side.back().sectorPtr(); // Determine the opening between the visual sector planes at this edge. coord_t openBottom; if(backSec && backSec->floor().heightSmoothed() > frontSec.floor().heightSmoothed()) { openBottom = backSec->floor().heightSmoothed(); } else { openBottom = frontSec.floor().heightSmoothed(); } coord_t openTop; if(backSec && backSec->ceiling().heightSmoothed() < frontSec.ceiling().heightSmoothed()) { openTop = backSec->ceiling().heightSmoothed(); } else { openTop = frontSec.ceiling().heightSmoothed(); } if(matAnimator.dimensions().y >= openTop - openBottom) { // Possibly; check the placement. if(side.leftHEdge()) // possibility of degenerate BSP leaf { WallEdge edge(WallSpec::fromMapSide(side, LineSide::Middle), *side.leftHEdge(), Line::From); return (edge.isValid() && edge.top().z() > edge.bottom().z() && edge.top().z() >= openTop && edge.bottom().z() <= openBottom); } } } return false; }
/** * Should angle based light level deltas be applied? */ static bool useWallSectionLightLevelDeltas(LineSide const &side, int section) { // Disabled? if(rendLightWallAngle <= 0) return false; // Never if the surface's material was chosen as a HOM fix (lighting must // be consistent with that applied to the relative back sector plane). if(side.surface(section).hasFixMaterial() && side.hasSector() && side.back().hasSector()) { Sector &backSector = side.back().sector(); if(backSector.floor().height() < backSector.ceiling().height()) return false; } return true; }
/// @todo fixme: Should use the visual plane heights of sector clusters. bool R_SideBackClosed(LineSide const &side, bool ignoreOpacity) { if(!side.hasSections()) return false; if(!side.hasSector()) return false; if(side.line().isSelfReferencing()) return false; // Never. if(side.considerOneSided()) return true; Sector const &frontSec = side.sector(); Sector const &backSec = side.back().sector(); if(backSec.floor().heightSmoothed() >= backSec.ceiling().heightSmoothed()) return true; if(backSec.ceiling().heightSmoothed() <= frontSec.floor().heightSmoothed()) return true; if(backSec.floor().heightSmoothed() >= frontSec.ceiling().heightSmoothed()) return true; // Perhaps a middle material completely covers the opening? if(side.middle().hasMaterial()) { MaterialAnimator &matAnimator = side.middle().material().getAnimator(Rend_MapSurfaceMaterialSpec()); // Ensure we have up to date info about the material. matAnimator.prepare(); if(ignoreOpacity || (matAnimator.isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1)) { // Stretched middles always cover the opening. if(side.isFlagged(SDF_MIDDLE_STRETCH)) return true; if(side.leftHEdge()) // possibility of degenerate BSP leaf { coord_t openRange, openBottom, openTop; openRange = visOpenRange(side, &openBottom, &openTop); if(matAnimator.dimensions().y >= openRange) { // Possibly; check the placement. WallEdge edge(WallSpec::fromMapSide(side, LineSide::Middle), *side.leftHEdge(), Line::From); return (edge.isValid() && edge.top().z() > edge.bottom().z() && edge.top().z() >= openTop && edge.bottom().z() <= openBottom); } } } } return false; }