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