1 #include <windows.h> 2 #include <scrnsave.h> 3 #include <tchar.h> 4 #include <math.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <GL/gl.h> 8 #include <GL/glu.h> 9 #include <GL/glext.h> 10 #include "resource.h" 11 12 HINSTANCE hInstance; // Holds The Instance Of The Application 13 14 GLuint texture[3]; //stores texture objects and display list 15 HDC hdcOpenGL; 16 17 LPCTSTR registryPath = _T("Software\\Microsoft\\ScreenSavers\\Butterflies"); 18 BOOL dRotate; 19 20 21 struct object // Create A Structure Called Object 22 { 23 int tex; // Integer Used To Select Our Texture 24 float x; // X Position 25 float y; // Y Position 26 float z; // Z Position 27 float yi; // Y Increase Speed (Fall Speed) 28 float spinz; // Z Axis Spin 29 float spinzi; // Z Axis Spin Speed 30 float flap; // Flapping Triangles :) 31 float fi; // Flap Direction (Increase Value) 32 }; 33 34 struct object obj[50]; 35 //object obj[50]; // Create 50 Objects Using The Object Structure 36 37 void SetDefaults() 38 { 39 dRotate = TRUE; 40 } 41 42 void ReadRegistry(){ 43 LONG result; 44 HKEY skey; 45 DWORD valtype, valsize, val; 46 47 SetDefaults(); 48 49 result = RegOpenKeyEx(HKEY_CURRENT_USER, registryPath, 0, KEY_READ, &skey); 50 if(result != ERROR_SUCCESS) 51 return; 52 53 valsize=sizeof(val); 54 55 result = RegQueryValueEx(skey, _T("Rotate"), 0, &valtype, (LPBYTE)&val, &valsize); 56 if(result == ERROR_SUCCESS) 57 dRotate = val; 58 RegCloseKey(skey); 59 } 60 61 void WriteRegistry(){ 62 LONG result; 63 HKEY skey; 64 DWORD val, disp; 65 66 result = RegCreateKeyEx(HKEY_CURRENT_USER, registryPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey, &disp); 67 if(result != ERROR_SUCCESS) 68 return; 69 70 val = dRotate; 71 RegSetValueEx(skey, _T("Rotate"), 0, REG_DWORD, (CONST BYTE*)&val, sizeof(val)); 72 73 RegCloseKey(skey); 74 } 75 76 void SetObject(int loop) // Sets The Initial Value Of Each Object (Random) 77 { 78 obj[loop].tex=rand()%3; // Texture Can Be One Of 3 Textures 79 obj[loop].x=rand()%34-17.0f; // Random x Value From -17.0f To 17.0f 80 obj[loop].y=18.0f; // Set y Position To 18 (Off Top Of Screen) 81 obj[loop].z=-((rand()%30000/1000.0f)+10.0f); // z Is A Random Value From -10.0f To -40.0f 82 obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f; // spinzi Is A Random Value From -1.0f To 1.0f 83 obj[loop].flap=0.0f; // flap Starts Off At 0.0f; 84 obj[loop].fi=0.05f+(rand()%100)/1000.0f; // fi Is A Random Value From 0.05f To 0.15f 85 obj[loop].yi=0.001f+(rand()%1000)/10000.0f; // yi Is A Random Value From 0.001f To 0.101f 86 } 87 88 void LoadGLTextures() // Creates Textures From Bitmaps In The Resource File 89 { 90 HBITMAP hBMP; // Handle Of The Bitmap 91 BITMAP BMP; // Bitmap Structure 92 int loop; 93 94 // The ID Of The 3 Bitmap Images We Want To Load From The Resource File 95 byte Texture[]={ IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 }; 96 97 glGenTextures(sizeof(Texture), &texture[0]); // Generate 3 Textures (sizeof(Texture)=3 ID's) 98 for (loop=0; loop<sizeof(Texture); loop++) // Loop Through All The ID's (Bitmap Images) 99 { 100 hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 101 if (hBMP) // Does The Bitmap Exist? 102 { // If So... 103 GetObject(hBMP,sizeof(BMP), &BMP); // Get The Object 104 // hBMP: Handle To Graphics Object 105 // sizeof(BMP): Size Of Buffer For Object Information 106 // Buffer For Object Information 107 glPixelStorei(GL_UNPACK_ALIGNMENT,4); // Pixel Storage Mode (Word Alignment / 4 Bytes) 108 glBindTexture(GL_TEXTURE_2D, texture[loop]); // Bind Our Texture 109 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering 110 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); // Mipmap Linear Filtering 111 112 // Generate Mipmapped Texture (3 Bytes, Width, Height And Data From The BMP) 113 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits); 114 } 115 } 116 } 117 118 HGLRC InitOGLWindow(HWND hWnd) 119 { 120 HDC hDC = GetDC(hWnd); 121 HGLRC hRC = 0; 122 PIXELFORMATDESCRIPTOR pfd; 123 int nFormat; 124 125 ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); 126 127 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 128 pfd.nVersion = 1; 129 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; 130 pfd.cColorBits = 24; 131 pfd.cDepthBits = 24; 132 133 nFormat = ChoosePixelFormat(hDC, &pfd); 134 DescribePixelFormat(hDC, nFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 135 SetPixelFormat(hDC, nFormat, &pfd); 136 137 hRC = wglCreateContext(hDC); 138 wglMakeCurrent(hDC, hRC); 139 140 hdcOpenGL = hDC; 141 142 return hRC; 143 } 144 145 void InitOpenGL(GLsizei width, GLsizei height) 146 { 147 int loop; 148 149 if (height==0) // Prevent A Divide By Zero By 150 { 151 height=1; // Making Height Equal One 152 } 153 154 glViewport(0,0,width,height); // Reset The Current Viewport 155 156 glMatrixMode(GL_PROJECTION); // Select The Projection Matrix 157 glLoadIdentity(); // Reset The Projection Matrix 158 159 // Calculate The Aspect Ratio Of The Window 160 gluPerspective (45.0f, (GLfloat)(width)/(GLfloat)(height),1.0f, 1000.0f); 161 162 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix 163 glLoadIdentity(); 164 // Start Of User Initialization 165 LoadGLTextures(); // Load The Textures From Our Resource File 166 167 glClearColor (0.0f, 0.0f, 0.0f, 0.5f); // Black Background 168 glClearDepth (1.0f); // Depth Buffer Setup 169 glDepthFunc (GL_LEQUAL); // The Type Of Depth Testing (Less Or Equal) 170 glDisable(GL_DEPTH_TEST); // Disable Depth Testing 171 glShadeModel (GL_SMOOTH); // Select Smooth Shading 172 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Set Perspective Calculations To Most Accurate 173 glEnable(GL_TEXTURE_2D); // Enable Texture Mapping 174 glBlendFunc(GL_ONE,GL_SRC_ALPHA); // Set Blending Mode (Cheap / Quick) 175 glEnable(GL_BLEND); 176 177 178 for (loop=0; loop<50; loop++) // Loop To Initialize 50 Objects 179 { 180 SetObject(loop); // Call SetObject To Assign New Random Values 181 } 182 183 } 184 185 void Display() 186 { 187 int loop; 188 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer 189 190 for (loop=0; loop<50; loop++) // Loop Of 50 (Draw 50 Objects) 191 { 192 glLoadIdentity (); // Reset The Modelview Matrix 193 glBindTexture(GL_TEXTURE_2D, texture[obj[loop].tex]); // Bind Our Texture 194 glTranslatef(obj[loop].x,obj[loop].y,obj[loop].z); // Position The Object 195 glRotatef(45.0f,1.0f,0.0f,0.0f); // Rotate On The X-Axis 196 if (dRotate) 197 { 198 glRotatef((obj[loop].spinz),0.0f,0.0f,1.0f); // Spin On The Z-Axis 199 } 200 glBegin(GL_TRIANGLES); // Begin Drawing Triangles 201 // First Triangle _____ 202 glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // (2)| / (1) 203 glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f, obj[loop].flap); // | / 204 glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // (3)|/ 205 206 // Second Triangle 207 glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // /|(1) 208 glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // / | 209 glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f,-1.0f, obj[loop].flap); // (2)/____|(3) 210 211 glEnd(); // Done Drawing Triangles 212 213 obj[loop].y-=obj[loop].yi; // Move Object Down The Screen 214 obj[loop].spinz+=obj[loop].spinzi; // Increase Z Rotation By spinzi 215 obj[loop].flap+=obj[loop].fi; // Increase flap Value By fi 216 217 if (obj[loop].y<-18.0f) // Is Object Off The Screen? 218 { 219 SetObject(loop); // If So, Reassign New Values 220 } 221 222 if ((obj[loop].flap>1.0f) || (obj[loop].flap<-1.0f)) // Time To Change Flap Direction? 223 { 224 obj[loop].fi=-obj[loop].fi; // Change Direction By Making fi = -fi 225 } 226 } 227 228 Sleep(15); // Create A Short Delay (15 Milliseconds) 229 230 glFlush (); 231 232 } 233 234 INT_PTR CALLBACK AboutProc(HWND hdlg, UINT msg, WPARAM wpm, LPARAM lpm){ 235 236 switch(msg){ 237 case WM_CTLCOLORSTATIC: 238 if(((HWND)lpm == GetDlgItem(hdlg, WEBPAGE1)) || ((HWND)lpm == GetDlgItem(hdlg, WEBPAGE2))) 239 { 240 SetTextColor((HDC)wpm, RGB(0,0,255)); 241 SetBkColor((HDC)wpm, (COLORREF)GetSysColor(COLOR_3DFACE)); 242 return (INT_PTR)GetSysColorBrush(COLOR_3DFACE); 243 } 244 break; 245 case WM_COMMAND: 246 switch(LOWORD(wpm)){ 247 case IDOK: 248 EndDialog(hdlg, LOWORD(wpm)); 249 break; 250 case WEBPAGE1: 251 ShellExecute(NULL, _T("open"), _T("http://nehe.gamedev.net"), NULL, NULL, SW_SHOWNORMAL); 252 break; 253 case WEBPAGE2: 254 ShellExecute(NULL, _T("open"), _T("http://www.thaputer.com"), NULL, NULL, SW_SHOWNORMAL); 255 break; 256 } 257 } 258 return FALSE; 259 } 260 261 LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT message, 262 WPARAM wParam, LPARAM lParam) 263 { 264 static HGLRC hRC; 265 static DWORD timer = 1; 266 HDC hDC; 267 RECT WindowRect; 268 int width; 269 int height; 270 271 switch (message) 272 { 273 case WM_CREATE: 274 ReadRegistry(); 275 hRC = InitOGLWindow(hWnd); 276 GetClientRect (hWnd, &WindowRect); 277 width = WindowRect.right - WindowRect.left; 278 height = WindowRect.bottom - WindowRect.top; 279 InitOpenGL(width,height); 280 SetTimer(hWnd, timer, 5, NULL); 281 break; 282 case WM_TIMER: 283 hDC = GetDC(hWnd); 284 Display(); 285 SwapBuffers(hDC); 286 ReleaseDC(hWnd, hDC); 287 break; 288 case WM_DESTROY: 289 wglMakeCurrent(NULL, NULL); 290 wglDeleteContext(hRC); 291 ReleaseDC(hWnd, hdcOpenGL); 292 break; 293 } 294 295 return DefScreenSaverProc(hWnd, message, wParam, lParam); 296 } 297 298 BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message, 299 WPARAM wParam, LPARAM lParam) 300 { 301 switch (message) 302 { 303 case WM_INITDIALOG: 304 ReadRegistry(); 305 CheckDlgButton(hDlg, ROTATE, dRotate); 306 return TRUE; 307 case WM_COMMAND: 308 switch (LOWORD(wParam)) 309 { 310 case IDOK: 311 dRotate = (IsDlgButtonChecked(hDlg, ROTATE) == BST_CHECKED); 312 WriteRegistry(); 313 EndDialog(hDlg, TRUE); 314 return TRUE; 315 case IDCANCEL: 316 EndDialog(hDlg, TRUE); 317 break; 318 case IDABOUT: 319 DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_ABOUT), hDlg, AboutProc); 320 break; 321 } 322 } 323 324 return FALSE; 325 } 326 327 BOOL WINAPI RegisterDialogClasses(HANDLE hInst) 328 { 329 return TRUE; 330 } 331 332