Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

658 lines
20 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: Pipes.cpp
  3. //
  4. // Desc: Fun screen saver.
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #include "stdafx.h"
  9. //-----------------------------------------------------------------------------
  10. // Name: struct MYVERTEX
  11. // Desc: D3D vertex type for this app
  12. //-----------------------------------------------------------------------------
  13. struct MYVERTEX
  14. {
  15. D3DXVECTOR3 p; // Position
  16. FLOAT tu; // Vertex texture coordinates
  17. FLOAT tv;
  18. MYVERTEX(D3DXVECTOR3 pInit, FLOAT tuInit, FLOAT tvInit)
  19. { p = pInit; tu = tuInit; tv = tvInit; }
  20. };
  21. #define D3DFVF_MYVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
  22. #define BUF_SIZE 255
  23. TCHAR g_szSectName[BUF_SIZE];
  24. TCHAR g_szFname[BUF_SIZE];
  25. CPipesScreensaver* g_pMyPipesScreensaver = NULL;
  26. //-----------------------------------------------------------------------------
  27. // Name: WinMain()
  28. // Desc: Entry point to the program. Initializes everything, and goes into a
  29. // message-processing loop. Idle time is used to render the scene.
  30. //-----------------------------------------------------------------------------
  31. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  32. {
  33. HRESULT hr;
  34. CPipesScreensaver pipesScreensaverSS;
  35. if( FAILED( hr = pipesScreensaverSS.Create( hInst ) ) )
  36. {
  37. pipesScreensaverSS.DisplayErrorMsg( hr );
  38. return 0;
  39. }
  40. return pipesScreensaverSS.Run();
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Name: CPipesScreensaver()
  44. // Desc: Constructor
  45. //-----------------------------------------------------------------------------
  46. CPipesScreensaver::CPipesScreensaver( )
  47. {
  48. g_pMyPipesScreensaver = this;
  49. InitCommonControls();
  50. for( int i=0; i<MAX_DEVICE_OBJECTS; i++ )
  51. {
  52. m_DeviceObjects[i].m_pState = NULL;
  53. }
  54. LoadString( NULL, IDS_DESCRIPTION, m_strWindowTitle, 200 );
  55. m_bUseDepthBuffer = TRUE;
  56. m_SwapEffectFullscreen = D3DSWAPEFFECT_COPY;
  57. m_SwapEffectWindowed = D3DSWAPEFFECT_COPY_VSYNC;
  58. m_pDeviceObjects = NULL;
  59. lstrcpy( m_strRegPath, TEXT("Software\\Microsoft\\ScreenSavers\\Pipes") );
  60. m_Config.bMultiPipes = FALSE;
  61. m_Config.nJointType = JOINT_ELBOW;
  62. m_Config.bTextured = FALSE;
  63. m_Config.bDefaultTexture = TRUE;
  64. lstrcpy( m_Config.strTextureName[0], TEXT("") );
  65. m_Config.bFlexMode = FALSE;
  66. m_Config.dwTesselFact = 0;
  67. m_Config.dwSpeed = 16;
  68. m_iRenderUnit = 0;
  69. RandInit();
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Name: SetDevice()
  73. // Desc:
  74. //-----------------------------------------------------------------------------
  75. VOID CPipesScreensaver::SetDevice( UINT iDevice )
  76. {
  77. m_pDeviceObjects = &m_DeviceObjects[iDevice];
  78. m_iRenderUnit = iDevice;
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Name: RegisterSoftwareDevice()
  82. // Desc: This can register the D3D8RGBRasterizer or any other
  83. // pluggable software rasterizer.
  84. //-----------------------------------------------------------------------------
  85. HRESULT CPipesScreensaver::RegisterSoftwareDevice()
  86. {
  87. m_pD3D->RegisterSoftwareDevice( D3D8RGBRasterizer );
  88. return S_OK;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Name: FrameMove()
  92. // Desc: Called once per frame, the call is the entry point for animating
  93. // the scene.
  94. //-----------------------------------------------------------------------------
  95. HRESULT CPipesScreensaver::FrameMove()
  96. {
  97. m_pDeviceObjects->m_pState->FrameMove( m_fElapsedTime );
  98. return S_OK;
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Name: DoPaint()
  102. // Desc:
  103. //-----------------------------------------------------------------------------
  104. VOID CPipesScreensaver::DoPaint(HWND hwnd, HDC hdc)
  105. {
  106. CD3DScreensaver::DoPaint( hwnd, hdc );
  107. for( int iDevice=0; iDevice<MAX_DEVICE_OBJECTS; iDevice++ )
  108. {
  109. if( m_DeviceObjects[iDevice].m_pState )
  110. m_DeviceObjects[iDevice].m_pState->Repaint();
  111. }
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Name: Render()
  115. // Desc: Called once per frame, the call is the entry point for 3d
  116. // rendering. This function sets up render states, clears the
  117. // viewport, and renders the scene.
  118. //-----------------------------------------------------------------------------
  119. HRESULT CPipesScreensaver::Render()
  120. {
  121. BOOL bRenderNewPiece = FALSE;
  122. if( m_Config.dwSpeed == 20 )
  123. {
  124. bRenderNewPiece = TRUE;
  125. }
  126. else
  127. {
  128. FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
  129. if( fCurTime - m_pDeviceObjects->m_pState->m_fLastTime >
  130. (20-m_Config.dwSpeed) * 0.005 )
  131. {
  132. bRenderNewPiece = TRUE;
  133. m_pDeviceObjects->m_pState->m_fLastTime = fCurTime;
  134. }
  135. }
  136. if( bRenderNewPiece )
  137. {
  138. // Begin the scene
  139. if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  140. {
  141. m_pDeviceObjects->m_pState->Render();
  142. // End the scene.
  143. m_pd3dDevice->EndScene();
  144. }
  145. }
  146. else
  147. {
  148. if( m_iRenderUnit == 0 )
  149. {
  150. // Wait for a little while so we don't draw the pipes too fast
  151. Sleep(10);
  152. }
  153. }
  154. return S_OK;
  155. }
  156. //-----------------------------------------------------------------------------
  157. // Name: RestoreDeviceObjects()
  158. // Desc:
  159. //-----------------------------------------------------------------------------
  160. HRESULT CPipesScreensaver::RestoreDeviceObjects()
  161. {
  162. if( m_pd3dDevice == NULL )
  163. return S_OK;
  164. m_pDeviceObjects->m_pState = new STATE( &m_Config );
  165. m_pDeviceObjects->m_pState->InitDeviceObjects( m_pd3dDevice );
  166. m_pDeviceObjects->m_pState->RestoreDeviceObjects();
  167. m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  168. 0x00000000, 1.0f, 0L );
  169. return S_OK;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Name: InvalidateDeviceObjects()
  173. // Desc:
  174. //-----------------------------------------------------------------------------
  175. HRESULT CPipesScreensaver::InvalidateDeviceObjects()
  176. {
  177. m_pDeviceObjects->m_pState->InvalidateDeviceObjects();
  178. m_pDeviceObjects->m_pState->DeleteDeviceObjects();
  179. SAFE_DELETE( m_pDeviceObjects->m_pState );
  180. return S_OK;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Name: ConfigureDialogProcHelper()
  184. // Desc:
  185. //-----------------------------------------------------------------------------
  186. INT_PTR CALLBACK ConfigureDialogProcHelper( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  187. {
  188. return g_pMyPipesScreensaver->ConfigureDialogProc( hwndDlg, uMsg, wParam, lParam );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Name: DoConfig()
  192. // Desc:
  193. //-----------------------------------------------------------------------------
  194. VOID CPipesScreensaver::DoConfig()
  195. {
  196. DialogBox( NULL, MAKEINTRESOURCE(IDD_CONFIGURE), m_hWndParent, ConfigureDialogProcHelper );
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Name: ConfigureDialogProc()
  200. // Desc:
  201. //-----------------------------------------------------------------------------
  202. INT_PTR CALLBACK CPipesScreensaver::ConfigureDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  203. {
  204. static CONFIG s_TempConfig;
  205. switch (uMsg)
  206. {
  207. case WM_INITDIALOG:
  208. {
  209. ReadSettings();
  210. s_TempConfig = m_Config;
  211. lstrcpy( s_TempConfig.strTextureName[0], m_Config.strTextureName[0] );
  212. if( s_TempConfig.bMultiPipes )
  213. CheckRadioButton(hwndDlg, IDC_RADIO_SINGLE_PIPE, IDC_RADIO_MULTIPLE_PIPES,
  214. IDC_RADIO_MULTIPLE_PIPES);
  215. else
  216. CheckRadioButton(hwndDlg, IDC_RADIO_SINGLE_PIPE, IDC_RADIO_MULTIPLE_PIPES,
  217. IDC_RADIO_SINGLE_PIPE);
  218. HWND hCtrl = GetDlgItem(hwndDlg, DLG_COMBO_JOINTTYPE);
  219. SendMessage(hCtrl, CB_RESETCONTENT, 0, 0);
  220. TCHAR strJointNames[IDS_JOINT_COUNT][MAX_PATH];
  221. for (int i = 0; i < IDS_JOINT_COUNT; i++)
  222. {
  223. LoadString( NULL, i+IDS_JOINT_FIRST, strJointNames[i],
  224. sizeof(strJointNames)/IDS_JOINT_COUNT );
  225. SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)strJointNames[i]);
  226. }
  227. SendMessage(hCtrl, CB_SETCURSEL, s_TempConfig.nJointType, 0);
  228. if( !s_TempConfig.bTextured )
  229. {
  230. CheckRadioButton(hwndDlg, IDC_RADIO_SOLID, IDC_RADIO_TEX,
  231. IDC_RADIO_SOLID);
  232. EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), FALSE );
  233. }
  234. else
  235. {
  236. CheckRadioButton(hwndDlg, IDC_RADIO_SOLID, IDC_RADIO_TEX,
  237. IDC_RADIO_TEX);
  238. EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), TRUE );
  239. }
  240. SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 20 ) );
  241. SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) m_Config.dwSpeed );
  242. SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETPAGESIZE, (WPARAM) 0, (LPARAM) 5 );
  243. SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETLINESIZE, (WPARAM) 0, (LPARAM) 1 );
  244. return TRUE;
  245. }
  246. case WM_COMMAND:
  247. {
  248. switch( LOWORD( wParam ) )
  249. {
  250. case IDC_RADIO_TEX:
  251. EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), TRUE );
  252. break;
  253. case IDC_RADIO_SOLID:
  254. EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), FALSE );
  255. break;
  256. case DLG_SETUP_TEXTURE:
  257. {
  258. if( SelectTextureFile( hwndDlg, s_TempConfig.strTextureName[0] ) )
  259. {
  260. CheckRadioButton(hwndDlg, IDC_RADIO_SOLID, IDC_RADIO_TEX,
  261. IDC_RADIO_TEX);
  262. s_TempConfig.bDefaultTexture = FALSE;
  263. }
  264. else
  265. {
  266. s_TempConfig.bDefaultTexture = TRUE;
  267. }
  268. break;
  269. }
  270. case IDC_SCREENSETTINGS:
  271. {
  272. DoScreenSettingsDialog( hwndDlg );
  273. break;
  274. }
  275. case IDOK:
  276. {
  277. s_TempConfig.bMultiPipes = IsDlgButtonChecked(hwndDlg, IDC_RADIO_MULTIPLE_PIPES);
  278. HWND hCtrl = GetDlgItem(hwndDlg, DLG_COMBO_JOINTTYPE);
  279. s_TempConfig.nJointType = (DWORD) SendMessage(hCtrl, CB_GETCURSEL, 0, 0);
  280. s_TempConfig.bTextured = IsDlgButtonChecked(hwndDlg, IDC_RADIO_TEX);
  281. s_TempConfig.dwSpeed = (DWORD) SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_GETPOS, 0, 0 );
  282. m_Config = s_TempConfig;
  283. lstrcpy( m_Config.strTextureName[0], s_TempConfig.strTextureName[0] );
  284. WriteSettings();
  285. EndDialog(hwndDlg, IDOK);
  286. break;
  287. }
  288. case IDCANCEL:
  289. {
  290. EndDialog(hwndDlg, IDCANCEL);
  291. break;
  292. }
  293. }
  294. return TRUE;
  295. }
  296. }
  297. return FALSE;
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Name: SelectTextureFile()
  301. // Desc:
  302. //-----------------------------------------------------------------------------
  303. BOOL CPipesScreensaver::SelectTextureFile( HWND hDlg, TCHAR* origPathName )
  304. {
  305. TCHAR fn[MAX_PATH] = TEXT("\0");
  306. TCHAR szDialogTitle[MAX_PATH];
  307. TCHAR szTextureFilter[MAX_PATH];
  308. TCHAR szTitle[MAX_PATH];
  309. LoadString(NULL, IDS_TEXTUREFILTER, szTextureFilter, MAX_PATH);
  310. // Filter strings are weird because they contain nulls.
  311. // The string loaded from a resource has # where nulls
  312. // should be inserted.
  313. for( TCHAR* pch = szTextureFilter; *pch != TEXT('\0'); pch++ )
  314. {
  315. if (*pch == TEXT('#'))
  316. *pch = TEXT('\0');
  317. }
  318. LoadString(NULL, IDS_TEXTUREDIALOGTITLE, szDialogTitle, MAX_PATH);
  319. LoadString(NULL, IDS_TITLE, szTitle, MAX_PATH);
  320. TCHAR szWindowsDir[MAX_PATH];
  321. szWindowsDir[0] = TEXT('\0');
  322. GetWindowsDirectory( szWindowsDir, MAX_PATH );
  323. OPENFILENAME ofn;
  324. memset( &ofn, 0, sizeof(ofn) );
  325. ofn.lStructSize = sizeof(ofn);
  326. ofn.hwndOwner = hDlg;
  327. ofn.hInstance = m_hInstance;
  328. ofn.lpstrFilter = szTextureFilter;
  329. ofn.nFilterIndex = 1;
  330. ofn.lpstrFile = origPathName;
  331. ofn.nMaxFile = sizeof(fn);
  332. ofn.lpstrTitle = szDialogTitle;
  333. ofn.Flags = OFN_ENABLESIZING|OFN_FILEMUSTEXIST;
  334. ofn.lpstrDefExt = TEXT("BMP");
  335. if( lstrlen( origPathName ) == 0 )
  336. ofn.lpstrInitialDir = szWindowsDir;
  337. if( GetOpenFileName( &ofn ) )
  338. {
  339. lstrcpy( origPathName, ofn.lpstrFile );
  340. return TRUE;
  341. }
  342. else
  343. {
  344. return FALSE;
  345. }
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Name: ReadSettings()
  349. // Desc:
  350. //-----------------------------------------------------------------------------
  351. VOID CPipesScreensaver::ReadSettings()
  352. {
  353. HKEY hkey;
  354. // Read OpenGL settings first, so OS upgrade cases work
  355. ss_ReadSettings();
  356. if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath,
  357. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
  358. {
  359. ReadScreenSettings( hkey );
  360. // DXUtil_ReadBoolRegKey( hkey, TEXT("Flex Mode"), &m_Config.bFlexMode, m_Config.bFlexMode );
  361. DXUtil_ReadBoolRegKey( hkey, TEXT("MultiPipes"), &m_Config.bMultiPipes, m_Config.bMultiPipes );
  362. DXUtil_ReadBoolRegKey( hkey, TEXT("Textured"), &m_Config.bTextured, m_Config.bTextured );
  363. DXUtil_ReadBoolRegKey( hkey, TEXT("Default Texture"), &m_Config.bDefaultTexture, m_Config.bDefaultTexture );
  364. DXUtil_ReadIntRegKey( hkey, TEXT("Tessel Factor"), &m_Config.dwTesselFact, m_Config.dwTesselFact );
  365. if( m_Config.dwTesselFact >= 4 )
  366. m_Config.dwTesselFact = 4;
  367. DXUtil_ReadIntRegKey( hkey, TEXT("Joint Type"), &m_Config.nJointType, m_Config.nJointType );
  368. if( m_Config.nJointType >= NUM_JOINTTYPES )
  369. m_Config.nJointType = JOINT_ELBOW;
  370. DXUtil_ReadIntRegKey( hkey, TEXT("Speed"), &m_Config.dwSpeed, m_Config.dwSpeed );
  371. DXUtil_ReadStringRegKey( hkey, TEXT("Texture Name"), m_Config.strTextureName[0], MAX_PATH, m_Config.strTextureName[0] );
  372. RegCloseKey( hkey );
  373. }
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Name: ss_ReadSettings()
  377. // Desc:
  378. //-----------------------------------------------------------------------------
  379. VOID CPipesScreensaver::ss_ReadSettings()
  380. {
  381. // Get registry settings
  382. if( ss_RegistrySetup( IDS_SAVERNAME, IDS_INIFILE ) )
  383. {
  384. m_Config.nJointType = ss_GetRegistryInt( IDS_JOINTTYPE, 0 );
  385. m_Config.bTextured = (ss_GetRegistryInt( IDS_SURFSTYLE, 0 ) == 1);
  386. if( m_Config.bTextured )
  387. m_Config.bDefaultTexture = TRUE;
  388. m_Config.bMultiPipes = ss_GetRegistryInt( IDS_MULTIPIPES, 0 );
  389. ss_GetRegistryString( IDS_TEXTURE, 0, m_Config.strTextureName[0], MAX_PATH);
  390. if( lstrlen(m_Config.strTextureName[0]) > 0 )
  391. m_Config.bDefaultTexture = FALSE;
  392. }
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Name: ss_GetRegistryString()
  396. // Desc:
  397. //-----------------------------------------------------------------------------
  398. BOOL CPipesScreensaver::ss_RegistrySetup( int section, int file )
  399. {
  400. if( LoadString(m_hInstance, section, g_szSectName, BUF_SIZE) &&
  401. LoadString(m_hInstance, file, g_szFname, BUF_SIZE) )
  402. {
  403. TCHAR pBuffer[100];
  404. DWORD dwRealSize = GetPrivateProfileSection( g_szSectName, pBuffer, 100, g_szFname );
  405. if( dwRealSize > 0 )
  406. return TRUE;
  407. }
  408. return FALSE;
  409. }
  410. //-----------------------------------------------------------------------------
  411. // Name: ss_GetRegistryString()
  412. // Desc:
  413. //-----------------------------------------------------------------------------
  414. int CPipesScreensaver::ss_GetRegistryInt( int name, int iDefault )
  415. {
  416. TCHAR szItemName[BUF_SIZE];
  417. if( LoadString( m_hInstance, name, szItemName, BUF_SIZE ) )
  418. return GetPrivateProfileInt(g_szSectName, szItemName, iDefault, g_szFname);
  419. return 0;
  420. }
  421. //-----------------------------------------------------------------------------
  422. // Name: ss_GetRegistryString()
  423. // Desc:
  424. //-----------------------------------------------------------------------------
  425. VOID CPipesScreensaver::ss_GetRegistryString( int name, LPTSTR lpDefault,
  426. LPTSTR lpDest, int bufSize )
  427. {
  428. TCHAR szItemName[BUF_SIZE];
  429. if( LoadString( m_hInstance, name, szItemName, BUF_SIZE ) )
  430. GetPrivateProfileString(g_szSectName, szItemName, lpDefault, lpDest,
  431. bufSize, g_szFname);
  432. return;
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Name: WriteSettings()
  436. // Desc:
  437. //-----------------------------------------------------------------------------
  438. VOID CPipesScreensaver::WriteSettings()
  439. {
  440. HKEY hkey;
  441. DWORD dwType = REG_DWORD;
  442. DWORD dwLength = sizeof(DWORD);
  443. if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath,
  444. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
  445. {
  446. WriteScreenSettings( hkey );
  447. // DXUtil_WriteBoolRegKey( hkey, TEXT("Flex Mode"), m_Config.bFlexMode );
  448. DXUtil_WriteBoolRegKey( hkey, TEXT("MultiPipes"), m_Config.bMultiPipes );
  449. DXUtil_WriteBoolRegKey( hkey, TEXT("Textured"), m_Config.bTextured );
  450. DXUtil_WriteBoolRegKey( hkey, TEXT("Default Texture"), m_Config.bDefaultTexture );
  451. DXUtil_WriteIntRegKey( hkey, TEXT("Tessel Factor"), m_Config.dwTesselFact );
  452. DXUtil_WriteIntRegKey( hkey, TEXT("Joint Type"), m_Config.nJointType );
  453. DXUtil_WriteStringRegKey( hkey, TEXT("Texture Name"), m_Config.strTextureName[0] );
  454. DXUtil_WriteIntRegKey( hkey, TEXT("Speed"), m_Config.dwSpeed );
  455. RegCloseKey( hkey );
  456. }
  457. }
  458. //-----------------------------------------------------------------------------
  459. // Name: iRand()
  460. // Desc: Generates integer random number 0..(max-1)
  461. //-----------------------------------------------------------------------------
  462. int CPipesScreensaver::iRand( int max )
  463. {
  464. return (int) ( max * ( ((float)rand()) / ((float)(RAND_MAX+1)) ) );
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Name: iRand2()
  468. // Desc: Generates integer random number min..max
  469. //-----------------------------------------------------------------------------
  470. int CPipesScreensaver::iRand2( int min, int max )
  471. {
  472. if( min == max )
  473. {
  474. return min;
  475. }
  476. else if( max < min )
  477. {
  478. int temp = min;
  479. min = max;
  480. max = temp;
  481. }
  482. return min + (int) ( (max-min+1) * ( ((float)rand()) / ((float)(RAND_MAX+1)) ) );
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Name: fRand()
  486. // Desc: Generates float random number min...max
  487. //-----------------------------------------------------------------------------
  488. FLOAT CPipesScreensaver::fRand( FLOAT min, FLOAT max )
  489. {
  490. FLOAT diff;
  491. diff = max - min;
  492. return min + ( diff * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
  493. }
  494. //-----------------------------------------------------------------------------
  495. // Name: RandInit()
  496. // Desc: Initializes the randomizer
  497. //-----------------------------------------------------------------------------
  498. VOID CPipesScreensaver::RandInit()
  499. {
  500. struct _timeb time;
  501. _ftime( &time );
  502. srand( time.millitm );
  503. for( int i = 0; i < 10; i ++ )
  504. rand();
  505. }