Open Scene Graph事件处理

OSG 的事件处理系统是其交互功能的核心,用于处理用户输入(键盘、鼠标等)和系统事件。以下是 OSG 事件处理的全面介绍:

1. 事件处理基本架构

OSG 的事件处理基于观察者模式,主要包含以下组件:

  • 事件队列(EventQueue):存储接收到的原始输入事件

  • 事件处理器(GUIEventHandler):处理事件的接口

  • 操作器(Manipulator):预定义的高级交互行为(如轨迹球操作器)

2. 核心类介绍

2.1 osgGA::GUIEventHandler

所有事件处理器的基类,主要方法:

virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);

2.2 osgGA::EventQueue

负责收集和分发事件,通常由视图器(Viewer)内部管理。

2.3 osgGA::GUIEventAdapter

封装了各种事件类型和参数,如:

  • 事件类型(EventType):KEYDOWN、KEYUP、PUSH、RELEASE等

  • 键盘码(KeySymbol)

  • 鼠标位置(X,Y)

  • 鼠标按钮(MouseButtonMask)

3. 事件处理流程

  1. 操作系统输入 → 2. OSG EventQueue → 3. GUIEventHandler → 4. 场景响应

4. 实现自定义事件处理器

示例代码:

class MyEventHandler : public osgGA::GUIEventHandler {
public:
    bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override {
        switch(ea.getEventType()) {
            case osgGA::GUIEventAdapter::KEYDOWN:
                if(ea.getKey() == 'a') {
                    // 处理A键按下
                    return true; // 事件已处理
                }
                break;
            case osgGA::GUIEventAdapter::PUSH:
                if(ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) {
                    // 处理鼠标左键点击
                    return true;
                }
                break;
        }
        return false; // 事件未处理,传递给其他处理器
    }
};

// 添加到视图器
viewer.addEventHandler(new MyEventHandler());

5. 常用预定义操作器

  • TrackballManipulator:轨迹球操作器(默认)

  • FlightManipulator:飞行操作器

  • DriveManipulator:驾驶操作器

  • TerrainManipulator:地形适配操作器

使用示例:

viewer.setCameraManipulator(new osgGA::TrackballManipulator());

6. 高级主题

6.1 多视图事件处理

通过设置ViewEventQueue可以实现多视图独立事件处理。

6.2 事件处理优先级

通过setAllowThrow()等方法可以控制操作器的行为特性。

6.3 自定义操作器

继承osgGA::MatrixManipulator可以实现完全自定义的交互方式。

7. 调试技巧

  • 使用osgViewer::ViewerEventHandlers添加默认调试处理器

  • 查看事件参数:

    osg::notify(osg::INFO) << "Event: " << ea.getX() << "," << ea.getY();

8. 性能考虑

  • 避免在事件处理器中进行复杂计算

  • 需要频繁更新的操作考虑使用回调(Callback)机制

  • 使用setHandled(true)标记已处理事件,防止重复处理