Search code examples
c++openglgraphicsglut

OpenGL drawing rectangle with mouse drag?


I'm trying to draw a shape like you do with the tool in paint, where you drag it and when you release the mouse and it will draw the shape.

Currently what my program does is that if you click it will come up with the rubber band to show you what the shape looks like, but nothing gets drawn when you release the mouse click.

The relevant code is as follows:

// this function draws the list of objects
void drawList() {
    glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
    if (list[numObj].t==1){
        glBegin(GL_LINE_LOOP);
        glVertex2i(list[numObj].x1, list[numObj].y1);
        glVertex2i(list[numObj].x1, list[numObj].y2);
        glVertex2i(list[numObj].x2, list[numObj].y2);
        glVertex2i(list[numObj].x2, list[numObj].y1);
        glEnd();
    }
    glFlush();
}

void mouseDraw(GLint button, GLint action, GLint xMouse, GLint yMouse) {
    if (type == 1){
        if (button == GLUT_LEFT_BUTTON) {
            if (action == GLUT_DOWN && button != GLUT_RIGHT_BUTTON && numObj < MaxNumObj -1) {
                list[numObj].x1 = xMouse;
                list[numObj].y1 = yMouse;
                list[numObj].x2 = xMouse;
                list[numObj].y2 = yMouse;
                list[numObj].t = type;
                list[numObj].s = 2;
                list[numObj].r = red;
                list[numObj].g = green;
                list[numObj].b = blue;
                glutPostRedisplay();

            } else if (action == GLUT_UP && button != GLUT_RIGHT_BUTTON) {
                list[numObj].x2 = xMouse;
                list[numObj].y2 = yMouse;
                list[numObj].s = style;
                numObj++;
                glutPostRedisplay();
            }
        }
    }
}

// this function takes the mouse position while moving mouse, use this for intermediate drawing
void Motion(GLint x, GLint y) {
    // add the (x, y) coordinates of the second point to the intermediate rectangle
    list[numObj].x2 = x;
    list[numObj].y2 = y;
    // redisplay the object list after the above insertion. It will give a rubber band effect

    glutPostRedisplay ( );
}

relevant main code:

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(100, 100);
glutInitWindowSize(winWidth, winHeight);
glutCreateWindow("SimpleDraw Example");

init();

// register call back funtions
glutDisplayFunc(drawList);
glutReshapeFunc(winReshapeFcn);
glutMouseFunc(mouseDraw);
glutMotionFunc(Motion);

//add right click menu
glutAttachMenu(GLUT_RIGHT_BUTTON);

glutMainLoop();

Please ignore the .s .t and stuff, the only relevant things should be the x and ys.

Here are some gifs to show my current outcome and the desired outcome:

my current program
my current program

what I want it to do
what I want it to do


Solution

  • You have to draw all the rectangles, that you have stored in your list, from the first till the last:

    void drawList() {
    
        glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
    
        for( size_t i = 0; i <= numObj; ++ i ) {
    
            if (list[numObj].t==1){
    
                glBegin(GL_LINE_LOOP);
                glVertex2i(list[i].x1, list[i].y1);
                glVertex2i(list[i].x1, list[i].y2);
                glVertex2i(list[i].x2, list[i].y2);
                glVertex2i(list[i].x2, list[i].y1);
                glEnd();
            }
        }
        glFlush();
    }