-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSDLGLFont.cpp
More file actions
196 lines (167 loc) · 6.59 KB
/
Copy pathSDLGLFont.cpp
File metadata and controls
196 lines (167 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/**
* \file SDLGLFont.cpp
* \brief Bitmap font class.
*
* Defines a bitmap font class. A bitmap font is represented with 95
* characters that represent ASCII characters 32 to 126 (0x20 to 0x7E).
* Characters that fall out of this range should be represented with 0x20, or
* space.
*/
#include "SDLGLFont.hpp"
#include "SDLGLTexture.hpp"
#include <assert.h>
#include <vector>
/* Prerequisites:
To support alpha-blended textures, you need to call the following GL functions
somewhere earlier in your program:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glAlphaFunc(GL_GREATER,0.1f);
*/
/**
* \brief Creates an SDLGLFont object from the PNG of the given filename.
* \param fileName The file name of the PNG with the bitmap font.
*/
SDLGLFont::SDLGLFont( std::string fileName ) {
fontLoaded = LoadFontFromFile(fileName);
}
/**
* \brief Destructor for fonts.
*/
SDLGLFont::~SDLGLFont( ) {
if ( fontLoaded == true )
SDLGL_FreeTexture( fontTexture );
}
/**
* \brief Finds the next power of two for an integer.
* \param v The integer to find the next power of two for.
* \return The next power of two of v.
*
* This code is directly copy/pasted from:
* http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
*/
static unsigned int NextPowerOfTwo( unsigned int v ) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/**
* \brief Loads a font from a file.
* \param fileName File name of the PNG containing the bitmap font.
* \return True if the font loaded.
*/
bool SDLGLFont::LoadFontFromFile( std::string fileName ) {
// Linear filtering will make the SDLGLFont look crappy.
fontTexture = SDLGL_LoadTextureFromFileBestFit( fileName,
false,
fontX,
fontY );
// If the font doesn't load, we've got a problem.
if ( fontTexture )
fontLoaded = true;
else
assert(0);
// charX and charY are the width and height of a single character.
charX = fontX / 95; // 95 = number of characters in the SDLGLFont
charY = fontY; // character height is the same.
// texX and texY are the width and height of the font in the OpenGL texture
// buffer, the dimensions of which must be a power of two. As a result, we
// waste a little memory and use the next power of two from the actual
// texture size.
texX = NextPowerOfTwo( fontX );
texY = NextPowerOfTwo( fontY );
return fontLoaded;
}
/**
* \brief Draws the string. Use this if you are already in a glOrtho state.
* \param x The x coordinate on the screen to draw from (upper-left corner).
* \param y The y coordinate on the screen to draw from (upper-left corner).
* \param theString The string to draw on the screen.
*/
void SDLGLFont::DrawString( float x, float y, std::string theString ) {
float charPieceX = ((float)fontX/(float)texX)/95.0f;
// These are the coordinate arrays we're going to send to the GPU.
GLfloat vertices[theString.length()*2*4];
GLfloat texcoords[theString.length()*2*4];
// Set the current GL texture to the font we want to use.
glBindTexture( GL_TEXTURE_2D, fontTexture );
// Populate the vertices & texcoords arrays.
for ( int count = 0; count < theString.length(); count++ ) {
// These must be defined in a counter-clockwise order.
// Upper-left
vertices[count*2*4+0] = x + charX*count;
vertices[count*2*4+1] = y;
texcoords[count*2*4+0] = charPieceX*(theString[count]-32);
texcoords[count*2*4+1] = 0.0f;
// Lower-left
vertices[count*2*4+2] = x + charX*count;
vertices[count*2*4+3] = y + charY;
texcoords[count*2*4+2] = charPieceX*(theString[count]-32);
texcoords[count*2*4+3] = (float)fontY/(float)texY;
// Lower-right
vertices[count*2*4+4] = x + charX*(count+1);
vertices[count*2*4+5] = y + charY;
texcoords[count*2*4+4] = charPieceX*(theString[count]-32+1);
texcoords[count*2*4+5] = (float)fontY/(float)texY;
// Upper-right
vertices[count*2*4+6] = x + charX*(count+1);
vertices[count*2*4+7] = y;
texcoords[count*2*4+6] = charPieceX*(theString[count]-32+1);
texcoords[count*2*4+7] = 0.0f;
}
// Set up the GL state so vertex and texcoord arrays can be uploaded.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Send the arrays to the GPU.
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
// draw the letters
glDrawArrays(GL_QUADS, 0, theString.length()*4);
// deactivate vertex arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
/**
* \brief Draws the string. Use if you need a glOrtho overlay made for you.
* \param x The x coordinate on the screen to draw from (upper-left corner).
* \param y The y coordinate on the screen to draw from (upper-left corner).
* \param theString The string to draw on the screen.
* \param xResolution The total resolution of the glOrtho overlay to make.
* \param yResolution The total resolution of the glOrtho overlay to make.
*/
void SDLGLFont::DrawString( float x, float y, std::string theString, int xResolution, int yResolution ) {
// Saves the old ModelView and Projection matrices, then puts you
// into a GLOrtho environment. Activates textures.
GLfloat modelview[16];
GLfloat projection[16];
// Get the current Modelview and Projection matrices so we can put them
// back when we're done here.
glGetFloatv(GL_MODELVIEW_MATRIX,modelview);
glGetFloatv(GL_PROJECTION_MATRIX,projection);
// Blank out the projection matrix.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the projection matrix to orthoganal to make a "HUD-style" overlay.
glOrtho(0, xResolution, yResolution, 0, -1, 1);
// Blank out the Modelview matrix.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Depth test is inconvenient, texturing is necessary.
glDisable( GL_DEPTH_TEST );
glEnable( GL_TEXTURE_2D );
// Now that everything's in order, actually draw the string.
DrawString( x, y, theString );
// Reloads the old Modelview and Projection matrices. Deactivates textures.
glDisable( GL_TEXTURE_2D);
glEnable( GL_DEPTH_TEST );
// Put the Projection and Modelview matrices back.
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(projection);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(modelview);
}