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

news2024/12/23 18:38:08

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

—— 2024-10-02 下午


在这里插入图片描述

code review!

文章目录

  • OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离
    • 1.代码图片
    • 2.分析
    • 3.UML
    • 4.代码

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 指针和事件回调函数指针,通过 setMouseCallbacksetKeyCallback 设置事件回调。
  • CameraControl 是一个抽象基类,定义了处理鼠标事件、键盘事件和更新的接口。
  • SimpleCameraControl 继承自 CameraControl,实现了具体的事件处理逻辑。
  • MouseEventKeyEvent 分别表示鼠标事件和键盘事件的数据结构。

事件处理流程图:

mouseCallback
keyCallback
鼠标/键盘事件
Application::triggerMouseEvent/triggerKeyEvent
onMouseEvent
onKeyEvent
SimpleCameraControl::handleMouseEvent
SimpleCameraControl::handleKeyEvent

事件处理流程如下:

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

主程序流程图:

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

主程序的流程如下:

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

3.UML

+------------------+
|  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.代码

#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2185431.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

老年人最真实的养老需求

子孝父心宽。&#xff08;陈元靓&#xff09; 向往的养老胜地 下文节选(有删改&#xff09;&#xff1a; 中消协发布报告 揭示老年人最真实的养老服务需求 主页&#xff1a; 博客 文章目录 前言1. 需求端1.1 居家养老更关注家政餐饮等“日常所需”1.2 机构养老的需求重在“医…

猫咪尿闭的症状有哪些?适合尿闭猫咪的猫罐头盘点

刚开始养猫的时候只喂猫粮&#xff0c;也没督促孩子喝水&#xff0c;也没喂猫罐头&#xff0c;结果猫咪尿闭了&#xff0c;每次上厕所都在惨叫&#xff0c;完全无法排尿。带去医院治疗&#xff0c;前前后后总共花了8000&#xff0c;真实花钱买教训。我总结了一下猫咪尿闭时会出…

kettle从入门到精通 第八十九课 ETL之kettle kettle jms activemq使用教程

场景&#xff1a;群里有小伙伴求助jms activemq如何使用kettle 进行消费数据&#xff0c;之前连接过kafka&#xff0c;rabbtimq&#xff0c;想着activemq应该也没啥难度&#xff0c;结果低估了activemq。盘他&#xff01;&#xff01;&#xff01; 插曲&#xff1a;ActiveMq 有…

SQL连接Python

对于运营部门的Yoyo来说&#xff0c;她想要知道夜曲优选的订单都来自哪些省份&#xff0c;每个省份的总订单数以及总订单金额分别是多少。 这时小鹿就会通过SQL对连接的数据库进行查询&#xff0c;再将结果传递给Python处理&#xff0c;并帮助Yoyo生成可视化图表。 我们先来快…

工程师 - Github文件访问加速

如果是下载单独的又比较大的Github上的文件&#xff0c;网速较差时&#xff0c;可以使用镜像网站&#xff0c;比如下面这个工具。 GitHub 文件加速 - Sonder (akams.cn) GitHub 文件加速 - Sonder 另外&#xff0c;也可以在搜索引擎里直接搜索“Github 文件加速”&#xff0c;…

MySQL高阶2041-面试中被录取的候选人

目录 题目 准备数据 分析数据 总结 题目 编写解决方案&#xff0c;找出 至少有两年 工作经验、且面试分数之和 严格大于 15 的候选人的 ID 。 可以以 任何顺序 返回结果表。 准备数据 Create table If Not Exists Candidates (candidate_id int, name varchar(30), yea…

检索增强生成(RAG)有什么好的优化方案?

RAG&#xff08;检索增强生成&#xff09;是一种结合了信息检索和内容生成的技术&#xff0c;常用于提升人工智能回答问题的准确性和相关性。本文将RAG的优化分为两个主要方向进行介绍&#xff1a;基础功能优化和架构优化。 一、RAG基础功能优化 基础功能优化主要是对RAG的每个…

以太网交换安全:端口安全

一、端口安全介绍 端口安全是一种网络设备防护措施&#xff0c;通过将接口学习到的动态MAC地址转换为安全MAC地址&#xff08;包括安全动态MAC和Sticky MAC&#xff09;&#xff0c;阻止除安全MAC和静态MAC之外的主机通过本接口和设备通信&#xff0c;从而增强设备的安全性。以…

计组复习笔记

计组笔记 汇编部分 通用寄存器&#xff08;General Registers&#xff09;: AX (Accumulator): 用于累加运算&#xff0c;也是乘法和除法的默认寄存器。BX (Base Register): 可以用作一个基址寄存器&#xff0c;通常用于存放数据的基地址。CX (Counter Register): 通常用于循环…

Lab3 【哈工大_操作系统】系统调用

本节将更新哈工大《操作系统》课程第三个 Lab 实验 系统调用。按照实验书要求&#xff0c;介绍了非常详细的实验操作流程&#xff0c;并提供了超级无敌详细的代码注释。文末附完整标准答案代码&#xff0c;包括系统调用实现 who.c 和测试函数 iam.c、whoami.c 以及超详细注释。…

mac M2安装单机版 MongoDB 7.x

1. 通过tgz包安装MongoDB 1.1 下载并解压缩安装包 官网下载 mac OS 的 MongoDB 安装包&#xff0c;这里选择7.x版本进行安装&#xff08;下载链接&#xff09; 下载好的tgz包&#xff0c;双击解压缩&#xff0c;并重命名为mongdb 将安装包拷贝到安装目录&#xff0c;笔者的…

深入解析开源大模型的GPU资源需求与优化策略

随着大模型的火热很多项目中都使用到了开源大模型&#xff0c;这时候准确评估大模型的GPU资源非常重要&#xff0c;主要有下面几个方面 成本效率&#xff1a;GPU是昂贵的资源。高估内存需求可能导致在硬件上的不必要支出&#xff0c;而低估则可能导致系统故障或性能下降。 性…

【数据结构】什么是红黑树(Red Black Tree)?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;红黑树的概念 &#x1f4cc;红黑树的操作 &#x1f38f;红黑树的插入操作 &#x1f38f;红黑树的删除操作 结语 &#x1f4cc;红黑树的概念 我们之前学过了…

资源《Arduino 扩展板3-WS2812》说明。

资源链接&#xff1a; Arduino 扩展板3-WS2812 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;AD工程、原理图、PCB。 3.内容展示 4.简述 该文件为PCB工程&#xff0c;采用AD做的。 该文件打板后配合Arduino使用&#xff0c;属于Arduino的扩展板。 该文件主要…

通义千问“百宝箱”:效率神器,解放你的双手!

你在为播客转文字、音视频转写和长文本阅读而烦恼吗&#xff1f;今天&#xff0c;就让通义千问的“百宝箱”来帮你解决这些难题&#xff01; 最近&#xff0c;我发现通义千问首页隐藏着一个效率神器——“百宝箱”&#xff08;现在更名为工具箱&#xff09;&#xff0c;简直是…

batch和momentum

&#x1f680; 机器学习系列前期回顾 1、初识机器学习 2、线性模型到神经网络 3、local minima的问题如何解决 &#x1f680;在初识机器学习中&#xff0c;了解了机器学习是如何工作的并引入了线性模型&#xff0c;在线性模型到神经网络这节&#xff0c;将线性模型进一步改进为…

FireRedTTS - 小红书最新开源AI语音克隆合成系统 免训练一键音频克隆 本地一键整合包下载

小红书技术团队FireRed最近推出了一款名为FireRedTTS的先进语音合成系统&#xff0c;该系统能够基于少量参考音频快速模仿任意音色和说话风格&#xff0c;实现独特的音频内容创造。 FireRedTTS 只需要给定文本和几秒钟参考音频&#xff0c;无需训练&#xff0c;就可模仿任意音色…

【Golang】关于Go语言字符串转换strconv

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

ProtoBuf快速上手

文章目录 创建 .proto文件编译 .proto文件编译后生成的文件序列化与反序列化的使用 此篇文章实现内容&#xff1a; 对一个通讯录的联系人信息&#xff0c;使用PB进行序列化&#xff0c;并将结果输出对序列化的内容使用PB进行反序列化&#xff0c;解析联系人信息并输出联系人信…

【成神之路】Ambari实战-015-代码生命周期-metainfo-category详解

1.Redis 集群 metainfo.xml 示例 <?xml version"1.0"?> <metainfo><schemaVersion>2.0</schemaVersion><services><service><!-- Redis 集群服务的基本信息 --><name>REDIS</name><displayName>Redi…