📄 particle.c
字号:
if (particles[i].alive == 0) continue; c = particles[i].position[1]/2.1*255; glColor3ub(c, 128+c*0.5, 255); glVertex3fv(particles[i].position); } glEnd(); } else { glBegin(GL_LINES); for (i = 0; i < num_particles; i++) { if (particles[i].alive == 0) continue; c = particles[i].previous[1]/2.1*255; glColor4ub(c, 128+c*0.5, 255, 32); glVertex3fv(particles[i].previous); c = particles[i].position[1]/2.1*255; glColor4ub(c, 128+c*0.5, 255, 196); glVertex3fv(particles[i].position); } glEnd(); } /* spit out frame rate. */ if (frame_rate) { frames++; if (frames > 7) { sprintf(s, "%g fps", (float)7/frame_time); frame_time = 0; frames = 0; } text(5, 5, s); } glPopMatrix(); glutSwapBuffers();}voididle(void){ static int i, j; static int living = 0; /* index to end of live particles */ static float dt; static float last = 0; dt = timedelta(); frame_time += dt;#if 1 /* slow the simulation if we can't keep the frame rate up around 10 fps */ if (dt > 0.1) { slow_down = 1.0/(100*dt); } else if (dt < 0.1) { slow_down = 1; }#endif dt *= slow_down; /* resurrect a few particles */ for (i = 0; i < flow*dt; i++) { psNewParticle(&particles[living], dt); living++; if (living >= num_particles) living = 0; } for (i = 0; i < num_particles; i++) { psTimeStep(&particles[i], dt); /* collision with sphere? */ if (draw_spheres) { for (j = 0; j < draw_spheres; j++) { psCollideSphere(&particles[i], &spheres[j]); } } /* collision with ground? */ if (particles[i].position[1] <= 0) { psBounce(&particles[i], dt); } /* dead particle? */ if (particles[i].position[1] < 0.1 && fequal(particles[i].velocity[1], 0)) { particles[i].alive = 0; } } glutPostRedisplay();}voidvisible(int state){ if (state == GLUT_VISIBLE) glutIdleFunc(idle); else glutIdleFunc(NULL);}voidbail(int code){ free(particles); exit(code);}#ifdef SCREEN_SAVER_MODEvoidss_keyboard(char key, int x, int y){ bail(0);}voidss_mouse(int button, int state, int x, int y){ bail(0);}voidss_passive(int x, int y){ static int been_here = 0; /* for some reason, GLUT sends an initial passive motion callback when a window is initialized, so this would immediately terminate the program. to get around this, see if we've been here before. (actually if we've been here twice.) */ if (been_here > 1) bail(0); been_here++;}#elsevoidkeyboard(unsigned char key, int x, int y){ static int fullscreen = 0; static int old_x = 50; static int old_y = 50; static int old_width = 512; static int old_height = 512; static int s = 0; switch (key) { case 27: bail(0); break; case 't': if (type == PS_WATERFALL) type = PS_FOUNTAIN; else if (type == PS_FOUNTAIN) type = PS_WATERFALL; break; case 's': draw_spheres++; if (draw_spheres > NUM_SPHERES) draw_spheres = 0; break; case 'S': printf("PSsphere spheres[NUM_SPHERES] = {/* position of spheres */\n"); for (s = 0; s < NUM_SPHERES; s++) { printf(" { %g, %g, %g, %g },\n", spheres[s].x, spheres[s].y, spheres[s].z, spheres[s].radius); } printf("};\n"); break; case 'l': points = !points; break; case 'P': point_size++; glPointSize(point_size); break; case 'p': point_size--; if (point_size < 1) point_size = 1; glPointSize(point_size); break; case '+': flow += 100; if (flow > num_particles) flow = num_particles; printf("%g particles/second\n", flow); break; case '-': flow -= 100; if (flow < 0) flow = 0; printf("%g particles/second\n", flow); break; case '#': frame_rate = !frame_rate; break; case '~': fullscreen = !fullscreen; if (fullscreen) { old_x = glutGet(GLUT_WINDOW_X); old_y = glutGet(GLUT_WINDOW_Y); old_width = glutGet(GLUT_WINDOW_WIDTH); old_height = glutGet(GLUT_WINDOW_HEIGHT); glutFullScreen(); } else { glutReshapeWindow(old_width, old_height); glutPositionWindow(old_x, old_y); } break; case '!': s++; if (s >= NUM_SPHERES) s = 0; break; case '4': spheres[s].x -= 0.05; break; case '6': spheres[s].x += 0.05; break; case '2': spheres[s].y -= 0.05; break; case '8': spheres[s].y += 0.05; break; case '7': spheres[s].z -= 0.05; break; case '3': spheres[s].z += 0.05; break; case '9': spheres[s].radius += 0.05; break; case '1': spheres[s].radius -= 0.05; break; }}voidmenu(int item){ keyboard((unsigned char)item, 0, 0);}voidmenustate(int state){ /* hook up a fake time delta to avoid jumping when menu comes up */ if (state == GLUT_MENU_NOT_IN_USE) timedelta();}#endifint old_x, old_y;voidmouse(int button, int state, int x, int y){ old_x = x; old_y = y; glutPostRedisplay();}voidmotion(int x, int y){ spin_x = x - old_x; spin_y = y - old_y; glutPostRedisplay();}intmain(int argc, char** argv){ glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowPosition(0, 0); glutInitWindowSize(640, 480); glutInit(&argc, argv); glutCreateWindow("Particles"); glutDisplayFunc(display); glutReshapeFunc(reshape);#ifdef SCREEN_SAVER_MODE glutPassiveMotionFunc(ss_passive); glutKeyboardFunc(ss_keyboard); glutMouseFunc(ss_mouse); glutSetCursor(GLUT_CURSOR_NONE); glutFullScreen(); #else glutMotionFunc(motion); glutMouseFunc(mouse); glutKeyboardFunc(keyboard);#endif glutMenuStateFunc(menustate); glutCreateMenu(menu); glutAddMenuEntry("Particle", 0); glutAddMenuEntry("", 0); glutAddMenuEntry("[f] Fog on/off", 'f'); glutAddMenuEntry("[t] Spray type", 't'); glutAddMenuEntry("[s] Collision spheres", 's'); glutAddMenuEntry("[-] Less flow", '-'); glutAddMenuEntry("[+] More flow", '+'); glutAddMenuEntry("[p] Smaller points", 'p'); glutAddMenuEntry("[P] Larger points", 'P'); glutAddMenuEntry("[l] Toggle points/lines", 'l'); glutAddMenuEntry("[#] Toggle framerate on/off", '#'); glutAddMenuEntry("[~] Toggle fullscreen on/off", '~'); glutAddMenuEntry("", 0); glutAddMenuEntry("Use the numeric keypad to move the spheres", 0); glutAddMenuEntry("[!] Change active sphere", 0); glutAddMenuEntry("", 0); glutAddMenuEntry("[Esc] Quit", 27); glutAttachMenu(GLUT_RIGHT_BUTTON); if (argc > 1) { if (strcmp(argv[1], "-h") == 0) { fprintf(stderr, "%s [particles] [flow] [speed%]\n", argv[0]); exit(0); } sscanf(argv[1], "%d", &num_particles); if (argc > 2) sscanf(argv[2], "%f", &flow); if (argc > 3) sscanf(argv[3], "%f", &slow_down); } particles = (PSparticle*)malloc(sizeof(PSparticle) * num_particles); glutVisibilityFunc(visible); glutMainLoop(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -