openFrameworks vectorMathExample 实战指南:用 glm::vec3 与自定义形状实现矢量绘图与 3D 旋转
图形学音视频【免费下载链接】openFrameworksopenFrameworks is a community-developed cross platform toolkit for creative coding in C.项目地址https://gitcode.com/gh_mirrors/op/openFrameworks点击查看免费下载导读vectorMathExample是 openFrameworks 官方examples/math目录下的一个入门级数学示例它的核心目的只有一个用最直观的方式展示「矢量vector到底是什么」以及「如何用矢量来绘图」。在这个示例里你按住鼠标拖动即可在屏幕上画线而存储每一笔轨迹的数据结构就是glm::vec3数组程序还会自动让整条轨迹绕屏幕中心旋转并允许你用键盘实时调节旋转速度与旋转轴。读完本文你将掌握glm::vec3的基本用法、ofBeginShape()/ofVertex()/ofEndShape()自定义形状绘制流程以及「平移—旋转—平移回来」这一 3D 数学变换的经典套路并能在自己的 openFrameworks 工程中复现这套交互。示例概况与文件结构该示例位于 examples/math/vectorMathExample源码结构非常精简src/main.cpp创建 1024×768 的窗口并启动应用src/ofApp.h声明点数组、旋转参数、坐标轴端点等成员src/ofApp.cpp实现 setup / update / draw 以及全部鼠标键盘交互。main.cpp 使用ofGLWindowSettings设置窗口尺寸为 1024×768、窗口模式为OF_WINDOW然后通过ofCreateWindow与ofRunApp启动应用这是当前版本 openFrameworks 的标准启动写法。核心数据结构glm::vec3 点数组在 ofApp.h 中示例用两个关键成员承载整个程序的状态#define MAX_N_PTS 1500 glm::vec3 pts[MAX_N_PTS]; // 存储用户画下的每一个点 int nPts; // 当前已存储的点数 glm::vec3 rotateAmount; // 绕 x/y/z 三个轴的旋转量 float speedOfRotation; // 每帧旋转的角度glm::vec3是 openFrameworks 内置的 GLM 数学库提供的三维矢量类型每个矢量包含x、y、z三个分量。正如 README 中所强调的一个矢量在抽象的空间里同时代表方向和大小magnitude。本示例中它被当作「点的坐标」来使用同时也被用来描述「旋转轴」。MAX_N_PTS是点的容量上限1500 个这个上限同时在mouseDragged中被检查保证pts[nPts]永远不会越界写入。数组的写入方式也很典型pts[nPts].x x; pts[nPts].y y; nPts;即通过下标nPts定位到数组中的特定位置逐分量赋值再自增计数器。鼠标绘制存储轨迹点绘制交互集中在 ofApp.cppmouseDragged每拖动一次就向pts数组中追加一个点上限MAX_N_PTS并置bDrawnAnything true这样屏幕上会随之显示提示文字mousePressed把nPts归零实现「单击一次清屏」。void ofApp::mouseDragged(int x, int y, int button){ bDrawnAnything true; if (nPts MAX_N_PTS){ pts[nPts].x x; pts[nPts].y y; nPts; } }这是典型的「采样式」轨迹记录把鼠标的实时坐标(x, y)按序存入数组后续的旋转、绘制都基于这份点序列进行。自定义形状绘制ofBeginShape → ofVertex → ofEndShapedraw()中先用ofBeginShape()开启一段新的形状然后遍历所有点调用ofVertex(pts[i].x, pts[i].y)最后以ofEndShape()结束ofSetHexColor(0x000000); ofNoFill(); ofBeginShape(); for (int i 0; i nPts; i){ ofVertex(pts[i].x, pts[i].y); } ofEndShape();在 ofGraphics.h 中这三个 API 的契约非常明确ofBeginShape()开始绘制一个新的形状之后必须跟一串顶点最后调用ofEndShape()ofVertex(...)在ofBeginShape()与ofEndShape()之间指定形状上的单个点除(x, y)、(x, y, z)两个重载外还支持直接传入glm::vec3/glm::vec2ofEndShape(bool bClose false)结束形状并绘制到屏幕必须调用否则看不到形状参数bClose为 true 时自动闭合形状默认 false即不闭合。这段代码配合ofNoFill()只描边不填充于是用户拖出的轨迹被渲染成一条连续的黑线。类似的形状 API 还有ofCurveVertex曲线顶点、ofBezierVertex贝塞尔顶点、ofVertices批量顶点等均需在ofBeginShape()/ofEndShape()之间使用。三轴旋转参考线为了让用户直观感受到旋转setup()中定义了 x/y/z 三条坐标轴的端点各 100 个单位长并平移到窗口中心glm::vec3 center(ofGetWidth()/2, ofGetHeight()/2, 0); xAxisMin {-100, 0, 0}; xAxisMax { 100, 0, 0}; yAxisMin { 0,-100, 0}; yAxisMax { 0, 100, 0}; zAxisMin { 0, 0,-100}; zAxisMax { 0, 0, 100}; xAxisMin center; // ... 其余端点同样 centerdraw()里用三组ofBeginShape()/ofVertex(x, y, z)/ofEndShape()分别绘制三条轴线颜色为ofSetColor(50,50,255)的蓝色。由于视角正对 z 轴z 分量在屏幕上不可见所以默认只能看到 x、y 两条轴——这正是 README 所说的只有 x 和 y 轴可见。3D 旋转变换平移—旋转—平移回去update()是整个示例的数学核心。由于glm::rotate是绕原点 (0,0,0) 旋转而屏幕坐标系的原点在左上角所以直接旋转会导致轨迹绕角落打转。示例用注释把标准流程拆成了三步ofApp.cpp// (A) 平移到原点把每个点减去中心坐标 for (int i 0; i nPts; i){ pts[i] - center; } // (B) 旋转glm::rotate(vec, angle, axis) for (int i 0; i nPts; i){ pts[i] glm::rotate(pts[i], speedOfRotation, rotateAmount); } // (C) 平移回来把每个点加回中心坐标 for (int i 0; i nPts; i){ pts[i] center; }glm::rotate(vec, angle, axis)会返回绕axis轴旋转angle弧度后的新矢量。同样的三步变换也应用在三条坐标轴的 6 个端点上保证轴线与轨迹同步旋转。setup()中的初始值rotateAmount {0, 0, 1}; // 默认绕 z 轴旋转 speedOfRotation ofDegToRad(0.5f); // 每帧 0.5 度换算为弧度ofDegToRad(0.5f)把 0.5 度转成弧度作为每帧旋转角初始旋转轴为 z 轴。键盘交互实时调节旋转keyPressedofApp.cpp用 switch 处理 8 个按键规则与 README 完全一致按键作用增量a/z增加 / 减小旋转速度speedOfRotation±0.001 弧度s/x增加 / 减小 x 方向旋转量rotateAmount.x±0.05d/c增加 / 减小 y 方向旋转量rotateAmount.y±0.05f/v增加 / 减小 z 方向旋转量rotateAmount.z±0.05case a: speedOfRotation 0.001f; break; case s: rotateAmount.x 0.05f; break; // ... 其余按键同理改变rotateAmount的各分量相当于改变旋转轴的朝向——例如把rotateAmount设为{1, 0, 0}并减小 z 分量轨迹就会从绕屏幕平面旋转变为绕水平轴翻转。注意旋转轴矢量无需归一化GLM 内部会自行处理但各分量的相对比例决定了轴向。HUD 信息面板draw()的末尾绘制了一个芥末黄0xE5A93F信息面板实时显示旋转速度与三轴旋转量string info speed of rotation (a/z): ofToString(speedOfRotation,3) \n rotateAmount in x (s/x): ofToString(rotateAmount.x,3) \n rotateAmount in y (d/c): ofToString(rotateAmount.y,3) \n rotateAmount in z (f/v): ofToString(rotateAmount.z,3); ofFill(); ofSetHexColor(0xE5A93F); ofDrawRectangle(10,10,300,70); ofSetHexColor(0x000000); ofDrawBitmapString(info,30,30);ofToString(value, 3)将浮点数保留 3 位小数输出面板由ofDrawRectangle画底、ofDrawBitmapString写字组成。另外若用户尚未画过任何东西bDrawnAnything false屏幕中央会显示 draw something! 提示。运行与体验运行该示例的方式与 openFrameworks 其他示例一致在 examples/math/vectorMathExample 目录下使用 openFrameworks 项目生成器Project Generator生成对应平台工程后编译运行或直接通过of命令行工具构建。启动后按住鼠标左键并拖动即可画出一条连续的黑色轨迹轨迹顶点被实时存入pts数组轨迹与蓝色坐标轴会绕窗口中心持续旋转默认绕 z 轴每帧 0.5 度按a/z调节旋转速度按s/x、d/c、f/v分别调节 x/y/z 三个方向的旋转量左上角面板实时反馈当前数值单击鼠标左键清空屏幕重新作画。下方为示例的实际运行截图从示例到实战几个可扩展方向换成曲线顶点把ofVertex换成ofCurveVertex轨迹会从折线变成平滑的 Catmull-Rom 曲线画感更圆润引入 z 轴深度示例默认 z 分量为 0若在mouseDragged中根据鼠标速度或时间给pts[nPts].z赋值即可画出真正的 3D 轨迹保存与回放将pts数组序列化到文件即可实现笔迹的保存、回放或导出理解变换顺序平移—旋转—平移是绕任意点做旋转变换的通用模板在 ofMesh.inl 等引擎内部代码中同样可以见到glm::rotate对法线、顶点做旋转运算的用法本示例正是这套数学在实际绘图中的最小可运行演示。小结vectorMathExample用不到 200 行代码串起了 openFrameworks 中三个最常用的基础能力glm::vec3矢量数据、ofBeginShape()/ofVertex()/ofEndShape()自定义形状绘制以及绕任意点旋转的变换套路。它是理解后续particlesExample、3DPrimitivesExample等 math/3d 示例的良好起点——矢量不再只是数学课本上的概念而是你手中笔迹的每一个点。赞分享图形学音视频【免费下载链接】openFrameworksopenFrameworks is a community-developed cross platform toolkit for creative coding in C.项目地址https://gitcode.com/gh_mirrors/op/openFrameworks点击查看免费下载相关推荐openFrameworks iOS 字体渲染实战用 ofTrueTypeFont 与 ofPath 实现位图/矢量字形绘制openFrameworks iOS 字体渲染实战用 ofTrueTypeFont 与 ofPath 实现位图/矢量字形绘制 本篇文章基于 openFrame图形学音视频openFrameworks 一维噪声实战指南用 ofSignedNoise 驱动波形、旋转与颜色openFrameworks 一维噪声实战指南用 ofSignedNoise 驱动波形、旋转与颜色 openFrameworks 一维噪声实战指南用 ofS图形学音视频FlappySwift中的自定义绘制使用SKShapeNode创建矢量图形FlappySwift中的自定义绘制使用SKShapeNode创建矢量图形 在游戏开发中视觉元素的呈现往往决定了游戏的吸引力。FlappySwift作为经典游戏开发上一篇KMS_VL_ALL_AIO3分钟完成Windows和Office永久激活的终极指南下一篇OpenSearch 贡献者工程手册仓库结构、构建、测试与提交规范的源码级解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

类和对象(上):一文讲透C++构造函数与析构函数:调用时机+常见坑+代码示例

类和对象(上):一文讲透C++构造函数与析构函数:调用时机+常见坑+代码示例

前言:本篇以Date类和Stack类为例C为什么要引入构造函数和析构函数?在C语言的结构体中,如果需要初始化成员,通常要自己编写一个初始化函数,并在定义变量后手动调用它——这一步非常容易遗漏。C引入构造函数,…

2026/9/24 15:51:04 阅读更多 →
Hive 生产级 AI 智能体中的 YouTube 数据工具:YouTube Data API v3 MCP 工具集实战指南

Hive 生产级 AI 智能体中的 YouTube 数据工具:YouTube Data API v3 MCP 工具集实战指南

Hive 生产级 AI 智能体中的 YouTube 数据工具:YouTube Data API v3 MCP 工具集实战指南 【免费下载链接】hive Multi-Agent Harness for Production AI 项目地址: https://gitcode.com/gh_mirrors/hive48/hive 本指南围绕 Hive 仓库中 Aden Tools 的 youtube…

2026/9/24 15:51:04 阅读更多 →
2026四款智能锁横评实测:防撬时间、解锁速度、续航表现量化对比

2026四款智能锁横评实测:防撬时间、解锁速度、续航表现量化对比

2026年上半年,智能门锁行业三强合计拿下线上销额55.7%的份额。千元档与高端旗舰之间,德施曼、凯迪仕、小米、格行四个品牌各据一方。本文从暴力拆解、解锁体验、猫眼抓拍、续航与售后四个维度横向实测。一、四款机型速览:3D人脸、锁芯、续航&…

2026/9/24 15:50:04 阅读更多 →

最新新闻

AWS SDK for C++ 跨服务示例全解析:从 Aurora Serverless 任务追踪器到 SNS/SQS 发布订阅

AWS SDK for C++ 跨服务示例全解析:从 Aurora Serverless 任务追踪器到 SNS/SQS 发布订阅

示例工程教程后端 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below. 项目地…

2026/9/24 16:37:44 阅读更多 →
关于电缆标签

关于电缆标签

1.电缆按照树结构分 2,隐藏电缆高层代号3.页—页宏–插入 导入宏文件 线缆标签名称自动生成 线缆标签不重复

2026/9/24 16:37:44 阅读更多 →
PHPStan 错误标识符 requireImplements.deprecatedClass 详解:`@phpstan-require-implements` 引用已废弃类时的检测与修复

PHPStan 错误标识符 requireImplements.deprecatedClass 详解:`@phpstan-require-implements` 引用已废弃类时的检测与修复

PHPStan 错误标识符 requireImplements.deprecatedClass 详解:phpstan-require-implements 引用已废弃类时的检测与修复 【免费下载链接】phpstan PHP Static Analysis Tool - discover bugs in your code without running it! 项目地址: https://gitcode.com/gh_…

2026/9/24 16:37:43 阅读更多 →
优秀的项目经理,从来不靠记忆力跟进项目进度

优秀的项目经理,从来不靠记忆力跟进项目进度

很多管理者每天极度内耗: 靠着大脑死记几十项任务、记每个节点工期、记谁的工作没完成、记哪里存在卡点。 真正资深、能同时掌控多个项目的项目经理,往往一点都不忙乱。不是他们记忆力更强、精力更充沛,而是他们早就戒掉了靠记忆管理项目的低…

2026/9/24 16:37:43 阅读更多 →
如何自动识别文件编码?chardet4cj 字符编码检测库新手完全入门指南

如何自动识别文件编码?chardet4cj 字符编码检测库新手完全入门指南

如何自动识别文件编码?chardet4cj 字符编码检测库新手完全入门指南 【免费下载链接】chardet4cj 一个用于检测常用文本编码的库 项目地址: https://gitcode.com/Cangjie-TPC/chardet4cj 打开一个来路不明的文本文件,却看到满屏乱码?这…

2026/9/24 16:37:43 阅读更多 →
如何快速接入支付宝支付?alipay_sdk_cj仓颉原生SDK完全指南

如何快速接入支付宝支付?alipay_sdk_cj仓颉原生SDK完全指南

如何快速接入支付宝支付?alipay_sdk_cj仓颉原生SDK完全指南 【免费下载链接】alipay_sdk_cj AliPay Sdk for 仓颉 支付宝接口后端sdk,方便cangjie开发者快速接入支付宝的支付接口(目前只支持最广泛使用的商户直接接入模式,只支持最…

2026/9/24 16:36:43 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →