当前位置: 首页 > news >正文

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

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

—— 2024-10-02 下午


在这里插入图片描述
bilibili赵新政老师的教程看后笔记

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

相关文章:

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

OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离 —— 2024-10-02 下午 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离1.代码图片2.分析3.UML4.代码 1.代码图片 运行 Mouse button 1 pressed at (1…...

低代码时代的企业信息化:规范与标准化的重要性

在当今数字化转型的浪潮中&#xff0c;企业的信息化建设正逐步向低代码平台倾斜。低代码不仅仅是简化开发过程&#xff0c;更是对企业内部流程、规范和标准化的深刻理解与应用。本文将探讨低代码在企业信息化中的重要性&#xff0c;特别是在运维和开发流程中的标准化&#xff0…...

理解无监督学习、无监督图像分割

系列文章目录 文章目录 系列文章目录一、无监督学习如何学习 能不能举一个非常具体的例子&#xff0c;带着运算过程的例子总结 二、在图像分割中呢&#xff0c;具体怎样实现无监督示例&#xff1a;使用自编码器和k-means进行无监督图像分割1. **数据准备**2. **构建自编码器**3…...

C语言— exec系列函数

exec系列函数 在C语言编程中&#xff0c;exec 系列函数用于在当前进程中执行一个新程序&#xff0c;从而替换当前进程的映像。这些函数不会返回&#xff0c;除非发生错误。exec 系列函数有多个变体&#xff0c;其中最常用的包括 execl, execle, execlp, execv, execve, execvp…...

命名管道Linux

管道是 毫不相关的进程进程间通信::命名管道 管道 首先自己要用用户层缓冲区&#xff0c;还得把用户层缓冲区拷贝到管道里&#xff0c;&#xff08;从键盘里输入数据到用户层缓冲区里面&#xff09;&#xff0c;然后用户层缓冲区通过系统调用&#xff08;write&#xff09;写…...

【ios】---swift开发从入门到放弃

swift开发从入门到放弃 环境swift入门变量与常量类型安全和类型推断print函数字符串整数双精度布尔运算符数组集合set字典区间元祖可选类型循环语句条件语句switch语句函数枚举类型闭包数组方法结构体 环境 1.在App Store下载Xcode 2.新建项目&#xff08;可以先使用这个&…...

【AUTOSAR 基础软件】PduR模块详解(通信路由)

文章包含了AUTOSAR基础软件&#xff08;BSW&#xff09;中PduR模块相关的内容详解。本文从AUTOSAR规范解析&#xff0c;ISOLAR-AB配置以及模块相关代码分析三个维度来帮读者清晰的认识和了解PduR这一基础软件模块。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的…...

[控制理论]—差分变换法与双线性变换法的基本原理和代码实现

差分变换法与双线性变换法的基本原理和代码实现 1.差分变换法 差分变换法就是把微分方程中的导数用有限差分来近似等效&#xff0c;得到一个与原微分方程逼近的差分方程。 差分变换法包括后向差分与前向差分。 1.1 后向差分法 差分变换如下&#xff1a; d e ( t ) d t e…...

【JavaEE】——多线程常用类

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 引入&#xff1a; 一&#xff1a;Callable和FutureTask类 1&#xff1a;对比Runnable 2&#xff1a…...

Cilium-实战系列-(二)Cilium-Multi Networking-多网络

一、Cilium必要开启的功能 1、enable-multi-network 2、ipam模式选择:multi-pool 二、涉及的CRD资源 1、 ciliumpodippools.cilium.io *通过Cilium管理节点上的pod cidr.网络分为主网络和第二网络。 *主网络的 ciliumpodippools.cilium.io default根据配置文件默认生成的。 …...

springboot自动配置

自动配置的核心就在SpringBootApplication注解上&#xff0c;SpringBootApplication这个注解 底层包含了3个注解&#xff0c;分别是&#xff1a; SpringBootConfiguration ComponentScan EnableAutoConfiguration EnableAutoConfiguration这个注解才是自动配置的核心,它 封…...

mock数据,不使用springboot的单元测试

业务代码 package com.haier.configure.service.impl;import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.haier.common.util.RequestUtil; import com.haier.configure.entity.Langua…...

【pytorch】pytorch入门5:最大池化层(Pooling layers )

文章目录 前言一、定义概念 缩写二、参数三、最大池化操作四、使用步骤总结参考文献 前言 使用 B站小土堆课程 一、定义概念 缩写 池化&#xff08;Pooling&#xff09;是深度学习中常用的一种操作&#xff0c;用于降低卷积神经网络&#xff08;CNN&#xff09;或循环神经网…...

职场上的人情世故,你知多少?这五点一定要了解

职场是一个由人组成的复杂社交网络&#xff0c;人情世故在其中起着至关重要的作用。良好的人际关系可以帮助我们更好地融入团队&#xff0c;提升工作效率&#xff0c;甚至影响职业发展。在职场中&#xff0c;我们需要了解一些关键要素&#xff0c;以更好地处理人际关系&#xf…...

Python | Leetcode Python题解之第456题132模式

题目&#xff1a; 题解&#xff1a; class Solution:def find132pattern(self, nums: List[int]) -> bool:candidate_i, candidate_j [-nums[0]], [-nums[0]]for v in nums[1:]:idx_i bisect.bisect_right(candidate_i, -v)idx_j bisect.bisect_left(candidate_j, -v)if…...

【重学 MySQL】五十四、整型数据类型

【重学 MySQL】五十四、整型数据类型 整型类型TINYINTSMALLINTMEDIUMINTINT&#xff08;或INTEGER&#xff09;BIGINT 可选属性UNSIGNEDZEROFILL显示宽度&#xff08;M&#xff09;AUTO_INCREMENT注意事项 适合场景TINYINTSMALLINTMEDIUMINTINT&#xff08;或INTEGER&#xff0…...

查看 Git 对象存储中的内容

查看 Git 对象存储中的内容 ls -C .git/objects/<dir>ls: 列出目录内容的命令。-C: 以列的形式显示内容。.git/objects/<dir>: .git 是存储仓库信息的 Git 目录&#xff0c;objects 是其中存储对象的子目录。<dir> 是对象存储目录下的一个特定的子目录。 此…...

Redis 中热 Key 的判定及其解决方案

引言 Redis 作为高效的内存数据库&#xff0c;常用于缓存、消息队列等场景。随着数据量和并发量的增加&#xff0c;某些数据的访问频率会远远高于其他数据&#xff0c;这些被频繁访问的 Key 被称为 热 Key。热 Key 问题是 Redis 应用中常见的性能瓶颈之一&#xff0c;它可能导…...

elasticsearch创建索引

1对比关系型数据库&#xff0c;创建索引就等同于创建数据库 在postman中&#xff0c;向ES服务器发PUT请求 显示已经创建成功了 http://192.168.1.108:9200/shopping 请求方式get http://192.168.1.108:9200/shopping 请求全部的index的url地址 get 请求 http://192.168.1.10…...

【STM32单片机_(HAL库)】4-2-1【定时器TIM】定时器输出PWM实现呼吸灯实验

1.硬件 STM32单片机最小系统LED灯模块 2.软件 pwm驱动文件添加定时器HAL驱动层文件添加GPIO常用函数定时器输出PWM配置步骤main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "pwm.h"int main(void) {HA…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...