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指针和事件回调函数指针,通过setMouseCallback和setKeyCallback设置事件回调。CameraControl是一个抽象基类,定义了处理鼠标事件、键盘事件和更新的接口。SimpleCameraControl继承自CameraControl,实现了具体的事件处理逻辑。MouseEvent和KeyEvent分别表示鼠标事件和键盘事件的数据结构。
事件处理流程图:
事件处理流程如下:
- 应用程序触发鼠标或键盘事件
- 事件通过
Application::triggerMouseEvent或Application::triggerKeyEvent分发到对应的全局回调函数 - 回调函数
onMouseEvent或onKeyEvent调用SimpleCameraControl的对应事件处理函数 SimpleCameraControl的事件处理函数根据事件数据进行相应的处理
主程序流程图:
主程序的流程如下:
- 创建
Application对象 - 设置鼠标回调函数为
onMouseEvent - 设置键盘回调函数为
onKeyEvent - 调用
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…...
低代码时代的企业信息化:规范与标准化的重要性
在当今数字化转型的浪潮中,企业的信息化建设正逐步向低代码平台倾斜。低代码不仅仅是简化开发过程,更是对企业内部流程、规范和标准化的深刻理解与应用。本文将探讨低代码在企业信息化中的重要性,特别是在运维和开发流程中的标准化࿰…...
理解无监督学习、无监督图像分割
系列文章目录 文章目录 系列文章目录一、无监督学习如何学习 能不能举一个非常具体的例子,带着运算过程的例子总结 二、在图像分割中呢,具体怎样实现无监督示例:使用自编码器和k-means进行无监督图像分割1. **数据准备**2. **构建自编码器**3…...
C语言— exec系列函数
exec系列函数 在C语言编程中,exec 系列函数用于在当前进程中执行一个新程序,从而替换当前进程的映像。这些函数不会返回,除非发生错误。exec 系列函数有多个变体,其中最常用的包括 execl, execle, execlp, execv, execve, execvp…...
命名管道Linux
管道是 毫不相关的进程进程间通信::命名管道 管道 首先自己要用用户层缓冲区,还得把用户层缓冲区拷贝到管道里,(从键盘里输入数据到用户层缓冲区里面),然后用户层缓冲区通过系统调用(write)写…...
【ios】---swift开发从入门到放弃
swift开发从入门到放弃 环境swift入门变量与常量类型安全和类型推断print函数字符串整数双精度布尔运算符数组集合set字典区间元祖可选类型循环语句条件语句switch语句函数枚举类型闭包数组方法结构体 环境 1.在App Store下载Xcode 2.新建项目(可以先使用这个&…...
【AUTOSAR 基础软件】PduR模块详解(通信路由)
文章包含了AUTOSAR基础软件(BSW)中PduR模块相关的内容详解。本文从AUTOSAR规范解析,ISOLAR-AB配置以及模块相关代码分析三个维度来帮读者清晰的认识和了解PduR这一基础软件模块。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的…...
[控制理论]—差分变换法与双线性变换法的基本原理和代码实现
差分变换法与双线性变换法的基本原理和代码实现 1.差分变换法 差分变换法就是把微分方程中的导数用有限差分来近似等效,得到一个与原微分方程逼近的差分方程。 差分变换法包括后向差分与前向差分。 1.1 后向差分法 差分变换如下: d e ( t ) d t e…...
【JavaEE】——多线程常用类
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 引入: 一:Callable和FutureTask类 1:对比Runnable 2:…...
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注解上,SpringBootApplication这个注解 底层包含了3个注解,分别是: 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站小土堆课程 一、定义概念 缩写 池化(Pooling)是深度学习中常用的一种操作,用于降低卷积神经网络(CNN)或循环神经网…...
职场上的人情世故,你知多少?这五点一定要了解
职场是一个由人组成的复杂社交网络,人情世故在其中起着至关重要的作用。良好的人际关系可以帮助我们更好地融入团队,提升工作效率,甚至影响职业发展。在职场中,我们需要了解一些关键要素,以更好地处理人际关系…...
Python | Leetcode Python题解之第456题132模式
题目: 题解: 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(或INTEGER)BIGINT 可选属性UNSIGNEDZEROFILL显示宽度(M)AUTO_INCREMENT注意事项 适合场景TINYINTSMALLINTMEDIUMINTINT(或INTEGER࿰…...
查看 Git 对象存储中的内容
查看 Git 对象存储中的内容 ls -C .git/objects/<dir>ls: 列出目录内容的命令。-C: 以列的形式显示内容。.git/objects/<dir>: .git 是存储仓库信息的 Git 目录,objects 是其中存储对象的子目录。<dir> 是对象存储目录下的一个特定的子目录。 此…...
Redis 中热 Key 的判定及其解决方案
引言 Redis 作为高效的内存数据库,常用于缓存、消息队列等场景。随着数据量和并发量的增加,某些数据的访问频率会远远高于其他数据,这些被频繁访问的 Key 被称为 热 Key。热 Key 问题是 Redis 应用中常见的性能瓶颈之一,它可能导…...
elasticsearch创建索引
1对比关系型数据库,创建索引就等同于创建数据库 在postman中,向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…...
设备管理系统是什么?如何建立设备管理体系?
在现代企业的运转中,生产设备无疑是核心资产。无论是制造业的数控机床,还是建筑工地的重型机械,甚至是医疗机构的精密仪器,设备的稳定运行直接决定了企业的生产效率、产品质量和成本控制。然而,许多企业在设备管理上仍…...
从“看见光点”到“看懂世界”:视觉重建让这个世界变得更近一些
三十多年前,“让盲人重新看见”更像一句带有未来感的科学想象。而今天,这件事已经进入临床试验和真实的人体研究。视觉重建之所以被视为脑机接口里最具挑战性的方向之一,不只是因为它要解决“能不能刺激大脑”的问题,更因为它要回…...
STM32实战:sprintf格式化字符串在嵌入式LCD显示中的高效应用
1. sprintf函数在STM32开发中的基础应用 第一次在STM32上使用sprintf函数时,我被它的强大功能惊艳到了。这个看似简单的函数,却能帮我们把各种数据类型转换成整齐的字符串,这在嵌入式开发中简直是神器。记得当时我在调试一个温湿度传感器项目…...
网络安全的概念与规范:从基础到实践
网络安全的概念与规范:从基础到实践 在数字化浪潮席卷全球的今天,网络安全已成为国家安全的重要组成部分。本文将系统梳理网络安全的核心概念、发展历程、主要威胁、前沿趋势以及标准规范,帮助读者建立完整的网络安全知识体系。 一、网络安全…...
理解usearch的动态内存调整:实现高效向量搜索的终极指南
理解usearch的动态内存调整:实现高效向量搜索的终极指南 【免费下载链接】usearch Fast Open-Source Search & Clustering engine for Vectors & Arbitrary Objects in C, C, Python, JavaScript, Rust, Java, Objective-C, Swift, C#, GoLang, and Wolfr…...
从LVGL V7.11到V9.1:我维护中文文档这三年踩过的坑与实战经验
从LVGL V7.11到V9.1:一个中文文档维护者的技术叙事 三年前,当我第一次在嵌入式项目中尝试使用LVGL时,完全没想到这个轻量级图形库会成为我技术生涯中的重要篇章。作为国内最早系统维护LVGL中文文档的开发者之一,这段跨越三个大版本…...
Qwen3-14B GPU算力优化实践:显存占用降低28%的FlashAttention-2配置
Qwen3-14B GPU算力优化实践:显存占用降低28%的FlashAttention-2配置 1. 开箱即用的私有部署方案 对于想要快速部署Qwen3-14B大模型的企业和个人开发者来说,这个经过优化的私有部署镜像提供了完美的解决方案。它基于RTX 4090D 24GB显存显卡和CUDA 12.4环…...
告别虚拟机!在Windows上用WSL2和NDK r27c交叉编译Android动态库(附CMake集成避坑指南)
在Windows上利用WSL2与NDK r27c高效构建Android动态库的完整指南 对于Android开发者而言,跨平台编译一直是个令人头疼的问题。传统虚拟机方案虽然功能完整,但资源占用高、启动慢,而纯Windows环境下的NDK工具链又常常遇到各种兼容性问题。本文…...
LumiPixel Canvas Quest集成Vue.js:打造动态人像画廊管理后台
LumiPixel Canvas Quest集成Vue.js:打造动态人像画廊管理后台 1. 项目背景与需求分析 在数字内容创作领域,AI生成人像正成为设计师和内容创作者的重要工具。传统人工绘制方式耗时费力,而直接使用AI生成工具又缺乏系统化管理。我们团队最近用…...
C++ 安全子集:探讨在关键任务系统中限制部分 C++ 特性(如 RTTI)的必要性
尊敬的各位专家、各位同仁,大家好。今天,我们齐聚一堂,共同探讨一个在软件工程领域,尤其是在关键任务系统(Critical Mission Systems)开发中至关重要的话题:C 安全子集——在严苛环境下限制部分…...
