Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ac0f2bae2 | ||
|
|
cee28c6166 | ||
|
|
a6be267325 | ||
|
|
426740e0ac | ||
|
|
78c0f64135 |
No files matched your search
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
Reference in new issue
Block a user