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