最近在转型做游戏,那么阅读Box2D当然是件必要且愉快的事情。

Box2D的源码地址https://github.com/erincatto/Box2D

Box2D的官网 http://www.box2d.org

Paladin的Box2D克隆地址 https://github.com/PaladinDu/Box2D.git

这个克隆目前并没有新增内容,只是增加了一些中文注释。

在后续的学习过程中可能会添加一些demo到Testbed中。

选择从void b2World::Step说起是因为Step是Box2D对一个逻辑针的实现。

我想这应该是一个物理引擎核心的代码了。

了解了Step,你就了解了物理引擎的逻辑结构。

当然Box2D之所以这么优秀,与其背后高超的结构设计,碰撞算法,逻辑优化同样密不可分。

不过本文旨在在流程上了解Box2D。

将只会对Step进行一定的展开。

首先让我们看下step的声明

/**@brief 处理一个逻辑帧*@param dt 逻辑帧的时间长度*@param velocityIterations 速度计算迭代次数,*@note 将一个逻辑帧内的速度计算迭代velocityIterations次,迭代的次数越多,碰撞传导的速度越快*@param positionIterations 位移计算迭代次数*@note 迭代的次数越多,解决刚体重叠的速度越快*/void b2World::Step(float32 dt,int32 velocityIterations,int32 positionIterations);

b2World::Step 的流程:

1 如果有新的刚体(Fixture)就执行一次基础碰撞检测。

这里有两点需要说明:

1.1 Box2D创建了一个AABB碰撞树,来对物体的碰撞进行基础检测。

1.1.1 先说AABB是什么鬼。

AABB的描述:

  1. AABB是一个旋转永远为0的矩形。
  2. 每一个刚体都会产生一个AABB。
  3. AABB会将刚体包裹,且比刚体略大(至少是略大)。

1.1.2 再说说AABB碰撞树是什么鬼

AABB碰撞树的描述:
  1. AABB碰撞树是二叉平衡树。
  2. 每一个叶子节点都是一个刚体的AABB。
  3. 非叶子节点也是一个AABB,但并不是刚体的AABB。
  4. 父节点的AABB总是包涵子节点的AABB。
  5. 新的叶子节点插入是第一优先级是保持树的平衡。
  6. 第二是插入到而两个子节点中(由于两个节点并没有排序,所以请允许我使用第二个来形容它的位置)。
  7. 详细的树处理操作在b2DynamicTree.cpp中。

1.2.3 使用AABB碰撞树进行初步检测

使用AABB碰撞树无疑是为了进行初步筛选,在AABB都无法碰撞的情况下刚体肯定无法碰撞。而且矩形碰撞检测极其简单(只需要检测矩形的右上角是否在B的左下角的左边或下边和与B的右上角是否在A的左下角的左边或下边)。而在查询的时候只需要使用刚体的AABB在树中进行遍历(剪掉节点AABB与刚体AABB不碰撞的节点及其子节点)就能初步获取所有可能产生碰撞的刚体。并组成碰撞元素(Contact)。

1.2 并不是说没有新的刚体产生就不进行碰撞处理

由于老的刚体在上一帧的逻辑处理是就已经进行过初步碰撞检测。所以这里是由于新的刚体没有处理过所以需要进行一次初步碰撞检测。

2 进行准确碰撞检测,并对真实碰撞的碰撞元素进行碰撞初始化

在进行准确碰撞检测时会排除掉一些不活跃的、重复的、无效的碰撞元素。并根据刚体的类型进行碰撞初始化。详细碰撞实现在
void b2Collide??(b2Manifold* manifold,constb2CircleShape* circleA,constb2Transform& xfA,constb2CircleShape* circleB,constb2Transform& xfB)

中。当??为一个刚体类型是,是同类型刚体碰撞否则将形如b2Collide{typeA}And{typeB}。

不同类型的碰撞是有向的不会出现b2CollideTypeAAndTypeB与b2CollideTypeBAndTypeA两种碰撞。

碰撞初始化的内容主要是记录碰撞体的发力点(point),以方便后续物理模拟计算。比如说圆与圆碰撞时point并不是交点二十圆心。

碰撞完毕后还会更具条件触发开始碰撞或者结束碰撞。

值得注意的是,如果一个刚体被标记为传感器(sensor)的话,他是不会触发碰撞初始化处理的。需要注意的是,他只会出发开始碰撞和结束碰撞,并不会持续发送碰撞信号。如果一个刚体没有被标记为传感器,在发送碰撞时她还会回调

virtual void PreSolve(b2Contact* contact,constb2Manifold* oldManifold)

这个方法本意是允许用户进行自定义个物理模拟。当然了,你也可以拿来作别的事情。

2.1. 传感器是什么鬼

传感器是一种会发送碰撞信号但不进行系统物理碰撞模拟的刚体(你也可以自己模拟碰撞效果)。
传感器是可以穿过边界的,他真不会进行任何系统的物理碰撞。所以如果一个传感器在高速运动。你需要在有需要的时候销毁它。
当我们要模拟一些技能效果的时候,就可以使用传感器。当然传感器并不只是这一个用途,至于其它用途就要看你的想象力了。

3 在需要的时候进行物理模拟

Box2D在进行物理模拟(也包括下面的连续物理模拟)时使用到了island减小计算规模。Box2D将大量需要进行模拟的元素分为一个一个的island,然后再进行物理碰撞模拟。

3.1 island是什么鬼

island的定义:

  1. island 由刚体,碰撞元素,连接器(joint)组成。
  2. island 与island 之间互不影响(这是island存在的理由,也使得Box2D对island可以生成一个处理一个)。

大量的刚体,碰撞事件和连接器被分为多个island后可以有效的降低物理模拟是消耗的计算资源。原因是碰撞的算法复杂度为O(n2)。这也是为什么一个复杂机器我们会将其分为几个小的模块进行模拟,而不是使用单个动力驱动并将其组为一个整体。

3.2 连接器又是什么鬼

有的时候我们并不会实现整个物理结构的模拟(比如引擎带动车轮旋转),而是选择在更宏观的层面进行模拟(引擎运作时轮子就会转,但实际上两者之间没有进行物理联系),忽略掉这些细节是为了更高速的进行模拟。同样的,连接器也是为了在较为宏观的层面对一些看似简单其实很复杂的物理逻辑进行模拟。
举个栗子,b2PulleyJoint 滑轮连接器。
如果我们想要使用原始的物理定力进行模拟我们需要怎么做?(这还是在理想状态进行模拟)
  1. 将绳子分割为无数个(很多,比如1个单位分割为10000份,这里有夸张的成分)小线段。
  2. 相邻的两个小线段受到大小相同方向相反的拉力(绳子是没有压力的,当然在滑轮中不需要考虑这一点)。
  3. 将滑轮设定为一个可以旋转,永远进行静摩擦,且旋转阻力为0的圆。
  4. 对其进行物理模拟。绳子一端的开始线段受到一个拉力,并不断的通过下一线段进行传导力,滑轮可以有效的改变力的方向。
我相信,同样可以完成对滑轮的模拟。但这样做会增加会增加成吨的计算量。
而我们使用滑轮连接器进行模拟。
  1. 力的发力方向为 发力点与圆的切点 指向 发力点 的方向。
  2. 力的受力方向为 受力点 指向 受力点与圆的切点 的方向。
  3. 发力与受力大小相同。
完了,毫无疑问,使用模拟的方式更高效,甚至更真实(理想状态内的真实)。如果你有兴趣还可以给滑轮加个阻尼(b2PulleyJoint是有添加这一属性的)。

综上所诉,使用模拟的方式表现某些物理结构会更高效且真实。然后Box2D将这些模拟进行了一些整合,也就成了现在的连接器了。

3.3 物理碰撞模拟的流程

1.将碰撞元素,刚体,链接器分为一个个island。
2.进行island内部物理碰撞模拟。
2.1 更新整体的线速度,角速度。主要是环境产生的速度影响,如重力,阻尼,浮力。Box2D中对速度是有限制的。这是为了减轻物理冲突事件发生的概率(比如穿越),速度越快发生的可能性就越高。
2.2 多次迭代 连接器与碰撞元素 对刚体速度产生的影响。迭代次数越多越真实,因为在一个逻辑针的事件 类由于速度在改变实际上可能已经产生很远的连锁反应,需要多次迭代计算才可以将影响传递过去。
2.3 更具最新的速度更新位移。这里也做了速度限制。
2.4 多次迭代 位置修复,防止物体被挤的连到一起了。迭代次数越多修复效果越好。当然是在没有空间的地方多次迭代会导致资源浪费。
2.5 出发碰撞元素影响信号。你可以在回调中获取到碰撞中由速度产生的力(Impulses)。举个栗子,你可以根据这个值来计算伤害,而不是简单的使用碰撞给固定伤害。
2.6 标记不活跃刚体。这样可以减少变化较少的刚体的计算。
3.更行AABB,以及基础碰撞检测以方便下一针的处理。  

4 在需要的时候进行连续物理模拟

4.1 为什么要进行连续物理模拟

我们知道现实世界的时间是连续的。但是物理引擎中的时间确实粒子化的,无论几秒中计算多少次都无法模拟连续的时间(更何况由于cpu或gpu算力有限,时间1秒进行的计算次数并不多)。这就产生了一个问题,如果一个物体移动速度够快,在两次物理模拟计算中间穿越了另一个物体,引擎是无法发现的(一般情况下)。而连续物理模拟就是为了缓解这一问题。

4.2. 连续碰撞物理模拟的对象

连续碰撞只会针对标记为bullet的刚体进行处理。

4.3 连续碰撞物理模拟的流程

1. 将Bullet 的碰撞元素,连接器分为一个个island。直到再也获取不到island就会直接结束。
1.1 获取一个bullet。
1.2 获取bullet最块发生的碰撞元素。
1.3 获取该碰撞元素的两个刚体小范围内的碰撞元素(不会连续感染,速度太快了还没传递过去?)
2.进行island内部物理碰撞模拟。
2.1 基本流程与物理模拟相同,区别的是这里只会更新速度,不会更新位移。不用太担心(在一些极端情况下连续物理模拟还是会失效)在连续碰撞物理模拟前bullet就已经穿越了。实际上连续模拟是提前模拟了下一针的速度影响。
2.2 返回第1个步骤,寻找下一个最快碰撞的碰撞元素。
到此Step就说完啦。
期待下一次更新!!!

解读Box2D (1)核心入口 void b2World::Step相关推荐

  1. DDIM代码详细解读(3):核心采样代码、超分辨率重建

    Diffusion models代码解读:入门与实战 前言:之前写过三篇详细解读DDPM代码的博客,随着时间已经来到2022年10月,单纯使用DDPM已经逐渐被淘汰,最新的论文更多使用DDPM的改进版 ...

  2. MeanTeacher文章解读+算法流程+核心代码详解

    MeanTeacher 本博客仅做算法流程疏导,具体细节请参见原文 原文 原文链接点这里 Github 代码 Github代码点这里 解读 论文解读点这里 算法流程 代码详解 train_transf ...

  3. FixMatch文章解读+算法流程+核心代码详解

    FixMatch 本博客仅做算法流程疏导,具体细节请参见原文 原文 查看原文点这里 Github代码 Github代码点这里 解读 FixMatch算法抓住了半监督算法的两个重要观点,第一个是一致性正 ...

  4. 【智能制造】38页超赞PPT解读智能制造核心要素及其标准化!

    文丨 欧阳劲松 机械工业仪器仪表综合技术经济研究所所长.教授级高工欧阳劲松先生在首届世界智能制造大会标准化分论坛上的演讲PPT.欧阳劲松先生也是工信部最新成立的智能制造专家咨询委员会委员. BCG波士 ...

  5. 【观察】解读StarCard新核心系统:全新跨越,生态赋能

    申耀的科技观察 读懂科技,赢取未来! <Bank 4.0>一书在2019年席卷全球,此书的副标题是"金融服务无处不在,就是不在银行网点",看似大胆的预测却在今年成为了现 ...

  6. 2022年的网络工程师就业前景解读三个核心转变方向

    许多朋友都在我的后台留言,询问我们作为网络工程的的就业前景或者说未来是什么样子的? 网络工程师是弱电与通讯工业中的一个重要组成部分,一般来说,网络工程师分为售前.实施.售后.运维,当然也有一些以产品开 ...

  7. 飞桨全新发布,核心框架首次完整公开解读

    导读:11 月 5 日,在 Wave Summit+2019 深度学习开发者峰会上,飞桨全新发布和重要升级了最新的 21 项进展,在深度学习开发者社区引起了巨大的反响.很多未到场的开发者觉得遗憾,希望 ...

  8. Box2D v2.0.1 用户手册

    Box2D v2.0.1 用户手册 原文:Box2D v2.0.2 User Manual 译者:Aman JIANG(江超宇),翻译信息. 1. 导言 1.1 关于 Box2D 是一个用于游戏的 2 ...

  9. Box2D物理引擎的使用方法

    转:http://www.toswf.com/blog/blogview.asp?logID=103 众所周知的Box2DFlash是一款不错的物理引擎,如果我们了解了他的使用的技巧,我们也可以做出不 ...

最新文章

  1. 独立云计算服务商的多维实践之道:用户需求驱动变革
  2. python3多线程----锁机制
  3. 动态改变_【学校动态】在坚守与改变中追求卓越——礼县二中召开2019—2020学年度秋季学期第二次全体教职工大会...
  4. java 循环查询list_Java用list储存,遍历,查询指定信息过程详解
  5. 如何在Hibernate中维护表的历史记录
  6. 用javascript生成指定范围的随机数
  7. Dubbo 本地存根
  8. HTTP Keep-Alive的作用
  9. 语言 泰克示波器程序_泰克Tektronix 任意波函数发生器AFG2000系列AFG2021
  10. java 设计模式学习笔记四 prototype模式
  11. DirectX修复工具有什么用
  12. Linux vi 命令创建,Linux vi命令 创建文件
  13. clone git 修改保存路径_SEO优化知识一般需要了解什么代码_学云网
  14. Android自动化测试之Monkey
  15. C#编程:常用数学函数
  16. 专题-参数方程与极坐标
  17. iOS 小数向上、下取整
  18. 征兵系统集合版(登录系统+信息填写及查看功能)
  19. leetcode 给我上了深深的一课,被删掉所有题解后的我感动了
  20. 荣耀v30能用鸿蒙吗,荣耀30、V30和20系列等用户有福啦

热门文章

  1. DirectX Jun2010 安装error S1023
  2. jqueryMobile 过度
  3. 农业物联网的智慧解决方案
  4. geojson 数据如何合并区域的边界?
  5. rom个性刷机也完美,你刷机了吗?
  6. 地球的“3D大片”来了!高分多模卫星首批亚米级立体影像公布
  7. ZYNQ PL通过EMIO ETHE1外接PHY由GMII转RGMII
  8. 智慧养老解决方案有哪些新行业诞生?
  9. 物理学专业英语(词汇整理)--------07
  10. 最全的Creator游戏优化方案(一)