You need to enable JavaScript to run this app. GLUT绘制多边形时如何避免重绘导致已绘制的多边形消失?
优惠活动
大模型
产品
解决方案
定价
更多

GLUT绘制多边形时如何避免重绘导致已绘制的多边形消失?

问题根因
  • OpenGL即时渲染模式下,glClear会清空整个画布的所有内容,所有图形必须在每次display回调中重新调用绘制命令生成,不存在“一次性绘制后永久保留在画布上”的效果。
  • 现有代码的全局变量仅支持单个正在绘制的多边形的临时存储,没有任何用于持久化保存已闭合多边形的存储结构:
    • 鼠标左击开启新多边形时,代码会直接执行numPoints = 0,直接覆盖清空上一个多边形的顶点坐标数据,从数据层面就把之前的多边形丢失了
    • display函数每次清屏后,仅能读取当前临时多边形的坐标做绘制,没有已存储的多边形数据可以用来重绘,清屏后自然看不到之前的图形
  • 原代码使用固定容量40的数组存坐标,不仅单个多边形顶点数超过40就会出错,也完全没有多图形存储的扩展能力
修复方案
  • 拆分数据存储结构:划分为「已完成多边形的持久化存储区」和「当前正在绘制的多边形临时存储区」两部分
    • 持久化区用嵌套动态数组,按列表顺序存储每一个已闭合多边形的所有顶点坐标
    • 临时区保留原来的鼠标位置、当前顶点数、闭合状态变量,用来处理实时绘制的预览效果
  • 修改鼠标回调逻辑:右键点击闭合当前多边形时,先把当前临时区的顶点数据完整拷贝到持久化存储区,再清空临时区准备绘制下一个多边形,不要等开启新多边形时才丢弃旧数据
  • 修改渲染流程:每次清屏后,先遍历持久化存储区把所有已完成的多边形全部重绘,再绘制当前正在编辑的临时多边形的预览线
  • 可选优化:把原单缓冲模式改为双缓冲,避免多图形绘制时的画面闪烁,只需把初始化时的GLUT_SINGLE换成GLUT_DOUBLE,渲染完成后用glutSwapBuffers()代替glFlush()即可
核心修改代码参考
// 持久化存储区:保存所有已完成的多边形,每一项是一个多边形的全部X/Y坐标
vector<vector<float>> completedPolyX;
vector<vector<float>> completedPolyY;
// 临时存储区:当前正在绘制的多边形的相关变量
float mouseX, mouseY;
vector<float> currentX, currentY;
int currentPointCount = 0;
bool isCurrentClosed = false;

void mouse(int button, int state, int x, int y)
{
    mouseX = x;
    mouseY = y;
    // 左键添加顶点
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        // 上一个多边形已闭合/点数超限时,清空临时区准备开启新多边形
        if (isCurrentClosed || currentPointCount > 1000)
        {
            currentX.clear();
            currentY.clear();
            currentPointCount = 0;
            isCurrentClosed = false;
        }
        currentX.push_back(mouseX);
        currentY.push_back(mouseY);
        currentPointCount++;
    }
    // 右键闭合当前多边形
    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN && currentPointCount >=3)
    {
        // 把当前多边形存入持久化存储区,永久保留数据
        completedPolyX.push_back(currentX);
        completedPolyY.push_back(currentY);
        isCurrentClosed = true;
    }
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    // 先绘制所有已完成的多边形
    if (!completedPolyX.empty())
    {
        glBegin(GL_LINE_LOOP);
        for (int polyIdx = 0; polyIdx < completedPolyX.size(); polyIdx++)
        {
            for (int pointIdx = 0; pointIdx < completedPolyX[polyIdx].size(); pointIdx++)
            {
                glVertex2f(completedPolyX[polyIdx][pointIdx], completedPolyY[polyIdx][pointIdx]);
            }
        }
        glEnd();
    }
    // 再绘制当前正在编辑的多边形预览
    if (currentPointCount > 0)
    {
        glBegin(GL_LINE_STRIP);
        for (int i = 0; i < currentPointCount; i++)
        {
            glVertex2f(currentX[i], currentY[i]);
        }
        // 未闭合时,连线到当前鼠标位置做实时预览
        if (!isCurrentClosed)
        {
            glVertex2f(mouseX, mouseY);
        }
        glEnd();
    }
    // 使用双缓冲模式时,将glFlush()替换为glutSwapBuffers()
    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();
}

内容的提问来源于stack exchange,提问作者user15754100

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 17:57:04