mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 17:22:12 +00:00
Merge branch 'portals2' into 'master'
Portal-based skybox rendering replacement for the software renderer See merge request STJr/SRB2Internal!226
This commit is contained in:
commit
740c561b0e
16 changed files with 633 additions and 340 deletions
|
@ -123,6 +123,7 @@ set(SRB2_CORE_RENDER_SOURCES
|
|||
r_sky.c
|
||||
r_splats.c
|
||||
r_things.c
|
||||
r_portal.c
|
||||
|
||||
r_bsp.h
|
||||
r_data.h
|
||||
|
@ -136,6 +137,7 @@ set(SRB2_CORE_RENDER_SOURCES
|
|||
r_splats.h
|
||||
r_state.h
|
||||
r_things.h
|
||||
r_portal.h
|
||||
)
|
||||
|
||||
set(SRB2_CORE_GAME_SOURCES
|
||||
|
|
|
@ -455,6 +455,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/r_sky.o \
|
||||
$(OBJDIR)/r_splats.o \
|
||||
$(OBJDIR)/r_things.o \
|
||||
$(OBJDIR)/r_portal.o \
|
||||
$(OBJDIR)/screen.o \
|
||||
$(OBJDIR)/v_video.o \
|
||||
$(OBJDIR)/s_sound.o \
|
||||
|
|
|
@ -6194,7 +6194,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
|
|||
}
|
||||
|
||||
// note: sets viewangle, viewx, viewy, viewz
|
||||
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);
|
||||
|
||||
// copy view cam position for local use
|
||||
dup_viewx = viewx;
|
||||
|
|
|
@ -3147,7 +3147,6 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
savedata.lives = 0;
|
||||
}
|
||||
|
||||
skyVisible = skyVisible1 = skyVisible2 = true; // assume the skybox is visible on level load.
|
||||
if (loadprecip) // uglier hack
|
||||
{ // to make a newly loaded level start on the second frame.
|
||||
INT32 buf = gametic % BACKUPTICS;
|
||||
|
|
13
src/r_bsp.c
13
src/r_bsp.c
|
@ -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
|
||||
|
@ -26,11 +27,11 @@ side_t *sidedef;
|
|||
line_t *linedef;
|
||||
sector_t *frontsector;
|
||||
sector_t *backsector;
|
||||
boolean portalline; // is curline a portal seg?
|
||||
|
||||
// very ugly realloc() of drawsegs at run-time, I upped it to 512
|
||||
// instead of 256.. and someone managed to send me a level with
|
||||
// 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;
|
||||
|
||||
|
@ -459,7 +460,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;
|
||||
}
|
||||
|
@ -1377,13 +1378,5 @@ void R_RenderBSPNode(INT32 bspnum)
|
|||
bspnum = bsp->children[side^1];
|
||||
}
|
||||
|
||||
// PORTAL CULLING
|
||||
if (portalcullsector) {
|
||||
sector_t *sect = subsectors[bspnum & ~NF_SUBSECTOR].sector;
|
||||
if (sect != portalcullsector)
|
||||
return;
|
||||
portalcullsector = NULL;
|
||||
}
|
||||
|
||||
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ extern boolean portalline; // is curline a portal seg?
|
|||
|
||||
extern INT32 checkcoord[12][4];
|
||||
|
||||
extern drawseg_t *curdrawsegs;
|
||||
extern drawseg_t *drawsegs;
|
||||
extern drawseg_t *ds_p;
|
||||
extern INT32 doorclosed;
|
||||
|
@ -38,7 +39,6 @@ void R_ClearClipSegs(void);
|
|||
void R_PortalClearClipSegs(INT32 start, INT32 end);
|
||||
void R_ClearDrawSegs(void);
|
||||
void R_RenderBSPNode(INT32 bspnum);
|
||||
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2);
|
||||
|
||||
#ifdef POLYOBJECTS
|
||||
void R_SortPolyObjects(subsector_t *sub);
|
||||
|
|
260
src/r_main.c
260
src/r_main.c
|
@ -30,6 +30,7 @@
|
|||
#include "p_spec.h" // skyboxmo
|
||||
#include "z_zone.h"
|
||||
#include "m_random.h" // quake camera shake
|
||||
#include "r_portal.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
@ -65,37 +66,9 @@ size_t loopcount;
|
|||
fixed_t viewx, viewy, viewz;
|
||||
angle_t viewangle, aimingangle;
|
||||
fixed_t viewcos, viewsin;
|
||||
boolean viewsky, skyVisible;
|
||||
boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, for splitscreen
|
||||
sector_t *viewsector;
|
||||
player_t *viewplayer;
|
||||
|
||||
// PORTALS!
|
||||
// You can thank and/or curse JTE for these.
|
||||
UINT8 portalrender;
|
||||
sector_t *portalcullsector;
|
||||
typedef struct portal_pair
|
||||
{
|
||||
INT32 line1;
|
||||
INT32 line2;
|
||||
UINT8 pass;
|
||||
struct portal_pair *next;
|
||||
|
||||
fixed_t viewx;
|
||||
fixed_t viewy;
|
||||
fixed_t viewz;
|
||||
angle_t viewangle;
|
||||
|
||||
INT32 start;
|
||||
INT32 end;
|
||||
INT16 *ceilingclip;
|
||||
INT16 *floorclip;
|
||||
fixed_t *frontscale;
|
||||
} portal_pair;
|
||||
portal_pair *portal_base, *portal_cap;
|
||||
line_t *portalclipline;
|
||||
INT32 portalclipstart, portalclipend;
|
||||
|
||||
//
|
||||
// precalculated math tables
|
||||
//
|
||||
|
@ -764,7 +737,7 @@ static void R_SetupFreelook(void)
|
|||
|
||||
#undef AIMINGTODY
|
||||
|
||||
void R_SetupFrame(player_t *player, boolean skybox)
|
||||
void R_SetupFrame(player_t *player)
|
||||
{
|
||||
camera_t *thiscam;
|
||||
boolean chasecam = false;
|
||||
|
@ -794,7 +767,6 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
else if (!chasecam)
|
||||
thiscam->chase = false;
|
||||
|
||||
viewsky = !skybox;
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
// cut-away view stuff
|
||||
|
@ -883,7 +855,6 @@ void R_SkyboxFrame(player_t *player)
|
|||
thiscam = &camera;
|
||||
|
||||
// cut-away view stuff
|
||||
viewsky = true;
|
||||
viewmobj = skyboxmo[0];
|
||||
#ifdef PARANOIA
|
||||
if (!viewmobj)
|
||||
|
@ -1010,17 +981,8 @@ void R_SkyboxFrame(player_t *player)
|
|||
R_SetupFreelook();
|
||||
}
|
||||
|
||||
#define ANGLED_PORTALS
|
||||
|
||||
static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
||||
static void R_PortalFrame(portal_t *portal)
|
||||
{
|
||||
vertex_t dest_c, start_c;
|
||||
#ifdef ANGLED_PORTALS
|
||||
// delta angle
|
||||
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
|
||||
#endif
|
||||
|
||||
//R_SetupFrame(player, false);
|
||||
viewx = portal->viewx;
|
||||
viewy = portal->viewy;
|
||||
viewz = portal->viewz;
|
||||
|
@ -1029,96 +991,37 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
portalcullsector = dest->frontsector;
|
||||
viewsector = dest->frontsector;
|
||||
portalclipline = dest;
|
||||
portalclipstart = portal->start;
|
||||
portalclipend = portal->end;
|
||||
|
||||
// Offset the portal view by the linedef centers
|
||||
|
||||
// looking glass center
|
||||
start_c.x = (start->v1->x + start->v2->x) / 2;
|
||||
start_c.y = (start->v1->y + start->v2->y) / 2;
|
||||
|
||||
// other side center
|
||||
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
|
||||
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
|
||||
|
||||
// Heights!
|
||||
viewz += dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
|
||||
// calculate the difference in position and rotation!
|
||||
#ifdef ANGLED_PORTALS
|
||||
if (dangle == 0)
|
||||
#endif
|
||||
{ // the entrance goes straight opposite the exit, so we just need to mess with the offset.
|
||||
viewx += dest_c.x - start_c.x;
|
||||
viewy += dest_c.y - start_c.y;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ANGLED_PORTALS
|
||||
viewangle += dangle;
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
//CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS);
|
||||
|
||||
// ????
|
||||
if (portal->clipline != -1)
|
||||
{
|
||||
fixed_t disttopoint;
|
||||
angle_t angtopoint;
|
||||
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint += dangle;
|
||||
|
||||
viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
|
||||
{
|
||||
portal_pair *portal = Z_Malloc(sizeof(portal_pair), PU_LEVEL, NULL);
|
||||
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
|
||||
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
|
||||
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1), PU_LEVEL, NULL);
|
||||
|
||||
portal->line1 = line1;
|
||||
portal->line2 = line2;
|
||||
portal->pass = portalrender+1;
|
||||
portal->next = NULL;
|
||||
|
||||
R_PortalStoreClipValues(x1, x2, ceilingclipsave, floorclipsave, frontscalesave);
|
||||
|
||||
portal->ceilingclip = ceilingclipsave;
|
||||
portal->floorclip = floorclipsave;
|
||||
portal->frontscale = frontscalesave;
|
||||
|
||||
portal->start = x1;
|
||||
portal->end = x2;
|
||||
|
||||
portalline = true; // this tells R_StoreWallRange that curline is a portal seg
|
||||
|
||||
portal->viewx = viewx;
|
||||
portal->viewy = viewy;
|
||||
portal->viewz = viewz;
|
||||
portal->viewangle = viewangle;
|
||||
|
||||
if (!portal_base)
|
||||
{
|
||||
portal_base = portal;
|
||||
portal_cap = portal;
|
||||
portalclipline = &lines[portal->clipline];
|
||||
viewsector = portalclipline->frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
portal_cap->next = portal;
|
||||
portal_cap = portal;
|
||||
portalclipline = 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
|
||||
// ================
|
||||
|
@ -1131,8 +1034,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 nummasks = 1;
|
||||
maskcount_t* masks = malloc(sizeof(maskcount_t));
|
||||
|
||||
if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1
|
||||
{
|
||||
|
@ -1142,38 +1045,7 @@ void R_RenderPlayerView(player_t *player)
|
|||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15));
|
||||
}
|
||||
|
||||
// load previous saved value of skyVisible for the player
|
||||
if (splitscreen && player == &players[secondarydisplayplayer])
|
||||
skyVisible = skyVisible2;
|
||||
else
|
||||
skyVisible = skyVisible1;
|
||||
|
||||
portalrender = 0;
|
||||
portal_base = portal_cap = NULL;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
R_SetupFrame(player, skybox);
|
||||
skyVisible = false;
|
||||
R_SetupFrame(player);
|
||||
framecount++;
|
||||
validcount++;
|
||||
|
||||
|
@ -1185,19 +1057,21 @@ void R_RenderPlayerView(player_t *player)
|
|||
#ifdef FLOORSPLATS
|
||||
R_ClearVisibleFloorSplats();
|
||||
#endif
|
||||
Portal_InitList();
|
||||
|
||||
// check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// The head node is the last node output.
|
||||
|
||||
Mask_Pre(&masks[nummasks - 1]);
|
||||
curdrawsegs = ds_p;
|
||||
//profile stuff ---------------------------------------------------------
|
||||
#ifdef TIMING
|
||||
mytotal = 0;
|
||||
ProfZeroTimer();
|
||||
#endif
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_ClipSprites();
|
||||
#ifdef TIMING
|
||||
RDMSR(0x10, &mycount);
|
||||
mytotal += mycount; // 64bit add
|
||||
|
@ -1205,54 +1079,66 @@ void R_RenderPlayerView(player_t *player)
|
|||
CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal);
|
||||
#endif
|
||||
//profile stuff ---------------------------------------------------------
|
||||
Mask_Post(&masks[nummasks - 1]);
|
||||
|
||||
// PORTAL RENDERING
|
||||
for(portal = portal_base; portal; portal = portal_base)
|
||||
R_ClipSprites(drawsegs, NULL);
|
||||
|
||||
|
||||
// Add skybox portals caused by sky visplanes.
|
||||
if (cv_skybox.value && skyboxmo[0])
|
||||
Portal_AddSkyboxPortals();
|
||||
|
||||
// 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;
|
||||
|
||||
// Render the BSP from the new viewpoint, and clip
|
||||
// any sprites with the new clipsegs and window.
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
Mask_Post(&masks[nummasks - 1]);
|
||||
|
||||
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
|
||||
|
||||
Portal_Remove(portal);
|
||||
}
|
||||
}
|
||||
// END PORTAL RENDERING
|
||||
|
||||
R_DrawPlanes();
|
||||
#ifdef FLOORSPLATS
|
||||
R_DrawVisibleFloorSplats();
|
||||
#endif
|
||||
|
||||
// draw mid texture and sprite
|
||||
// And now 3D floors/sides!
|
||||
R_DrawMasked();
|
||||
R_DrawMasked(masks, nummasks);
|
||||
|
||||
// Check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// save value to skyVisible1 or skyVisible2
|
||||
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
|
||||
if (splitscreen && player == &players[secondarydisplayplayer])
|
||||
skyVisible2 = skyVisible;
|
||||
else
|
||||
skyVisible1 = skyVisible;
|
||||
free(masks);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
|
|
@ -94,7 +94,7 @@ void R_ExecuteSetViewSize(void);
|
|||
|
||||
void R_SkyboxFrame(player_t *player);
|
||||
|
||||
void R_SetupFrame(player_t *player, boolean skybox);
|
||||
void R_SetupFrame(player_t *player);
|
||||
// Called by G_Drawer.
|
||||
void R_RenderPlayerView(player_t *player);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
@ -43,9 +45,8 @@
|
|||
//#define QUINCUNX
|
||||
|
||||
//SoM: 3/23/2000: Use Boom visplane hashing.
|
||||
#define MAXVISPLANES 512
|
||||
|
||||
static visplane_t *visplanes[MAXVISPLANES];
|
||||
visplane_t *visplanes[MAXVISPLANES];
|
||||
static visplane_t *freetail;
|
||||
static visplane_t **freehead = &freetail;
|
||||
|
||||
|
@ -112,50 +113,6 @@ void R_InitPlanes(void)
|
|||
// FIXME: unused
|
||||
}
|
||||
|
||||
// R_PortalStoreClipValues
|
||||
// Saves clipping values for later. -Red
|
||||
void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < end-start; i++)
|
||||
{
|
||||
*ceil = ceilingclip[start+i];
|
||||
ceil++;
|
||||
*floor = floorclip[start+i];
|
||||
floor++;
|
||||
*scale = frontscale[start+i];
|
||||
scale++;
|
||||
}
|
||||
}
|
||||
|
||||
// R_PortalRestoreClipValues
|
||||
// Inverse of the above. Restores the old value!
|
||||
void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < end-start; i++)
|
||||
{
|
||||
ceilingclip[start+i] = *ceil;
|
||||
ceil++;
|
||||
floorclip[start+i] = *floor;
|
||||
floor++;
|
||||
frontscale[start+i] = *scale;
|
||||
scale++;
|
||||
}
|
||||
|
||||
// HACKS FOLLOW
|
||||
for (i = 0; i < start; i++)
|
||||
{
|
||||
floorclip[i] = -1;
|
||||
ceilingclip[i] = (INT16)viewheight;
|
||||
}
|
||||
for (i = end; i < vid.width; i++)
|
||||
{
|
||||
floorclip[i] = -1;
|
||||
ceilingclip[i] = (INT16)viewheight;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_MapPlane
|
||||
//
|
||||
|
@ -348,6 +305,23 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
|
|||
#endif
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -370,8 +344,6 @@ void R_ClearPlanes(void)
|
|||
}
|
||||
}
|
||||
|
||||
numffloors = 0;
|
||||
|
||||
for (i = 0; i < MAXVISPLANES; i++)
|
||||
for (*freehead = visplanes[i], visplanes[i] = NULL;
|
||||
freehead && *freehead ;)
|
||||
|
@ -723,16 +695,6 @@ static void R_DrawSkyPlane(visplane_t *pl)
|
|||
INT32 x;
|
||||
INT32 angle;
|
||||
|
||||
// If we're not supposed to draw the sky (e.g. for skyboxes), don't do anything!
|
||||
// This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately
|
||||
if (!viewsky)
|
||||
{
|
||||
// Mark that the sky was visible here for next tic
|
||||
// (note: this is a hack and it sometimes can cause HOMs to appear for a tic IIRC)
|
||||
skyVisible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset column drawer function (note: couldn't we just call walldrawerfunc directly?)
|
||||
// (that is, unless we'll need to switch drawers in future for some reason)
|
||||
wallcolfunc = walldrawerfunc;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "r_data.h"
|
||||
#include "p_polyobj.h"
|
||||
|
||||
#define MAXVISPLANES 512
|
||||
|
||||
//
|
||||
// Now what is a visplane, anyway?
|
||||
// Simple: kinda floor/ceiling polygon optimised for SRB2 rendering.
|
||||
|
@ -53,6 +55,7 @@ typedef struct visplane_s
|
|||
#endif
|
||||
} visplane_t;
|
||||
|
||||
extern visplane_t *visplanes[MAXVISPLANES];
|
||||
extern visplane_t *floorplane;
|
||||
extern visplane_t *ceilingplane;
|
||||
|
||||
|
@ -72,9 +75,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);
|
||||
|
@ -122,4 +124,6 @@ typedef struct planemgr_s
|
|||
|
||||
extern visffloor_t ffloor[MAXFFLOORS];
|
||||
extern INT32 numffloors;
|
||||
|
||||
void Portal_AddSkyboxPortals (void);
|
||||
#endif
|
||||
|
|
333
src/r_portal.c
Normal file
333
src/r_portal.c
Normal file
|
@ -0,0 +1,333 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_portal.c
|
||||
/// \brief Software renderer portals.
|
||||
|
||||
#include "r_portal.h"
|
||||
#include "r_plane.h"
|
||||
#include "r_main.h"
|
||||
#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. */
|
||||
|
||||
// Linked list for portals.
|
||||
portal_t *portal_base, *portal_cap;
|
||||
|
||||
line_t *portalclipline;
|
||||
INT32 portalclipstart, portalclipend;
|
||||
|
||||
boolean portalline; // is curline a portal seg?
|
||||
|
||||
void Portal_InitList (void)
|
||||
{
|
||||
portalrender = 0;
|
||||
portal_base = portal_cap = NULL;
|
||||
}
|
||||
|
||||
/** Store the clipping window for a portal in its given range.
|
||||
*
|
||||
* The window is copied from the current window at the time
|
||||
* the function is called, so it is useful for converting one-sided
|
||||
* lines into portals.
|
||||
*/
|
||||
void Portal_ClipRange (portal_t* portal)
|
||||
{
|
||||
INT32 start = portal->start;
|
||||
INT32 end = portal->end;
|
||||
INT16 *ceil = portal->ceilingclip;
|
||||
INT16 *floor = portal->floorclip;
|
||||
fixed_t *scale = portal->frontscale;
|
||||
|
||||
INT32 i;
|
||||
for (i = 0; i < end-start; i++)
|
||||
{
|
||||
*ceil = ceilingclip[start+i];
|
||||
ceil++;
|
||||
*floor = floorclip[start+i];
|
||||
floor++;
|
||||
*scale = frontscale[start+i];
|
||||
scale++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply the clipping window from a portal.
|
||||
*/
|
||||
void Portal_ClipApply (const portal_t* portal)
|
||||
{
|
||||
INT32 i;
|
||||
INT32 start = portal->start;
|
||||
INT32 end = portal->end;
|
||||
INT16 *ceil = portal->ceilingclip;
|
||||
INT16 *floor = portal->floorclip;
|
||||
fixed_t *scale = portal->frontscale;
|
||||
|
||||
for (i = 0; i < end-start; i++)
|
||||
{
|
||||
ceilingclip[start+i] = *ceil;
|
||||
ceil++;
|
||||
floorclip[start+i] = *floor;
|
||||
floor++;
|
||||
frontscale[start+i] = *scale;
|
||||
scale++;
|
||||
}
|
||||
|
||||
// HACKS FOLLOW
|
||||
for (i = 0; i < start; i++)
|
||||
{
|
||||
floorclip[i] = -1;
|
||||
ceilingclip[i] = (INT16)viewheight;
|
||||
}
|
||||
for (i = end; i < vid.width; i++)
|
||||
{
|
||||
floorclip[i] = -1;
|
||||
ceilingclip[i] = (INT16)viewheight;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return portal;
|
||||
}
|
||||
|
||||
void Portal_Remove (portal_t* portal)
|
||||
{
|
||||
portal_base = portal->next;
|
||||
Z_Free(portal->ceilingclip);
|
||||
Z_Free(portal->floorclip);
|
||||
Z_Free(portal->frontscale);
|
||||
Z_Free(portal);
|
||||
}
|
||||
|
||||
/** Creates a portal out of two lines and a determined screen range.
|
||||
*
|
||||
* line1 determines the entrance, and line2 the exit.
|
||||
* x1 and x2 determine the screen's column bounds.
|
||||
|
||||
* The view's offset from the entry line center is obtained,
|
||||
* and then rotated&translated to the exit line's center.
|
||||
* When the portal renders, it will create the illusion of
|
||||
* the two lines being seamed together.
|
||||
*/
|
||||
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2)
|
||||
{
|
||||
portal_t* portal = Portal_Add(x1, x2);
|
||||
|
||||
// Offset the portal view by the linedef centers
|
||||
line_t* start = &lines[line1];
|
||||
line_t* dest = &lines[line2];
|
||||
|
||||
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
|
||||
|
||||
fixed_t disttopoint;
|
||||
angle_t angtopoint;
|
||||
|
||||
vertex_t dest_c, start_c;
|
||||
|
||||
// looking glass center
|
||||
start_c.x = (start->v1->x + start->v2->x) / 2;
|
||||
start_c.y = (start->v1->y + start->v2->y) / 2;
|
||||
|
||||
// other side center
|
||||
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
|
||||
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
|
||||
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint += dangle;
|
||||
|
||||
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
portal->viewangle = viewangle + dangle;
|
||||
|
||||
portal->clipline = line2;
|
||||
|
||||
Portal_ClipRange(portal);
|
||||
|
||||
portalline = true; // 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.
|
||||
*/
|
||||
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 = skyboxmo[0]->z;
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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->picnum == skyflatnum)
|
||||
{
|
||||
Portal_AddSkybox(pl);
|
||||
|
||||
pl->minx = 0;
|
||||
pl->maxx = -1;
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count);
|
||||
}
|
59
src/r_portal.h
Normal file
59
src/r_portal.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
// 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. */
|
||||
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 line_t *portalclipline;
|
||||
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_AddSkybox (const visplane_t* plane);
|
||||
|
||||
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"
|
||||
|
@ -1737,6 +1738,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)
|
||||
|
@ -1744,6 +1746,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;
|
||||
}
|
||||
|
|
|
@ -80,14 +80,8 @@ extern side_t *sides;
|
|||
//
|
||||
extern fixed_t viewx, viewy, viewz;
|
||||
extern angle_t viewangle, aimingangle;
|
||||
extern boolean viewsky, skyVisible;
|
||||
extern boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, for splitscreen
|
||||
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;
|
||||
|
|
183
src/r_things.c
183
src/r_things.c
|
@ -24,6 +24,7 @@
|
|||
#include "i_video.h" // rendermode
|
||||
#include "r_things.h"
|
||||
#include "r_plane.h"
|
||||
#include "r_portal.h"
|
||||
#include "p_tick.h"
|
||||
#include "p_local.h"
|
||||
#include "p_slopes.h"
|
||||
|
@ -444,7 +445,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
|
|||
//
|
||||
// GAME FUNCTIONS
|
||||
//
|
||||
static UINT32 visspritecount;
|
||||
UINT32 visspritecount;
|
||||
static UINT32 clippedvissprites;
|
||||
static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL};
|
||||
|
||||
|
@ -1249,7 +1250,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
}
|
||||
|
||||
// PORTAL SPRITE CLIPPING
|
||||
if (portalrender)
|
||||
if (portalrender && portalclipline)
|
||||
{
|
||||
if (x2 < portalclipstart || x1 > portalclipend)
|
||||
return;
|
||||
|
@ -1351,8 +1352,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
{
|
||||
if (vis->x1 < portalclipstart)
|
||||
vis->x1 = portalclipstart;
|
||||
if (vis->x2 > portalclipend)
|
||||
vis->x2 = portalclipend;
|
||||
if (vis->x2 >= portalclipend)
|
||||
vis->x2 = portalclipend-1;
|
||||
}
|
||||
|
||||
vis->xscale = xscale; //SoM: 4/17/2000
|
||||
|
@ -1517,7 +1518,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
return;
|
||||
|
||||
// PORTAL SPRITE CLIPPING
|
||||
if (portalrender)
|
||||
if (portalrender && portalclipline)
|
||||
{
|
||||
if (x2 < portalclipstart || x1 > portalclipend)
|
||||
return;
|
||||
|
@ -1569,8 +1570,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
{
|
||||
if (vis->x1 < portalclipstart)
|
||||
vis->x1 = portalclipstart;
|
||||
if (vis->x2 > portalclipend)
|
||||
vis->x2 = portalclipend;
|
||||
if (vis->x2 >= portalclipend)
|
||||
vis->x2 = portalclipend-1;
|
||||
}
|
||||
|
||||
vis->xscale = xscale; //SoM: 4/17/2000
|
||||
|
@ -1696,9 +1697,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
|
|||
//
|
||||
// R_SortVisSprites
|
||||
//
|
||||
static vissprite_t vsprsortedhead;
|
||||
|
||||
void R_SortVisSprites(void)
|
||||
static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end)
|
||||
{
|
||||
UINT32 i, linkedvissprites = 0;
|
||||
vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
|
||||
|
@ -1707,20 +1706,17 @@ void R_SortVisSprites(void)
|
|||
fixed_t bestscale;
|
||||
INT32 bestdispoffset;
|
||||
|
||||
if (!visspritecount)
|
||||
return;
|
||||
|
||||
unsorted.next = unsorted.prev = &unsorted;
|
||||
|
||||
dsfirst = R_GetVisSprite(0);
|
||||
dsfirst = R_GetVisSprite(start);
|
||||
|
||||
// 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, dsnext = dsfirst, ds = NULL; i < end; i++)
|
||||
{
|
||||
dsprev = ds;
|
||||
ds = dsnext;
|
||||
if (i < visspritecount - 1) dsnext = R_GetVisSprite(i + 1);
|
||||
if (i < end - 1) dsnext = R_GetVisSprite(i + 1);
|
||||
|
||||
ds->next = dsnext;
|
||||
ds->prev = dsprev;
|
||||
|
@ -1798,8 +1794,8 @@ void R_SortVisSprites(void)
|
|||
}
|
||||
|
||||
// pull the vissprites out by scale
|
||||
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
|
||||
for (i = 0; i < visspritecount-linkedvissprites; i++)
|
||||
vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead;
|
||||
for (i = start; i < end-linkedvissprites; i++)
|
||||
{
|
||||
bestscale = bestdispoffset = INT32_MAX;
|
||||
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
|
||||
|
@ -1824,10 +1820,10 @@ void R_SortVisSprites(void)
|
|||
}
|
||||
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 = vsprsortedhead;
|
||||
best->prev = vsprsortedhead->prev;
|
||||
vsprsortedhead->prev->next = best;
|
||||
vsprsortedhead->prev = best;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1837,28 +1833,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];
|
||||
}
|
||||
|
@ -1873,7 +1869,7 @@ static void R_CreateDrawNodes(void)
|
|||
;
|
||||
else {
|
||||
// Put it in!
|
||||
entry = R_CreateDrawNode(&nodehead);
|
||||
entry = R_CreateDrawNode(head);
|
||||
entry->plane = plane;
|
||||
entry->seg = ds;
|
||||
}
|
||||
|
@ -1882,7 +1878,7 @@ static void R_CreateDrawNodes(void)
|
|||
#endif
|
||||
if (ds->maskedtexturecol)
|
||||
{
|
||||
entry = R_CreateDrawNode(&nodehead);
|
||||
entry = R_CreateDrawNode(head);
|
||||
entry->seg = ds;
|
||||
}
|
||||
if (ds->numffloorplanes)
|
||||
|
@ -1913,7 +1909,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;
|
||||
|
@ -1924,6 +1920,9 @@ static void R_CreateDrawNodes(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (tempskip)
|
||||
return;
|
||||
|
||||
#ifdef POLYOBJECTS_PLANES
|
||||
// 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
|
||||
|
@ -1940,17 +1939,19 @@ 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
@ -1958,7 +1959,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)
|
||||
{
|
||||
|
@ -2097,9 +2098,9 @@ static void R_CreateDrawNodes(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (r2 == &nodehead)
|
||||
if (r2 == head)
|
||||
{
|
||||
entry = R_CreateDrawNode(&nodehead);
|
||||
entry = R_CreateDrawNode(head);
|
||||
entry->sprite = rover;
|
||||
}
|
||||
}
|
||||
|
@ -2141,25 +2142,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;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2185,7 +2185,7 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
|
|||
|
||||
// R_ClipSprites
|
||||
// Clips vissprites without drawing, so that portals can work. -Red
|
||||
void R_ClipSprites(void)
|
||||
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
||||
{
|
||||
vissprite_t *spr;
|
||||
for (; clippedvissprites < visspritecount; clippedvissprites++)
|
||||
|
@ -2211,7 +2211,7 @@ void R_ClipSprites(void)
|
|||
// and buggy, by going past LEFT end of array:
|
||||
|
||||
// for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code
|
||||
for (ds = ds_p; ds-- > drawsegs ;)
|
||||
for (ds = ds_p; ds-- > dsstart;)
|
||||
{
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 > spr->x2 ||
|
||||
|
@ -2223,34 +2223,37 @@ void R_ClipSprites(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
|
||||
continue; // is a portal
|
||||
if (ds->portalpass != 66)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// clip this piece of the sprite
|
||||
silhouette = ds->silhouette;
|
||||
|
||||
|
@ -2367,20 +2370,29 @@ void R_ClipSprites(void)
|
|||
//Fab : 26-04-98: was -1, now clips against console bottom
|
||||
spr->cliptop[x] = (INT16)con_clipviewtop;
|
||||
}
|
||||
|
||||
if (portal)
|
||||
{
|
||||
for (x = spr->x1; x <= spr->x2; 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
|
@ -2432,7 +2444,38 @@ void R_DrawMasked(void)
|
|||
r2 = next;
|
||||
}
|
||||
}
|
||||
R_ClearDrawNodes();
|
||||
}
|
||||
|
||||
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
|
||||
{
|
||||
drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */
|
||||
INT8 i;
|
||||
|
||||
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 (i = 0; i < nummasks; i++)
|
||||
// CONS_Printf("Mask no.%d:\ndrawsegs: %d\n vissprites: %d\n\n", i, masks[i].drawsegs[1] - masks[i].drawsegs[0], masks[i].vissprites[1] - masks[i].vissprites[0]);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "sounds.h"
|
||||
#include "r_plane.h"
|
||||
#include "r_portal.h"
|
||||
|
||||
// "Left" and "Right" character symbols for additional rotation functionality
|
||||
#define ROT_L ('L' - '0')
|
||||
|
@ -45,7 +46,6 @@ extern fixed_t windowbottom;
|
|||
|
||||
void R_DrawMaskedColumn(column_t *column);
|
||||
void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight);
|
||||
void R_SortVisSprites(void);
|
||||
|
||||
//faB: find sprites in wadfile, replace existing, add new ones
|
||||
// (only sprites from namelist are added or replaced)
|
||||
|
@ -55,8 +55,21 @@ void R_AddSpriteDefs(UINT16 wadnum);
|
|||
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
||||
void R_InitSprites(void);
|
||||
void R_ClearSprites(void);
|
||||
void R_ClipSprites(void);
|
||||
void R_DrawMasked(void);
|
||||
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
|
||||
|
||||
/** 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, UINT8 nummasks);
|
||||
|
||||
// -----------
|
||||
// SKINS STUFF
|
||||
|
@ -207,6 +220,7 @@ typedef struct drawnode_s
|
|||
|
||||
extern INT32 numskins;
|
||||
extern skin_t skins[MAXSKINS];
|
||||
extern UINT32 visspritecount;
|
||||
|
||||
void SetPlayerSkin(INT32 playernum,const char *skinname);
|
||||
void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
|
||||
|
|
Loading…
Reference in a new issue