/* Demo of the classic mass-spring oscillator. This is undamped (frictionless), so it will oscillate forever like this. Recall that the frequency of oscillation is equal to sqrt(k/m). The higher the spring constant, the fasster the oscillation. The larger the mass, the slower the oscillation. The greater the initial displacement, the greater the amplitude of the oscillation. The smaller the "dt," the smoother the motion will be. Implemented Fall 2004 Scott D. Anderson */ #include #include // for atof #include // for sqrt and cos #include const int Width =100; // width of scene const int WallWidth=10; // thickness of left wall const int WallSize=50; // the height and depth of left wall void leftWall() { glPushAttrib(GL_ALL_ATTRIB_BITS); glPushMatrix(); glTranslatef(-Width/2-WallWidth/2,0,0); glScalef(WallWidth,WallSize,WallSize); twColorName(TW_YELLOW); glutSolidCube(1); glPopMatrix(); glPopAttrib(); } void platform() { const int PlatformHeight=10; glPushAttrib(GL_ALL_ATTRIB_BITS); glPushMatrix(); glTranslatef(0,-PlatformHeight/2,0); glScalef(Width,PlatformHeight,WallSize); twColorName(TW_BROWN); glutSolidCube(1); glPopMatrix(); glPopAttrib(); } void origin() { glPushAttrib(GL_ALL_ATTRIB_BITS); twColorName(TW_CYAN); glutSolidSphere(1,32,32); glPopAttrib(); } GLfloat MASS_INIT_X = 40; // initial horizonal position of the mass GLfloat mass = 1200; // the mass (in kilograms?) GLfloat springK = 3; // the spring constant (in what units?) GLfloat massV; // velocity of the mass GLfloat massA; // acceleration of the mass GLfloat massX = MASS_INIT_X; GLfloat DT = 0.1; // time step const int MASS_SIZE=20; void massSpring() { glPushAttrib(GL_ALL_ATTRIB_BITS); twColorName(TW_RED); glBegin(GL_LINES); glVertex3f(-Width/2,MASS_SIZE/2,0); glVertex3f(massX,MASS_SIZE/2,0); glEnd(); twColorName(TW_BLUE); glPushMatrix(); glTranslatef(massX,MASS_SIZE/2,0); glutSolidCube(MASS_SIZE); glPopMatrix(); glPopAttrib(); } void display(void) { twDisplayInit(); twCamera(); leftWall(); platform(); origin(); massSpring(); glFlush(); glutSwapBuffers(); } GLfloat Time = 0; void idle() { // by diff eq massA = - springK / mass * massX; massV += massA * DT; massX += massV * DT; // by solved diff eq. These values are ignored by the simulation, but // are computed for comparison during debugging. Time += DT; GLfloat omega = sqrt(springK/mass); GLfloat massX2 = MASS_INIT_X * cos(omega*Time); // printf("%f %f %f\n",massX, massX2, massX/massX2); glutPostRedisplay(); } int main(int argc, char** argv) { if(argc != 5) { printf("Usage: %s mass spring_constant initx dt\nTry 1 16 30 0.01\n",argv[0]); exit(0); } else { mass = atof(argv[1]); springK = atof(argv[2]); massX = MASS_INIT_X = atof(argv[3]); DT = atof(argv[4]); } glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); twInitWindowSize(500,500); glutCreateWindow(argv[0]); glutDisplayFunc(display); twBoundingBox(-Width/2,Width/2,0,WallSize,-WallSize/2,WallSize/2); twMainInit(); glutIdleFunc(idle); glutMainLoop(); return 0; }