Search code examples
c++openglglut

How to avoid restarting the polygon when redraw?


I'm writing the program that continuously draws a polygon until the user clicks right-click, but when I continue to draw something else on the screen the polygon disappears, how can I avoid this? This is my program:

float mouseX, mouseY;
vector<float> vecX(40);
vector<float> vecY(40);
int numPoints = 0;
int closed = 0;

void mouse(int button, int state, int x, int y)
{
    mouseX = x;
    mouseY = y;

    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        if (closed || numPoints > 40)
             numPoints = 0;
        closed = 0;
        vecX[numPoints] = mouseX;
        vecY[numPoints] = mouseY;
        numPoints++;
    }
    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        closed = 1;
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    if (numPoints)
    {
        glBegin(GL_LINE_STRIP);
        for (int i = 0; i < numPoints; ++i)
            glVertex2f(vecX[i], vecY[i]);
        if (closed)
            glVertex2f(vecX[0], vecY[0]);
        else
            glVertex2f(mouseX, mouseY);
        glEnd();
    }
    glFlush();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(600, 400);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("Testing");
    gluOrtho2D(0, 600, 400, 0);

    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMainLoop();
}

The vecX and vecY are used to store the coordinate of the mouse click.


Solution

  • Once a polyline is finished, you need to store it to a container. Use a std::vector of polylines. The type of a polyline is std::vector<float>. At the begin, just 1 empty polyline is in the container:

    std::vector<std::vector<float>> polylines(1);
    

    When you left-click, a new vertex coordinate is added to the last polyline in the container. When you right-click, a new polyline is added to the container:

    void mouse(int button, int state, int x, int y)
    {
        mouseX = x;
        mouseY = y;
    
        if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        {
            polylines.back().push_back(mouseX);
            polylines.back().push_back(mouseY);
        }
        if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        {
            polylines.push_back(std::vector<float>());
        }
    }
    

    Draw the polylines in nested loops:

    void display()
    {
        glClear(GL_COLOR_BUFFER_BIT);
    
        for (auto i=0; i < polylines.size(); ++ i)
        {
            bool is_last = i == polylines.size() - 1;
            const auto& polyline = polylines[i];
            glBegin(is_last ? GL_LINE_STRIP : GL_LINE_LOOP);
            for (auto j = 0; j < polyline.size(); j += 2)
                glVertex2f(polyline[j], polyline[j+1]);
            if (is_last)
                glVertex2f(mouseX, mouseY);
            glEnd();
        }
    
        glutSwapBuffers();
    }