//Origami Simulator C++ version Sept 3rd in 2013 #include #include "glut.h" #include "geometry.h" // vector.h and matrix.h are included in geometry.h #include "image.h" // color.h is included in image.h #include "keystate.h" #include "viewer.h" KeyState Key, Special; Viewer View; #include "fold.h" #include "vertex.h" #include "edge.h" #include "faceproperty.h" #include "face.h" #include "facegroup.h" #include "stage.h" #include "adjust.h" #include "origami.h" _Origami Origami( "origami.txt" ); class cursor3D{ public: int x; int y; double z; cursor3D(){ x = y = 0; z = 0.0; } void set( int a, int b ){ x = a; y = b; } void set( int a, int b, double c ){ x = a; y = b; z = c; } } Cursor3D; class state{ public: bool inFolding; bool inAnimation; bool inRotation; bool drawAxis; int fps; state(){ inFolding = false; inAnimation = false; inRotation = false; drawAxis = false; fps = 60; } } State; void reshape( int w, int h ){ glViewport( 0, 0, w, h ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 45.0, GLdouble(w)/GLdouble(h), 1.0, 10000.0 ); View.lookAt( 0, 0, 40, 0, 0, 0, 0, 1, 0 ); //eye, target, up } void display(){ glClear( GL_COLOR_BUFFER_BIT ); Origami.draw( View.eyePosition() ); if( State.drawAxis ){ glBegin(GL_LINES); glColor3ub(255, 0, 0); glVertex3d(-20.0,0.0,0.0); glColor3ub(255,255,255); glVertex3d( 0.0,0.0,0.0); glVertex3d(0.0,0.0,0.0); glColor3ub(255, 0, 0); glVertex3d( 20.0,0.0,0.0); glColor3ub( 0,255, 0); glVertex3d(0.0,-20.0,0.0); glColor3ub(255,255,255); glVertex3d(0.0, 0.0,0.0); glVertex3d(0.0,0.0,0.0); glColor3ub( 0,255, 0); glVertex3d(0.0, 20.0,0.0); glColor3ub( 0, 0,255); glVertex3d(0.0,0.0,-20.0); glColor3ub(255,255,255); glVertex3d(0.0,0.0, 0.0); glVertex3d(0.0,0.0,0.0); glColor3ub( 0, 0,255); glVertex3d(0.0,0.0, 20.0); glEnd(); } Origami.drawAdjust(); glutSwapBuffers(); } void timer(int value) { bool redisplay = false; // modify view double angle = 1.5/double(State.fps); double delta = 1.5/double(State.fps); double deltaZ = 0.015/double(State.fps); double scale = 1.0+1.5/double(State.fps); if( Special.down(GLUT_KEY_LEFT) ) { View.twistLeft( angle ); redisplay=true; } if( Special.down(GLUT_KEY_RIGHT) ) { View.twistRight( angle ); redisplay=true; } if( Special.down(GLUT_KEY_UP) ) { View.zoom( 1.0/scale ); redisplay=true; } if( Special.down(GLUT_KEY_DOWN) ) { View.zoom( scale ); redisplay=true; } if( Key.down('4') || State.inRotation ) { View.rotateLeft( angle ); redisplay=true; } // need numlock on if( Key.down('6') ) { View.rotateRight( angle ); redisplay=true; } if( Key.down('8') ) { View.rotateUp( angle ); redisplay=true; } if( Key.down('2') ) { View.rotateDown( angle ); redisplay=true; } if( Key.down('1') ) { View.slideLeft( delta ); redisplay=true; } if( Key.down('3') ) { View.slideRight( delta ); redisplay=true; } if( Key.down('5') ) { View.lookAt( 0, 0, 40, 0, 0, 0, 0, 1, 0 ); redisplay=true; } // renew folding if( State.inFolding ){ bool inBending = false; if( Key.down('m') ){ Cursor3D.z -= deltaZ; inBending = true; }else if( Key.down('n') ){ Cursor3D.z += deltaZ; } Vector destination; View.window2world( Cursor3D.x, Cursor3D.y, Cursor3D.z, destination ); Origami.moveVertex( destination, View.eyePosition(), inBending ); View.world2window( destination, Cursor3D.x, Cursor3D.y, Cursor3D.z ); redisplay = true; }else if( State.inAnimation ){ if( Origami.play( State.fps ) ) State.inAnimation = false; redisplay = true; } if(redisplay) glutPostRedisplay(); glutTimerFunc(1000/State.fps, timer , 0); } void mouse( int button, int state, int x, int y ){ if( button == GLUT_LEFT_BUTTON && !State.inAnimation && !State.inRotation ){ if( state == GLUT_DOWN ){ //pick a vertex Line line = View.cursorLine( x, y ); Vector destination = Origami.pickVertex( View.cursorLine( x, y ) ); View.world2window( destination, Cursor3D.x, Cursor3D.y, Cursor3D.z ); glutWarpPointer( Cursor3D.x, Cursor3D.y ); State.inFolding = true; }else{ // GLUT_UP Origami.releaseVertex(); State.inFolding = false; } } } void motion( int x, int y ){ if( State.inFolding ) Cursor3D.set(x, y); } void menu( int n ){ if(State.inFolding) return; switch( n ){ case 1: exit(0); case 2: State.inRotation = !State.inRotation; break; case 3: State.drawAxis = !State.drawAxis; break; case 4: Origami.save( "default.ori" ); break; case 5: Origami.load( "default.ori" ); break; case 6: if(!State.inFolding && !State.inAnimation){ Origami.save( "fold.tmp" ); Origami.reset( "fold.tmp" ); State.inAnimation = true; }else{ Origami.load( "fold.tmp" ); State.inAnimation = false; } break; case 7: Origami.reset(); break; case 8: Origami.reset( 0 ); break; } glutPostRedisplay(); } void keyboard( unsigned char key, int x, int y ){ Key.press(key); switch( key ){ case 'q': menu(1); break; case 'r': menu(2); break; case 'a': menu(3); break; case 'z': menu(7); break; case 'i': menu(8); break; } glutPostRedisplay(); } void keyboardUp( unsigned char key, int x, int y ){ Key.release(key); } void special( int key, int x, int y ){ Special.press(key); } void specialUp( int key, int x, int y ){ Special.release(key); } int main( int argc, char **argv ){ glutInit( &argc, argv ); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA ); glutInitWindowSize( 640, 480 ); glutCreateWindow( "Origami Simulation C++" ); glClearColor( 0.0, 0.0, 0.0, 1.0 ); glutReshapeFunc( reshape ); glutDisplayFunc( display ); glutTimerFunc(1000/State.fps , timer , 0); glutMouseFunc( mouse ); glutMotionFunc( motion ); glutKeyboardFunc( keyboard ); glutKeyboardUpFunc( keyboardUp ); glutSpecialFunc( special ); glutSpecialUpFunc( specialUp ); glutCreateMenu( menu ); glutAddMenuEntry( "Quit (Q)", 1 ); glutAddMenuEntry( "Rotation On/Off (R)", 2 ); glutAddMenuEntry( "Coordinates Axis On/Off (A)", 3 ); glutAddMenuEntry( "Save Folding", 4 ); glutAddMenuEntry( "Load Folding", 5 ); glutAddMenuEntry("Animation On/Off", 6); glutAddMenuEntry("Undo a Fold (Z)", 7); glutAddMenuEntry("Initialize Folds (I)", 8); glutAttachMenu( GLUT_RIGHT_BUTTON ); glutMainLoop(); return 0; }