openFrameworks 粒子系统实战:particlesExample 四种交互模式与源码级解析
图形学音视频【免费下载链接】openFrameworksopenFrameworks is a community-developed cross platform toolkit for creative coding in C.项目地址https://gitcode.com/gh_mirrors/op/openFrameworks点击查看免费下载本文以 openFrameworks 官方示例 examples/math/particlesExample 为蓝本深入剖析一个完整的 C 粒子系统是如何构建的从数据模型、受力计算到四种可切换的交互模式吸引、排斥、最近点、噪声雪花再到由ofSignedNoise驱动的有机运动。读完本文你将掌握粒子系统的基本骨架位置/速度/力三要素 阻尼 边界处理并能在此基础上自由扩展出属于自己的粒子特效。示例概览你会看到什么启动该应用窗口尺寸 1024×768见 main.cpp后你会看到一个黑色渐变背景的窗口ofBackgroundGradient从(60,60,60)渐变到(10,10,10)1500 个彩色粒子在屏幕上聚集、散开或飘落粒子的颜色随当前模式变化初始状态下粒子系统处于PARTICLE_MODE_ATTRACT模式粒子群会向鼠标位置聚集屏幕左上角显示当前模式说明与操作提示文字ofDrawBitmapString绘制。交互控制一键切换四种粒子行为README 与本例的 keyPressed 实现共同定义了全部交互按键按键效果1切换到PARTICLE_MODE_ATTRACT粒子被鼠标吸引2切换到PARTICLE_MODE_REPEL粒子被鼠标排斥3切换到PARTICLE_MODE_NEAREST_POINTS粒子被最近的吸引点捕获按住f可禁用受力4切换到PARTICLE_MODE_NOISE雪花飘落模拟同时调用resetParticles()重建粒子Spacebar重置粒子系统回到初始状态PARTICLE_MODE_ATTRACT按键处理只负责修改currentMode与提示字符串currentModeStr真正的行为变化发生在每一帧的update()中update()会先对每个粒子调用p[i].setMode(currentMode)再执行p[i].update()从而保证模式切换即时生效。这是 openFrameworks 交互编程的典型模式——输入事件驱动状态变更更新循环消费状态。项目结构与粒子数据模型示例由五个源文件组成位于 examples/math/particlesExample/srcmain.cpp程序入口创建 1024×768 的 GLFW 窗口并运行应用ofApp.h/ofApp.cpp应用主类负责生命周期、粒子容器管理与交互demoParticle.h/demoParticle.cpp单个粒子的实现。particleMode枚举定义在 demoParticle.henum particleMode{ PARTICLE_MODE_ATTRACT 0, PARTICLE_MODE_REPEL, PARTICLE_MODE_NEAREST_POINTS, PARTICLE_MODE_NOISE };每个粒子demoParticle的数据模型demoParticle.h是经典粒子系统的五要素pos、vel、frc位置、速度、力均为glm::vec3openFrameworks 内置 glm 数学库drag阻尼系数0~1每帧对速度做乘法衰减模拟空气阻力uniqueVal每个粒子的随机唯一值作为噪声采样的偏移种子让粒子行为互不雷同scale随机缩放0.5~1.0决定绘制半径attractPoints指向吸引点数组的指针供PARTICLE_MODE_NEAREST_POINTS使用。粒子初始化与重置resetParticlessetup() 中值得注意的两行README 特别点名的学习要点ofSetVerticalSync(true); // 开启垂直同步 p.assign(num, demoParticle()); // 用 num1500 个默认粒子填充 vectorofSetVerticalSync(true)将重绘同步到屏幕垂直刷新率避免画面撕裂并限制帧率其底层实现在 libs/openFrameworks/app/ofAppRunner.cpp最终委托给当前窗口的setVerticalSync(bSync)。p.assign(num, demoParticle())一次性创建长度为num1500的demoParticle向量用于存放所有粒子的引用。resetParticles() 负责重建整个系统它做了三件事清空并随机生成4 个吸引点横坐标用ofMap(i, 0, 4, 100, ofGetWidth()-100)在窗口水平方向上均匀分布纵坐标用ofRandom(100, ofGetHeight()-100)随机z 为 0复制一份到attractPointsWithMovement作为“会移动的吸引点”遍历全部粒子依次调用setMode、setAttractPoints与reset()。在 demoParticle::reset() 中每个粒子被赋予随机位置、随机初速度ofRandom(-3.9, 3.9)、随机uniqueValofRandom(-10000, 10000)和随机scale。特别地若处于PARTICLE_MODE_NOISE模式阻尼取0.97~0.99且vel.y取绝对值放大 3 倍强制所有粒子向下运动——为“雪花”效果做准备。四种模式的受力逻辑核心demoParticle::update()demoParticle.cpp是全文的灵魂结构为“按模式计算力 → 更新位置 → 屏幕边界处理”三段式。1. PARTICLE_MODE_ATTRACT向鼠标吸引glm::vec3 attractPt(ofGetMouseX(), ofGetMouseY(), 0); frc attractPt - pos; // 指向鼠标的方向向量 frc glm::normalize(frc); // 归一化忽略距离远近 vel * drag; // 施加阻尼 vel frc * 0.6; // 施加恒定向心力关键点对力向量做glm::normalize后吸引力强度与距离无关粒子无论远近都以相同速率趋向鼠标配合阻尼drag0.95~0.998形成收敛且不过冲的聚集效果。注释明确说明by normalizing we disregard how close the particle is。2. PARTICLE_MODE_REPEL从鼠标排斥float dist glm::length(frc); frc glm::normalize(frc); vel * drag; if( dist 150 ){ vel -frc * 0.6; // 距离小于150时反向推离 }else{ // 否则用噪声添加轻微随机漂移 frc.x ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2); frc.y ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2); vel frc * 0.04; }排斥模式引入了距离阈值150 像素只有靠近鼠标的粒子才被推开远离鼠标的粒子则借助ofSignedNoise做低强度×0.04的随机漫步避免画面静止。3. PARTICLE_MODE_NEAREST_POINTS吸附最近吸引点该模式遍历 4 个吸引点用glm::length2平方距离避免开方开销寻找最近者然后frc closestPt - pos; // 不归一化力与距离成正比 vel * drag; if( dist 300 dist 40 !ofGetKeyPressed(f) ){ vel frc * 0.003; // 在40~300范围内被吸引 }else{ // 否则噪声漂移 vel frc * 0.4; }这里特意不归一化让吸引力随距离衰减从而产生平滑的“入轨”曲线dist 40防止粒子在目标点附近震荡按住f键ofGetKeyPressed(f)可随时冻结受力观察粒子的自由漂移。同时 ofApp::draw() 会在该模式下绘制吸引点的位置指示外圈ofNoFill半径 10 的空心圆 半径 4 的实心圆。4. PARTICLE_MODE_NOISE噪声雪花模拟float fakeWindX ofSignedNoise(pos.x * 0.003, pos.y * 0.006, ofGetElapsedTimef() * 0.6); frc.x fakeWindX * 0.25 ofSignedNoise(uniqueVal, pos.y * 0.04) * 0.6; frc.y ofSignedNoise(uniqueVal, pos.x * 0.006, ofGetElapsedTimef()*0.2) * 0.09 0.18; vel * drag; vel frc * 0.4; if( pos.y vel.y ofGetHeight() ){ pos.y - ofGetHeight(); // 飘出底部后回卷到顶部 }这个模式完全不需要鼠标交互横向力由“假风”fakeWindX加个体噪声构成纵向力带0.18的恒定下落分量配合reset()中向下的初始速度与 0.97~0.99 的高阻尼模拟出雪花摇摆下落的质感。源码注释特别提示pos.y * 0.006这一项用来避免围绕 x 值出现明显的垂直条带banding删掉它即可观察到此现象——这是学习噪声采样的绝佳实验。有机运动的秘密ofSignedNoiseREADME 强调ofSignedNoise是让吸引点产生自然随机运动的关键。在 ofApp::update() 中4 个吸引点每一帧都围绕初始位置做小幅游走attractPointsWithMovement[i].x attractPoints[i].x ofSignedNoise(i * 10, ofGetElapsedTimef() * 0.7) * 12.0; attractPointsWithMovement[i].y attractPoints[i].y ofSignedNoise(i * -10, ofGetElapsedTimef() * 0.7) * 12.0;从 libs/openFrameworks/math/ofMath.cpp 的实现看ofSignedNoise是ofNoise的有符号变体ofNoise返回noise * 0.5 0.5值域为0~1见 ofMath.cppofSignedNoise直接返回底层噪声函数值值域约为-1~1天然适合作为偏移量这里乘以 12 像素。与ofRandom不同噪声是连续平滑的相邻时刻采样值相近因此吸引点不会跳变而是呼吸般缓慢漂移让粒子群的聚集中心始终在微妙变化。ofSignedNoise提供 1~4 维的重载可接受glm::vec2/vec3/vec4参数示例中大量使用(uniqueVal, pos.x * 系数, ofGetElapsedTimef() * 速度)三维采样——第一维区分个体、后两维区分空间位置与时间这正是本示例每个粒子既独立又连贯的底层原理。边界处理与渲染update()的最后一段demoParticle.cpp是可选但实用的屏幕边界约束粒子碰到左右/上下边缘时位置被钳制回窗口内并把对应轴向速度取反vel.x * -1.0实现弹性反弹。源码注释提示这段逻辑也可以在 ofApp 层面统一处理。渲染阶段demoParticle::draw()按模式着色四种模式分别使用品红(255,63,180)、黄绿(208,255,63)、蓝紫(99,63,255)、天蓝(103,160,237)最终以ofDrawCircle(pos.x, pos.y, scale * 4.0)绘制半径为scale*4的圆点——颜色的变化让模式切换一目了然。如何运行本示例openFrameworks 项目需配合 Project Generator 生成对应平台的工程文件后再编译运行各平台完整安装与编译指南见 docs/PLATFORMS.md其中 Linux 用户可参考 docs/linux.mdmacOS 参考 docs/osx.mdWindows/Visual Studio 参考 docs/visualstudio.md使用 docs/projectgenerator.md 描述的 Project Generator 导入examples/math/particlesExample目录并生成工程也可借助 scripts/linux/compileOF.sh 等平台脚本完成 openFrameworks 核心库的编译。运行后即可体验 1~4 键切换模式、空格重置、f键最近点模式禁用受力的全部交互。扩展思路在理解本示例的基础上可以沿以下方向继续深入参数化将粒子数量num、阻尼区间、力系数改为ofParameter结合 examples/gui/guiExample 制作实时调节面板多吸引点动力学把attractPoints从 4 个扩展到任意数量或让吸引点本身遵循demoParticle的运动规律形成追随者系统力的叠加当前每种模式只使用单一力可尝试将吸引/排斥/噪声力按权重叠加形成复合行为GPU 化1500 个粒子在 CPU 端逐帧更新毫无压力但若扩展到数万粒子可参考 examples/gl/gpuParticleSystemExample 与 examples/gl/computeShaderParticlesExample 将粒子逻辑迁移到着色器。粒子的核心思想始终不变——力改变速度速度改变位置阻尼保证稳定。掌握 particlesExample 的四种模式与ofSignedNoise的运用你就拿到了 openFrameworks 交互式粒子系统的完整钥匙。赞分享图形学音视频【免费下载链接】openFrameworksopenFrameworks is a community-developed cross platform toolkit for creative coding in C.项目地址https://gitcode.com/gh_mirrors/op/openFrameworks点击查看免费下载相关推荐openFrameworks GPU 粒子系统实战Ping-Pong FBO 着色器链实现万级粒子的边界反弹与火花渲染openFrameworks GPU 粒子系统实战Ping Pong FBO 着色器链实现万级粒子的边界反弹与火花渲染 GPU图形处理器粒子系统是创意图形学音视频Beads Docker部署容器化你的AI任务跟踪系统Beads Docker部署容器化你的AI任务跟踪系统 Beads作为一款强大的AI任务跟踪系统能为你的开发流程提供智能记忆升级。通过Docker容器化部署前端UI组件一键4KVideo2X免费视频超分一键4KVideo2X免费视频超分 翻出一硬盘十年前的老番全是480P。放进4K显示器每个角色脸上都糊着一层马赛克。Video2X是免费开源AGPLv3音视频视频处理图像处理深度学习上一篇如何快速上手Rusty V85个实用示例带你入门JavaScript引擎绑定下一篇探索 LaTeX 编辑的新境界LaTeX-Mimosis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考