b11a6c36ff7211b9e762d056f564b272446d17ae
[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 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 Receive 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 // Save ticks count of previous frame here
204 static DWORD dwTicks = 0;
205
206 // Clear The Screen And The Depth Buffer
207 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
208
209 // Reset The View
210 glLoadIdentity();
211
212 // Move One Unit Into The Screen
213 glTranslatef(0.0f, 0.0f, -10.0f);
214
215 // Rotate On The X Axis
216 glRotatef(rot, 1.0f, 0.0f, 0.0f);
217
218 // Rotate On The Y Axis
219 glRotatef(rot * 1.2f, 0.0f, 1.0f, 0.0f);
220
221 // Rotate On The Z Axis
222 glRotatef(rot * 1.4f, 0.0f, 0.0f, 1.0f);
223
224 // Move to the Left and Down before drawing
225 glTranslatef(-(extentX / 2.0f),
226 -(extentY / 2.0f),
227 0.0f);
228
229 // Pulsing Colors Based On The Rotation
230 glColor3f((1.0f * (GLfloat)(cos(rot / 20.0f))),
231 (1.0f * (GLfloat)(sin(rot / 25.0f))),
232 (1.0f - 0.5f * (GLfloat)(cos(rot / 17.0f))));
233
234 // Print GL Text To The Screen
235 glPrint(m_Text);
236
237 // Make The Text Blue
238 glColor3f(0.0f, 0.0f, 1.0f);
239
240 // Increase The Rotation Variable
241 if(dwTicks)
242 rot += (GetTickCount() - dwTicks) / 20.0f;
243 dwTicks = GetTickCount();
244 }
245
246 LRESULT CALLBACK
247 ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
248 {
249 RECT Screen; // Used Later On To Get The Size Of The Window
250 GLuint PixelFormat; // Pixel Format Storage
251 static PIXELFORMATDESCRIPTOR pfd= // Pixel Format Descriptor
252 {
253 sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
254 1, // Version Number (?)
255 PFD_DRAW_TO_WINDOW | // Format Must Support Window
256 PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
257 PFD_DOUBLEBUFFER, // Must Support Double Buffering
258 PFD_TYPE_RGBA, // Request An RGBA Format
259 16, // Select A 16Bit Color Depth
260 0, 0, 0, 0, 0, 0, // Color Bits Ignored (?)
261 0, // No Alpha Buffer
262 0, // Shift Bit Ignored (?)
263 0, // No Accumulation Buffer
264 0, 0, 0, 0, // Accumulation Bits Ignored (?)
265 16, // 16Bit Z-Buffer (Depth Buffer)
266 0, // No Stencil Buffer
267 0, // No Auxiliary Buffer (?)
268 PFD_MAIN_PLANE, // Main Drawing Layer
269 0, // Reserved (?)
270 0, 0, 0 // Layer Masks Ignored (?)
271 };
272
273 switch (message)
274 {
275 case WM_CREATE:
276 LoadSettings();
277
278 // Gets A Device Context For The Window
279 hDC = GetDC(hWnd);
280
281 // Finds The Closest Match To The Pixel Format We Set Above
282 PixelFormat = ChoosePixelFormat(hDC, &pfd);
283
284 // No Matching Pixel Format?
285 if (!PixelFormat)
286 {
287 MessageBox(0, _TEXT("Can't Find A Suitable PixelFormat."), _TEXT("Error"),MB_OK | MB_ICONERROR);
288
289 // This Sends A 'Message' Telling The Program To Quit
290 PostQuitMessage(0);
291 break;
292 }
293
294 // Can We Set The Pixel Mode?
295 if (!SetPixelFormat(hDC, PixelFormat, &pfd))
296 {
297 MessageBox(0, _TEXT("Can't Set The PixelFormat."), _TEXT("Error"), MB_OK | MB_ICONERROR);
298
299 // This Sends A 'Message' Telling The Program To Quit
300 PostQuitMessage(0);
301 break;
302 }
303
304 // Grab A Rendering Context
305 hRC = wglCreateContext(hDC);
306
307 // Did We Get One?
308 if (!hRC)
309 {
310 MessageBox(0, _TEXT("Can't Create A GL Rendering Context."), _TEXT("Error"), MB_OK | MB_ICONERROR);
311
312 // This Sends A 'Message' Telling The Program To Quit
313 PostQuitMessage(0);
314 break;
315 }
316
317 // Can We Make The RC Active?
318 if (!wglMakeCurrent(hDC, hRC))
319 {
320 MessageBox(0, _TEXT("Can't Activate GLRC."), _TEXT("Error"), MB_OK | MB_ICONERROR);
321
322 // This Sends A 'Message' Telling The Program To Quit
323 PostQuitMessage(0);
324 break;
325 }
326
327 // Grab Screen Info For The Current Window
328 GetClientRect(hWnd, &Screen);
329
330 // Initialize The GL Screen Using Screen Info
331 InitGL(Screen.right, Screen.bottom);
332 break;
333
334 case WM_DESTROY:
335 // Disable Fullscreen Mode
336 ChangeDisplaySettings(NULL, 0);
337
338 // Deletes The Font Display List
339 KillFont();
340
341 // Make The DC Current
342 wglMakeCurrent(hDC, NULL);
343
344 // Kill The RC
345 wglDeleteContext(hRC);
346
347 // Free The DC
348 ReleaseDC(hWnd, hDC);
349 break;
350
351 case WM_PAINT:
352 DrawGLScene();
353 SwapBuffers(hDC);
354 break;
355
356 case WM_SIZE: // Resizing The Screen
357 // Resize To The New Window Size
358 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
359 break;
360
361 default:
362 // Pass Windows Messages to the default screensaver window procedure
363 return DefScreenSaverProc(hWnd, message, wParam, lParam);
364 }
365
366 return 0;
367 }
368
369 //
370 // Dialogbox procedure for Configuration window
371 //
372 BOOL CALLBACK ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
373 {
374 switch (uMsg)
375 {
376 case WM_INITDIALOG:
377 LoadSettings();
378 SetDlgItemText(hDlg, IDC_MESSAGE_TEXT, m_Text);
379 return TRUE;
380
381 case WM_COMMAND:
382 switch (LOWORD(wParam))
383 {
384 case IDOK:
385 GetDlgItemText(hDlg, IDC_MESSAGE_TEXT, m_Text, MAX_PATH);
386 SaveSettings();
387
388 /* Fall through */
389
390 case IDCANCEL:
391 EndDialog(hDlg, IDCANCEL);
392 break;
393 }
394 return FALSE;
395
396 case WM_CLOSE:
397 EndDialog(hDlg, 0);
398 break;
399
400 default:
401 return FALSE;
402 }
403
404 return TRUE;
405 }
406
407 BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
408 {
409 return TRUE;
410 }