mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-24 04:51:41 +00:00
Rewrite VisibleSpriteList to use TArray
This commit is contained in:
parent
cd9043fd94
commit
57d8b0e34c
9 changed files with 75 additions and 132 deletions
|
@ -102,7 +102,6 @@ namespace swrenderer
|
|||
int savedextralight = extralight;
|
||||
DVector3 savedpos = ViewPos;
|
||||
DAngle savedangle = ViewAngle;
|
||||
ptrdiff_t savedvissprite_p = VisibleSpriteList::vissprite_p - VisibleSpriteList::vissprites;
|
||||
ptrdiff_t savedds_p = ds_p - drawsegs;
|
||||
size_t savedinteresting = FirstInterestingDrawseg;
|
||||
double savedvisibility = R_GetVisibility();
|
||||
|
@ -220,15 +219,13 @@ namespace swrenderer
|
|||
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||
memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||
|
||||
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprite_p;
|
||||
firstdrawseg = draw_segment;
|
||||
FirstInterestingDrawseg = InterestingDrawsegs.Size();
|
||||
|
||||
interestingStack.Push(FirstInterestingDrawseg);
|
||||
ptrdiff_t diffnum = firstdrawseg - drawsegs;
|
||||
drawsegStack.Push(diffnum);
|
||||
diffnum = VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites;
|
||||
visspriteStack.Push(diffnum);
|
||||
VisibleSpriteList::Instance()->PushPortal();
|
||||
viewposStack.Push(ViewPos);
|
||||
visplaneStack.Push(pl);
|
||||
|
||||
|
@ -249,8 +246,6 @@ namespace swrenderer
|
|||
|
||||
drawsegStack.Pop(pd);
|
||||
firstdrawseg = drawsegs + pd;
|
||||
visspriteStack.Pop(pd);
|
||||
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites + pd;
|
||||
|
||||
// Masked textures and planes need the view coordinates restored for proper positioning.
|
||||
viewposStack.Pop(ViewPos);
|
||||
|
@ -258,7 +253,8 @@ namespace swrenderer
|
|||
RenderTranslucentPass::Render();
|
||||
|
||||
ds_p = firstdrawseg;
|
||||
VisibleSpriteList::vissprite_p = VisibleSpriteList::firstvissprite;
|
||||
|
||||
VisibleSpriteList::Instance()->PopPortal();
|
||||
|
||||
visplaneStack.Pop(pl);
|
||||
if (pl->Alpha > 0 && pl->picnum != skyflatnum)
|
||||
|
@ -268,8 +264,6 @@ namespace swrenderer
|
|||
*planes->freehead = pl;
|
||||
planes->freehead = &pl->next;
|
||||
}
|
||||
VisibleSpriteList::firstvissprite = VisibleSpriteList::vissprites;
|
||||
VisibleSpriteList::vissprite_p = VisibleSpriteList::vissprites + savedvissprite_p;
|
||||
firstdrawseg = drawsegs;
|
||||
ds_p = drawsegs + savedds_p;
|
||||
InterestingDrawsegs.Resize((unsigned int)FirstInterestingDrawseg);
|
||||
|
|
|
@ -55,7 +55,6 @@ namespace swrenderer
|
|||
|
||||
TArray<size_t> interestingStack;
|
||||
TArray<ptrdiff_t> drawsegStack;
|
||||
TArray<ptrdiff_t> visspriteStack;
|
||||
TArray<DVector3> viewposStack;
|
||||
TArray<visplane_t *> visplaneStack;
|
||||
};
|
||||
|
|
|
@ -51,14 +51,12 @@ namespace swrenderer
|
|||
|
||||
void RenderTranslucentPass::Deinit()
|
||||
{
|
||||
VisibleSpriteList::Deinit();
|
||||
SortedVisibleSpriteList::Deinit();
|
||||
RenderVoxel::Deinit();
|
||||
}
|
||||
|
||||
void RenderTranslucentPass::Clear()
|
||||
{
|
||||
VisibleSpriteList::Clear();
|
||||
VisibleSpriteList::Instance()->Clear();
|
||||
DrewAVoxel = false;
|
||||
}
|
||||
|
||||
|
@ -529,11 +527,12 @@ namespace swrenderer
|
|||
{
|
||||
RenderPortal *renderportal = RenderPortal::Instance();
|
||||
|
||||
for (int i = SortedVisibleSpriteList::vsprcount; i > 0; i--)
|
||||
auto &sortedSprites = VisibleSpriteList::Instance()->SortedSprites;
|
||||
for (int i = sortedSprites.Size(); i > 0; i--)
|
||||
{
|
||||
if (SortedVisibleSpriteList::spritesorter[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
if (sortedSprites[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
continue; // probably another time
|
||||
DrawSprite(SortedVisibleSpriteList::spritesorter[i - 1]);
|
||||
DrawSprite(sortedSprites[i - 1]);
|
||||
}
|
||||
|
||||
// render any remaining masked mid textures
|
||||
|
@ -565,7 +564,7 @@ namespace swrenderer
|
|||
void RenderTranslucentPass::Render()
|
||||
{
|
||||
CollectPortals();
|
||||
SortedVisibleSpriteList::Sort(DrewAVoxel ? SortedVisibleSpriteList::sv_compare2d : SortedVisibleSpriteList::sv_compare, VisibleSpriteList::firstvissprite - VisibleSpriteList::vissprites);
|
||||
VisibleSpriteList::Instance()->Sort(DrewAVoxel);
|
||||
|
||||
Clip3DFloors *clip3d = Clip3DFloors::Instance();
|
||||
if (clip3d->height_top == nullptr)
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace swrenderer
|
|||
double tz, tiz;
|
||||
double xscale, yscale;
|
||||
int x1, x2, y1, y2;
|
||||
vissprite_t* vis;
|
||||
sector_t* heightsec = NULL;
|
||||
FSWColormap* map;
|
||||
|
||||
|
@ -179,7 +178,7 @@ namespace swrenderer
|
|||
return;
|
||||
|
||||
// store information in a vissprite
|
||||
vis = VisibleSpriteList::Add();
|
||||
vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
|
||||
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
vis->heightsec = heightsec;
|
||||
vis->xscale = FLOAT2FIXED(xscale);
|
||||
|
@ -223,6 +222,8 @@ namespace swrenderer
|
|||
vis->Style.ColormapNum = GETPALOOKUP(tiz * r_SpriteVisibility * 0.5, shade);
|
||||
vis->Style.BaseColormap = map;
|
||||
}
|
||||
|
||||
VisibleSpriteList::Instance()->Push(vis);
|
||||
}
|
||||
|
||||
void RenderParticle::Render(vissprite_t *vis)
|
||||
|
|
|
@ -156,7 +156,7 @@ namespace swrenderer
|
|||
double yscale = spriteScale.Y / tex->Scale.Y;
|
||||
|
||||
// store information in a vissprite
|
||||
vissprite_t *vis = VisibleSpriteList::Add();
|
||||
vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
|
||||
|
||||
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
vis->xscale = FLOAT2FIXED(xscale);
|
||||
|
@ -274,6 +274,8 @@ namespace swrenderer
|
|||
vis->Style.BaseColormap = mybasecolormap;
|
||||
}
|
||||
}
|
||||
|
||||
VisibleSpriteList::Instance()->Push(vis);
|
||||
}
|
||||
|
||||
void RenderSprite::Render(vissprite_t *vis, const short *mfloorclip, const short *mceilingclip)
|
||||
|
|
|
@ -28,118 +28,78 @@
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
void VisibleSpriteList::Deinit()
|
||||
VisibleSpriteList *VisibleSpriteList::Instance()
|
||||
{
|
||||
// Free vissprites
|
||||
for (int i = 0; i < MaxVisSprites; ++i)
|
||||
{
|
||||
delete vissprites[i];
|
||||
}
|
||||
free(vissprites);
|
||||
vissprites = nullptr;
|
||||
vissprite_p = lastvissprite = nullptr;
|
||||
MaxVisSprites = 0;
|
||||
static VisibleSpriteList instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void VisibleSpriteList::Clear()
|
||||
{
|
||||
vissprite_p = firstvissprite;
|
||||
Sprites.Clear();
|
||||
StartIndices.Clear();
|
||||
SortedSprites.Clear();
|
||||
}
|
||||
|
||||
vissprite_t *VisibleSpriteList::Add()
|
||||
void VisibleSpriteList::PushPortal()
|
||||
{
|
||||
if (vissprite_p == lastvissprite)
|
||||
{
|
||||
ptrdiff_t firstvisspritenum = firstvissprite - vissprites;
|
||||
ptrdiff_t prevvisspritenum = vissprite_p - vissprites;
|
||||
|
||||
MaxVisSprites = MaxVisSprites ? MaxVisSprites * 2 : 128;
|
||||
vissprites = (vissprite_t **)M_Realloc(vissprites, MaxVisSprites * sizeof(vissprite_t));
|
||||
lastvissprite = &vissprites[MaxVisSprites];
|
||||
firstvissprite = &vissprites[firstvisspritenum];
|
||||
vissprite_p = &vissprites[prevvisspritenum];
|
||||
DPrintf(DMSG_NOTIFY, "MaxVisSprites increased to %d\n", MaxVisSprites);
|
||||
|
||||
// Allocate sprites from the new pile
|
||||
for (vissprite_t **p = vissprite_p; p < lastvissprite; ++p)
|
||||
{
|
||||
*p = new vissprite_t;
|
||||
}
|
||||
StartIndices.Push(Sprites.Size());
|
||||
}
|
||||
|
||||
vissprite_p++;
|
||||
return *(vissprite_p - 1);
|
||||
void VisibleSpriteList::PopPortal()
|
||||
{
|
||||
Sprites.Resize(StartIndices.Last());
|
||||
StartIndices.Pop();
|
||||
}
|
||||
|
||||
int VisibleSpriteList::MaxVisSprites;
|
||||
vissprite_t **VisibleSpriteList::vissprites;
|
||||
vissprite_t **VisibleSpriteList::firstvissprite;
|
||||
vissprite_t **VisibleSpriteList::vissprite_p;
|
||||
vissprite_t **VisibleSpriteList::lastvissprite;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SortedVisibleSpriteList::Deinit()
|
||||
void VisibleSpriteList::Push(vissprite_t *sprite)
|
||||
{
|
||||
delete[] spritesorter;
|
||||
spritesortersize = 0;
|
||||
spritesorter = nullptr;
|
||||
Sprites.Push(sprite);
|
||||
}
|
||||
|
||||
// This is the standard version, which does a simple test based on depth.
|
||||
bool SortedVisibleSpriteList::sv_compare(vissprite_t *a, vissprite_t *b)
|
||||
void VisibleSpriteList::Sort(bool compare2d)
|
||||
{
|
||||
return a->idepth > b->idepth;
|
||||
}
|
||||
size_t first = StartIndices.Size() == 0 ? 0 : StartIndices.Last();
|
||||
size_t count = Sprites.Size() - first;
|
||||
|
||||
// This is an alternate version, for when one or more voxel is in view.
|
||||
// It does a 2D distance test based on whichever one is furthest from
|
||||
// the viewpoint.
|
||||
bool SortedVisibleSpriteList::sv_compare2d(vissprite_t *a, vissprite_t *b)
|
||||
{
|
||||
return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared();
|
||||
}
|
||||
SortedSprites.Resize(count);
|
||||
|
||||
void SortedVisibleSpriteList::Sort(bool(*compare)(vissprite_t *, vissprite_t *), size_t first)
|
||||
{
|
||||
int i;
|
||||
vissprite_t **spr;
|
||||
|
||||
vsprcount = int(VisibleSpriteList::vissprite_p - &VisibleSpriteList::vissprites[first]);
|
||||
|
||||
if (vsprcount == 0)
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (spritesortersize < VisibleSpriteList::MaxVisSprites)
|
||||
{
|
||||
if (spritesorter != nullptr)
|
||||
delete[] spritesorter;
|
||||
spritesorter = new vissprite_t *[VisibleSpriteList::MaxVisSprites];
|
||||
spritesortersize = VisibleSpriteList::MaxVisSprites;
|
||||
}
|
||||
|
||||
if (!(i_compatflags & COMPATF_SPRITESORT))
|
||||
{
|
||||
for (i = 0, spr = VisibleSpriteList::firstvissprite; i < vsprcount; i++, spr++)
|
||||
{
|
||||
spritesorter[i] = *spr;
|
||||
}
|
||||
for (size_t i = 0; i < count; i++)
|
||||
SortedSprites[i] = Sprites[first + i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the compatibility option is on sprites of equal distance need to
|
||||
// be sorted in inverse order. This is most easily achieved by
|
||||
// filling the sort array backwards before the sort.
|
||||
for (i = 0, spr = VisibleSpriteList::firstvissprite + vsprcount - 1; i < vsprcount; i++, spr--)
|
||||
for (size_t i = 0; i < count; i++)
|
||||
SortedSprites[i] = Sprites[first + count - i - 1];
|
||||
}
|
||||
|
||||
if (compare2d)
|
||||
{
|
||||
spritesorter[i] = *spr;
|
||||
}
|
||||
}
|
||||
// This is an alternate version, for when one or more voxel is in view.
|
||||
// It does a 2D distance test based on whichever one is furthest from
|
||||
// the viewpoint.
|
||||
|
||||
std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare);
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](vissprite_t *a, vissprite_t *b) -> bool
|
||||
{
|
||||
return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the standard version, which does a simple test based on depth.
|
||||
|
||||
vissprite_t **SortedVisibleSpriteList::spritesorter;
|
||||
int SortedVisibleSpriteList::spritesortersize = 0;
|
||||
int SortedVisibleSpriteList::vsprcount;
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](vissprite_t *a, vissprite_t *b) -> bool
|
||||
{
|
||||
return a->idepth > b->idepth;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,33 +21,18 @@ namespace swrenderer
|
|||
class VisibleSpriteList
|
||||
{
|
||||
public:
|
||||
static int MaxVisSprites;
|
||||
static vissprite_t **vissprites;
|
||||
static vissprite_t **firstvissprite;
|
||||
static vissprite_t **vissprite_p;
|
||||
static VisibleSpriteList *Instance();
|
||||
|
||||
static void Deinit();
|
||||
static void Clear();
|
||||
static vissprite_t *Add();
|
||||
void Clear();
|
||||
void PushPortal();
|
||||
void PopPortal();
|
||||
void Push(vissprite_t *sprite);
|
||||
void Sort(bool compare2d);
|
||||
|
||||
TArray<vissprite_t *> SortedSprites;
|
||||
|
||||
private:
|
||||
static vissprite_t **lastvissprite;
|
||||
};
|
||||
|
||||
class SortedVisibleSpriteList
|
||||
{
|
||||
public:
|
||||
static void Deinit();
|
||||
|
||||
static void Sort(bool(*compare)(vissprite_t *, vissprite_t *), size_t first);
|
||||
|
||||
static bool sv_compare(vissprite_t *a, vissprite_t *b);
|
||||
static bool sv_compare2d(vissprite_t *a, vissprite_t *b);
|
||||
|
||||
static vissprite_t **spritesorter;
|
||||
static int vsprcount;
|
||||
|
||||
private:
|
||||
static int spritesortersize;
|
||||
TArray<vissprite_t *> Sprites;
|
||||
TArray<size_t> StartIndices;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "swrenderer/scene/r_scene.h"
|
||||
#include "swrenderer/scene/r_viewport.h"
|
||||
#include "swrenderer/scene/r_light.h"
|
||||
#include "swrenderer/r_memory.h"
|
||||
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
|
||||
|
||||
|
@ -104,7 +105,7 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
vissprite_t *vis = VisibleSpriteList::Add();
|
||||
vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
|
||||
|
||||
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
vis->xscale = FLOAT2FIXED(xscale);
|
||||
|
@ -157,8 +158,6 @@ namespace swrenderer
|
|||
vis->bWallSprite = false;
|
||||
vis->foggy = foggy;
|
||||
|
||||
RenderTranslucentPass::DrewAVoxel = true;
|
||||
|
||||
// The software renderer cannot invert the source without inverting the overlay
|
||||
// too. That means if the source is inverted, we need to do the reverse of what
|
||||
// the invert overlay flag says to do.
|
||||
|
@ -223,6 +222,9 @@ namespace swrenderer
|
|||
vis->Style.BaseColormap = mybasecolormap;
|
||||
}
|
||||
}
|
||||
|
||||
VisibleSpriteList::Instance()->Push(vis);
|
||||
RenderTranslucentPass::DrewAVoxel = true;
|
||||
}
|
||||
|
||||
void RenderVoxel::Render(vissprite_t *sprite, int minZ, int maxZ, short *cliptop, short *clipbottom)
|
||||
|
|
|
@ -72,7 +72,6 @@ namespace swrenderer
|
|||
DAngle ang = thing->Angles.Yaw + 90;
|
||||
double angcos = ang.Cos();
|
||||
double angsin = ang.Sin();
|
||||
vissprite_t *vis;
|
||||
|
||||
// Determine left and right edges of sprite. The sprite's angle is its normal,
|
||||
// so the edges are 90 degrees each side of it.
|
||||
|
@ -105,7 +104,7 @@ namespace swrenderer
|
|||
gzt = pos.Z + scale.Y * scaled_to;
|
||||
gzb = pos.Z + scale.Y * scaled_bo;
|
||||
|
||||
vis = VisibleSpriteList::Add();
|
||||
vissprite_t *vis = RenderMemory::NewObject<vissprite_t>();
|
||||
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
vis->x1 = wallc.sx1 < renderportal->WindowLeft ? renderportal->WindowLeft : wallc.sx1;
|
||||
vis->x2 = wallc.sx2 >= renderportal->WindowRight ? renderportal->WindowRight : wallc.sx2;
|
||||
|
@ -137,6 +136,8 @@ namespace swrenderer
|
|||
vis->Style.BaseColormap = basecolormap;
|
||||
vis->wallc = wallc;
|
||||
vis->foggy = foggy;
|
||||
|
||||
VisibleSpriteList::Instance()->Push(vis);
|
||||
}
|
||||
|
||||
void RenderWallSprite::Render(vissprite_t *spr, const short *mfloorclip, const short *mceilingclip)
|
||||
|
|
Loading…
Reference in a new issue