sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) { // [RH] allow per-plane lighting if (floorlightlevel != NULL) { *floorlightlevel = sec->floorlightsec == NULL ? sec->lightlevel : sec->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = sec->ceilinglightsec == NULL ? // killough 4/11/98 sec->lightlevel : sec->ceilinglightsec->lightlevel; } FakeSide = FAKED_Center; if (!sec->heightsec || sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) return sec; if (!camera || !camera->subsector || !camera->subsector->sector) return sec; const sector_t* s = sec->heightsec; sector_t *heightsec = camera->subsector->sector->heightsec; bool underwater = r_fakingunderwater || (heightsec && viewz <= P_FloorHeight(viewx, viewy, heightsec)); bool doorunderwater = false; int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES); // Replace sector being drawn with a copy to be hacked *tempsec = *sec; // Replace floor and ceiling height with control sector's heights. if (diffTex) { if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane)) tempsec->floorpic = s->floorpic; else if (s->MoreFlags & SECF_FAKEFLOORONLY) { if (underwater) { tempsec->colormap = s->colormap; if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = s->floorlightsec == NULL ? s->lightlevel : s->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = s->ceilinglightsec == NULL ? s->lightlevel : s->ceilinglightsec->lightlevel; } } FakeSide = FAKED_BelowFloor; return tempsec; } return sec; } } else { tempsec->floorplane = s->floorplane; } if (!(s->MoreFlags & SECF_FAKEFLOORONLY)) { if (diffTex) { if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane)) tempsec->ceilingpic = s->ceilingpic; } else { tempsec->ceilingplane = s->ceilingplane; } } fixed_t refceilz = P_CeilingHeight(viewx, viewy, s); fixed_t orgceilz = P_CeilingHeight(viewx, viewy, sec); // [RH] Allow viewing underwater areas through doors/windows that // are underwater but not in a water sector themselves. // Only works if you cannot see the top surface of any deep water // sectors at the same time. if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL) { fixed_t fcz1 = P_CeilingHeight(curline->v1->x, curline->v1->y, frontsector); fixed_t fcz2 = P_CeilingHeight(curline->v2->x, curline->v2->y, frontsector); if (fcz1 <= P_FloorHeight(curline->v1->x, curline->v1->y, s) && fcz2 <= P_FloorHeight(curline->v2->x, curline->v2->y, s)) { // will any columns of this window be visible or will they be blocked // by 1s lines and closed doors? if (memchr(solidcol + rw_start, 0, rw_stop - rw_start + 1) != NULL) { doorunderwater = true; r_fakingunderwater = true; } } } if (underwater || doorunderwater) { tempsec->floorplane = sec->floorplane; tempsec->ceilingplane = s->floorplane; P_InvertPlane(&tempsec->ceilingplane); P_ChangeCeilingHeight(tempsec, -1); tempsec->colormap = s->colormap; } // killough 11/98: prevent sudden light changes from non-water sectors: if ((underwater && !back) || doorunderwater) { // head-below-floor hack tempsec->floorpic = diffTex ? sec->floorpic : s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_xscale = s->floor_xscale; tempsec->floor_yscale = s->floor_yscale; tempsec->floor_angle = s->floor_angle; tempsec->base_floor_angle = s->base_floor_angle; tempsec->base_floor_yoffs = s->base_floor_yoffs; tempsec->ceilingplane = s->floorplane; P_InvertPlane(&tempsec->ceilingplane); P_ChangeCeilingHeight(tempsec, -1); if (s->ceilingpic == skyflatnum) { tempsec->floorplane = tempsec->ceilingplane; P_InvertPlane(&tempsec->floorplane); P_ChangeFloorHeight(tempsec, +1); tempsec->ceilingpic = tempsec->floorpic; tempsec->ceiling_xoffs = tempsec->floor_xoffs; tempsec->ceiling_yoffs = tempsec->floor_yoffs; tempsec->ceiling_xscale = tempsec->floor_xscale; tempsec->ceiling_yscale = tempsec->floor_yscale; tempsec->ceiling_angle = tempsec->floor_angle; tempsec->base_ceiling_angle = tempsec->base_floor_angle; tempsec->base_ceiling_yoffs = tempsec->base_floor_yoffs; } else { tempsec->ceilingpic = diffTex ? s->floorpic : s->ceilingpic; tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceiling_xscale = s->ceiling_xscale; tempsec->ceiling_yscale = s->ceiling_yscale; tempsec->ceiling_angle = s->ceiling_angle; tempsec->base_ceiling_angle = s->base_ceiling_angle; tempsec->base_ceiling_yoffs = s->base_ceiling_yoffs; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = s->floorlightsec == NULL ? s->lightlevel : s->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = s->ceilinglightsec == NULL ? s->lightlevel : s->ceilinglightsec->lightlevel; } } FakeSide = FAKED_BelowFloor; } else if (heightsec && viewz >= P_CeilingHeight(viewx, viewy, heightsec) && orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY)) { // Above-ceiling hack tempsec->ceilingplane = s->ceilingplane; tempsec->floorplane = s->ceilingplane; P_InvertPlane(&tempsec->floorplane); P_ChangeFloorHeight(tempsec, +1); tempsec->colormap = s->colormap; tempsec->ceilingpic = diffTex ? sec->ceilingpic : s->ceilingpic; tempsec->floorpic = s->ceilingpic; tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floor_xscale = tempsec->ceiling_xscale = s->ceiling_xscale; tempsec->floor_yscale = tempsec->ceiling_yscale = s->ceiling_yscale; tempsec->floor_angle = tempsec->ceiling_angle = s->ceiling_angle; tempsec->base_floor_angle = tempsec->base_ceiling_angle = s->base_ceiling_angle; tempsec->base_floor_yoffs = tempsec->base_ceiling_yoffs = s->base_ceiling_yoffs; if (s->floorpic != skyflatnum) { tempsec->ceilingplane = sec->ceilingplane; tempsec->floorpic = s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_xscale = s->floor_xscale; tempsec->floor_yscale = s->floor_yscale; tempsec->floor_angle = s->floor_angle; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = s->floorlightsec == NULL ? s->lightlevel : s->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = s->ceilinglightsec == NULL ? s->lightlevel : s->ceilinglightsec->lightlevel; } } FakeSide = FAKED_AboveCeiling; } sec = tempsec; // Use other sector return sec; }
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) { // [RH] allow per-plane lighting if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (sec); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (sec); } FakeSide = FAKED_Center; const sector_t *s = sec->GetHeightSec(); if (s != NULL) { sector_t *heightsec = viewsector->heightsec; bool underwater = r_fakingunderwater || (heightsec && viewz <= heightsec->floorplane.ZatPoint (viewx, viewy)); bool doorunderwater = false; int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES); // Replace sector being drawn with a copy to be hacked *tempsec = *sec; // Replace floor and ceiling height with control sector's heights. if (diffTex) { if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane)) { tempsec->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); } else if (s->MoreFlags & SECF_FAKEFLOORONLY) { if (underwater) { tempsec->ColorMap = s->ColorMap; if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (s); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (s); } } FakeSide = FAKED_BelowFloor; return tempsec; } return sec; } } else { tempsec->floorplane = s->floorplane; } if (!(s->MoreFlags & SECF_FAKEFLOORONLY)) { if (diffTex) { if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane)) { tempsec->SetTexture(sector_t::ceiling, s->GetTexture(sector_t::ceiling), false); } } else { tempsec->ceilingplane = s->ceilingplane; } } // fixed_t refflorz = s->floorplane.ZatPoint (viewx, viewy); fixed_t refceilz = s->ceilingplane.ZatPoint (viewx, viewy); // fixed_t orgflorz = sec->floorplane.ZatPoint (viewx, viewy); fixed_t orgceilz = sec->ceilingplane.ZatPoint (viewx, viewy); #if 1 // [RH] Allow viewing underwater areas through doors/windows that // are underwater but not in a water sector themselves. // Only works if you cannot see the top surface of any deep water // sectors at the same time. if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL) { if (rw_frontcz1 <= s->floorplane.ZatPoint (curline->v1->x, curline->v1->y) && rw_frontcz2 <= s->floorplane.ZatPoint (curline->v2->x, curline->v2->y)) { // Check that the window is actually visible for (int z = WallSX1; z < WallSX2; ++z) { if (floorclip[z] > ceilingclip[z]) { doorunderwater = true; r_fakingunderwater = true; break; } } } } #endif if (underwater || doorunderwater) { tempsec->floorplane = sec->floorplane; tempsec->ceilingplane = s->floorplane; tempsec->ceilingplane.FlipVert (); tempsec->ceilingplane.ChangeHeight (-1); tempsec->ColorMap = s->ColorMap; } // killough 11/98: prevent sudden light changes from non-water sectors: if ((underwater && !back) || doorunderwater) { // head-below-floor hack tempsec->SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false); tempsec->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform; tempsec->ceilingplane = s->floorplane; tempsec->ceilingplane.FlipVert (); tempsec->ceilingplane.ChangeHeight (-1); if (s->GetTexture(sector_t::ceiling) == skyflatnum) { tempsec->floorplane = tempsec->ceilingplane; tempsec->floorplane.FlipVert (); tempsec->floorplane.ChangeHeight (+1); tempsec->SetTexture(sector_t::ceiling, tempsec->GetTexture(sector_t::floor), false); tempsec->planes[sector_t::ceiling].xform = tempsec->planes[sector_t::floor].xform; } else { tempsec->SetTexture(sector_t::ceiling, diffTex ? s->GetTexture(sector_t::floor) : s->GetTexture(sector_t::ceiling), false); tempsec->planes[sector_t::ceiling].xform = s->planes[sector_t::ceiling].xform; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (s); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (s); } } FakeSide = FAKED_BelowFloor; } else if (heightsec && viewz >= heightsec->ceilingplane.ZatPoint (viewx, viewy) && orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY)) { // Above-ceiling hack tempsec->ceilingplane = s->ceilingplane; tempsec->floorplane = s->ceilingplane; tempsec->floorplane.FlipVert (); tempsec->floorplane.ChangeHeight (+1); tempsec->ColorMap = s->ColorMap; tempsec->ColorMap = s->ColorMap; tempsec->SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false); tempsec->SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false); tempsec->planes[sector_t::ceiling].xform = tempsec->planes[sector_t::floor].xform = s->planes[sector_t::ceiling].xform; if (s->GetTexture(sector_t::floor) != skyflatnum) { tempsec->ceilingplane = sec->ceilingplane; tempsec->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); tempsec->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (s); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (s); } } FakeSide = FAKED_AboveCeiling; } sec = tempsec; // Use other sector } return sec; }
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) { // [ZDoomGL] - convenience, so you don't have to check for NULL before calling function if (!sec) { return NULL; } // [RH] allow per-plane lighting if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (sec); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (sec); } FakeSide = FAKED_Center; if (sec->heightsec && !(sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)) { const sector_t *s = sec->heightsec; sector_t *heightsec = viewsector->heightsec; bool underwater = r_fakingunderwater || (heightsec && viewz <= heightsec->floorplane.ZatPoint (viewx, viewy)); bool doorunderwater = false; int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES); // Replace sector being drawn with a copy to be hacked *tempsec = *sec; // Replace floor and ceiling height with control sector's heights. if (diffTex) { if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane)) { tempsec->floorpic = s->floorpic; } else if (s->MoreFlags & SECF_FAKEFLOORONLY) { if (underwater) { tempsec->ColorMap = s->ColorMap; if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (s); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (s); } } FakeSide = FAKED_BelowFloor; return tempsec; } return sec; } } else { tempsec->floorplane = s->floorplane; } if (!(s->MoreFlags & SECF_FAKEFLOORONLY)) { if (diffTex) { if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane)) { tempsec->ceilingpic = s->ceilingpic; } } else { tempsec->ceilingplane = s->ceilingplane; } } // fixed_t refflorz = s->floorplane.ZatPoint (viewx, viewy); fixed_t refceilz = s->ceilingplane.ZatPoint (viewx, viewy); // fixed_t orgflorz = sec->floorplane.ZatPoint (viewx, viewy); fixed_t orgceilz = sec->ceilingplane.ZatPoint (viewx, viewy); #if 1 if ( OPENGL_GetCurrentRenderer( ) == RENDERER_SOFTWARE ) { // [RH] Allow viewing underwater areas through doors/windows that // are underwater but not in a water sector themselves. // Only works if you cannot see the top surface of any deep water // sectors at the same time. if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL) { if (rw_frontcz1 <= s->floorplane.ZatPoint (curline->v1->x, curline->v1->y) && rw_frontcz2 <= s->floorplane.ZatPoint (curline->v2->x, curline->v2->y)) { // Check that the window is actually visible for (int z = WallSX1; z < WallSX2; ++z) { if (floorclip[z] > ceilingclip[z]) { doorunderwater = true; r_fakingunderwater = true; break; } } } } } else { // have to do this a different way for the hardware engine... } #endif if (underwater || doorunderwater) { tempsec->floorplane = sec->floorplane; tempsec->ceilingplane = s->floorplane; tempsec->ceilingplane.FlipVert (); tempsec->ceilingplane.ChangeHeight (-1); tempsec->ColorMap = s->ColorMap; } // killough 11/98: prevent sudden light changes from non-water sectors: if ((underwater && !back) || doorunderwater) { // head-below-floor hack tempsec->floorpic = diffTex ? sec->floorpic : s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_xscale = s->floor_xscale; tempsec->floor_yscale = s->floor_yscale; tempsec->floor_angle = s->floor_angle; tempsec->base_floor_angle = s->base_floor_angle; tempsec->base_floor_yoffs = s->base_floor_yoffs; tempsec->ceilingplane = s->floorplane; tempsec->ceilingplane.FlipVert (); tempsec->ceilingplane.ChangeHeight (-1); if (s->ceilingpic == skyflatnum) { tempsec->floorplane = tempsec->ceilingplane; tempsec->floorplane.FlipVert (); tempsec->floorplane.ChangeHeight (+1); tempsec->ceilingpic = tempsec->floorpic; tempsec->ceiling_xoffs = tempsec->floor_xoffs; tempsec->ceiling_yoffs = tempsec->floor_yoffs; tempsec->ceiling_xscale = tempsec->floor_xscale; tempsec->ceiling_yscale = tempsec->floor_yscale; tempsec->ceiling_angle = tempsec->floor_angle; tempsec->base_ceiling_angle = tempsec->base_floor_angle; tempsec->base_ceiling_yoffs = tempsec->base_floor_yoffs; } else { tempsec->ceilingpic = diffTex ? s->floorpic : s->ceilingpic; tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceiling_xscale = s->ceiling_xscale; tempsec->ceiling_yscale = s->ceiling_yscale; tempsec->ceiling_angle = s->ceiling_angle; tempsec->base_ceiling_angle = s->base_ceiling_angle; tempsec->base_ceiling_yoffs = s->base_ceiling_yoffs; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (s); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (s); } } FakeSide = FAKED_BelowFloor; } else if (heightsec && viewz >= heightsec->ceilingplane.ZatPoint (viewx, viewy) && orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY)) { // Above-ceiling hack tempsec->ceilingplane = s->ceilingplane; tempsec->floorplane = s->ceilingplane; tempsec->floorplane.FlipVert (); tempsec->floorplane.ChangeHeight (+1); tempsec->ColorMap = s->ColorMap; tempsec->ColorMap = s->ColorMap; tempsec->ceilingpic = diffTex ? sec->ceilingpic : s->ceilingpic; tempsec->floorpic = s->ceilingpic; tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floor_xscale = tempsec->ceiling_xscale = s->ceiling_xscale; tempsec->floor_yscale = tempsec->ceiling_yscale = s->ceiling_yscale; tempsec->floor_angle = tempsec->ceiling_angle = s->ceiling_angle; tempsec->base_floor_angle = tempsec->base_ceiling_angle = s->base_ceiling_angle; tempsec->base_floor_yoffs = tempsec->base_ceiling_yoffs = s->base_ceiling_yoffs; if (s->floorpic != skyflatnum) { tempsec->ceilingplane = sec->ceilingplane; tempsec->floorpic = s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_xscale = s->floor_xscale; tempsec->floor_yscale = s->floor_yscale; tempsec->floor_angle = s->floor_angle; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = GetFloorLight (s); } if (ceilinglightlevel != NULL) { *ceilinglightlevel = GetCeilingLight (s); } } FakeSide = FAKED_AboveCeiling; } sec = tempsec; // Use other sector } return sec; }