a64e3252ecf508a2dcde71debd05433990c289e3
[reactos.git] / reactos / 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 #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 }