Box2d物理引擎v230中文手册.docx

上传人:b****7 文档编号:9613450 上传时间:2023-02-05 格式:DOCX 页数:79 大小:339.24KB
下载 相关 举报
Box2d物理引擎v230中文手册.docx_第1页
第1页 / 共79页
Box2d物理引擎v230中文手册.docx_第2页
第2页 / 共79页
Box2d物理引擎v230中文手册.docx_第3页
第3页 / 共79页
Box2d物理引擎v230中文手册.docx_第4页
第4页 / 共79页
Box2d物理引擎v230中文手册.docx_第5页
第5页 / 共79页
点击查看更多>>
下载资源
资源描述

Box2d物理引擎v230中文手册.docx

《Box2d物理引擎v230中文手册.docx》由会员分享,可在线阅读,更多相关《Box2d物理引擎v230中文手册.docx(79页珍藏版)》请在冰豆网上搜索。

Box2d物理引擎v230中文手册.docx

Box2d物理引擎v230中文手册

Box2Dv2.3.0用户手册

Copyright©2007-2013ErinCatto著

Copyright©2015Antkillerfarm译

基于

AmanJIANG(江超宇)的v2.0.1用户手册

complex_ok的2.1.0用户手册

Chapter1导言7

1.1关于7

1.2先决条件7

1.3关于手册7

1.4反馈和报告BUG8

1.5核心概念8

形状(shape)8

刚体(rigidbody)8

夹具(fixture)8

约束(constraint)8

接触约束(contactconstraint)9

关节(joint)9

关节限制(jointlimit)9

关节马达(jointmotor)9

世界(world)9

求解器(solver)9

连续碰撞(continuouscollision)9

1.6模块10

1.7单位11

1.8工厂和定义11

Chapter2HelloBox2D13

2.1创建世界13

2.2创建地面盒13

2.3创建动态物体14

2.4模拟(Box2D的)世界15

2.5清理17

2.6TheTestbed17

Chapter3通用模块19

3.1关于19

3.2配置19

类型19

常数19

分配器包装19

版本号19

3.3内存管理19

3.4数学20

Chapter4碰撞模块21

4.1关于21

4.2形状21

圆形21

多边形22

边框形状(Edgeshapes)24

链接形状(ChainShapes)25

4.3单元几何查询(UnaryGeometricQueries)26

形状点测试(ShapePointTest)26

形状的光线投射(ShapeRayCast)27

4.4对等函数27

重叠27

接触形(ContactManifolds)28

距离29

撞击时间29

4.5动态树30

4.6Broad-phase31

Chapter5力学模块33

5.1概述33

Chapter6物体34

6.1关于34

b2_staticBody34

b2_kinematicBody34

b2_dynamicBody34

6.2物体定义34

物体类型35

位置和角度35

阻尼35

重力因子36

休眠参数36

固定旋转36

子弹36

活动状态37

用户数据37

6.3物体工厂(BodyFactory)37

6.4使用物体38

质量数据38

状态信息39

位置和速度39

Chapter7夹具40

7.1关于40

7.2创建夹具40

密度40

摩擦41

恢复41

筛选41

7.3传感器43

Chapter8关节44

8.1关于44

8.2关节定义44

8.3关节工厂44

8.4使用关节45

8.5距离关节46

8.6旋转关节46

8.7移动关节48

8.8滑轮关节49

8.9齿轮关节50

8.10鼠标关节51

8.11轮子关节51

8.12焊接关节52

8.13绳子关节52

8.14摩擦关节52

8.15马达关节52

Chapter9接触53

9.1关于53

接触点53

接触法线53

接触分隔53

接触流形53

法向冲量53

切向冲量53

接触标识54

9.2接触类54

9.3访问接触55

9.4接触监听器55

开始接触事件56

结束接触事件56

求解前事件56

求解后事件57

9.5接触筛选59

Chapter10世界类60

关于60

创建和摧毁世界60

使用世界60

模拟60

探测世界61

AABB查询62

光线投射63

力与冲量64

坐标转换64

列表64

Chapter11杂项66

11.1用户数据66

11.2隐式摧毁67

11.3像素和坐标系统68

Chapter12调试绘图70

Chapter13限制71

Chapter14参考72

Chapter1导言

1.1关于

Box2D是一个用于游戏的2D刚体仿真库。

程序员可以在他们的游戏里使用它,它可以使物体的运动更加真实,并让游戏世界看起来更具交互性。

从游戏引擎的视角来看,物理引擎就是一个程序性动画(proceduralanimation)的系统。

(译注:

做动画常有两种方法,一种是预先准备好动画所需的数据,比如图片,再一帧一帧地播放。

另一种是以一定方法,动态计算出动画所需的数据,根据数据再进行绘图。

 

从这种角度看,预先准备的,可称为数据性动画,动态计算的可称为程序性动画。

这个区别,就类似以前我们做历史题和数学题,做历史题,记忆很重要,也就是答案需要预先准备好的。

做数学题,方法就很重要,答案是需要用方法推导出来的。

 

Box2D就是用物理学的方法,推导出那游戏世界物体的位置,角度等数据。

而Box2D也仅仅推导出数据,至于得到数据之后怎么处理就是程序员自己的事情了。

Box2D是用可移植的C++写成的。

引擎中大部分类型的定义都有b2前缀,希望这能有效的消除它和你的游戏引擎之间的名字冲突。

1.2先决条件

在此,我假定你已经熟悉了基本的物理学概念,例如质量、力、扭矩和冲量。

如果没有,请先查询一下Google搜索和维基百科。

Box2D是游戏开发者大会(GameDeveloperConference,GDC)的物理学教程的一部分。

你可以从box2d.org的下载页面获得这些教程。

因为Box2D是用C++写成的,所以你应该具备C++程序设计的经验。

Box2D不应该成为你的第一个C++程序项目。

你应该已经能熟练地编译,链接和调试了。

注意

Box2D不应该成为你的第一个C++程序项目。

你应该已经能熟练地编译,链接和调试了。

网络上有很多关于C++的资料。

1.3关于手册

这个手册包含了主要的Box2D的API,但并不是每一个都包含了。

你可以通过阅读Box2D自带的testbed程序的代码来学习更多的东西。

而且Box2D代码的注释已经按照Doxygen格式编写,可以很容易的创建超链接形式的API文档。

这个手册只在新版本发布的时候更新。

因此相比版本库中的代码版本,它可能已经过时了。

1.4反馈和报告BUG

如果你有关于Box2D的问题或者反馈意见,请在论坛留言。

这也是社区讨论的好地方。

Box2D使用Googlecodeproject来跟踪问题。

这是个很好的方式,它可以确保你的问题不会淹没在论坛之中。

请在这里列出BUG和功能需求:

如果你能提供更有效的细节的话,就能确保你的问题得到解决。

一个用于复现问题的testbed用例是很有意义的。

你可以在随后章节读到和testbed相关的内容。

1.5核心概念

Box2D中有一些基本的概念和对象,这里我们先做一个简要的定义,在随后的章节里会有更详细的描述。

形状(shape)

形状是一个2D的几何对象。

例如圆或多边形。

刚体(rigidbody)

一块十分坚硬的物质,它上面的任何两点之间的距离都是完全不变的。

它们就像钻石那样坚硬。

在后面的讨论中,我们用物体(body)来指代刚体。

夹具(fixture)

夹具将形状绑定到物体上,并添加密度(density)、摩擦(friction)和恢复(restitution)等材料特性。

夹具还将形状放入碰撞系统(碰撞检测(BroadPhase))中,以使之能与其他形状相碰撞。

(译注:

一个物体和另一物体碰撞,碰撞后速度和碰撞前速度的比值会保持不变,这比值就叫恢复系数。

(译注:

BroadPhase是碰撞检测的一个子阶段,将空间分割,每个空间对应一个子树,物体就放到树中,不同子树内的物体不可能相交不用去计算,在同一个子树由对应的算法再计算出接触点等信息。

因为这是远距碰撞检测,就叫BroadPhase,接下来还有NarrowPhase。

约束(constraint)

约束(constraint)就是消除物体自由度的物理连接。

一个2D物体有3个自由度(两个平移坐标和一个旋转坐标)。

如果我们把一个物体钉在墙上(像摆锤那样),那我们就把它约束到了墙上。

这样,此物体就只能绕着这个钉子旋转,因此这个约束消除了它2个自由度。

接触约束(contactconstraint)

一种防止刚体穿透,并模拟摩擦和恢复的特殊约束。

你不必创建接触约束,它们会自动被Box2D创建。

关节(joint)

它是一种用于把两个或更多的物体固定到一起的约束。

Box2D支持若干种关节类型:

旋转、棱柱、距离等等。

有些关节拥有限制(limits)和马达(motors)。

关节限制(jointlimit)

关节限制限定了关节的运动范围。

例如,人类的胳膊肘只能做某一范围角度的运动。

关节马达(jointmotor)

关节马达能依照关节的自由度来驱动所连接的物体。

例如,你可以使用马达来驱动胳膊肘的

旋转。

世界(world)

物理世界就是相互作用的物体,夹具和约束的集合。

Box2D支持创建多个世界,但这通常是不必要或不推荐的。

求解器(solver)

物理世界使用求解器来推算时间,求解接触和关节约束。

Box2D的求解器是一种高性能的迭代求解器,它会顺序执行N次,这里的N是约束的个数。

(译注:

即算法的复杂度为O(N)。

连续碰撞(continuouscollision)

求解器使用时域上的离散时间步来推算物体状态。

如果没有特殊处理的话,这会导致隧穿效应。

(译注:

假设我们采用1s的固定时间间隔来推算一个物理系统的运动。

那么如果这个系统中有两个物体在某一秒的0.5s的时刻,发生碰撞的话。

死板的采用固定时间间隔计算的方法,就会导致物体实际上越过了碰撞点的现象发生,这就是隧穿效应。

解决的办法显然是要估算出碰撞发生的时刻,并做相应的处理,这也是下一段提到的TOI的含义。

Box2D拥有特殊的算法来处理隧穿效应。

首先,碰撞算法能够在两个物体的运动过程中进行插值运算,以找到首次碰撞时间(thefirsttimeofimpact,TOI)。

接着,一个分步求解器将物体移动到它们的TOI时刻,并对碰撞求解。

1.6模块

Box2D由三个模块组成:

通用模块(Common),碰撞模块(Collision)和力学模块(Dynamics).通用模块包含了内存分配、数学和配置的代码。

碰撞模块定义形状、碰撞检测和碰撞的函数或队列。

最终力学模块提供对世界、物体、夹具和关节的模拟。

1.7单位

Box2D使用浮点数,所以必须使用公差来保证它正常工作。

这些公差已经被调谐得适合米-千克-秒(MKS)单位制。

尤其是,Box2D已被调谐得能良好地处理0.1到10米之间的移动物体。

这意味着从罐头盒到公共汽车大小的对象都能良好地工作。

静态的物体就算大到50米都没有问题。

作为一个2D物理引擎,使用像素作为单位是很诱人的。

但很不幸,那将导致不良的模拟,也可能会造成古怪的行为。

一个200像素长的物体在Box2D看来就有45层建筑那么大。

注意

Box2D已被调谐至MKS单位。

移动物体的尺寸应该保持在大约0.1到10米之间。

当你渲染场景和角色时,可能要用到一些比例缩放系统。

Box2D自带的testbed例子,使用了OpenGL的视口变换。

不要使用像素!

最好把Box2D中的物体看作是被贴上了你的艺术创作品的移动广告板。

这个广告板在一个以米为单位的系统里运动,但你可以利用简单的比例因子把它转换为像素坐标。

之后就可以使用这些像素坐标去确定你的精灵(sprites)的位置,等等。

你也可以将它的坐标轴翻转过来。

(译注:

坐标轴翻转的含义是比例因子可以为负数。

Box2D里的角使用弧度制。

物体的旋转角度以弧度方式存储,并可以无限增大。

如角度变得太大,可考虑将角度进行规范化。

(使用b2Body:

:

SetAngle)

注意

Box2D使用弧度,而不是度。

1.8工厂和定义

快速内存管理在Box2DAPI的设计中担当了一个中心角色。

所以当你创建一个b2Body或一个b2Joint时,你需要调用b2World的工厂函数(factoryfunctions)。

你不应以别的方式为这些类型分配内存。

这些是创建函数:

b2Body*b2World:

:

CreateBody(constb2BodyDef*def)

b2Joint*b2World:

:

CreateJoint(constb2JointDef*def)

这些是对应的销毁函数:

voidb2World:

:

DestroyBody(b2Body*body)

voidb2World:

:

DestroyJoint(b2Joint*joint)

当你创建物体或关节时,需要提供定义(definition)。

这些定义包含了创建物体或关节时所需的所有信息。

使用这样的方法,我们能够预防构造错误,保持较少的函数参数数量,提供有意义的默认值,并减少访问子(accessor)的个数。

因为fixture必须有父body,所以要使用b2Body的工厂方法来创建并销毁它们。

b2Fixture*b2Body:

:

CreateFixture(constb2FixtureDef*def)

voidb2Body:

:

DestroyFixture(b2Fixture*fixture)

也有个简便的方法直接用形状和密度来创建fixture。

b2Fixture*b2Body:

:

CreateFixture(constb2Shape*shape,float32density)

工厂并不保留定义的引用,因此你可以在栈上创建定义,并在临时资源中保存它们。

Chapter2HelloBox2D

Box2D的发布包中有个HelloWorld程序。

程序创建了一个大大的地面盒(groundbox)和一个小小的动态盒(dynamicbox)。

代码没有涉及到图形界面,你只能在控制台中看到随时间变化的盒子位置的文字输出。

这是个很好的例子,展示了怎么学习和使用Box2D。

2.1创建世界

每个Box2D程序开始时都会创建一个b2World对象。

b2World是个物理枢纽(physicshub),用于管理内存、对象和模拟。

你可以在栈,堆或数据区中创建出world。

创建Box2D的world很简单。

首先,我们定义重力矢量。

b2Vec2gravity(0.0f,-10.0f);

现在可以创建world对象了。

注意,我们是在栈中创建world,所以world不能离开它的作用域。

b2Worldworld(gravity);

现在我们已经有了自己的物理世界,开始向里面加东西了。

2.2创建地面盒

body用以下步骤来创建:

1.用位置(position),阻尼(damping)等来定义body。

2.用world对象来创建body。

3.用形状(shape),摩擦(friction),密度(density)等来定义fixture。

4.在body上来创建fixture。

第一步,创建groundbody。

为此我们需要一个body定义。

在定义中,我们指定groundbody的初始位置。

b2BodyDefgroundBodyDef;

groundBodyDef.position.Set(0.0f,-10.0f);

第二步,将body定义传给world对象,用以创建groundbody。

world对象并不保留body定义的引用。

body默认是静态的。

静态物体和其它静态物体之间并没有碰撞,它们是固定的。

b2Body*groundBody=world.CreateBody(&groundBodyDef);

第三步,创建地面多边形。

我们用简便函数SetAsBox使得地面多边形构成一个盒子形状,盒子的中心点就是父body的原点。

b2PolygonShapegroundBox;

groundBox.SetAsBox(50.0f,10.0f);

SetAsBox函数接收半个宽度和半个高度作为参数。

因此在这种情况下,地面盒就是100个单位宽(x轴),20个单位高(y轴)。

Box2D已被调谐到使用米,千克和秒做单位。

你可以认为长度单位就是米。

当物体的大小跟真实世界一样时,Box2D通常工作良好。

例如,一个桶约1米高。

由于浮点算法的局限性,使用Box2D模拟冰川或沙尘的运动并不是一个好主意。

第四步,我们创建shapefixture,以完成groundbody。

在这步中,我们有个简便方法。

我们并不需要修改fixture默认的材质属性,可以直接将形状传给body而不需要创建fixture的定义。

随后的教程中,我们将会看到如何使用fixture定义来定制材质属性。

第二个参数是形状密度,单位是千克/平方米。

静态物体的质量定义为0,因此密度对它们是没有用的。

groundBody->CreateFixture(&groundBox,0.0f);

Box2D并不保存shape的引用。

它把数据复制到一个新的b2Shape对象中。

注意,每个fixture都必须有一个父body,即使fixture是静态的。

然而,你可以把所有的静态fixture都依附在单个静态body之上。

当你使用fixture向body添加shape的时候,shape的坐标对于body来说就变成本地的了。

因此当body移动的时候,shape也一起移动。

fixture的世界变换继承自它的父body。

fixture没有独立于body的变换。

所以我们不需要移动body上的shape。

不支持移动或修改body上的shape。

原因很简单:

形状发生改变的物体不是刚体,而Box2D只是个刚体引擎。

Box2D所做的很多假设都是基于刚体模型的。

如果这一条被改变的话,很多事情都会出错。

2.3创建动态物体

现在我们已经有了一个地面body,我们可以使用同样的方法来创建一个动态body。

除尺寸之外的主要区别是,我们必须为动态body设置质量属性。

首先我们用CreateBody创建body。

默认情况下,body是静态的,所以在构造时候应该设置b2BodyType,使得body成为动态的。

b2BodyDefbodyDef;

bodyDef.type=b2_dynamicBody;

bodyDef.position.Set(0.0f,4.0f);

b2Body*body=world.CreateBody(&bodyDef);

注意

如果你想让body受力的影响而运动,你必须将body的类型设为b2_dynamicBody。

然后,我们创建一个多边形shape,并将它附加到fixture定义上。

我们先创建一个boxshape:

b2PolygonShapedynamicBox;

dynamicBox.SetAsBox(1.0f,1.0f);

接下来,我们使用box创建一个fixture定义。

注意,我们把密度值设置为1,而密度值默认是0。

并且,shape的摩擦系数设置为0.3。

b2FixtureDeffixtureDef;

fixtureDef.shape=&dynamicBox;

fixtureDef.density=1.0f;

fixtureDef.friction=0.3f;

注意

一个动态body至少有一个密度不为0的fixture。

否则会出现一些奇怪的行为。

使用fixture定义,我们现在就可以创建fixture。

这会自动更新body的质量。

要是你喜欢,你可以为body添加许多不同的fixture。

每个fixture都会增加物体的总质量。

body->CreateFixture(&fixtureDef);

这就是初始化过程。

现在我们已经做好准备,可以开始模拟了。

2.4模拟(Box2D的)世界

我们已经初始化了地面box和一个动态box。

该让牛顿来接手了。

我们只有少数几个问题需要考虑。

Box2D使用了一种名叫积分器(integrator)的数值算法。

积分器在离散的时间点上模拟物理方程。

它与传统的游戏动画循环一同运行。

我们需要为Box2D选取一个时间步(timestep)。

通常来说用于游戏的物理引擎需要至少60Hz的速度,也就是1/60秒的时间步。

你可以使用更大的时间步,但是你必须更加小心地为你的世界调整定义。

我们也不喜欢时间步变化得太大,一个变化的时间步会导致变化的结果,这会给调试带来困难。

所以不要把时间步关联到帧频(除非你真的必须这样做)。

直截了当地,这个就是时间步。

float32timeStep=1.0f/60.0f;

除积分器外,Box2D代码还使用了约束求解器(constraintsolver)。

约束求解器用于解决模拟中的所有约束,一次一个。

单个的约束会被完美的求解,然而当我们求解一个约束的时候,我们就会稍微干扰另一个约束。

要得到良好的解,我们需要多次迭代所有约束。

约束求解有两个阶段:

速度阶段和位置阶段。

在速度阶段,求解器会计算必要的冲量,使得物体正确运动。

而在位置阶段,求解器会调整物体的位置,减少物体之间的重叠和关节的脱节。

每个阶段都有自己的迭代计数。

此外,如果误差已足够小的话,位置阶段的迭代可能会提前退出。

Box2D建议的迭代次数,对于速度是8次,对于位置是3次。

你可以按自己的喜好去调整这个数字,但要记得它是性能与精度之间的折中。

更少的迭代会增加性能但降低精度,同样地,更多的迭代会降低性能但能提高模拟的质量。

对于这个简单示例,我们不需要很多的迭代。

这里是我们选择的迭代次数。

int32velocityIterations=6;

int32positionIterations=2;

注意,时间步和迭代数是完全无关的。

一个迭代并不是一个子步。

一次迭代就是在时间步之中的单次遍历所有约束,你可以在单个时间步内多次遍历约束。

现在我们可以开始模拟循环了,在你的游戏中,模拟循环和游戏循环可以合并起来。

每次游戏循环你都应该调用b2World:

:

Step,通常调用一次就够了,这取决于帧频以及物理时间步。

这个HelloWorld程序设计得非常简单,它没有图形输出。

代码会打印出动态body的位置以及旋转角。

这就是模拟1秒钟内60个时间步的循环。

for(int32i=0;i<60;++i)

{

world.Step(timeStep,velocityIterations,positionIterations);

b2Vec2position=body->GetPosition();

float32angle=body->GetAngle();

printf("%4.2f

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 判决书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1