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.

568 lines
16 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: gendrop.c
  3. *
  4. * The Splash style of the 3D Flying Objects screen saver.
  5. *
  6. * Simulation of a drop of water falling into a pool of water.
  7. *
  8. * Copyright (c) 1994 Microsoft Corporation
  9. *
  10. \**************************************************************************/
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include <d3dx8.h>
  15. #include "D3DSaver.h"
  16. #include "FlyingObjects.h"
  17. #include "mesh.h"
  18. #define FLOAT_SMALL (1e-6)
  19. #define DROPPREC 10
  20. // Remember from pre-calc:
  21. // x = r cos th
  22. // y = r sin th
  23. // to convert from polar to rect, and that
  24. // x = x' cos th - y' sin th
  25. // y = x' sin th + y' cos th
  26. // to rotate axes.
  27. //
  28. // Also, note that the equation for a lemniscate is:
  29. // r = sqrt(sin 2*th)
  30. //
  31. static POINT3D *circle;
  32. static POINT3D *drop;
  33. static POINT3D *curves;
  34. static MESH waterMesh;
  35. static MESH waterInmesh;
  36. static MESH waterOutmesh;
  37. static MESH waterBorderMesh;
  38. static MESH *drops;
  39. static int iPrec;
  40. static float fRadiusFact = 0.35f;
  41. static FLOAT light0Pos[] = {100.0f, 100.0f, 100.0f, 0.0f};
  42. void genCurves()
  43. {
  44. // iPrec is already protected from getting too low in InitDropScene,
  45. // but this will make "prefix" happy:
  46. if( iPrec <= 1 )
  47. return;
  48. int i;
  49. double angle;
  50. double step = -PI / (float)(iPrec - 1);
  51. double start = PI / 2.0;
  52. double rotSin = sin(PI / 4.0);
  53. double rotCos = cos(PI / 4.0);
  54. double aFract = 0.0;
  55. double bFract = 1.0;
  56. double fractInc = 1.0 / (double)(iPrec - 1);
  57. POINT3D *pt = curves;
  58. for (i = 0, angle = start; i < iPrec; i++, angle += step) {
  59. circle[i].x = (float) (0.5 * cos(angle));
  60. circle[i].y = (float) (0.5 * sin(angle));
  61. }
  62. step = (-PI / 4.0) / (float)(iPrec - 1);
  63. start = PI / 4.0;
  64. for (i = 0, angle = start; i < iPrec; i++, angle += step) {
  65. double x, y, r;
  66. double xrot, yrot;
  67. double sinVal;
  68. sinVal = sin(2.0 * angle);
  69. if (sinVal < 0.0)
  70. sinVal = -sinVal;
  71. r = 1.5 * sqrt(sinVal);
  72. x = r * cos(angle);
  73. y = r * sin(angle);
  74. xrot = x * rotCos - y * rotSin;
  75. yrot = x * rotSin + y * rotCos - 1.0;
  76. drop[i].x = (float) xrot;
  77. drop[i].y = (float) yrot;
  78. }
  79. for (i = 0; i < DROPPREC; i++) {
  80. int j;
  81. for (j = 0; j < iPrec; j++, pt++) {
  82. pt->x = (float) (aFract * circle[j].x +
  83. bFract * drop[j].x);
  84. pt->y = (float) (aFract * circle[j].y +
  85. bFract * drop[j].y);
  86. pt->z = 0.0f;
  87. }
  88. aFract += fractInc;
  89. bFract -= fractInc;
  90. }
  91. }
  92. #define NORMS(x, y) waterMesh.norms[((x) * iPrec) + y]
  93. #define BNORMS(x, y) waterBorderMesh.norms[((x) * iPrec) + y]
  94. #define INGRID(x, y) waterInmesh.pts[((x) * iPrec) + y]
  95. #define OUTGRID(x, y) waterOutmesh.pts[((x) * iPrec) + y]
  96. #define GRID(x, y) waterMesh.pts[((x) * iPrec) + y]
  97. #define BGRID(x, y) waterBorderMesh.pts[((x) * iPrec) + y]
  98. void genWater(double freq, double damp, double mag, double w, double minr)
  99. {
  100. int i;
  101. int j;
  102. double r;
  103. double theta;
  104. double thetaInc = (2.0 * PI) / (float)iPrec;
  105. double posInc = 1.0 / (float)iPrec;
  106. int facecount;
  107. double xCenter = 0.0;
  108. double zCenter = 0.0;
  109. POINT3D norm;
  110. static BOOL first = TRUE;
  111. if (first) {
  112. for (i = 0, r = 0.0; i < iPrec; i++, r += posInc) {
  113. for (j = 0, theta = 0.0; j < iPrec; j++, theta += thetaInc) {
  114. float x, z;
  115. float dx, dz;
  116. float rr;
  117. x = (float) cos(theta);
  118. z = (float) sin(theta);
  119. dx = x - (float) xCenter;
  120. dz = z - (float) zCenter;
  121. rr = (float) sqrt((dx * dx) + (dz * dz));
  122. dx /= rr;
  123. dz /= rr;
  124. dx *= i / (float)(iPrec - 1);
  125. dz *= i / (float)(iPrec - 1);
  126. GRID(i, j).x = dx + (float) xCenter;
  127. GRID(i, j).z = dz + (float) zCenter;
  128. INGRID(i, j).y = 0.0f;
  129. OUTGRID(i, j).y = 0.0f;
  130. }
  131. }
  132. }
  133. for (i = (iPrec - 1), r = 1.0; i >= 0; i--, r -= posInc) {
  134. float val;
  135. if (i == 0) {
  136. if (minr != 0.0)
  137. val = (float) (-mag * cos(w + (r * freq)) * exp((-damp * r)/2.0));
  138. else
  139. val = INGRID(0, 0).y * 0.95f;
  140. } else
  141. val = OUTGRID(i - 1, 0).y * 0.95f;
  142. for (j = 0; j < iPrec; j++)
  143. OUTGRID(i, j).y = val;
  144. }
  145. for (i = 0, r = 0.0; i < iPrec; i++, r += posInc) {
  146. for (j = 0; j < iPrec; j++) {
  147. if (i == iPrec-1)
  148. INGRID(i, j).y = -OUTGRID(i, j).y;
  149. else
  150. INGRID(i, j).y = INGRID(i + 1, j).y * 0.95f;
  151. }
  152. }
  153. waterMesh.numFaces = 0;
  154. waterBorderMesh.numFaces = 0;
  155. for (i = 0; i < iPrec; i++) {
  156. for (j = 0; j < iPrec; j++) {
  157. NORMS(i, j).x = 0.0f;
  158. NORMS(i, j).y = 0.0f;
  159. NORMS(i, j).z = 0.0f;
  160. }
  161. }
  162. for (i = 0, r = 0.0; i < iPrec; i++, r += posInc) {
  163. for (j = 0, theta = 0.0; j < iPrec; j++, theta += thetaInc) {
  164. GRID(i, j).y = OUTGRID(i, j).y + INGRID(i, j).y;
  165. if (i == (iPrec - 1)) {
  166. GRID(i, j).y = 0.0f;
  167. BGRID(0, j).x = GRID(i, j).x;
  168. BGRID(0, j).z = GRID(i, j).z;
  169. BGRID(0, j).y = GRID(i, j).y;
  170. BGRID(1, j).x = GRID(i, j).x;
  171. BGRID(1, j).z = GRID(i, j).z;
  172. BGRID(1, j).y = -0.5f;
  173. }
  174. }
  175. }
  176. for (i = 0; i < 2; i++) {
  177. for (j = 0; j < iPrec; j++) {
  178. BNORMS(i, j).x = 0.0f;
  179. BNORMS(i, j).y = 0.0f;
  180. BNORMS(i, j).z = 0.0f;
  181. }
  182. }
  183. for (facecount = 0, i = 0; i < (iPrec - 1); i++) {
  184. for (j = 0; j < iPrec; j++) {
  185. int k, l;
  186. k = i + 1;
  187. if (j == (iPrec - 1))
  188. l = 0;
  189. else
  190. l = j + 1;
  191. ss_calcNorm(&norm, &GRID(k, j), &GRID(i, j), &GRID(i, l));
  192. if (norm.x > -FLOAT_SMALL && norm.x < FLOAT_SMALL &&
  193. norm.y > -FLOAT_SMALL && norm.y < FLOAT_SMALL &&
  194. norm.z > -FLOAT_SMALL && norm.z < FLOAT_SMALL)
  195. ss_calcNorm(&norm, &GRID(i, l), &GRID(k, l), &GRID(k, j));
  196. waterMesh.faces[facecount].material = 0;
  197. waterMesh.faces[facecount].norm = norm;
  198. NORMS(i, j).x += norm.x;
  199. NORMS(i, j).y += norm.y;
  200. NORMS(i, j).z += norm.z;
  201. NORMS(k, j).x += norm.x;
  202. NORMS(k, j).y += norm.y;
  203. NORMS(k, j).z += norm.z;
  204. NORMS(i, l).x += norm.x;
  205. NORMS(i, l).y += norm.y;
  206. NORMS(i, l).z += norm.z;
  207. NORMS(k, l).x += norm.x;
  208. NORMS(k, l).y += norm.y;
  209. NORMS(k, l).z += norm.z;
  210. waterMesh.faces[facecount].p[0] = (k * iPrec) + j;
  211. waterMesh.faces[facecount].p[1] = (i * iPrec) + j;
  212. waterMesh.faces[facecount].p[2] = (k * iPrec) + l;
  213. waterMesh.faces[facecount].p[3] = (i * iPrec) + l;
  214. waterMesh.numFaces++;
  215. facecount++;
  216. }
  217. }
  218. waterMesh.numPoints = iPrec * iPrec;
  219. for (facecount = 0, i = 0; i < 1; i++) {
  220. for (j = 0; j < iPrec; j++) {
  221. int k, l;
  222. k = i + 1;
  223. if (j == (iPrec - 1))
  224. l = 0;
  225. else
  226. l = j + 1;
  227. ss_calcNorm(&norm, &BGRID(k, j), &BGRID(i, j), &BGRID(i, l));
  228. waterBorderMesh.faces[facecount].material = 0;
  229. waterBorderMesh.faces[facecount].norm = norm;
  230. // Setting SMOOTH_BORDER will render the border (the sides of the "pool")
  231. // with smooth shading. This effect is good at higher tesselations, but
  232. // doesn't really look that good for low tesselations.
  233. //
  234. // A possible enhancement for later: use smooth shading if tesselation
  235. // exceeds some threshold. Should we just pick some arbitrary threshold?
  236. // Make it a setup option? Things look pretty good now, so don't bother?
  237. #if SMOOTH_BORDER
  238. BNORMS(i, j).x += norm.x;
  239. BNORMS(i, j).y += norm.y;
  240. BNORMS(i, j).z += norm.z;
  241. if (i) {
  242. BNORMS(i-1, j).x += norm.x;
  243. BNORMS(i-1, j).y += norm.y;
  244. BNORMS(i-1, j).z += norm.z;
  245. }
  246. if (j) {
  247. BNORMS(i, j-1).x += norm.x;
  248. BNORMS(i, j-1).y += norm.y;
  249. BNORMS(i, j-1).z += norm.z;
  250. }
  251. BNORMS(k, j).x += norm.x;
  252. BNORMS(k, j).y += norm.y;
  253. BNORMS(k, j).z += norm.z;
  254. BNORMS(i, l).x += norm.x;
  255. BNORMS(i, l).y += norm.y;
  256. BNORMS(i, l).z += norm.z;
  257. #else
  258. BNORMS(i, j) = norm;
  259. if (i)
  260. BNORMS(i-1, j) = norm;
  261. if (j)
  262. BNORMS(i, j-1) = norm;
  263. BNORMS(k, j) = norm;
  264. BNORMS(i, l) = norm;
  265. #endif
  266. waterBorderMesh.faces[facecount].p[0] = (k * iPrec) + j;
  267. waterBorderMesh.faces[facecount].p[1] = (i * iPrec) + j;
  268. waterBorderMesh.faces[facecount].p[2] = (k * iPrec) + l;
  269. waterBorderMesh.faces[facecount].p[3] = (i * iPrec) + l;
  270. waterBorderMesh.numFaces++;
  271. facecount++;
  272. }
  273. }
  274. waterBorderMesh.numPoints = 2 * iPrec;
  275. ss_normalizeNorms(waterBorderMesh.norms, waterBorderMesh.numPoints);
  276. ss_normalizeNorms(waterMesh.norms, waterMesh.numPoints);
  277. first = FALSE;
  278. }
  279. BOOL initDropScene()
  280. {
  281. int i;
  282. iPrec = (int)(fTesselFact * 10.5);
  283. if (iPrec < 4)
  284. iPrec = 4;
  285. if (fTesselFact > fRadiusFact)
  286. fRadiusFact = fTesselFact;
  287. circle = (POINT3D *)SaverAlloc(iPrec * sizeof(POINT3D));
  288. if( circle == NULL )
  289. return FALSE;
  290. drop = (POINT3D *)SaverAlloc(iPrec * sizeof(POINT3D));
  291. if( drop == NULL )
  292. return FALSE;
  293. curves = (POINT3D *)SaverAlloc(DROPPREC * iPrec * sizeof(POINT3D));
  294. if( curves == NULL )
  295. return FALSE;
  296. drops = (MESH *)SaverAlloc(DROPPREC * sizeof(MESH));
  297. if( drops == NULL )
  298. return FALSE;
  299. /*
  300. D3DXMATRIX matProj;
  301. D3DXMatrixOrthoLH( &matProj, 3.0, 3.0, 0.0f, 3.0f );
  302. m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  303. */
  304. SetProjectionMatrixInfo( TRUE, 3.0, 3.0, 0.0, 3.0 );
  305. D3DXMATRIX matView;
  306. D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
  307. D3DXVECTOR3 vEyePt(0, 0, 1.5f);
  308. D3DXVECTOR3 vLookatPt(0, 0, 0);
  309. D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
  310. m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  311. if (!newMesh(&waterInmesh, iPrec * iPrec, iPrec * iPrec + iPrec) )
  312. return FALSE;
  313. if (!newMesh(&waterOutmesh, iPrec * iPrec, iPrec * iPrec + iPrec) )
  314. return FALSE;
  315. if (!newMesh(&waterMesh, iPrec * iPrec, iPrec * iPrec + iPrec) )
  316. return FALSE;
  317. if (!newMesh(&waterBorderMesh, iPrec, 2 * iPrec) )
  318. return FALSE;
  319. genCurves();
  320. for (i = 0; i < DROPPREC; i++)
  321. revolveSurface(&drops[i], &curves[i * iPrec], iPrec);
  322. return TRUE;
  323. }
  324. void delDropScene()
  325. {
  326. int i;
  327. for (i = 0; i < DROPPREC; i++) {
  328. delMesh(&drops[i]);
  329. }
  330. SaverFree(circle);
  331. SaverFree(drop);
  332. SaverFree(curves);
  333. SaverFree(drops);
  334. delMesh(&waterMesh);
  335. delMesh(&waterInmesh);
  336. delMesh(&waterOutmesh);
  337. delMesh(&waterBorderMesh);
  338. }
  339. void updateDropScene(int flags, FLOAT fElapsedTime)
  340. {
  341. static double zrot = 0.0;
  342. static double yrot = 0.0;
  343. static double myrot = 0.0;
  344. static double myrotInc = 0.1;
  345. static double zrotInc = 3.0;
  346. static double yrotInc = 1.5;
  347. static double ypos = 1.0;
  348. static int dropnum = 0;
  349. static double radius = 0.3;
  350. static double damp = 1.0;
  351. static double mag = 0.0;
  352. static double w = 1.0;
  353. static double freq = 1.0;
  354. static double dist;
  355. static double minr = 0.0;
  356. static FLOAT fH = 0.0f;
  357. static FLOAT fTimer = 0.0f;
  358. FLOAT fTimeFactor = fElapsedTime * 20.0f;
  359. if( fTimeFactor > 0.25f )
  360. fTimeFactor = 0.25f;
  361. RGBA color;
  362. D3DXMATRIX mat1, mat2, mat3, mat4, mat5, matFinal;
  363. zrot += zrotInc * fTimeFactor;
  364. if (zrot >= 45.0) {
  365. zrot = 45.0;
  366. zrotInc = -(2.0 + ((float)rand() / (float)RAND_MAX) * 3.0);
  367. } else if (zrot <= -45.0) {
  368. zrot = -45.0;
  369. zrotInc = 2.0 + ((float)rand() / (float)RAND_MAX) * 3.0;
  370. }
  371. yrot += yrotInc * fTimeFactor;
  372. if (yrot >= 10.0) {
  373. yrot = 10.0;
  374. yrotInc = -(1.0 + ((float)rand() / (float)RAND_MAX) * 2.0);
  375. } else if (zrot <= -10.0) {
  376. yrot = -10.0;
  377. yrotInc = 1.0 + ((float)rand() / (float)RAND_MAX) * 2.0;
  378. }
  379. if ((ypos + 0.5 < -radius) && (mag < 0.05)) {
  380. radius = (float)rand() / (6.0 * (float)RAND_MAX) + 0.1;
  381. ypos = 1.0;
  382. dropnum = 0;
  383. }
  384. dist = (ypos + 0.5);
  385. if ((dist > -radius / 2.0) && (dist < radius / 2.0)) {
  386. if (dist <= 0.0)
  387. dist = radius / 2.0;
  388. else
  389. dist = (radius / 2.0) - dist;
  390. freq = (0.25 * PI) / dist;
  391. if (freq < 0.2)
  392. freq = 0.2;
  393. minr = radius;
  394. damp = 20.0;
  395. mag = (0.35 / fRadiusFact) + 0.2 * dist;
  396. w = 0;
  397. } else {
  398. minr -= 0.05 * fTimeFactor;
  399. if (minr < 0.0)
  400. minr = 0.0;
  401. mag = mag * 0.95 * fTimeFactor;
  402. if (minr == 0.0) {
  403. w -= (PI / 6.0) * fTimeFactor;
  404. mag *= 0.75 * fTimeFactor;
  405. }
  406. if (damp > 0.0)
  407. damp -= 1.0 * fTimeFactor;
  408. }
  409. // Only call genWater about 10x per second
  410. fTimer += fElapsedTime;
  411. if( fTimer > 0.07f)
  412. {
  413. genWater(freq, damp, mag, w, minr);
  414. fTimer = 0.0f;
  415. }
  416. D3DXMatrixRotationZ(&mat1, D3DXToRadian((FLOAT)zrot));
  417. D3DXMatrixRotationX(&mat2, D3DXToRadian(30.0f));
  418. D3DXMatrixTranslation(&mat3, 0.0f, -0.5f, 0.0f);
  419. D3DXMatrixRotationY(&mat4, D3DXToRadian((FLOAT) (myrot * (180.0 / PI))));
  420. matFinal = mat4 * mat3 * mat2 * mat1 ;
  421. m_pd3dDevice->SetTransform( D3DTS_WORLD , &matFinal );
  422. if (bColorCycle) {
  423. ss_HsvToRgb(fH, 1.0f, 1.0f, &color );
  424. myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  425. (FLOAT *) &color);
  426. fH += fTimeFactor;
  427. if( fH >= 360.0f )
  428. fH -= 360.0f;
  429. } else {
  430. myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  431. (FLOAT *) &Material[6].Diffuse);
  432. }
  433. RenderMesh3(&waterMesh, bSmoothShading);
  434. if (!bColorCycle)
  435. {
  436. myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  437. (FLOAT *) &Material[2].Diffuse);
  438. }
  439. RenderMesh3(&waterBorderMesh, FALSE);
  440. if (dist > -radius) {
  441. if (!bColorCycle)
  442. {
  443. myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  444. (FLOAT *) &Material[6].Diffuse);
  445. }
  446. D3DXMatrixRotationZ(&mat1, D3DXToRadian((FLOAT)zrot));
  447. D3DXMatrixRotationX(&mat2, D3DXToRadian(30.0f));
  448. D3DXMatrixTranslation(&mat3, 0.0f, (FLOAT) ypos, 0.0f);
  449. D3DXMatrixScaling(&mat4, (FLOAT) radius, (FLOAT) radius, (FLOAT) radius);
  450. D3DXMatrixRotationX(&mat5, D3DXToRadian(180.0f));
  451. matFinal = mat5 * mat4 * mat3 * mat2 * mat1;
  452. m_pd3dDevice->SetTransform( D3DTS_WORLD , &matFinal );
  453. RenderMesh3( &drops[dropnum], bSmoothShading );
  454. }
  455. myrot += myrotInc * fTimeFactor;
  456. ypos -= 0.08 * fTimeFactor;
  457. dropnum = (int) ((DROPPREC - 1) - (ypos * (DROPPREC - 1)));
  458. if (dropnum > (DROPPREC - 1))
  459. dropnum = DROPPREC - 1;
  460. }