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
相关产品推荐
相关产品推荐

