From 3e1707e64116d43696ae85b9c8daabd62eb70bd3 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Tue, 27 May 2003 00:20:54 +0000 Subject: [PATCH] Consolidate poly line code, so it can be used with both renderers. Use it with D3D instead of hardware lines. --- stepmania/src/RageDisplay.cpp | 68 ++++++++++++++ stepmania/src/RageDisplay.h | 6 +- stepmania/src/RageDisplay_D3D.cpp | 5 +- stepmania/src/RageDisplay_D3D.h | 2 +- stepmania/src/RageDisplay_OGL.cpp | 151 ++++++++++-------------------- 5 files changed, 127 insertions(+), 105 deletions(-) diff --git a/stepmania/src/RageDisplay.cpp b/stepmania/src/RageDisplay.cpp index 7c374d63cf..e2dbb7c05f 100644 --- a/stepmania/src/RageDisplay.cpp +++ b/stepmania/src/RageDisplay.cpp @@ -76,6 +76,74 @@ void RageDisplay::ResetStats() void RageDisplay::StatsAddVerts( int iNumVertsRendered ) { g_iVertsRenderedSinceLastCheck += iNumVertsRendered; } +/* Draw a line as a quad. GL_LINES with antialiasing off can draw line + * ends at odd angles--they're forced to axis-alignment regardless of the + * angle of the line. */ +void RageDisplay::DrawPolyLine(const RageVertex &p1, const RageVertex &p2, float LineWidth ) +{ + /* soh cah toa strikes strikes again! */ + float opp = p2.p.x - p1.p.x; + float adj = p2.p.y - p1.p.y; + float hyp = powf(opp*opp + adj*adj, 0.5f); + + float lsin = opp/hyp; + float lcos = adj/hyp; + + RageVertex v[4]; + + v[0] = v[1] = p1; + v[2] = v[3] = p2; + + float ydist = lsin * LineWidth/2; + float xdist = lcos * LineWidth/2; + + v[0].p.x += xdist; + v[0].p.y -= ydist; + v[1].p.x -= xdist; + v[1].p.y += ydist; + v[2].p.x -= xdist; + v[2].p.y += ydist; + v[3].p.x += xdist; + v[3].p.y -= ydist; + + this->DrawQuad(v); +} + + +void RageDisplay::DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ) +{ + ASSERT( iNumVerts >= 2 ); + + /* Draw a line strip with rounded corners using polys. This is used on + * cards that have strange allergic reactions to antialiased points and + * lines. */ + int i; + for(i = 0; i < iNumVerts-1; ++i) + DrawPolyLine(v[i], v[i+1], LineWidth); + + /* Join the lines with circles so we get rounded corners. */ + for(i = 0; i < iNumVerts; ++i) + DrawCircle( v[i], LineWidth/2 ); +} + +void RageDisplay::DrawCircle( const RageVertex &p, float radius ) +{ + const int subdivisions = 32; + RageVertex v[subdivisions+2]; + v[0] = p; + + for(int i = 0; i < subdivisions+1; ++i) + { + const float fRotation = float(i) / subdivisions * 2*PI; + const float fX = cosf(fRotation) * radius; + const float fY = -sinf(fRotation) * radius; + v[1+i] = v[0]; + v[1+i].p.x += fX; + v[1+i].p.y += fY; + } + + this->DrawFan( v, subdivisions+2 ); +} diff --git a/stepmania/src/RageDisplay.h b/stepmania/src/RageDisplay.h index 172d5f24f1..db90720cd8 100644 --- a/stepmania/src/RageDisplay.h +++ b/stepmania/src/RageDisplay.h @@ -133,13 +133,17 @@ public: virtual void DrawStrip( const RageVertex v[], int iNumVerts ) = 0; virtual void DrawTriangles( const RageVertex v[], int iNumVerts ) = 0; virtual void DrawIndexedTriangles( const RageVertex v[], const Uint16* pIndices, int iNumIndices ) = 0; - virtual void DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ) = 0; + virtual void DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ); + + void DrawCircle( const RageVertex &v, float radius ); virtual void SaveScreenshot( CString sPath ) = 0; protected: virtual void SetViewport(int shift_left, int shift_down) = 0; + void DrawPolyLine(const RageVertex &p1, const RageVertex &p2, float LineWidth ); + // Stuff in RageDisplay.cpp void SetDefaultRenderStates(); diff --git a/stepmania/src/RageDisplay_D3D.cpp b/stepmania/src/RageDisplay_D3D.cpp index dc8a7ecf54..9d3542cc4e 100644 --- a/stepmania/src/RageDisplay_D3D.cpp +++ b/stepmania/src/RageDisplay_D3D.cpp @@ -665,6 +665,9 @@ void RageDisplay_D3D::DrawIndexedTriangles( const RageVertex v[], const Uint16 p StatsAddVerts( iNumIndices ); } +/* Use the default poly-based implementation. D3D lines apparently don't support + * AA with greater-than-one widths. */ +/* void RageDisplay_D3D::DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ) { ASSERT( iNumVerts >= 2 ); @@ -679,7 +682,7 @@ void RageDisplay_D3D::DrawLineStrip( const RageVertex v[], int iNumVerts, float ); StatsAddVerts( iNumVerts ); } - +*/ void RageDisplay_D3D::SetTexture( RageTexture* pTexture ) { if( pTexture == NULL ) diff --git a/stepmania/src/RageDisplay_D3D.h b/stepmania/src/RageDisplay_D3D.h index 261384fd18..d461a558a4 100644 --- a/stepmania/src/RageDisplay_D3D.h +++ b/stepmania/src/RageDisplay_D3D.h @@ -64,7 +64,7 @@ public: void DrawStrip( const RageVertex v[], int iNumVerts ); void DrawTriangles( const RageVertex v[], int iNumVerts ); void DrawIndexedTriangles( const RageVertex v[], const Uint16* pIndices, int iNumIndices ); - void DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ); +// void DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ); void SaveScreenshot( CString sPath ); protected: diff --git a/stepmania/src/RageDisplay_OGL.cpp b/stepmania/src/RageDisplay_OGL.cpp index 3897819188..f0d68f4ca9 100644 --- a/stepmania/src/RageDisplay_OGL.cpp +++ b/stepmania/src/RageDisplay_OGL.cpp @@ -485,127 +485,74 @@ void RageDisplay_OGL::DrawIndexedTriangles( const RageVertex v[], const Uint16 p StatsAddVerts( iNumIndices ); } -/* Draw a line as a quad. GL_LINES with antialiasing off can draw line - * ends at odd angles--they're forced to axis-alignment regardless of the - * angle of the line. */ -void DrawPolyLine(const RageVertex &p1, const RageVertex &p2, float LineWidth ) -{ - /* soh cah toa strikes strikes again! */ - float opp = p2.p.x - p1.p.x; - float adj = p2.p.y - p1.p.y; - float hyp = powf(opp*opp + adj*adj, 0.5f); - - float lsin = opp/hyp; - float lcos = adj/hyp; - - RageVertex v[4]; - - v[0] = v[1] = p1; - v[2] = v[3] = p2; - - float ydist = lsin * LineWidth/2; - float xdist = lcos * LineWidth/2; - - v[0].p.x += xdist; - v[0].p.y -= ydist; - v[1].p.x -= xdist; - v[1].p.y += ydist; - v[2].p.x -= xdist; - v[2].p.y += ydist; - v[3].p.x += xdist; - v[3].p.y -= ydist; - - DISPLAY->DrawQuad(v); -} - void RageDisplay_OGL::DrawLineStrip( const RageVertex v[], int iNumVerts, float LineWidth ) { ASSERT( iNumVerts >= 2 ); - + + if( g_bAALinesBroken ) + { + RageDisplay::DrawLineStrip(v, iNumVerts, LineWidth ); + return; + } + glMatrixMode( GL_PROJECTION ); glLoadMatrixf( (const float*)GetProjection() ); glMatrixMode( GL_MODELVIEW ); glLoadMatrixf( (const float*)GetModelViewTop() ); - if( g_bAALinesBroken ) - { - /* Draw a line strip with rounded corners using polys. This is used on - * cards that have strange allergic reactions to antialiased points and - * lines. */ - int i; - for(i = 0; i < iNumVerts-1; ++i) - DrawPolyLine(v[i], v[i+1], LineWidth); + /* Draw a nice AA'd line loop. One problem with this is that point and line + * sizes don't always precisely match, which doesn't look quite right. + * It's worth it for the AA, though. */ + glEnable(GL_LINE_SMOOTH); - /* Join the lines with circles so we get rounded corners. */ - GLUquadricObj *q = gluNewQuadric(); - for(i = 0; i < iNumVerts; ++i) - { - glPushMatrix(); - glColor4ub(v[i].c.r, v[i].c.g, v[i].c.b, v[i].c.a); - glTexCoord3fv(v[i].t); - glTranslatef(v[i].p.x, v[i].p.y, v[i].p.z); + /* Our line width is wrt the regular internal SCREEN_WIDTHxSCREEN_HEIGHT screen, + * but these width functions actually want raster sizes (that is, actual pixels). + * Scale the line width and point size by the average ratio of the scale. */ + float WidthVal = float(wind->GetWidth()) / SCREEN_WIDTH; + float HeightVal = float(wind->GetHeight()) / SCREEN_HEIGHT; + LineWidth *= (WidthVal + HeightVal) / 2; - gluDisk(q, 0, LineWidth/2, 32, 32); - glPopMatrix(); - } - gluDeleteQuadric(q); - } - else - { - /* Draw a nice AA'd line loop. One problem with this is that point and line - * sizes don't always precisely match, which doesn't look quite right. - * It's worth it for the AA, though. */ - glEnable(GL_LINE_SMOOTH); + /* Clamp the width to the hardware max for both lines and points (whichever + * is more restrictive). */ + LineWidth = clamp(LineWidth, g_line_range[0], g_line_range[1]); + LineWidth = clamp(LineWidth, g_point_range[0], g_point_range[1]); - /* Our line width is wrt the regular internal SCREEN_WIDTHxSCREEN_HEIGHT screen, - * but these width functions actually want raster sizes (that is, actual pixels). - * Scale the line width and point size by the average ratio of the scale. */ - float WidthVal = float(wind->GetWidth()) / SCREEN_WIDTH; - float HeightVal = float(wind->GetHeight()) / SCREEN_HEIGHT; - LineWidth *= (WidthVal + HeightVal) / 2; + /* Hmm. The granularity of lines and points might be different; for example, + * if lines are .5 and points are .25, we might want to snap the width to the + * nearest .5, so the hardware doesn't snap them to different sizes. Does it + * matter? */ + glLineWidth(LineWidth); - /* Clamp the width to the hardware max for both lines and points (whichever - * is more restrictive). */ - LineWidth = clamp(LineWidth, g_line_range[0], g_line_range[1]); - LineWidth = clamp(LineWidth, g_point_range[0], g_point_range[1]); + /* Draw the line loop: */ + SetupVertices( v, iNumVerts ); + glDrawArrays( GL_LINE_STRIP, 0, iNumVerts ); - /* Hmm. The granularity of lines and points might be different; for example, - * if lines are .5 and points are .25, we might want to snap the width to the - * nearest .5, so the hardware doesn't snap them to different sizes. Does it - * matter? */ - glLineWidth(LineWidth); + glDisable(GL_LINE_SMOOTH); - /* Draw the line loop: */ - SetupVertices( v, iNumVerts ); - glDrawArrays( GL_LINE_STRIP, 0, iNumVerts ); + /* Round off the corners. This isn't perfect; the point is sometimes a little + * larger than the line, causing a small bump on the edge. Not sure how to fix + * that. */ + glPointSize(LineWidth); - glDisable(GL_LINE_SMOOTH); + /* Hack: if the points will all be the same, we don't want to draw + * any points at all, since there's nothing to connect. That'll happen + * if both scale factors in the matrix are ~0. (Actually, I think + * it's true if two of the three scale factors are ~0, but we don't + * use this for anything 3d at the moment anyway ...) This is needed + * because points aren't scaled like regular polys--a zero-size point + * will still be drawn. */ + RageMatrix mat; + glGetFloatv( GL_MODELVIEW_MATRIX, (float*)mat ); - /* Round off the corners. This isn't perfect; the point is sometimes a little - * larger than the line, causing a small bump on the edge. Not sure how to fix - * that. */ - glPointSize(LineWidth); + if(mat.m[0][0] < 1e-5 && mat.m[1][1] < 1e-5) + return; - /* Hack: if the points will all be the same, we don't want to draw - * any points at all, since there's nothing to connect. That'll happen - * if both scale factors in the matrix are ~0. (Actually, I think - * it's true if two of the three scale factors are ~0, but we don't - * use this for anything 3d at the moment anyway ...) This is needed - * because points aren't scaled like regular polys--a zero-size point - * will still be drawn. */ - RageMatrix mat; - glGetFloatv( GL_MODELVIEW_MATRIX, (float*)mat ); + glEnable(GL_POINT_SMOOTH); - if(mat.m[0][0] < 1e-5 && mat.m[1][1] < 1e-5) - return; + SetupVertices( v, iNumVerts ); + glDrawArrays( GL_POINTS, 0, iNumVerts ); - glEnable(GL_POINT_SMOOTH); - - SetupVertices( v, iNumVerts ); - glDrawArrays( GL_POINTS, 0, iNumVerts ); - - glDisable(GL_POINT_SMOOTH); - } + glDisable(GL_POINT_SMOOTH); } void RageDisplay_OGL::SetTexture( RageTexture* pTexture )