You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL ARToolkit中基于按键事件调用指定绘制函数的实现问询

没问题,我来帮你搞定这个按键交互的需求!其实核心思路很简单:用一个状态变量跟踪当前要绘制的内容,在键盘事件里更新这个状态,最后在主循环里根据状态调用对应的绘制函数就行。下面是完整的实现方案:

1. 定义状态控制变量

首先我们需要一个变量来记录当前的绘制模式,用枚举类型会比单纯用整数更清晰:

// 定义绘制模式的枚举类型
typedef enum {
    DRAW_NONE,          // 初始状态,什么都不画
    DRAW_COMPONENTS,    // 绘制组件模式
    DRAW_SIGNALS        // 绘制信号模式
} DrawMode;

// 静态全局变量,用来存储当前绘制模式
static DrawMode currentDrawMode = DRAW_NONE;

2. 完善keyEvent键盘回调函数

接下来我们把按键逻辑补全,当用户按下1或2时切换绘制模式,同时保留ESC退出的常规操作:

void keyEvent(unsigned char key, int x, int y) {
    switch(key) {
        case '1':
            currentDrawMode = DRAW_COMPONENTS;
            printf("已切换到【绘制组件】模式\n");
            break;
        case '2':
            currentDrawMode = DRAW_SIGNALS;
            printf("已切换到【绘制信号】模式\n");
            break;
        case 27: // ESC键的ASCII码是27
            exit(0); // 退出程序
            break;
        default:
            printf("未知按键!按1绘制组件,按2绘制信号,ESC键退出\n");
            break;
    }

    // 触发窗口重绘(GLUT环境下需要调用这个函数刷新画面)
    glutPostRedisplay();
}

注意:如果是ARToolKit结合GLUT开发,一定要在初始化阶段注册这个键盘回调函数,否则按键事件不会被触发:

// 初始化GLUT时添加这行代码
glutKeyboardFunc(keyEvent);

3. 修改主循环的绘制逻辑

把原来直接调用两个绘制函数的逻辑,改成根据currentDrawMode来选择调用:

void MainLoop(void) {
    // 保留你原来的AR跟踪逻辑,获取trans1和trans2矩阵
    ARdouble trans1[3][4], trans2[3][4];
    // (这里假设你已经通过ARToolKit的arGetTransMat等函数获取了跟踪矩阵)

    // OpenGL常规渲染准备:清屏、设置投影和模型视图矩阵
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadMatrixd(projectionMatrix); // 替换成你的投影矩阵变量
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // 根据当前绘制模式调用对应的函数
    switch(currentDrawMode) {
        case DRAW_COMPONENTS:
            // 传入你需要的RGB颜色值,这里用红色示例
            drawComponents(trans1, trans2, 255, 0, 0);
            break;
        case DRAW_SIGNALS:
            // 传入你需要的RGB颜色值,这里用绿色示例
            drawSignals(trans1, trans2, 0, 255, 0);
            break;
        case DRAW_NONE:
            // 初始状态可以打印提示,或者绘制一些引导信息
            printf("请按1或2切换绘制模式\n");
            break;
    }

    // 交换缓冲区,完成当前帧渲染
    glutSwapBuffers();
}

额外优化建议

  • 你原来的drawComponents和drawSignals函数里,glTranslatef(0.0f, 0.0f, 0.0f)是无效操作(平移0单位),可以直接删掉,节省一点性能。
  • 如果想要支持同时显示组件和信号,可以把状态改成位掩码的形式,这样用户可以通过按键切换显示/隐藏单个内容:
// 用位掩码定义绘制标记
#define DRAW_COMPONENTS_FLAG (1 << 0)
#define DRAW_SIGNALS_FLAG    (1 << 1)
static unsigned int drawFlags = 0; // 初始什么都不显示

// 修改keyEvent里的逻辑
void keyEvent(unsigned char key, int x, int y) {
    switch(key) {
        case '1':
            drawFlags ^= DRAW_COMPONENTS_FLAG; // 切换组件的显示状态
            printf("组件显示状态:%s\n", (drawFlags & DRAW_COMPONENTS_FLAG) ? "开启" : "关闭");
            break;
        case '2':
            drawFlags ^= DRAW_SIGNALS_FLAG; // 切换信号的显示状态
            printf("信号显示状态:%s\n", (drawFlags & DRAW_SIGNALS_FLAG) ? "开启" : "关闭");
            break;
        case 27:
            exit(0);
            break;
        default:
            printf("按1切换组件显示,按2切换信号显示,ESC退出\n");
            break;
    }
    glutPostRedisplay();
}

// 主循环里的绘制逻辑改成:
if (drawFlags & DRAW_COMPONENTS_FLAG) {
    drawComponents(trans1, trans2, 255, 0, 0);
}
if (drawFlags & DRAW_SIGNALS_FLAG) {
    drawSignals(trans1, trans2, 0, 255, 0);
}

这种方式更灵活,用户可以自由组合显示内容~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:57:44