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