绘制新矩形时如何避免重新启动矩形?
How to avoid restarting the rectangle when drawing a new one?
我想在这个程序中绘制多个矩形,但是每当我绘制一个新矩形时,旧矩形就消失了,如何在不丢失旧矩形的情况下绘制新矩形?这是我的程序:
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();
}
请注意,简单地删除 glClear
会导致 所有 个您曾经绘制的矩形持续显示在屏幕上 - 您将无法,例如只删除其中一个。它还可能导致 window 的初始内容包含一些垃圾像素(尽管这可以通过在程序开始时执行 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
。
创建一个类型来存储一个矩形:
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();
}
我想在这个程序中绘制多个矩形,但是每当我绘制一个新矩形时,旧矩形就消失了,如何在不丢失旧矩形的情况下绘制新矩形?这是我的程序:
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();
}
请注意,简单地删除 glClear
会导致 所有 个您曾经绘制的矩形持续显示在屏幕上 - 您将无法,例如只删除其中一个。它还可能导致 window 的初始内容包含一些垃圾像素(尽管这可以通过在程序开始时执行 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
。
创建一个类型来存储一个矩形:
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();
}