void P_Recalculate3DFloors(sector_t * sector) { F3DFloor * rover; F3DFloor * pick; unsigned pickindex; F3DFloor * clipped=NULL; F3DFloor * solid=NULL; double solid_bottom=0; double clipped_top; double clipped_bottom=0; double maxheight, minheight; unsigned i, j; lightlist_t newlight; lightlist_t resetlight; // what it goes back to after FF_DOUBLESHADOW TArray<F3DFloor*> & ffloors=sector->e->XFloor.ffloors; TArray<lightlist_t> & lightlist = sector->e->XFloor.lightlist; // Sort the floors top to bottom for quicker access here and later // Translucent and swimmable floors are split if they overlap with solid ones. if (ffloors.Size()>1) { TArray<F3DFloor*> oldlist; oldlist = ffloors; ffloors.Clear(); // first delete the old dynamic stuff for(i=0;i<oldlist.Size();i++) { F3DFloor * rover=oldlist[i]; if (rover->flags&FF_DYNAMIC) { delete rover; oldlist.Delete(i); i--; continue; } if (rover->flags&FF_CLIPPED) { rover->flags&=~FF_CLIPPED; rover->flags|=FF_EXISTS; } } while (oldlist.Size()) { pick=oldlist[0]; double height=pick->top.plane->ZatPoint(sector->centerspot); // find highest starting ffloor - intersections are not supported! pickindex=0; for (j=1;j<oldlist.Size();j++) { double h2=oldlist[j]->top.plane->ZatPoint(sector->centerspot); if (h2>height) { pick=oldlist[j]; pickindex=j; height=h2; } } oldlist.Delete(pickindex); double pick_bottom=pick->bottom.plane->ZatPoint(sector->centerspot); if (pick->flags & FF_THISINSIDE) { // These have the floor higher than the ceiling and cannot be processed // by the clipping code below. ffloors.Push(pick); } else if ((pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) || (!(pick->flags&FF_RENDERALL))) && pick->flags&FF_EXISTS) { // We must check if this nonsolid segment gets clipped from the top by another 3D floor if (solid != NULL && solid_bottom < height) { ffloors.Push(pick); if (solid_bottom < pick_bottom) { // this one is fully covered pick->flags|=FF_CLIPPED; pick->flags&=~FF_EXISTS; } else { F3DFloor * dyn=new F3DFloor; *dyn=*pick; pick->flags|=FF_CLIPPED; pick->flags&=~FF_EXISTS; dyn->flags|=FF_DYNAMIC; dyn->top.copyPlane(&solid->bottom); ffloors.Push(dyn); clipped = dyn; clipped_top = solid_bottom; clipped_bottom = pick_bottom; } } else if (pick_bottom > height) // do not allow inverted planes { F3DFloor * dyn = new F3DFloor; *dyn = *pick; pick->flags |= FF_CLIPPED; pick->flags &= ~FF_EXISTS; dyn->flags |= FF_DYNAMIC; dyn->bottom.copyPlane(&pick->top); ffloors.Push(pick); ffloors.Push(dyn); } else { clipped = pick; clipped_top = height; clipped_bottom = pick_bottom; ffloors.Push(pick); } } else if (clipped && clipped_bottom<height) { // translucent floor above must be clipped to this one! F3DFloor * dyn=new F3DFloor; *dyn=*clipped; clipped->flags|=FF_CLIPPED; clipped->flags&=~FF_EXISTS; dyn->flags|=FF_DYNAMIC; dyn->bottom.copyPlane(&pick->top); ffloors.Push(dyn); ffloors.Push(pick); if (pick_bottom<=clipped_bottom) { clipped=NULL; } else { // the translucent part extends below the clipper dyn=new F3DFloor; *dyn=*clipped; dyn->flags|=FF_DYNAMIC|FF_EXISTS; dyn->top.copyPlane(&pick->bottom); ffloors.Push(dyn); clipped = dyn; clipped_top = pick_bottom; } solid = pick; solid_bottom = pick_bottom; } else { clipped = NULL; if (solid == NULL || solid_bottom > pick_bottom) { // only if this one is lower solid = pick; solid_bottom = pick_bottom; } ffloors.Push(pick); } } } // having the floors sorted makes this routine significantly simpler // Only some overlapping cases with FF_DOUBLESHADOW might create anomalies // but these are clearly undefined. if(ffloors.Size()) { lightlist.Resize(1); lightlist[0].plane = sector->ceilingplane; lightlist[0].p_lightlevel = §or->lightlevel; lightlist[0].caster = NULL; lightlist[0].lightsource = NULL; lightlist[0].extra_colormap = sector->ColorMap; lightlist[0].blend = 0; lightlist[0].flags = 0; resetlight = lightlist[0]; maxheight = sector->ceilingplane.ZatPoint(sector->centerspot); minheight = sector->floorplane.ZatPoint(sector->centerspot); for(i = 0; i < ffloors.Size(); i++) { rover=ffloors[i]; if ( !(rover->flags & FF_EXISTS) || rover->flags & FF_NOSHADE ) continue; double ff_top=rover->top.plane->ZatPoint(sector->centerspot); if (ff_top < minheight) break; // reached the floor if (ff_top < maxheight) { newlight.plane = *rover->top.plane; newlight.p_lightlevel = rover->toplightlevel; newlight.caster = rover; newlight.lightsource = rover; newlight.extra_colormap = rover->GetColormap(); newlight.blend = rover->GetBlend(); newlight.flags = rover->flags; lightlist.Push(newlight); } else { double ff_bottom=rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom<maxheight) { // this segment begins over the ceiling and extends beyond it lightlist[0].p_lightlevel = rover->toplightlevel; lightlist[0].caster = rover; lightlist[0].lightsource = rover; lightlist[0].extra_colormap = rover->GetColormap(); lightlist[0].blend = rover->GetBlend(); lightlist[0].flags = rover->flags; } } if (!(rover->flags & (FF_DOUBLESHADOW | FF_RESET))) { resetlight = lightlist.Last(); } else if (rover->flags & FF_RESET) { resetlight.p_lightlevel = §or->lightlevel; resetlight.lightsource = NULL; resetlight.extra_colormap = sector->ColorMap; resetlight.blend = 0; } if (rover->flags&FF_DOUBLESHADOW) { double ff_bottom=rover->bottom.plane->ZatPoint(sector->centerspot); if(ff_bottom < maxheight && ff_bottom>minheight) { newlight.caster = rover; newlight.plane = *rover->bottom.plane; newlight.lightsource = resetlight.lightsource; newlight.p_lightlevel = resetlight.p_lightlevel; newlight.extra_colormap = resetlight.extra_colormap; newlight.blend = resetlight.blend; newlight.flags = rover->flags; lightlist.Push(newlight); } } } } }
void GLFlat::ProcessSector(sector_t * frontsector) { lightlist_t * light; #ifdef _DEBUG if (frontsector->sectornum==gl_breaksec) { int a = 0; } #endif // Get the real sector for this one. sector=§ors[frontsector->sectornum]; extsector_t::xfloor &x = sector->e->XFloor; this->sub=NULL; dynlightindex = -1; byte &srf = gl_drawinfo->sectorrenderflags[sector->sectornum]; // // // // do floors // // // if (frontsector->floorplane.ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy)) <= FIXED2FLOAT(viewz)) { // process the original floor first. srf |= SSRF_RENDERFLOOR; lightlevel = gl_ClampLight(frontsector->GetFloorLight()); Colormap=frontsector->ColorMap; if ((stack = (frontsector->portals[sector_t::floor] != NULL))) { gl_drawinfo->AddFloorStack(sector); alpha = frontsector->GetAlpha(sector_t::floor)/65536.0f; } else { alpha = 1.0f-frontsector->GetReflect(sector_t::floor); } if (frontsector->VBOHeightcheck(sector_t::floor)) { vboindex = frontsector->vboindex[sector_t::floor]; } else { vboindex = -1; } ceiling=false; renderflags=SSRF_RENDERFLOOR; if (x.ffloors.Size()) { light = P_GetPlaneLight(sector, &frontsector->floorplane, false); if ((!(sector->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING) || !light->fromsector) && (light->p_lightlevel != &frontsector->lightlevel)) { lightlevel = *light->p_lightlevel; } Colormap.CopyLightColor(light->extra_colormap); } renderstyle = STYLE_Translucent; if (alpha!=0.0f) Process(frontsector, false, false); } // // // // do ceilings // // // if (frontsector->ceilingplane.ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy)) >= FIXED2FLOAT(viewz)) { // process the original ceiling first. srf |= SSRF_RENDERCEILING; lightlevel = gl_ClampLight(frontsector->GetCeilingLight()); Colormap=frontsector->ColorMap; if ((stack = (frontsector->portals[sector_t::ceiling] != NULL))) { gl_drawinfo->AddCeilingStack(sector); alpha = frontsector->GetAlpha(sector_t::ceiling)/65536.0f; } else { alpha = 1.0f-frontsector->GetReflect(sector_t::ceiling); } if (frontsector->VBOHeightcheck(sector_t::ceiling)) { vboindex = frontsector->vboindex[sector_t::ceiling]; } else { vboindex = -1; } ceiling=true; renderflags=SSRF_RENDERCEILING; if (x.ffloors.Size()) { light = P_GetPlaneLight(sector, §or->ceilingplane, true); if ((!(sector->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) && (light->p_lightlevel != &frontsector->lightlevel)) { lightlevel = *light->p_lightlevel; } Colormap.CopyLightColor(light->extra_colormap); } renderstyle = STYLE_Translucent; if (alpha!=0.0f) Process(frontsector, true, false); } // // // // do 3D floors // // // stack=false; if (x.ffloors.Size()) { player_t * player=players[consoleplayer].camera->player; renderflags=SSRF_RENDER3DPLANES; srf |= SSRF_RENDER3DPLANES; // 3d-floors must not overlap! fixed_t lastceilingheight=sector->CenterCeiling(); // render only in the range of the fixed_t lastfloorheight=sector->CenterFloor(); // current sector part (if applicable) F3DFloor * rover; int k; // floors are ordered now top to bottom so scanning the list for the best match // is no longer necessary. ceiling=true; for(k=0;k<(int)x.ffloors.Size();k++) { rover=x.ffloors[k]; if ((rover->flags&(FF_EXISTS|FF_RENDERPLANES|FF_THISINSIDE))==(FF_EXISTS|FF_RENDERPLANES)) { if (rover->flags&FF_FOG && gl_fixedcolormap) continue; if (!rover->top.copied && rover->flags&(FF_INVERTPLANES|FF_BOTHPLANES)) { fixed_t ff_top=rover->top.plane->ZatPoint(CenterSpot(sector)); if (ff_top<lastceilingheight) { if (FIXED2FLOAT(viewz) <= rover->top.plane->ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy))) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor=frontsector->ColorMap->Fade; Process(rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG)); } lastceilingheight=ff_top; } } if (!rover->bottom.copied && !(rover->flags&FF_INVERTPLANES)) { fixed_t ff_bottom=rover->bottom.plane->ZatPoint(CenterSpot(sector)); if (ff_bottom<lastceilingheight) { if (FIXED2FLOAT(viewz)<=rover->bottom.plane->ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy))) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor=frontsector->ColorMap->Fade; Process(rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG)); } lastceilingheight=ff_bottom; if (rover->alpha<255) lastceilingheight++; } } } } ceiling=false; for(k=x.ffloors.Size()-1;k>=0;k--) { rover=x.ffloors[k]; if ((rover->flags&(FF_EXISTS|FF_RENDERPLANES|FF_THISINSIDE))==(FF_EXISTS|FF_RENDERPLANES)) { if (rover->flags&FF_FOG && gl_fixedcolormap) continue; if (!rover->bottom.copied && rover->flags&(FF_INVERTPLANES|FF_BOTHPLANES)) { fixed_t ff_bottom=rover->bottom.plane->ZatPoint(CenterSpot(sector)); if (ff_bottom>lastfloorheight || (rover->flags&FF_FIX)) { if (FIXED2FLOAT(viewz) >= rover->bottom.plane->ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy))) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor=frontsector->ColorMap->Fade; if (rover->flags&FF_FIX) { lightlevel = gl_ClampLight(rover->model->lightlevel); Colormap = rover->GetColormap(); } Process(rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG)); } lastfloorheight=ff_bottom; } } if (!rover->top.copied && !(rover->flags&FF_INVERTPLANES)) { fixed_t ff_top=rover->top.plane->ZatPoint(CenterSpot(sector)); if (ff_top>lastfloorheight) { if (FIXED2FLOAT(viewz) >= rover->top.plane->ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy))) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor=frontsector->ColorMap->Fade; Process(rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG)); } lastfloorheight=ff_top; if (rover->alpha<255) lastfloorheight--; } } } } } }