Code refactoring to turn portal struct into a more generalized shape.

Split portal-related code to its own source files.
Most of the 2-line-specific setup has been moved to the function which adds a 2-line case. The portals should render as they used to so far, anyway.
This commit is contained in:
Nev3r 2019-06-01 13:07:23 +02:00
parent ec0719f74f
commit df0a40b3c2
10 changed files with 273 additions and 190 deletions

View File

@ -123,6 +123,7 @@ set(SRB2_CORE_RENDER_SOURCES
r_sky.c
r_splats.c
r_things.c
r_portal.c
r_bsp.h
r_data.h
@ -136,6 +137,7 @@ set(SRB2_CORE_RENDER_SOURCES
r_splats.h
r_state.h
r_things.h
r_portal.h
)
set(SRB2_CORE_GAME_SOURCES

View File

@ -455,6 +455,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_sky.o \
$(OBJDIR)/r_splats.o \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \

View File

@ -26,7 +26,6 @@ side_t *sidedef;
line_t *linedef;
sector_t *frontsector;
sector_t *backsector;
boolean portalline; // is curline a portal seg?
// very ugly realloc() of drawsegs at run-time, I upped it to 512
// instead of 256.. and someone managed to send me a level with
@ -459,7 +458,7 @@ static void R_AddLine(seg_t *line)
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
if (line2 >= 0) // found it!
{
R_AddPortal(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
//return; // Don't fill in that space now!
goto clipsolid;
}

View File

@ -38,7 +38,6 @@ void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum);
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2);
#ifdef POLYOBJECTS
void R_SortPolyObjects(subsector_t *sub);

View File

@ -30,6 +30,7 @@
#include "p_spec.h" // skyboxmo
#include "z_zone.h"
#include "m_random.h" // quake camera shake
#include "r_portal.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -70,32 +71,6 @@ boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, f
sector_t *viewsector;
player_t *viewplayer;
// PORTALS!
// You can thank and/or curse JTE for these.
UINT8 portalrender;
sector_t *portalcullsector;
typedef struct portal_pair
{
INT32 line1;
INT32 line2;
UINT8 pass;
struct portal_pair *next;
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
angle_t viewangle;
INT32 start;
INT32 end;
INT16 *ceilingclip;
INT16 *floorclip;
fixed_t *frontscale;
} portal_pair;
portal_pair *portal_base, *portal_cap;
line_t *portalclipline;
INT32 portalclipstart, portalclipend;
//
// precalculated math tables
//
@ -1010,17 +985,8 @@ void R_SkyboxFrame(player_t *player)
R_SetupFreelook();
}
#define ANGLED_PORTALS
static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
static void R_PortalFrame(portal_t *portal)
{
vertex_t dest_c, start_c;
#ifdef ANGLED_PORTALS
// delta angle
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
#endif
//R_SetupFrame(player, false);
viewx = portal->viewx;
viewy = portal->viewy;
viewz = portal->viewz;
@ -1029,93 +995,18 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
portalcullsector = dest->frontsector;
viewsector = dest->frontsector;
portalclipline = dest;
portalclipstart = portal->start;
portalclipend = portal->end;
// Offset the portal view by the linedef centers
// looking glass center
start_c.x = (start->v1->x + start->v2->x) / 2;
start_c.y = (start->v1->y + start->v2->y) / 2;
// other side center
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
// Heights!
viewz += dest->frontsector->floorheight - start->frontsector->floorheight;
// calculate the difference in position and rotation!
#ifdef ANGLED_PORTALS
if (dangle == 0)
#endif
{ // the entrance goes straight opposite the exit, so we just need to mess with the offset.
viewx += dest_c.x - start_c.x;
viewy += dest_c.y - start_c.y;
return;
}
#ifdef ANGLED_PORTALS
viewangle += dangle;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
//CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS);
// ????
if (portal->clipline != -1)
{
fixed_t disttopoint;
angle_t angtopoint;
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
angtopoint += dangle;
viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
}
#endif
}
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
{
portal_pair *portal = Z_Malloc(sizeof(portal_pair), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1), PU_LEVEL, NULL);
portal->line1 = line1;
portal->line2 = line2;
portal->pass = portalrender+1;
portal->next = NULL;
R_PortalStoreClipValues(x1, x2, ceilingclipsave, floorclipsave, frontscalesave);
portal->ceilingclip = ceilingclipsave;
portal->floorclip = floorclipsave;
portal->frontscale = frontscalesave;
portal->start = x1;
portal->end = x2;
portalline = true; // this tells R_StoreWallRange that curline is a portal seg
portal->viewx = viewx;
portal->viewy = viewy;
portal->viewz = viewz;
portal->viewangle = viewangle;
if (!portal_base)
{
portal_base = portal;
portal_cap = portal;
portalclipline = &lines[portal->clipline];
viewsector = portalcullsector = portalclipline->frontsector;
}
else
{
portal_cap->next = portal;
portal_cap = portal;
portalclipline = NULL;
viewsector = portalcullsector = R_PointInSubsector(viewx, viewy)->sector;
}
}
@ -1131,7 +1022,7 @@ void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
void R_RenderPlayerView(player_t *player)
{
portal_pair *portal;
portal_t *portal;
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1
@ -1148,8 +1039,7 @@ void R_RenderPlayerView(player_t *player)
else
skyVisible = skyVisible1;
portalrender = 0;
portal_base = portal_cap = NULL;
Portal_InitList();
if (skybox && skyVisible)
{
@ -1206,35 +1096,37 @@ void R_RenderPlayerView(player_t *player)
#endif
//profile stuff ---------------------------------------------------------
// PORTAL RENDERING
for(portal = portal_base; portal; portal = portal_base)
// Portal rendering. Hijacks the BSP traversal.
if (portal_base)
{
// render the portal
CONS_Debug(DBG_RENDER, "Rendering portal from line %d to %d\n", portal->line1, portal->line2);
portalrender = portal->pass;
for(portal = portal_base; portal; portal = portal_base)
{
portalrender = portal->pass; // Recursiveness depth.
R_PortalFrame(&lines[portal->line1], &lines[portal->line2], portal);
// Apply the viewpoint stored for the portal.
R_PortalFrame(portal);
R_PortalClearClipSegs(portal->start, portal->end);
// Hack in the clipsegs to delimit the starting
// clipping for sprites and possibly other similar
// future items.
R_PortalClearClipSegs(portal->start, portal->end);
R_PortalRestoreClipValues(portal->start, portal->end, portal->ceilingclip, portal->floorclip, portal->frontscale);
// Hack in the top/bottom clip values for the window
// that were previously stored.
Portal_ClipApply(portal);
validcount++;
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
//R_DrawPlanes();
//R_DrawMasked();
Portal_Remove(portal);
validcount++;
}
// okay done. free it.
portalcullsector = NULL; // Just in case...
portal_base = portal->next;
Z_Free(portal->ceilingclip);
Z_Free(portal->floorclip);
Z_Free(portal->frontscale);
Z_Free(portal);
}
// END PORTAL RENDERING
R_DrawPlanes();
#ifdef FLOORSPLATS

View File

@ -112,50 +112,6 @@ void R_InitPlanes(void)
// FIXME: unused
}
// R_PortalStoreClipValues
// Saves clipping values for later. -Red
void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale)
{
INT32 i;
for (i = 0; i < end-start; i++)
{
*ceil = ceilingclip[start+i];
ceil++;
*floor = floorclip[start+i];
floor++;
*scale = frontscale[start+i];
scale++;
}
}
// R_PortalRestoreClipValues
// Inverse of the above. Restores the old value!
void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale)
{
INT32 i;
for (i = 0; i < end-start; i++)
{
ceilingclip[start+i] = *ceil;
ceil++;
floorclip[start+i] = *floor;
floor++;
frontscale[start+i] = *scale;
scale++;
}
// HACKS FOLLOW
for (i = 0; i < start; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
for (i = end; i < vid.width; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
}
//
// R_MapPlane
//

View File

@ -72,8 +72,6 @@ extern fixed_t *yslope;
extern lighttable_t **planezlight;
void R_InitPlanes(void);
void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale);
void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale);
void R_ClearPlanes(void);
void R_MapPlane(INT32 y, INT32 x1, INT32 x2);

187
src/r_portal.c Normal file
View File

@ -0,0 +1,187 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_portal.c
/// \brief Software renderer portals.
#include "r_portal.h"
#include "r_plane.h"
#include "r_main.h" // viewheight, viewwidth
#include "z_zone.h"
UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */
sector_t *portalcullsector;
// Linked list for portals.
portal_t *portal_base, *portal_cap;
line_t *portalclipline;
INT32 portalclipstart, portalclipend;
boolean portalline; // is curline a portal seg?
void Portal_InitList (void)
{
portalrender = 0;
portal_base = portal_cap = NULL;
}
/** Store the clipping window for a portal in its given range.
*
* The window is copied from the current window at the time
* the function is called, so it is useful for converting one-sided
* lines into portals.
*/
void Portal_ClipStoreFromRange (portal_t* portal)
{
INT32 start = portal->start;
INT32 end = portal->end;
INT16 *ceil = portal->ceilingclip;
INT16 *floor = portal->floorclip;
fixed_t *scale = portal->frontscale;
INT32 i;
for (i = 0; i < end-start; i++)
{
*ceil = ceilingclip[start+i];
ceil++;
*floor = floorclip[start+i];
floor++;
*scale = frontscale[start+i];
scale++;
}
}
/** Apply the clipping window from a portal.
*/
void Portal_ClipApply (const portal_t* portal)
{
INT32 i;
INT32 start = portal->start;
INT32 end = portal->end;
INT16 *ceil = portal->ceilingclip;
INT16 *floor = portal->floorclip;
fixed_t *scale = portal->frontscale;
for (i = 0; i < end-start; i++)
{
ceilingclip[start+i] = *ceil;
ceil++;
floorclip[start+i] = *floor;
floor++;
frontscale[start+i] = *scale;
scale++;
}
// HACKS FOLLOW
for (i = 0; i < start; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
for (i = end; i < vid.width; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
}
portal_t* Portal_Add (const INT16 x1, const INT16 x2)
{
portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1), PU_LEVEL, NULL);
// Linked list.
if (!portal_base)
{
portal_base = portal;
portal_cap = portal;
}
else
{
portal_cap->next = portal;
portal_cap = portal;
}
portal->next = NULL;
// Store clipping values so they can be restored once the portal is rendered.
portal->ceilingclip = ceilingclipsave;
portal->floorclip = floorclipsave;
portal->frontscale = frontscalesave;
portal->start = x1;
portal->end = x2;
// Increase recursion level.
portal->pass = portalrender+1;
return portal;
}
void Portal_Remove (portal_t* portal)
{
portal_base = portal->next;
Z_Free(portal->ceilingclip);
Z_Free(portal->floorclip);
Z_Free(portal->frontscale);
Z_Free(portal);
}
/** Creates a portal out of two lines and a determined screen range.
*
* line1 determines the entrance, and line2 the exit.
* x1 and x2 determine the screen's column bounds.
* The view's offset from the entry line center is obtained,
* and then rotated&translated to the exit line's center.
* When the portal renders, it will create the illusion of
* the two lines being seamed together.
*/
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2)
{
portal_t* portal = Portal_Add(x1, x2);
// Offset the portal view by the linedef centers
line_t* start = &lines[line1];
line_t* dest = &lines[line2];
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
fixed_t disttopoint;
angle_t angtopoint;
vertex_t dest_c, start_c;
// looking glass center
start_c.x = (start->v1->x + start->v2->x) / 2;
start_c.y = (start->v1->y + start->v2->y) / 2;
// other side center
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
angtopoint += dangle;
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
portal->clipline = line2;
Portal_ClipStoreFromRange(portal);
portalline = true; // this tells R_StoreWallRange that curline is a portal seg
}

49
src/r_portal.h Normal file
View File

@ -0,0 +1,49 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_portal.h
/// \brief Software renderer portal struct, functions, linked list extern.
#include "r_data.h"
/** Portal structure.
*/
typedef struct portal_s
{
struct portal_s *next;
// Viewport.
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
angle_t viewangle;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */
INT32 clipline; /**< Optional clipline for line-based portals. */
// Clipping information.
INT32 start; /**< First horizontal pixel coordinate to draw at. */
INT32 end; /**< Last horizontal pixel coordinate to draw at. */
INT16 *ceilingclip; /**< Temporary screen top clipping array. */
INT16 *floorclip; /**< Temporary screen bottom clipping array. */
fixed_t *frontscale;/**< Temporary screen bottom clipping array. */
} portal_t;
extern portal_t* portal_base;
extern portal_t* portal_cap;
extern UINT8 portalrender;
void Portal_InitList (void);
void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_ClipStoreFromRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);

View File

@ -1249,7 +1249,7 @@ static void R_ProjectSprite(mobj_t *thing)
}
// PORTAL SPRITE CLIPPING
if (portalrender)
if (portalrender && portalclipline)
{
if (x2 < portalclipstart || x1 > portalclipend)
return;
@ -1517,7 +1517,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
return;
// PORTAL SPRITE CLIPPING
if (portalrender)
if (portalrender && portalclipline)
{
if (x2 < portalclipstart || x1 > portalclipend)
return;