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