From bead3e046bd5c440254143a74a96c290a8e41299 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 4 Apr 2015 17:50:22 +0200 Subject: [PATCH] - fixed weapon positioning again, after finding out that the first fix just worked around the actual problem: The entire coordinate calculation must be done in floating point with no integer math at all. Due to roundoff errors the stored int values needed for wall and flat placement significantly lack precision and with the high scaling factor that needs to be used for weapon HUD sprites these can easily become several pixels. After fixing this the border around sprite textures could be reverted to one pixel again. - fixed: The 'may not be expanded' state should be stored in the texture and reused later. This also needs to revalidate the material if it decides that expansion should be disallowed. --- src/gl/scene/gl_weapon.cpp | 56 +++++++++++++++-------------- src/gl/textures/gl_material.cpp | 64 ++++++++++++++++++--------------- src/gl/textures/gl_material.h | 7 ---- src/gl/textures/gl_texture.cpp | 1 + src/textures/textures.h | 1 + 5 files changed, 67 insertions(+), 62 deletions(-) diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 89a5e1efb0..71b4a8fdc8 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -75,13 +75,13 @@ void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed { float fU1,fV1; float fU2,fV2; - fixed_t tx; - int x1,y1,x2,y2; + float tx; + float x1,y1,x2,y2; float scale; - fixed_t scalex; + float scalex; float ftexturemid; - // 4:3 16:9 16:10 17:10 5:4 - static fixed_t xratio[] = {FRACUNIT, FRACUNIT*3/4, FRACUNIT*5/6, FRACUNIT*40/51, FRACUNIT}; + // 4:3 16:9 16:10 17:10 5:4 + static float xratio[] = {1.f, 3.f/4, 5.f/6, 40.f/51, 1.f}; // [BB] In the HUD model step we just render the model and break out. if ( hudModelStep ) @@ -100,30 +100,34 @@ void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed gl_RenderState.SetMaterial(tex, CLAMP_XY_NOMIP, 0, OverrideShader, alphatexture); - int vw = viewwidth; - int vh = viewheight; + float vw = (float)viewwidth; + float vh = (float)viewheight; + + FloatRect r; + tex->GetSpriteRect(&r); // calculate edges of the shape scalex = xratio[WidescreenRatio] * vw / 320; - tx = sx - ((160 + tex->GetScaledLeftOffset())<>FRACBITS) + (vw>>1); + tx = FIXED2FLOAT(sx) - (160 - r.left); + x1 = tx * scalex + vw/2; if (x1 > vw) return; // off the right side - x1+=viewwindowx; + x1 += viewwindowx; - tx += tex->TextureWidth() << FRACBITS; - x2 = (FixedMul(tx, scalex)>>FRACBITS) + (vw>>1); + tx += r.width; + x2 = tx * scalex + vw / 2; if (x2 < 0) return; // off the left side - x2+=viewwindowx; + x2 += viewwindowx; + // killough 12/98: fix psprite positioning problem - ftexturemid = 100.f - FIXED2FLOAT(sy) + tex->GetScaledTopOffsetFloat(); + ftexturemid = 100.f - FIXED2FLOAT(sy) - r.top; AWeapon * wi=player->ReadyWeapon; if (wi && wi->YAdjust) { float fYAd = FIXED2FLOAT(wi->YAdjust); - if (screenblocks>=11) + if (screenblocks >= 11) { ftexturemid -= fYAd; } @@ -133,23 +137,23 @@ void FGLRenderer::DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed } } - scale = (SCREENHEIGHT*vw)/ (SCREENWIDTH * 200.0f); - y1 = viewwindowy + (vh >> 1) - (int)(ftexturemid * scale); - y2 = y1 + (int)((float)tex->TextureHeight() * scale) + 1; + scale = (SCREENHEIGHT*vw) / (SCREENWIDTH * 200.0f); + y1 = viewwindowy + vh / 2 - (ftexturemid * scale); + y2 = y1 + (r.height * scale) + 1; if (!mirror) { - fU1=tex->GetUL(); - fV1=tex->GetVT(); - fU2=tex->GetUR(); - fV2=tex->GetVB(); + fU1=tex->GetSpriteUL(); + fV1=tex->GetSpriteVT(); + fU2=tex->GetSpriteUR(); + fV2=tex->GetSpriteVB(); } else { - fU2=tex->GetUL(); - fV1=tex->GetVT(); - fU1=tex->GetUR(); - fV2=tex->GetVB(); + fU2=tex->GetSpriteUL(); + fV1=tex->GetSpriteVT(); + fU1=tex->GetSpriteUR(); + fV2=tex->GetSpriteVB(); } if (tex->GetTransparent() || OverrideShader != -1) diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index f54cad27b8..a359191e1f 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -89,7 +89,6 @@ FGLTexture::FGLTexture(FTexture * tx, bool expandpatches) bHasColorkey = false; bIsTransparent = -1; bExpandFlag = expandpatches; - mExpandX = mExpandY = 0; tex->gl_info.SystemTexture[expandpatches] = this; } @@ -199,20 +198,10 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F } } - int exx, exy; - if (createexpanded) - { - exx = mExpandX; - exy = mExpandY; - } - else - { - exx = exy = 0; - } - + int exx = bExpandFlag && createexpanded; W = w = tex->GetWidth() + 2 * exx; - H = h = tex->GetHeight() + 2 * exy; + H = h = tex->GetHeight() + 2 * exx; buffer=new unsigned char[W*(H+1)*4]; @@ -230,7 +219,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F if (imgCreate.Create(W, H)) { memset(imgCreate.GetPixels(), 0, W * H * 4); - int trans = tex->CopyTrueColorPixels(&imgCreate, exx, exy); + int trans = tex->CopyTrueColorPixels(&imgCreate, exx, exx); bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), W, H, 4, W * 4, 0, CF_BGRA); tex->CheckTrans(buffer, W*H, trans); bIsTransparent = tex->gl_info.mIsTransparent; @@ -238,7 +227,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F } else if (translation<=0) { - int trans = tex->CopyTrueColorPixels(&bmp, exx, exy); + int trans = tex->CopyTrueColorPixels(&bmp, exx, exx); tex->CheckTrans(buffer, W*H, trans); bIsTransparent = tex->gl_info.mIsTransparent; } @@ -247,7 +236,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F // When using translations everything must be mapped to the base palette. // Since FTexture's method is doing exactly that by calling GetPixels let's use that here // to do all the dirty work for us. ;) - tex->FTexture::CopyTrueColorPixels(&bmp, exx, exy); + tex->FTexture::CopyTrueColorPixels(&bmp, exx, exx); bIsTransparent = 0; } @@ -271,7 +260,7 @@ FHardwareTexture *FGLTexture::CreateHwTexture() if (tex->UseType==FTexture::TEX_Null) return NULL; // Cannot register a NULL texture if (mHwTexture == NULL) { - mHwTexture = new FHardwareTexture(tex->GetWidth() + mExpandX*2, tex->GetHeight() + mExpandY*2, tex->gl_info.bNoCompress); + mHwTexture = new FHardwareTexture(tex->GetWidth() + bExpandFlag*2, tex->GetHeight() + bExpandFlag*2, tex->gl_info.bNoCompress); } return mHwTexture; } @@ -454,7 +443,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) } } } - mBaseLayer = ValidateSysTexture(tx, true); + mBaseLayer = ValidateSysTexture(tx, expanded); mWidth = tx->GetWidth(); @@ -467,7 +456,11 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) mSpriteU[1] = mSpriteV[1] = 1.f; FTexture *basetex = tx->GetRedirect(false); - mBaseLayer = ValidateSysTexture(basetex, expanded); + // allow the redirect only if the textute is not expanded or the scale matches. + if (!expanded || (tx->xScale == basetex->xScale && tx->yScale == basetex->yScale)) + { + mBaseLayer = ValidateSysTexture(basetex, expanded); + } float fxScale = FIXED2FLOAT(tx->xScale); float fyScale = FIXED2FLOAT(tx->yScale); @@ -481,20 +474,17 @@ FMaterial::FMaterial(FTexture * tx, bool expanded) if (expanded) { // a little adjustment to make sprites look better with texture filtering: - // create a 1 pixel wide empty frame around them. The frame must be the same size as the texture scale so that - // position calculations remain scale independent. + // create a 1 pixel wide empty frame around them. int trim[4]; bool trimmed = TrimBorders(trim); // get the trim size before adding the empty frame - int intscaleX = MAX(1, tex->xScale >> FRACBITS); - int intscaleY = MAX(1, tex->yScale >> FRACBITS); int oldwidth = mWidth; int oldheight = mHeight; - mWidth+=2*intscaleX; - mHeight+=2*intscaleY; - mLeftOffset+=intscaleX; - mTopOffset+=intscaleY; + mWidth+=2; + mHeight+=2; + mLeftOffset+=1; + mTopOffset+=1; mRenderWidth = mRenderWidth * mWidth / oldwidth; mRenderHeight = mRenderHeight * mHeight / oldheight; @@ -793,14 +783,30 @@ void FMaterial::BindToFrameBuffer() FMaterial * FMaterial::ValidateTexture(FTexture * tex, bool expand) { +again: if (tex && tex->UseType!=FTexture::TEX_Null) { + if (tex->gl_info.bNoExpand) expand = false; + FMaterial *gltex = tex->gl_info.Material[expand]; if (gltex == NULL) { - if (tex->bWarped || tex->bHasCanvas || tex->gl_info.shaderindex >= FIRST_USER_SHADER)// || tex->xScale != FRACUNIT && tex->yScale != FRACUNIT) + if (expand) { - expand = false; + if (tex->bWarped || tex->bHasCanvas || tex->gl_info.shaderindex >= FIRST_USER_SHADER) + { + tex->gl_info.bNoExpand = true; + goto again; + } + if (tex->gl_info.Brightmap != NULL && + (tex->GetWidth() != tex->gl_info.Brightmap->GetWidth() || + tex->GetHeight() != tex->gl_info.Brightmap->GetHeight()) + ) + { + // do not expand if the brightmap's size differs. + tex->gl_info.bNoExpand = true; + goto again; + } } gltex = new FMaterial(tex, expand); } diff --git a/src/gl/textures/gl_material.h b/src/gl/textures/gl_material.h index 96404c3164..61fdd6e462 100644 --- a/src/gl/textures/gl_material.h +++ b/src/gl/textures/gl_material.h @@ -66,8 +66,6 @@ private: bool bHasColorkey; // only for hires bool bExpandFlag; - int mExpandX; - int mExpandY; unsigned char * LoadHiresTexture(FTexture *hirescheck, int *width, int *height); @@ -80,11 +78,6 @@ public: ~FGLTexture(); unsigned char * CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck, bool createexpanded = true); - void SetExpand(int x, int y) - { - mExpandX = x; - mExpandY = y; - } void Clean(bool all); int Dump(int i); diff --git a/src/gl/textures/gl_texture.cpp b/src/gl/textures/gl_texture.cpp index 27a489162a..414f631a45 100644 --- a/src/gl/textures/gl_texture.cpp +++ b/src/gl/textures/gl_texture.cpp @@ -235,6 +235,7 @@ FTexture::MiscGLInfo::MiscGLInfo() throw() bDisableFullbright = false; bNoFilter = false; bNoCompress = false; + bNoExpand = false; areas = NULL; areacount = 0; mIsTransparent = -1; diff --git a/src/textures/textures.h b/src/textures/textures.h index 6192da8354..6a75dfed34 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -352,6 +352,7 @@ public: bool bDisableFullbright:1; // This texture will not be displayed as fullbright sprite bool bNoFilter:1; bool bNoCompress:1; + bool bNoExpand:1; MiscGLInfo() throw (); ~MiscGLInfo();