Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

pointblast.c 11KB

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