--- /dev/null
+/*
+ * Copyright 2000 Jeff Molofee http://nehe.gamedev.net/ (Original code)
+ * Copyright 2006 Eric Kohl
+ * Copyright 2007 Marc Piulachs (marc.piulachs@codexchange.net) - minor modifications , converted to screensaver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "3dtext.h"
+
+#include <winbase.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include <scrnsave.h>
+#include <math.h>
+#include <GL/glu.h>
+
+#include "resource.h"
+
+static HGLRC hRC; // Permanent Rendering Context
+static HDC hDC; // Private GDI Device Context
+
+GLuint base; // Base Display List For The Font Set
+GLfloat rot; // Used To Rotate The Text
+GLfloat extentX = 0.0f;
+GLfloat extentY = 0.0f;
+
+#define APPNAME _T("3DText")
+
+HINSTANCE hInstance;
+BOOL fullscreen = FALSE;
+
+// Build Our Bitmap Font
+GLvoid BuildFont(GLvoid)
+{
+ // Address Buffer For Font Storage
+ GLYPHMETRICSFLOAT gmf[256];
+ // Windows Font Handle
+ HFONT font;
+ size_t i;
+ TCHAR c;
+ GLfloat cellOriginX = 0.0f;
+ GLfloat stringOriginX;
+ GLfloat stringExtentX = 0.0f;
+ GLfloat stringExtentY = 0.0f;
+
+ // Storage For 256 Characters
+ base = glGenLists(256);
+
+ font = CreateFont(-12,
+ 0, // Width Of Font
+ 0, // Angle Of Escapement
+ 0, // Orientation Angle
+ FW_BOLD, // Font Weight
+ FALSE, // Italic
+ FALSE, // Underline
+ FALSE, // Strikeout
+ DEFAULT_CHARSET, // Character Set Identifier
+ OUT_TT_PRECIS, // Output Precision
+ CLIP_DEFAULT_PRECIS, // Clipping Precision
+ ANTIALIASED_QUALITY, // Output Quality
+ FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
+ _T("Tahoma")); // Font Name
+
+ // Selects The Font We Created
+ SelectObject(hDC, font);
+
+ wglUseFontOutlines(hDC, // Select The Current DC
+ 0, // Starting Character
+ 255, // Number Of Display Lists To Build
+ base, // Starting Display Lists
+ 0.0f, // Deviation From The True Outlines
+ 0.2f, // Font Thickness In The Z Direction
+ WGL_FONT_POLYGONS, // Use Polygons, Not Lines
+ gmf); // Address Of Buffer To Receive Data
+
+ // Calculate the string extent
+ for (i = 0; i < _tcslen(m_Text); i++)
+ {
+ c = m_Text[i];
+
+ stringOriginX = cellOriginX + gmf[c].gmfptGlyphOrigin.x;
+
+ stringExtentX = stringOriginX + gmf[c].gmfBlackBoxX;
+ if (gmf[c].gmfBlackBoxY > stringExtentY)
+ stringExtentY = gmf[c].gmfBlackBoxY;
+
+ cellOriginX = cellOriginX + gmf[c].gmfCellIncX;
+ }
+
+ extentX = stringExtentX;
+ extentY = stringExtentY;
+}
+
+// Delete The Font
+GLvoid KillFont(GLvoid)
+{
+ // Delete all 256 characters
+ glDeleteLists(base, 256);
+}
+
+// Custom GL "Print" Routine
+GLvoid glPrint(LPTSTR text)
+{
+ // If there's no text, do nothing
+ if (text == NULL)
+ return;
+
+ // Pushes The Display List Bits
+ glPushAttrib(GL_LIST_BIT);
+
+ // Sets The Base Character to 32
+ glListBase(base);
+
+ // Draws The Display List Text
+ glCallLists(_tcslen(text),
+#ifdef UNICODE
+ GL_UNSIGNED_SHORT,
+#else
+ GL_UNSIGNED_BYTE,
+#endif
+ text);
+
+ // Pops The Display List Bits
+ glPopAttrib();
+}
+
+// Will Be Called Right After The GL Window Is Created
+GLvoid InitGL(GLsizei Width, GLsizei Height)
+{
+ // Clear The Background Color To Black
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Enables Clearing Of The Depth Buffer
+ glClearDepth(1.0);
+
+ // The Type Of Depth Test To Do
+ glDepthFunc(GL_LESS);
+
+ // Enables Depth Testing
+ glEnable(GL_DEPTH_TEST);
+
+ // Enables Smooth Color Shading
+ glShadeModel(GL_SMOOTH);
+
+ // Select The Projection Matrix
+ glMatrixMode(GL_PROJECTION);
+
+ // Reset The Projection Matrix
+ glLoadIdentity();
+
+ // Calculate The Aspect Ratio Of The Window
+ gluPerspective(45.0f, (GLfloat)Width / (GLfloat)Height, 0.1f, 100.0f);
+
+ // Select The Modelview Matrix
+ glMatrixMode(GL_MODELVIEW);
+
+ // Build The Font
+ BuildFont();
+
+ // Enable Default Light (Quick And Dirty)
+ glEnable(GL_LIGHT0);
+
+ // Enable Lighting
+ glEnable(GL_LIGHTING);
+
+ // Enable Coloring Of Material
+ glEnable(GL_COLOR_MATERIAL);
+}
+
+// Handles Window Resizing
+GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
+{
+ // Is Window Too Small (Divide By Zero Error)
+ if (Height == 0)
+ {
+ // If So Make It One Pixel Tall
+ Height = 1;
+ }
+
+ // Reset The Current Viewport And Perspective Transformation
+ glViewport(0, 0, Width, Height);
+
+ // Select The Projection Matrix
+ glMatrixMode(GL_PROJECTION);
+
+ // Reset The Projection Matrix
+ glLoadIdentity();
+
+ // Calculate The Aspect Ratio Of The Window
+ gluPerspective(45.0f, (GLfloat)Width / (GLfloat)Height, 0.1f, 100.0f);
+
+ // Select The Modelview Matrix
+ glMatrixMode(GL_MODELVIEW);
+}
+
+// Handles Rendering
+GLvoid DrawGLScene(GLvoid)
+{
+ // Save ticks count of previous frame here
+ static DWORD dwTicks = 0;
+
+ // Clear The Screen And The Depth Buffer
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // Reset The View
+ glLoadIdentity();
+
+ // Move One Unit Into The Screen
+ glTranslatef(0.0f, 0.0f, -10.0f);
+
+ // Rotate On The X Axis
+ glRotatef(rot, 1.0f, 0.0f, 0.0f);
+
+ // Rotate On The Y Axis
+ glRotatef(rot * 1.2f, 0.0f, 1.0f, 0.0f);
+
+ // Rotate On The Z Axis
+ glRotatef(rot * 1.4f, 0.0f, 0.0f, 1.0f);
+
+ // Move to the Left and Down before drawing
+ glTranslatef(-(extentX / 2.0f),
+ -(extentY / 2.0f),
+ 0.0f);
+
+ // Pulsing Colors Based On The Rotation
+ glColor3f((1.0f * (GLfloat)(cos(rot / 20.0f))),
+ (1.0f * (GLfloat)(sin(rot / 25.0f))),
+ (1.0f - 0.5f * (GLfloat)(cos(rot / 17.0f))));
+
+ // Print GL Text To The Screen
+ glPrint(m_Text);
+
+ // Make The Text Blue
+ glColor3f(0.0f, 0.0f, 1.0f);
+
+ // Increase The Rotation Variable
+ if(dwTicks)
+ rot += (GetTickCount() - dwTicks) / 20.0f;
+ dwTicks = GetTickCount();
+}
+
+LRESULT CALLBACK
+ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ RECT Screen; // Used Later On To Get The Size Of The Window
+ GLuint PixelFormat; // Pixel Format Storage
+ static PIXELFORMATDESCRIPTOR pfd= // Pixel Format Descriptor
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
+ 1, // Version Number (?)
+ PFD_DRAW_TO_WINDOW | // Format Must Support Window
+ PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
+ PFD_DOUBLEBUFFER, // Must Support Double Buffering
+ PFD_TYPE_RGBA, // Request An RGBA Format
+ 16, // Select A 16Bit Color Depth
+ 0, 0, 0, 0, 0, 0, // Color Bits Ignored (?)
+ 0, // No Alpha Buffer
+ 0, // Shift Bit Ignored (?)
+ 0, // No Accumulation Buffer
+ 0, 0, 0, 0, // Accumulation Bits Ignored (?)
+ 16, // 16Bit Z-Buffer (Depth Buffer)
+ 0, // No Stencil Buffer
+ 0, // No Auxiliary Buffer (?)
+ PFD_MAIN_PLANE, // Main Drawing Layer
+ 0, // Reserved (?)
+ 0, 0, 0 // Layer Masks Ignored (?)
+ };
+
+ switch (message)
+ {
+ case WM_CREATE:
+ LoadSettings();
+
+ // Gets A Device Context For The Window
+ hDC = GetDC(hWnd);
+
+ // Finds The Closest Match To The Pixel Format We Set Above
+ PixelFormat = ChoosePixelFormat(hDC, &pfd);
+
+ // No Matching Pixel Format?
+ if (!PixelFormat)
+ {
+ MessageBox(0, _TEXT("Can't Find A Suitable PixelFormat."), _TEXT("Error"),MB_OK | MB_ICONERROR);
+
+ // This Sends A 'Message' Telling The Program To Quit
+ PostQuitMessage(0);
+ break;
+ }
+
+ // Can We Set The Pixel Mode?
+ if (!SetPixelFormat(hDC, PixelFormat, &pfd))
+ {
+ MessageBox(0, _TEXT("Can't Set The PixelFormat."), _TEXT("Error"), MB_OK | MB_ICONERROR);
+
+ // This Sends A 'Message' Telling The Program To Quit
+ PostQuitMessage(0);
+ break;
+ }
+
+ // Grab A Rendering Context
+ hRC = wglCreateContext(hDC);
+
+ // Did We Get One?
+ if (!hRC)
+ {
+ MessageBox(0, _TEXT("Can't Create A GL Rendering Context."), _TEXT("Error"), MB_OK | MB_ICONERROR);
+
+ // This Sends A 'Message' Telling The Program To Quit
+ PostQuitMessage(0);
+ break;
+ }
+
+ // Can We Make The RC Active?
+ if (!wglMakeCurrent(hDC, hRC))
+ {
+ MessageBox(0, _TEXT("Can't Activate GLRC."), _TEXT("Error"), MB_OK | MB_ICONERROR);
+
+ // This Sends A 'Message' Telling The Program To Quit
+ PostQuitMessage(0);
+ break;
+ }
+
+ // Grab Screen Info For The Current Window
+ GetClientRect(hWnd, &Screen);
+
+ // Initialize The GL Screen Using Screen Info
+ InitGL(Screen.right, Screen.bottom);
+ break;
+
+ case WM_DESTROY:
+ // Disable Fullscreen Mode
+ ChangeDisplaySettings(NULL, 0);
+
+ // Deletes The Font Display List
+ KillFont();
+
+ // Make The DC Current
+ wglMakeCurrent(hDC, NULL);
+
+ // Kill The RC
+ wglDeleteContext(hRC);
+
+ // Free The DC
+ ReleaseDC(hWnd, hDC);
+ break;
+
+ case WM_PAINT:
+ DrawGLScene();
+ SwapBuffers(hDC);
+ break;
+
+ case WM_SIZE: // Resizing The Screen
+ // Resize To The New Window Size
+ ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
+ break;
+
+ default:
+ // Pass Windows Messages to the default screensaver window procedure
+ return DefScreenSaverProc(hWnd, message, wParam, lParam);
+ }
+
+ return 0;
+}
+
+//
+// Dialogbox procedure for Configuration window
+//
+BOOL CALLBACK ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ LoadSettings();
+ SetDlgItemText(hDlg, IDC_MESSAGE_TEXT, m_Text);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ GetDlgItemText(hDlg, IDC_MESSAGE_TEXT, m_Text, MAX_PATH);
+ SaveSettings();
+
+ /* Fall through */
+
+ case IDCANCEL:
+ EndDialog(hDlg, IDCANCEL);
+ break;
+ }
+ return FALSE;
+
+ case WM_CLOSE:
+ EndDialog(hDlg, 0);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
+{
+ return TRUE;
+}