//========================================================================== // // // //========================================================================== bool FDrawInfo::DoOneSectorLower(subsector_t * subsec, fixed_t planez) { // Is there a one-sided wall in this subsector? // Do this first to avoid unnecessary recursion for(DWORD i=0; i< subsec->numlines; i++) { if (subsec->firstline[i].backsector == NULL) return false; if (subsec->firstline[i].PartnerSeg == NULL) return false; } for(DWORD i=0; i< subsec->numlines; i++) { seg_t * seg = subsec->firstline + i; subsector_t * backsub = seg->PartnerSeg->Subsector; // already checked? if (backsub->validcount == validcount) continue; backsub->validcount=validcount; if (seg->frontsector != seg->backsector && seg->linedef) { // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! sector_t * sec = gl_FakeFlat(seg->backsector, &fakesec, true); // Don't bother with slopes if (sec->floorplane.a!=0 || sec->floorplane.b!=0) return false; // Is the neighboring floor higher than the desired height? if (sec->GetPlaneTexZ(sector_t::floor)>planez) { // todo: check for missing textures. return false; } // This is an exact height match which means we don't have to do any further checks for this sector if (sec->GetPlaneTexZ(sector_t::floor)==planez) { // If there's a texture abort FTexture * tex = TexMan[seg->sidedef->GetTexture(side_t::bottom)]; if (!tex || tex->UseType==FTexture::TEX_Null) continue; else return false; } } if (!DoOneSectorLower(backsub, planez)) return false; } // all checked ok. This sector is part of the current fake plane HandledSubsectors.Push(subsec); return 1; }
//========================================================================== // // Draws the fake planes // //========================================================================== void FDrawInfo::HandleMissingTextures() { sector_t fake; totalms.Clock(); totalupper=MissingUpperTextures.Size(); totallower=MissingLowerTextures.Size(); for(unsigned int i=0; i<MissingUpperTextures.Size(); i++) { if (!MissingUpperTextures[i].seg) continue; HandledSubsectors.Clear(); validcount++; if (MissingUpperTextures[i].planez > viewz) { // close the hole only if all neighboring sectors are an exact height match // Otherwise just fill in the missing textures. MissingUpperTextures[i].sub->validcount=validcount; if (DoOneSectorUpper(MissingUpperTextures[i].sub, MissingUpperTextures[i].planez)) { sector_t * sec = MissingUpperTextures[i].seg->backsector; // The mere fact that this seg has been added to the list means that the back sector // will be rendered so we can safely assume that it is already in the render list for(unsigned int j=0; j<HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = SSR_List.GetNew(); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(sec->sectornum, node); } if (HandledSubsectors.Size()!=1) { // mark all subsectors in the missing list that got processed by this for(unsigned int j=0; j<HandledSubsectors.Size(); j++) { for(unsigned int k=0; k<MissingUpperTextures.Size(); k++) { if (MissingUpperTextures[k].sub==HandledSubsectors[j]) { MissingUpperTextures[k].seg=NULL; } } } } else MissingUpperTextures[i].seg=NULL; continue; } } if (!MissingUpperTextures[i].seg->PartnerSeg) continue; if (!MissingUpperTextures[i].seg->PartnerSeg->Subsector) continue; validcount++; HandledSubsectors.Clear(); { // It isn't a hole. Now check whether it might be a fake bridge sector_t * fakesector = gl_FakeFlat(MissingUpperTextures[i].seg->frontsector, &fake, false); fixed_t planez = fakesector->GetPlaneTexZ(sector_t::ceiling); MissingUpperTextures[i].seg->PartnerSeg->Subsector->validcount=validcount; if (DoFakeCeilingBridge(MissingUpperTextures[i].seg->PartnerSeg->Subsector, planez)) { // The mere fact that this seg has been added to the list means that the back sector // will be rendered so we can safely assume that it is already in the render list for(unsigned int j=0; j<HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = SSR_List.GetNew(); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(fakesector->sectornum, node); } } continue; } } for(unsigned int i=0; i<MissingLowerTextures.Size(); i++) { if (!MissingLowerTextures[i].seg) continue; HandledSubsectors.Clear(); validcount++; if (MissingLowerTextures[i].planez < viewz) { // close the hole only if all neighboring sectors are an exact height match // Otherwise just fill in the missing textures. MissingLowerTextures[i].sub->validcount=validcount; if (DoOneSectorLower(MissingLowerTextures[i].sub, MissingLowerTextures[i].planez)) { sector_t * sec = MissingLowerTextures[i].seg->backsector; // The mere fact that this seg has been added to the list means that the back sector // will be rendered so we can safely assume that it is already in the render list for(unsigned int j=0; j<HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = SSR_List.GetNew(); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(sec->sectornum, node); } if (HandledSubsectors.Size()!=1) { // mark all subsectors in the missing list that got processed by this for(unsigned int j=0; j<HandledSubsectors.Size(); j++) { for(unsigned int k=0; k<MissingLowerTextures.Size(); k++) { if (MissingLowerTextures[k].sub==HandledSubsectors[j]) { MissingLowerTextures[k].seg=NULL; } } } } else MissingLowerTextures[i].seg=NULL; continue; } } if (!MissingLowerTextures[i].seg->PartnerSeg) continue; if (!MissingLowerTextures[i].seg->PartnerSeg->Subsector) continue; validcount++; HandledSubsectors.Clear(); { // It isn't a hole. Now check whether it might be a fake bridge sector_t * fakesector = gl_FakeFlat(MissingLowerTextures[i].seg->frontsector, &fake, false); fixed_t planez = fakesector->GetPlaneTexZ(sector_t::floor); MissingLowerTextures[i].seg->PartnerSeg->Subsector->validcount=validcount; if (DoFakeBridge(MissingLowerTextures[i].seg->PartnerSeg->Subsector, planez)) { // The mere fact that this seg has been added to the list means that the back sector // will be rendered so we can safely assume that it is already in the render list for(unsigned int j=0; j<HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = SSR_List.GetNew(); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(fakesector->sectornum, node); } } continue; } } totalms.Unclock(); showtotalms=totalms; totalms.Reset(); }
//========================================================================== // // Draws the fake planes // //========================================================================== void HWDrawInfo::HandleMissingTextures(area_t in_area) { for (unsigned int i = 0; i < MissingUpperTextures.Size(); i++) { if (!MissingUpperTextures[i].seg) continue; HandledSubsectors.Clear(); validcount++; if (MissingUpperTextures[i].Planez > Viewpoint.Pos.Z) { // close the hole only if all neighboring sectors are an exact height match // Otherwise just fill in the missing textures. MissingUpperTextures[i].sub->validcount = validcount; if (DoOneSectorUpper(MissingUpperTextures[i].sub, MissingUpperTextures[i].Planez, in_area)) { sector_t * sec = MissingUpperTextures[i].seg->backsector; for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(sec->sectornum, node); } if (HandledSubsectors.Size() != 1) { // mark all subsectors in the missing list that got processed by this for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { for (unsigned int k = 0; k < MissingUpperTextures.Size(); k++) { if (MissingUpperTextures[k].sub == HandledSubsectors[j]) { MissingUpperTextures[k].seg = NULL; } } } } else MissingUpperTextures[i].seg = NULL; continue; } } if (!MissingUpperTextures[i].seg->PartnerSeg) continue; subsector_t *backsub = MissingUpperTextures[i].seg->PartnerSeg->Subsector; if (!backsub) continue; validcount++; HandledSubsectors.Clear(); { // It isn't a hole. Now check whether it might be a fake bridge sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, in_area, false); float planez = (float)fakesector->GetPlaneTexZ(sector_t::ceiling); backsub->validcount = validcount; if (DoFakeCeilingBridge(backsub, planez, in_area)) { for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(fakesector->sectornum, node); } } continue; } } for (unsigned int i = 0; i < MissingLowerTextures.Size(); i++) { if (!MissingLowerTextures[i].seg) continue; HandledSubsectors.Clear(); validcount++; if (MissingLowerTextures[i].Planez < Viewpoint.Pos.Z) { // close the hole only if all neighboring sectors are an exact height match // Otherwise just fill in the missing textures. MissingLowerTextures[i].sub->validcount = validcount; if (DoOneSectorLower(MissingLowerTextures[i].sub, MissingLowerTextures[i].Planez, in_area)) { sector_t * sec = MissingLowerTextures[i].seg->backsector; for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(sec->sectornum, node); } if (HandledSubsectors.Size() != 1) { // mark all subsectors in the missing list that got processed by this for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { for (unsigned int k = 0; k < MissingLowerTextures.Size(); k++) { if (MissingLowerTextures[k].sub == HandledSubsectors[j]) { MissingLowerTextures[k].seg = NULL; } } } } else MissingLowerTextures[i].seg = NULL; continue; } } if (!MissingLowerTextures[i].seg->PartnerSeg) continue; subsector_t *backsub = MissingLowerTextures[i].seg->PartnerSeg->Subsector; if (!backsub) continue; validcount++; HandledSubsectors.Clear(); { // It isn't a hole. Now check whether it might be a fake bridge sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, in_area, false); float planez = (float)fakesector->GetPlaneTexZ(sector_t::floor); backsub->validcount = validcount; if (DoFakeBridge(backsub, planez, in_area)) { for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(fakesector->sectornum, node); } } continue; } } }