Fixes to rendering

This commit is contained in:
Lactozilla 2023-06-26 15:05:00 -03:00
parent 982ce8a62c
commit c2ff2c4f94
13 changed files with 190 additions and 411 deletions

View file

@ -298,6 +298,31 @@ gamestate_t wipegamestate = GS_LEVEL;
INT16 wipetypepre = -1; INT16 wipetypepre = -1;
INT16 wipetypepost = -1; INT16 wipetypepost = -1;
static void D_RenderView(UINT32 viewnum)
{
player_t *player = viewnum == 1 ? &players[secondarydisplayplayer] : &players[displayplayer];
R_PrepareViewWorld(player);
if (viewworld == NULL)
return;
R_ApplyLevelInterpolators(viewworld, R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
if (player->mo || player->playerstate == PST_DEAD)
{
R_SetViewNum(viewnum);
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(viewnum, player);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(player);
}
}
static void D_Display(void) static void D_Display(void)
{ {
boolean forcerefresh = false; boolean forcerefresh = false;
@ -478,42 +503,17 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value) if (!automapactive && !dedicated && cv_renderview.value)
{ {
R_ApplyLevelInterpolators(players[displayplayer].world, R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
PS_START_TIMING(ps_rendercalltime); PS_START_TIMING(ps_rendercalltime);
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) objectsdrawn = 0;
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx; D_RenderView(0);
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen // render the second screen
if (splitscreen && players[secondarydisplayplayer].mo) if (splitscreen)
{ D_RenderView(1);
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx; for (INT32 wi = 0; wi < numworlds; wi++)
worldlist[wi]->interpolated_level_this_frame = false;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect // Image postprocessing effect
if (rendermode == render_soft) if (rendermode == render_soft)

View file

@ -23,17 +23,15 @@
#include "../i_video.h" #include "../i_video.h"
#include "../w_wad.h" #include "../w_wad.h"
#include "../p_setup.h" // levelfadecol #include "../p_setup.h" // levelfadecol
#include "../p_world.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// This is global data for planes rendering // This is global data for planes rendering
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
extrasubsector_t *extrasubsectors = NULL;
// newsubsectors are subsectors without segs, added for the plane polygons // newsubsectors are subsectors without segs, added for the plane polygons
#define NEWSUBSECTORS 50 #define NEWSUBSECTORS 50
static size_t totsubsectors; static size_t totsubsectors;
size_t addsubsector;
typedef struct typedef struct
{ {
@ -45,121 +43,24 @@ typedef struct
// FLOOR & CEILING CONVEX POLYS GENERATION // FLOOR & CEILING CONVEX POLYS GENERATION
// ========================================================================== // ==========================================================================
//debug counters
static INT32 nobackpoly = 0;
static INT32 skipcut = 0;
static INT32 totalsubsecpolys = 0;
// --------------------------------------------------------------------------
// Polygon fast alloc / free
// --------------------------------------------------------------------------
//hurdler: quick fix for those who wants to play with larger wad
#define ZPLANALLOC
#ifndef ZPLANALLOC
//#define POLYPOOLSIZE 1024000 // may be much over what is needed
/// \todo check out how much is used
static size_t POLYPOOLSIZE = 1024000;
static UINT8 *gl_polypool = NULL;
static UINT8 *gl_ppcurrent;
static size_t gl_ppfree;
#endif
// only between levels, clear poly pool
static void HWR_ClearPolys(void)
{
#ifndef ZPLANALLOC
gl_ppcurrent = gl_polypool;
gl_ppfree = POLYPOOLSIZE;
#endif
}
// allocate pool for fast alloc of polys
void HWR_InitPolyPool(void)
{
#ifndef ZPLANALLOC
INT32 pnum;
//hurdler: quick fix for those who wants to play with larger wad
if ((pnum = M_CheckParm("-polypoolsize")))
POLYPOOLSIZE = atoi(myargv[pnum+1])*1024; // (in kb)
CONS_Debug(DBG_RENDER, "HWR_InitPolyPool(): allocating %d bytes\n", POLYPOOLSIZE);
gl_polypool = malloc(POLYPOOLSIZE);
if (!gl_polypool)
I_Error("HWR_InitPolyPool(): couldn't malloc polypool\n");
HWR_ClearPolys();
#endif
}
void HWR_FreePolyPool(void)
{
#ifndef ZPLANALLOC
if (gl_polypool)
free(gl_polypool);
gl_polypool = NULL;
#endif
}
static poly_t *HWR_AllocPoly(INT32 numpts) static poly_t *HWR_AllocPoly(INT32 numpts)
{ {
poly_t *p;
size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * numpts; size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * numpts;
#ifdef ZPLANALLOC poly_t *p = Z_Malloc(size, PU_HWRPLANE, NULL);
p = Z_Malloc(size, PU_HWRPLANE, NULL);
#else
#ifdef PARANOIA
if (!gl_polypool)
I_Error("Used gl_polypool without init!\n");
if (!gl_ppcurrent)
I_Error("gl_ppcurrent == NULL!\n");
#endif
if (gl_ppfree < size)
I_Error("HWR_AllocPoly(): no more memory %u bytes left, %u bytes needed\n\n%s\n",
gl_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)");
p = (poly_t *)gl_ppcurrent;
gl_ppcurrent += size;
gl_ppfree -= size;
#endif
p->numpts = numpts; p->numpts = numpts;
return p; return p;
} }
static polyvertex_t *HWR_AllocVertex(void) static polyvertex_t *HWR_AllocVertex(void)
{ {
polyvertex_t *p; return Z_Malloc(sizeof (polyvertex_t), PU_HWRPLANE, NULL);
size_t size = sizeof (polyvertex_t);
#ifdef ZPLANALLOC
p = Z_Malloc(size, PU_HWRPLANE, NULL);
#else
if (gl_ppfree < size)
I_Error("HWR_AllocVertex(): no more memory %u bytes left, %u bytes needed\n\n%s\n",
gl_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)");
p = (polyvertex_t *)gl_ppcurrent;
gl_ppcurrent += size;
gl_ppfree -= size;
#endif
return p;
} }
/// \todo polygons should be freed in reverse order for efficiency,
/// for now don't free because it doesn't free in reverse order
static void HWR_FreePoly(poly_t *poly) static void HWR_FreePoly(poly_t *poly)
{ {
#ifdef ZPLANALLOC
Z_Free(poly); Z_Free(poly);
#else
const size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * poly->numpts;
memset(poly, 0x00, size);
//mempoly -= polysize;
#endif
} }
// Return interception along bsp line, // Return interception along bsp line,
// with the polygon segment // with the polygon segment
// //
@ -532,9 +433,6 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
// only when the cut is not needed it seems (when the cut // only when the cut is not needed it seems (when the cut
// line is aligned to one of the borders of the poly, and // line is aligned to one of the borders of the poly, and
// only some times..) // only some times..)
else
skipcut++;
// I_Error("CutOutPoly: only one point for split line (%d %d) %d", ps, pe, debugpos);
} }
} }
return poly; return poly;
@ -551,16 +449,15 @@ static inline void HWR_SubsecPoly(INT32 num, poly_t *poly)
subsector_t *sub; subsector_t *sub;
seg_t *lseg; seg_t *lseg;
sub = &subsectors[num]; sub = &world->subsectors[num];
count = sub->numlines; count = sub->numlines;
lseg = &segs[sub->firstline]; lseg = &world->segs[sub->firstline];
if (poly) if (poly)
{ {
poly = CutOutSubsecPoly (lseg,count,poly); poly = CutOutSubsecPoly (lseg,count,poly);
totalsubsecpolys++;
//extra data for this subsector //extra data for this subsector
extrasubsectors[num].planepoly = poly; world->extrasubsectors[num].planepoly = poly;
} }
} }
@ -627,13 +524,13 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
if (poly && poly->numpts > 2) if (poly && poly->numpts > 2)
{ {
CONS_Debug(DBG_RENDER, "Adding a new subsector\n"); CONS_Debug(DBG_RENDER, "Adding a new subsector\n");
if (addsubsector == numsubsectors + NEWSUBSECTORS) if (world->numextrasubsectors == numsubsectors + NEWSUBSECTORS)
I_Error("WalkBSPNode: not enough addsubsectors\n"); I_Error("WalkBSPNode: not enough addsubsectors\n");
else if (addsubsector > 0x7fff) else if (world->numextrasubsectors > 0x7fff)
I_Error("WalkBSPNode: addsubsector > 0x7fff\n"); I_Error("WalkBSPNode: addsubsector > 0x7fff\n");
*leafnode = (UINT16)((UINT16)addsubsector | NF_SUBSECTOR); *leafnode = (UINT16)((UINT16)world->numextrasubsectors | NF_SUBSECTOR);
extrasubsectors[addsubsector].planepoly = poly; world->extrasubsectors[world->numextrasubsectors].planepoly = poly;
addsubsector++; world->numextrasubsectors++;
} }
//add subsectors without segs here? //add subsectors without segs here?
@ -653,7 +550,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
#endif #endif
} }
M_ClearBox(bbox); M_ClearBox(bbox);
poly = extrasubsectors[bspnum & ~NF_SUBSECTOR].planepoly; poly = world->extrasubsectors[bspnum & ~NF_SUBSECTOR].planepoly;
for (i = 0, pt = poly->pts; i < poly->numpts; i++,pt++) for (i = 0, pt = poly->pts; i < poly->numpts; i++,pt++)
M_AddToBox(bbox, FLOAT_TO_FIXED(pt->x), FLOAT_TO_FIXED(pt->y)); M_AddToBox(bbox, FLOAT_TO_FIXED(pt->x), FLOAT_TO_FIXED(pt->y));
@ -666,10 +563,6 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
SplitPoly(&fdivline, poly, &frontpoly, &backpoly); SplitPoly(&fdivline, poly, &frontpoly, &backpoly);
poly = NULL; poly = NULL;
//debug
if (!backpoly)
nobackpoly++;
// Recursively divide front space. // Recursively divide front space.
if (frontpoly) if (frontpoly)
{ {
@ -696,11 +589,10 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
} }
// FIXME: use Z_Malloc() STATIC ? // FIXME: use Z_Malloc() STATIC ?
void HWR_FreeExtraSubsectors(void) void HWR_FreeExtraSubsectors(extrasubsector_t *sub)
{ {
if (extrasubsectors) if (sub)
free(extrasubsectors); free(sub);
extrasubsectors = NULL;
} }
#define MAXDIST 1.5f #define MAXDIST 1.5f
@ -774,7 +666,7 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
if (bspnum != -1) if (bspnum != -1)
{ {
bspnum &= ~NF_SUBSECTOR; bspnum &= ~NF_SUBSECTOR;
q = extrasubsectors[bspnum].planepoly; q = world->extrasubsectors[bspnum].planepoly;
if (poly == q || !q) if (poly == q || !q)
return; return;
for (j = 0; j < q->numpts; j++) for (j = 0; j < q->numpts; j++)
@ -795,7 +687,7 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
for (n = k+1; n < newpoly->numpts; n++) for (n = k+1; n < newpoly->numpts; n++)
newpoly->pts[n] = q->pts[n-1]; newpoly->pts[n] = q->pts[n-1];
numsplitpoly++; numsplitpoly++;
extrasubsectors[bspnum].planepoly = world->extrasubsectors[bspnum].planepoly =
newpoly; newpoly;
HWR_FreePoly(q); HWR_FreePoly(q);
return; return;
@ -840,9 +732,9 @@ static INT32 SolveTProblem(void)
numsplitpoly = 0; numsplitpoly = 0;
for (l = 0; l < addsubsector; l++) for (l = 0; l < world->numextrasubsectors; l++)
{ {
p = extrasubsectors[l].planepoly; p = world->extrasubsectors[l].planepoly;
if (p) if (p)
for (i = 0; i < p->numpts; i++) for (i = 0; i < p->numpts; i++)
SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p); SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p);
@ -870,9 +762,9 @@ static void AdjustSegs(void)
for (i = 0; i < numsubsectors; i++) for (i = 0; i < numsubsectors; i++)
{ {
count = subsectors[i].numlines; count = world->subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline]; lseg = &world->segs[world->subsectors[i].firstline];
p = extrasubsectors[i].planepoly; p = world->extrasubsectors[i].planepoly;
//if (!p) //if (!p)
//continue; //continue;
for (; count--; lseg++) for (; count--; lseg++)
@ -955,40 +847,28 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
{ {
poly_t *rootp; poly_t *rootp;
polyvertex_t *rootpv; polyvertex_t *rootpv;
size_t i;
fixed_t rootbbox[4]; fixed_t rootbbox[4];
CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n"); CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n");
#ifdef HWR_LOADING_SCREEN #ifdef HWR_LOADING_SCREEN
ls_count = ls_percent = 0; // reset the loading status ls_count = ls_percent = 0; // reset the loading status
CON_Drawer(); //let the user know what we are doing CON_Drawer(); //let the user know what we are doing
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
#endif #endif
HWR_ClearPolys();
// find min/max boundaries of map // find min/max boundaries of map
//CONS_Debug(DBG_RENDER, "Looking for boundaries of map...\n");
M_ClearBox(rootbbox); M_ClearBox(rootbbox);
for (i = 0;i < numvertexes; i++) for (size_t i = 0; i < world->numvertexes; i++)
M_AddToBox(rootbbox, vertexes[i].x, vertexes[i].y); M_AddToBox(rootbbox, world->vertexes[i].x, world->vertexes[i].y);
//CONS_Debug(DBG_RENDER, "Generating subsector polygons... %d subsectors\n", numsubsectors);
HWR_FreeExtraSubsectors();
// allocate extra data for each subsector present in map // allocate extra data for each subsector present in map
totsubsectors = numsubsectors + NEWSUBSECTORS; totsubsectors = world->numsubsectors + NEWSUBSECTORS;
extrasubsectors = calloc(totsubsectors, sizeof (*extrasubsectors)); world->extrasubsectors = calloc(totsubsectors, sizeof (*world->extrasubsectors));
if (extrasubsectors == NULL) if (world->extrasubsectors == NULL)
I_Error("couldn't malloc extrasubsectors totsubsectors %s\n", sizeu1(totsubsectors)); I_Error("couldn't malloc extrasubsectors totsubsectors %s\n", sizeu1(totsubsectors));
// allocate table for back to front drawing of subsectors world->numextrasubsectors = world->numsubsectors; // number of the first new subsector that might be added
/*gl_drawsubsectors = (INT16 *)malloc(sizeof (*gl_drawsubsectors) * totsubsectors);
if (!gl_drawsubsectors)
I_Error("couldn't malloc gl_drawsubsectors\n");*/
// number of the first new subsector that might be added
addsubsector = numsubsectors;
// construct the initial convex poly that encloses the full map // construct the initial convex poly that encloses the full map
rootp = HWR_AllocPoly(4); rootp = HWR_AllocPoly(4);
@ -1007,20 +887,10 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXBOTTOM]); //ll rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXBOTTOM]); //ll
rootpv++; rootpv++;
WalkBSPNode(bspnum, rootp, NULL,rootbbox); WalkBSPNode(bspnum, rootp, NULL, rootbbox);
i = SolveTProblem(); SolveTProblem();
//CONS_Debug(DBG_RENDER, "%d point divides a polygon line\n",i);
AdjustSegs(); AdjustSegs();
//debug debug..
//if (nobackpoly)
// CONS_Debug(DBG_RENDER, "no back polygon %u times\n",nobackpoly);
//"(should happen only with the deep water trick)"
//if (skipcut)
// CONS_Debug(DBG_RENDER, "%u cuts were skipped because of only one point\n",skipcut);
//CONS_Debug(DBG_RENDER, "done: %u total subsector convex polygons\n", totalsubsecpolys);
} }
#endif //HWRENDER #endif //HWRENDER

View file

@ -28,35 +28,6 @@
// structures // structures
// ----------- // -----------
// a vertex of a Doom 'plane' polygon
typedef struct
{
float x;
float y;
float z;
} polyvertex_t;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
// a convex 'plane' polygon, clockwise order
typedef struct
{
INT32 numpts;
polyvertex_t pts[0];
} poly_t;
#ifdef _MSC_VER
#pragma warning(default : 4200)
#endif
// holds extra info for 3D render, for each subsector in subsectors[]
typedef struct
{
poly_t *planepoly; // the generated convex polygon
} extrasubsector_t;
// needed for sprite rendering // needed for sprite rendering
// equivalent of the software renderer's vissprites // equivalent of the software renderer's vissprites
typedef struct gl_vissprite_s typedef struct gl_vissprite_s
@ -97,13 +68,7 @@ typedef struct gl_vissprite_s
// -------- // --------
// hw_bsp.c // hw_bsp.c
// -------- // --------
extern extrasubsector_t *extrasubsectors; void HWR_FreeExtraSubsectors(extrasubsector_t *sub);
extern size_t addsubsector;
void HWR_InitPolyPool(void);
void HWR_FreePolyPool(void);
void HWR_FreeExtraSubsectors(void);
// -------- // --------
// hw_cache.c // hw_cache.c

View file

@ -50,7 +50,6 @@
#define R_FAKEFLOORS #define R_FAKEFLOORS
#define HWPRECIP #define HWPRECIP
//#define POLYSKY
// ========================================================================== // ==========================================================================
// the hardware driver object // the hardware driver object
@ -102,10 +101,6 @@ static angle_t gl_xtoviewangle[MAXVIDWIDTH+1];
#define DOPLANES #define DOPLANES
//#define DOWALLS //#define DOWALLS
// test of drawing sky by polygons like in software with visplane, unfortunately
// this doesn't work since we must have z for pixel and z for texture (not like now with z = oow)
//#define POLYSKY
// test change fov when looking up/down but bsp projection messup :( // test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK //#define NOCRAPPYMLOOK
@ -639,51 +634,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
HWR_PlaneLighting(planeVerts, nrPlaneVerts); HWR_PlaneLighting(planeVerts, nrPlaneVerts);
#endif #endif
} }
#ifdef POLYSKY
// this don't draw anything it only update the z-buffer so there isn't problem with
// wall/things upper that sky (map12)
static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight)
{
polyvertex_t *pv;
float height; //constant y for all points on the convex flat polygon
FOutVector *v3d;
INT32 nrPlaneVerts; //verts original define of convex flat polygon
INT32 i;
// no convex poly were generated for this subsector
if (!xsub->planepoly)
return;
height = FIXED_TO_FLOAT(fixedheight);
pv = xsub->planepoly->pts;
nrPlaneVerts = xsub->planepoly->numpts;
if (nrPlaneVerts < 3) // not even a triangle?
return;
if (nrPlaneVerts > MAXPLANEVERTICES) // FIXME: exceeds plVerts size
{
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, MAXPLANEVERTICES);
return;
}
// transform
v3d = planeVerts;
for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
{
v3d->s = 0.0f;
v3d->t = 0.0f;
v3d->x = pv->x;
v3d->y = height;
v3d->z = pv->y;
}
HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, PF_Invisible|PF_NoTexture|PF_Occlude);
}
#endif //polysky
#endif //doplanes #endif //doplanes
FBITFIELD HWR_GetBlendModeFlag(INT32 style) FBITFIELD HWR_GetBlendModeFlag(INT32 style)
@ -2903,14 +2853,9 @@ static void HWR_Subsector(size_t num)
ffloor_t *rover; ffloor_t *rover;
#ifdef PARANOIA //no risk while developing, enough debugging nights! #ifdef PARANOIA //no risk while developing, enough debugging nights!
if (num >= addsubsector) if (num >= world->numextrasubsectors)
I_Error("HWR_Subsector: ss %s with numss = %s, addss = %s\n", I_Error("HWR_Subsector: ss %s with numss = %s, addss = %s\n",
sizeu1(num), sizeu2(numsubsectors), sizeu3(addsubsector)); sizeu1(num), sizeu2(numsubsectors), sizeu3(world->numextrasubsectors));
/*if (num >= numsubsectors)
I_Error("HWR_Subsector: ss %i with numss = %i",
num,
numsubsectors);*/
#endif #endif
if (num < numsubsectors) if (num < numsubsectors)
@ -3005,19 +2950,13 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount) if (sub->validcount != validcount)
{ {
HWR_GetLevelFlat(&viewworld->flats[gl_frontsector->floorpic]); HWR_GetLevelFlat(&viewworld->flats[gl_frontsector->floorpic]);
HWR_RenderPlane(sub, &extrasubsectors[num], false, HWR_RenderPlane(sub, &world->extrasubsectors[num], false,
// Hack to make things continue to work around slopes. // Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight, locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight,
// We now return you to your regularly scheduled rendering. // We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, &viewworld->flats[gl_frontsector->floorpic], NULL, 255, floorcolormap); PF_Occlude, floorlightlevel, &viewworld->flats[gl_frontsector->floorpic], NULL, 255, floorcolormap);
} }
} }
else
{
#ifdef POLYSKY
HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight);
#endif
}
} }
if (cullCeilingHeight > dup_viewz) if (cullCeilingHeight > dup_viewz)
@ -3027,26 +2966,18 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount) if (sub->validcount != validcount)
{ {
HWR_GetLevelFlat(&viewworld->flats[gl_frontsector->ceilingpic]); HWR_GetLevelFlat(&viewworld->flats[gl_frontsector->ceilingpic]);
HWR_RenderPlane(sub, &extrasubsectors[num], true, HWR_RenderPlane(sub, &world->extrasubsectors[num], true,
// Hack to make things continue to work around slopes. // Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight, locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering. // We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, &viewworld->flats[gl_frontsector->ceilingpic], NULL, 255, ceilingcolormap); PF_Occlude, ceilinglightlevel, &viewworld->flats[gl_frontsector->ceilingpic], NULL, 255, ceilingcolormap);
} }
} }
else
{
#ifdef POLYSKY
HWR_RenderSkyPlane(&extrasubsectors[num], locCeilingHeight);
#endif
}
} }
#ifndef POLYSKY
// Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky // Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky
if (gl_frontsector->ceilingpic == viewworld->skyflatnum || gl_frontsector->floorpic == viewworld->skyflatnum) if (gl_frontsector->ceilingpic == viewworld->skyflatnum || gl_frontsector->floorpic == viewworld->skyflatnum)
drawsky = true; drawsky = true;
#endif
#ifdef R_FAKEFLOORS #ifdef R_FAKEFLOORS
if (gl_frontsector->ffloors) if (gl_frontsector->ffloors)
@ -3078,9 +3009,9 @@ static void HWR_Subsector(size_t num)
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0, HWR_AddTransparentFloor(NULL,
&extrasubsectors[num], &world->extrasubsectors[num],
false, false,
*rover->bottomheight, *rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel, *gl_frontsector->lightlist[light].lightlevel,
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
@ -3090,9 +3021,9 @@ static void HWR_Subsector(size_t num)
{ {
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_AddTransparentFloor(&world->flats[*rover->bottompic], HWR_AddTransparentFloor(&viewworld->flats[*rover->bottompic],
&extrasubsectors[num], &world->extrasubsectors[num],
false, false,
*rover->bottomheight, *rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel, *gl_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector,
@ -3101,9 +3032,9 @@ static void HWR_Subsector(size_t num)
} }
else else
{ {
HWR_GetLevelFlat(&world->flats[*rover->bottompic]); HWR_GetLevelFlat(&viewworld->flats[*rover->bottompic]);
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &world->flats[*rover->bottompic], HWR_RenderPlane(sub, &world->extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &viewworld->flats[*rover->bottompic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
} }
} }
@ -3124,21 +3055,21 @@ static void HWR_Subsector(size_t num)
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0, HWR_AddTransparentFloor(NULL,
&extrasubsectors[num], &world->extrasubsectors[num],
true, true,
*rover->topheight, *rover->topheight,
*gl_frontsector->lightlist[light].lightlevel, *gl_frontsector->lightlist[light].lightlevel,
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, rover->master->frontsector->extra_colormap); true, rover->master->frontsector->extra_colormap);
} }
else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
{ {
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_AddTransparentFloor(&world->flats[*rover->toppic], HWR_AddTransparentFloor(&viewworld->flats[*rover->toppic],
&extrasubsectors[num], &world->extrasubsectors[num],
true, true,
*rover->topheight, *rover->topheight,
*gl_frontsector->lightlist[light].lightlevel, *gl_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector,
@ -3147,9 +3078,9 @@ static void HWR_Subsector(size_t num)
} }
else else
{ {
HWR_GetLevelFlat(&world->flats[*rover->toppic]); HWR_GetLevelFlat(&viewworld->flats[*rover->toppic]);
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &world->flats[*rover->toppic], HWR_RenderPlane(sub, &world->extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &viewworld->flats[*rover->toppic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
} }
} }
@ -3249,33 +3180,6 @@ fixed_t *hwbbox;
static void HWR_RenderBSPNode(INT32 bspnum) static void HWR_RenderBSPNode(INT32 bspnum)
{ {
/*//GZDoom code
if(bspnum == -1)
{
HWR_Subsector(subsectors);
return;
}
while(!((size_t)bspnum&(~NF_SUBSECTOR))) // Keep going until found a subsector
{
node_t *bsp = &nodes[bspnum];
// Decide which side the view point is on
INT32 side = R_PointOnSide(dup_viewx, dup_viewy, bsp);
// Recursively divide front space (toward the viewer)
HWR_RenderBSPNode(bsp->children[side]);
// Possibly divide back space (away from viewer)
side ^= 1;
if (!HWR_CheckBBox(bsp->bbox[side]))
return;
bspnum = bsp->children[side];
}
HWR_Subsector(bspnum-1);
*/
node_t *bsp = &nodes[bspnum]; node_t *bsp = &nodes[bspnum];
// Decide which side the view point is on // Decide which side the view point is on
@ -3288,12 +3192,10 @@ static void HWR_RenderBSPNode(INT32 bspnum)
{ {
if (bspnum == -1) if (bspnum == -1)
{ {
//*(gl_drawsubsector_p++) = 0;
HWR_Subsector(0); HWR_Subsector(0);
} }
else else
{ {
//*(gl_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR);
HWR_Subsector(bspnum&(~NF_SUBSECTOR)); HWR_Subsector(bspnum&(~NF_SUBSECTOR));
} }
return; return;
@ -3317,28 +3219,6 @@ static void HWR_RenderBSPNode(INT32 bspnum)
} }
} }
/*
//
// Clear 'stack' of subsectors to draw
//
static void HWR_ClearDrawSubsectors(void)
{
gl_drawsubsector_p = gl_drawsubsectors;
}
//
// Draw subsectors pushed on the drawsubsectors 'stack', back to front
//
static void HWR_RenderSubsectors(void)
{
while (gl_drawsubsector_p > gl_drawsubsectors)
{
HWR_RenderBSPNode(
lastsubsec->nextsubsec = bspnum & (~NF_SUBSECTOR);
}
}
*/
// ========================================================================== // ==========================================================================
// FROM R_MAIN.C // FROM R_MAIN.C
// ========================================================================== // ==========================================================================
@ -6189,7 +6069,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
const boolean skybox = (world->skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on const boolean skybox = viewworld->skyboxmo[0] && cv_skybox.value; // True if there's a skybox object and skyboxes are on
FRGBAFloat ClearColor; FRGBAFloat ClearColor;
@ -6418,7 +6298,8 @@ void HWR_LoadLevel(void)
HWR_ResetLights(); HWR_ResetLights();
#endif #endif
HWR_CreatePlanePolygons((INT32)numnodes - 1); if (world->extrasubsectors == NULL)
HWR_CreatePlanePolygons((INT32)world->numnodes - 1);
// Build the sky dome // Build the sky dome
HWR_ClearSkyDome(); HWR_ClearSkyDome();
@ -6537,7 +6418,6 @@ void HWR_Startup(void)
{ {
CONS_Printf("HWR_Startup()...\n"); CONS_Printf("HWR_Startup()...\n");
HWR_InitPolyPool();
HWR_AddSessionCommands(); HWR_AddSessionCommands();
HWR_InitMapTextures(); HWR_InitMapTextures();
HWR_InitModels(); HWR_InitModels();
@ -6587,8 +6467,6 @@ void HWR_Switch(void)
void HWR_Shutdown(void) void HWR_Shutdown(void)
{ {
CONS_Printf("HWR_Shutdown()\n"); CONS_Printf("HWR_Shutdown()\n");
HWR_FreeExtraSubsectors();
HWR_FreePolyPool();
HWR_FreeMapTextures(); HWR_FreeMapTextures();
HWD.pfnFlushScreenTextures(); HWD.pfnFlushScreenTextures();
} }

View file

@ -7853,9 +7853,6 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo
#ifdef HWRENDER // not win32 only 19990829 by Kin #ifdef HWRENDER // not win32 only 19990829 by Kin
gl_maploaded = false; gl_maploaded = false;
// Lactozilla: Free extrasubsectors regardless of renderer.
HWR_FreeExtraSubsectors();
// Create plane polygons. // Create plane polygons.
if (rendermode == render_opengl) if (rendermode == render_opengl)
HWR_LoadLevel(); HWR_LoadLevel();
@ -7941,7 +7938,7 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo
R_ResetViewInterpolation(0); R_ResetViewInterpolation(0);
R_ResetViewInterpolation(0); R_ResetViewInterpolation(0);
R_UpdateMobjInterpolators(); R_UpdateMobjInterpolators(world);
// Title card! // Title card!
G_StartTitleCard(); G_StartTitleCard();

View file

@ -762,7 +762,7 @@ void P_Ticker(boolean run)
if (OP_FreezeObjectplace()) if (OP_FreezeObjectplace())
{ {
P_MapStart(); P_MapStart();
R_UpdateMobjInterpolators(); R_UpdateMobjInterpolators(world);
OP_ObjectplaceMovement(&players[0]); OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera, false); P_MoveChaseCamera(&players[0], &camera, false);
R_UpdateViewInterpolation(); R_UpdateViewInterpolation();
@ -788,7 +788,7 @@ void P_Ticker(boolean run)
if (run) if (run)
{ {
R_UpdateMobjInterpolators(); R_UpdateMobjInterpolators(world);
if (demorecording) if (demorecording)
G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0);
@ -962,8 +962,6 @@ void P_Ticker(boolean run)
} }
P_MapEnd(); P_MapEnd();
// Z_CheckMemCleanup();
} }
// Abbreviated ticker for pre-loading, calls thinkers and assorted things // Abbreviated ticker for pre-loading, calls thinkers and assorted things
@ -981,7 +979,7 @@ void P_PreTicker(INT32 frames)
{ {
P_MapStart(); P_MapStart();
R_UpdateMobjInterpolators(); R_UpdateMobjInterpolators(world);
RunLuaHookForWorld(HOOK(PreThinkFrame)); RunLuaHookForWorld(HOOK(PreThinkFrame));

View file

@ -253,11 +253,6 @@ void P_SwitchWorld(player_t *player, world_t *w)
boolean local = ((INT32)playernum == consoleplayer); boolean local = ((INT32)playernum == consoleplayer);
boolean resetplayer = (player->powers[pw_carry] != CR_PLAYER); boolean resetplayer = (player->powers[pw_carry] != CR_PLAYER);
#if 0
if (w == player->world)
return;
#endif
if (!playeringame[playernum] || !player->mo || P_MobjWasRemoved(player->mo)) if (!playeringame[playernum] || !player->mo || P_MobjWasRemoved(player->mo))
return; return;
@ -303,6 +298,11 @@ void P_SwitchWorld(player_t *player, world_t *w)
if (resetplayer) if (resetplayer)
P_ResetPlayer(player); P_ResetPlayer(player);
P_MapEnd(); P_MapEnd();
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_LoadLevel();
#endif
} }
void Command_Switchworld_f(void) void Command_Switchworld_f(void)
@ -367,6 +367,12 @@ void P_UnloadWorld(world_t *w)
LUA_InvalidateLevel(w); LUA_InvalidateLevel(w);
P_UnloadSectorAttachments(w->sectors, w->numsectors); P_UnloadSectorAttachments(w->sectors, w->numsectors);
if (world->extrasubsectors)
{
HWR_FreeExtraSubsectors(world->extrasubsectors);
world->extrasubsectors = NULL;
}
} }
// //

View file

@ -26,10 +26,9 @@
#define NUMWAYPOINTSEQUENCES 256 #define NUMWAYPOINTSEQUENCES 256
// //
// Lactozilla: A "world" is the environment that players interact with. // A "world" is the environment that players interact with
// A "map" is what defines how the world is built (what you edit in a level editor.) // A "map" is what defines how the world is built (what you edit in a level editor)
// And you could say that a "level" both describes metadata about that "map" (level headers), and contains a world. // And a "level" both describes metadata (level headers), and contains many worlds
// (This is my terminology anyway, "map" and "level" are usually interchangeable.)
// //
typedef struct typedef struct
{ {
@ -48,6 +47,9 @@ typedef struct
side_t *sides; side_t *sides;
mapthing_t *mapthings; mapthing_t *mapthings;
extrasubsector_t *extrasubsectors;
size_t numextrasubsectors;
sector_t *spawnsectors; sector_t *spawnsectors;
line_t *spawnlines; line_t *spawnlines;
side_t *spawnsides; side_t *spawnsides;
@ -126,6 +128,8 @@ typedef struct
void **interpolated_mobjs; void **interpolated_mobjs;
size_t interpolated_mobjs_len; size_t interpolated_mobjs_len;
size_t interpolated_mobjs_capacity; size_t interpolated_mobjs_capacity;
boolean interpolated_level_this_frame;
} world_t; } world_t;
extern world_t *world; extern world_t *world;

View file

@ -714,6 +714,35 @@ typedef struct
UINT16 children[2]; UINT16 children[2];
} node_t; } node_t;
// a vertex of a Doom 'plane' polygon
typedef struct
{
float x;
float y;
float z;
} polyvertex_t;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
// a convex 'plane' polygon, clockwise order
typedef struct
{
INT32 numpts;
polyvertex_t pts[0];
} poly_t;
#ifdef _MSC_VER
#pragma warning(default : 4200)
#endif
// holds extra info for 3D render, for each subsector in subsectors[]
typedef struct
{
poly_t *planepoly; // the generated convex polygon
} extrasubsector_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif #endif

View file

@ -556,6 +556,8 @@ void R_ClearLevelInterpolatorState(thinker_t *thinker)
void R_ApplyLevelInterpolators(void *wptr, fixed_t frac) void R_ApplyLevelInterpolators(void *wptr, fixed_t frac)
{ {
world_t *w = (world_t *)wptr; world_t *w = (world_t *)wptr;
if (w->interpolated_level_this_frame)
return;
size_t i, ii; size_t i, ii;
@ -608,6 +610,8 @@ void R_ApplyLevelInterpolators(void *wptr, fixed_t frac)
break; break;
} }
} }
w->interpolated_level_this_frame = true;
} }
static void R_RestoreLevelInterpolatorsForWorld(world_t *w) static void R_RestoreLevelInterpolatorsForWorld(world_t *w)
@ -753,17 +757,24 @@ void R_InitMobjInterpolators(void)
world->interpolated_mobjs_capacity = 0; world->interpolated_mobjs_capacity = 0;
} }
void R_UpdateMobjInterpolators(void) void R_UpdateMobjInterpolators(void *wptr)
{
world_t *w = (world_t *)wptr;
for (size_t i = 0; i < w->interpolated_mobjs_len; i++)
{
mobj_t *mobj = w->interpolated_mobjs[i];
if (!P_MobjWasRemoved(mobj))
R_ResetMobjInterpolationState(mobj);
}
}
void R_UpdateAllMobjInterpolators(void)
{ {
for (INT32 wi = 0; wi < numworlds; wi++) for (INT32 wi = 0; wi < numworlds; wi++)
{ {
world_t *w = worldlist[wi]; world_t *w = worldlist[wi];
for (size_t i = 0; i < w->interpolated_mobjs_len; i++) R_UpdateMobjInterpolators(w);
{
mobj_t *mobj = w->interpolated_mobjs[i];
if (!P_MobjWasRemoved(mobj))
R_ResetMobjInterpolationState(mobj);
}
} }
} }

View file

@ -155,7 +155,8 @@ void R_InitMobjInterpolators(void);
void R_AddMobjInterpolator(mobj_t *mobj); void R_AddMobjInterpolator(mobj_t *mobj);
// Remove the interpolation state for the given mobj // Remove the interpolation state for the given mobj
void R_RemoveMobjInterpolator(mobj_t *mobj); void R_RemoveMobjInterpolator(mobj_t *mobj);
void R_UpdateMobjInterpolators(void); void R_UpdateMobjInterpolators(void *wptr);
void R_UpdateAllMobjInterpolators(void);
void R_ResetMobjInterpolationState(mobj_t *mobj); void R_ResetMobjInterpolationState(mobj_t *mobj);
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj); void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj);

View file

@ -1472,19 +1472,30 @@ static void Mask_Post (maskcount_t* m)
m->vissprites[1] = visspritecount; m->vissprites[1] = visspritecount;
} }
// ================ void R_SetViewNum(UINT32 viewnum)
// R_RenderView {
// ================ if (rendermode != render_soft)
return;
// FAB NOTE FOR WIN32 PORT !! I'm not finished already, switch (viewnum)
// but I suspect network may have problems with the video buffer being locked {
// for all duration of rendering, and being released only once at the end.. case 0:
// I mean, there is a win16lock() or something that lasts all the rendering, viewwindowy = 0;
// so maybe we should release screen lock before each netupdate below..? M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
break;
case 1:
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
break;
}
void R_RenderPlayerView(player_t *player) topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
}
void R_PrepareViewWorld(player_t *player)
{ {
viewworld = NULL; viewworld = NULL;
R_SetViewMobj(player); R_SetViewMobj(player);
if (r_viewmobj) if (r_viewmobj)
@ -1494,8 +1505,14 @@ void R_RenderPlayerView(player_t *player)
else if (localworld && !splitscreen) // Yes? else if (localworld && !splitscreen) // Yes?
P_SetViewWorld(localworld); P_SetViewWorld(localworld);
else else
return; viewworld = worldlist[0];
}
// ================
// R_RenderView
// ================
void R_RenderPlayerView(player_t *player)
{
INT32 nummasks = 1; INT32 nummasks = 1;
maskcount_t* masks = malloc(sizeof(maskcount_t)); maskcount_t* masks = malloc(sizeof(maskcount_t));

View file

@ -140,6 +140,9 @@ void R_ExecuteSetViewSize(void);
void R_SetupFrame(player_t *player); void R_SetupFrame(player_t *player);
void R_SkyboxFrame(player_t *player); void R_SkyboxFrame(player_t *player);
void R_SetViewNum(UINT32 viewnum);
void R_PrepareViewWorld(player_t *player);
boolean R_ViewpointHasChasecam(player_t *player); boolean R_ViewpointHasChasecam(player_t *player);
boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox); boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox);