1 /* 2 * Copyright 2000 Jeff Molofee http://nehe.gamedev.net/ (Original code) 3 * Copyright 2006 Eric Kohl 4 * Copyright 2007 Marc Piulachs (marc.piulachs@codexchange.net) - minor modifications , converted to screensaver 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21 #include "3dtext.h" 22 23 #include <winbase.h> 24 #include <wingdi.h> 25 #include <winuser.h> 26 #include <scrnsave.h> 27 #include <math.h> 28 #include <GL/glu.h> 29 30 #include "resource.h" 31 32 static HGLRC hRC; // Permanent Rendering Context 33 static HDC hDC; // Private GDI Device Context 34 35 GLuint base; // Base Display List For The Font Set 36 GLfloat rot; // Used To Rotate The Text 37 GLfloat extentX = 0.0f; 38 GLfloat extentY = 0.0f; 39 40 #define APPNAME _T("3DText") 41 42 HINSTANCE hInstance; 43 BOOL fullscreen = FALSE; 44 45 // Build Our Bitmap Font 46 GLvoid BuildFont(GLvoid) 47 { 48 // Address Buffer For Font Storage 49 GLYPHMETRICSFLOAT gmf[256]; 50 // Windows Font Handle 51 HFONT font; 52 size_t i; 53 TCHAR c; 54 GLfloat cellOriginX = 0.0f; 55 GLfloat stringOriginX; 56 GLfloat stringExtentX = 0.0f; 57 GLfloat stringExtentY = 0.0f; 58 59 // Storage For 256 Characters 60 base = glGenLists(256); 61 62 font = CreateFont(-12, 63 0, // Width Of Font 64 0, // Angle Of Escapement 65 0, // Orientation Angle 66 FW_BOLD, // Font Weight 67 FALSE, // Italic 68 FALSE, // Underline 69 FALSE, // Strikeout 70 DEFAULT_CHARSET, // Character Set Identifier 71 OUT_TT_PRECIS, // Output Precision 72 CLIP_DEFAULT_PRECIS, // Clipping Precision 73 ANTIALIASED_QUALITY, // Output Quality 74 FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch 75 _T("Tahoma")); // Font Name 76 77 // Selects The Font We Created 78 SelectObject(hDC, font); 79 80 wglUseFontOutlines(hDC, // Select The Current DC 81 0, // Starting Character 82 255, // Number Of Display Lists To Build 83 base, // Starting Display Lists 84 0.0f, // Deviation From The True Outlines 85 0.2f, // Font Thickness In The Z Direction 86 WGL_FONT_POLYGONS, // Use Polygons, Not Lines 87 gmf); // Address Of Buffer To Receive Data 88 89 // Calculate the string extent 90 for (i = 0; i < _tcslen(m_Text); i++) 91 { 92 c = m_Text[i]; 93 94 stringOriginX = cellOriginX + gmf[c].gmfptGlyphOrigin.x; 95 96 stringExtentX = stringOriginX + gmf[c].gmfBlackBoxX; 97 if (gmf[c].gmfBlackBoxY > stringExtentY) 98 stringExtentY = gmf[c].gmfBlackBoxY; 99 100 cellOriginX = cellOriginX + gmf[c].gmfCellIncX; 101 } 102 103 extentX = stringExtentX; 104 extentY = stringExtentY; 105 } 106 107 // Delete The Font 108 GLvoid KillFont(GLvoid) 109 { 110 // Delete all 256 characters 111 glDeleteLists(base, 256); 112 } 113 114 // Custom GL "Print" Routine 115 GLvoid glPrint(LPTSTR text) 116 { 117 // If there's no text, do nothing 118 if (text == NULL) 119 return; 120 121 // Pushes The Display List Bits 122 glPushAttrib(GL_LIST_BIT); 123 124 // Sets The Base Character to 32 125 glListBase(base); 126 127 // Draws The Display List Text 128 glCallLists(_tcslen(text), 129 #ifdef UNICODE 130 GL_UNSIGNED_SHORT, 131 #else 132 GL_UNSIGNED_BYTE, 133 #endif 134 text); 135 136 // Pops The Display List Bits 137 glPopAttrib(); 138 } 139 140 // Will Be Called Right After The GL Window Is Created 141 GLvoid InitGL(GLsizei Width, GLsizei Height) 142 { 143 // Clear The Background Color To Black 144 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 145 146 // Enables Clearing Of The Depth Buffer 147 glClearDepth(1.0); 148 149 // The Type Of Depth Test To Do 150 glDepthFunc(GL_LESS); 151 152 // Enables Depth Testing 153 glEnable(GL_DEPTH_TEST); 154 155 // Enables Smooth Color Shading 156 glShadeModel(GL_SMOOTH); 157 158 // Select The Projection Matrix 159 glMatrixMode(GL_PROJECTION); 160 161 // Reset The Projection Matrix 162 glLoadIdentity(); 163 164 // Calculate The Aspect Ratio Of The Window 165 gluPerspective(45.0f, (GLfloat)Width / (GLfloat)Height, 0.1f, 100.0f); 166 167 // Select The Modelview Matrix 168 glMatrixMode(GL_MODELVIEW); 169 170 // Build The Font 171 BuildFont(); 172 173 // Enable Default Light (Quick And Dirty) 174 glEnable(GL_LIGHT0); 175 176 // Enable Lighting 177 glEnable(GL_LIGHTING); 178 179 // Enable Coloring Of Material 180 glEnable(GL_COLOR_MATERIAL); 181 } 182 183 // Handles Window Resizing 184 GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height) 185 { 186 // Is Window Too Small (Divide By Zero Error) 187 if (Height == 0) 188 { 189 // If So Make It One Pixel Tall 190 Height = 1; 191 } 192 193 // Reset The Current Viewport And Perspective Transformation 194 glViewport(0, 0, Width, Height); 195 196 // Select The Projection Matrix 197 glMatrixMode(GL_PROJECTION); 198 199 // Reset The Projection Matrix 200 glLoadIdentity(); 201 202 // Calculate The Aspect Ratio Of The Window 203 gluPerspective(45.0f, (GLfloat)Width / (GLfloat)Height, 0.1f, 100.0f); 204 205 // Select The Modelview Matrix 206 glMatrixMode(GL_MODELVIEW); 207 } 208 209 // Handles Rendering 210 GLvoid DrawGLScene(GLvoid) 211 { 212 // Save ticks count of previous frame here 213 static DWORD dwTicks = 0; 214 215 // Clear The Screen And The Depth Buffer 216 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 217 218 // Reset The View 219 glLoadIdentity(); 220 221 // Move One Unit Into The Screen 222 glTranslatef(0.0f, 0.0f, -10.0f); 223 224 // Rotate On The X Axis 225 glRotatef(rot, 1.0f, 0.0f, 0.0f); 226 227 // Rotate On The Y Axis 228 glRotatef(rot * 1.2f, 0.0f, 1.0f, 0.0f); 229 230 // Rotate On The Z Axis 231 glRotatef(rot * 1.4f, 0.0f, 0.0f, 1.0f); 232 233 // Move to the Left and Down before drawing 234 glTranslatef(-(extentX / 2.0f), 235 -(extentY / 2.0f), 236 0.0f); 237 238 // Pulsing Colors Based On The Rotation 239 glColor3f((1.0f * (GLfloat)(cos(rot / 20.0f))), 240 (1.0f * (GLfloat)(sin(rot / 25.0f))), 241 (1.0f - 0.5f * (GLfloat)(cos(rot / 17.0f)))); 242 243 // Print GL Text To The Screen 244 glPrint(m_Text); 245 246 // Make The Text Blue 247 glColor3f(0.0f, 0.0f, 1.0f); 248 249 // Increase The Rotation Variable 250 if(dwTicks) 251 rot += (GetTickCount() - dwTicks) / 20.0f; 252 dwTicks = GetTickCount(); 253 } 254 255 LRESULT CALLBACK 256 ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 257 { 258 RECT Screen; // Used Later On To Get The Size Of The Window 259 GLuint PixelFormat; // Pixel Format Storage 260 static PIXELFORMATDESCRIPTOR pfd= // Pixel Format Descriptor 261 { 262 sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 263 1, // Version Number (?) 264 PFD_DRAW_TO_WINDOW | // Format Must Support Window 265 PFD_SUPPORT_OPENGL | // Format Must Support OpenGL 266 PFD_DOUBLEBUFFER, // Must Support Double Buffering 267 PFD_TYPE_RGBA, // Request An RGBA Format 268 16, // Select A 16Bit Color Depth 269 0, 0, 0, 0, 0, 0, // Color Bits Ignored (?) 270 0, // No Alpha Buffer 271 0, // Shift Bit Ignored (?) 272 0, // No Accumulation Buffer 273 0, 0, 0, 0, // Accumulation Bits Ignored (?) 274 16, // 16Bit Z-Buffer (Depth Buffer) 275 0, // No Stencil Buffer 276 0, // No Auxiliary Buffer (?) 277 PFD_MAIN_PLANE, // Main Drawing Layer 278 0, // Reserved (?) 279 0, 0, 0 // Layer Masks Ignored (?) 280 }; 281 282 switch (message) 283 { 284 case WM_CREATE: 285 LoadSettings(); 286 287 // Gets A Device Context For The Window 288 hDC = GetDC(hWnd); 289 290 // Finds The Closest Match To The Pixel Format We Set Above 291 PixelFormat = ChoosePixelFormat(hDC, &pfd); 292 293 // No Matching Pixel Format? 294 if (!PixelFormat) 295 { 296 MessageBox(0, _TEXT("Can't Find A Suitable PixelFormat."), _TEXT("Error"),MB_OK | MB_ICONERROR); 297 298 // This Sends A 'Message' Telling The Program To Quit 299 PostQuitMessage(0); 300 break; 301 } 302 303 // Can We Set The Pixel Mode? 304 if (!SetPixelFormat(hDC, PixelFormat, &pfd)) 305 { 306 MessageBox(0, _TEXT("Can't Set The PixelFormat."), _TEXT("Error"), MB_OK | MB_ICONERROR); 307 308 // This Sends A 'Message' Telling The Program To Quit 309 PostQuitMessage(0); 310 break; 311 } 312 313 // Grab A Rendering Context 314 hRC = wglCreateContext(hDC); 315 316 // Did We Get One? 317 if (!hRC) 318 { 319 MessageBox(0, _TEXT("Can't Create A GL Rendering Context."), _TEXT("Error"), MB_OK | MB_ICONERROR); 320 321 // This Sends A 'Message' Telling The Program To Quit 322 PostQuitMessage(0); 323 break; 324 } 325 326 // Can We Make The RC Active? 327 if (!wglMakeCurrent(hDC, hRC)) 328 { 329 MessageBox(0, _TEXT("Can't Activate GLRC."), _TEXT("Error"), MB_OK | MB_ICONERROR); 330 331 // This Sends A 'Message' Telling The Program To Quit 332 PostQuitMessage(0); 333 break; 334 } 335 336 // Grab Screen Info For The Current Window 337 GetClientRect(hWnd, &Screen); 338 339 // Initialize The GL Screen Using Screen Info 340 InitGL(Screen.right, Screen.bottom); 341 break; 342 343 case WM_DESTROY: 344 // Disable Fullscreen Mode 345 ChangeDisplaySettings(NULL, 0); 346 347 // Deletes The Font Display List 348 KillFont(); 349 350 // Make The DC Current 351 wglMakeCurrent(hDC, NULL); 352 353 // Kill The RC 354 wglDeleteContext(hRC); 355 356 // Free The DC 357 ReleaseDC(hWnd, hDC); 358 break; 359 360 case WM_PAINT: 361 DrawGLScene(); 362 SwapBuffers(hDC); 363 break; 364 365 case WM_SIZE: // Resizing The Screen 366 // Resize To The New Window Size 367 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); 368 break; 369 370 default: 371 // Pass Windows Messages to the default screensaver window procedure 372 return DefScreenSaverProc(hWnd, message, wParam, lParam); 373 } 374 375 return 0; 376 } 377 378 // 379 // Dialogbox procedure for Configuration window 380 // 381 BOOL CALLBACK ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 382 { 383 switch (uMsg) 384 { 385 case WM_INITDIALOG: 386 LoadSettings(); 387 SetDlgItemText(hDlg, IDC_MESSAGE_TEXT, m_Text); 388 return TRUE; 389 390 case WM_COMMAND: 391 switch (LOWORD(wParam)) 392 { 393 case IDOK: 394 GetDlgItemText(hDlg, IDC_MESSAGE_TEXT, m_Text, MAX_PATH); 395 SaveSettings(); 396 397 /* Fall through */ 398 399 case IDCANCEL: 400 EndDialog(hDlg, IDCANCEL); 401 break; 402 } 403 return FALSE; 404 405 case WM_CLOSE: 406 EndDialog(hDlg, 0); 407 break; 408 409 default: 410 return FALSE; 411 } 412 413 return TRUE; 414 } 415 416 BOOL WINAPI RegisterDialogClasses(HANDLE hInst) 417 { 418 return TRUE; 419 } 420