1 /* 2 * Copyright 2003 J Brown 3 * Copyright 2006 Andrey Korotaev <unC0Rr@inbox.ru> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 18 */ 19 20 #include <windows.h> 21 #include <GL/gl.h> 22 #include <GL/glu.h> 23 #include <tchar.h> 24 #include <scrnsave.h> 25 #include "resource.h" 26 27 #define APPNAME _T("Cylfrac") 28 #define wfactor 0.9 29 #define rotfactor 1.5 30 #define FPS 100 31 #define timerdelay 1000/FPS 32 33 POINT initpoint; 34 HDC dc; 35 HGLRC hrc; 36 DWORD oldticks; 37 MMRESULT TimerID; 38 39 DWORD lvls = 7; 40 int cylquality = 8; 41 42 HINSTANCE hInstance; 43 44 GLUquadricObj * cylinder; 45 46 float angle = 0; 47 float colorh = 0.0; 48 float rval, gval, bval; 49 50 BOOL fullscreen = FALSE; 51 52 float _RGB(float H, float M1, float M2) 53 { 54 if(H < 0.0) H += 360.0; 55 else if(H > 360.0) H -= 360.0; 56 if(H < 60) return M1 + (M2 - M1) * H / 60.0; 57 if((H >= 60 )&&(H < 180)) return M2; 58 if((H >= 180)&&(H < 240)) return M1 + (M2 - M1)*(240 - H) / 60.0; 59 return M1; 60 } 61 62 void HLStoRGB(float H, float L, float S, 63 float* R, float* G, float* B) 64 { 65 float M1, M2; 66 if(S <= 0.5) M2 = S * (1 + L); 67 else M2 = S * (1 - L) + L; 68 M1 = 2 * S - M2; 69 if (L == 0.0) 70 { 71 *R = S; 72 *G = S; 73 *B = S; 74 } else { 75 *R = _RGB(H + 120.0, M1, M2); 76 *G = _RGB(H , M1, M2); 77 *B = _RGB(H - 120.0, M1, M2); 78 } 79 } 80 81 void DrawCylinder(int n, float rota, float width) 82 { 83 glPushMatrix(); 84 glColor3f(rval/n, gval/n, bval/n); 85 glRotatef(rota, 0.0, 1.0, 0.0); 86 gluCylinder(cylinder, width, width * wfactor, n * 0.5, cylquality, 1); 87 glTranslatef(0.0, 0.0, -n * 0.5); 88 gluCylinder(cylinder, width * wfactor, width, n * 0.5, cylquality, 1); 89 if(n > 1) 90 { 91 float r = rota * rotfactor; 92 glRotatef(90.0, 1.0, 0.0, 0.0); 93 DrawCylinder(n - 1, r, width * wfactor); 94 glTranslatef(0.0, n, 0.0); 95 DrawCylinder(n - 1, -r, width * wfactor); 96 } 97 glPopMatrix(); 98 } 99 100 void DrawScene(HWND hwnd, HDC dc, int ticks) 101 { 102 PAINTSTRUCT ps; 103 dc = BeginPaint(hwnd, &ps); 104 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 105 glRotatef(ticks * 0.01, 0.0, 1.0, -0.5); 106 angle += ticks * 0.01; 107 colorh += ticks * 0.003; 108 if (colorh > 360.0) colorh -= 360.0; 109 HLStoRGB(colorh, 1.0f, 0.7f, &rval, &gval, &bval); 110 DrawCylinder(lvls, angle, 0.2f); 111 SwapBuffers(dc); 112 EndPaint(hwnd, &ps); 113 } 114 115 void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) 116 { 117 InvalidateRect((HWND)dwUser, NULL, 0); 118 } 119 120 void MyPixelFormat(HDC dc) 121 { 122 int npf; 123 PIXELFORMATDESCRIPTOR pfd; 124 125 ZeroMemory(&pfd, sizeof(pfd)); 126 pfd.nSize = sizeof(pfd); 127 pfd.nVersion = 1; 128 pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; 129 130 npf = ChoosePixelFormat(dc, &pfd); 131 if(npf != 0) 132 SetPixelFormat(dc, npf, &pfd); 133 } 134 135 void InitGL(HWND hwnd) 136 { 137 GLfloat lightpos[4] = {2.0f, 2.0f, -2.0f, 0.7f}; 138 GLfloat ca = 1.0; 139 dc = GetDC(hwnd); 140 MyPixelFormat(dc); 141 hrc = wglCreateContext(dc); 142 wglMakeCurrent(dc, hrc); 143 cylinder = gluNewQuadric(); 144 glEnable(GL_DEPTH_TEST); 145 glEnable(GL_LIGHT0); 146 glLightfv(GL_LIGHT0, GL_POSITION, (GLfloat *)&lightpos); 147 glLightfv(GL_LIGHT0, GL_LINEAR_ATTENUATION, &ca); 148 glEnable(GL_LIGHTING); 149 glEnable(GL_COLOR_MATERIAL); 150 } 151 152 LRESULT WINAPI ScreenSaverProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 153 { 154 switch(msg) { 155 case WM_CREATE: 156 { 157 GetCursorPos(&initpoint); 158 InitGL(hwnd); 159 oldticks = GetTickCount(); 160 TimerID = timeSetEvent(timerdelay, 0, TimeProc, (DWORD_PTR)hwnd, TIME_PERIODIC); 161 } 162 break; 163 case WM_PAINT: 164 { 165 DWORD ticks = oldticks; 166 POINT currpoint; 167 oldticks = GetTickCount(); 168 DrawScene(hwnd, dc, oldticks - ticks); 169 if(fullscreen) 170 { 171 GetCursorPos(&currpoint); 172 if(abs(currpoint.x - initpoint.x) + (abs(currpoint.y - initpoint.y)) > 10) 173 PostMessage(hwnd, WM_CLOSE, 0, 0); 174 } 175 } 176 break; 177 case WM_DESTROY: 178 { 179 timeKillEvent(TimerID); 180 gluDeleteQuadric(cylinder); 181 wglMakeCurrent(0, 0); 182 wglDeleteContext(hrc); 183 ReleaseDC(hwnd, dc); 184 DeleteDC(dc); 185 if (fullscreen) 186 ShowCursor(TRUE); 187 PostQuitMessage(0); 188 } 189 break; 190 case WM_SIZE: 191 { 192 int width = LOWORD(lParam); 193 int height = HIWORD(lParam); 194 float fscale; 195 glViewport(0, 0, width, height); 196 glMatrixMode(GL_MODELVIEW); 197 glLoadIdentity(); 198 fscale = 0.8/(float)lvls; 199 glScalef(fscale, fscale, fscale); 200 } 201 break; 202 default: 203 return DefScreenSaverProc(hwnd, msg, wParam, lParam); 204 } 205 return 0; 206 } 207 208 BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam) 209 { 210 return FALSE; 211 } 212 213 BOOL WINAPI RegisterDialogClasses(HANDLE hmodule) 214 { 215 TCHAR szTitle[256]; 216 TCHAR szText[256]; 217 218 LoadString(hmodule, 219 IDS_TITLE, 220 szTitle, 221 256); 222 223 LoadString(hmodule, 224 IDS_TEXT, 225 szText, 226 256); 227 228 MessageBox(0, 229 szText, 230 szTitle, 231 MB_OK | MB_ICONWARNING); 232 return FALSE; 233 } 234