void HWDrawInfo::DispatchRenderHacks() { TMap<int, gl_subsectorrendernode*>::Pair *pair; TMap<int, gl_floodrendernode*>::Pair *fpair; TMap<int, gl_subsectorrendernode*>::Iterator ofi(otherFloorPlanes); GLFlat glflat; glflat.section = nullptr; while (ofi.NextPair(pair)) { auto sec = hw_FakeFlat(&Level->sectors[pair->Key], in_area, false); glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK); } TMap<int, gl_subsectorrendernode*>::Iterator oci(otherCeilingPlanes); while (oci.NextPair(pair)) { auto sec = hw_FakeFlat(&Level->sectors[pair->Key], in_area, false); glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK); } TMap<int, gl_floodrendernode*>::Iterator ffi(floodFloorSegs); while (ffi.NextPair(fpair)) { auto sec = hw_FakeFlat(&Level->sectors[fpair->Key], in_area, false); glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK); } TMap<int, gl_floodrendernode*>::Iterator fci(floodCeilingSegs); while (fci.NextPair(fpair)) { auto sec = hw_FakeFlat(&Level->sectors[fpair->Key], in_area, false); glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK); } }
void HWDrawInfo::PrepareLowerGap(seg_t * seg) { wallseg ws; sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false); sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true); vertex_t * v1, *v2; // Although the plane can be sloped this code will only be called // when the edge itself is not. double backz = fakebsector->floorplane.ZatPoint(seg->v1); double frontz = fakefsector->floorplane.ZatPoint(seg->v1); if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return; if (fakebsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) return; if (seg->sidedef == seg->linedef->sidedef[0]) { v1 = seg->linedef->v1; v2 = seg->linedef->v2; } else { v1 = seg->linedef->v2; v2 = seg->linedef->v1; } ws.x1 = v1->fX(); ws.y1 = v1->fY(); ws.x2 = v2->fX(); ws.y2 = v2->fY(); ws.z2 = frontz; ws.z1 = backz; auto vertices = screen->mVertexData->AllocVertices(8); CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false); gl_floodrendernode *node = NewFloodRenderNode(); auto pNode = floodFloorSegs.CheckKey(fakebsector->sectornum); node->next = pNode? *pNode : nullptr; node->seg = seg; node->vertexindex = vertices.second; floodFloorSegs[fakebsector->sectornum] = node; }
void FDrawInfo::FloodLowerGap(seg_t * seg) { wallseg ws; sector_t ffake, bfake; sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true); sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false); vertex_t * v1, * v2; // Although the plane can be sloped this code will only be called // when the edge itself is not. double backz = fakebsector->floorplane.ZatPoint(seg->v1); double frontz = fakefsector->floorplane.ZatPoint(seg->v1); if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return; if (fakebsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) return; if (seg->sidedef == seg->linedef->sidedef[0]) { v1=seg->linedef->v1; v2=seg->linedef->v2; } else { v1=seg->linedef->v2; v2=seg->linedef->v1; } ws.x1 = v1->fX(); ws.y1 = v1->fY(); ws.x2 = v2->fX(); ws.y2 = v2->fY(); ws.z2= frontz; ws.z1= backz; // Step1: Draw a stencil into the gap SetupFloodStencil(&ws); // Step2: Project the ceiling plane into the gap DrawFloodedPlane(&ws, ws.z1, fakebsector, false); // Step3: Delete the stencil ClearFloodStencil(&ws); }
//========================================================================== // // // //========================================================================== bool HWDrawInfo::DoOneSectorLower(subsector_t * subsec, float Planez, area_t in_area) { // Is there a one-sided wall in this subsector? // Do this first to avoid unnecessary recursion for (uint32_t i = 0; i < subsec->numlines; i++) { if (subsec->firstline[i].backsector == NULL) return false; if (subsec->firstline[i].PartnerSeg == NULL) return false; } for (uint32_t 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 = hw_FakeFlat(seg->backsector, in_area, true); // Don't bother with slopes if (sec->floorplane.isSlope()) 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.GetTexture(seg->sidedef->GetTexture(side_t::bottom)); if (!tex || !tex->isValid()) continue; else return false; } } if (!DoOneSectorLower(backsub, Planez, in_area)) return false; } // all checked ok. This sector is part of the current fake plane HandledSubsectors.Push(subsec); return 1; }
//========================================================================== // // 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; } } }