OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离

OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离

------ 2024-10-02 下午

code review!

文章目录

1.代码图片

运行

复制代码
Mouse button 1 pressed at (100, 200)
Mouse dragged by (50, 50)
Key pressed: 65
Updating camera control

2.分析

类图:
Application -cameraControl: CameraControl* -mouseCallback: MouseCallback -keyCallback: KeyCallback +Application() +setMouseCallback(MouseCallback) +setKeyCallback(KeyCallback) +triggerMouseEvent(MouseEvent) +triggerKeyEvent(KeyEvent) +run() <<interface>> CameraControl +handleMouseEvent(MouseEvent) +handleKeyEvent(KeyEvent) +update() SimpleCameraControl -mousePressed: bool -lastX: double -lastY: double -keys: map +handleMouseEvent(MouseEvent) +handleKeyEvent(KeyEvent) +update() MouseEvent +x: int +y: int +button: int +pressed: bool KeyEvent +key: int

上面的类图展示了代码中主要类的结构和关系:

  • Application 类包含一个 CameraControl 指针和事件回调函数指针,通过 setMouseCallback 和 setKeyCallback 设置事件回调。
  • CameraControl 是一个抽象基类,定义了处理鼠标事件、键盘事件和更新的接口。
  • SimpleCameraControl 继承自 CameraControl,实现了具体的事件处理逻辑。
  • MouseEvent 和 KeyEvent 分别表示鼠标事件和键盘事件的数据结构。

事件处理流程图:
mouseCallback keyCallback 鼠标/键盘事件 Application::triggerMouseEvent/triggerKeyEvent onMouseEvent onKeyEvent SimpleCameraControl::handleMouseEvent SimpleCameraControl::handleKeyEvent

事件处理流程如下:

  1. 应用程序触发鼠标或键盘事件
  2. 事件通过 Application::triggerMouseEvent 或 Application::triggerKeyEvent 分发到对应的全局回调函数
  3. 回调函数 onMouseEvent 或 onKeyEvent 调用 SimpleCameraControl 的对应事件处理函数
  4. SimpleCameraControl 的事件处理函数根据事件数据进行相应的处理

主程序流程图:
main 创建Application对象 设置鼠标回调为onMouseEvent 设置键盘回调为onKeyEvent 调用Application::run 模拟触发鼠标事件 模拟触发键盘事件 调用CameraControl::update

主程序的流程如下:

  1. 创建 Application 对象
  2. 设置鼠标回调函数为 onMouseEvent
  3. 设置键盘回调函数为 onKeyEvent
  4. 调用 Application::run
    • 模拟触发鼠标事件
    • 模拟触发键盘事件
    • 调用 CameraControl::update 更新相机状态

3.UML

asciidoc 复制代码
+------------------+
|  CameraControl   |  <<abstract>>
+------------------+
| +handleMouseEvent(MouseEvent) : void |
| +handleKeyEvent(KeyEvent) : void     |
| +update() : void                     |
+------------------+

        ^
        |
        |
+----------------------+
| SimpleCameraControl  |
+----------------------+
| -mousePressed : bool |
| -lastX : double      |
| -lastY : double      |
| -keys : map<int, bool> |
+----------------------+
| +handleMouseEvent(MouseEvent) : void |
| +handleKeyEvent(KeyEvent) : void     |
| +update() : void                     |
+----------------------+

+-------------------+
|    Application    |
+-------------------+
| -cameraControl : SimpleCameraControl*
| -mouseCallback : MouseCallback       |
| -keyCallback : KeyCallback           |
+-------------------+
| +setMouseCallback(MouseCallback) : void |
| +setKeyCallback(KeyCallback) : void     |
| +triggerMouseEvent(MouseEvent) : void   |
| +triggerKeyEvent(KeyEvent) : void       |
| +run() : void                           |
+-------------------+

+-------------------+
|    MouseEvent     |
+-------------------+
| +x : int          |
| +y : int          |
| +button : int     |
| +pressed : bool   |
+-------------------+

+-----------------+
|    KeyEvent     |
+-----------------+
| +key : int      |
+-----------------+

+--------------------+
|   Global Functions |
+--------------------+
| +onMouseEvent(MouseEvent) : void |
| +onKeyEvent(KeyEvent) : void     |
+--------------------+

4.代码

cpp 复制代码
#include <iostream>
#include <map>

// 定义事件类型
enum class EventType {
    MouseClick,
    KeyPress
};

// 定义鼠标事件信息
struct MouseEvent {
    int x, y;
    int button;
    bool pressed;
};

// 定义键盘事件信息
struct KeyEvent {
    int key;
};

// 事件回调函数指针类型
using MouseCallback = void (*)(const MouseEvent&);
using KeyCallback = void (*)(const KeyEvent&);

// 抽象相机控制器基类
class CameraControl {
public:
    virtual void handleMouseEvent(const MouseEvent& event) = 0;
    virtual void handleKeyEvent(const KeyEvent& event) = 0;
    virtual void update() = 0;
};

// 一个简单的相机控制器实现
class SimpleCameraControl : public CameraControl {
public:
    void handleMouseEvent(const MouseEvent& event) override {
        if (event.pressed) {
            mousePressed = true;
            lastX = event.x;
            lastY = event.y;
            std::cout << "Mouse button " << event.button << " pressed at ("
                      << event.x << ", " << event.y << ")\n";
        } else {
            mousePressed = false;
            double deltaX = event.x - lastX;
            double deltaY = event.y - lastY;
            std::cout << "Mouse dragged by (" << deltaX << ", " << deltaY << ")\n";
            lastX = event.x;
            lastY = event.y;
        }
    }

    void handleKeyEvent(const KeyEvent& event) override {
        keys[event.key] = true;
        std::cout << "Key pressed: " << event.key << "\n";
    }

    void update() override {
        std::cout << "Updating camera control\n";
    }

private:
    bool mousePressed = false;
    double lastX = 0.0, lastY = 0.0;
    std::map<int, bool> keys;
};

// 应用程序类
class Application {
public:
    Application()
        : cameraControl(new SimpleCameraControl()) {}

    void setMouseCallback(MouseCallback callback) {
        mouseCallback = callback;
    }

    void setKeyCallback(KeyCallback callback) {
        keyCallback = callback;
    }

    void triggerMouseEvent(const MouseEvent& event) {
        if (mouseCallback) {
            mouseCallback(event);
        }
    }

    void triggerKeyEvent(const KeyEvent& event) {
        if (keyCallback) {
            keyCallback(event);
        }
    }

    void run() {
        // 模拟事件触发
        triggerMouseEvent(MouseEvent{100, 200, 1, true});
        triggerMouseEvent(MouseEvent{150, 250, 1, false});
        triggerKeyEvent(KeyEvent{65});

        // 更新相机控制
        cameraControl->update();
    }

private:
    SimpleCameraControl* cameraControl;
    MouseCallback mouseCallback = nullptr;
    KeyCallback keyCallback = nullptr;
};

// 全局函数
void onMouseEvent(const MouseEvent& event) {
    static SimpleCameraControl control;
    control.handleMouseEvent(event);
}

void onKeyEvent(const KeyEvent& event) {
    static SimpleCameraControl control;
    control.handleKeyEvent(event);
}

int main() {
    Application app;
    app.setMouseCallback(onMouseEvent);
    app.setKeyCallback(onKeyEvent);
    app.run();
    return 0;
}
相关推荐
Android系统攻城狮1 小时前
Linux Gstreamer深度解析之gst_audio_encoder_set_frame_max调用流程与实战(六十一)
android·linux·运维·音视频·gstreamer音视频·音视频进阶·gstreamer音视频进阶
2501_926978332 小时前
给自指系统接一个外部锚 —— 一个关于「用 AI 观察自己」的方法
人工智能·经验分享·笔记·机器学习·ai写作
传奇开心果编程5 小时前
【Compose Multiplatform 跨端开发学与练】第7课 平台适配与互操作
android·windows·学习·ui·ios·kotlin·composer
mmsx5 小时前
Android 地图数据链路:从 GDAL、KML 到多引擎适配
android·kotlin
2601_968900775 小时前
大模型版本回归评估实战:从能力指标到额度口径的完整链路
android·数据挖掘·回归
AOI小白新手上路6 小时前
anomalib 缺陷检测复现笔记:从跑通库到 EfficientAD 落地
人工智能·笔记·机器学习
xxwl5857 小时前
RabbitMQ 学习笔记
笔记·学习·rabbitmq
ao-weilai7 小时前
MySQL数据库:基本查询
android·数据库·mysql
加油努力有饭吃8 小时前
DLMS/COSEM 蓝皮书解读(二十六):Auto connect(class_id = 29)—— 自动拨号与主动连接(出站管理)
笔记
段一凡-华北理工大学8 小时前
高炉炼铁机器视觉与智能识别十八讲~系列文章06:铁口与出铁场:出铁状态识别与渣铁分离判断
人工智能·数码相机·计算机视觉·高炉出铁识别·高炉渣铁分离·高炉铁口识别