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.

544 lines
14 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 <stdlib.h>
  12. #include <windows.h>
  13. #include <GL\gl.h>
  14. #include <string.h>
  15. #include <math.h>
  16. #include "ss3dfo.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 GLfloat light0Pos[] = {100.0f, 100.0f, 100.0f, 0.0f};
  42. static dropList[DROPPREC];
  43. void genCurves()
  44. {
  45. int i;
  46. double angle;
  47. double step = -PI / (float)(iPrec - 1);
  48. double start = PI / 2.0;
  49. double rotSin = sin(PI / 4.0);
  50. double rotCos = cos(PI / 4.0);
  51. double aFract = 0.0;
  52. double bFract = 1.0;
  53. double fractInc = 1.0 / (double)(iPrec - 1);
  54. POINT3D *pt = curves;
  55. for (i = 0, angle = start; i < iPrec; i++, angle += step) {
  56. circle[i].x = (float) (0.5 * cos(angle));
  57. circle[i].y = (float) (0.5 * sin(angle));
  58. }
  59. step = (-PI / 4.0) / (float)(iPrec - 1);
  60. start = PI / 4.0;
  61. for (i = 0, angle = start; i < iPrec; i++, angle += step) {
  62. double x, y, r;
  63. double xrot, yrot;
  64. double sinVal;
  65. sinVal = sin(2.0 * angle);
  66. if (sinVal < 0.0)
  67. sinVal = -sinVal;
  68. r = 1.5 * sqrt(sinVal);
  69. x = r * cos(angle);
  70. y = r * sin(angle);
  71. xrot = x * rotCos - y * rotSin;
  72. yrot = x * rotSin + y * rotCos - 1.0;
  73. drop[i].x = (float) xrot;
  74. drop[i].y = (float) yrot;
  75. }
  76. for (i = 0; i < DROPPREC; i++) {
  77. int j;
  78. for (j = 0; j < iPrec; j++, pt++) {
  79. pt->x = (float) (aFract * circle[j].x +
  80. bFract * drop[j].x);
  81. pt->y = (float) (aFract * circle[j].y +
  82. bFract * drop[j].y);
  83. pt->z = 0.0f;
  84. }
  85. aFract += fractInc;
  86. bFract -= fractInc;
  87. }
  88. }
  89. #define NORMS(x, y) waterMesh.norms[((x) * iPrec) + y]
  90. #define BNORMS(x, y) waterBorderMesh.norms[((x) * iPrec) + y]
  91. #define INGRID(x, y) waterInmesh.pts[((x) * iPrec) + y]
  92. #define OUTGRID(x, y) waterOutmesh.pts[((x) * iPrec) + y]
  93. #define GRID(x, y) waterMesh.pts[((x) * iPrec) + y]
  94. #define BGRID(x, y) waterBorderMesh.pts[((x) * iPrec) + y]
  95. void genWater(double freq, double damp, double mag, double w, double minr)
  96. {
  97. int i;
  98. int j;
  99. double r;
  100. double theta;
  101. double thetaInc = (2.0 * PI) / (float)iPrec;
  102. double posInc = 1.0 / (float)iPrec;
  103. int facecount;
  104. double xCenter = 0.0;
  105. double zCenter = 0.0;
  106. POINT3D norm;
  107. static BOOL first = TRUE;
  108. if (first) {
  109. for (i = 0, r = 0.0; i < iPrec; i++, r += posInc) {
  110. for (j = 0, theta = 0.0; j < iPrec; j++, theta += thetaInc) {
  111. float x, z;
  112. float dx, dz;
  113. float rr;
  114. x = (float) cos(theta);
  115. z = (float) sin(theta);
  116. dx = x - (float) xCenter;
  117. dz = z - (float) zCenter;
  118. rr = (float) sqrt((dx * dx) + (dz * dz));
  119. dx /= rr;
  120. dz /= rr;
  121. dx *= i / (float)(iPrec - 1);
  122. dz *= i / (float)(iPrec - 1);
  123. GRID(i, j).x = dx + (float) xCenter;
  124. GRID(i, j).z = dz + (float) zCenter;
  125. INGRID(i, j).y = 0.0f;
  126. OUTGRID(i, j).y = 0.0f;
  127. }
  128. }
  129. }
  130. for (i = (iPrec - 1), r = 1.0; i >= 0; i--, r -= posInc) {
  131. float val;
  132. if (i == 0) {
  133. if (minr != 0.0)
  134. val = (float) (-mag * cos(w + (r * freq)) * exp((-damp * r)/2.0));
  135. else
  136. val = INGRID(0, 0).y * 0.95f;
  137. } else
  138. val = OUTGRID(i - 1, 0).y * 0.95f;
  139. for (j = 0; j < iPrec; j++)
  140. OUTGRID(i, j).y = val;
  141. }
  142. for (i = 0, r = 0.0; i < iPrec; i++, r += posInc) {
  143. for (j = 0; j < iPrec; j++) {
  144. if (i == iPrec-1)
  145. INGRID(i, j).y = -OUTGRID(i, j).y;
  146. else
  147. INGRID(i, j).y = INGRID(i + 1, j).y * 0.95f;
  148. }
  149. }
  150. waterMesh.numFaces = 0;
  151. waterBorderMesh.numFaces = 0;
  152. for (i = 0; i < iPrec; i++) {
  153. for (j = 0; j < iPrec; j++) {
  154. NORMS(i, j).x = 0.0f;
  155. NORMS(i, j).y = 0.0f;
  156. NORMS(i, j).z = 0.0f;
  157. }
  158. }
  159. for (i = 0, r = 0.0; i < iPrec; i++, r += posInc) {
  160. for (j = 0, theta = 0.0; j < iPrec; j++, theta += thetaInc) {
  161. GRID(i, j).y = OUTGRID(i, j).y + INGRID(i, j).y;
  162. if (i == (iPrec - 1)) {
  163. GRID(i, j).y = 0.0f;
  164. BGRID(0, j).x = GRID(i, j).x;
  165. BGRID(0, j).z = GRID(i, j).z;
  166. BGRID(0, j).y = GRID(i, j).y;
  167. BGRID(1, j).x = GRID(i, j).x;
  168. BGRID(1, j).z = GRID(i, j).z;
  169. BGRID(1, j).y = -0.5f;
  170. }
  171. }
  172. }
  173. for (i = 0; i < 2; i++) {
  174. for (j = 0; j < iPrec; j++) {
  175. BNORMS(i, j).x = 0.0f;
  176. BNORMS(i, j).y = 0.0f;
  177. BNORMS(i, j).z = 0.0f;
  178. }
  179. }
  180. for (facecount = 0, i = 0; i < (iPrec - 1); i++) {
  181. for (j = 0; j < iPrec; j++) {
  182. int k, l;
  183. k = i + 1;
  184. if (j == (iPrec - 1))
  185. l = 0;
  186. else
  187. l = j + 1;
  188. ss_calcNorm(&norm, &GRID(k, j), &GRID(i, j), &GRID(i, l));
  189. if (norm.x > -FLOAT_SMALL && norm.x < FLOAT_SMALL &&
  190. norm.y > -FLOAT_SMALL && norm.y < FLOAT_SMALL &&
  191. norm.z > -FLOAT_SMALL && norm.z < FLOAT_SMALL)
  192. ss_calcNorm(&norm, &GRID(i, l), &GRID(k, l), &GRID(k, j));
  193. waterMesh.faces[facecount].material = 0;
  194. waterMesh.faces[facecount].norm = norm;
  195. NORMS(i, j).x += norm.x;
  196. NORMS(i, j).y += norm.y;
  197. NORMS(i, j).z += norm.z;
  198. NORMS(k, j).x += norm.x;
  199. NORMS(k, j).y += norm.y;
  200. NORMS(k, j).z += norm.z;
  201. NORMS(i, l).x += norm.x;
  202. NORMS(i, l).y += norm.y;
  203. NORMS(i, l).z += norm.z;
  204. NORMS(k, l).x += norm.x;
  205. NORMS(k, l).y += norm.y;
  206. NORMS(k, l).z += norm.z;
  207. waterMesh.faces[facecount].p[0] = (k * iPrec) + j;
  208. waterMesh.faces[facecount].p[1] = (i * iPrec) + j;
  209. waterMesh.faces[facecount].p[2] = (k * iPrec) + l;
  210. waterMesh.faces[facecount].p[3] = (i * iPrec) + l;
  211. waterMesh.numFaces++;
  212. facecount++;
  213. }
  214. }
  215. waterMesh.numPoints = iPrec * iPrec;
  216. for (facecount = 0, i = 0; i < 1; i++) {
  217. for (j = 0; j < iPrec; j++) {
  218. int k, l;
  219. k = i + 1;
  220. if (j == (iPrec - 1))
  221. l = 0;
  222. else
  223. l = j + 1;
  224. ss_calcNorm(&norm, &BGRID(k, j), &BGRID(i, j), &BGRID(i, l));
  225. waterBorderMesh.faces[facecount].material = 0;
  226. waterBorderMesh.faces[facecount].norm = norm;
  227. // Setting SMOOTH_BORDER will render the border (the sides of the "pool")
  228. // with smooth shading. This effect is good at higher tesselations, but
  229. // doesn't really look that good for low tesselations.
  230. //
  231. // A possible enhancement for later: use smooth shading if tesselation
  232. // exceeds some threshold. Should we just pick some arbitrary threshold?
  233. // Make it a setup option? Things look pretty good now, so don't bother?
  234. #if SMOOTH_BORDER
  235. BNORMS(i, j).x += norm.x;
  236. BNORMS(i, j).y += norm.y;
  237. BNORMS(i, j).z += norm.z;
  238. if (i) {
  239. BNORMS(i-1, j).x += norm.x;
  240. BNORMS(i-1, j).y += norm.y;
  241. BNORMS(i-1, j).z += norm.z;
  242. }
  243. if (j) {
  244. BNORMS(i, j-1).x += norm.x;
  245. BNORMS(i, j-1).y += norm.y;
  246. BNORMS(i, j-1).z += norm.z;
  247. }
  248. BNORMS(k, j).x += norm.x;
  249. BNORMS(k, j).y += norm.y;
  250. BNORMS(k, j).z += norm.z;
  251. BNORMS(i, l).x += norm.x;
  252. BNORMS(i, l).y += norm.y;
  253. BNORMS(i, l).z += norm.z;
  254. #else
  255. BNORMS(i, j) = norm;
  256. if (i)
  257. BNORMS(i-1, j) = norm;
  258. if (j)
  259. BNORMS(i, j-1) = norm;
  260. BNORMS(k, j) = norm;
  261. BNORMS(i, l) = norm;
  262. #endif
  263. waterBorderMesh.faces[facecount].p[0] = (k * iPrec) + j;
  264. waterBorderMesh.faces[facecount].p[1] = (i * iPrec) + j;
  265. waterBorderMesh.faces[facecount].p[2] = (k * iPrec) + l;
  266. waterBorderMesh.faces[facecount].p[3] = (i * iPrec) + l;
  267. waterBorderMesh.numFaces++;
  268. facecount++;
  269. }
  270. }
  271. waterBorderMesh.numPoints = 2 * iPrec;
  272. ss_normalizeNorms(waterBorderMesh.norms, waterBorderMesh.numPoints);
  273. ss_normalizeNorms(waterMesh.norms, waterMesh.numPoints);
  274. first = FALSE;
  275. }
  276. void initDropScene()
  277. {
  278. int i;
  279. iPrec = (int)(fTesselFact * 10.5);
  280. if (iPrec < 4)
  281. iPrec = 4;
  282. if (fTesselFact > fRadiusFact)
  283. fRadiusFact = fTesselFact;
  284. circle = (POINT3D *)SaverAlloc(iPrec * sizeof(POINT3D));
  285. drop = (POINT3D *)SaverAlloc(iPrec * sizeof(POINT3D));
  286. curves = (POINT3D *)SaverAlloc(DROPPREC * iPrec * sizeof(POINT3D));
  287. drops = (MESH *)SaverAlloc(DROPPREC * sizeof(MESH));
  288. glMatrixMode(GL_PROJECTION);
  289. glLoadIdentity();
  290. glOrtho(-1.5, 1.5, -1.5, 1.5, 0.0, 3.0);
  291. glMatrixMode(GL_MODELVIEW);
  292. glLoadIdentity();
  293. glTranslatef(0.0f, 0.0f, -1.5f);
  294. glDisable(GL_CULL_FACE);
  295. newMesh(&waterInmesh, iPrec * iPrec, iPrec * iPrec + iPrec);
  296. newMesh(&waterOutmesh, iPrec * iPrec, iPrec * iPrec + iPrec);
  297. newMesh(&waterMesh, iPrec * iPrec, iPrec * iPrec + iPrec);
  298. newMesh(&waterBorderMesh, iPrec, 2 * iPrec);
  299. genCurves();
  300. for (i = 0; i < DROPPREC; i++)
  301. revolveSurface(&drops[i], &curves[i * iPrec], iPrec);
  302. for (i = 0; i < DROPPREC; i++) {
  303. GLuint id = 0x10 + i;
  304. dropList[i] = id;
  305. MakeList(id, &drops[i]);
  306. }
  307. for (i = 0; i < DROPPREC; i++) {
  308. delMesh(&drops[i]);
  309. }
  310. SaverFree(circle);
  311. SaverFree(drop);
  312. SaverFree(curves);
  313. SaverFree(drops);
  314. }
  315. void delDropScene()
  316. {
  317. delMesh(&waterMesh);
  318. delMesh(&waterInmesh);
  319. delMesh(&waterOutmesh);
  320. delMesh(&waterBorderMesh);
  321. }
  322. void updateDropScene(int flags)
  323. {
  324. static double zrot = 0.0;
  325. static double yrot = 0.0;
  326. static double mxrot = 0.0;
  327. static double myrot = 0.0;
  328. static double mzrot = 0.0;
  329. static double mxrotInc = 0.0;
  330. static double myrotInc = 0.1;
  331. static double zrotInc = 3.0;
  332. static double yrotInc = 1.5;
  333. static double mzrotInc = 0.0;
  334. static double ypos = 1.0;
  335. static int dropnum = 0;
  336. static double radius = 0.3;
  337. static double damp = 1.0;
  338. static double mag = 0.0;
  339. static double w = 1.0;
  340. static double freq = 1.0;
  341. static double dist;
  342. static double minr = 0.0;
  343. static int h = 0;
  344. RGBA color;
  345. glPushMatrix();
  346. zrot += zrotInc;
  347. if (zrot >= 45.0) {
  348. zrot = 45.0;
  349. zrotInc = -(2.0 + ((float)rand() / (float)RAND_MAX) * 3.0);
  350. } else if (zrot <= -45.0) {
  351. zrot = -45.0;
  352. zrotInc = 2.0 + ((float)rand() / (float)RAND_MAX) * 3.0;
  353. }
  354. yrot += yrotInc;
  355. if (yrot >= 10.0) {
  356. yrot = 10.0;
  357. yrotInc = -(1.0 + ((float)rand() / (float)RAND_MAX) * 2.0);
  358. } else if (zrot <= -10.0) {
  359. yrot = -10.0;
  360. yrotInc = 1.0 + ((float)rand() / (float)RAND_MAX) * 2.0;
  361. }
  362. if ((ypos + 0.5 < -radius) && (mag < 0.05)) {
  363. radius = (float)rand() / (6.0 * (float)RAND_MAX) + 0.1;
  364. ypos = 1.0;
  365. dropnum = 0;
  366. }
  367. dist = (ypos + 0.5);
  368. if ((dist > -radius / 2.0) && (dist < radius / 2.0)) {
  369. if (dist <= 0.0)
  370. dist = radius / 2.0;
  371. else
  372. dist = (radius / 2.0) - dist;
  373. freq = (0.25 * PI) / dist;
  374. if (freq < 0.2)
  375. freq = 0.2;
  376. minr = radius;
  377. damp = 20.0;
  378. mag = (0.35 / fRadiusFact) + 0.2 * dist;
  379. w = 0;
  380. } else {
  381. minr -= 0.05;
  382. if (minr < 0.0)
  383. minr = 0.0;
  384. mag = mag * 0.95;
  385. if (minr == 0.0) {
  386. w -= (PI / 6.0);
  387. mag *= 0.75;
  388. }
  389. if (damp > 0.0)
  390. damp -= 1.0;
  391. }
  392. genWater(freq, damp, mag, w, minr);
  393. glRotatef((GLfloat) zrot, 0.0f, 0.0f, 1.0f);
  394. glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
  395. glPushMatrix();
  396. glTranslatef(0.0f, -0.5f, 0.0f);
  397. glRotatef((GLfloat) (myrot * (180.0 / PI)), 0.0f, 1.0f, 0.0f);
  398. if (bColorCycle) {
  399. ss_HsvToRgb((float)h, 1.0f, 1.0f, &color );
  400. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  401. (GLfloat *) &color);
  402. h++;
  403. h %= 360;
  404. } else {
  405. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  406. (GLfloat *) &Material[6].kd);
  407. }
  408. updateObject(&waterMesh, bSmoothShading);
  409. if (bSmoothShading)
  410. glShadeModel(GL_FLAT);
  411. if (!bColorCycle)
  412. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  413. (GLfloat *) &Material[2].kd);
  414. updateObject2(&waterBorderMesh, FALSE);
  415. glPopMatrix();
  416. if (bSmoothShading)
  417. glShadeModel(GL_SMOOTH);
  418. if (dist > -radius) {
  419. if (!bColorCycle)
  420. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
  421. (GLfloat *) &Material[6].kd);
  422. glTranslatef(0.0f, (GLfloat) ypos, 0.0f);
  423. glScalef((GLfloat) radius, (GLfloat) radius, (GLfloat) radius);
  424. glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
  425. glEnable(GL_NORMALIZE);
  426. glCallList(dropList[dropnum]);
  427. glDisable(GL_NORMALIZE);
  428. }
  429. myrot += myrotInc;
  430. ypos -= 0.08;
  431. dropnum = (int) ((DROPPREC - 1) - (ypos * (DROPPREC - 1)));
  432. if (dropnum > (DROPPREC - 1))
  433. dropnum = DROPPREC - 1;
  434. glPopMatrix();
  435. }