小萌新刚开始学OpenGL,想做一个三维小球碰撞模拟。一开始试了好多写法,但都有问题,不断改进,终于完成了,感觉有必要记录一下。

首先,为了能够无限添加小球,我采用链表结构,并定义了小球结构体,其中包含小球的各个物理属性。

struct ball {glm::vec3 position; //球心坐标glm::vec3 speed; //速度矢量glm::vec3 color;//可有可无float r; //小球半径float m; //小球质量struct ball* next;
};

在渲染循环里面加上p->position += p->speed * deltaTime;实现小球移动。deltatime为渲染的时间间隔。

然后就是简单的循环,用来筛选发生碰撞的小球。

struct ball* p = head;
struct ball* q;while (p != NULL) {      q = p->next;while ((q != NULL)) {if ((veclength(p->position - q->position) <= (p->r + q->r))) {}q = q->next;}p = p->next;}

接着最关键的就是发生碰撞的两个小球的代码了。

一开始,我尝试先在草稿纸上,把碰撞后的速度算出来。然后if他们之间的距离小于半径之和,就给他们的速度附上碰撞后的值。

然而,当我满怀期待地运行的时候,发现只有少数小球符合要求,大多数小球刚一碰撞,就直接飞走了。于是我只好回来再看代码,发现可能是因为重复判定。也就是赋值完速度之后的下一帧,他们可能还没有分离,这时候又会给速度赋值一次。

于是我添加了一个开关,当两个球分离之前,只会执行一次碰撞速度赋值。

当我运行的时候又发现,当两个球未分离的时候,如果有第三个球撞上来,那第一个球和第二个球就会发生重合。这也是不对的。

觉得这个问题过于复杂的我决定另辟蹊径。想到了一种更接近自然界本质的方法,那就是弹力。小球碰撞速度的改变,终究还是因为他们之间的相互作用力,给了他们加速度。

于是我在小球属性里面添加了加速度glm::vec3 a,并且在渲染循环里面添加了p->speed += p->a * deltaTime;当小球发生碰撞时,根据质量反比,赋给他们分离的加速度99999.0f/m。

   if ((veclength(p->position - q->position) <= (p->r + q->r))) {p->a = glm::normalize(p->position - q->position) * 999999.0f / p->m;q->a = glm::normalize(q->position - p->position) * 999999.0f / q->m;}

经过不断实验,我发现虽然这样解决了上述问题,但是又出现了新的问题:

1、当两个质量较小的球,即使以很慢的速度碰撞,碰撞之后速度会变得很大。

2、当多个小球竖直叠在一起时,会发生严重的弹跳。

3、同一个小球无法同时和多个小球同时碰撞

针对上述问题我又进行了改进。

对于问题1、2,是因为当两个小球分离或者接触的瞬间,和加速度改变的瞬间有误差。这是由于小球的移动终究是离散的,不是移动的。于是我想到了把恒力改为随小球距离变化的保守力。并且当小球刚接触的时候,这个力得趋于0,并且要随距离减少快速增加(防止球质量过大时吞球)。于是我选择了指数函数,A^x^2-1.具体需要自己调试。

对于问题三,是因为一开始加速度用的是=,不能叠加,于是我改成了+=。完美(我觉得)解决了上述问题。

此外,由于自然界不存在完全弹性碰撞,因此我加了一个随速度阻尼,保证熵增。

最终代码如下:

void BALLMOVE() {struct ball* p = head;struct ball* q;while (p != NULL) {      p->speed += p->a * deltaTime;p->speed += 30.0f * deltaTime * glm::vec3(0, -1, 0);//这是重力加速度p->position += p->speed * deltaTime;q = p->next;p->a = glm::vec3(0, 0, 0);while ((q != NULL)) {if ((veclength(p->position - q->position) <= (p->r + q->r))) {float k = fabs(veclength(p->position - q->position) - (p->r + q->r));float kn = pow(7,k*k)-1;p->a += kn*(glm::normalize(p->position - q->position) * 999999.0f - (p->speed - q->speed) * 100000.0f) / p->m;q->a += kn*(glm::normalize(q->position - p->position) * 999999.0f - (q->speed - p->speed)*100000.0f) / q->m; }q = q->next;}p = p->next;}}

将这个函数插入到渲染循环里面,就可以实现小球碰撞啦。

OpenGL三维小球碰撞实现方法(glm、glfw)相关推荐

  1. Simscape基础教程之实例(一)——使用Simscape三维物理仿真自由落体小球碰撞平面

    一. 简介 本实例使用MATLAB/Simulink里面的simscape,实现自由落体小球碰撞平面的三维物理仿真,可用于新手入门simscape的参考示例. 二. 准备工作 需要安装的工具箱 (1) ...

  2. 三维投影总结:数学原理、投影几何、OpenGL教程、我的方法

    如果要得到pose视图,除非有精密的测量方法,否则进行大量的样本采集时很耗时耗力的.可以采取一些取巧的方法,正如A Survey on Partial of 3d shapes,描述的,可以利用已得到 ...

  3. OpenGL三维图形编程技术(转)

    人们对三维图形技术的研究已经经历了一个很长的历程,而且涌现了许多三维图形开发工具,其中SGI公司推出的GL(Graphics Library)三维图形库表现尤为突出,它易于使用且功能强大.随着计算机技 ...

  4. 01 C语言实现动态气泡碰撞和移动的效果,小球碰撞,Win7气泡壁纸,碰撞算法

    C语言实现动态气泡碰撞和移动的效果 作者 将狼才鲸 创建日期 2023-01-29 Git源码仓库地址:C语言实现动态气泡碰撞和移动的效果 CSDN文章地址:01 C语言实现动态气泡碰撞和移动的效果 ...

  5. OPENGL三维场景搭建、漫游、交互

    OPENGL三维场景搭建.漫游.交互 标签(空格分隔): OPENGL 这是博主的一次实验,实验截止日期还没有到.等deadline过后,博主附上源码. 源码地址:更新:OPENGL三维场景搭建.漫游 ...

  6. Java反弹球两球相撞_java实现小球碰撞反弹

    java实现小球碰撞反弹 java实现小球碰撞反弹 首先我们要在一个窗口里面显示这个功能,因此引入JFrame类然后创建一个窗口代码如下: JFrame win=new JFrame();//新建窗口 ...

  7. JS实现小球碰撞边界反弹-点击消失(详细解析实现思路)

    本篇文章给大家带来的是原生JS实现小球碰到边界就反弹,点击小球时小球被会销毁,并重新创建一个小球,让小球的数量一直保持在初始的数量,按照思路按步骤进行讲解,只需要源码的小伙伴可以定位到文本末尾直接复制 ...

  8. js 小球碰壁反弹and小球碰撞

    好像好几天没有更博了呢,最近有点变懒了,这样不好,不好~~我们要做热爱学习的好孩子,嘻嘻,今天下午补上... 我们在学习js的时候,一个很经典的案例就是小球的碰壁反弹效果啦~简单的小球碰壁效果可以慢慢 ...

  9. 绘制canvas彩色泡泡小球碰撞

    globalCompositeOperation带来的不一样的烟花 一.知识点 1.动画: setInterval(             function(){                 d ...

  10. 服务器物理碰撞检测,一种在服务器端实现三维游戏碰撞检测的方法

    1.一种在服务器端实现三维游戏碰撞检测的方法,其特征在于,包括:在三维游戏场景中的物体外面预置一个包围体,所述包围体包围该物或物的主要部分,表示包围体的面的数值存储于游戏地图文件中:在游戏玩家的外面预 ...

最新文章

  1. Firewall防火墙应用案例
  2. 发展大数据还有三道坎要迈
  3. C/C++中程序内存区域划分大总结
  4. Java Formatter locale()方法与示例
  5. 打开运行PS、AI等软件时卡在启动窗口的解决办
  6. 过滤器在图纸上的符号_看不懂电气图纸?资深级老师傅教你如何识图,学会后受用一生...
  7. proteus三输入与非门名字_商标取名大全-有创意的2020商标名字大全
  8. ARTS打卡计划第一周-Tips-ControllerAdvice的使用
  9. vc mysql ado blob_在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。...
  10. android+图标自动排列,Android用RecyclerView实现图标拖拽排序以及增删管理
  11. j2me模拟器qq2007_如何在J2ME中创建MIDlet
  12. 基于单片机和C语言的毕业设计,毕业论文基于51单片机的C语言程序设计实训100例(1)(喜欢就下吧)...
  13. 肖忠付武汉大学计算机学院,丁立新(武汉大学计算机学院教授)_百度百科
  14. Base32 应用与原理解析
  15. 逻辑教育大厂必备IOS面试突击班
  16. python模糊层次分析法案例_python实现AHP算法的方法实例(层次分析法)
  17. 不同因子影响下的不同情境的世界气温预测(的辣鸡tkinter UI可视化DEMO)
  18. Android实现通过浏览器点击链接打开本地应用(APP)
  19. CEF 最新版本自己编译加上支持播放MP4视频
  20. Python学习笔记(八)爬虫基础(正则和编解码)

热门文章

  1. TMDB 5000电影数据集
  2. cad灯具图标_CAD图纸灯具图例
  3. PCL RANSAC点云配准
  4. JEECG框架自定义下拉框
  5. bch编码matlab,BCH码的编码方法.doc
  6. 算法——排序——快速排序图解动画
  7. 对DS证据理论的改进如yager、bayes、孙权、murphy的改进处理,及皮尔逊改进处理
  8. 小程序好看的表单样式
  9. Element 表单样式调整
  10. 数学建模:现代优化算法之粒子群算法