- eliminated global in_area variable.

Removing this made me realize that calling the renderers' FakeFlat functions from the automap is inherently unsafe with the recent refactorings because there is absolutely no guarantee that the data may actually still be defined when the automap is being drawn.
So the best approach here is to give the automap its own FakeFlat function that runs independently of render data and assumptions of data preservation. This one can also be a lot simpler because it only needs the floor, not the ceiling info.
This commit is contained in:
Christoph Oelckers 2017-03-12 23:13:07 +01:00
parent 4c61048278
commit d72623b9b5
14 changed files with 162 additions and 75 deletions

View File

@ -1883,6 +1883,124 @@ void AM_drawGrid (int color)
}
}
//==========================================================================
//
// This was previously using the variants from the renderers but with
// all globals being factored out this will become dangerouns and unpredictable
// as the original R_FakeFlat heavily depended on global variables from
// the last rendered scene.
//
//==========================================================================
sector_t * AM_FakeFlat(AActor *viewer, sector_t * sec, sector_t * dest)
{
if (sec->GetHeightSec() == nullptr) return sec;
DVector3 pos = viewer->Pos();
if (viewer->player)
{
pos.Z = viewer->player->viewz;
}
else
{
pos.Z += viewer->GetCameraHeight();
}
int in_area;
if (viewer->Sector->GetHeightSec() == nullptr)
{
in_area = 0;
}
else
{
in_area = pos.Z <= viewer->Sector->heightsec->floorplane.ZatPoint(pos) ? -1 :
(pos.Z > viewer->Sector->heightsec->ceilingplane.ZatPoint(pos) && !(viewer->Sector->heightsec->MoreFlags&SECF_FAKEFLOORONLY)) ? 1 : 0;
}
int diffTex = (sec->heightsec->MoreFlags & SECF_CLIPFAKEPLANES);
sector_t * s = sec->heightsec;
memcpy(dest, sec, sizeof(sector_t));
// Replace floor height with control sector's heights.
// The automap is only interested in the floor so let's skip the ceiling.
if (diffTex)
{
if (s->floorplane.CopyPlaneIfValid(&dest->floorplane, &sec->ceilingplane))
{
dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false);
dest->SetPlaneTexZ(sector_t::floor, s->GetPlaneTexZ(sector_t::floor));
}
else if (s->MoreFlags & SECF_FAKEFLOORONLY)
{
if (in_area == -1)
{
dest->ColorMap = s->ColorMap;
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
{
dest->lightlevel = s->lightlevel;
dest->SetPlaneLight(sector_t::floor, s->GetPlaneLight(sector_t::floor));
dest->ChangeFlags(sector_t::floor, -1, s->GetFlags(sector_t::floor));
}
return dest;
}
return sec;
}
}
else
{
dest->SetPlaneTexZ(sector_t::floor, s->GetPlaneTexZ(sector_t::floor));
dest->floorplane = s->floorplane;
}
if (in_area == -1)
{
dest->ColorMap = s->ColorMap;
dest->SetPlaneTexZ(sector_t::floor, sec->GetPlaneTexZ(sector_t::floor));
dest->floorplane = sec->floorplane;
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
{
dest->lightlevel = s->lightlevel;
}
dest->SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false);
dest->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform;
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
{
dest->SetPlaneLight(sector_t::floor, s->GetPlaneLight(sector_t::floor));
dest->ChangeFlags(sector_t::floor, -1, s->GetFlags(sector_t::floor));
}
}
else if (in_area == 1)
{
dest->ColorMap = s->ColorMap;
dest->SetPlaneTexZ(sector_t::floor, s->GetPlaneTexZ(sector_t::ceiling));
dest->floorplane = s->ceilingplane;
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
{
dest->lightlevel = s->lightlevel;
}
dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false);
if (s->GetTexture(sector_t::floor) != skyflatnum)
{
dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false);
dest->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform;
}
if (!(s->MoreFlags & SECF_NOFAKELIGHT))
{
dest->lightlevel = s->lightlevel;
dest->SetPlaneLight(sector_t::floor, s->GetPlaneLight(sector_t::floor));
dest->ChangeFlags(sector_t::floor, -1, s->GetFlags(sector_t::floor));
}
}
return dest;
}
//=============================================================================
//
// AM_drawSubsectors
@ -1895,7 +2013,7 @@ void AM_drawSubsectors()
double scale = scale_mtof;
DAngle rotation;
sector_t tempsec;
int floorlight, ceilinglight;
int floorlight;
double scalex, scaley;
double originx, originy;
FDynamicColormap *colormap;
@ -1933,7 +2051,8 @@ void AM_drawSubsectors()
points[j].Y = float(f_y + (f_h - (pt.y - m_y) * scale));
}
// For lighting and texture determination
sector_t *sec = Renderer->FakeFlat(subsectors[i].render_sector, &tempsec, &floorlight, &ceilinglight);
sector_t *sec = AM_FakeFlat(players[consoleplayer].camera, subsectors[i].render_sector, &tempsec);
floorlight = sec->GetFloorLight();
// Find texture origin.
originpt.x = -sec->GetXOffset(sector_t::floor);
originpt.y = sec->GetYOffset(sector_t::floor);

View File

@ -196,27 +196,18 @@ public:
static float GetZFar() { return 65536.f; }
};
enum area_t
{
area_normal,
area_below,
area_above,
area_default
};
// Global functions. Make them members of GLRenderer later?
void gl_RenderBSPNode (void *node);
bool gl_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
void gl_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector);
typedef enum
{
area_normal,
area_below,
area_above,
area_default
} area_t;
extern area_t in_area;
sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
inline sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, bool back)
{
return gl_FakeFlat(sec, dest, in_area, back);
}
struct TexFilter_s
{

View File

@ -147,9 +147,9 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
else
{
// clipping checks are only needed when the backsector is not the same as the front sector
gl_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
backsector = gl_FakeFlat(seg->backsector, &bs, true);
backsector = gl_FakeFlat(seg->backsector, &bs, in_area, true);
if (gl_CheckClip(seg->sidedef, currentsector, backsector))
{
@ -435,7 +435,7 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
}
if (clipper.IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
fakesector=gl_FakeFlat(sector, &fake, false);
fakesector=gl_FakeFlat(sector, &fake, in_area, false);
if (GLRenderer->mClipPortal)
{
@ -502,7 +502,7 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
sector = sub->render_sector;
// the planes of this subsector are faked to belong to another sector
// This means we need the heightsec parts and light info of the render sector, not the actual one.
fakesector = gl_FakeFlat(sector, &fake, false);
fakesector = gl_FakeFlat(sector, &fake, in_area, false);
}
uint8_t &srf = gl_drawinfo->sectorrenderflags[sub->render_sector->sectornum];

View File

@ -1230,8 +1230,8 @@ void FDrawInfo::FloodUpperGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = gl_FakeFlat(seg->frontsector, &ffake, true);
sector_t * fakebsector = gl_FakeFlat(seg->backsector, &bfake, false);
sector_t * fakefsector = gl_FakeFlat(seg->frontsector, &ffake, mDrawer->in_area, true);
sector_t * fakebsector = gl_FakeFlat(seg->backsector, &bfake, mDrawer->in_area, false);
vertex_t * v1, * v2;
@ -1282,8 +1282,8 @@ void FDrawInfo::FloodLowerGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = gl_FakeFlat(seg->frontsector, &ffake, true);
sector_t * fakebsector = gl_FakeFlat(seg->backsector, &bfake, false);
sector_t * fakefsector = gl_FakeFlat(seg->frontsector, &ffake, mDrawer->in_area, true);
sector_t * fakebsector = gl_FakeFlat(seg->backsector, &bfake, mDrawer->in_area, false);
vertex_t * v1, * v2;

View File

@ -31,7 +31,7 @@
#include "a_sharedglobal.h"
#include "r_sky.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/scene/gl_clipper.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/data/gl_data.h"
@ -160,7 +160,7 @@ bool gl_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsecto
//
//==========================================================================
void gl_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector)
void GLSceneDrawer::CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector)
{
if (in_area == area_default &&
(backsector->heightsec && !(backsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)) &&

View File

@ -287,7 +287,7 @@ bool GLPortal::Start(bool usestencil, bool doquery)
savedshowviewer = r_viewpoint.showviewer;
savedAngles = r_viewpoint.Angles;
savedviewactor=GLRenderer->mViewActor;
savedviewarea=in_area;
savedviewarea=drawer->in_area;
savedviewpath[0] = r_viewpoint.Path[0];
savedviewpath[1] = r_viewpoint.Path[1];
savedvisibility = r_viewpoint.camera ? r_viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
@ -359,7 +359,7 @@ void GLPortal::End(bool usestencil)
r_viewpoint.ActorPos = savedViewActorPos;
r_viewpoint.Angles = savedAngles;
GLRenderer->mViewActor=savedviewactor;
in_area=savedviewarea;
drawer->in_area=savedviewarea;
if (r_viewpoint.camera != nullptr) r_viewpoint.camera->renderflags = (r_viewpoint.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
@ -418,7 +418,7 @@ void GLPortal::End(bool usestencil)
r_viewpoint.Pos = savedViewPos;
r_viewpoint.Angles = savedAngles;
GLRenderer->mViewActor=savedviewactor;
in_area=savedviewarea;
drawer->in_area=savedviewarea;
if (r_viewpoint.camera != nullptr) r_viewpoint.camera->renderflags |= savedvisibility;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

View File

@ -37,6 +37,7 @@
#include "gl/dynlights/gl_glow.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_portal.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/utility/gl_clock.h"
#include "gl/utility/gl_templates.h"
@ -280,7 +281,7 @@ bool FDrawInfo::DoOneSectorUpper(subsector_t * subsec, float Planez)
// 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);
sector_t * sec = gl_FakeFlat(seg->backsector, &fakesec, mDrawer->in_area, true);
// Don't bother with slopes
if (sec->ceilingplane.isSlope()) return false;
@ -338,7 +339,7 @@ bool FDrawInfo::DoOneSectorLower(subsector_t * subsec, float Planez)
// 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);
sector_t * sec = gl_FakeFlat(seg->backsector, &fakesec, mDrawer->in_area, true);
// Don't bother with slopes
if (sec->floorplane.isSlope()) return false;
@ -397,7 +398,7 @@ bool FDrawInfo::DoFakeBridge(subsector_t * subsec, float Planez)
// 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);
sector_t * sec = gl_FakeFlat(seg->backsector, &fakesec, mDrawer->in_area, true);
// Don't bother with slopes
if (sec->floorplane.isSlope()) return false;
@ -450,7 +451,7 @@ bool FDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez)
// 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);
sector_t * sec = gl_FakeFlat(seg->backsector, &fakesec, mDrawer->in_area, true);
// Don't bother with slopes
if (sec->ceilingplane.isSlope()) return false;
@ -539,7 +540,7 @@ void FDrawInfo::HandleMissingTextures()
{
// 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);
sector_t * fakesector = gl_FakeFlat(MissingUpperTextures[i].seg->frontsector, &fake, mDrawer->in_area, false);
float planez = (float)fakesector->GetPlaneTexZ(sector_t::ceiling);
backsub->validcount = validcount;
@ -610,7 +611,7 @@ void FDrawInfo::HandleMissingTextures()
{
// 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);
sector_t * fakesector = gl_FakeFlat(MissingLowerTextures[i].seg->frontsector, &fake, mDrawer->in_area, false);
float planez = (float)fakesector->GetPlaneTexZ(sector_t::floor);
backsub->validcount = validcount;
@ -1042,7 +1043,7 @@ void FDrawInfo::CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor)
if (sub->numlines>2 && !(ss_renderflags[uint32_t(sub-subsectors)]&SSRF_PROCESSED)) return;
// Must be the exact same visplane
sector_t * me = gl_FakeFlat(sub->render_sector, &fakesec, false);
sector_t * me = gl_FakeFlat(sub->render_sector, &fakesec, mDrawer->in_area, false);
if (me->GetTexture(sector_t::ceiling) != anchor->GetTexture(sector_t::ceiling) ||
me->ceilingplane != anchor->ceilingplane ||
me->GetCeilingLight() != anchor->GetCeilingLight() ||
@ -1085,7 +1086,7 @@ void FDrawInfo::CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor)
if (sub->numlines>2 && !(ss_renderflags[uint32_t(sub-subsectors)]&SSRF_PROCESSED)) return;
// Must be the exact same visplane
sector_t * me = gl_FakeFlat(sub->render_sector, &fakesec, false);
sector_t * me = gl_FakeFlat(sub->render_sector, &fakesec, mDrawer->in_area, false);
if (me->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
me->floorplane != anchor->floorplane ||
me->GetFloorLight() != anchor->GetFloorLight() ||
@ -1124,7 +1125,7 @@ void FDrawInfo::ProcessSectorStacks()
validcount++;
for (i=0;i<CeilingStacks.Size (); i++)
{
sector_t *sec = gl_FakeFlat(CeilingStacks[i], &fake, false);
sector_t *sec = gl_FakeFlat(CeilingStacks[i], &fake, mDrawer->in_area, false);
FPortal *portal = sec->GetGLPortal(sector_t::ceiling);
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
{
@ -1168,7 +1169,7 @@ void FDrawInfo::ProcessSectorStacks()
validcount++;
for (i=0;i<FloorStacks.Size (); i++)
{
sector_t *sec = gl_FakeFlat(FloorStacks[i], &fake, false);
sector_t *sec = gl_FakeFlat(FloorStacks[i], &fake, mDrawer->in_area, false);
FPortal *portal = sec->GetGLPortal(sector_t::floor);
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
{

View File

@ -85,7 +85,6 @@ EXTERN_CVAR (Bool, r_deathcamera)
EXTERN_CVAR (Float, underwater_fade_scalar)
extern int viewpitch;
extern bool NoInterpolateView;
area_t in_area;
@ -991,7 +990,6 @@ struct FGLInterface : public FRenderer
void StartSerialize(FSerializer &arc) override;
void EndSerialize(FSerializer &arc) override;
void RenderTextureView (FCanvasTexture *self, AActor *viewpoint, int fov) override;
sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel) override;
void SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefogdensity, int _skyfog) override;
void PreprocessLevel() override;
void CleanLevelData() override;
@ -1165,25 +1163,6 @@ void FGLInterface::RenderTextureView (FCanvasTexture *tex, AActor *Viewpoint, in
camtexcount++;
}
//==========================================================================
//
//
//
//==========================================================================
sector_t *FGLInterface::FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel)
{
if (floorlightlevel != NULL)
{
*floorlightlevel = sec->GetFloorLight ();
}
if (ceilinglightlevel != NULL)
{
*ceilinglightlevel = sec->GetCeilingLight ();
}
return gl_FakeFlat(sec, tempsec, false);
}
//===========================================================================
//
//

View File

@ -5,6 +5,7 @@
#include "gl_clipper.h"
#include "gl_portal.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderer.h"
class GLSceneDrawer
{
@ -39,6 +40,7 @@ public:
Clipper clipper;
int FixedColormap;
area_t in_area;
angle_t FrustumAngle();
void SetViewMatrix(float vx, float vy, float vz, bool mirror, bool planemirror);
@ -55,6 +57,8 @@ public:
void EndDrawScene(sector_t * viewsector);
void RenderActorsInPortal(FGLLinePortal *glport);
void CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector);
sector_t *RenderViewpoint(AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen);
void RenderView(player_t *player);
void WriteSavePic(player_t *player, FileWriter *file, int width, int height);

View File

@ -752,7 +752,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
if (sector->sectornum != thing->Sector->sectornum && !thruportal)
{
rendersector = gl_FakeFlat(thing->Sector, &rs, false);
rendersector = gl_FakeFlat(thing->Sector, &rs, mDrawer->in_area, false);
}
else
{
@ -927,7 +927,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
Colormap=rendersector->ColorMap;
if (fullbright)
{
if (rendersector == &level.sectors[rendersector->sectornum] || in_area != area_below)
if (rendersector == &level.sectors[rendersector->sectornum] || mDrawer->in_area != area_below)
// under water areas keep their color for fullbright objects
{
// Only make the light white but keep everything else (fog, desaturation and Boom colormap.)
@ -1259,7 +1259,7 @@ void GLSceneDrawer::RenderActorsInPortal(FGLLinePortal *glport)
th->Prev += newpos - savedpos;
GLSprite spr(this);
spr.Process(th, gl_FakeFlat(th->Sector, &fakesector, false), 2);
spr.Process(th, gl_FakeFlat(th->Sector, &fakesector, in_area, false), 2);
th->Angles.Yaw = savedangle;
th->SetXYZ(savedpos);
th->Prev -= newpos - savedpos;

View File

@ -245,7 +245,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
}
else
{
fakesec = gl_FakeFlat(viewsector, &fs, false);
fakesec = gl_FakeFlat(viewsector, &fs, in_area, false);
// calculate light level for weapon sprites
lightlevel = gl_ClampLight(fakesec->lightlevel);

View File

@ -53,7 +53,6 @@ struct FRenderer
virtual void SetClearColor(int color) = 0;
virtual void Init() = 0;
virtual void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) = 0;
virtual sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel) = 0;
virtual void SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefogdensity, int _skyfog) {}
virtual void PreprocessLevel() {}
virtual void CleanLevelData() {}

View File

@ -353,11 +353,6 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin
r_viewwindow = viewport->viewwindow;
}
sector_t *FSoftwareRenderer::FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel)
{
return mScene.MainThread()->OpaquePass->FakeFlat(sec, tempsec, floorlightlevel, ceilinglightlevel, nullptr, 0, 0, 0, 0);
}
void FSoftwareRenderer::PreprocessLevel()
{
gl_PreprocessLevel();

View File

@ -34,7 +34,6 @@ struct FSoftwareRenderer : public FRenderer
void SetClearColor(int color) override;
void Init() override;
void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) override;
sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel) override;
void PreprocessLevel() override;
void CleanLevelData() override;