|
|
/**********************************Module**********************************\
* * ssflwbox.c * * 3D FlowerBox screen saver * * History: * Wed Jul 19 14:50:27 1995 -by- Drew Bliss [drewb] * Created * * Copyright (c) 1995 Microsoft Corporation * \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
// Minimum and maximum image sizes
#define MINIMAGESIZE 10
#define MAXIMAGESIZE 100
// Color tables for checkboard, per-side and single color modes
GLfloat base_checker_cols[MAXSIDES][NCCOLS][4] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }; GLfloat checker_cols[MAXSIDES][NCCOLS][4];
GLfloat base_side_cols[MAXSIDES][4] = { 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, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f }; GLfloat side_cols[MAXSIDES][4];
GLfloat base_solid_cols[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat solid_cols[4];
// Current geometry
GEOMETRY *cur_geom;
// Set when a rendering context is available
BOOL gbGlInit = FALSE;
// Common library context
SSContext gssc;
// Spin rotations
double xr = 0, yr = 0, zr = 0; // Scale factor and increment
FLT sf; FLT sfi; // Color cycling hue phase
FLT phase = 0.0f;
// Default configuration
CONFIG config = { TRUE, FALSE, FALSE, TRUE, TRUE, MAXSUBDIV, ID_COL_PER_SIDE, (MAXIMAGESIZE+MINIMAGESIZE)/2, GEOM_CUBE, GL_FRONT };
// A slider range
typedef struct _RANGE { int min_val; int max_val; int step; int page_step; } RANGE;
RANGE complexity_range = {MINSUBDIV, MAXSUBDIV, 1, 2}; RANGE image_size_range = {MINIMAGESIZE, MAXIMAGESIZE, 1, 10};
// True if the current OpenGL version is 1.1
BOOL bOgl11;
// True if checkered mode is on
BOOL bCheckerOn;
/******************************Public*Routine******************************\
* * dprintf * * Debug output printf * * History: * Wed Jul 26 15:16:11 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
#if DBG
void dprintf_out(char *fmt, ...) { va_list args; char dbg[256];
va_start(args, fmt); vsprintf(dbg, fmt, args); va_end(args); OutputDebugStringA(dbg); } #endif
/******************************Public*Routine******************************\
* * assert_failed * * Assertion failure handler * * History: * Fri Jul 28 17:40:28 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
#if DBG
void assert_failed(char *file, int line, char *msg) { dprintf(("Assertion failed %s(%d): %s\n", file, line, msg)); DebugBreak(); } #endif
/******************************Public*Routine******************************\
* * V3Len * * Vector length * * History: * Wed Jul 19 14:52:21 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
FLT V3Len(PT3 *v) { return (FLT)sqrt(v->x*v->x+v->y*v->y+v->z*v->z); }
/******************************Public*Routine******************************\
* * ComputeHsvColors * * Compute a smooth range of colors depending on the current color mode * * History: * Wed Jul 19 14:53:32 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void ComputeHsvColors(void) { GLfloat *cols; int ncols; FLT ang, da; int hex; FLT fhex, frac; FLT p, q, t; FLT sat, val;
switch(config.color_pick) { case ID_COL_CHECKER: ncols = MAXSIDES*NCCOLS; cols = &checker_cols[0][0][0]; break; case ID_COL_PER_SIDE: ncols = MAXSIDES; cols = &side_cols[0][0]; break; case ID_COL_SINGLE: ncols = 1; cols = &solid_cols[0]; break; }
ang = phase; da = (FLT)((2*PI)/ncols); val = sat = 1.0f;
while (ncols > 0) { fhex = (FLT)(6*ang/(2*PI)); hex = (int)fhex; frac = fhex-hex; hex = hex % 6; p = val*(1-sat); q = val*(1-sat*frac); t = val*(1-sat*(1-frac)); switch(hex) { case 0: cols[0] = val; cols[1] = t; cols[2] = p; break; case 1: cols[0] = q; cols[1] = val; cols[2] = p; break; case 2: cols[0] = p; cols[1] = val; cols[2] = t; break; case 3: cols[0] = p; cols[1] = q; cols[2] = val; break; case 4: cols[0] = t; cols[1] = p; cols[2] = val; break; case 5: cols[0] = val; cols[1] = p; cols[2] = q; break; }
ang += da; cols += 4; ncols--; } }
/******************************Public*Routine******************************\
* * Draw * * Draw everything * * History: * Wed Jul 19 14:54:16 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void Draw(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotated(xr, 1, 0, 0); glRotated(yr, 0, 1, 0); glRotated(zr, 0, 0, 1);
DrawGeom(cur_geom);
glFlush(); }
/******************************Public*Routine******************************\
* * Update * * Update all varying values, called by the common library * * History: * Wed Jul 19 14:54:24 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void Update(void *data) { if (config.spin) { xr += 3; yr += 2; }
if (config.bloom) { sf += sfi; if (sf > cur_geom->max_sf || sf < cur_geom->min_sf) { sfi = -sfi; } UpdatePts(cur_geom, sf); }
if (config.cycle_colors) { ComputeHsvColors(); phase += (FLT)(2.5*PI/180.); } Draw(); }
// String storage
TCHAR geom_names[IDS_GEOM_COUNT][20];
/******************************Public*Routine******************************\
* getIniSettings * * Get the screen saver configuration options from .INI file/registry. * \**************************************************************************/
static void getIniSettings() { // Get registry settings
if( ! ss_RegistrySetup( GetModuleHandle(NULL), IDS_INI_SECTION, IDS_INIFILE ) ) return; config.smooth_colors = ss_GetRegistryInt( IDS_CONFIG_SMOOTH_COLORS, config.smooth_colors ); config.triangle_colors = ss_GetRegistryInt( IDS_CONFIG_TRIANGLE_COLORS, config.triangle_colors ); config.cycle_colors = ss_GetRegistryInt( IDS_CONFIG_CYCLE_COLORS, config.cycle_colors ); config.spin = ss_GetRegistryInt( IDS_CONFIG_SPIN, config.spin ); config.bloom = ss_GetRegistryInt( IDS_CONFIG_BLOOM, config.bloom ); config.subdiv = ss_GetRegistryInt( IDS_CONFIG_SUBDIV, config.subdiv ); config.color_pick = ss_GetRegistryInt( IDS_CONFIG_COLOR_PICK, config.color_pick ); config.image_size = ss_GetRegistryInt( IDS_CONFIG_IMAGE_SIZE, config.image_size ); config.geom = ss_GetRegistryInt( IDS_CONFIG_GEOM, config.geom ); config.two_sided = ss_GetRegistryInt( IDS_CONFIG_TWO_SIDED, config.two_sided ); }
/******************************Public*Routine******************************\
* saveIniSettings * * Save the screen saver configuration option to the .INI file/registry. * \**************************************************************************/
static void saveIniSettings() { if( ! ss_RegistrySetup( GetModuleHandle(NULL), IDS_INI_SECTION, IDS_INIFILE ) ) return;
ss_WriteRegistryInt( IDS_CONFIG_SMOOTH_COLORS, config.smooth_colors );
ss_WriteRegistryInt( IDS_CONFIG_TRIANGLE_COLORS, config.triangle_colors ); ss_WriteRegistryInt( IDS_CONFIG_CYCLE_COLORS, config.cycle_colors ); ss_WriteRegistryInt( IDS_CONFIG_SPIN, config.spin ); ss_WriteRegistryInt( IDS_CONFIG_BLOOM, config.bloom ); ss_WriteRegistryInt( IDS_CONFIG_SUBDIV, config.subdiv ); ss_WriteRegistryInt( IDS_CONFIG_COLOR_PICK, config.color_pick ); ss_WriteRegistryInt( IDS_CONFIG_IMAGE_SIZE, config.image_size ); ss_WriteRegistryInt( IDS_CONFIG_GEOM, config.geom ); ss_WriteRegistryInt( IDS_CONFIG_TWO_SIDED, config.two_sided ); }
/******************************Public*Routine******************************\
* * NewConfig * * Set up a new configuration * * History: * Wed Jul 19 14:55:34 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void NewConfig(CONFIG *cnf) { // Set new config
config = *cnf;
// Save to ini file
saveIniSettings(); // Reset colors
memcpy(checker_cols, base_checker_cols, sizeof(checker_cols)); memcpy(side_cols, base_side_cols, sizeof(side_cols)); memcpy(solid_cols, base_solid_cols, sizeof(solid_cols));
// Reset geometry
cur_geom = geom_table[config.geom]; cur_geom->init(cur_geom); if (bOgl11 && !bCheckerOn) DrawWithVArrays (cur_geom); assert(cur_geom->total_pts <= MAXPTS); InitVlen(cur_geom, cur_geom->total_pts, cur_geom->pts); sf = 0.0f; sfi = cur_geom->sf_inc; UpdatePts(cur_geom, sf);
// Reset OpenGL parameters according to configuration
// Only done if GL has been initialized
if (gbGlInit) { GLfloat fv4[4]; if (config.two_sided == GL_FRONT_AND_BACK) { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glDisable(GL_CULL_FACE); } else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); glEnable(GL_CULL_FACE); } fv4[0] = fv4[1] = fv4[2] = .8f; fv4[3] = 1.0f; glMaterialfv(config.two_sided, GL_SPECULAR, fv4); glMaterialf(config.two_sided, GL_SHININESS, 30.0f); } }
/******************************Public*Routine******************************\
* * RegisterDialogClasses * * Standard screensaver hook * * History: * Wed Jul 19 15:18:14 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL WINAPI RegisterDialogClasses(HANDLE hinst) { return TRUE; }
// Temporary configuration for when the configuration dialog is active
// If the dialog is ok'ed then this becomes the current configuration,
// otherwise it is discarded
CONFIG temp_config;
/******************************Public*Routine******************************\
* * ScreenSaverConfigureDialog * * Standard screensaver hook * * History: * Wed Jul 19 14:56:41 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL CALLBACK ScreenSaverConfigureDialog(HWND hdlg, UINT msg, WPARAM wpm, LPARAM lpm) { WORD pos; RANGE *rng; HWND hCtrl; int i; switch(msg) { case WM_INITDIALOG:
InitCommonControls();
getIniSettings(); temp_config = config; CheckRadioButton(hdlg, ID_COL_PICK_FIRST, ID_COL_PICK_LAST, config.color_pick); CheckDlgButton(hdlg, ID_COL_SMOOTH, config.smooth_colors); CheckDlgButton(hdlg, ID_COL_TRIANGLE, config.triangle_colors); CheckDlgButton(hdlg, ID_COL_CYCLE, config.cycle_colors); CheckDlgButton(hdlg, ID_SPIN, config.spin); CheckDlgButton(hdlg, ID_BLOOM, config.bloom); CheckDlgButton(hdlg, ID_TWO_SIDED, config.two_sided == GL_FRONT_AND_BACK); ss_SetupTrackbar( hdlg, ID_COMPLEXITY, MINSUBDIV, MAXSUBDIV, complexity_range.step, complexity_range.page_step, config.subdiv);
ss_SetupTrackbar( hdlg, ID_IMAGE_SIZE, MINIMAGESIZE, MAXIMAGESIZE, image_size_range.step, image_size_range.page_step, config.image_size);
hCtrl = GetDlgItem(hdlg, ID_GEOM); SendMessage(hCtrl, CB_RESETCONTENT, 0, 0); for (i = 0; i < IDS_GEOM_COUNT; i++) { LoadString( hMainInstance, i+IDS_GEOM_FIRST, geom_names[i], sizeof(geom_names)/IDS_GEOM_COUNT ); SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)geom_names[i]); } SendMessage(hCtrl, CB_SETCURSEL, config.geom, 0); SetFocus(GetDlgItem(hdlg, ID_COMPLEXITY)); return FALSE;
case WM_COMMAND: switch(LOWORD(wpm)) { case ID_COL_CHECKER: case ID_COL_PER_SIDE: case ID_COL_SINGLE: temp_config.color_pick = LOWORD(wpm); break;
case ID_COL_SMOOTH: temp_config.smooth_colors = !temp_config.smooth_colors; break; case ID_COL_TRIANGLE: temp_config.triangle_colors = !temp_config.triangle_colors; break; case ID_COL_CYCLE: temp_config.cycle_colors = !temp_config.cycle_colors; break; case ID_SPIN: temp_config.spin = !temp_config.spin; break; case ID_BLOOM: temp_config.bloom = !temp_config.bloom; break; case ID_TWO_SIDED: temp_config.two_sided = temp_config.two_sided == GL_FRONT_AND_BACK ? GL_FRONT : GL_FRONT_AND_BACK; break;
case IDOK: temp_config.subdiv = ss_GetTrackbarPos(hdlg, ID_COMPLEXITY); temp_config.image_size = ss_GetTrackbarPos(hdlg, ID_IMAGE_SIZE); temp_config.geom = (int)SendMessage(GetDlgItem(hdlg, ID_GEOM), CB_GETCURSEL, 0, 0); NewConfig(&temp_config); // Fall through
case IDCANCEL: EndDialog(hdlg, LOWORD(wpm)); break; } return TRUE; }
return FALSE; }
/******************************Public*Routine******************************\
* * Init * * Drawing initialization, called by common library * * History: * Wed Jul 19 14:47:13 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
void Init(void *data) { GLfloat fv4[4];
gbGlInit = TRUE; bOgl11 = ss_fOnGL11();
if (config.color_pick == ID_COL_CHECKER) bCheckerOn = TRUE; else bCheckerOn = FALSE;
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, 1, 2, 5); // for object range -1.5 to 1.5
gluLookAt(0, 0, 3.5, 0, 0, 0, 0, 1, 0); glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST); glClearDepth(1);
glCullFace(GL_BACK); fv4[0] = 2.0f; fv4[1] = 2.0f; fv4[2] = 10.0f; fv4[3] = 1.0f; glLightfv(GL_LIGHT0, GL_POSITION, fv4); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE); // Make default configuration current
NewConfig(&config); }
/******************************Public*Routine******************************\
* SetFloaterInfo * * Set the size and motion of the floating window * * History * Apr. 28, 95 : [marcfo] * - Wrote it * \**************************************************************************/
void SetFloaterInfo( ISIZE *pParentSize, CHILD_INFO *pChild ) { float sizeFact; float sizeScale; int size; ISIZE *pChildSize = &pChild->size; MOTION_INFO *pMotion = &pChild->motionInfo;
sizeScale = (float)config.image_size / 100.0f; sizeFact = 0.25f + (0.5f * sizeScale); // range 25-75%
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 = .005f * (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******************************\
* * FloaterFail * * Called when the floating window cannot be created * * History: * Wed Jul 19 15:06:18 1995 -by- Drew Bliss [drewb] * Taken from text3d * \**************************************************************************/
void FloaterFail(void *data) { HINSTANCE hinst; TCHAR error_str[20]; TCHAR start_failed[80];
hinst = GetModuleHandle(NULL); if (LoadString(hinst, IDS_ERROR, error_str, sizeof(error_str)) && LoadString(hinst, IDS_START_FAILED, start_failed, sizeof(start_failed))) { MessageBox(NULL, start_failed, error_str, MB_OK); } }
/******************************Public*Routine******************************\
* * ss_Init * * Screensaver initialization routine, called at startup by common library * * History: * Wed Jul 19 14:44:46 1995 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
SSContext *ss_Init(void) { getIniSettings(); ss_InitFunc(Init); ss_UpdateFunc(Update);
gssc.bFloater = TRUE; gssc.floaterInfo.bMotion = TRUE; gssc.floaterInfo.ChildSizeFunc = SetFloaterInfo;
gssc.bDoubleBuf = TRUE; gssc.depthType = SS_DEPTH16;
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; }
|