// hlRubber2.cpp Sandy Hill Oct. 22, 1998, for ECE660 // test rubber banding and rubber rectangling with different colors // also test menuing/sub_menuing #include #include #include //needed for rand() #include //neededfor cos(), sin() #include #include #include //###################### CLASSES ################### //$$$$$$$$$$$$ Point $$$$$$$$$$ class Point{ public: float x, y; Point(){x = y = 0;} Point(float xx, float yy){ x = xx; y = yy;} void set(float xx, float yy){x=xx; y=yy;} void set(Point p){ x = p.x; y = p.y;} }; //$$$$$$$$$$$$$$$$$$$ IntPoint $$$$$$$$$$$$$$4 class IntPoint{ public: int x, y; IntPoint(){ x = y = 0;} IntPoint(int xx, int yy){ x = xx; y = yy;} // constructor void set(int xx, int yy){x = xx; y = yy;} void set(IntPoint p) {x = p.x; y = p.y;} }; //$$$$$$$$ Rect $$$$$$$$$$$ class Rect{ public: float left, top, right, bott; Rect(){ left = top = right = bott = 0;} // default constructor Rect(float ll, float tt, float rr, float bb){left == ll; top = tt; right = rr; bott = bb;} void set(float ll, float tt, float rr, float bb){left == ll; top = tt; right = rr; bott = bb;} void set(Rect r){left = r.left;top = r.top; right = r.right; bott = r.bott;} void set(Point p, Point q) //given two opposite corners of aligned rect { left = min(p.x, q.x); right = max(p.x, q.x); top = max(p.y, q.y); bott = min(p.y, q.y); } }; //$$$$$$$$$$$$ IntRect $$$$$$$$$$$ class IntRect{ public: int left, top, right, bott; void set(int ll, int tt, int rr, int bb){left = ll; top = tt; right = rr; bott = bb;} void set(IntRect r){left = r.left;top = r.top; right = r.right; bott = r.bott;} void print(){ cout << "IntRect: " << left << " " << top << " " << right << " " << bott << endl;} void draw() // draw rectangle { glBegin(GL_LINE_LOOP); glVertex2i(left,top); glVertex2i(right, top); glVertex2i(right,bott); glVertex2i(left, bott); glEnd(); glFlush(); } void drawDiag() // draw diagonal : good for rubber banding { glBegin(GL_LINES); glVertex2i(left,top); glVertex2i(right,bott); glEnd(); } }; //<<<<<<<<<<<<<<<<<<<<<<<<<<< Canvas class definition >>>>>>>>>>> class Canvas { private: int screenWidth, screenHeight; Point CP; // current position in world public: Canvas(){screenWidth = 640; screenHeight = 480; CP.set(0,0);};// constructor void lineTo(float x, float y){ glBegin(GL_LINES); glVertex2f((GLfloat)CP.x, (GLfloat)CP.y); CP.x = x; CP.y = y; glVertex2f((GLfloat)CP.x, (GLfloat)CP.y); glEnd(); glFlush(); } void lineTo(Point p){lineTo(p.x,p.y);} // convenient interface void getScreen(int& wid, int& ht){wid = screenWidth; ht = screenHeight;} int getScreenHeight(){return screenHeight;} int getScreenWidth(){ return screenWidth;} void setScreen(int w, int h){ screenWidth = w;screenHeight = h;} void moveTo(float x, float y){CP.set(x,y);} void moveTo(Point p){moveTo(p.x, p.y);} void line(Point a, Point b) {moveTo(a); lineTo(b);} void setWindow(Rect win) { // tell openGL this window setWindow(win.left, win.top, win.right, win.bott); } void setWindow(float left, float top, float right, float bott) { //tell openGL this window glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(left, right, bott, top); } void restoreFull() { setWindow(0, screenHeight, screenWidth, 0); setViewport(0, screenHeight, screenWidth, 0); } void setViewport(IntRect vp) { glViewport(vp.left,vp.bott,vp.right - vp.left, vp.top - vp.bott); } void setViewport(int left, int top, int right, int bott) { glViewport(left, bott, right - left, top - bott); } void drawDot(Point p) { glBegin(GL_POINTS); glVertex2f(p.x, p.y);glEnd(); } }; // end of class Canvas //############################ GLOBALS ######################## Canvas cvs; // global canvas object enum Modes{picMode,lineMode,rubberMode}theMode = picMode; IntRect rubber, rubLine; //############################################################# //<<<<<<<<<<<<<<<<<<<<<<< rosette >>>>>>>>>>>>>>>>>>>> void rosette(int N, float radius) { #define MaxNum 97 // can draw up to 97 vertex rosette Point pt[MaxNum]; // vertices of the N-gon float angle = 2 * 3.14159265 / N; if(N < 3 || N >= MaxNum) return; for (int j = 0; j < N; j++) // create the vertices pt[j].set(radius * cos(angle * j), radius * sin(angle * j)); for(int i = 0; i < N -1;i++) for(int j = i+1; j < N ; j++) cvs.line(pt[i],pt[j]); } //<<<<<<<<<<<<<<<<<<<<<< drawSierpinski >>>>>>>>>>>>>>>>>>>. void drawSierpinski(void) { Point T[3]; glPointSize(2.0f); // point size is 2 T[0].set(0,0); // corners of triangle T[1].set(cvs.getScreenWidth()/2, cvs.getScreenHeight()); T[2].set(cvs.getScreenWidth(), 0); Point p(T[rand()%3]); // choose initial point for(int i=0; i < 50000; i++) { int index = rand() %3; // random in range 0,1,2 p.set((p.x + T[index].x)/2, (p.y + T[index].y)/2); cvs.drawDot(p); } glFlush(); } //<<<<<<<<<<<<<<<<<<<<<<<<< myMouse >>>>>>>>>>>>>>>>>>>>>>>> void myMouse(int button, int state, int mx, int my) { IntPoint s(mx,cvs.getScreenHeight() - my); // mouse pt in screen coord's if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { switch(theMode) { case rubberMode: glEnable(GL_COLOR_LOGIC_OP); cvs.restoreFull(); rubber.set(s.x, s.y, s.x, s.y); break; case lineMode: glEnable(GL_COLOR_LOGIC_OP); cvs.restoreFull(); rubLine.set(s.x,s.y,s.x,s.y); break; case picMode: glutPostRedisplay(); break; } } if(button == GLUT_LEFT_BUTTON && state == GLUT_UP) glDisable(GL_COLOR_LOGIC_OP); } //<<<<<<<<<<<<<<<<<<<<<<<<< mouseMove >>>>>>>>>>>>>>>>> void mouseMove(int mx, int my) { IntPoint s(mx, cvs.getScreenHeight() - my); // mouse pt in screen coord's switch(theMode) { case rubberMode: // do this when mouse moves in rubber mode rubber.draw(); //erase old rubber.right = s.x; rubber.bott = s.y; // new opposite corner rubber.draw(); // draw new break; case lineMode: rubLine.drawDiag(); //erase old rubLine.right = s.x; rubLine.bott = s.y; // new oppposite corner rubLine.drawDiag(); //draw new break; } } //<<<<<<<<<<<<<<<<<<<<<<<< myKeys >>>>>>>>>>>>>>>>>>>>>> void myKeys(unsigned char key, int x, int y) { switch(key) { case 27: exit(0); //escape key case 'r':cvs.setWindow(-1, 1, 1, -1); cvs.setViewport(0, 200, 200, 0); rosette(17,1.0); cvs.restoreFull(); break; } } // end of myKeys //<<<<<<<<<<<<<<<<<<<<<<<<<< myReshape >>>>>>>>>>>>>>>>>>> void myReshape(int w, int h) { cvs.setScreen(w,h); cvs.restoreFull(); glutPostRedisplay(); } //<<<<<<<<<<<<<<<<<<<<<<< display >>>>>>>>>>>>>>>>>>>>>>>>>> void display(void) { static int firstTime = 1; if(firstTime) // clear screen upon start-up { glClear(GL_COLOR_BUFFER_BIT); firstTime = 0; } cvs.setWindow(-4, 4, 4, -4); cvs.setViewport(100, 200, 200, 100); rosette(13, 4.0); } //<<<<<<<<<<<<<<<<<<<<< myMenu >>>>>>>>>>>>>>> void myMenu(int id) { // main menu switch(id){ case 1: cvs.setWindow(-1, 1, 1, -1); cvs.setViewport(300, 400, 600,100); rosette(17,1.0); cvs.restoreFull();break; case 2: cvs.setWindow(-1, 1, 1, -1); cvs.setViewport(10, 210, 210, 10); rosette(9,1.0); cvs.restoreFull();break; case 3: cvs.restoreFull();drawSierpinski(); break; case 4: glClear(GL_COLOR_BUFFER_BIT); break; case 5: exit(0); } } //<<<<<<<<<<<<<<<<<<<<<< subMenuCallback >>>>>>>>>>>>>>>>>>>>>>> void subMenuCallback(int id) { switch(id) { // choose drawing color case 1: glColor3f(0, 1.0f,0); break; // green case 2: glColor3f(0, 0, 1.0f); break; // blue case 3: glColor3f(1.0f,0, 0); break; // red case 4: glColor3f(0, 0, 0); break; // black case 5: glColor3f(1.0f,1.0f,1.0f); break; // white case 6: glColor3ub(0X55,0XAA,0Xcc); break; //r = 01010101, g = 10101010, b = 11001100 } } //<<<<<<<<<<<<<<<<<<<<<< modeSelectCallback >>>>>>>>>>>>>>> void modeSelectCallback(int id) { switch(id) { //choose drawing mode case 1: theMode = picMode; break; case 2: theMode = lineMode; break; case 3: theMode = rubberMode; break; } } //<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void main(int argc, char **argv) { int scrnWid, scrnHt; glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); cvs.getScreen(scrnWid,scrnHt); glutInitWindowSize(scrnWid, scrnHt); glutInitWindowPosition(30, 30); glutCreateWindow("testing rubber banding and rubber rectangles"); int mySubMenu1 = glutCreateMenu(subMenuCallback); //define submenu glutAddMenuEntry("green",1); glutAddMenuEntry("blue", 2); glutAddMenuEntry("red", 3); glutAddMenuEntry("black",4); glutAddMenuEntry("white",5); glutAddMenuEntry("hex", 6); int modeChoosemenu = glutCreateMenu(modeSelectCallback); //define another one glutAddMenuEntry("draw mode",1); glutAddMenuEntry("rubber band mode",2); glutAddMenuEntry("rubber rectangle mode",3); glutCreateMenu(myMenu); //define main menu glutAddMenuEntry("17-rosette",1); glutAddMenuEntry("9-rosette",2); glutAddMenuEntry("Sierpinski",3); glutAddMenuEntry("clear screen",4); glutAddSubMenu("choose color",mySubMenu1); glutAddSubMenu("choose mode",modeChoosemenu); glutAddMenuEntry("quit",5); glutAttachMenu(GLUT_RIGHT_BUTTON); glClearColor(0.9f, 0.9f, 0.9f, 0.0); // background is greenish glClear(GL_COLOR_BUFFER_BIT); glLogicOp(GL_XOR); // must be enabled to operate glColor3f(1.0f,1.0f,0.5f); // initial drawing color glutKeyboardFunc(myKeys); glutMouseFunc(myMouse); glutMotionFunc(mouseMove); glutDisplayFunc(display); glutReshapeFunc(myReshape); glutMainLoop(); }