reactos/modules/rosapps/applications/screensavers/butterflies/butterflies.c

332 lines
9.9 KiB
C

#include <windows.h>
#include <scrnsave.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include "resource.h"
HINSTANCE hInstance; // Holds The Instance Of The Application
GLuint texture[3]; //stores texture objects and display list
HDC hdcOpenGL;
LPCTSTR registryPath = _T("Software\\Microsoft\\ScreenSavers\\Butterflies");
BOOL dRotate;
struct object // Create A Structure Called Object
{
int tex; // Integer Used To Select Our Texture
float x; // X Position
float y; // Y Position
float z; // Z Position
float yi; // Y Increase Speed (Fall Speed)
float spinz; // Z Axis Spin
float spinzi; // Z Axis Spin Speed
float flap; // Flapping Triangles :)
float fi; // Flap Direction (Increase Value)
};
struct object obj[50];
//object obj[50]; // Create 50 Objects Using The Object Structure
void SetDefaults()
{
dRotate = TRUE;
}
void ReadRegistry(){
LONG result;
HKEY skey;
DWORD valtype, valsize, val;
SetDefaults();
result = RegOpenKeyEx(HKEY_CURRENT_USER, registryPath, 0, KEY_READ, &skey);
if(result != ERROR_SUCCESS)
return;
valsize=sizeof(val);
result = RegQueryValueEx(skey, _T("Rotate"), 0, &valtype, (LPBYTE)&val, &valsize);
if(result == ERROR_SUCCESS)
dRotate = val;
RegCloseKey(skey);
}
void WriteRegistry(){
LONG result;
HKEY skey;
DWORD val, disp;
result = RegCreateKeyEx(HKEY_CURRENT_USER, registryPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey, &disp);
if(result != ERROR_SUCCESS)
return;
val = dRotate;
RegSetValueEx(skey, _T("Rotate"), 0, REG_DWORD, (CONST BYTE*)&val, sizeof(val));
RegCloseKey(skey);
}
void SetObject(int loop) // Sets The Initial Value Of Each Object (Random)
{
obj[loop].tex=rand()%3; // Texture Can Be One Of 3 Textures
obj[loop].x=rand()%34-17.0f; // Random x Value From -17.0f To 17.0f
obj[loop].y=18.0f; // Set y Position To 18 (Off Top Of Screen)
obj[loop].z=-((rand()%30000/1000.0f)+10.0f); // z Is A Random Value From -10.0f To -40.0f
obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f; // spinzi Is A Random Value From -1.0f To 1.0f
obj[loop].flap=0.0f; // flap Starts Off At 0.0f;
obj[loop].fi=0.05f+(rand()%100)/1000.0f; // fi Is A Random Value From 0.05f To 0.15f
obj[loop].yi=0.001f+(rand()%1000)/10000.0f; // yi Is A Random Value From 0.001f To 0.101f
}
void LoadGLTextures() // Creates Textures From Bitmaps In The Resource File
{
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure
int loop;
// The ID Of The 3 Bitmap Images We Want To Load From The Resource File
byte Texture[]={ IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 };
glGenTextures(sizeof(Texture), &texture[0]); // Generate 3 Textures (sizeof(Texture)=3 ID's)
for (loop=0; loop<sizeof(Texture); loop++) // Loop Through All The ID's (Bitmap Images)
{
hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (hBMP) // Does The Bitmap Exist?
{ // If So...
GetObject(hBMP,sizeof(BMP), &BMP); // Get The Object
// hBMP: Handle To Graphics Object
// sizeof(BMP): Size Of Buffer For Object Information
// Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT,4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
glBindTexture(GL_TEXTURE_2D, texture[loop]); // Bind Our Texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); // Mipmap Linear Filtering
// Generate Mipmapped Texture (3 Bytes, Width, Height And Data From The BMP)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
}
}
}
HGLRC InitOGLWindow(HWND hWnd)
{
HDC hDC = GetDC(hWnd);
HGLRC hRC = 0;
PIXELFORMATDESCRIPTOR pfd;
int nFormat;
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
pfd.cColorBits = 24;
pfd.cDepthBits = 24;
nFormat = ChoosePixelFormat(hDC, &pfd);
DescribePixelFormat(hDC, nFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
SetPixelFormat(hDC, nFormat, &pfd);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
hdcOpenGL = hDC;
return hRC;
}
void InitOpenGL(GLsizei width, GLsizei height)
{
int loop;
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective (45.0f, (GLfloat)(width)/(GLfloat)(height),1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity();
// Start Of User Initialization
LoadGLTextures(); // Load The Textures From Our Resource File
glClearColor (0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth (1.0f); // Depth Buffer Setup
glDepthFunc (GL_LEQUAL); // The Type Of Depth Testing (Less Or Equal)
glDisable(GL_DEPTH_TEST); // Disable Depth Testing
glShadeModel (GL_SMOOTH); // Select Smooth Shading
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Set Perspective Calculations To Most Accurate
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glBlendFunc(GL_ONE,GL_SRC_ALPHA); // Set Blending Mode (Cheap / Quick)
glEnable(GL_BLEND);
for (loop=0; loop<50; loop++) // Loop To Initialize 50 Objects
{
SetObject(loop); // Call SetObject To Assign New Random Values
}
}
void Display()
{
int loop;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
for (loop=0; loop<50; loop++) // Loop Of 50 (Draw 50 Objects)
{
glLoadIdentity (); // Reset The Modelview Matrix
glBindTexture(GL_TEXTURE_2D, texture[obj[loop].tex]); // Bind Our Texture
glTranslatef(obj[loop].x,obj[loop].y,obj[loop].z); // Position The Object
glRotatef(45.0f,1.0f,0.0f,0.0f); // Rotate On The X-Axis
if (dRotate)
{
glRotatef((obj[loop].spinz),0.0f,0.0f,1.0f); // Spin On The Z-Axis
}
glBegin(GL_TRIANGLES); // Begin Drawing Triangles
// First Triangle _____
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // (2)| / (1)
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f, obj[loop].flap); // | /
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // (3)|/
// Second Triangle
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // /|(1)
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // / |
glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f,-1.0f, obj[loop].flap); // (2)/____|(3)
glEnd(); // Done Drawing Triangles
obj[loop].y-=obj[loop].yi; // Move Object Down The Screen
obj[loop].spinz+=obj[loop].spinzi; // Increase Z Rotation By spinzi
obj[loop].flap+=obj[loop].fi; // Increase flap Value By fi
if (obj[loop].y<-18.0f) // Is Object Off The Screen?
{
SetObject(loop); // If So, Reassign New Values
}
if ((obj[loop].flap>1.0f) || (obj[loop].flap<-1.0f)) // Time To Change Flap Direction?
{
obj[loop].fi=-obj[loop].fi; // Change Direction By Making fi = -fi
}
}
Sleep(15); // Create A Short Delay (15 Milliseconds)
glFlush ();
}
INT_PTR CALLBACK AboutProc(HWND hdlg, UINT msg, WPARAM wpm, LPARAM lpm){
switch(msg){
case WM_CTLCOLORSTATIC:
if(((HWND)lpm == GetDlgItem(hdlg, WEBPAGE1)) || ((HWND)lpm == GetDlgItem(hdlg, WEBPAGE2)))
{
SetTextColor((HDC)wpm, RGB(0,0,255));
SetBkColor((HDC)wpm, (COLORREF)GetSysColor(COLOR_3DFACE));
return (INT_PTR)GetSysColorBrush(COLOR_3DFACE);
}
break;
case WM_COMMAND:
switch(LOWORD(wpm)){
case IDOK:
EndDialog(hdlg, LOWORD(wpm));
break;
case WEBPAGE1:
ShellExecute(NULL, _T("open"), _T("http://nehe.gamedev.net"), NULL, NULL, SW_SHOWNORMAL);
break;
case WEBPAGE2:
ShellExecute(NULL, _T("open"), _T("http://www.thaputer.com"), NULL, NULL, SW_SHOWNORMAL);
break;
}
}
return FALSE;
}
LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
static HGLRC hRC;
static DWORD timer = 1;
HDC hDC;
RECT WindowRect;
int width;
int height;
switch (message)
{
case WM_CREATE:
ReadRegistry();
hRC = InitOGLWindow(hWnd);
GetClientRect (hWnd, &WindowRect);
width = WindowRect.right - WindowRect.left;
height = WindowRect.bottom - WindowRect.top;
InitOpenGL(width,height);
SetTimer(hWnd, timer, 5, NULL);
break;
case WM_TIMER:
hDC = GetDC(hWnd);
Display();
SwapBuffers(hDC);
ReleaseDC(hWnd, hDC);
break;
case WM_DESTROY:
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hdcOpenGL);
break;
}
return DefScreenSaverProc(hWnd, message, wParam, lParam);
}
BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
ReadRegistry();
CheckDlgButton(hDlg, ROTATE, dRotate);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
dRotate = (IsDlgButtonChecked(hDlg, ROTATE) == BST_CHECKED);
WriteRegistry();
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, TRUE);
break;
case IDABOUT:
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_ABOUT), hDlg, AboutProc);
break;
}
}
return FALSE;
}
BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
return TRUE;
}