From c2ff2c4f947a9a80cad36c06ad7a08ee4394c8a4 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 26 Jun 2023 15:05:00 -0300 Subject: [PATCH] Fixes to rendering --- src/d_main.c | 64 +++++++------- src/hardware/hw_bsp.c | 192 +++++++---------------------------------- src/hardware/hw_glob.h | 37 +------- src/hardware/hw_main.c | 170 ++++++------------------------------ src/p_setup.c | 5 +- src/p_tick.c | 8 +- src/p_world.c | 16 ++-- src/p_world.h | 12 ++- src/r_defs.h | 29 +++++++ src/r_fps.c | 25 ++++-- src/r_fps.h | 3 +- src/r_main.c | 37 +++++--- src/r_main.h | 3 + 13 files changed, 190 insertions(+), 411 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index fe10f6a38..d2d796fda 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -298,6 +298,31 @@ gamestate_t wipegamestate = GS_LEVEL; INT16 wipetypepre = -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) { boolean forcerefresh = false; @@ -478,42 +503,17 @@ static void D_Display(void) if (!automapactive && !dedicated && cv_renderview.value) { - R_ApplyLevelInterpolators(players[displayplayer].world, R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT); PS_START_TIMING(ps_rendercalltime); - if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) - { - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; - objectsdrawn = 0; - #ifdef HWRENDER - if (rendermode != render_soft) - HWR_RenderPlayerView(0, &players[displayplayer]); - else - #endif - if (rendermode != render_none) - R_RenderPlayerView(&players[displayplayer]); - } + objectsdrawn = 0; + + D_RenderView(0); // render the second screen - if (splitscreen && players[secondarydisplayplayer].mo) - { - #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])); + if (splitscreen) + D_RenderView(1); - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; - - R_RenderPlayerView(&players[secondarydisplayplayer]); - - viewwindowy = 0; - M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); - } - } + for (INT32 wi = 0; wi < numworlds; wi++) + worldlist[wi]->interpolated_level_this_frame = false; // Image postprocessing effect if (rendermode == render_soft) diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 4db69ff8b..fc4158733 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -23,17 +23,15 @@ #include "../i_video.h" #include "../w_wad.h" #include "../p_setup.h" // levelfadecol +#include "../p_world.h" // -------------------------------------------------------------------------- // This is global data for planes rendering // -------------------------------------------------------------------------- -extrasubsector_t *extrasubsectors = NULL; - // newsubsectors are subsectors without segs, added for the plane polygons #define NEWSUBSECTORS 50 static size_t totsubsectors; -size_t addsubsector; typedef struct { @@ -45,121 +43,24 @@ typedef struct // 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) { - poly_t *p; size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * numpts; -#ifdef ZPLANALLOC - 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 + poly_t *p = Z_Malloc(size, PU_HWRPLANE, NULL); p->numpts = numpts; return p; } static polyvertex_t *HWR_AllocVertex(void) { - polyvertex_t *p; - 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; + return Z_Malloc(sizeof (polyvertex_t), PU_HWRPLANE, NULL); } -/// \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) { -#ifdef ZPLANALLOC 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, // 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 // line is aligned to one of the borders of the poly, and // only some times..) - else - skipcut++; - // I_Error("CutOutPoly: only one point for split line (%d %d) %d", ps, pe, debugpos); } } return poly; @@ -551,16 +449,15 @@ static inline void HWR_SubsecPoly(INT32 num, poly_t *poly) subsector_t *sub; seg_t *lseg; - sub = &subsectors[num]; + sub = &world->subsectors[num]; count = sub->numlines; - lseg = &segs[sub->firstline]; + lseg = &world->segs[sub->firstline]; if (poly) { poly = CutOutSubsecPoly (lseg,count,poly); - totalsubsecpolys++; //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) { 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"); - else if (addsubsector > 0x7fff) + else if (world->numextrasubsectors > 0x7fff) I_Error("WalkBSPNode: addsubsector > 0x7fff\n"); - *leafnode = (UINT16)((UINT16)addsubsector | NF_SUBSECTOR); - extrasubsectors[addsubsector].planepoly = poly; - addsubsector++; + *leafnode = (UINT16)((UINT16)world->numextrasubsectors | NF_SUBSECTOR); + world->extrasubsectors[world->numextrasubsectors].planepoly = poly; + world->numextrasubsectors++; } //add subsectors without segs here? @@ -653,7 +550,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b #endif } 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++) 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); poly = NULL; - //debug - if (!backpoly) - nobackpoly++; - // Recursively divide front space. if (frontpoly) { @@ -696,11 +589,10 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b } // FIXME: use Z_Malloc() STATIC ? -void HWR_FreeExtraSubsectors(void) +void HWR_FreeExtraSubsectors(extrasubsector_t *sub) { - if (extrasubsectors) - free(extrasubsectors); - extrasubsectors = NULL; + if (sub) + free(sub); } #define MAXDIST 1.5f @@ -774,7 +666,7 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly) if (bspnum != -1) { bspnum &= ~NF_SUBSECTOR; - q = extrasubsectors[bspnum].planepoly; + q = world->extrasubsectors[bspnum].planepoly; if (poly == q || !q) return; 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++) newpoly->pts[n] = q->pts[n-1]; numsplitpoly++; - extrasubsectors[bspnum].planepoly = + world->extrasubsectors[bspnum].planepoly = newpoly; HWR_FreePoly(q); return; @@ -840,9 +732,9 @@ static INT32 SolveTProblem(void) 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) for (i = 0; i < p->numpts; i++) SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p); @@ -870,9 +762,9 @@ static void AdjustSegs(void) for (i = 0; i < numsubsectors; i++) { - count = subsectors[i].numlines; - lseg = &segs[subsectors[i].firstline]; - p = extrasubsectors[i].planepoly; + count = world->subsectors[i].numlines; + lseg = &world->segs[world->subsectors[i].firstline]; + p = world->extrasubsectors[i].planepoly; //if (!p) //continue; for (; count--; lseg++) @@ -955,40 +847,28 @@ void HWR_CreatePlanePolygons(INT32 bspnum) { poly_t *rootp; polyvertex_t *rootpv; - size_t i; fixed_t rootbbox[4]; CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n"); + #ifdef HWR_LOADING_SCREEN ls_count = ls_percent = 0; // reset the loading status CON_Drawer(); //let the user know what we are doing I_FinishUpdate(); // page flip or blit buffer #endif - HWR_ClearPolys(); - // find min/max boundaries of map - //CONS_Debug(DBG_RENDER, "Looking for boundaries of map...\n"); M_ClearBox(rootbbox); - for (i = 0;i < numvertexes; i++) - M_AddToBox(rootbbox, vertexes[i].x, vertexes[i].y); + for (size_t i = 0; i < world->numvertexes; i++) + 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 - totsubsectors = numsubsectors + NEWSUBSECTORS; - extrasubsectors = calloc(totsubsectors, sizeof (*extrasubsectors)); - if (extrasubsectors == NULL) + totsubsectors = world->numsubsectors + NEWSUBSECTORS; + world->extrasubsectors = calloc(totsubsectors, sizeof (*world->extrasubsectors)); + if (world->extrasubsectors == NULL) I_Error("couldn't malloc extrasubsectors totsubsectors %s\n", sizeu1(totsubsectors)); - // allocate table for back to front drawing of subsectors - /*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; + world->numextrasubsectors = world->numsubsectors; // number of the first new subsector that might be added // construct the initial convex poly that encloses the full map rootp = HWR_AllocPoly(4); @@ -1007,20 +887,10 @@ void HWR_CreatePlanePolygons(INT32 bspnum) rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXBOTTOM]); //ll rootpv++; - WalkBSPNode(bspnum, rootp, NULL,rootbbox); + WalkBSPNode(bspnum, rootp, NULL, rootbbox); - i = SolveTProblem(); - //CONS_Debug(DBG_RENDER, "%d point divides a polygon line\n",i); + SolveTProblem(); 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 diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index b5daba822..3c30d3c8c 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -28,35 +28,6 @@ // 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 // equivalent of the software renderer's vissprites typedef struct gl_vissprite_s @@ -97,13 +68,7 @@ typedef struct gl_vissprite_s // -------- // hw_bsp.c // -------- -extern extrasubsector_t *extrasubsectors; -extern size_t addsubsector; - -void HWR_InitPolyPool(void); -void HWR_FreePolyPool(void); - -void HWR_FreeExtraSubsectors(void); +void HWR_FreeExtraSubsectors(extrasubsector_t *sub); // -------- // hw_cache.c diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index add1074ee..6d80cac43 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -50,7 +50,6 @@ #define R_FAKEFLOORS #define HWPRECIP -//#define POLYSKY // ========================================================================== // the hardware driver object @@ -102,10 +101,6 @@ static angle_t gl_xtoviewangle[MAXVIDWIDTH+1]; #define DOPLANES //#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 :( //#define NOCRAPPYMLOOK @@ -639,51 +634,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool HWR_PlaneLighting(planeVerts, nrPlaneVerts); #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 FBITFIELD HWR_GetBlendModeFlag(INT32 style) @@ -2903,14 +2853,9 @@ static void HWR_Subsector(size_t num) ffloor_t *rover; #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", - sizeu1(num), sizeu2(numsubsectors), sizeu3(addsubsector)); - - /*if (num >= numsubsectors) - I_Error("HWR_Subsector: ss %i with numss = %i", - num, - numsubsectors);*/ + sizeu1(num), sizeu2(numsubsectors), sizeu3(world->numextrasubsectors)); #endif if (num < numsubsectors) @@ -3005,19 +2950,13 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { 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. locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight, // We now return you to your regularly scheduled rendering. PF_Occlude, floorlightlevel, &viewworld->flats[gl_frontsector->floorpic], NULL, 255, floorcolormap); } } - else - { -#ifdef POLYSKY - HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight); -#endif - } } if (cullCeilingHeight > dup_viewz) @@ -3027,26 +2966,18 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { 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. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. 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 if (gl_frontsector->ceilingpic == viewworld->skyflatnum || gl_frontsector->floorpic == viewworld->skyflatnum) drawsky = true; -#endif #ifdef R_FAKEFLOORS 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); alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); - HWR_AddTransparentFloor(0, - &extrasubsectors[num], - false, + HWR_AddTransparentFloor(NULL, + &world->extrasubsectors[num], + false, *rover->bottomheight, *gl_frontsector->lightlist[light].lightlevel, 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); - HWR_AddTransparentFloor(&world->flats[*rover->bottompic], - &extrasubsectors[num], - false, + HWR_AddTransparentFloor(&viewworld->flats[*rover->bottompic], + &world->extrasubsectors[num], + false, *rover->bottomheight, *gl_frontsector->lightlist[light].lightlevel, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, @@ -3101,9 +3032,9 @@ static void HWR_Subsector(size_t num) } else { - HWR_GetLevelFlat(&world->flats[*rover->bottompic]); + HWR_GetLevelFlat(&viewworld->flats[*rover->bottompic]); 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); } } @@ -3124,21 +3055,21 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); - HWR_AddTransparentFloor(0, - &extrasubsectors[num], - true, + HWR_AddTransparentFloor(NULL, + &world->extrasubsectors[num], + true, *rover->topheight, *gl_frontsector->lightlist[light].lightlevel, 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) { light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_AddTransparentFloor(&world->flats[*rover->toppic], - &extrasubsectors[num], - true, + HWR_AddTransparentFloor(&viewworld->flats[*rover->toppic], + &world->extrasubsectors[num], + true, *rover->topheight, *gl_frontsector->lightlist[light].lightlevel, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, @@ -3147,9 +3078,9 @@ static void HWR_Subsector(size_t num) } else { - HWR_GetLevelFlat(&world->flats[*rover->toppic]); + HWR_GetLevelFlat(&viewworld->flats[*rover->toppic]); 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); } } @@ -3249,33 +3180,6 @@ fixed_t *hwbbox; 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]; // Decide which side the view point is on @@ -3288,12 +3192,10 @@ static void HWR_RenderBSPNode(INT32 bspnum) { if (bspnum == -1) { - //*(gl_drawsubsector_p++) = 0; HWR_Subsector(0); } else { - //*(gl_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR); HWR_Subsector(bspnum&(~NF_SUBSECTOR)); } 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 // ========================================================================== @@ -6189,7 +6069,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); 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; @@ -6418,7 +6298,8 @@ void HWR_LoadLevel(void) HWR_ResetLights(); #endif - HWR_CreatePlanePolygons((INT32)numnodes - 1); + if (world->extrasubsectors == NULL) + HWR_CreatePlanePolygons((INT32)world->numnodes - 1); // Build the sky dome HWR_ClearSkyDome(); @@ -6537,7 +6418,6 @@ void HWR_Startup(void) { CONS_Printf("HWR_Startup()...\n"); - HWR_InitPolyPool(); HWR_AddSessionCommands(); HWR_InitMapTextures(); HWR_InitModels(); @@ -6587,8 +6467,6 @@ void HWR_Switch(void) void HWR_Shutdown(void) { CONS_Printf("HWR_Shutdown()\n"); - HWR_FreeExtraSubsectors(); - HWR_FreePolyPool(); HWR_FreeMapTextures(); HWD.pfnFlushScreenTextures(); } diff --git a/src/p_setup.c b/src/p_setup.c index 4995b7b42..78c8659ee 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7853,9 +7853,6 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo #ifdef HWRENDER // not win32 only 19990829 by Kin gl_maploaded = false; - // Lactozilla: Free extrasubsectors regardless of renderer. - HWR_FreeExtraSubsectors(); - // Create plane polygons. if (rendermode == render_opengl) HWR_LoadLevel(); @@ -7941,7 +7938,7 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo R_ResetViewInterpolation(0); R_ResetViewInterpolation(0); - R_UpdateMobjInterpolators(); + R_UpdateMobjInterpolators(world); // Title card! G_StartTitleCard(); diff --git a/src/p_tick.c b/src/p_tick.c index ed555e188..705a483a6 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -762,7 +762,7 @@ void P_Ticker(boolean run) if (OP_FreezeObjectplace()) { P_MapStart(); - R_UpdateMobjInterpolators(); + R_UpdateMobjInterpolators(world); OP_ObjectplaceMovement(&players[0]); P_MoveChaseCamera(&players[0], &camera, false); R_UpdateViewInterpolation(); @@ -788,7 +788,7 @@ void P_Ticker(boolean run) if (run) { - R_UpdateMobjInterpolators(); + R_UpdateMobjInterpolators(world); if (demorecording) G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); @@ -962,8 +962,6 @@ void P_Ticker(boolean run) } P_MapEnd(); - -// Z_CheckMemCleanup(); } // Abbreviated ticker for pre-loading, calls thinkers and assorted things @@ -981,7 +979,7 @@ void P_PreTicker(INT32 frames) { P_MapStart(); - R_UpdateMobjInterpolators(); + R_UpdateMobjInterpolators(world); RunLuaHookForWorld(HOOK(PreThinkFrame)); diff --git a/src/p_world.c b/src/p_world.c index d35fe04b4..8289a5832 100644 --- a/src/p_world.c +++ b/src/p_world.c @@ -253,11 +253,6 @@ void P_SwitchWorld(player_t *player, world_t *w) boolean local = ((INT32)playernum == consoleplayer); 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)) return; @@ -303,6 +298,11 @@ void P_SwitchWorld(player_t *player, world_t *w) if (resetplayer) P_ResetPlayer(player); P_MapEnd(); + +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_LoadLevel(); +#endif } void Command_Switchworld_f(void) @@ -367,6 +367,12 @@ void P_UnloadWorld(world_t *w) LUA_InvalidateLevel(w); P_UnloadSectorAttachments(w->sectors, w->numsectors); + + if (world->extrasubsectors) + { + HWR_FreeExtraSubsectors(world->extrasubsectors); + world->extrasubsectors = NULL; + } } // diff --git a/src/p_world.h b/src/p_world.h index 919cf915a..219e27573 100644 --- a/src/p_world.h +++ b/src/p_world.h @@ -26,10 +26,9 @@ #define NUMWAYPOINTSEQUENCES 256 // -// Lactozilla: 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.) -// And you could say that a "level" both describes metadata about that "map" (level headers), and contains a world. -// (This is my terminology anyway, "map" and "level" are usually interchangeable.) +// 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) +// And a "level" both describes metadata (level headers), and contains many worlds // typedef struct { @@ -48,6 +47,9 @@ typedef struct side_t *sides; mapthing_t *mapthings; + extrasubsector_t *extrasubsectors; + size_t numextrasubsectors; + sector_t *spawnsectors; line_t *spawnlines; side_t *spawnsides; @@ -126,6 +128,8 @@ typedef struct void **interpolated_mobjs; size_t interpolated_mobjs_len; size_t interpolated_mobjs_capacity; + + boolean interpolated_level_this_frame; } world_t; extern world_t *world; diff --git a/src/r_defs.h b/src/r_defs.h index 2d19e065b..e52fe9f07 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -714,6 +714,35 @@ typedef struct UINT16 children[2]; } 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) #pragma pack(1) #endif diff --git a/src/r_fps.c b/src/r_fps.c index b5fee1876..c358fb369 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -556,6 +556,8 @@ void R_ClearLevelInterpolatorState(thinker_t *thinker) void R_ApplyLevelInterpolators(void *wptr, fixed_t frac) { world_t *w = (world_t *)wptr; + if (w->interpolated_level_this_frame) + return; size_t i, ii; @@ -608,6 +610,8 @@ void R_ApplyLevelInterpolators(void *wptr, fixed_t frac) break; } } + + w->interpolated_level_this_frame = true; } static void R_RestoreLevelInterpolatorsForWorld(world_t *w) @@ -753,17 +757,24 @@ void R_InitMobjInterpolators(void) 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++) { world_t *w = worldlist[wi]; - 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); - } + R_UpdateMobjInterpolators(w); } } diff --git a/src/r_fps.h b/src/r_fps.h index 1c8af5cb6..0252922c5 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -155,7 +155,8 @@ void R_InitMobjInterpolators(void); void R_AddMobjInterpolator(mobj_t *mobj); // Remove the interpolation state for the given 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_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj); diff --git a/src/r_main.c b/src/r_main.c index b893b587c..4205534ad 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1472,19 +1472,30 @@ static void Mask_Post (maskcount_t* m) m->vissprites[1] = visspritecount; } -// ================ -// R_RenderView -// ================ +void R_SetViewNum(UINT32 viewnum) +{ + if (rendermode != render_soft) + return; -// FAB NOTE FOR WIN32 PORT !! I'm not finished already, -// 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.. -// I mean, there is a win16lock() or something that lasts all the rendering, -// so maybe we should release screen lock before each netupdate below..? + switch (viewnum) + { + case 0: + viewwindowy = 0; + 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; + R_SetViewMobj(player); if (r_viewmobj) @@ -1494,8 +1505,14 @@ void R_RenderPlayerView(player_t *player) else if (localworld && !splitscreen) // Yes? P_SetViewWorld(localworld); else - return; + viewworld = worldlist[0]; +} +// ================ +// R_RenderView +// ================ +void R_RenderPlayerView(player_t *player) +{ INT32 nummasks = 1; maskcount_t* masks = malloc(sizeof(maskcount_t)); diff --git a/src/r_main.h b/src/r_main.h index c40f93448..dc51815a6 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -140,6 +140,9 @@ void R_ExecuteSetViewSize(void); void R_SetupFrame(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_IsViewpointThirdPerson(player_t *player, boolean skybox);