- set up engine portals for SW.

Also moving more code to _polymost.cpp which is only needed for ad-hoc lookup of portals with a client side implementation of a two-layer renderer.
This commit is contained in:
Christoph Oelckers 2021-03-21 17:04:06 +01:00
parent a36377111c
commit 09a9e14feb
8 changed files with 407 additions and 324 deletions

View file

@ -40,7 +40,8 @@ enum
PORTAL_SECTOR_CEILING_REFLECT = 4,
PORTAL_WALL_VIEW = 5,
PORTAL_WALL_MIRROR = 6,
PORTAL_SECTOR_GEOMETRY = 7,
PORTAL_WALL_TO_SPRITE = 7,
PORTAL_SECTOR_GEOMETRY = 8,
};
@ -119,7 +120,7 @@ struct walltype
float xpan_, ypan_;
angle_t clipangle;
uint8_t portalflags;
uint8_t portalnum;
uint16_t portalnum;
int xpan() const { return int(xpan_); }
int ypan() const { return int(ypan_); }

View file

@ -87,7 +87,7 @@ void InitMirrors(void)
{
mirrorcnt++;
wall[i].portalflags = PORTAL_WALL_VIEW;
wall[i].portalnum = portalAdd(PORTAL_WALL_VIEW, j);
wall[i].portalnum = j;
}
}
continue;

View file

@ -1,5 +1,350 @@
BEGIN_SW_NS
short GlobStackSect[2];
void
GetUpperLowerSector(short match, int x, int y, short* upper, short* lower)
{
int i;
short sectorlist[16];
int sln = 0;
int SpriteNum;
SPRITEp sp;
// keep a list of the last stacked sectors the view was in and
// check those fisrt
sln = 0;
for (i = 0; i < (int)SIZ(GlobStackSect); i++)
{
// will not hurt if GlobStackSect is invalid - inside checks for this
if (inside(x, y, GlobStackSect[i]) == 1)
{
bool found = false;
SectIterator it(GlobStackSect[i]);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
sectorlist[sln] = GlobStackSect[i];
sln++;
}
}
// didn't find it yet so test ALL sectors
if (sln < 2)
{
sln = 0;
for (i = numsectors - 1; i >= 0; i--)
{
if (inside(x, y, (short)i) == 1)
{
bool found = false;
SectIterator it(i);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
if (sln < (int)SIZ(GlobStackSect))
GlobStackSect[sln] = i;
if (sln < (int)SIZ(sectorlist))
sectorlist[sln] = i;
sln++;
}
}
}
// might not find ANYTHING if not tagged right
if (sln == 0)
{
*upper = -1;
*lower = -1;
return;
}
// Map rooms have NOT been dragged on top of each other
else if (sln == 1)
{
*lower = sectorlist[0];
*upper = sectorlist[0];
return;
}
// Map rooms HAVE been dragged on top of each other
// inside will somtimes find that you are in two different sectors if the x,y
// is exactly on a sector line.
else if (sln > 2)
{
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
MONO_PRINT(ds);
// try again moving the x,y pos around until you only get two sectors
GetUpperLowerSector(match, x - 1, y, upper, lower);
}
if (sln == 2)
{
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
{
// swap
// make sectorlist[0] the LOW sector
short hold;
hold = sectorlist[0];
sectorlist[0] = sectorlist[1];
sectorlist[1] = hold;
}
*lower = sectorlist[0];
*upper = sectorlist[1];
}
}
bool
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int pix_diff;
int newz;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_FLOOR)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = upper;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move lower levels ceilings up for the correct view
if (sp->hitag == VIEW_LEVEL2)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].floorz;
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
sector[sp->sectnum].floorz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].floorpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC + 1;
sector[sp->sectnum].floorheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
return true;
}
bool
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int newz;
int pix_diff;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_CEILING)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = lower;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_CEILING);
// move ceiling multiple of 128 so that the wall tile will line up
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move upper levels floors down for the correct view
if (sp->hitag == VIEW_LEVEL1)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
sector[sp->sectnum].ceilingz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].ceilingpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC + 1;
sector[sp->sectnum].ceilingheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
return true;
}
short
ViewSectorInScene(short cursectnum, short level)
{
int i;
SPRITEp sp;
short match;
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == level)
{
if (cursectnum == sp->sectnum)
{
// ignore case if sprite is pointing up
if (sp->ang == 1536)
continue;
// only gets to here is sprite is pointing down
// found a potential match
match = sp->lotag;
if (!PicInView(FAF_MIRROR_PIC, true))
return -1;
return match;
}
}
}
return -1;
}
void
DrawOverlapRoom(int tx, int ty, int tz, fixed_t tq16ang, fixed_t tq16horiz, short tsectnum)
{

View file

@ -1416,6 +1416,33 @@ void DoPlayerDiveMeter(PLAYERp pp);
void polymost_drawscreen(PLAYERp pp, int tx, int ty, int tz, binangle tang, fixedhoriz thoriz, int tsectnum);
void UpdateWallPortalState()
{
// This is too obtuse to be maintained statically, but with 8 mirrors at most easy to be kept up to date.
for (int i = 0; i < MAXMIRRORS; i++)
{
auto wal = &wall[mirror[i].mirrorwall];
wal->portalflags = 0;
wal->portalnum = 0;
if (!mirror[i].ismagic)
{
// a simple mirror
wal->portalflags = PORTAL_WALL_MIRROR;
}
else
{
auto sp = &sprite[mirror[i].camera];
if (!TEST_BOOL1(sp))
{
wal->portalflags = PORTAL_WALL_TO_SPRITE;
wal->portalnum = mirror[i].camera;
}
}
}
}
void
drawscreen(PLAYERp pp, double smoothratio)
{
@ -1568,6 +1595,7 @@ drawscreen(PLAYERp pp, double smoothratio)
}
else
{
UpdateWallPortalState();
render_drawrooms(pp->SpriteP, { tx, ty, tz }, tsectnum, tang.asq16(), thoriz.asq16(), trotscrnang.asbuildf());
}

View file

@ -407,6 +407,7 @@ void InitLevel(MapRecord *maprec)
PlaceActorsOnTracks();
PostSetupSectorObject();
SetupMirrorTiles();
SetupSectorPortals();
initlava();
// reset NewGame

View file

@ -2135,6 +2135,7 @@ void DrawOverlapRoom(int tx,int ty,int tz,fixed_t tq16ang,fixed_t tq16horiz,shor
void SetupMirrorTiles(void); // rooms.c
bool FAF_Sector(short sectnum); // rooms.c
int GetZadjustment(short sectnum,short hitag); // rooms.c
void SetupSectorPortals();
void InitSetup(void); // setup.c

View file

@ -354,7 +354,7 @@ void JS_InitMirrors(void)
if (sp->hitag == MIRROR_CAM && sp->lotag == wall[i].hitag)
{
mirror[mirrorcnt].camera = ii;
// Set up camera varialbes
// Set up camera variables
SP_TAG5(sp) = sp->ang; // Set current angle to
// sprite angle
Found_Cam = true;
@ -370,7 +370,7 @@ void JS_InitMirrors(void)
if (sp->hitag == MIRROR_CAM && sp->lotag == wall[i].hitag)
{
mirror[mirrorcnt].camera = ii;
// Set up camera varialbes
// Set up camera variables
SP_TAG5(sp) = sp->ang; // Set current angle to
// sprite angle
Found_Cam = true;
@ -536,6 +536,7 @@ int lastcamclock;
// views
short camplayerview = 1; // Don't show yourself!
// Hack job alert!
// Mirrors and cameras are maintained in the same data structure, but for hardware rendering they cannot be interleaved.
// So this function replicates JS_DrawMirrors to only process the camera textures but not change any global state.

View file

@ -678,344 +678,50 @@ SetupMirrorTiles(void)
}
}
short GlobStackSect[2];
void
GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
void SetupSectorPortals()
{
int i;
short sectorlist[16];
int sln = 0;
int SpriteNum;
SPRITEp sp;
// keep a list of the last stacked sectors the view was in and
// check those fisrt
sln = 0;
for (i = 0; i < (int)SIZ(GlobStackSect); i++)
{
// will not hurt if GlobStackSect is invalid - inside checks for this
if (inside(x, y, GlobStackSect[i]) == 1)
{
bool found = false;
SectIterator it(GlobStackSect[i]);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
sectorlist[sln] = GlobStackSect[i];
sln++;
}
}
// didn't find it yet so test ALL sectors
if (sln < 2)
{
sln = 0;
for (i = numsectors - 1; i >= 0; i--)
{
if (inside(x, y, (short) i) == 1)
{
bool found = false;
SectIterator it(i);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
if (sln < (int)SIZ(GlobStackSect))
GlobStackSect[sln] = i;
if (sln < (int)SIZ(sectorlist))
sectorlist[sln] = i;
sln++;
}
}
}
// might not find ANYTHING if not tagged right
if (sln == 0)
{
*upper = -1;
*lower = -1;
return;
}
// Map rooms have NOT been dragged on top of each other
else if (sln == 1)
{
*lower = sectorlist[0];
*upper = sectorlist[0];
return;
}
// Map rooms HAVE been dragged on top of each other
// inside will somtimes find that you are in two different sectors if the x,y
// is exactly on a sector line.
else if (sln > 2)
{
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
MONO_PRINT(ds);
// try again moving the x,y pos around until you only get two sectors
GetUpperLowerSector(match, x - 1, y, upper, lower);
}
if (sln == 2)
{
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
{
// swap
// make sectorlist[0] the LOW sector
short hold;
hold = sectorlist[0];
sectorlist[0] = sectorlist[1];
sectorlist[1] = hold;
}
*lower = sectorlist[0];
*upper = sectorlist[1];
}
}
bool
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int pix_diff;
int newz;
save.zcount = 0;
TArray<int> foundf, foundc;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_FLOOR)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = upper;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move lower levels ceilings up for the correct view
if (sp->hitag == VIEW_LEVEL2)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].floorz;
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
sector[sp->sectnum].floorz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].floorpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1;
sector[sp->sectnum].floorheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
return true;
}
bool
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int newz;
int pix_diff;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
auto sp = &sprite[i];
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
if (sp->hitag == VIEW_THRU_CEILING) foundc.Push(i);
if (sp->hitag == VIEW_THRU_FLOOR) foundf.Push(i);
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
portalClear();
while (foundf.Size())
{
sp = &sprite[i];
if (sp->lotag == match)
auto spf = &sprite[foundf[0]];
auto cindex = foundc.FindEx([=](int i) { return spf->lotag == sprite[i].lotag; });
if (cindex != foundc.Size())
{
// determine x,y position
if (sp->hitag == VIEW_THRU_CEILING)
{
short upper, lower;
auto spc = &sprite[foundf[cindex]];
sector[spf->sectnum].portalflags = PORTAL_SECTOR_FLOOR;
sector[spf->sectnum].portalnum = portalAdd(PORTAL_SECTOR_FLOOR, spc->sectnum, spc->x - spf->x, spc->y - spf->y, 0);
*x = sp->x + xoff;
*y = sp->y + yoff;
sector[spc->sectnum].portalflags = PORTAL_SECTOR_CEILING;
sector[spc->sectnum].portalnum = portalAdd(PORTAL_SECTOR_CEILING, spf->sectnum, spf->x - spc->x, spf->y - spc->y, 0);
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = lower;
break;
}
//Printf("Portal with tag %d\n", sprite[foundf[0]].lotag);
foundf.Delete(0);
foundc.Delete(cindex);
}
else
{
//Printf("Floor portal %d without partner\n", sprite[foundf[0]].lotag);
foundf.Delete(0);
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_CEILING);
// move ceiling multiple of 128 so that the wall tile will line up
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
for (auto c : foundc)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move upper levels floors down for the correct view
if (sp->hitag == VIEW_LEVEL1)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
sector[sp->sectnum].ceilingz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].ceilingpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1;
sector[sp->sectnum].ceilingheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
//Printf("Ceiling portal %d without partner\n", sprite[c].lotag);
}
return true;
}
short
ViewSectorInScene(short cursectnum, short level)
{
int i;
SPRITEp sp;
short match;
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == level)
{
if (cursectnum == sp->sectnum)
{
// ignore case if sprite is pointing up
if (sp->ang == 1536)
continue;
// only gets to here is sprite is pointing down
// found a potential match
match = sp->lotag;
if (!PicInView(FAF_MIRROR_PIC, true))
return -1;
return match;
}
}
}
return -1;
}
END_SW_NS