绘制新矩形时如何避免重新启动矩形?

时间:2021-05-02 04:26:32

标签: c++ opengl glut

我试图在这个程序中绘制多个矩形,但是每当我绘制一个新的矩形时,旧的矩形就会消失,我怎样才能在不丢失旧矩形的情况下绘制一个新的矩形?这是我的程序:

struct Position
{
    Position() : x(0), y(0) {}
    float x, y;
};
Position start, finish;

void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        start.x = finish.x = x;
        start.y = finish.y = y;
    }
    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
    {
        finish.x = x;
        finish.y = y;
    }
    glutPostRedisplay();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_QUADS);
    glVertex2f(start.x, start.y);
    glVertex2f(finish.x, start.y);
    glVertex2f(finish.x, finish.y);
    glVertex2f(start.x, finish.y);
    glEnd();
    
    glFlush();
}

2 个答案:

答案 0 :(得分:3)

创建一个类型来存储一个矩形:

struct Rect
{
    Rect(const Position& s, const Position& f) 
        : start(s), finish(f) {}
    Position start;
    Position finish;
};

使用类型为 std::vector<Rect> 的容器来存储矩形

#include <vector>
std::vector<Rect> rects;

当一个矩形完成后,将其添加到容器中:

void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        start.x = finish.x = x;
        start.y = finish.y = y;
    }
    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
    {
        finish.x = x;
        finish.y = y;
        rects.emplace_back(start, finish);
        start = finish;
    }
    glutPostRedisplay();
}

在一个循环中绘制所有矩形:

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_QUADS);
    for (auto& rect : rects)
    {
        glVertex2f(rect.start.x, rect.start.y);
        glVertex2f(rect.finish.x, rect.start.y);
        glVertex2f(rect.finish.x, rect.finish.y);
        glVertex2f(rect.start.x, rect.finish.y);
    }
    glVertex2f(start.x, start.y);
    glVertex2f(finish.x, start.y);
    glVertex2f(finish.x, finish.y);
    glVertex2f(start.x, finish.y);
    glEnd();
    
    glFlush();
}

此外,您还可以通过实现 glutMotionFunc 回调获得不错的绘图效果:

void motion(int x, int y)
{
    finish.x = x;
    finish.y = y;
    glutPostRedisplay();
}
int main(int argc, char** argv)
{
    // [...]

    glutMotionFunc(motion);

    // [...]
}


GL_LINE_LOOP Primitive 的实现:

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    for (auto& rect : rects)
    {
        glBegin(GL_LINE_LOOP);
        glVertex2f(rect.start.x, rect.start.y);
        glVertex2f(rect.finish.x, rect.start.y);
        glVertex2f(rect.finish.x, rect.finish.y);
        glVertex2f(rect.start.x, rect.finish.y);
        glEnd();
    }

    glBegin(GL_LINE_LOOP);
    glVertex2f(start.x, start.y);
    glVertex2f(finish.x, start.y);
    glVertex2f(finish.x, finish.y);
    glVertex2f(start.x, finish.y);
    glEnd();
    
    glFlush();
}

答案 1 :(得分:2)

请注意,简单地删除 glClear 会导致您绘制的所有矩形持续在屏幕上 - 您将无法例如只删除其中之一。它还可能导致窗口的初始内容包含一些垃圾像素(尽管这可以通过在程序开始时执行 glClear 来解决)。

一个典型的解决方案是,正如 jackw11111 建议的那样,将所有矩形坐标存储在某个数据结构中(std::vector 是一个完美的选择,如果你使用 C++),并在你的 display 函数中您首先执行 glClear,然后遍历所有矩形并一个一个地绘制它们。类似的东西

struct Rectangle
{
    Position start, finish;
};
std::vector<Rectangle> rectangles;

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_QUADS);
    for (Rectangle const & r : rectangles)
    {
        glVertex2f(r.start.x, r.start.y);
        glVertex2f(r.finish.x, r.start.y);
        glVertex2f(r.finish.x, r.finish.y);
        glVertex2f(r.start.x, r.finish.y);
    }
    glEnd();
}

顺便说一下,您几乎绝对不需要glFlush

相关问题