From f2918b748f4784e717acb30730a2d4a9debb5f87 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 17 Jun 2018 14:38:17 +0300 Subject: [PATCH 1/4] - deleted leftover declaration in Cocoa backend --- src/posix/cocoa/i_video.mm | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 8593f86e7..c6ee90eb1 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -112,9 +112,6 @@ CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_ } -EXTERN_CVAR(Bool, gl_smooth_rendered) - - // --------------------------------------------------------------------------- From 832de42c249c371c64f18835a610c4db5f591afa Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 17 Jun 2018 14:35:25 +0300 Subject: [PATCH 2/4] - prevented crashes caused by inconsistent status bar Incorrectly initialized or deliberately broken status bar could lead to integer division by zero and null pointer dereference class BuggyStatusBar : DoomStatusBar { override void Init() { // No super.Init() } } --- src/g_statusbar/shared_sbar.cpp | 35 ++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 6309ca65f..4d6d6e737 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -349,8 +349,25 @@ DBaseStatusBar::DBaseStatusBar () defaultScale = { (double)CleanXfac, (double)CleanYfac }; } +static void ValidateResolution(int &hres, int &vres) +{ + if (hres == 0) + { + static const int HORIZONTAL_RESOLUTION_DEFAULT = 320; + hres = HORIZONTAL_RESOLUTION_DEFAULT; + } + + if (vres == 0) + { + static const int VERTICAL_RESOLUTION_DEFAULT = 200; + vres = VERTICAL_RESOLUTION_DEFAULT; + } +} + void DBaseStatusBar::SetSize(int reltop, int hres, int vres, int hhres, int hvres) { + ValidateResolution(hres, vres); + BaseRelTop = reltop; BaseSBarHorizontalResolution = hres; BaseSBarVerticalResolution = vres; @@ -361,6 +378,8 @@ void DBaseStatusBar::SetSize(int reltop, int hres, int vres, int hhres, int hvre void DBaseStatusBar::SetDrawSize(int reltop, int hres, int vres) { + ValidateResolution(hres, vres); + RelTop = reltop; HorizontalResolution = hres; VerticalResolution = vres; @@ -415,6 +434,8 @@ void DBaseStatusBar::OnDestroy () void DBaseStatusBar::SetScale () { + ValidateResolution(HorizontalResolution, VerticalResolution); + int w = SCREENWIDTH; int h = SCREENHEIGHT; if (st_scale < 0 || ForcedScale) @@ -481,10 +502,14 @@ DVector2 DBaseStatusBar::GetHUDScale() const } scale = GetUIScale(hud_scale); + int hres = HorizontalResolution; + int vres = VerticalResolution; + ValidateResolution(hres, vres); + // Since status bars and HUDs can be designed for non 320x200 screens this needs to be factored in here. // The global scaling factors are for resources at 320x200, so if the actual ones are higher resolution // the resulting scaling factor needs to be reduced accordingly. - int realscale = MAX(1, (320 * scale) / HorizontalResolution); + int realscale = MAX(1, (320 * scale) / hres); return{ double(realscale), double(realscale * (hud_aspectscale ? 1.2 : 1.)) }; } @@ -1439,7 +1464,11 @@ void DBaseStatusBar::StatusbarToRealCoords(double &x, double &y, double &w, doub { if (SBarScale.X == -1 || ForcedScale) { - screen->VirtualToRealCoords(x, y, w, h, HorizontalResolution, VerticalResolution, true, true); + int hres = HorizontalResolution; + int vres = VerticalResolution; + ValidateResolution(hres, vres); + + screen->VirtualToRealCoords(x, y, w, h, hres, vres, true, true); } else { @@ -1802,7 +1831,7 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString) { PARAM_SELF_PROLOGUE(DBaseStatusBar); - PARAM_POINTER(font, DHUDFont); + PARAM_POINTER_NOT_NULL(font, DHUDFont); PARAM_STRING(string); PARAM_FLOAT(x); PARAM_FLOAT(y); From bce49ad7c8a52fd75f79d5532fabe855e31d7307 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 17 Jun 2018 14:56:34 +0200 Subject: [PATCH 3/4] - fix Software models don't display over nonexistent sprites --- src/polyrenderer/scene/poly_scene.cpp | 56 +++++++++++++++++++++++--- src/polyrenderer/scene/poly_scene.h | 1 + src/polyrenderer/scene/poly_sprite.cpp | 9 ++--- src/swrenderer/scene/r_opaque_pass.cpp | 30 ++++++-------- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 469f56bc9..284f24b1a 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -37,6 +37,8 @@ EXTERN_CVAR(Int, r_portal_recursions) +extern double model_distance_cull; + ///////////////////////////////////////////////////////////////////////////// RenderPolyScene::RenderPolyScene() @@ -71,11 +73,24 @@ void RenderPolyScene::Render(PolyPortalViewpoint *viewpoint) sector_t *sector = &level.sectors[sectorIndex]; for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) { - DVector2 left, right; - if (!RenderPolySprite::GetLine(thing, left, right)) - continue; - double distanceSquared = (thing->Pos() - rviewpoint.Pos).LengthSquared(); - AddSprite(thread, thing, distanceSquared, left, right); + if (!RenderPolySprite::IsThingCulled(thing)) + { + int spritenum = thing->sprite; + bool isPicnumOverride = thing->picnum.isValid(); + FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + double distanceSquared = (thing->Pos() - rviewpoint.Pos).LengthSquared(); + if (r_modelscene && modelframe && distanceSquared < model_distance_cull) + { + AddModel(thread, thing, distanceSquared, thing->Pos()); + } + else + { + DVector2 left, right; + if (!RenderPolySprite::GetLine(thing, left, right)) + continue; + AddSprite(thread, thing, distanceSquared, left, right); + } + } } } PolyMaskedCycles.Unclock(); @@ -296,6 +311,37 @@ void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, CurrentViewpoint->StencilValue)); } +void RenderPolyScene::AddModel(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 pos) +{ + if (level.nodes.Size() == 0) + { + subsector_t *sub = &level.subsectors[0]; + if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) + thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); + } + else + { + void *node = level.HeadNode(); + + while (!((size_t)node & 1)) // Keep going until found a subsector + { + node_t *bsp = (node_t *)node; + + DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y)); + DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx)); + double planeD = planeNormal | planePos; + + int side = (pos | planeNormal) > planeD; + node = bsp->children[side]; + } + + subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); + + if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) + thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); + } +} + void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) { // Tell automap we saw this diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index 26241a027..238116c52 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -96,6 +96,7 @@ private: void RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth); void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); + void AddModel(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 pos); void RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector); void RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector); diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 7be5648b0..3b1b4347b 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -39,13 +39,12 @@ EXTERN_CVAR (Bool, r_debug_disable_vis_filter) EXTERN_CVAR(Int, gl_spriteclip) EXTERN_CVAR(Float, gl_sclipthreshold) EXTERN_CVAR(Float, gl_sclipfactor) + extern uint32_t r_renderercaps; +extern double model_distance_cull; bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right) { - if (IsThingCulled(thing)) - return false; - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); @@ -76,12 +75,12 @@ void RenderPolySprite::Render(PolyRenderThread *thread, AActor *thing, subsector { if (r_modelscene) { + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; int spritenum = thing->sprite; bool isPicnumOverride = thing->picnum.isValid(); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); - if (modelframe) + if (modelframe && (thing->Pos() - viewpoint.Pos).LengthSquared() < model_distance_cull) { - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); PolyRenderModel(thread, PolyRenderer::Instance()->Scene.CurrentViewpoint->WorldToClip, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); return; diff --git a/src/swrenderer/scene/r_opaque_pass.cpp b/src/swrenderer/scene/r_opaque_pass.cpp index 1cb7045eb..987b89b5b 100644 --- a/src/swrenderer/scene/r_opaque_pass.cpp +++ b/src/swrenderer/scene/r_opaque_pass.cpp @@ -76,11 +76,12 @@ EXTERN_CVAR(Bool, r_drawvoxels); EXTERN_CVAR(Bool, r_debug_disable_vis_filter); extern uint32_t r_renderercaps; +double model_distance_cull = 1e16; + namespace { double sprite_distance_cull = 1e16; double line_distance_cull = 1e16; - double model_distance_cull = 1e16; } CUSTOM_CVAR(Float, r_sprite_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -935,7 +936,15 @@ namespace swrenderer if (IsPotentiallyVisible(thing)) { ThingSprite sprite; - if (GetThingSprite(thing, sprite)) + int spritenum = thing->sprite; + bool isPicnumOverride = thing->picnum.isValid(); + FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + if (r_modelscene && modelframe && (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared() < model_distance_cull) + { + DVector3 pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); + RenderModel::Project(Thread, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); + } + else if (GetThingSprite(thing, sprite)) { FDynamicColormap *thingColormap = basecolormap; int thingShade = spriteshade; @@ -954,24 +963,9 @@ namespace swrenderer { RenderVoxel::Project(Thread, thing, sprite.pos, sprite.voxel, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); } - else if (!r_modelscene) - { - RenderSprite::Project(Thread, thing, sprite.pos, sprite.tex, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); - } else { - int spritenum = thing->sprite; - bool isPicnumOverride = thing->picnum.isValid(); - FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); - if (modelframe && (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared() < model_distance_cull) - { - DVector3 pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); - RenderModel::Project(Thread, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); - } - else - { - RenderSprite::Project(Thread, thing, sprite.pos, sprite.tex, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); - } + RenderSprite::Project(Thread, thing, sprite.pos, sprite.tex, sprite.spriteScale, sprite.renderflags, fakeside, fakefloor, fakeceiling, sec, thingShade, foggy, thingColormap); } } } From c91d4750f3ef635559f12077c9f501c043d29da0 Mon Sep 17 00:00:00 2001 From: Erick Tenorio Date: Fri, 15 Jun 2018 21:21:14 -0500 Subject: [PATCH 4/4] Save item statistics Items are now saved into save games and are displayed on the statfile --- src/statistics.cpp | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/statistics.cpp b/src/statistics.cpp index 0a3aeadea..348288de1 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -72,6 +72,7 @@ CVAR(String, statfile, "zdoomstat.txt", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) struct OneLevel { int totalkills, killcount; + int totalitems, itemcount; int totalsecrets, secretcount; int leveltime; FString Levelname; @@ -84,10 +85,10 @@ static FEpisode *StartEpisode; // The statistics for one level struct FLevelStatistics { - char info[30]; + char info[60]; short skill; short playerclass; - char name[12]; + char name[24]; int timeneeded; }; @@ -139,9 +140,9 @@ static void ParseStatistics(const char *fn, TArray &statlist) sc.MustGetString(); sc.MustGetString(); - strncpy(session.name, sc.String, 12); + strncpy(session.name, sc.String, 24); sc.MustGetString(); - strncpy(session.info, sc.String, 30); + strncpy(session.info, sc.String, 60); int h,m,s; sc.MustGetString(); @@ -157,9 +158,9 @@ static void ParseStatistics(const char *fn, TArray &statlist) FLevelStatistics &lstats = session.levelstats[session.levelstats.Reserve(1)]; sc.MustGetString(); - strncpy(lstats.name, sc.String, 12); + strncpy(lstats.name, sc.String, 24); sc.MustGetString(); - strncpy(lstats.info, sc.String, 30); + strncpy(lstats.info, sc.String, 60); int h,m,s; sc.MustGetString(); @@ -262,7 +263,7 @@ static void SaveStatistics(const char *fn, TArray &statlist) FSessionStatistics *sst = &ep_stats.stats[j]; if (sst->info[0]>0) { - fw->Printf("\t%2i. %10s \"%-22s\" %02d:%02d:%02d %i\n", j+1, sst->name, sst->info, + fw->Printf("\t%2i. %10s \"%-33s\" %02d:%02d:%02d %i\n", j+1, sst->name, sst->info, hours(sst->timeneeded), minutes(sst->timeneeded), seconds(sst->timeneeded), sst->skill); TArray &ls = sst->levelstats; @@ -274,7 +275,7 @@ static void SaveStatistics(const char *fn, TArray &statlist) for(unsigned k=0;kPrintf("\t\t%-8s \"%-22s\" %02d:%02d:%02d\n", ls[k].name, ls[k].info, + fw->Printf("\t\t%-8s \"%-33s\" %02d:%02d:%02d\n", ls[k].name, ls[k].info, hours(ls[k].timeneeded), minutes(ls[k].timeneeded), seconds(ls[k].timeneeded)); } fw->Printf("\t}\n"); @@ -404,6 +405,8 @@ static void StoreLevelStats() } LevelData[i].totalkills = level.total_monsters; LevelData[i].killcount = level.killed_monsters; + LevelData[i].totalitems = level.total_items; + LevelData[i].itemcount = level.found_items; LevelData[i].totalsecrets = level.total_secrets; LevelData[i].secretcount = level.found_secrets; LevelData[i].leveltime = level.maptime; @@ -464,26 +467,28 @@ void STAT_ChangeLevel(const char *newl) if (*ep_name == '$') ep_name = GStrings[ep_name+1]; FStatistics *sl = GetStatisticsList(EpisodeStatistics, section, ep_name); - int statvals[4] = {0,0,0,0}; + int statvals[6] = {0,0,0,0,0,0}; FString infostring; int validlevels = LevelData.Size(); for(unsigned i = 0; i < LevelData.Size(); i++) { statvals[0] += LevelData[i].killcount; statvals[1] += LevelData[i].totalkills; - statvals[2] += LevelData[i].secretcount; - statvals[3] += LevelData[i].totalsecrets; + statvals[2] += LevelData[i].itemcount; + statvals[3] += LevelData[i].totalitems; + statvals[4] += LevelData[i].secretcount; + statvals[5] += LevelData[i].totalsecrets; } - infostring.Format("%4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], validlevels); + infostring.Format("%4d/%4d, %4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], statvals[4], statvals[5], validlevels); FSessionStatistics *es = StatisticsEntry(sl, infostring, level.totaltime); for(unsigned i = 0; i < LevelData.Size(); i++) { FString lsection = LevelData[i].Levelname; lsection.ToUpper(); - infostring.Format("%4d/%4d, %3d/%3d", - LevelData[i].killcount, LevelData[i].totalkills, LevelData[i].secretcount, LevelData[i].totalsecrets); + infostring.Format("%4d/%4d, %4d/%4d, %3d/%3d", + LevelData[i].killcount, LevelData[i].totalkills, LevelData[i].itemcount, LevelData[i].totalitems, LevelData[i].secretcount, LevelData[i].totalsecrets); LevelStatEntry(es, lsection, infostring, LevelData[i].leveltime); } @@ -508,6 +513,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, OneLevel &l, OneLevel { arc("totalkills", l.totalkills) ("killcount", l.killcount) + ("totalitems", l.totalitems) + ("itemcount", l.itemcount) ("totalsecrets", l.totalsecrets) ("secretcount", l.secretcount) ("leveltime", l.leveltime) @@ -561,8 +568,8 @@ FString GetStatString() for(unsigned i = 0; i < LevelData.Size(); i++) { OneLevel *l = &LevelData[i]; - compose.AppendFormat("Level %s - Kills: %d/%d - Secrets: %d/%d - Time: %d:%02d\n", - l->Levelname.GetChars(), l->killcount, l->totalkills, l->secretcount, l->totalsecrets, + compose.AppendFormat("Level %s - Kills: %d/%d - Items: %d/%d - Secrets: %d/%d - Time: %d:%02d\n", + l->Levelname.GetChars(), l->killcount, l->totalkills, l->itemcount, l->totalitems, l->secretcount, l->totalsecrets, l->leveltime/(60*TICRATE), (l->leveltime/TICRATE)%60); } return compose;