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.

608 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: gentex.c
  3. *
  4. * The Textured Flag 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) 1994 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. static FLOAT winTotalwidth = (FLOAT)0.75;
  21. static FLOAT winTotalheight = (FLOAT)0.75 * (FLOAT)0.75;
  22. #define MAX_FRAMES 20
  23. // IPREC is the number of faces in the mesh that models the flag.
  24. #define IPREC 15
  25. static int Frames = 10;
  26. static MESH winMesh[MAX_FRAMES];
  27. static FLOAT sinAngle = (FLOAT)0.0;
  28. static FLOAT xTrans = (FLOAT)0.0;
  29. static int curMatl = 0;
  30. // Material properties.
  31. static RGBA matlBrightSpecular = {1.0f, 1.0f, 1.0f, 1.0f};
  32. static RGBA matlDimSpecular = {0.5f, 0.5f, 0.5f, 1.0f};
  33. static RGBA matlNoSpecular = {0.0f, 0.0f, 0.0f, 0.0f};
  34. // Lighting properties.
  35. static FLOAT light0Pos[] = {20.0f, 5.0f, 20.0f, 0.0f};
  36. static FLOAT light1Pos[] = {-20.0f, 5.0f, 0.0f, 0.0f};
  37. static RGBA light1Ambient = {0.0f, 0.0f, 0.0f, 0.0f};
  38. static RGBA light1Diffuse = {0.4f, 0.4f, 0.4f, 1.0f};
  39. static RGBA light1Specular = {0.0f, 0.0f, 0.0f, 0.0f};
  40. static RGBA flagColors[] = {{1.0f, 1.0f, 1.0f, 1.0f},
  41. {0.94f, 0.37f, 0.13f, 1.0f}, // red
  42. };
  43. // Default texture resource
  44. static TEX_RES gTexRes = { TEX_BMP, IDB_DEFTEX };
  45. static TEXTURE gTex = {0}; // One global texture
  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) / 4)
  86. *
  87. * The shape of the wave varies from frame to frame by changing the
  88. * phase, sinAngle.
  89. *
  90. \**************************************************************************/
  91. 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. // xAbs += (winTotalwidth / 2.0);
  97. return (FLOAT)((sin((double)angle) / 4.0) *
  98. sqrt((double)(xAbs / winTotalwidth )));
  99. }
  100. /******************************Public*Routine******************************\
  101. * genTex
  102. *
  103. * Generate a mesh representing a frame of the flag. The phase, sinAngle,
  104. * is a global variable.
  105. *
  106. \**************************************************************************/
  107. BOOL genTex(MESH *winMesh)
  108. {
  109. POINT3D pos;
  110. POINT3D pts[4];
  111. FLOAT w, h;
  112. int i;
  113. if( !newMesh(winMesh, IPREC * IPREC, IPREC * IPREC) )
  114. return FALSE;
  115. // Width and height of each face
  116. w = (winTotalwidth) / (FLOAT)(IPREC + 1);
  117. h = winTotalheight;
  118. // Generate the mesh data. At equally spaced intervals along the x-axis,
  119. // we compute the z-position of the flag surface.
  120. pos.y = (FLOAT) 0.0;
  121. pos.z = (FLOAT) 0.0;
  122. for (i = 0, pos.x = xTrans; i < IPREC; i++, pos.x += w) {
  123. int faceCount = winMesh->numFaces;
  124. pts[0].x = (FLOAT)pos.x;
  125. pts[0].y = (FLOAT)(pos.y);
  126. pts[0].z = getZpos(pos.x);
  127. pts[1].x = (FLOAT)pos.x;
  128. pts[1].y = (FLOAT)(pos.y + h);
  129. pts[1].z = getZpos(pos.x);
  130. pts[2].x = (FLOAT)(pos.x + w);
  131. pts[2].y = (FLOAT)(pos.y);
  132. pts[2].z = getZpos(pos.x + w);
  133. pts[3].x = (FLOAT)(pos.x + w);
  134. pts[3].y = (FLOAT)(pos.y + h);
  135. pts[3].z = getZpos(pos.x + w);
  136. // Compute the face normal.
  137. ss_calcNorm(&winMesh->faces[faceCount].norm, pts + 2, pts + 1, pts);
  138. // Add the face to the mesh.
  139. winMesh->faces[faceCount].material = 0;
  140. winMesh->faces[faceCount].p[0] = iPtInList(winMesh, 0, pts,
  141. &winMesh->faces[faceCount].norm, TRUE);
  142. winMesh->faces[faceCount].p[1] = iPtInList(winMesh, 0, pts + 1,
  143. &winMesh->faces[faceCount].norm, TRUE);
  144. winMesh->faces[faceCount].p[2] = iPtInList(winMesh, 0, pts + 2,
  145. &winMesh->faces[faceCount].norm, TRUE);
  146. winMesh->faces[faceCount].p[3] = iPtInList(winMesh, 0, pts + 3,
  147. &winMesh->faces[faceCount].norm, TRUE);
  148. winMesh->numFaces++;
  149. }
  150. // Normalize the vertex normals in the mesh.
  151. ss_normalizeNorms(winMesh->norms, winMesh->numPoints);
  152. return TRUE;
  153. }
  154. /******************************Public*Routine******************************\
  155. * initTexScene
  156. *
  157. * Initialize the screen saver.
  158. *
  159. * This function is exported to the main module in ss3dfo.c.
  160. *
  161. \**************************************************************************/
  162. BOOL initTexScene()
  163. {
  164. int i;
  165. FLOAT angleDelta;
  166. // FLOAT aspectRatio;
  167. // Initialize the transform.
  168. /*
  169. glMatrixMode(GL_PROJECTION);
  170. glLoadIdentity();
  171. glOrtho(-0.25, 1.0, -0.25, 1.0, 0.0, 3.0);
  172. glTranslatef(0.0f, 0.0f, -1.5f);
  173. */
  174. SetProjectionMatrixInfo( TRUE, 2.0f, 2.0f, 0.0f, 3.0f );
  175. D3DXMATRIX matView;
  176. D3DXMatrixTranslation(&matView, 0.0f, 0.0f, 1.5f);
  177. m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  178. // Initialize and turn on lighting.
  179. /*
  180. glDisable(GL_DEPTH_TEST);
  181. */
  182. // Light 0
  183. D3DLIGHT8 light;
  184. m_pd3dDevice->GetLight(0, &light);
  185. light.Position.x = light0Pos[0];
  186. light.Position.y = light0Pos[1];
  187. light.Position.z = light0Pos[2];
  188. m_pd3dDevice->SetLight(0, &light);
  189. // Light 1
  190. light.Type = D3DLIGHT_POINT;
  191. light.Ambient.r = light1Ambient.r;
  192. light.Ambient.g = light1Ambient.g;
  193. light.Ambient.b = light1Ambient.b;
  194. light.Ambient.a = light1Ambient.a;
  195. light.Diffuse.r = light1Diffuse.r;
  196. light.Diffuse.g = light1Diffuse.g;
  197. light.Diffuse.b = light1Diffuse.b;
  198. light.Diffuse.a = light1Diffuse.a;
  199. light.Specular.r = light1Specular.r;
  200. light.Specular.g = light1Specular.g;
  201. light.Specular.b = light1Specular.b;
  202. light.Specular.a = light1Specular.a;
  203. light.Position.x = light1Pos[0];
  204. light.Position.y = light1Pos[1];
  205. light.Position.z = light1Pos[2];
  206. m_pd3dDevice->SetLight(1, &light);
  207. m_pd3dDevice->LightEnable(1, TRUE);
  208. // Leave OpenGL in a state ready to accept the model view transform (we
  209. // are going to have the flag vary its orientation from frame to frame).
  210. /*
  211. glMatrixMode(GL_MODELVIEW);
  212. */
  213. // Define orientation of polygon faces.
  214. // glFrontFace(GL_CW);
  215. // glEnable(GL_CULL_FACE);
  216. m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  217. m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLORARG1 , D3DTA_TEXTURE );
  218. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
  219. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  220. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  221. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
  222. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
  223. Frames = (int)((FLOAT)(MAX_FRAMES / 2) * fTesselFact);
  224. // Load user texture - if that fails load default texture resource
  225. #if 0
  226. // glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  227. if( ss_LoadTextureFile( &gTexFile, &gTex ) ||
  228. ss_LoadTextureResource( &gTexRes, &gTex) )
  229. {
  230. /* glEnable(GL_TEXTURE_2D);
  231. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  232. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  233. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  234. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  235. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  236. */
  237. ss_SetTexture( &gTex );
  238. // Correct aspect ratio of flag to match image.
  239. //
  240. // The 1.4 is a correction factor to account for the length of the
  241. // curve that models the surface ripple of the waving flag. This
  242. // factor is the length of the curve at zero phase. It would be
  243. // more accurate to determine the length of the curve at each phase,
  244. // but this is a sufficient approximation for our purposes.
  245. aspectRatio = ((FLOAT) gTex.height / (FLOAT) gTex.width)
  246. * (FLOAT) 1.4;
  247. if (aspectRatio < (FLOAT) 1.0) {
  248. winTotalwidth = (FLOAT)0.75;
  249. winTotalheight = winTotalwidth * aspectRatio;
  250. } else {
  251. winTotalheight = (FLOAT) 0.75;
  252. winTotalwidth = winTotalheight / aspectRatio;
  253. };
  254. }
  255. #endif
  256. if (Frames < 5)
  257. Frames = 5;
  258. if (Frames > MAX_FRAMES)
  259. Frames = MAX_FRAMES;
  260. // Generate the geometry data (stored in the array of mesh structures),
  261. // for each frame of the animation. The shape of the flag is varied by
  262. // changing the global variable sinAngle.
  263. angleDelta = (FLOAT)(2.0 * PI) / (FLOAT)Frames;
  264. sinAngle = (FLOAT) 0.0;
  265. for (i = 0; i < Frames; i++) {
  266. if( !genTex(&winMesh[i]) )
  267. return FALSE;
  268. sinAngle += angleDelta;
  269. }
  270. return TRUE;
  271. }
  272. /******************************Public*Routine******************************\
  273. * delTexScene
  274. *
  275. * Cleanup the data associated with this screen saver.
  276. *
  277. * This function is exported to the main module in ss3dfo.c.
  278. *
  279. \**************************************************************************/
  280. void delTexScene()
  281. {
  282. int i;
  283. for (i = 0; i < Frames; i++)
  284. delMesh(&winMesh[i]);
  285. // Delete the texture
  286. ss_DeleteTexture( &gTex );
  287. }
  288. /******************************Public*Routine******************************\
  289. * updateTexScene
  290. *
  291. * Generate a scene by taking one of the meshes and rendering it with
  292. * OpenGL.
  293. *
  294. * This function is exported to the main module in ss3dfo.c.
  295. *
  296. \**************************************************************************/
  297. void updateTexScene(int flags, FLOAT fElapsedTime)
  298. {
  299. MESH *mesh;
  300. static double mxrot = 23.0;
  301. static double myrot = 23.0;
  302. static double mzrot = 5.7;
  303. static double mxrotInc = 0.0;
  304. static double myrotInc = 3.0;
  305. static double mzrotInc = 0.0;
  306. static int frameNum = 0;
  307. static FLOAT fFrameNum = 0.0f;
  308. if( fElapsedTime > 0.25f )
  309. fElapsedTime = 0.25f;
  310. FLOAT fTimeFactor = fElapsedTime * 20.0f;
  311. /*
  312. MFACE *faces;
  313. int i;
  314. POINT3D *pp;
  315. POINT3D *pn;
  316. int lastC, lastD;
  317. int aOffs, bOffs, cOffs, dOffs;
  318. int a, b;
  319. */
  320. FLOAT s = (FLOAT) 0.0;
  321. FLOAT ds;
  322. // In addition to having the flag wave (an effect acheived by switching
  323. // meshes from frame to frame), the flag changes its orientation from
  324. // frame to frame. This is done by applying a model view transform.
  325. D3DXMATRIX mat1, mat2, mat3, matFinal;
  326. D3DXMatrixRotationX(&mat1, D3DXToRadian((FLOAT)mxrot));
  327. D3DXMatrixRotationY(&mat2, D3DXToRadian((FLOAT)myrot));
  328. D3DXMatrixRotationZ(&mat3, D3DXToRadian((FLOAT)mzrot));
  329. matFinal = mat3 * mat2 * mat1 ;
  330. m_pd3dDevice->SetTransform( D3DTS_WORLD, &matFinal );
  331. // Divide the texture into IPREC slices. ds is the texture coordinate
  332. // delta we apply as we move along the x-axis.
  333. ds = (FLOAT)1.0 / (FLOAT)IPREC;
  334. // Setup the material property of the flag. The material property, light
  335. // properties, and polygon orientation will interact with the texture.
  336. curMatl = 0;
  337. myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (FLOAT *) &flagColors[0]);
  338. myglMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (FLOAT *) &matlBrightSpecular);
  339. myglMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, (FLOAT) 60.0);
  340. // Pick the mesh for the current frame.
  341. mesh = &winMesh[frameNum];
  342. // Take the geometry data is the mesh and convert it to a single OpenGL
  343. // quad strip. If smooth shading is required, use the vertex normals stored
  344. // in the mesh. Otherwise, use the face normals.
  345. //
  346. // As we define each vertex, we also define a corresponding vertex and
  347. // texture coordinate.
  348. // glBegin(GL_QUAD_STRIP);
  349. #if 0
  350. pp = mesh->pts;
  351. pn = mesh->norms;
  352. for (i = 0, faces = mesh->faces, lastC = faces->p[0], lastD = faces->p[1];
  353. i < mesh->numFaces; i++, faces++) {
  354. a = faces->p[0];
  355. b = faces->p[1];
  356. if (!bSmoothShading) {
  357. // Since flag is a single quad strip, this isn't needed.
  358. // But lets keep it in case we ever change to a more
  359. // complex model (ie., one that uses more than one quad
  360. // strip).
  361. #if 0
  362. if ((a != lastC) || (b != lastD)) {
  363. /*
  364. glNormal3fv((FLOAT *)&(faces - 1)->norm);
  365. glTexCoord2f(s, (FLOAT) 0.0);
  366. glVertex3fv((FLOAT *)((char *)pp +
  367. (lastC << 3) + (lastC << 2)));
  368. glTexCoord2f(s, (FLOAT) 1.0);
  369. glVertex3fv((FLOAT *)((char *)pp +
  370. (lastD << 3) + (lastD << 2)));
  371. */
  372. s += ds;
  373. /*
  374. glEnd();
  375. glBegin(GL_QUAD_STRIP);
  376. */
  377. }
  378. #endif
  379. if (faces->material != curMatl) {
  380. curMatl = faces->material;
  381. /*
  382. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
  383. (FLOAT *) &matlNoSpecular);
  384. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
  385. (FLOAT *) &flagColors[curMatl]);
  386. */
  387. }
  388. /*
  389. glNormal3fv((FLOAT *)&faces->norm);
  390. glTexCoord2f(s, (FLOAT) 0.0);
  391. glVertex3fv((FLOAT *)((char *)pp + (a << 3) + (a << 2)));
  392. glTexCoord2f(s, (FLOAT) 1.0);
  393. glVertex3fv((FLOAT *)((char *)pp + (b << 3) + (b << 2)));
  394. */
  395. s += ds;
  396. } else {
  397. aOffs = (a << 3) + (a << 2);
  398. bOffs = (b << 3) + (b << 2);
  399. if (faces->material != curMatl) {
  400. curMatl = faces->material;
  401. /*
  402. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
  403. (FLOAT *) &matlNoSpecular);
  404. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
  405. (FLOAT *) &flagColors[curMatl]);
  406. */
  407. }
  408. /*
  409. glTexCoord2f(s, (FLOAT) 0.0);
  410. glNormal3fv((FLOAT *)((char *)pn + aOffs));
  411. glVertex3fv((FLOAT *)((char *)pp + aOffs));
  412. glTexCoord2f(s, (FLOAT) 1.0);
  413. glNormal3fv((FLOAT *)((char *)pn + bOffs));
  414. glVertex3fv((FLOAT *)((char *)pp + bOffs));
  415. */
  416. s += ds;
  417. }
  418. lastC = faces->p[2];
  419. lastD = faces->p[3];
  420. }
  421. if (!bSmoothShading) {
  422. /*
  423. glNormal3fv((FLOAT *)&(faces - 1)->norm);
  424. glTexCoord2f(s, (FLOAT) 0.0);
  425. glVertex3fv((FLOAT *)((char *)pp + (lastC << 3) + (lastC << 2)));
  426. glTexCoord2f(s, (FLOAT) 1.0);
  427. glVertex3fv((FLOAT *)((char *)pp + (lastD << 3) + (lastD << 2)));
  428. */
  429. } else {
  430. cOffs = (lastC << 3) + (lastC << 2);
  431. dOffs = (lastD << 3) + (lastD << 2);
  432. /*
  433. glTexCoord2f(s, (FLOAT) 0.0);
  434. glNormal3fv((FLOAT *)((char *)pn + cOffs));
  435. glVertex3fv((FLOAT *)((char *)pp + cOffs));
  436. glTexCoord2f(s, (FLOAT) 1.0);
  437. glNormal3fv((FLOAT *)((char *)pn + dOffs));
  438. glVertex3fv((FLOAT *)((char *)pp + dOffs));
  439. */
  440. }
  441. // glEnd();
  442. #endif
  443. {
  444. HRESULT hr;
  445. WORD indexArray[4];
  446. MYVERTEX2 vertexArray[4];
  447. m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX2 );
  448. indexArray[0] = 0;
  449. indexArray[1] = 1;
  450. indexArray[2] = 2;
  451. indexArray[3] = 3;
  452. for( int iFace = 0; iFace < mesh->numFaces; iFace++ )
  453. {
  454. vertexArray[0].p = mesh->pts[ mesh->faces[iFace].p[0] ];
  455. vertexArray[1].p = mesh->pts[ mesh->faces[iFace].p[1] ];
  456. vertexArray[2].p = mesh->pts[ mesh->faces[iFace].p[2] ];
  457. vertexArray[3].p = mesh->pts[ mesh->faces[iFace].p[3] ];
  458. vertexArray[0].tu = s; vertexArray[0].tv = 1.0f;
  459. vertexArray[1].tu = s; vertexArray[1].tv = 0.0f;
  460. vertexArray[2].tu = s+ds; vertexArray[2].tv = 1.0f;
  461. vertexArray[3].tu = s+ds; vertexArray[3].tv = 0.0f;
  462. s += ds;
  463. if( bSmoothShading )
  464. {
  465. vertexArray[0].n = mesh->norms[ mesh->faces[iFace].p[0] ];
  466. vertexArray[1].n = mesh->norms[ mesh->faces[iFace].p[1] ];
  467. vertexArray[2].n = mesh->norms[ mesh->faces[iFace].p[2] ];
  468. vertexArray[3].n = mesh->norms[ mesh->faces[iFace].p[3] ];
  469. }
  470. else
  471. {
  472. vertexArray[0].n = mesh->faces[iFace].norm;
  473. vertexArray[1].n = mesh->faces[iFace].norm;
  474. vertexArray[2].n = mesh->faces[iFace].norm;
  475. vertexArray[3].n = mesh->faces[iFace].norm;
  476. }
  477. hr = m_pd3dDevice->DrawIndexedPrimitiveUP( D3DPT_TRIANGLESTRIP, 0,
  478. 4, 2, indexArray, D3DFMT_INDEX16, vertexArray, sizeof(MYVERTEX2) );
  479. }
  480. }
  481. // Transfer the image to the floating OpenGL window.
  482. // Determine the flag orientation for the next frame.
  483. // What we are doing is an oscillating rotation about the y-axis
  484. // (mxrotInc and mzrotInc are currently 0).
  485. mxrot += mxrotInc * fTimeFactor;
  486. myrot += myrotInc * fTimeFactor;
  487. mzrot += mzrotInc * fTimeFactor;
  488. if ((myrot < -65.0 && myrotInc < 0) || (myrot > 25.0 && myrotInc > 0))
  489. myrotInc = -myrotInc;
  490. // frameNum++;
  491. fFrameNum += fTimeFactor;
  492. frameNum = (INT)fFrameNum;
  493. if (frameNum >= Frames)
  494. {
  495. fFrameNum = 0.0f;
  496. frameNum = 0;
  497. }
  498. }