Fix a rounding bug that effected screenshots and resolutions.

Previously, you may have gotten values like 639x480 (4:3) or 853x480 (16:9).
These are due to rounding errors caused by lrintf; ceilf does what we really want.

[RageDisplay.cpp] modified screenshot function
[ScreenDimensions] modified SCREEN_WIDTH and SCREEN_HEIGHT algorithms (no longer do you need to SCREEN_WIDTH+1 for 16:9 support)
[StepMania.cpp] modified windowed mode width calculation
This commit is contained in:
AJ Kelly
2010-03-21 17:02:42 -05:00
parent e79835ee78
commit 54b6dffb75
3 changed files with 43 additions and 46 deletions
+25 -29
View File
@@ -15,9 +15,7 @@
#include "DisplayResolutions.h" #include "DisplayResolutions.h"
#include "arch/ArchHooks/ArchHooks.h" #include "arch/ArchHooks/ArchHooks.h"
//
// Statistics stuff // Statistics stuff
//
RageTimer g_LastCheckTimer; RageTimer g_LastCheckTimer;
int g_iNumVerts; int g_iNumVerts;
int g_iFPS, g_iVPF, g_iCFPS; int g_iFPS, g_iVPF, g_iCFPS;
@@ -145,7 +143,7 @@ void RageDisplay::ResetStats()
RString RageDisplay::GetStats() const RString RageDisplay::GetStats() const
{ {
RString s; RString s;
/* If FPS == 0, we don't have stats yet. */ // If FPS == 0, we don't have stats yet.
if( !GetFPS() ) if( !GetFPS() )
s = "-- FPS\n-- av FPS\n-- VPF"; s = "-- FPS\n-- av FPS\n-- VPF";
@@ -182,7 +180,7 @@ void RageDisplay::StatsAddVerts( int iNumVertsRendered ) { g_iVertsRenderedSince
* angle of the line. */ * angle of the line. */
void RageDisplay::DrawPolyLine(const RageSpriteVertex &p1, const RageSpriteVertex &p2, float LineWidth ) void RageDisplay::DrawPolyLine(const RageSpriteVertex &p1, const RageSpriteVertex &p2, float LineWidth )
{ {
/* soh cah toa strikes strikes again! */ // soh cah toa strikes strikes again!
float opp = p2.p.x - p1.p.x; float opp = p2.p.x - p1.p.x;
float adj = p2.p.y - p1.p.y; float adj = p2.p.y - p1.p.y;
float hyp = powf(opp*opp + adj*adj, 0.5f); float hyp = powf(opp*opp + adj*adj, 0.5f);
@@ -215,13 +213,13 @@ void RageDisplay::DrawLineStripInternal( const RageSpriteVertex v[], int iNumVer
{ {
ASSERT( iNumVerts >= 2 ); ASSERT( iNumVerts >= 2 );
/* Draw a line strip with rounded corners using polys. This is used on /* Draw a line strip with rounded corners using polys. This is used on
* cards that have strange allergic reactions to antialiased points and * cards that have strange allergic reactions to antialiased points and
* lines. */ * lines. */
for( int i = 0; i < iNumVerts-1; ++i ) for( int i = 0; i < iNumVerts-1; ++i )
DrawPolyLine(v[i], v[i+1], LineWidth); DrawPolyLine(v[i], v[i+1], LineWidth);
/* Join the lines with circles so we get rounded corners. */ // Join the lines with circles so we get rounded corners.
for( int i = 0; i < iNumVerts; ++i ) for( int i = 0; i < iNumVerts; ++i )
DrawCircle( v[i], LineWidth/2 ); DrawCircle( v[i], LineWidth/2 );
} }
@@ -246,7 +244,6 @@ void RageDisplay::DrawCircleInternal( const RageSpriteVertex &p, float radius )
} }
void RageDisplay::SetDefaultRenderStates() void RageDisplay::SetDefaultRenderStates()
{ {
SetLighting( false ); SetLighting( false );
@@ -261,9 +258,7 @@ void RageDisplay::SetDefaultRenderStates()
} }
//
// Matrix stuff // Matrix stuff
//
class MatrixStack class MatrixStack
{ {
vector<RageMatrix> stack; vector<RageMatrix> stack;
@@ -279,14 +274,14 @@ public:
void Pop() void Pop()
{ {
stack.pop_back(); stack.pop_back();
ASSERT( stack.size() > 0 ); // underflow ASSERT( stack.size() > 0 ); // underflow
} }
// Pushes the stack by one, duplicating the current matrix. // Pushes the stack by one, duplicating the current matrix.
void Push() void Push()
{ {
stack.push_back( stack.back() ); stack.push_back( stack.back() );
ASSERT( stack.size() < 100 ); // overflow ASSERT( stack.size() < 100 ); // overflow
} }
// Loads identity in the current matrix. // Loads identity in the current matrix.
@@ -555,7 +550,7 @@ void RageDisplay::TextureTranslate( float x, float y )
void RageDisplay::LoadMenuPerspective( float fovDegrees, float fWidth, float fHeight, float fVanishPointX, float fVanishPointY ) void RageDisplay::LoadMenuPerspective( float fovDegrees, float fWidth, float fHeight, float fVanishPointX, float fVanishPointY )
{ {
/* fovDegrees == 0 gives ortho projection. */ // fovDegrees == 0 gives ortho projection.
if( fovDegrees == 0 ) if( fovDegrees == 0 )
{ {
float left = 0, right = fWidth, bottom = fHeight, top = 0; float left = 0, right = fWidth, bottom = fHeight, top = 0;
@@ -575,8 +570,7 @@ void RageDisplay::LoadMenuPerspective( float fovDegrees, float fWidth, float fHe
fVanishPointX -= fWidth/2; fVanishPointX -= fWidth/2;
fVanishPointY -= fHeight/2; fVanishPointY -= fHeight/2;
// It's the caller's responsibility to push first.
/* It's the caller's responsibility to push first. */
g_ProjectionStack.LoadMatrix( g_ProjectionStack.LoadMatrix(
GetFrustumMatrix( GetFrustumMatrix(
(fVanishPointX-fWidth/2)/fDistCameraFromImage, (fVanishPointX-fWidth/2)/fDistCameraFromImage,
@@ -608,14 +602,14 @@ void RageDisplay::CameraPopMatrix()
} }
/* gluLookAt. The result is pre-multiplied to the matrix (M = L * M) instead of /* gluLookAt. The result is pre-multiplied to the matrix (M = L * M) instead of
* post-multiplied. */ * post-multiplied. */
void RageDisplay::LoadLookAt( float fFOV, const RageVector3 &Eye, const RageVector3 &At, const RageVector3 &Up ) void RageDisplay::LoadLookAt( float fFOV, const RageVector3 &Eye, const RageVector3 &At, const RageVector3 &Up )
{ {
float fAspect = GetActualVideoModeParams().fDisplayAspectRatio; float fAspect = GetActualVideoModeParams().fDisplayAspectRatio;
g_ProjectionStack.LoadMatrix( GetPerspectiveMatrix(fFOV, fAspect, 1, 1000) ); g_ProjectionStack.LoadMatrix( GetPerspectiveMatrix(fFOV, fAspect, 1, 1000) );
/* Flip the Y coordinate, so positive numbers go down. */ // Flip the Y coordinate, so positive numbers go down.
g_ProjectionStack.Scale( 1, -1, 1 ); g_ProjectionStack.Scale( 1, -1, 1 );
g_ViewStack.LoadMatrix( RageLookAt(Eye.x, Eye.y, Eye.z, At.x, At.y, At.z, Up.x, Up.y, Up.z) ); g_ViewStack.LoadMatrix( RageLookAt(Eye.x, Eye.y, Eye.z, At.x, At.y, At.z, Up.x, Up.y, Up.z) );
@@ -624,12 +618,12 @@ void RageDisplay::LoadLookAt( float fFOV, const RageVector3 &Eye, const RageVect
RageMatrix RageDisplay::GetPerspectiveMatrix(float fovy, float aspect, float zNear, float zFar) RageMatrix RageDisplay::GetPerspectiveMatrix(float fovy, float aspect, float zNear, float zFar)
{ {
float ymax = zNear * tanf(fovy * PI / 360.0f); float ymax = zNear * tanf(fovy * PI / 360.0f);
float ymin = -ymax; float ymin = -ymax;
float xmin = ymin * aspect; float xmin = ymin * aspect;
float xmax = ymax * aspect; float xmax = ymax * aspect;
return GetFrustumMatrix(xmin, xmax, ymin, ymax, zNear, zFar); return GetFrustumMatrix(xmin, xmax, ymin, ymax, zNear, zFar);
} }
RageSurface *RageDisplay::CreateSurfaceFromPixfmt( PixelFormat pixfmt, RageSurface *RageDisplay::CreateSurfaceFromPixfmt( PixelFormat pixfmt,
@@ -663,9 +657,9 @@ PixelFormat RageDisplay::FindPixelFormat( int iBPP, int iRmask, int iGmask, int
return PixelFormat_Invalid; return PixelFormat_Invalid;
} }
/* These convert to OpenGL's coordinate system: -1,-1 is the bottom-left, +1,+1 is the /* These convert to OpenGL's coordinate system: -1,-1 is the bottom-left,
* top-right, and Z goes from -1 (viewer) to +1 (distance). It's a little odd, but * +1,+1 is the top-right, and Z goes from -1 (viewer) to +1 (distance).
* very well-defined. */ * It's a little odd, but very well-defined. */
RageMatrix RageDisplay::GetOrthoMatrix( float l, float r, float b, float t, float zn, float zf ) RageMatrix RageDisplay::GetOrthoMatrix( float l, float r, float b, float t, float zn, float zf )
{ {
RageMatrix m( RageMatrix m(
@@ -693,20 +687,20 @@ RageMatrix RageDisplay::GetFrustumMatrix( float l, float r, float b, float t, fl
void RageDisplay::ResolutionChanged() void RageDisplay::ResolutionChanged()
{ {
/* The centering matrix depends on the resolution. */ // The centering matrix depends on the resolution.
UpdateCentering(); UpdateCentering();
} }
void RageDisplay::CenteringPushMatrix() void RageDisplay::CenteringPushMatrix()
{ {
g_CenteringStack.push_back( g_CenteringStack.back() ); g_CenteringStack.push_back( g_CenteringStack.back() );
ASSERT( g_CenteringStack.size() < 100 ); // overflow ASSERT( g_CenteringStack.size() < 100 ); // overflow
} }
void RageDisplay::CenteringPopMatrix() void RageDisplay::CenteringPopMatrix()
{ {
g_CenteringStack.pop_back(); g_CenteringStack.pop_back();
ASSERT( g_CenteringStack.size() > 0 ); // underflow ASSERT( g_CenteringStack.size() > 0 ); // underflow
UpdateCentering(); UpdateCentering();
} }
@@ -761,10 +755,12 @@ bool RageDisplay::SaveScreenshot( RString sPath, GraphicsFileFormat format )
* screenshots in a strange (non-1) sample aspect ratio. */ * screenshots in a strange (non-1) sample aspect ratio. */
if( format != SAVE_LOSSLESS && format != SAVE_LOSSLESS_SENSIBLE ) if( format != SAVE_LOSSLESS && format != SAVE_LOSSLESS_SENSIBLE )
{ {
/* Maintain the DAR. */ // Maintain the DAR.
ASSERT( GetActualVideoModeParams().fDisplayAspectRatio > 0 ); ASSERT( GetActualVideoModeParams().fDisplayAspectRatio > 0 );
int iHeight = 480; int iHeight = 480;
int iWidth = lrintf( iHeight * GetActualVideoModeParams().fDisplayAspectRatio ); // This used to be lrintf. However, lrintf causes odd resolutions like
// 639x480 (4:3) and 853x480 (16:9). ceilf gives correct values. -aj
int iWidth = ceilf( iHeight * GetActualVideoModeParams().fDisplayAspectRatio );
timer.Touch(); timer.Touch();
RageSurfaceUtils::Zoom( surface, iWidth, iHeight ); RageSurfaceUtils::Zoom( surface, iWidth, iHeight );
// LOG->Trace( "%ix%i -> %ix%i (%.3f) in %f seconds", surface->w, surface->h, iWidth, iHeight, GetActualVideoModeParams().fDisplayAspectRatio, timer.GetDeltaTime() ); // LOG->Trace( "%ix%i -> %ix%i (%.3f) in %f seconds", surface->w, surface->h, iWidth, iHeight, GetActualVideoModeParams().fDisplayAspectRatio, timer.GetDeltaTime() );
+5 -2
View File
@@ -25,6 +25,9 @@ float ScreenDimensions::GetThemeAspectRatio()
return THEME_NATIVE_ASPECT; return THEME_NATIVE_ASPECT;
} }
// ceilf was originally lrintf. However, lrintf causes odd resolutions like
// 639x480 (4:3) and 853x480 (16:9). ceilf gives the correct values of 640x480
// and 854x480 respectively. -aj
float ScreenDimensions::GetScreenWidth() float ScreenDimensions::GetScreenWidth()
{ {
float fAspect = PREFSMAN->m_fDisplayAspectRatio; float fAspect = PREFSMAN->m_fDisplayAspectRatio;
@@ -32,7 +35,7 @@ float ScreenDimensions::GetScreenWidth()
if( fAspect > THEME_NATIVE_ASPECT ) if( fAspect > THEME_NATIVE_ASPECT )
fScale = fAspect / THEME_NATIVE_ASPECT; fScale = fAspect / THEME_NATIVE_ASPECT;
ASSERT( fScale >= 1 ); ASSERT( fScale >= 1 );
return (float) lrintf(THEME_SCREEN_WIDTH * fScale); return (float) ceilf(THEME_SCREEN_WIDTH * fScale);
} }
float ScreenDimensions::GetScreenHeight() float ScreenDimensions::GetScreenHeight()
@@ -42,7 +45,7 @@ float ScreenDimensions::GetScreenHeight()
if( fAspect < THEME_NATIVE_ASPECT ) if( fAspect < THEME_NATIVE_ASPECT )
fScale = THEME_NATIVE_ASPECT / fAspect; fScale = THEME_NATIVE_ASPECT / fAspect;
ASSERT( fScale >= 1 ); ASSERT( fScale >= 1 );
return (float) lrintf(THEME_SCREEN_HEIGHT * fScale); return (float) ceilf(THEME_SCREEN_HEIGHT * fScale);
} }
void ScreenDimensions::ReloadScreenDimensions() void ScreenDimensions::ReloadScreenDimensions()
+3 -5
View File
@@ -103,11 +103,9 @@ void StepMania::GetPreferredVideoModeParams( VideoModeParams &paramsOut )
int iWidth = PREFSMAN->m_iDisplayWidth; int iWidth = PREFSMAN->m_iDisplayWidth;
if( PREFSMAN->m_bWindowed ) if( PREFSMAN->m_bWindowed )
{ {
/* //float fRatio = PREFSMAN->m_iDisplayWidth / PREFSMAN->m_iDisplayHeight;
float fRatio = PREFSMAN->m_iDisplayWidth / PREFSMAN->m_iDisplayHeight; //iWidth = PREFSMAN->m_iDisplayHeight * fRatio;
iWidth = PREFSMAN->m_iDisplayHeight * fRatio; iWidth = ceilf(PREFSMAN->m_iDisplayHeight * PREFSMAN->m_fDisplayAspectRatio);
*/
iWidth = PREFSMAN->m_iDisplayHeight * PREFSMAN->m_fDisplayAspectRatio;
} }
paramsOut = VideoModeParams( paramsOut = VideoModeParams(