Clone of mesa.
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.

pointblast.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /* Copyright (c) Mark J. Kilgard, 1997. */
  2. /* This program is freely distributable without licensing fees
  3. and is provided without guarantee or warrantee expressed or
  4. implied. This program is -not- in the public domain. */
  5. /* This example demonstrates how to render particle effects
  6. with OpenGL. A cloud of pinkish/orange particles explodes with the
  7. particles bouncing off the ground. When the EXT_point_parameters
  8. is present , the particle size is attenuated based on eye distance. */
  9. /*
  10. * $Log: pointblast.c,v $
  11. * Revision 1.3 2002/01/16 00:48:43 kschultz
  12. * Demo updates for Windows (Robert Bergkvist)
  13. *
  14. * Revision 1.2 2000/06/27 17:04:43 brianp
  15. * fixed compiler warnings
  16. *
  17. * Revision 1.1.1.1 1999/08/19 00:55:40 jtg
  18. * Imported sources
  19. *
  20. * Revision 3.3 1998/07/26 01:24:27 brianp
  21. * removed include of gl.h
  22. *
  23. * Revision 3.2 1998/02/14 18:51:46 brianp
  24. * fixed a small compiler warning
  25. *
  26. * Revision 3.1 1998/02/14 18:45:25 brianp
  27. * optimized to use flat shading, don't blend ground polygon
  28. *
  29. * Revision 3.0 1998/02/14 18:42:29 brianp
  30. * initial rev
  31. *
  32. */
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <math.h> /* for cos(), sin(), and sqrt() */
  37. #ifdef _WIN32
  38. #include <windows.h>
  39. #endif
  40. #define GL_GLEXT_LEGACY
  41. #include <GL/glut.h>
  42. /* Some <math.h> files do not define M_PI... */
  43. #ifndef M_PI
  44. #define M_PI 3.14159265
  45. #endif
  46. #if 0 /* For debugging. */
  47. #undef GL_EXT_point_parameters
  48. #endif
  49. static GLfloat angle = -150; /* in degrees */
  50. static int spin = 0;
  51. static int moving, begin;
  52. static int newModel = 1;
  53. static float theTime;
  54. static int repeat = 1;
  55. static int blend = 1;
  56. int useMipmaps = 1;
  57. int linearFiltering = 1;
  58. static GLfloat constant[3] = { 1/5.0, 0.0, 0.0 };
  59. static GLfloat linear[3] = { 0.0, 1/5.0, 0.0 };
  60. static GLfloat theQuad[3] = { 0.25, 0.0, 1/60.0 };
  61. #define MAX_POINTS 2000
  62. static int numPoints = 200;
  63. static GLfloat pointList[MAX_POINTS][3];
  64. static GLfloat pointTime[MAX_POINTS];
  65. static GLfloat pointVelocity[MAX_POINTS][2];
  66. static GLfloat pointDirection[MAX_POINTS][2];
  67. static int colorList[MAX_POINTS];
  68. static int animate = 1, motion = 0;
  69. static GLfloat colorSet[][4] = {
  70. /* Shades of red. */
  71. { 0.7, 0.2, 0.4, 0.5 },
  72. { 0.8, 0.0, 0.7, 0.5 },
  73. { 1.0, 0.0, 0.0, 0.5 },
  74. { 0.9, 0.3, 0.6, 0.5 },
  75. { 1.0, 0.4, 0.0, 0.5 },
  76. { 1.0, 0.0, 0.5, 0.5 },
  77. };
  78. #define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0]))
  79. #define DEAD (NUM_COLORS+1)
  80. #if 0 /* drand48 might be better on Unix machines */
  81. #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48())
  82. #else
  83. static float float_rand(void) { return rand() / (float) RAND_MAX; }
  84. #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand())
  85. #endif
  86. #define MEAN_VELOCITY 3.0
  87. #define GRAVITY 2.0
  88. #define TIME_DELTA 0.025 /* The speed of time. */
  89. /* Modeling units of ground extent in each X and Z direction. */
  90. #define EDGE 12
  91. static void
  92. makePointList(void)
  93. {
  94. float angle, velocity, direction;
  95. int i;
  96. motion = 1;
  97. for (i=0; i<numPoints; i++) {
  98. pointList[i][0] = 0.0;
  99. pointList[i][1] = 0.0;
  100. pointList[i][2] = 0.0;
  101. pointTime[i] = 0.0;
  102. angle = (RANDOM_RANGE(60.0, 70.0)) * M_PI/180.0;
  103. direction = RANDOM_RANGE(0.0, 360.0) * M_PI/180.0;
  104. pointDirection[i][0] = cos(direction);
  105. pointDirection[i][1] = sin(direction);
  106. velocity = MEAN_VELOCITY + RANDOM_RANGE(-0.8, 1.0);
  107. pointVelocity[i][0] = velocity * cos(angle);
  108. pointVelocity[i][1] = velocity * sin(angle);
  109. colorList[i] = rand() % NUM_COLORS;
  110. }
  111. theTime = 0.0;
  112. }
  113. static void
  114. updatePointList(void)
  115. {
  116. float distance;
  117. int i;
  118. motion = 0;
  119. for (i=0; i<numPoints; i++) {
  120. distance = pointVelocity[i][0] * theTime;
  121. /* X and Z */
  122. pointList[i][0] = pointDirection[i][0] * distance;
  123. pointList[i][2] = pointDirection[i][1] * distance;
  124. /* Z */
  125. pointList[i][1] =
  126. (pointVelocity[i][1] - 0.5 * GRAVITY * pointTime[i])*pointTime[i];
  127. /* If we hit the ground, bounce the point upward again. */
  128. if (pointList[i][1] <= 0.0) {
  129. if (distance > EDGE) {
  130. /* Particle has hit ground past the distance duration of
  131. the particles. Mark particle as dead. */
  132. colorList[i] = NUM_COLORS; /* Not moving. */
  133. continue;
  134. }
  135. pointVelocity[i][1] *= 0.8; /* 80% of previous up velocity. */
  136. pointTime[i] = 0.0; /* Reset the particles sense of up time. */
  137. }
  138. motion = 1;
  139. pointTime[i] += TIME_DELTA;
  140. }
  141. theTime += TIME_DELTA;
  142. if (!motion && !spin) {
  143. if (repeat) {
  144. makePointList();
  145. } else {
  146. glutIdleFunc(NULL);
  147. }
  148. }
  149. }
  150. static void
  151. idle(void)
  152. {
  153. updatePointList();
  154. if (spin) {
  155. angle += 0.3;
  156. newModel = 1;
  157. }
  158. glutPostRedisplay();
  159. }
  160. static void
  161. visible(int vis)
  162. {
  163. if (vis == GLUT_VISIBLE) {
  164. if (animate && (motion || spin)) {
  165. glutIdleFunc(idle);
  166. }
  167. } else {
  168. glutIdleFunc(NULL);
  169. }
  170. }
  171. static void
  172. recalcModelView(void)
  173. {
  174. glPopMatrix();
  175. glPushMatrix();
  176. glRotatef(angle, 0.0, 1.0, 0.0);
  177. newModel = 0;
  178. }
  179. static void
  180. redraw(void)
  181. {
  182. int i;
  183. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  184. if (newModel)
  185. recalcModelView();
  186. glDepthMask(GL_FALSE);
  187. /* Draw the floor. */
  188. /* glEnable(GL_TEXTURE_2D);*/
  189. glColor3f(0.5, 1.0, 0.5);
  190. glBegin(GL_QUADS);
  191. glTexCoord2f(0.0, 0.0);
  192. glVertex3f(-EDGE, -0.05, -EDGE);
  193. glTexCoord2f(20.0, 0.0);
  194. glVertex3f(EDGE, -0.05, -EDGE);
  195. glTexCoord2f(20.0, 20.0);
  196. glVertex3f(EDGE, -0.05, EDGE);
  197. glTexCoord2f(0.0, 20.0);
  198. glVertex3f(-EDGE, -0.05, EDGE);
  199. glEnd();
  200. /* Allow particles to blend with each other. */
  201. glDepthMask(GL_TRUE);
  202. if (blend)
  203. glEnable(GL_BLEND);
  204. glDisable(GL_TEXTURE_2D);
  205. glBegin(GL_POINTS);
  206. for (i=0; i<numPoints; i++) {
  207. /* Draw alive particles. */
  208. if (colorList[i] != DEAD) {
  209. glColor4fv(colorSet[colorList[i]]);
  210. glVertex3fv(pointList[i]);
  211. }
  212. }
  213. glEnd();
  214. glDisable(GL_BLEND);
  215. glutSwapBuffers();
  216. }
  217. /* ARGSUSED2 */
  218. static void
  219. mouse(int button, int state, int x, int y)
  220. {
  221. /* Scene can be spun around Y axis using left
  222. mouse button movement. */
  223. if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  224. moving = 1;
  225. begin = x;
  226. }
  227. if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  228. moving = 0;
  229. }
  230. }
  231. /* ARGSUSED1 */
  232. static void
  233. mouseMotion(int x, int y)
  234. {
  235. if (moving) {
  236. angle = angle + (x - begin);
  237. begin = x;
  238. newModel = 1;
  239. glutPostRedisplay();
  240. }
  241. }
  242. static void
  243. menu(int option)
  244. {
  245. switch (option) {
  246. case 0:
  247. makePointList();
  248. break;
  249. #if GL_EXT_point_parameters
  250. case 1:
  251. glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, constant);
  252. break;
  253. case 2:
  254. glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, linear);
  255. break;
  256. case 3:
  257. glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, theQuad);
  258. break;
  259. #endif
  260. case 4:
  261. blend = 1;
  262. break;
  263. case 5:
  264. blend = 0;
  265. break;
  266. #if GL_EXT_point_parameters
  267. case 6:
  268. glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0);
  269. break;
  270. case 7:
  271. glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 10.0);
  272. break;
  273. #endif
  274. case 8:
  275. glEnable(GL_POINT_SMOOTH);
  276. break;
  277. case 9:
  278. glDisable(GL_POINT_SMOOTH);
  279. break;
  280. case 10:
  281. glPointSize(2.0);
  282. break;
  283. case 11:
  284. glPointSize(4.0);
  285. break;
  286. case 12:
  287. glPointSize(8.0);
  288. break;
  289. case 13:
  290. spin = 1 - spin;
  291. if (animate && (spin || motion)) {
  292. glutIdleFunc(idle);
  293. } else {
  294. glutIdleFunc(NULL);
  295. }
  296. break;
  297. case 14:
  298. numPoints = 200;
  299. break;
  300. case 15:
  301. numPoints = 500;
  302. break;
  303. case 16:
  304. numPoints = 1000;
  305. break;
  306. case 17:
  307. numPoints = 2000;
  308. break;
  309. case 666:
  310. exit(0);
  311. }
  312. glutPostRedisplay();
  313. }
  314. /* ARGSUSED1 */
  315. static void
  316. key(unsigned char c, int x, int y)
  317. {
  318. switch (c) {
  319. case 13:
  320. animate = 1 - animate; /* toggle. */
  321. if (animate && (motion || spin)) {
  322. glutIdleFunc(idle);
  323. } else {
  324. glutIdleFunc(NULL);
  325. }
  326. break;
  327. case ' ':
  328. animate = 1;
  329. makePointList();
  330. glutIdleFunc(idle);
  331. break;
  332. case 27:
  333. exit(0);
  334. }
  335. }
  336. /* Nice floor texture tiling pattern. */
  337. static char *circles[] = {
  338. "....xxxx........",
  339. "..xxxxxxxx......",
  340. ".xxxxxxxxxx.....",
  341. ".xxx....xxx.....",
  342. "xxx......xxx....",
  343. "xxx......xxx....",
  344. "xxx......xxx....",
  345. "xxx......xxx....",
  346. ".xxx....xxx.....",
  347. ".xxxxxxxxxx.....",
  348. "..xxxxxxxx......",
  349. "....xxxx........",
  350. "................",
  351. "................",
  352. "................",
  353. "................",
  354. };
  355. static void
  356. makeFloorTexture(void)
  357. {
  358. GLubyte floorTexture[16][16][3];
  359. GLubyte *loc;
  360. int s, t;
  361. /* Setup RGB image for the texture. */
  362. loc = (GLubyte*) floorTexture;
  363. for (t = 0; t < 16; t++) {
  364. for (s = 0; s < 16; s++) {
  365. if (circles[t][s] == 'x') {
  366. /* Nice blue. */
  367. loc[0] = 0x1f;
  368. loc[1] = 0x1f;
  369. loc[2] = 0x8f;
  370. } else {
  371. /* Light gray. */
  372. loc[0] = 0xca;
  373. loc[1] = 0xca;
  374. loc[2] = 0xca;
  375. }
  376. loc += 3;
  377. }
  378. }
  379. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  380. if (useMipmaps) {
  381. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  382. GL_LINEAR_MIPMAP_LINEAR);
  383. gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16,
  384. GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
  385. } else {
  386. if (linearFiltering) {
  387. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  388. } else {
  389. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  390. }
  391. glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
  392. GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
  393. }
  394. }
  395. int
  396. main(int argc, char **argv)
  397. {
  398. int i;
  399. glutInit(&argc, argv);
  400. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  401. for (i=1; i<argc; i++) {
  402. if(!strcmp("-noms", argv[i])) {
  403. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  404. printf("forcing no multisampling\n");
  405. } else if(!strcmp("-nomipmaps", argv[i])) {
  406. useMipmaps = 0;
  407. } else if(!strcmp("-nearest", argv[i])) {
  408. linearFiltering = 0;
  409. }
  410. }
  411. glutCreateWindow("point burst");
  412. glutDisplayFunc(redraw);
  413. glutMouseFunc(mouse);
  414. glutMotionFunc(mouseMotion);
  415. glutVisibilityFunc(visible);
  416. glutKeyboardFunc(key);
  417. glutCreateMenu(menu);
  418. glutAddMenuEntry("Reset time", 0);
  419. glutAddMenuEntry("Constant", 1);
  420. glutAddMenuEntry("Linear", 2);
  421. glutAddMenuEntry("Quadratic", 3);
  422. glutAddMenuEntry("Blend on", 4);
  423. glutAddMenuEntry("Blend off", 5);
  424. glutAddMenuEntry("Threshold 1", 6);
  425. glutAddMenuEntry("Threshold 10", 7);
  426. glutAddMenuEntry("Point smooth on", 8);
  427. glutAddMenuEntry("Point smooth off", 9);
  428. glutAddMenuEntry("Point size 2", 10);
  429. glutAddMenuEntry("Point size 4", 11);
  430. glutAddMenuEntry("Point size 8", 12);
  431. glutAddMenuEntry("Toggle spin", 13);
  432. glutAddMenuEntry("200 points ", 14);
  433. glutAddMenuEntry("500 points ", 15);
  434. glutAddMenuEntry("1000 points ", 16);
  435. glutAddMenuEntry("2000 points ", 17);
  436. glutAddMenuEntry("Quit", 666);
  437. glutAttachMenu(GLUT_RIGHT_BUTTON);
  438. glShadeModel(GL_FLAT);
  439. glEnable(GL_DEPTH_TEST);
  440. glEnable(GL_POINT_SMOOTH);
  441. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  442. glPointSize(8.0);
  443. #if GL_EXT_point_parameters
  444. glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, theQuad);
  445. #endif
  446. glMatrixMode(GL_PROJECTION);
  447. gluPerspective( /* field of view in degree */ 40.0,
  448. /* aspect ratio */ 1.0,
  449. /* Z near */ 0.5, /* Z far */ 40.0);
  450. glMatrixMode(GL_MODELVIEW);
  451. gluLookAt(0.0, 1.0, 8.0, /* eye location */
  452. 0.0, 1.0, 0.0, /* center is at (0,0,0) */
  453. 0.0, 1.0, 0.); /* up is in postivie Y direction */
  454. glPushMatrix(); /* dummy push so we can pop on model
  455. recalc */
  456. makePointList();
  457. makeFloorTexture();
  458. glutMainLoop();
  459. return 0; /* ANSI C requires main to return int. */
  460. }