/* Simulation Project * Justin Day * Started 03/30/2002 */ #include "config.h" #include #include #include #include #include #include "world.h" #define drawline(x1,y1,x2,y2) glBegin(GL_LINES); \ glVertex2f((x1),(y1)); glVertex2f((x2),(y2)); glEnd(); int drag=-1; float dragx, dragy; int drag_fixed; int mouseover=-1; float elapsed_time; float max_time = 0; float total_distance = 0; int time_compression = 1; float minline = 0; float maxline = 0; float jumpline = -1; int calls=0; void drawcircle(float x, float y, float r) { float cx,cy; cy = y+r; cx = x; glBegin(GL_LINE_STRIP); for(float angle=0.0;angle<=2*PI;angle+=0.1) { glVertex2d(cx,cy); cx = x+(r*sin(angle)); cy = y+(r*cos(angle)); } glEnd(); } void drawsolidcircle(float x, float y, float r) { float cx=x; float cy=y; glBegin(GL_TRIANGLES); for(float angle=0.0;angle<=2*PI;angle+=0.3) { glVertex2d(cx,cy); glVertex2d(x,y); cx = x+(r*sin(angle)); cy = y+(r*cos(angle)); glVertex2d(cx,cy); } glEnd(); } // Function to display output void onPaint(void) { Joint* J; #if DEBUG_ALL cout << "onPaint()\n"; #endif // Clear color buffer glClear(GL_COLOR_BUFFER_BIT); if (time_compression > 1 || max_time) { glColor3f(0.0f,0.0f,0.7f); if (Spring::MuscleFlow()>0) { drawline(minline*PIXELS_PER_METER,0,minline*PIXELS_PER_METER,WINDOW_Y); } else { drawline(maxline*PIXELS_PER_METER,0,maxline*PIXELS_PER_METER,WINDOW_Y); } drawline(0,jumpline*PIXELS_PER_METER,WINDOW_X,jumpline*PIXELS_PER_METER); } for(int i=0;iSprings();j++) { if (J->SpringEnd(j)) { glColor3f(J->GetSpring(j)->Muscle(),0.5f,0.5f); drawline( J->SpringX(j,0)*PIXELS_PER_METER, J->SpringY(j,0)*PIXELS_PER_METER+JOINT_RADIUS, J->SpringX(j,1)*PIXELS_PER_METER, J->SpringY(j,1)*PIXELS_PER_METER+JOINT_RADIUS ); } } if (i==drag || i==mouseover) { glColor3f(1.0f,1.0f,1.0f); } else { glColor3f(0.7f,0.7f,0.7f); } drawsolidcircle(J->X()*PIXELS_PER_METER,J->Y()*PIXELS_PER_METER+JOINT_RADIUS,JOINT_RADIUS); } if (drag>-1) { drawcircle( World::Joints(drag)->X()*PIXELS_PER_METER, World::Joints(drag)->Y()*PIXELS_PER_METER+JOINT_RADIUS, JOINT_RADIUS+3 ); } else if (mouseover>-1) { drawcircle( World::Joints(mouseover)->X()*PIXELS_PER_METER, World::Joints(mouseover)->Y()*PIXELS_PER_METER+JOINT_RADIUS, JOINT_RADIUS+3 ); } glutSwapBuffers(); } // Called by GLUT when the window is initially opened or resized void onResize(GLsizei w, GLsizei h) { // Set viewport to window dimensions glViewport(0, 0, w, h); // Reset coordinate system glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLfloat) w, 0.0, (GLfloat) h); World::Width(w/PIXELS_PER_METER); World::Height(h/PIXELS_PER_METER); } void onTimeSlice(int n) { Joint *J; float distance = 0; float min=999; float max=0; float minheight=0; float newline=0; #if DEBUG_ALL cout << "onTimeSlice(" << n << ")\n"; #endif if (n) { for (int frames=0;framesOnTimeSlice((float) n/1000.0*TIME_PER_FRAME); } minheight = 9999; min = 9999; max = 0; for (int i=0;iTranslate(); if (J->Y()<0) { J->BounceY(); // Don't want to track jumping until the model has hit the ground once. if (jumpline<0) { jumpline=0; } } if (J->X()<0) { if (Spring::MuscleFlow()<0) total_distance -= 1.0; J->BounceX(); } else if (J->X()>World::Width()) { if (Spring::MuscleFlow()>0) total_distance -= 1.0; J->BounceX(); } if (min>J->X()) min = J->X(); if (maxX()) max = J->X(); if (minheight>J->Y()) minheight = J->Y(); } calls++; if (jumpline>=0 && minheight>jumpline) jumpline = minheight; if (Spring::MuscleFlow()>0 && minline) total_distance += min-minline; else if (maxline) total_distance -= max-maxline; //cout << min << " " << (min-minline) << " - " ; minline=min; maxline=max; elapsed_time += (float) n/1000.0*TIME_PER_FRAME; //cout << elapsed_time << ": " << total_distance << " meters "<=max_time) break; } if (time_compression < 1000) glutPostRedisplay(); if (max_time && elapsed_time>=max_time) { #if USE_FULLSCREEN if (time_compression < 1000) glutLeaveGameMode(); #endif cout.setf(ios::fixed); n=0; cout << "Final Time = "<=J->X()*PIXELS_PER_METER-10 && x<=J->X()*PIXELS_PER_METER+10 && y>=J->Y()*PIXELS_PER_METER-10 && y<=J->Y()*PIXELS_PER_METER+10) { drag = i; drag_fixed=J->IsFixed(); J->Fix(); break; } } } else { if (drag != -1 && !drag_fixed) { World::Joints(drag)->Unfix(); } drag = -1; } } void onDrag(int x, int y) { if (drag != -1) { dragy = glutGet(GLUT_WINDOW_HEIGHT)-y; dragx = x; World::Joints(drag)->MoveTo(dragx/PIXELS_PER_METER,dragy/PIXELS_PER_METER); } } void onMouseMove(int x, int y) { Joint *J; y = glutGet(GLUT_WINDOW_HEIGHT)-y; mouseover = -1; for (int i=0;i=J->X()*PIXELS_PER_METER-10 && x<=J->X()*PIXELS_PER_METER+10 && y>=J->Y()*PIXELS_PER_METER-10 && y<=J->Y()*PIXELS_PER_METER+10) { mouseover = i; } } } void onKeyPress(unsigned char key, int x, int y) { if (key == 27) { #if USE_FULLSCREEN glutLeaveGameMode(); #endif exit(0); } } int main(int argc, char **argv) { if (argc>1) { World::Load(argv[1]); } else { cout << argv[0] << " world.def [time_compression] [test_duration]\n"; exit(1); } if (argc>2) time_compression = atoi(argv[2]); if (argc>3) max_time = atoi(argv[3]); if (max_time && time_compression > 1000) { while(1) { onTimeSlice(1000/FRAMES_PER_SECOND); } } else { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); #if USE_FULLSCREEN glutGameModeString( "800x600:16" ); glutEnterGameMode(); #else glutInitWindowPosition(10, 10); glutInitWindowSize(WINDOW_X, WINDOW_Y); glutCreateWindow("Cobosoda - Simulating. . ."); #endif if (time_compression == 1) { glutMouseFunc(onClick); glutMotionFunc(onDrag); glutPassiveMotionFunc(onMouseMove); glutKeyboardFunc(onKeyPress); } glutDisplayFunc(onPaint); glutReshapeFunc(onResize); glutTimerFunc(1000/FRAMES_PER_SECOND,onTimeSlice,1000/FRAMES_PER_SECOND); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glutMainLoop(); } }