|
|
/******************************Module*Header*******************************\
* Module Name: ss3dfo.c * * Dispatcher and dialog box for the OpenGL-based 3D Flying Objects screen * saver. * * Created: 18-May-1994 14:54:59 * * Copyright (c) 1994 Microsoft Corporation \**************************************************************************/
#include <windows.h>
#include <scrnsave.h>
#include <GL\gl.h>
#include <math.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys\timeb.h>
#include <time.h>
#include <commdlg.h>
#include <commctrl.h>
#include "ss3dfo.h"
//#define SS_DEBUG 1
// Global strings.
#define GEN_STRING_SIZE 64
static SSContext gssc; BOOL gbBounce = FALSE; // floating window bounce off side
// Global message loop variables.
MATERIAL Material[16]; #ifdef MEMDEBUG
ULONG totalMem = 0; #endif
// Global screen saver settings.
void (*updateSceneFunc)(int); // current screen saver update function
void (*delSceneFunc)(void); // current screen saver deletion function
BOOL bColorCycle = FALSE; // color cycling flag
BOOL bSmoothShading = TRUE; // smooth shading flag
UINT uSize = 100; // object size
float fTesselFact = 1.0f; // object tessalation
int UpdateFlags = 0; // extra data sent to update function
int Type = 0; // screen saver index (into function arrays)
// Texture file information
TEXFILE gTexFile = {0};
// Lighting properties.
static const RGBA lightAmbient = {0.21f, 0.21f, 0.21f, 1.0f}; static const RGBA light0Ambient = {0.0f, 0.0f, 0.0f, 1.0f}; static const RGBA light0Diffuse = {0.7f, 0.7f, 0.7f, 1.0f}; static const RGBA light0Specular = {1.0f, 1.0f, 1.0f, 1.0f}; static const GLfloat light0Pos[] = {100.0f, 100.0f, 100.0f, 0.0f};
// Material properties.
static RGBA matlColors[7] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {0.235f, 0.0f, 0.78f, 1.0f}, };
extern void updateStripScene(int); extern void updateDropScene(int); extern void updateLemScene(int); extern void updateExplodeScene(int); extern void updateWinScene(int); extern void updateTexScene(int); extern void initStripScene(void); extern void initDropScene(void); extern void initLemScene(void); extern void initExplodeScene(void); extern void initWinScene(void); extern void initTexScene(void); extern void delStripScene(void); extern void delDropScene(void); extern void delLemScene(void); extern void delExplodeScene(void); extern void delWinScene(void); extern void delTexScene(void);
typedef void (*PTRUPDATE)(int); typedef void (*ptrdel)(); typedef void (*ptrinit)();
// Each screen saver style puts its hook functions into the function
// arrays below. A consistent ordering of the functions is required.
static PTRUPDATE updateFuncs[] = {updateWinScene, updateExplodeScene,updateStripScene, updateStripScene, updateDropScene, updateLemScene, updateTexScene}; static ptrdel delFuncs[] = {delWinScene, delExplodeScene, delStripScene, delStripScene, delDropScene, delLemScene, delTexScene}; static ptrinit initFuncs[] = {initWinScene, initExplodeScene, initStripScene, initStripScene, initDropScene, initLemScene, initTexScene}; static int idsStyles[] = {IDS_LOGO, IDS_EXPLODE, IDS_RIBBON, IDS_2RIBBON, IDS_SPLASH, IDS_TWIST, IDS_FLAG};
#define MAX_TYPE ( sizeof(initFuncs) / sizeof(ptrinit) - 1 )
// Each screen saver style can choose which dialog box controls it wants
// to use. These flags enable each of the controls. Controls not choosen
// will be disabled.
#define OPT_COLOR_CYCLE 0x00000001
#define OPT_SMOOTH_SHADE 0x00000002
#define OPT_TESSEL 0x00000008
#define OPT_SIZE 0x00000010
#define OPT_TEXTURE 0x00000020
#define OPT_STD ( OPT_COLOR_CYCLE | OPT_SMOOTH_SHADE | OPT_TESSEL | OPT_SIZE )
static ULONG gflConfigOpt[] = { OPT_STD, // Windows logo
OPT_STD, // Explode
OPT_STD, // Strip
OPT_STD, // Strip
OPT_STD, // Drop
OPT_STD, // Twist (lemniscate)
OPT_SMOOTH_SHADE | OPT_TESSEL | OPT_SIZE | OPT_TEXTURE // Texture mapped flag
};
static void updateDialogControls(HWND hDlg);
#ifdef MEMDEBUG
void xprintf(char *str, ...) { va_list ap; char buffer[256];
va_start(ap, str); vsprintf(buffer, str, ap);
OutputDebugString(buffer); va_end(ap); } #endif
void *SaverAlloc(ULONG size) { void *mPtr;
mPtr = malloc(size); #ifdef MEMDEBUG
totalMem += size; xprintf("malloc'd %x, size %d\n", mPtr, size); #endif
return mPtr; }
void SaverFree(void *pMem) { #ifdef MEMDEBUG
totalMem -= _msize(pMem); xprintf("free %x, size = %d, total = %d\n", pMem, _msize(pMem), totalMem); #endif
free(pMem); }
/******************************Public*Routine******************************\
* getIniSettings * * Get the screen saver configuration options from .INI file/registry. * * History: * 10-May-1994 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
static void getIniSettings() { int options; int optMask = 1; TCHAR szDefaultBitmap[MAX_PATH]; int tessel=0; LPTSTR psz;
LoadString(hMainInstance, IDS_GENNAME, szScreenSaver, sizeof(szScreenSaver) / sizeof(TCHAR));
if( ss_RegistrySetup( hMainInstance, IDS_SAVERNAME, IDS_INIFILE ) ) { options = ss_GetRegistryInt( IDS_OPTIONS, -1 ); if (options >= 0) { bSmoothShading = ((options & optMask) != 0); optMask <<= 1; bColorCycle = ((options & optMask) != 0); UpdateFlags = (bColorCycle << 1); }
Type = ss_GetRegistryInt( IDS_OBJTYPE, 0 );
// Sanity check Type. Don't want to index into function arrays
// with a bad index!
Type = min(Type, MAX_TYPE);
// Set flag so that updateStripScene will do two strips instead
// of one.
if (Type == 3) UpdateFlags |= 0x4;
tessel = ss_GetRegistryInt( IDS_TESSELATION, 100 ); SS_CLAMP_TO_RANGE2( tessel, 0, 200 );
if (tessel <= 100) fTesselFact = (float)tessel / 100.0f; else fTesselFact = 1.0f + (((float)tessel - 100.0f) / 100.0f);
uSize = ss_GetRegistryInt( IDS_SIZE, 50 ); if (uSize > 100) uSize = 100; // SS_CLAMP_TO_RANGE2( uSize, 0, 100 ); /* can't be less than zero since it is a UINT */
// Determine the default .bmp file
ss_GetDefaultBmpFile( szDefaultBitmap );
// Is there a texture specified in the registry that overrides the
// default?
ss_GetRegistryString( IDS_TEXTURE, szDefaultBitmap, gTexFile.szPathName, MAX_PATH);
gTexFile.nOffset = ss_GetRegistryInt( IDS_TEXTURE_FILE_OFFSET, 0 ); } }
/******************************Public*Routine******************************\
* saveIniSettings * * Save the screen saver configuration option to the .INI file/registry. * * History: * 10-May-1994 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
static void saveIniSettings(HWND hDlg) { if( ss_RegistrySetup( hMainInstance, IDS_SAVERNAME, IDS_INIFILE ) ) { int pos, options; int optMask = 1;
bSmoothShading = IsDlgButtonChecked(hDlg, DLG_SETUP_SMOOTH); bColorCycle = IsDlgButtonChecked(hDlg, DLG_SETUP_CYCLE); options = bColorCycle; options <<= 1; options |= bSmoothShading; ss_WriteRegistryInt( IDS_OPTIONS, options );
Type = (int)SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_GETCURSEL, 0, 0); ss_WriteRegistryInt( IDS_OBJTYPE, Type );
pos = ss_GetTrackbarPos( hDlg, DLG_SETUP_TESSEL ); ss_WriteRegistryInt( IDS_TESSELATION, pos );
pos = ss_GetTrackbarPos( hDlg, DLG_SETUP_SIZE ); ss_WriteRegistryInt( IDS_SIZE, pos );
ss_WriteRegistryString( IDS_TEXTURE, gTexFile.szPathName ); ss_WriteRegistryInt( IDS_TEXTURE_FILE_OFFSET, gTexFile.nOffset ); } }
/******************************Public*Routine******************************\
* setupDialogControls * * Setup the dialog controls initially. * \**************************************************************************/
static void setupDialogControls(HWND hDlg) { int pos;
InitCommonControls();
if ( gflConfigOpt[Type] & OPT_TESSEL ) { if (fTesselFact <= 1.0f) pos = (int)(fTesselFact * 100.0f); else pos = 100 + (int) ((fTesselFact - 1.0f) * 100.0f);
ss_SetupTrackbar( hDlg, DLG_SETUP_TESSEL, 0, 200, 1, 10, pos ); }
if ( gflConfigOpt[Type] & OPT_SIZE ) { ss_SetupTrackbar( hDlg, DLG_SETUP_SIZE, 0, 100, 1, 10, uSize ); }
updateDialogControls( hDlg ); }
/******************************Public*Routine******************************\
* updateDialogControls * * Update the dialog controls based on the current global state. * \**************************************************************************/
static void updateDialogControls(HWND hDlg) { CheckDlgButton(hDlg, DLG_SETUP_SMOOTH, bSmoothShading); CheckDlgButton(hDlg, DLG_SETUP_CYCLE, bColorCycle);
EnableWindow(GetDlgItem(hDlg, DLG_SETUP_SMOOTH), gflConfigOpt[Type] & OPT_SMOOTH_SHADE ); EnableWindow(GetDlgItem(hDlg, DLG_SETUP_CYCLE), gflConfigOpt[Type] & OPT_COLOR_CYCLE );
EnableWindow(GetDlgItem(hDlg, DLG_SETUP_TESSEL), gflConfigOpt[Type] & OPT_TESSEL); EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TESS), gflConfigOpt[Type] & OPT_TESSEL); EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TESS_MIN), gflConfigOpt[Type] & OPT_TESSEL); EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TESS_MAX), gflConfigOpt[Type] & OPT_TESSEL);
EnableWindow(GetDlgItem(hDlg, DLG_SETUP_SIZE), gflConfigOpt[Type] & OPT_SIZE); EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SIZE), gflConfigOpt[Type] & OPT_SIZE); EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SIZE_MIN), gflConfigOpt[Type] & OPT_SIZE); EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SIZE_MAX), gflConfigOpt[Type] & OPT_SIZE);
EnableWindow(GetDlgItem(hDlg, DLG_SETUP_TEXTURE), gflConfigOpt[Type] & OPT_TEXTURE); }
BOOL WINAPI RegisterDialogClasses(HANDLE hinst) { return TRUE; }
/******************************Public*Routine******************************\
* ScreenSaverConfigureDialog * * Processes messages for the configuration dialog box. * \**************************************************************************/
BOOL ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { int wTmp; TCHAR szString[GEN_STRING_SIZE];
switch (message) { case WM_INITDIALOG: getIniSettings();
setupDialogControls(hDlg);
for (wTmp = 0; wTmp <= MAX_TYPE; wTmp++) { LoadString(hMainInstance, idsStyles[wTmp], szString, GEN_STRING_SIZE); SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_ADDSTRING, 0, (LPARAM) szString); } SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_SETCURSEL, Type, 0);
return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) { case DLG_SETUP_TYPES: switch (HIWORD(wParam)) { case CBN_EDITCHANGE: case CBN_SELCHANGE: Type = (int)SendDlgItemMessage(hDlg, DLG_SETUP_TYPES, CB_GETCURSEL, 0, 0); updateDialogControls(hDlg); break; default: break; } return FALSE;
case DLG_SETUP_TEXTURE: ss_SelectTextureFile( hDlg, &gTexFile ); break;
case IDOK: saveIniSettings(hDlg); EndDialog(hDlg, TRUE); break;
case IDCANCEL: EndDialog(hDlg, FALSE); break;
case DLG_SETUP_SMOOTH: case DLG_SETUP_CYCLE: default: break; } return TRUE; break;
default: return 0; } return 0; }
/******************************Public*Routine******************************\
* SetFloaterInfo * * Set the size and motion of the floating window * It stays square in shape * \**************************************************************************/
static void SetFloaterInfo( ISIZE *pParentSize, CHILD_INFO *pChild ) { float sizeFact; float sizeScale; int size; ISIZE *pChildSize = &pChild->size; MOTION_INFO *pMotion = &pChild->motionInfo;
sizeScale = (float)uSize / 100.0f; // 0..1
sizeFact = 0.25f + (0.30f * sizeScale); size = (int) (sizeFact * ( ((float)(pParentSize->width + pParentSize->height)) / 2.0f )); SS_CLAMP_TO_RANGE2( size, 0, pParentSize->width ); SS_CLAMP_TO_RANGE2( size, 0, pParentSize->height );
pChildSize->width = pChildSize->height = size;
// Floater motion
pMotion->posInc.x = .01f * (float) size; if( pMotion->posInc.x < 1.0f ) pMotion->posInc.x = 1.0f; pMotion->posInc.y = pMotion->posInc.x; pMotion->posIncVary.x = .4f * pMotion->posInc.x; pMotion->posIncVary.y = pMotion->posIncVary.x; }
/******************************Public*Routine******************************\
* initMaterial * * Initialize the material properties. * \**************************************************************************/
void initMaterial(int id, float r, float g, float b, float a) { Material[id].ka.r = r; Material[id].ka.g = g; Material[id].ka.b = b; Material[id].ka.a = a;
Material[id].kd.r = r; Material[id].kd.g = g; Material[id].kd.b = b; Material[id].kd.a = a;
Material[id].ks.r = 1.0f; Material[id].ks.g = 1.0f; Material[id].ks.b = 1.0f; Material[id].ks.a = 1.0f;
Material[id].specExp = 128.0f; }
/******************************Public*Routine******************************\
* _3dfo_Init * \**************************************************************************/
static void _3dfo_Init(void *data) { int i;
for (i = 0; i < 7; i++) initMaterial(i, matlColors[i].r, matlColors[i].g, matlColors[i].b, matlColors[i].a);
// Set the OpenGL clear color to black.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); #ifdef SS_DEBUG
glClearColor(0.2f, 0.2f, 0.2f, 0.0f); #endif
// Enable the z-buffer.
glEnable(GL_DEPTH_TEST);
// Select the shading model.
if (bSmoothShading) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT);
// Setup the OpenGL matrices.
glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity();
// Setup the lighting.
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (GLfloat *) &lightAmbient); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); glLightfv(GL_LIGHT0, GL_AMBIENT, (GLfloat *) &light0Ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, (GLfloat *) &light0Diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, (GLfloat *) &light0Specular); glLightfv(GL_LIGHT0, GL_POSITION, light0Pos); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);
// Setup the material properties.
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat *) &Material[0].ks); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, (GLfloat *) &Material[0].specExp);
// call specific objects init func
(*initFuncs[Type])(); updateSceneFunc = updateFuncs[Type]; }
/******************************Public*Routine******************************\
* _3dfo_Draw * \**************************************************************************/
static void _3dfo_Draw(void *data) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); (*updateSceneFunc)(UpdateFlags); }
/******************************Public*Routine******************************\
* _3dfo_FloaterBounce * \**************************************************************************/
static void _3dfo_FloaterBounce(void *data) { gbBounce = TRUE; }
/******************************Public*Routine******************************\
* ss_Init * * Screen saver entry point. Pre-GL initialization * \**************************************************************************/
SSContext * ss_Init(void) { getIniSettings();
// Make sure the selected texture file is OK.
if ( gflConfigOpt[Type] & OPT_TEXTURE ) { // Verify texture file
ss_DisableTextureErrorMsgs(); ss_VerifyTextureFile( &gTexFile ); }
// set callbacks
ss_InitFunc( _3dfo_Init ); ss_UpdateFunc( _3dfo_Draw );
// set configuration info to return
gssc.bDoubleBuf = TRUE; gssc.depthType = SS_DEPTH16;
gssc.bFloater = TRUE; gssc.floaterInfo.bMotion = TRUE; gssc.floaterInfo.ChildSizeFunc = SetFloaterInfo; ss_FloaterBounceFunc( _3dfo_FloaterBounce );
return &gssc; }
/**************************************************************************\
* ConfigInit * * Dialog box version of ss_Init. Used for setting up any gl drawing on the * dialog. * \**************************************************************************/ BOOL ss_ConfigInit( HWND hDlg ) { return TRUE; }
|