mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-24 21:31:46 +00:00
Implement Eternity Engine's plane portal and horizon portal types
This commit is contained in:
parent
74ea880ca0
commit
6d812b4a43
10 changed files with 194 additions and 61 deletions
|
@ -1117,8 +1117,6 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
INT32 gl_toptexture = 0, gl_bottomtexture = 0;
|
||||
fixed_t texturevpeg;
|
||||
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
|
||||
SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight)
|
||||
SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight)
|
||||
|
||||
|
@ -2339,6 +2337,7 @@ static void HWR_AddLine(seg_t * line)
|
|||
#endif
|
||||
|
||||
gl_backsector = line->backsector;
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
|
||||
#ifdef NEWCLIP
|
||||
if (!line->backsector)
|
||||
|
@ -2347,8 +2346,6 @@ static void HWR_AddLine(seg_t * line)
|
|||
}
|
||||
else
|
||||
{
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
|
||||
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
|
||||
|
||||
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum
|
||||
|
|
30
src/p_spec.c
30
src/p_spec.c
|
@ -6227,6 +6227,9 @@ static boolean P_IsSectorPortalValid(sectorportal_t *secportal)
|
|||
return secportal->mobj && !P_MobjWasRemoved(secportal->mobj);
|
||||
case SECPORTAL_SKYBOX:
|
||||
return skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0]);
|
||||
case SECPORTAL_PLANE:
|
||||
case SECPORTAL_HORIZON:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -6525,6 +6528,23 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
ceiling = plane_type == TMP_CEILING;
|
||||
}
|
||||
|
||||
// Eternity's floor and horizon portal types
|
||||
if (portal_type == TMSECPORTAL_PLANE || portal_type == TMSECPORTAL_HORIZON)
|
||||
{
|
||||
secportaltype_e type = portal_type == TMSECPORTAL_HORIZON ? SECPORTAL_HORIZON : SECPORTAL_PLANE;
|
||||
if (floor)
|
||||
{
|
||||
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(lines[i].frontsector);
|
||||
floorportal->type = type;
|
||||
}
|
||||
if (ceiling)
|
||||
{
|
||||
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(lines[i].frontsector);
|
||||
ceilportal->type = type;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
INT32 s1 = -1;
|
||||
|
||||
TAG_ITER_SECTORS(target_sector_tag, s1) // Target sector tag
|
||||
|
@ -6532,7 +6552,7 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
sector_t *target_sector = §ors[s1];
|
||||
|
||||
// Line portal
|
||||
if (portal_type == 0)
|
||||
if (portal_type == TMSECPORTAL_NORMAL)
|
||||
{
|
||||
INT32 linenum = -1;
|
||||
TAG_ITER_LINES(misc, linenum)
|
||||
|
@ -6561,7 +6581,7 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
}
|
||||
}
|
||||
// Skybox portal
|
||||
else if (portal_type == 2)
|
||||
else if (portal_type == TMSECPORTAL_SKYBOX)
|
||||
{
|
||||
if (floor)
|
||||
{
|
||||
|
@ -6575,7 +6595,7 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
}
|
||||
}
|
||||
// Plane portal
|
||||
else if (portal_type == 7)
|
||||
else if (portal_type == TMSECPORTAL_SECTOR)
|
||||
{
|
||||
INT32 s2 = -1;
|
||||
TAG_ITER_SECTORS(misc, s2) // Sector tag to make a portal to
|
||||
|
@ -6596,7 +6616,7 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
}
|
||||
}
|
||||
// Use mobj as viewpoint
|
||||
else if (portal_type == 8)
|
||||
else if (portal_type == TMSECPORTAL_OBJECT)
|
||||
{
|
||||
mobj_t *mobj = P_GetMobjByTag(misc);
|
||||
if (!mobj)
|
||||
|
@ -7428,7 +7448,7 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
continue;
|
||||
|
||||
int portal_type = lines[i].args[1];
|
||||
if (portal_type != 1)
|
||||
if (portal_type != TMSECPORTAL_COPIED)
|
||||
continue;
|
||||
|
||||
int target_sector_tag = lines[i].args[0];
|
||||
|
|
15
src/p_spec.h
15
src/p_spec.h
|
@ -476,6 +476,21 @@ typedef enum
|
|||
TMB_MODULATE = 4,
|
||||
} textmapblendmodes_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TMSECPORTAL_NORMAL,
|
||||
TMSECPORTAL_COPIED,
|
||||
TMSECPORTAL_SKYBOX,
|
||||
TMSECPORTAL_PLANE,
|
||||
TMSECPORTAL_HORIZON,
|
||||
// The two portal types below are unimplemented
|
||||
TMSECPORTAL_COPY_PORTAL_TO_LINE,
|
||||
TMSECPORTAL_INTERACTIVE,
|
||||
// The two portal types below are new to SRB2
|
||||
TMSECPORTAL_SECTOR,
|
||||
TMSECPORTAL_OBJECT
|
||||
} textmapsecportaltype_t;
|
||||
|
||||
// GETSECSPECIAL (specialval, section)
|
||||
//
|
||||
// Pulls out the special # from a particular section.
|
||||
|
|
142
src/r_bsp.c
142
src/r_bsp.c
|
@ -39,6 +39,8 @@ drawseg_t *ds_p = NULL;
|
|||
boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
|
||||
boolean bothfloorssky = false; // likewise, but for floors
|
||||
|
||||
boolean horizonline = false;
|
||||
|
||||
// indicates doors closed wrt automap bugfix:
|
||||
INT32 doorclosed;
|
||||
|
||||
|
@ -456,6 +458,8 @@ static void R_AddLine(seg_t *line)
|
|||
return;
|
||||
|
||||
backsector = line->backsector;
|
||||
horizonline = line->linedef->special == HORIZONSPECIAL;
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
|
||||
// Portal line
|
||||
if (line->linedef->special == 40 && line->side == 0)
|
||||
|
@ -488,7 +492,6 @@ static void R_AddLine(seg_t *line)
|
|||
backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true);
|
||||
|
||||
doorclosed = 0;
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
|
||||
// hack to allow height changes in outdoor areas
|
||||
// This is what gets rid of the upper textures if there should be sky
|
||||
|
@ -844,6 +847,51 @@ static void R_AddPolyObjects(subsector_t *sub)
|
|||
|
||||
drawseg_t *firstseg;
|
||||
|
||||
static void R_CheckSectorLightLists(sector_t *sector, sector_t *fakeflat, INT32 *floorlightlevel, INT32 *ceilinglightlevel, extracolormap_t **floorcolormap, extracolormap_t **ceilingcolormap)
|
||||
{
|
||||
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
|
||||
if (fakeflat->ffloors)
|
||||
{
|
||||
fixed_t floorcenterz = P_GetSectorFloorZAt (fakeflat, fakeflat->soundorg.x, fakeflat->soundorg.y);
|
||||
fixed_t ceilingcenterz = P_GetSectorCeilingZAt(fakeflat, fakeflat->soundorg.x, fakeflat->soundorg.y);
|
||||
|
||||
boolean anyMoved = fakeflat->moved;
|
||||
|
||||
if (anyMoved == false)
|
||||
{
|
||||
for (ffloor_t *rover = fakeflat->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *controlSec = §ors[rover->secnum];
|
||||
|
||||
if (controlSec->moved == true)
|
||||
{
|
||||
anyMoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anyMoved == true)
|
||||
{
|
||||
fakeflat->numlights = sector->numlights = 0;
|
||||
R_Prep3DFloors(fakeflat);
|
||||
sector->lightlist = fakeflat->lightlist;
|
||||
sector->numlights = fakeflat->numlights;
|
||||
sector->moved = fakeflat->moved = false;
|
||||
}
|
||||
|
||||
INT32 light = R_GetPlaneLight(fakeflat, floorcenterz, false);
|
||||
if (fakeflat->floorlightsec == -1 && !fakeflat->floorlightabsolute)
|
||||
*floorlightlevel = max(0, min(255, *fakeflat->lightlist[light].lightlevel + fakeflat->floorlightlevel));
|
||||
*floorcolormap = *fakeflat->lightlist[light].extra_colormap;
|
||||
|
||||
light = R_GetPlaneLight(fakeflat, ceilingcenterz, false);
|
||||
if (fakeflat->ceilinglightsec == -1 && !fakeflat->ceilinglightabsolute)
|
||||
*ceilinglightlevel = max(0, min(255, *fakeflat->lightlist[light].lightlevel + fakeflat->ceilinglightlevel));
|
||||
*ceilingcolormap = *fakeflat->lightlist[light].extra_colormap;
|
||||
}
|
||||
}
|
||||
|
||||
static void R_Subsector(size_t num)
|
||||
{
|
||||
INT32 count, floorlightlevel, ceilinglightlevel, light;
|
||||
|
@ -877,43 +925,7 @@ static void R_Subsector(size_t num)
|
|||
floorcenterz = P_GetSectorFloorZAt (frontsector, frontsector->soundorg.x, frontsector->soundorg.y);
|
||||
ceilingcenterz = P_GetSectorCeilingZAt(frontsector, frontsector->soundorg.x, frontsector->soundorg.y);
|
||||
|
||||
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
|
||||
if (frontsector->ffloors)
|
||||
{
|
||||
boolean anyMoved = frontsector->moved;
|
||||
|
||||
if (anyMoved == false)
|
||||
{
|
||||
for (rover = frontsector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *controlSec = §ors[rover->secnum];
|
||||
|
||||
if (controlSec->moved == true)
|
||||
{
|
||||
anyMoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anyMoved == true)
|
||||
{
|
||||
frontsector->numlights = sub->sector->numlights = 0;
|
||||
R_Prep3DFloors(frontsector);
|
||||
sub->sector->lightlist = frontsector->lightlist;
|
||||
sub->sector->numlights = frontsector->numlights;
|
||||
sub->sector->moved = frontsector->moved = false;
|
||||
}
|
||||
|
||||
light = R_GetPlaneLight(frontsector, floorcenterz, false);
|
||||
if (frontsector->floorlightsec == -1 && !frontsector->floorlightabsolute)
|
||||
floorlightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->floorlightlevel));
|
||||
floorcolormap = *frontsector->lightlist[light].extra_colormap;
|
||||
light = R_GetPlaneLight(frontsector, ceilingcenterz, false);
|
||||
if (frontsector->ceilinglightsec == -1 && !frontsector->ceilinglightabsolute)
|
||||
ceilinglightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->ceilinglightlevel));
|
||||
ceilingcolormap = *frontsector->lightlist[light].extra_colormap;
|
||||
}
|
||||
R_CheckSectorLightLists(sub->sector, frontsector, &floorlightlevel, &ceilinglightlevel, &floorcolormap, &ceilingcolormap);
|
||||
|
||||
sub->sector->extra_colormap = frontsector->extra_colormap;
|
||||
|
||||
|
@ -1301,3 +1313,57 @@ void R_RenderBSPNode(INT32 bspnum)
|
|||
|
||||
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
|
||||
}
|
||||
|
||||
void R_RenderPortalHorizonLine(sector_t *sector)
|
||||
{
|
||||
INT32 floorlightlevel, ceilinglightlevel;
|
||||
static sector_t tempsec; // Deep water hack
|
||||
extracolormap_t *floorcolormap;
|
||||
extracolormap_t *ceilingcolormap;
|
||||
|
||||
frontsector = sector;
|
||||
backsector = NULL;
|
||||
|
||||
// Deep water/fake ceiling effect.
|
||||
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false);
|
||||
|
||||
floorcolormap = ceilingcolormap = frontsector->extra_colormap;
|
||||
|
||||
R_CheckSectorLightLists(sector, frontsector, &floorlightlevel, &ceilinglightlevel, &floorcolormap, &ceilingcolormap);
|
||||
|
||||
sector->extra_colormap = frontsector->extra_colormap;
|
||||
|
||||
if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz
|
||||
|| frontsector->floorpic == skyflatnum
|
||||
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
|
||||
{
|
||||
floorplane = R_FindPlane(frontsector, frontsector->floorheight, frontsector->floorpic, floorlightlevel,
|
||||
frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorangle, floorcolormap, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
floorplane = NULL;
|
||||
|
||||
if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz
|
||||
|| frontsector->ceilingpic == skyflatnum
|
||||
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
|
||||
{
|
||||
ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic,
|
||||
ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle,
|
||||
ceilingcolormap, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
ceilingplane = NULL;
|
||||
|
||||
numffloors = 0;
|
||||
portalline = false;
|
||||
doorclosed = 0;
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
horizonline = true;
|
||||
|
||||
firstseg = NULL;
|
||||
curline = &segs[0];
|
||||
|
||||
R_ClipSolidWallSegment(portalclipstart, portalclipend);
|
||||
|
||||
curline = NULL;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ extern drawseg_t *ds_p;
|
|||
extern boolean bothceilingssky;
|
||||
extern boolean bothfloorssky;
|
||||
|
||||
extern boolean horizonline;
|
||||
|
||||
extern INT32 doorclosed;
|
||||
|
||||
// BSP?
|
||||
|
@ -41,6 +43,7 @@ void R_ClearClipSegs(void);
|
|||
void R_PortalClearClipSegs(INT32 start, INT32 end);
|
||||
void R_ClearDrawSegs(void);
|
||||
void R_RenderBSPNode(INT32 bspnum);
|
||||
void R_RenderPortalHorizonLine(sector_t *sector);
|
||||
|
||||
void R_SortPolyObjects(subsector_t *sub);
|
||||
|
||||
|
|
12
src/r_defs.h
12
src/r_defs.h
|
@ -210,11 +210,13 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
SECPORTAL_LINE,
|
||||
SECPORTAL_OBJECT,
|
||||
SECPORTAL_SKYBOX,
|
||||
SECPORTAL_FLOOR,
|
||||
SECPORTAL_CEILING
|
||||
SECPORTAL_LINE, // Works similar to a line portal
|
||||
SECPORTAL_SKYBOX, // Uses the skybox object as the reference view
|
||||
SECPORTAL_PLANE, // Eternity Engine's plane portal type
|
||||
SECPORTAL_HORIZON, // Eternity Engine's horizon portal type
|
||||
SECPORTAL_OBJECT, // Uses an object as the reference view
|
||||
SECPORTAL_FLOOR, // Uses a sector as the reference view; the view height is aligned with the sector's floor
|
||||
SECPORTAL_CEILING // Uses a sector as the reference view; the view height is aligned with the sector's ceiling
|
||||
} secportaltype_e;
|
||||
|
||||
typedef struct sectorportal_s
|
||||
|
|
15
src/r_main.c
15
src/r_main.c
|
@ -1547,9 +1547,18 @@ void R_RenderPlayerView(player_t *player)
|
|||
Mask_Pre(&masks[nummasks - 1]);
|
||||
curdrawsegs = ds_p;
|
||||
|
||||
// Render the BSP from the new viewpoint, and clip
|
||||
// any sprites with the new clipsegs and window.
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
if (portal->is_horizon)
|
||||
{
|
||||
// If the portal is a plane or a horizon portal, then we just render a horizon line
|
||||
R_RenderPortalHorizonLine(portal->horizon_sector);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Render the BSP from the new viewpoint, and clip
|
||||
// any sprites with the new clipsegs and window.
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
}
|
||||
|
||||
Mask_Post(&masks[nummasks - 1]);
|
||||
|
||||
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "r_main.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_spec.h" // Skybox viewpoints
|
||||
#include "p_slopes.h" // P_GetSectorFloorZAt and P_GetSectorCeilingZAt
|
||||
#include "p_local.h"
|
||||
#include "z_zone.h"
|
||||
#include "r_things.h"
|
||||
|
@ -191,6 +192,8 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
|
|||
Portal_GetViewpointForLine(portal, start, dest);
|
||||
|
||||
portal->clipline = line2;
|
||||
portal->is_horizon = false;
|
||||
portal->horizon_sector = NULL;
|
||||
|
||||
Portal_ClipRange(portal);
|
||||
|
||||
|
@ -312,6 +315,8 @@ void Portal_AddSkybox (const visplane_t* plane)
|
|||
portal->viewz += viewz * -mh->skybox_scalez;
|
||||
|
||||
portal->clipline = -1;
|
||||
portal->is_horizon = false;
|
||||
portal->horizon_sector = NULL;
|
||||
}
|
||||
|
||||
/** Creates a sector portal out of a visplane.
|
||||
|
@ -337,6 +342,8 @@ void Portal_AddSectorPortal (const visplane_t* plane)
|
|||
Portal_ClipVisplane(plane, portal);
|
||||
|
||||
portal->clipline = -1;
|
||||
portal->is_horizon = false;
|
||||
portal->horizon_sector = NULL;
|
||||
|
||||
switch (secportal->type)
|
||||
{
|
||||
|
@ -354,13 +361,25 @@ void Portal_AddSectorPortal (const visplane_t* plane)
|
|||
case SECPORTAL_FLOOR:
|
||||
x = secportal->sector->soundorg.x;
|
||||
y = secportal->sector->soundorg.y;
|
||||
z = secportal->sector->floorheight;
|
||||
z = P_GetSectorFloorZAt(secportal->sector, x, y);
|
||||
angle = 0;
|
||||
break;
|
||||
case SECPORTAL_CEILING:
|
||||
x = secportal->sector->soundorg.x;
|
||||
y = secportal->sector->soundorg.y;
|
||||
z = secportal->sector->ceilingheight;
|
||||
z = P_GetSectorCeilingZAt(secportal->sector, x, y);
|
||||
angle = 0;
|
||||
break;
|
||||
case SECPORTAL_PLANE:
|
||||
case SECPORTAL_HORIZON:
|
||||
portal->is_horizon = true;
|
||||
portal->horizon_sector = plane->sector;
|
||||
x = plane->sector->soundorg.x;
|
||||
y = plane->sector->soundorg.y;
|
||||
if (secportal->type == SECPORTAL_PLANE)
|
||||
z = -viewz;
|
||||
else
|
||||
z = 0;
|
||||
angle = 0;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -30,6 +30,10 @@ typedef struct portal_s
|
|||
fixed_t viewz;
|
||||
angle_t viewangle;
|
||||
|
||||
// For horizon portals
|
||||
boolean is_horizon;
|
||||
sector_t *horizon_sector;
|
||||
|
||||
UINT8 pass; /**< Keeps track of the portal's recursion depth. */
|
||||
INT32 clipline; /**< Optional clipline for line-based portals. */
|
||||
|
||||
|
|
|
@ -1787,8 +1787,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
else
|
||||
{
|
||||
// two sided line
|
||||
bothceilingssky = bothfloorssky = false;
|
||||
|
||||
SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight)
|
||||
SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight)
|
||||
worldhigh -= viewz;
|
||||
|
@ -2334,7 +2332,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
worldtopslope >>= 4;
|
||||
worldbottomslope >>= 4;
|
||||
|
||||
if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES
|
||||
if (horizonline) { // HORIZON LINES
|
||||
topstep = bottomstep = 0;
|
||||
topfrac = bottomfrac = (centeryfrac>>4);
|
||||
topfrac++; // Prevent 1px HOM
|
||||
|
@ -2435,7 +2433,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
{
|
||||
ffloor[i].f_pos >>= 4;
|
||||
ffloor[i].f_pos_slope >>= 4;
|
||||
if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
|
||||
if (horizonline) // Horizon lines extend FOFs in contact with them too.
|
||||
{
|
||||
ffloor[i].f_step = 0;
|
||||
ffloor[i].f_frac = (centeryfrac>>4);
|
||||
|
|
Loading…
Reference in a new issue