/* rubber2gl.c rubber band with snap to grid */ /* Draw rectangle. left mouse down=first point */ /* Drag to second point. left mouse up=final point */ /* right mouse changes color of selected figure */ /* show grid and snap to grid G g S s */ #include static int winWidth = 500; static int winHeight = 500; static int tracking = 0; /* left button down, sense motion */ static int startX = 0; static int startY = 0; static int currentX = 0; static int currentY = 0; static int num_fig = 0; /* number of figures to draw */ static int select = 0; /* the currently selected figure index */ static int grid = 1; /* display grid points */ static int snap = 1; /* snap mouse press/release/motion to grid */ static int gridSize = 25; typedef struct{int kind; int x0; int y0; int x1; int y1; float r; float g; float b; float width;} fig; static fig figure[100]; /* list of figures to draw */ void rubberRect(int x0, int y0, int x1 , int y1) { /* can apply to all figures */ /* draw a rubber rectangle, mouse down, tracks mouse */ glLineStipple(1,0xF00F); glEnable(GL_LINE_STIPPLE); glLineWidth(1.0); glColor3f(0.0,0.0,0.0); glBegin(GL_LINE_LOOP); glVertex2f(x0, y0); glVertex2f(x0, y1); glVertex2f(x1, y1); glVertex2f(x1, y0); glEnd(); glDisable(GL_LINE_STIPPLE); } /* one of many possible figures, kind=1 */ void drawRect(fig rect) { /* draw a figure, rectangle */ glLineWidth(rect.width); glColor3f(rect.r, rect.g, rect.b); glBegin(GL_LINE_LOOP); glVertex2f(rect.x0, rect.y0); glVertex2f(rect.x0, rect.y1); glVertex2f(rect.x1, rect.y1); glVertex2f(rect.x1, rect.y0); glEnd(); } void snapxy(int *x, int *y) { int xg, yg; xg = (*x+gridSize/2)/gridSize; yg = (*y+gridSize/2)/gridSize; *x = xg*gridSize; *y = yg*gridSize; } void pick(int x, int y) { int i; float t; if(snap) snapxy(&x, &y); /* search figures in list, select */ for(i=0; ifigure[i].x1) continue; if(figure[i].x1 < figure[i].x0) if(xfigure[i].x0) continue; if(figure[i].y0 < figure[i].y1) if(yfigure[i].y1) continue; if(figure[i].y1 < figure[i].y0) if(yfigure[i].y0) continue; /* select here by just changing color */ figure[select].r = 1.0; figure[select].g = 0.0; select = i; figure[select].r = 0.0; figure[select].g = 1.0; break; } glutPostRedisplay(); } void mouseMotion(int xp, int yn) { int y; /* invert via winHeight */ int x; if(tracking) { y = winHeight-yn; x = xp; if(snap) snapxy(&x, &y); currentX = x; currentY = y; } glutPostRedisplay(); } void startMotion(int x, int y) { tracking = 1; startX = x; startY = y; currentX = x; currentY = y; /* start zero size, may choose to ignore later */ glutPostRedisplay(); } void stopMotion(int x, int y) { tracking = 0; /* no more rubber_rect */ /* save final figure data for 'display' to draw */ currentX = x; currentY = y; figure[num_fig].kind = 1; /* just rectangles here */ figure[num_fig].x0 = startX; figure[num_fig].y0 = startY; figure[num_fig].x1 = currentX; figure[num_fig].y1 = currentY; figure[num_fig].r = 1.0; figure[num_fig].g = 0.0; figure[num_fig].b = 0.0; figure[num_fig].width = 2.0; num_fig++; glutPostRedisplay(); } void mouseButton(int button, int state, int xp, int yn) { int y; /* inverted by winHeight */ int x; y = winHeight-yn; x = xp; if(snap) snapxy(&x, &y); if(button==GLUT_RIGHT_BUTTON && state==GLUT_DOWN) pick(x, y); if(button==GLUT_LEFT_BUTTON) { if(state==GLUT_DOWN) startMotion(x, y); if(state==GLUT_UP) stopMotion (x, y); } } void key(unsigned char key, int x, int y) { if(key=='G') grid = 1; if(key=='g') grid = 0; if(key=='S') snap = 1; if(key=='s') snap = 0; glutPostRedisplay(); } void reshape(int w, int h) { glViewport(0, 0, w, h); winWidth = w; winHeight = h; glutPostRedisplay(); } void display(void) { int i, j; glClear(GL_COLOR_BUFFER_BIT); if(tracking) rubberRect(startX, startY, currentX, currentY); if(grid) { glPointSize(1.0); glColor3f(0.5,0.5,0.5); glBegin(GL_POINTS); for(i=gridSize; i