Compare commits

...
Author SHA1 Message Date
Alug 0ac0f2bae2 forgor to remove this 2024-10-26 00:51:24 +02:00
Alug cee28c6166 refactor a bunch of crap and fix skyportals 2024-10-25 22:58:10 +02:00
Alug a6be267325 Add visplane portal creation functionality and use it to replace the skybox rendering.
https://git.do.srb2.org/STJr/SRB2/-/commit/264386f84257a47fe5480bb6300df02d039a2491
2024-10-25 22:58:05 +02:00
Alug 426740e0ac port srb2 software portal refactor 2024-10-25 22:57:43 +02:00
Alug 78c0f64135 dont pass skybox to r_setupframe
why was this even done?
neither srb2 nor v2/rr ever did this?
2024-10-25 22:57:38 +02:00
16 changed files with 673 additions and 348 deletions

No files matched your search

+1
View File
@@ -563,6 +563,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_splats.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \
+2 -2
View File
@@ -5316,7 +5316,7 @@ static void HWR_RenderPortal(gl_portal_t* portal, gl_portal_t* rootportal, const
HWR_PortalFrame(rootportal);
else // current frame is not a portal frame but the main view!
{
R_SetupFrame(player, false);
R_SetupFrame(player);
portalclipline = NULL;
}
@@ -5590,7 +5590,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
}
PS_STOP_TIMING(ps_skyboxtime);
R_SetupFrame(player, false); // This can stay false because it is only used to set viewsky in r_main.c, which isn't used here
R_SetupFrame(player); // This can stay false because it is only used to set viewsky in r_main.c, which isn't used here
framecount++; // for timedemo
HWR_RenderFrame(viewnumber, player, false);
}
+2 -6
View File
@@ -2989,13 +2989,9 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate)
savedata.lives = 0;
}
// assume the skybox is visible on level load.
skyVisible = true;
memset(skyVisiblePerPlayer, true, sizeof(skyVisiblePerPlayer));
if (loadprecip) // uglier hack
{ // to make a newly loaded level start on the second frame.
INT32 buf = gametic % TICQUEUE;
{
INT32 buf = gametic % TICQUEUE; // to make a newly loaded level start on the second frame.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
+4 -3
View File
@@ -679,16 +679,17 @@ void P_Ticker(boolean run)
for (i = 0; i <= splitscreen; i++)
{
player_t *player = &players[displayplayers[i]];
boolean isSkyVisibleForPlayer = skyVisiblePerPlayer[i];
if (!player->mo)
continue;
if (isSkyVisibleForPlayer && skyboxmo[0] && cv_skybox.value)
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
if (skybox)
{
R_SkyboxFrame(player);
}
R_SetupFrame(player, (skyboxmo[0] && cv_skybox.value));
R_SetupFrame(player);
}
}
}
+3 -2
View File
@@ -15,6 +15,7 @@
#include "g_game.h"
#include "r_local.h"
#include "r_state.h"
#include "r_portal.h" // Add seg portals
#include "r_splats.h"
#include "p_local.h" // camera
@@ -28,11 +29,11 @@ side_t *sidedef;
line_t *linedef;
sector_t *frontsector;
sector_t *backsector;
portal_pair *g_portal; // 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
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */
drawseg_t *drawsegs = NULL;
drawseg_t *ds_p = NULL;
@@ -486,7 +487,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;
}
+3 -2
View File
@@ -25,12 +25,14 @@ extern side_t *sidedef;
extern line_t *linedef;
extern sector_t *frontsector;
extern sector_t *backsector;
extern portal_pair *g_portal; // is curline a portal seg?
typedef struct portal_s portal_t;
extern portal_t *g_portal; // is curline a portal seg?
// drawsegs are allocated on the fly... see r_segs.c
extern INT32 checkcoord[12][4];
extern drawseg_t *curdrawsegs;
extern drawseg_t *drawsegs;
extern drawseg_t *ds_p;
extern INT32 doorclosed;
@@ -41,7 +43,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);
// determines when a given sector shouldn't abide by the encoremap's palette.
// no longer a static since this is used for encore in hw_main.c as well now:
+82 -179
View File
@@ -31,6 +31,7 @@
#include "p_spec.h" // skyboxmo
#include "z_zone.h"
#include "m_random.h" // quake camera shake
#include "r_portal.h"
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#include "r_fps.h" // Frame interpolation/uncapped
#include "tables.h"
@@ -61,19 +62,9 @@ fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle, viewroll;
UINT8 viewssnum;
fixed_t viewcos, viewsin;
boolean skyVisible;
boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player
sector_t *viewsector;
player_t *viewplayer;
// PORTALS!
// You can thank and/or curse JTE for these.
UINT8 portalrender;
sector_t *portalcullsector;
portal_pair *portal_base, *portal_cap;
line_t *portalclipline;
INT32 portalclipstart, portalclipend;
fixed_t rendertimefrac;
fixed_t rendertimefrac_unpaused;
fixed_t renderdeltatics;
@@ -1336,7 +1327,7 @@ void R_SkyboxFrame(player_t *player)
R_InterpolateView(R_UsingFrameInterpolation() ? (demo.playback && demo.freecam) ? rendertimefrac_unpaused : rendertimefrac : FRACUNIT, false);
}
void R_SetupFrame(player_t *player, boolean skybox)
void R_SetupFrame(player_t *player)
{
camera_t *thiscam;
boolean chasecam = false;
@@ -1399,7 +1390,7 @@ void R_SetupFrame(player_t *player, boolean skybox)
else if (thiscam && !chasecam)
thiscam->chase = false;
newview->sky = !skybox;
newview->sky = false;
if (player->awayviewtics) // cut-away view stuff
{
@@ -1481,115 +1472,49 @@ void R_SetupFrame(player_t *player, boolean skybox)
R_InterpolateView(R_UsingFrameInterpolation() ? (demo.playback && demo.freecam) ? rendertimefrac_unpaused : rendertimefrac : FRACUNIT, false);
}
#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;
viewangle = portal->viewangle;
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
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;
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(newview->angle>>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, newview->x, newview->y);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, newview->x, newview->y);
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;
g_portal = portal; // 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];
portalcullsector = portalclipline->frontsector;
viewsector = portalclipline->frontsector;
}
else
{
portal_cap->next = portal;
portal_cap = portal;
portalclipline = NULL;
portalcullsector = NULL;
viewsector = R_PointInSubsector(viewx, viewy)->sector;
}
}
static void Mask_Pre (maskcount_t* m)
{
m->drawsegs[0] = ds_p - drawsegs;
m->vissprites[0] = visspritecount;
m->viewx = viewx;
m->viewy = viewy;
m->viewz = viewz;
m->viewsector = viewsector;
}
static void Mask_Post (maskcount_t* m)
{
m->drawsegs[1] = ds_p - drawsegs;
m->vissprites[1] = visspritecount;
}
// ================
// R_RenderView
// ================
@@ -1602,9 +1527,8 @@ void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
void R_RenderPlayerView(player_t *player)
{
portal_pair *portal;
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
UINT8 i;
INT32 nummasks = 1;
maskcount_t* masks = malloc(sizeof(maskcount_t));
// if this is display player 1
if (cv_homremoval.value && player == &players[displayplayers[0]])
@@ -1629,44 +1553,7 @@ void R_RenderPlayerView(player_t *player)
}
}
// load previous saved value of skyVisible for the player
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
skyVisible = skyVisiblePerPlayer[i];
break;
}
portalrender = 0;
portal_base = portal_cap = NULL;
PS_START_TIMING(ps_skyboxtime);
if (skybox && skyVisible)
{
R_SkyboxFrame(player);
R_ClearClipSegs();
R_ClearDrawSegs();
R_ClearPlanes();
R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();
#endif
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
R_DrawPlanes();
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
R_DrawMasked();
}
PS_STOP_TIMING(ps_skyboxtime);
R_SetupFrame(player, skybox);
skyVisible = false;
R_SetupFrame(player);
framecount++;
validcount++;
@@ -1692,50 +1579,75 @@ void R_RenderPlayerView(player_t *player)
R_ClearVisibleFloorSplats();
#endif
// The head node is the last node output.
Portal_InitList();
// The head node is the last node output.
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1);
PS_STOP_TIMING(ps_bsptime);
Mask_Post(&masks[nummasks - 1]);
R_AddPrecipitationSprites();
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites();
R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime);
ps_numsprites.value.i = numvisiblesprites;
// PORTAL RENDERING
// Add skybox portals caused by sky visplanes.
if (skyboxmo[0] && cv_skybox.value)
Portal_AddSkyboxPortals();
PS_START_TIMING(ps_sw_portaltime);
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;
portal_t *portal;
R_PortalFrame(&lines[portal->line1], &lines[portal->line2], portal);
for (portal = portal_base; portal; portal = portal_base)
{
portalrender = portal->pass; // Recursiveness depth.
R_PortalClearClipSegs(portal->start, portal->end);
R_ClearFFloorClips();
R_PortalRestoreClipValues(portal->start, portal->end, portal->ceilingclip, portal->floorclip, portal->frontscale);
// Apply the viewpoint stored for the portal.
R_PortalFrame(portal);
validcount++;
// Hack in the clipsegs to delimit the starting
// clipping for sprites and possibly other similar
// future items.
R_PortalClearClipSegs(portal->start, portal->end);
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
//R_DrawPlanes();
//R_DrawMasked();
// Hack in the top/bottom clip values for the window
// that were previously stored.
Portal_ClipApply(portal);
// 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);
validcount++;
masks = realloc(masks, (++nummasks)*sizeof(maskcount_t));
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
portalskipprecipmobjs = portal->isskybox;
// 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]);
portalskipprecipmobjs = false;
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Portal_Remove(portal);
}
}
PS_STOP_TIMING(ps_sw_portaltime);
// END PORTAL RENDERING
PS_START_TIMING(ps_sw_planetime);
R_DrawPlanes();
@@ -1746,19 +1658,10 @@ void R_RenderPlayerView(player_t *player)
// draw mid texture and sprite
// And now 3D floors/sides!
PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked();
R_DrawMasked(masks, nummasks);
PS_STOP_TIMING(ps_sw_maskedtime);
// save value to skyVisiblePerPlayer
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
skyVisiblePerPlayer[i] = skyVisible;
break;
}
free(masks);
}
// =========================================================================
+1 -22
View File
@@ -107,27 +107,6 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y);
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh);
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;
// Performance stats
extern precise_t ps_prevframetime;// time when previous frame was rendered
extern ps_metric_t ps_rendercalltime;
@@ -181,8 +160,8 @@ void R_SetViewSize(void);
void R_ExecuteSetViewSize(void);
void R_SkyboxFrame(player_t *player);
void R_SetupFrame(player_t *player);
void R_SetupFrame(player_t *player, boolean skybox);
// Called by G_Drawer.
void R_RenderPlayerView(player_t *player);
+21 -59
View File
@@ -23,6 +23,8 @@
#include "r_state.h"
#include "r_splats.h" // faB(21jan):testing
#include "r_sky.h"
#include "r_portal.h"
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
@@ -39,13 +41,7 @@
// good night sweet prince
//#define SHITPLANESPARENCY
//SoM: 3/23/2000: Use Boom visplane hashing.
#define VISPLANEHASHBITS 9
#define VISPLANEHASHMASK ((1<<VISPLANEHASHBITS)-1)
// the last visplane list is outside of the hash table and is used for fof planes
#define MAXVISPLANES ((1<<VISPLANEHASHBITS)+1)
static visplane_t *visplanes[MAXVISPLANES];
visplane_t *visplanes[MAXVISPLANES];
static visplane_t *freetail;
static visplane_t **freehead = &freetail;
@@ -112,50 +108,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;
}
}
//
// Water ripple effect!!
// Needs the height of the plane, and the vertical position of the span.
@@ -307,6 +259,24 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
spanfunc();
}
void R_ClearFFloorClips (void)
{
INT32 i, p;
// opening / clipping determination
for (i = 0; i < viewwidth; i++)
{
for (p = 0; p < MAXFFLOORS; p++)
{
ffloor[p].f_clip[i] = (INT16)viewheight;
ffloor[p].c_clip[i] = -1;
}
}
numffloors = 0;
}
//
// R_ClearPlanes
// At begining of frame.
@@ -329,8 +299,6 @@ void R_ClearPlanes(void)
}
}
numffloors = 0;
for (i = 0; i < MAXVISPLANES; i++)
{
for (*freehead = visplanes[i], visplanes[i] = NULL;
@@ -665,12 +633,6 @@ static void R_DrawSkyPlane(visplane_t *pl)
INT32 x;
INT32 angle;
if (!newview->sky)
{
skyVisible = true;
return;
}
wallcolfunc = walldrawerfunc;
// use correct aspect ratio scale
+3 -2
View File
@@ -18,6 +18,7 @@
#include "r_data.h"
#include "p_polyobj.h"
//SoM: 3/23/2000: Use Boom visplane hashing.
#define VISPLANEHASHBITS 9
#define VISPLANEHASHMASK ((1<<VISPLANEHASHBITS)-1)
// the last visplane list is outside of the hash table and is used for fof planes
@@ -56,6 +57,7 @@ typedef struct visplane_s
boolean noencore;
} visplane_t;
extern visplane_t *visplanes[MAXVISPLANES];
extern visplane_t *floorplane;
extern visplane_t *ceilingplane;
@@ -75,9 +77,8 @@ 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_ClearFFloorClips (void);
void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
+317
View File
@@ -0,0 +1,317 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
//
// 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"
#include "doomstat.h"
#include "p_spec.h" // Skybox viewpoints
#include "z_zone.h"
#include "r_things.h"
#include "r_sky.h"
UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */
boolean portalskipprecipmobjs = false;
// Linked list for portals.
portal_t *portal_base, *portal_cap;
line_t *portalclipline;
sector_t *portalcullsector;
INT32 portalclipstart, portalclipend;
portal_t *g_portal; // is curline a portal seg?
void Portal_InitList (void)
{
portalrender = 0;
portal_base = portal_cap = NULL;
}
/** 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;
}
}
static 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 + 1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), 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;
portal->isskybox = false;
return portal;
}
void Portal_Remove (portal_t* portal)
{
portalcullsector = NULL;
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;
g_portal = portal; // this tells R_StoreWallRange that curline is a portal seg
}
/** Store the clipping window for a portal using a visplane.
*
* Since visplanes top/bottom windows work in an identical way,
* it can just be copied almost directly.
*/
static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal)
{
INT16 start = portal->start;
INT16 end = portal->end;
INT32 i;
for (i = 0; i < end - start; i++)
{
// Invalid column.
if (plane->top[i + start] == 65535)
{
portal->ceilingclip[i] = -1;
portal->floorclip[i] = -1;
continue;
}
portal->ceilingclip[i] = plane->top[i + start] - 1;
portal->floorclip[i] = plane->bottom[i + start] + 1;
portal->frontscale[i] = INT32_MAX;
}
}
extern INT32 viewwidth;
static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* end)
{
*start = plane->minx;
*end = plane->maxx + 1;
// Visplanes have 1-px pads on their sides (extra columns).
// Trim them, else it may render out of bounds.
if (*end > viewwidth)
*end = viewwidth;
if (!(*start < *end))
return true;
/** Trims a visplane's horizontal gap to match its render area.
*
* Visplanes' minx/maxx may sometimes exceed the area they're
* covering. This merely adjusts the boundaries to the next
* valid area.
*/
while (plane->bottom[*start] == 0 && plane->top[*start] == 65535 && *start < *end)
{
(*start)++;
}
while (plane->bottom[*end - 1] == 0 && plane->top[*start] == 65535 && *end > *start)
{
(*end)--;
}
return false;
}
/** Creates a skybox portal out of a visplane.
*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
static void Portal_AddSkybox (const visplane_t* plane)
{
INT16 start, end;
mapheader_t *mh;
portal_t* portal;
if (TrimVisplaneBounds(plane, &start, &end))
return;
portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
portal->viewx = skyboxmo[0]->x;
portal->viewy = skyboxmo[0]->y;
portal->viewz = 0;
if (skyboxmo[0]->spawnpoint)
portal->viewz = ((fixed_t)skyboxmo[0]->spawnpoint->angle)<<FRACBITS;
portal->viewangle = viewangle + skyboxmo[0]->angle;
mh = mapheaderinfo[gamemap-1];
// If a relative viewpoint exists, offset the viewpoint.
if (skyboxmo[1])
{
fixed_t x = 0, y = 0;
angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT;
if (mh->skybox_scalex > 0)
x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex;
else if (mh->skybox_scalex < 0)
x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex;
if (mh->skybox_scaley > 0)
y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley;
else if (mh->skybox_scaley < 0)
y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley;
// Apply transform to account for the skybox viewport angle.
portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
portal->viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
}
if (mh->skybox_scalez > 0)
portal->viewz += viewz / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
portal->viewz += viewz * -mh->skybox_scalez;
portal->clipline = -1;
portal->isskybox = true;
}
/** Creates portals for the currently existing sky visplanes.
* The visplanes are also removed and cleared from the list.
*/
void Portal_AddSkyboxPortals (void)
{
visplane_t *pl;
INT32 i;
UINT16 count = 0;
for (i = 0; i < MAXVISPLANES; i++, pl++)
{
for (pl = visplanes[i]; pl; pl = pl->next)
{
//if (pl->minx >= pl->maxx)
//continue;
if (pl->picnum == skyflatnum)
{
Portal_AddSkybox(pl);
pl->minx = 0;
pl->maxx = -1;
count++;
}
}
}
//CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count);
}
+63
View File
@@ -0,0 +1,63 @@
// 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.
#ifndef __R_PORTAL__
#define __R_PORTAL__
#include "r_data.h"
#include "r_plane.h" // visplanes
/*
* Portal structure for the software renderer.
*/
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. */
boolean isskybox;
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;
extern boolean portalskipprecipmobjs;
extern line_t *portalclipline;
extern sector_t *portalcullsector;
extern INT32 portalclipstart, portalclipend;
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_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkyboxPortals (void);
#endif
+4
View File
@@ -15,6 +15,7 @@
#include "r_local.h"
#include "r_sky.h"
#include "r_portal.h"
#include "r_splats.h"
#include "w_wad.h"
@@ -1642,6 +1643,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (ds_p == drawsegs+maxdrawsegs)
{
size_t curpos = curdrawsegs - drawsegs;
size_t pos = ds_p - drawsegs;
size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128;
if (firstseg)
@@ -1649,6 +1651,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL);
ds_p = drawsegs + pos;
maxdrawsegs = newmax;
curdrawsegs = drawsegs + curpos;
if (firstseg)
firstseg = drawsegs + (size_t)firstseg;
}
@@ -1701,6 +1704,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// borrowed fix from *cough* zdoom *cough*
// [RH] We also need to adjust the openings pointers that
// were already stored in drawsegs.
//for (ds = curdrawsegs; ds < ds_p; ds++)
for (ds = drawsegs; ds < ds_p; ds++)
{
#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings;
-6
View File
@@ -90,14 +90,8 @@ extern side_t *sides;
extern fixed_t viewx, viewy, viewz;
extern angle_t viewangle, aimingangle, viewroll;
extern UINT8 viewssnum; // splitscreen view number
extern boolean viewsky, skyVisible;
extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player
extern sector_t *viewsector;
extern player_t *viewplayer;
extern UINT8 portalrender;
extern sector_t *portalcullsector;
extern line_t *portalclipline;
extern INT32 portalclipstart, portalclipend;
extern consvar_t cv_allowmlook;
extern consvar_t cv_maxportals;
+152 -62
View File
@@ -25,6 +25,7 @@
#include "r_things.h"
#include "r_patch.h"
#include "r_plane.h"
#include "r_portal.h"
#include "p_tick.h"
#include "p_local.h"
#include "p_slopes.h"
@@ -1970,6 +1971,12 @@ void R_AddPrecipitationSprites(void)
return;
}
// do not render in skybox
if (portalskipprecipmobjs)
{
return;
}
R_GetRenderBlockMapDimensions(drawdist, &xl, &xh, &yl, &yh);
for (bx = xl; bx <= xh; bx++)
@@ -1993,46 +2000,47 @@ void R_AddPrecipitationSprites(void)
//
// R_SortVisSprites
//
static vissprite_t vsprsortedhead;
void R_SortVisSprites(void)
static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end)
{
UINT32 i;
UINT32 i, count = 0;
vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
vissprite_t *best = NULL;
vissprite_t unsorted;
fixed_t bestscale;
INT32 bestdispoffset;
if (!visspritecount)
return;
dsfirst = &unsorted;
dsprev = dsfirst;
dsnext = dsfirst;
unsorted.next = unsorted.prev = &unsorted;
I_Assert(start <= end);
dsfirst = R_GetVisSprite(0);
// The first's prev and last's next will be set to
// nonsense, but are fixed in a moment
for (i = 0, dsnext = dsfirst, ds = NULL; i < visspritecount; i++)
for (i = start; i < end; ++i)
{
dsprev = ds;
ds = dsnext;
if (i < visspritecount - 1) dsnext = R_GetVisSprite(i + 1);
ds = R_GetVisSprite(i);
ds->next = dsnext;
ds->prev = dsprev;
// Do not include this sprite, since it is completely obscured
if (ds->cut & SC_NOTVISIBLE)
{
continue;
}
dsnext = ds;
dsprev->next = dsnext;
dsnext->prev = dsprev;
dsprev = dsnext;
count++;
}
// Fix first and last. ds still points to the last one after the loop
dsfirst->prev = &unsorted;
unsorted.next = dsfirst;
if (ds)
ds->next = &unsorted;
unsorted.prev = ds;
dsnext->next = dsfirst;
dsfirst->prev = dsnext;
// pull the vissprites out by scale
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
for (i = 0; i < visspritecount; i++)
vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead;
for (i = 0; i < count; i++)
{
bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
@@ -2058,15 +2066,12 @@ void R_SortVisSprites(void)
best = ds;
}
}
if (best)
{
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = &vsprsortedhead;
best->prev = vsprsortedhead.prev;
vsprsortedhead.prev->next = best;
vsprsortedhead.prev = best;
}
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = vsprsortedhead;
best->prev = vsprsortedhead->prev;
vsprsortedhead->prev->next = best;
vsprsortedhead->prev = best;
}
}
@@ -2076,28 +2081,28 @@ void R_SortVisSprites(void)
static drawnode_t *R_CreateDrawNode(drawnode_t *link);
static drawnode_t nodebankhead;
static drawnode_t nodehead;
static void R_CreateDrawNodes(void)
static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean tempskip)
{
drawnode_t *entry;
drawseg_t *ds;
INT32 i, p, best, x1, x2;
fixed_t bestdelta, delta;
vissprite_t *rover;
static vissprite_t vsprsortedhead;
drawnode_t *r2;
visplane_t *plane;
INT32 sintersect;
fixed_t scale = 0;
// Add the 3D floors, thicksides, and masked textures...
for (ds = ds_p; ds-- > drawsegs ;)
for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];)
{
if (ds->numthicksides)
{
for (i = 0; i < ds->numthicksides; i++)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->thickseg = ds;
entry->ffloor = ds->thicksides[i];
}
@@ -2113,7 +2118,7 @@ static void R_CreateDrawNodes(void)
else
{
// Put it in!
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->plane = plane;
entry->seg = ds;
}
@@ -2121,7 +2126,7 @@ static void R_CreateDrawNodes(void)
}
if (ds->maskedtexturecol)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->seg = ds;
}
if (ds->numffloorplanes)
@@ -2153,7 +2158,7 @@ static void R_CreateDrawNodes(void)
}
if (best != -1)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->plane = ds->ffloorplanes[best];
entry->seg = ds;
ds->ffloorplanes[best] = NULL;
@@ -2164,6 +2169,9 @@ static void R_CreateDrawNodes(void)
}
}
if (tempskip)
return;
// find all the remaining polyobject planes and add them on the end of the list
// probably this is a terrible idea if we wanted them to be sorted properly
// but it works getting them in for now
@@ -2179,16 +2187,18 @@ static void R_CreateDrawNodes(void)
PolyObjects[i].visplane = NULL;
continue;
}
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->plane = plane;
// note: no seg is set, for what should be obvious reasons
PolyObjects[i].visplane = NULL;
}
if (visspritecount == 0)
// No vissprites in this mask?
if (mask->vissprites[1] - mask->vissprites[0] == 0)
return;
R_SortVisSprites();
R_SortVisSprites(&vsprsortedhead, mask->vissprites[0], mask->vissprites[1]);
for (rover = vsprsortedhead.prev; rover != &vsprsortedhead; rover = rover->prev)
{
if (rover->szt > vid.height || rover->sz < 0)
@@ -2196,7 +2206,7 @@ static void R_CreateDrawNodes(void)
sintersect = (rover->x1 + rover->x2) / 2;
for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next)
for (r2 = head->next; r2 != head; r2 = r2->next)
{
if (r2->plane)
{
@@ -2335,9 +2345,9 @@ static void R_CreateDrawNodes(void)
}
}
}
if (r2 == &nodehead)
if (r2 == head)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->sprite = rover;
}
}
@@ -2381,25 +2391,24 @@ static void R_DoneWithNode(drawnode_t *node)
(node->prev = &nodebankhead)->next = node;
}
static void R_ClearDrawNodes(void)
static void R_ClearDrawNodes(drawnode_t* head)
{
drawnode_t *rover;
drawnode_t *next;
for (rover = nodehead.next; rover != &nodehead ;)
for (rover = head->next; rover != head;)
{
next = rover->next;
R_DoneWithNode(rover);
rover = next;
}
nodehead.next = nodehead.prev = &nodehead;
head->next = head->prev = head;
}
void R_InitDrawNodes(void)
{
nodebankhead.next = nodebankhead.prev = &nodebankhead;
nodehead.next = nodehead.prev = &nodehead;
}
//
@@ -2463,7 +2472,7 @@ static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2)
// R_ClipVisSprite
// Clips vissprites without drawing, so that portals can work. -Red
static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
{
drawseg_t *ds;
INT32 x;
@@ -2502,8 +2511,36 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
ds = curr->user;
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
if (ds->portalpass != 66) // unused?
{
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
if (ds->scale1 > ds->scale2)
{
lowscale = ds->scale2;
scale = ds->scale1;
}
else
{
lowscale = ds->scale1;
scale = ds->scale2;
}
if (scale < spr->sortscale ||
(lowscale < spr->sortscale &&
!R_PointOnSegSide (spr->gx, spr->gy, ds->curline)))
{
// masked mid texture?
/*
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, r1, r2);
*/
// seg is behind sprite
continue;
}
}
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
@@ -2654,11 +2691,34 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
if (!R_CheckSpriteVisible(spr, x1, x2))
spr->cut |= SC_NOTVISIBLE;
}
if (portal)
{
INT32 start_index = max(portal->start, x1);
INT32 end_index = min(portal->start + portal->end - portal->start, x2);
for (x = x1; x < start_index; x++)
{
spr->clipbot[x] = -1;
spr->cliptop[x] = -1;
}
for (x = start_index; x <= end_index; x++)
{
if (spr->clipbot[x] > portal->floorclip[x - portal->start])
spr->clipbot[x] = portal->floorclip[x - portal->start];
if (spr->cliptop[x] < portal->ceilingclip[x - portal->start])
spr->cliptop[x] = portal->ceilingclip[x - portal->start];
}
for (x = end_index + 1; x <= x2; x++)
{
spr->clipbot[x] = -1;
spr->cliptop[x] = -1;
}
}
}
void R_ClipSprites(void)
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
{
const size_t maxdrawsegs = ds_p - drawsegs;
const size_t maxdrawsegs = ds_p - dsstart;
const INT32 cx = viewwidth / 2;
drawseg_t* ds;
INT32 i;
@@ -2691,7 +2751,7 @@ void R_ClipSprites(void)
}
}
for (ds = ds_p; ds-- > drawsegs;)
for (ds = ds_p; ds-- > dsstart;)
{
if (ds->silhouette || ds->maskedtexturecol)
{
@@ -2745,7 +2805,7 @@ void R_ClipSprites(void)
drawsegs_xrange_count = drawsegs_xranges[0].count;
}
R_ClipVisSprite(spr, spr->x1, spr->x2);
R_ClipVisSprite(spr, spr->x1, spr->x2, portal);
if ((spr->cut & SC_NOTVISIBLE) == 0)
numvisiblesprites++;
@@ -2790,14 +2850,12 @@ boolean R_ThingWithinDist (mobj_t *thing, fixed_t limit_dist)
//
// R_DrawMasked
//
void R_DrawMasked(void)
static void R_DrawMaskedList (drawnode_t* head)
{
drawnode_t *r2;
drawnode_t *next;
R_CreateDrawNodes();
for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next)
for (r2 = head->next; r2 != head; r2 = r2->next)
{
if (r2->plane)
{
@@ -2835,7 +2893,39 @@ void R_DrawMasked(void)
r2 = next;
}
}
R_ClearDrawNodes();
}
void R_DrawMasked(maskcount_t* masks, INT32 nummasks)
{
drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */
INT32 i;
heads = calloc(nummasks, sizeof(drawnode_t));
for (i = 0; i < nummasks; i++)
{
heads[i].next = heads[i].prev = &heads[i];
viewx = masks[i].viewx;
viewy = masks[i].viewy;
viewz = masks[i].viewz;
viewsector = masks[i].viewsector;
R_CreateDrawNodes(&masks[i], &heads[i], false);
}
for (; nummasks > 0; nummasks--)
{
viewx = masks[nummasks - 1].viewx;
viewy = masks[nummasks - 1].viewy;
viewz = masks[nummasks - 1].viewz;
viewsector = masks[nummasks - 1].viewsector;
R_DrawMaskedList(&heads[nummasks - 1]);
R_ClearDrawNodes(&heads[nummasks - 1]);
}
free(heads);
}
// ==========================================================================
+15 -3
View File
@@ -16,6 +16,7 @@
#include "sounds.h"
#include "r_plane.h"
#include "r_portal.h"
#include "r_patch.h"
// "Left" and "Right" character symbols for additional rotation functionality
@@ -60,7 +61,6 @@ extern INT32 lengthcol;
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
void R_DrawMaskedColumn(column_t *column);
void R_SortVisSprites(void);
//faB: find sprites in wadfile, replace existing, add new ones
// (only sprites from namelist are added or replaced)
@@ -71,7 +71,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_AddPrecipitationSprites(void);
void R_InitSprites(void);
void R_ClearSprites(void);
void R_DrawMasked(void);
/** Used to count the amount of masked elements
* per portal to later group them in separate
* drawnode lists.
*/
typedef struct
{
size_t drawsegs[2];
size_t vissprites[2];
fixed_t viewx, viewy, viewz; /**< View z stored at the time of the BSP traversal for the view/portal. Masked sorting/drawing needs it. */
sector_t* viewsector;
} maskcount_t;
void R_DrawMasked(maskcount_t* masks, INT32 nummasks);
boolean R_ThingVisible (mobj_t *thing);
boolean R_ThingWithinDist (mobj_t *thing, fixed_t limit_dist);
@@ -193,7 +205,7 @@ typedef struct vissprite_s
extern UINT32 visspritecount, numvisiblesprites;
void R_ClipSprites(void);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);