diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 6d9baea24..1846ecbc6 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -386,6 +386,7 @@ enum //Key words SBARINFO_STATUSBAR, SBARINFO_MUGSHOT, SBARINFO_CREATEPOPUP, + SBARINFO_PROTRUSION, }; enum //Bar types @@ -414,6 +415,7 @@ static const char *SBarInfoTopLevel[] = "statusbar", "mugshot", "createpopup", + "protrusion", NULL }; @@ -743,6 +745,21 @@ void SBarInfo::ParseSBarInfo(int lump) sc.MustGetToken(';'); break; } + case SBARINFO_PROTRUSION: + { + double lastvalue = -DBL_EPSILON; + do + { + sc.MustGetToken(TK_FloatConst); + if (sc.Float <= lastvalue) sc.ScriptError("Protrusion factors must be in ascending order"); + lastvalue = sc.Float; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + protrusions.Push({ lastvalue, sc.Number }); + } while (sc.CheckToken(',')); + sc.MustGetToken(';'); + break; + } } } } @@ -1160,6 +1177,17 @@ public: } } + int _GetProtrusion(double scalefac) + { + int returnval = 0; + for (auto &prot : script->protrusions) + { + if (prot.first > scalefac) break; + returnval = prot.second; + } + return returnval; + } + //draws an image with the specified flags void DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, double Alpha, bool fullScreenOffsets, bool translate=false, bool dim=false, int offsetflags=0, bool alphaMap=false, int forceWidth=-1, int forceHeight=-1, const double *clip = nulclip, bool clearDontDraw=false) const { @@ -1538,6 +1566,12 @@ DEFINE_ACTION_FUNCTION(DSBarInfo, ShowPop) return 0; } +DEFINE_ACTION_FUNCTION(DSBarInfo, GetProtrusion) +{ + PARAM_SELF_STRUCT_PROLOGUE(DSBarInfo); + PARAM_FLOAT(scalefac); + ACTION_RETURN_INT(self->_GetProtrusion(scalefac)); +} DBaseStatusBar *CreateCustomStatusBar(int scriptno) { diff --git a/src/g_statusbar/sbarinfo.h b/src/g_statusbar/sbarinfo.h index 136f814f7..cfc3395d8 100644 --- a/src/g_statusbar/sbarinfo.h +++ b/src/g_statusbar/sbarinfo.h @@ -101,6 +101,7 @@ struct SBarInfo bool completeBorder; bool lowerHealthCap; char spacingCharacter; + TArray> protrusions; MonospaceAlignment spacingAlignment; int interpolationSpeed; int armorInterpolationSpeed; diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 2f4bc5f8c..c30dca34e 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -37,31 +37,32 @@ PolySkyDome::PolySkyDome() void PolySkyDome::Render(const TriMatrix &worldToClip) { +#ifdef USE_GL_DOME_MATH + TriMatrix modelMatrix = GLSkyMath(); +#else + TriMatrix modelMatrix = TriMatrix::identity(); + PolySkySetup frameSetup; frameSetup.Update(); if (frameSetup != mCurrentSetup) { - double frontTexWidth = (double)frameSetup.frontskytex->GetWidth(); - float scaleFrontU = (float)(frameSetup.frontcyl / frontTexWidth); - if (frameSetup.skyflip) - scaleFrontU = -scaleFrontU; + // frontcyl = pixels for full 360 degrees, front texture + // backcyl = pixels for full 360 degrees, back texture + // skymid = Y scaled pixel offset + // sky1pos = unscaled X offset, front + // sky2pos = unscaled X offset, back + // frontpos = scaled X pixel offset (fixed point) + // backpos = scaled X pixel offset (fixed point) + // skyflip = flip X direction - float baseOffset = (float)(frameSetup.skyangle / 65536.0 / frontTexWidth); - float offsetFrontU = baseOffset * scaleFrontU + (float)(frameSetup.frontpos / 65536.0 / frontTexWidth); + float scaleBaseV = 1.42f; + float offsetBaseV = 0.25f; - float scaleFrontV = (float)(frameSetup.frontskytex->Scale.Y * 1.6); - float offsetFrontV; - - // BTSX - /*{ - offsetFrontU += 0.5f; - offsetFrontV = (float)((28.0f - frameSetup.skymid) / frameSetup.frontskytex->GetHeight()); - }*/ - // E1M1 - { - offsetFrontV = (float)((28.0f + frameSetup.skymid) / frameSetup.frontskytex->GetHeight()); - } + float scaleFrontU = frameSetup.frontcyl / (float)frameSetup.frontskytex->GetWidth(); + float scaleFrontV = (float)frameSetup.frontskytex->Scale.Y * scaleBaseV; + float offsetFrontU = (float)(frameSetup.frontpos / 65536.0 / frameSetup.frontskytex->GetWidth()); + float offsetFrontV = (float)((frameSetup.skymid / frameSetup.frontskytex->GetHeight() + offsetBaseV) * scaleBaseV); unsigned int count = mVertices.Size(); for (unsigned int i = 0; i < count; i++) @@ -72,9 +73,10 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) mCurrentSetup = frameSetup; } +#endif const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - TriMatrix objectToWorld = TriMatrix::translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z); + TriMatrix objectToWorld = TriMatrix::translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z) * modelMatrix; objectToClip = worldToClip * objectToWorld; int rc = mRows + 1; @@ -203,6 +205,80 @@ void PolySkyDome::SkyVertex(int r, int c, bool zflip) mInitialUV.Push({ vert.u, vert.v }); } +TriMatrix PolySkyDome::GLSkyMath() +{ + PolySkySetup frameSetup; + frameSetup.Update(); + mCurrentSetup = frameSetup; + + float x_offset = 0.0f; + float y_offset = 0.0f; + bool mirror = false; + FTexture *tex = mCurrentSetup.frontskytex; + float skyoffset = 0.0f; // skyoffset debugging CVAR in GL renderer + + int texh = 0; + int texw = 0; + + // 57 world units roughly represent one sky texel for the glTranslate call. + const float skyoffsetfactor = 57; + + TriMatrix modelMatrix = TriMatrix::identity(); + if (tex) + { + texw = tex->GetWidth(); + texh = tex->GetHeight(); + + modelMatrix = TriMatrix::rotate(-180.0f + x_offset, 0.f, 0.f, 1.f); + + float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f; + float yscale = 1.f; + if (texh <= 128 && (level.flags & LEVEL_FORCETILEDSKY)) + { + modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor); + modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.2f * 1.17f); + yscale = 240.f / texh; + } + else if (texh < 128) + { + // smaller sky textures must be tiled. We restrict it to 128 sky pixels, though + modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, -1250.f); + modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 128 / 230.f); + yscale = (float)(128 / texh); // intentionally left as integer. + } + else if (texh < 200) + { + modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, -1250.f); + modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, texh / 230.f); + } + else if (texh <= 240) + { + modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (200 - texh + tex->SkyOffset + skyoffset)*skyoffsetfactor); + modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f); + } + else + { + modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor); + modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.2f * 1.17f); + yscale = 240.f / texh; + } + + float offsetU = 1.0f; + float offsetV = y_offset / texh; + float scaleU = mirror ? -xscale : xscale; + float scaleV = yscale; + + unsigned int count = mVertices.Size(); + for (unsigned int i = 0; i < count; i++) + { + mVertices[i].u = offsetU + mInitialUV[i].X * scaleU; + mVertices[i].v = offsetV + mInitialUV[i].Y * scaleV; + } + } + + return modelMatrix; +} + ///////////////////////////////////////////////////////////////////////////// void PolySkySetup::Update() @@ -291,10 +367,6 @@ void PolySkySetup::Update() int frontxscale = int(frontskytex->Scale.X * 1024); frontcyl = MAX(frontskytex->GetWidth(), frontxscale); - if (skystretch) - { - skymid = skymid * frontskytex->GetScaledHeightDouble() / SKYSTRETCH_HEIGHT; - } } frontpos = int(fmod(frontdpos, sky1cyl * 65536.0)); diff --git a/src/polyrenderer/scene/poly_sky.h b/src/polyrenderer/scene/poly_sky.h index bf8f7e202..4fc30da70 100644 --- a/src/polyrenderer/scene/poly_sky.h +++ b/src/polyrenderer/scene/poly_sky.h @@ -63,5 +63,7 @@ private: TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0); + TriMatrix GLSkyMath(); + PolySkySetup mCurrentSetup; }; diff --git a/wadsrc/static/sbarinfo/heretic.txt b/wadsrc/static/sbarinfo/heretic.txt index 7f312be77..1515a1769 100755 --- a/wadsrc/static/sbarinfo/heretic.txt +++ b/wadsrc/static/sbarinfo/heretic.txt @@ -10,6 +10,7 @@ ******************************************************************************/ height 42; +protrusion 0.7, 8; monospacefonts true, "0", center; statusbar fullscreen, fullscreenoffsets diff --git a/wadsrc/static/sbarinfo/hexen.txt b/wadsrc/static/sbarinfo/hexen.txt index 583f02779..bd62cc52c 100755 --- a/wadsrc/static/sbarinfo/hexen.txt +++ b/wadsrc/static/sbarinfo/hexen.txt @@ -10,6 +10,7 @@ ******************************************************************************/ height 38; +protrusion 0.0, 12, 0.85, 28; monospacefonts true, "0", center; statusbar fullscreen, fullscreenoffsets diff --git a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt index 7a7aaea4f..efc6bedc8 100644 --- a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt +++ b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt @@ -8,6 +8,7 @@ struct SBarInfo native ui native bool MustDrawLog(int state); native void Tick(); native void ShowPop(int popnum); + native int GetProtrusion(double scalefac); } @@ -62,5 +63,10 @@ class SBarInfoWrapper : BaseStatusBar core.ShowPop(popnum); } + override int GetProtrusion(double scaleratio) const + { + return core.GetProtrusion(scaleratio); + } + } \ No newline at end of file