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.

481 lines
15 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: genwin2.c
  3. *
  4. * The new Windows style of the 3D Flying Objects screen saver.
  5. *
  6. * Texture maps .BMP files onto a simulation of a flag waving in the breeze.
  7. *
  8. * Copyright (c) 2001 Microsoft Corporation
  9. *
  10. \**************************************************************************/
  11. #include <stdlib.h>
  12. #include <windows.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #include <d3dx8.h>
  16. #include "D3DSaver.h"
  17. #include "FlyingObjects.h"
  18. #include "resource.h"
  19. #include "mesh.h"
  20. enum STATE
  21. {
  22. S_FREE,
  23. S_MOVETOORIGIN,
  24. S_FADETOCOLOR,
  25. S_PAUSE,
  26. S_FADEFROMCOLOR
  27. };
  28. #define TIME_FREE 10.0f
  29. #define TIME_FADETOCOLOR 1.0f
  30. #define TIME_PAUSE 5.0f
  31. #define TIME_FADEFROMCOLOR 1.0f
  32. // Note: There's no TIME_MOVETOORIGIN since that takes a variable amt of time.
  33. const FLOAT winTotalwidth = (FLOAT)0.75;
  34. const FLOAT winTotalheight = (FLOAT)0.75;
  35. #define MAX_FRAMES 20
  36. // IPREC is the number of faces in the mesh that models the flag.
  37. #define IPREC 35
  38. static int Frames = 10;
  39. static MESH winMesh[MAX_FRAMES];
  40. static FLOAT sinAngle = (FLOAT)0.0;
  41. static FLOAT xTrans = (FLOAT)0.0;
  42. // Material properties
  43. static RGBA matlBrightSpecular = {1.0f, 1.0f, 1.0f, 1.0f};
  44. // Lighting properties
  45. static FLOAT light0Pos[] = {-15.0f, 0.0f, -10.0f};
  46. /******************************Public*Routine******************************\
  47. * iPtInList
  48. *
  49. * Add a vertex and its normal to the mesh. If the vertex already exists,
  50. * add in the normal to the existing normal (we to accumulate the average
  51. * normal at each vertex). Normalization of the normals is the
  52. * responsibility of the caller.
  53. *
  54. \**************************************************************************/
  55. static int iPtInList(MESH *mesh, int start,
  56. POINT3D *p, POINT3D *norm, BOOL blend)
  57. {
  58. int i;
  59. POINT3D *pts = mesh->pts + start;
  60. if (blend) {
  61. for (i = start; i < mesh->numPoints; i++, pts++) {
  62. if ((pts->x == p->x) && (pts->y == p->y) && (pts->z == p->z)) {
  63. mesh->norms[i].x += norm->x;
  64. mesh->norms[i].y += norm->y;
  65. mesh->norms[i].z += norm->z;
  66. return i;
  67. }
  68. }
  69. } else {
  70. i = mesh->numPoints;
  71. }
  72. mesh->pts[i] = *p;
  73. mesh->norms[i] = *norm;
  74. mesh->numPoints++;
  75. return i;
  76. }
  77. /******************************Public*Routine******************************\
  78. * getZpos
  79. *
  80. * Get the z-position (depth) of the "wavy" flag component at the given x.
  81. *
  82. * The function used to model the wave is:
  83. *
  84. * 1/2
  85. * z = x * sin((2*PI*x + sinAngle) / 8)
  86. *
  87. * The shape of the wave varies from frame to frame by changing the
  88. * phase, sinAngle.
  89. *
  90. \**************************************************************************/
  91. static FLOAT getZpos(FLOAT x)
  92. {
  93. FLOAT xAbs = x - xTrans;
  94. FLOAT angle = sinAngle + ((FLOAT) (2.0 * PI) * (xAbs / winTotalwidth));
  95. xAbs = winTotalwidth - xAbs;
  96. return (FLOAT)(-(sin((double)angle) / 8.0) *
  97. sqrt((double)(xAbs / winTotalwidth )));
  98. }
  99. /******************************Public*Routine******************************\
  100. * genTex
  101. *
  102. * Generate a mesh representing a frame of the flag. The phase, sinAngle,
  103. * is a global variable.
  104. *
  105. \**************************************************************************/
  106. static BOOL genTex(MESH *winMesh)
  107. {
  108. POINT3D pos;
  109. POINT3D pts[4];
  110. FLOAT w, h;
  111. int i;
  112. if( !newMesh(winMesh, IPREC * IPREC, IPREC * IPREC) )
  113. return FALSE;
  114. // Width and height of each face
  115. w = (winTotalwidth) / (FLOAT)(IPREC + 1);
  116. h = winTotalheight;
  117. // Generate the mesh data. At equally spaced intervals along the x-axis,
  118. // we compute the z-position of the flag surface.
  119. pos.y = (FLOAT) 0.0;
  120. pos.z = (FLOAT) 0.0;
  121. for (i = 0, pos.x = xTrans; i < IPREC; i++, pos.x += w) {
  122. int faceCount = winMesh->numFaces;
  123. pts[0].x = (FLOAT)pos.x;
  124. pts[0].y = (FLOAT)(pos.y);
  125. pts[0].z = getZpos(pos.x);
  126. pts[1].x = (FLOAT)pos.x;
  127. pts[1].y = (FLOAT)(pos.y + h);
  128. pts[1].z = getZpos(pos.x);
  129. pts[2].x = (FLOAT)(pos.x + w);
  130. pts[2].y = (FLOAT)(pos.y);
  131. pts[2].z = getZpos(pos.x + w);
  132. pts[3].x = (FLOAT)(pos.x + w);
  133. pts[3].y = (FLOAT)(pos.y + h);
  134. pts[3].z = getZpos(pos.x + w);
  135. // Compute the face normal.
  136. ss_calcNorm(&winMesh->faces[faceCount].norm, pts + 2, pts + 1, pts);
  137. // Add the face to the mesh.
  138. winMesh->faces[faceCount].material = 0;
  139. winMesh->faces[faceCount].p[0] = iPtInList(winMesh, 0, pts,
  140. &winMesh->faces[faceCount].norm, TRUE);
  141. winMesh->faces[faceCount].p[1] = iPtInList(winMesh, 0, pts + 1,
  142. &winMesh->faces[faceCount].norm, TRUE);
  143. winMesh->faces[faceCount].p[2] = iPtInList(winMesh, 0, pts + 2,
  144. &winMesh->faces[faceCount].norm, TRUE);
  145. winMesh->faces[faceCount].p[3] = iPtInList(winMesh, 0, pts + 3,
  146. &winMesh->faces[faceCount].norm, TRUE);
  147. winMesh->numFaces++;
  148. }
  149. // Normalize the vertex normals in the mesh.
  150. ss_normalizeNorms(winMesh->norms, winMesh->numPoints);
  151. return TRUE;
  152. }
  153. /******************************Public*Routine******************************\
  154. * initWin2Scene
  155. *
  156. * Initialize the screen saver.
  157. *
  158. * This function is exported to the main module in ss3dfo.c.
  159. *
  160. \**************************************************************************/
  161. BOOL initWin2Scene()
  162. {
  163. int i;
  164. FLOAT angleDelta;
  165. SetProjectionMatrixInfo( TRUE, 2.0f, 2.0f, 0.0f, 3.0f );
  166. D3DXMATRIX matView;
  167. D3DXMatrixTranslation(&matView, -0.17f, -0.04f, 1.5f);
  168. m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  169. // Adjust position of light 0
  170. D3DLIGHT8 light;
  171. m_pd3dDevice->GetLight(0, &light);
  172. light.Position.x = light0Pos[0];
  173. light.Position.y = light0Pos[1];
  174. light.Position.z = light0Pos[2];
  175. m_pd3dDevice->SetLight(0, &light);
  176. m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  177. m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
  178. m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  179. m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  180. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  181. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  182. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  183. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  184. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  185. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
  186. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
  187. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  188. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  189. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
  190. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
  191. Frames = MAX_FRAMES;
  192. // Generate the geometry data (stored in the array of mesh structures),
  193. // for each frame of the animation. The shape of the flag is varied by
  194. // changing the global variable sinAngle.
  195. angleDelta = (FLOAT)(2.0 * PI) / (FLOAT)Frames;
  196. sinAngle = (FLOAT) 0.0;
  197. for (i = 0; i < Frames; i++) {
  198. if( !genTex(&winMesh[i]) )
  199. return FALSE;
  200. sinAngle += angleDelta;
  201. }
  202. return TRUE;
  203. }
  204. /******************************Public*Routine******************************\
  205. * delWin2Scene
  206. *
  207. * Cleanup the data associated with this screen saver.
  208. *
  209. * This function is exported to the main module in ss3dfo.c.
  210. *
  211. \**************************************************************************/
  212. void delWin2Scene()
  213. {
  214. int i;
  215. for (i = 0; i < Frames; i++)
  216. delMesh(&winMesh[i]);
  217. }
  218. /******************************Public*Routine******************************\
  219. * updateWin2Scene
  220. *
  221. * Generate a scene by taking one of the meshes and rendering it
  222. *
  223. * This function is exported to the main module in ss3dfo.c.
  224. *
  225. \**************************************************************************/
  226. void updateWin2Scene(int flags, FLOAT fElapsedTime)
  227. {
  228. MESH *pMesh;
  229. static double mxrot = 40.0;
  230. static double myrot = 0;
  231. static double mzrot = -12.0;
  232. static int frameNum = 0;
  233. static FLOAT fFrameNum = (FLOAT)Frames;
  234. FLOAT s = 0.0f;
  235. FLOAT ds;
  236. static FLOAT s_fTime = 0.0f;
  237. static FLOAT s_fTimeLastChange = 0.0f;
  238. static FLOAT s_fTimeNextChange = TIME_FREE;
  239. static STATE s_state = S_FREE;
  240. FLOAT fBeta;
  241. if( fElapsedTime > 0.25f )
  242. fElapsedTime = 0.25f;
  243. FLOAT fTimeFactor = fElapsedTime * 20.0f;
  244. HRESULT hr;
  245. s_fTime += fElapsedTime;
  246. if( s_fTimeNextChange != -1.0f && s_fTime > s_fTimeNextChange )
  247. {
  248. // Handle state transitions
  249. s_fTimeLastChange = s_fTime;
  250. switch( s_state )
  251. {
  252. case S_FREE:
  253. s_state = S_MOVETOORIGIN;
  254. g_bMoveToOrigin = TRUE;
  255. s_fTimeNextChange = -1.0f;
  256. break;
  257. case S_MOVETOORIGIN:
  258. s_state = S_FADETOCOLOR;
  259. s_fTimeNextChange = s_fTime + TIME_FADETOCOLOR;
  260. break;
  261. case S_FADETOCOLOR:
  262. s_state = S_PAUSE;
  263. s_fTimeNextChange = s_fTime + TIME_PAUSE;
  264. break;
  265. case S_PAUSE:
  266. s_state = S_FADEFROMCOLOR;
  267. s_fTimeNextChange = s_fTime + TIME_FADEFROMCOLOR;
  268. break;
  269. case S_FADEFROMCOLOR:
  270. s_state = S_FREE;
  271. s_fTimeNextChange = s_fTime + TIME_FREE;
  272. g_bMoveToOrigin = FALSE;
  273. break;
  274. }
  275. }
  276. fBeta = 0.0f;
  277. // Handle state processing
  278. switch( s_state )
  279. {
  280. case S_MOVETOORIGIN:
  281. if( g_bAtOrigin && frameNum == 0)
  282. s_fTimeNextChange = s_fTime; // provoke state change next time
  283. break;
  284. case S_FADETOCOLOR:
  285. fBeta = (s_fTime - s_fTimeLastChange) / TIME_FADETOCOLOR;
  286. break;
  287. case S_PAUSE:
  288. fBeta = 1.0f;
  289. break;
  290. case S_FADEFROMCOLOR:
  291. fBeta = 1.0f - ( (s_fTime - s_fTimeLastChange) / TIME_FADEFROMCOLOR );
  292. break;
  293. }
  294. if( fBeta != 0.0f )
  295. {
  296. // Render background logo
  297. MYVERTEX3 v[4];
  298. FLOAT fLeft = g_pFloatRect->xMin - g_xScreenOrigin;
  299. FLOAT fRight = fLeft + g_pFloatRect->xSize;
  300. FLOAT fBottom = g_pFloatRect->yMin - g_yScreenOrigin;
  301. FLOAT fTop = g_pFloatRect->yMin + g_pFloatRect->ySize;
  302. DWORD dwColor = D3DXCOLOR( 1.0f, 1.0f, 1.0f, fBeta );
  303. v[0].p = D3DXVECTOR3(fLeft, fBottom, 0.9f); v[0].rhw = 0.1f; v[0].dwDiffuse = dwColor; v[0].tu = 0.0f; v[0].tv = 0.0f;
  304. v[1].p = D3DXVECTOR3(fRight, fBottom, 0.9f); v[1].rhw = 0.1f; v[1].dwDiffuse = dwColor; v[1].tu = 1.0f; v[1].tv = 0.0f;
  305. v[2].p = D3DXVECTOR3(fLeft, fTop, 0.9f); v[2].rhw = 0.1f; v[2].dwDiffuse = dwColor; v[2].tu = 0.0f; v[2].tv = 1.0f;
  306. v[3].p = D3DXVECTOR3(fRight, fTop, 0.9f); v[3].rhw = 0.1f; v[3].dwDiffuse = dwColor; v[3].tu = 1.0f; v[3].tv = 1.0f;
  307. hr = m_pd3dDevice->SetTexture( 0, g_pDeviceObjects->m_pTexture2 );
  308. hr = m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX3 );
  309. hr = m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, v, sizeof(MYVERTEX3) );
  310. }
  311. m_pd3dDevice->SetTexture( 0, g_pDeviceObjects->m_pTexture );
  312. D3DXMATRIX mat1, mat2, mat3, mat4, matFinal;
  313. D3DXMatrixRotationX(&mat1, D3DXToRadian((FLOAT)mxrot));
  314. D3DXMatrixRotationY(&mat2, D3DXToRadian((FLOAT)myrot));
  315. D3DXMatrixRotationZ(&mat3, D3DXToRadian((FLOAT)mzrot));
  316. D3DXMatrixScaling( &mat4, 0.82f, 0.92f, 0.82f );
  317. matFinal = mat4 * mat3 * mat2 * mat1 ;
  318. m_pd3dDevice->SetTransform( D3DTS_WORLD, &matFinal );
  319. // Divide the texture into IPREC slices. ds is the texture coordinate
  320. // delta we apply as we move along the x-axis.
  321. ds = (FLOAT)1.0 / (FLOAT)IPREC;
  322. // Setup the material property of the flag. The material property, light
  323. // properties, and polygon orientation will interact with the texture.
  324. myglMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (FLOAT *) &matlBrightSpecular);
  325. myglMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, (FLOAT) 40.0);
  326. FLOAT fColor[4];
  327. fColor[0] = 1.0f;
  328. fColor[1] = 1.0f;
  329. fColor[2] = 1.0f;
  330. fColor[3] = 1.0f - fBeta; // Adjust flag alpha so it fades when showing logo
  331. if( fColor[3] != 0.0f )
  332. {
  333. // Render flag
  334. myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fColor);
  335. pMesh = &winMesh[frameNum];
  336. INT numPrims = 0;
  337. INT numIndices = 0;
  338. INT numVertices = 0;
  339. WORD iVertexA, iVertexB, iVertexC, iVertexD;
  340. INT a,b,c,d;
  341. MFACE *faces;
  342. WORD* i;
  343. MYVERTEX2* v;
  344. hr = m_pVB2->Lock( 0, 0, (BYTE**)&v, 0 );
  345. hr = m_pIB->Lock( 0, MAX_INDICES, (BYTE**)&i, 0 );
  346. faces = pMesh->faces;
  347. for( int iFace = 0; iFace < pMesh->numFaces; iFace++ )
  348. {
  349. a = faces[iFace].p[0];
  350. b = faces[iFace].p[1];
  351. c = faces[iFace].p[2];
  352. d = faces[iFace].p[3];
  353. v[numVertices].p = pMesh->pts[a];
  354. v[numVertices].n = bSmoothShading ? -pMesh->norms[a] : -faces[iFace].norm;
  355. v[numVertices].tu = s; v[numVertices].tv = 1.0f;
  356. iVertexA = numVertices++;
  357. v[numVertices].p = pMesh->pts[b];
  358. v[numVertices].n = bSmoothShading ? -pMesh->norms[b] : -faces[iFace].norm;
  359. v[numVertices].tu = s; v[numVertices].tv = 0.0f;
  360. iVertexB = numVertices++;
  361. v[numVertices].p = pMesh->pts[c];
  362. v[numVertices].n = bSmoothShading ? -pMesh->norms[c] : -faces[iFace].norm;
  363. v[numVertices].tu = s+ds; v[numVertices].tv = 1.0f;
  364. iVertexC = numVertices++;
  365. v[numVertices].p = pMesh->pts[d];
  366. v[numVertices].n = bSmoothShading ? -pMesh->norms[d] : -faces[iFace].norm;
  367. v[numVertices].tu = s+ds; v[numVertices].tv = 0.0f;
  368. iVertexD = numVertices++;
  369. s += ds;
  370. i[numIndices++] = iVertexA;
  371. i[numIndices++] = iVertexB;
  372. i[numIndices++] = iVertexC;
  373. numPrims++;
  374. i[numIndices++] = iVertexC;
  375. i[numIndices++] = iVertexB;
  376. i[numIndices++] = iVertexD;
  377. numPrims++;
  378. }
  379. hr = m_pVB2->Unlock();
  380. hr = m_pIB->Unlock();
  381. hr = m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX2 );
  382. hr = m_pd3dDevice->SetStreamSource( 0, m_pVB2, sizeof(MYVERTEX2) );
  383. hr = m_pd3dDevice->SetIndices( m_pIB, 0 );
  384. hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, numVertices,
  385. 0, numPrims );
  386. }
  387. // Don't change frame number if we're in S_FADETOCOLOR, S_PAUSE,
  388. // or S_FADEFROMCOLOR, unless by some chance we're in those states
  389. // but framenum is not at zero (yet).
  390. if( frameNum != 0 ||
  391. s_state != S_FADETOCOLOR &&
  392. s_state != S_PAUSE &&
  393. s_state != S_FADEFROMCOLOR )
  394. {
  395. fFrameNum -= fTimeFactor;
  396. frameNum = (INT)fFrameNum;
  397. if (frameNum < 0)
  398. {
  399. fFrameNum = (FLOAT)(Frames - 1);
  400. frameNum = Frames - 1;
  401. }
  402. }
  403. }