目录列表
1. 介绍
2. The Havok World
2.1. Creating an hkpWorld
2.2. Adding simulation elements
2.3. Entities
3. Rigid Bodies
3.1. Creating a Rigid Body
3.2. Adding a Rigid Body to the World
3.3. Removing a Rigid Body from the World
3.4. Changing the motion state
3.5. Rigid body collisions
3.6. Deactivation
3.7. Keyframed objects
4. Stepping the simulation forward
4.1. Synchronous stepping
4.2. "Half" stepping
4.3. Asynchronous stepping
4.4. Multithreaded stepping
5. Phantoms
5.1. hkpAabbPhantom
5.2. hkpShapePhantom
5.3. hkpPhantomCallbackShape
5.4. User hkpPhantom types
5.5. Using hkpPhantoms
6. Scale
7. Constraints
7.1. About constraints
7.2. Constraint types
7.3. Tuning and tweaking constraints
8. Constraint Chains
8.1. Introduction
8.2. How to use chains
8.3. Interface to the chains
8.4. Limitations of the Technology
8.5. What demos to look at
8.6. Performance Issues
8.7. Powered Chain Mapper
9. Actions
9.1. About Actions
9.2. Example actions
9.3. Creating a custom action
9.4. Important points when using actions
10. Listeners
10.1. Callbacks and events
10.2. Listener types
11. Postponing of Operations
12. Simluation Determinism
13. Memory Issues
13.1. Memory Capping
13.2. Memory Watchdogs
14. Saving Contact Points
14.1. Methods and parameters for saving
14.2. Methods and parameters for loading
14.3. Serialization
14.4. Limitations
Havok代码编辑模块,hkpDynamics是Havok系统最重要的模块。它允许你创建一个模拟的物理世界,并与相关的模拟物体关联,及时的进行模拟,以及与模拟进行交互。
这一章将会介绍如何:
l 创建和使用Havok 世界
l 创建和使用刚体,包括关键帧物体
l 创建和使用仿真物体
同时介绍三种其他类型的模拟元素——constraints,actions,listeners——在它们自己的章节会有更加详细的介绍。
每一个Havok模拟都会有一个或多个Havok世界——类hkpWorld的实例。hkpWorld在你的模拟中扮演着物理物体容器的角色,也用来及时的模拟。
HkpWorld被分成几个不同的组,叫做“岛”(island)hkpSimulationIsland,可以因为不同的目的分别进行模拟(这是被系统动态设置的)。
hkpWorldCinfo包含了创建hkpWorld对象的全部所需信息,你可以用它来创建Havok世界。你可以为hkpWorld指定下面的详细信息,或者你可以用默认的:
l 重力:一个hkpWorld的重力被应用到它所有的模拟对象。这个参数的默认值反映了“真实世界”的重力(在Y方向上值为-9.8,Havok默认的正方向是向上的)。在你的游戏世界中也可以用不同的重力设置(一会儿呢,你将会在所有轴的方向上定义重力为0),用你自己的重力轴(你的引擎可能会用Z轴作为向上的方向)。重力需要用一个hkVector4来指定。在游戏中使用始终不变的重力是很常见的,它已经被放到主要的引擎中了,而不是作为一种动作(action)来设置的。更多复杂的重力模型可以作为一个Action来使用、贯彻。
l Broadphase。m_broadphaseWorldAabb.m_min和m_broadphaseWorldAabb.m_max允许你来设置为你的hkpWorld的广检测的碰撞检测。默认的Broadphase设置时一个长为1000.0的盒子(如果你用推荐的比例尺的话,就相当于是一个1000米的立方体),m_broadPhaseQuerySize允许你设置广检测的重叠部分的本地数组的大小。你可以在碰撞检测这章弄清更多关于广检测和改变大小所带来影响的信息。
l Solver(解决者、处理)。Havok模拟使用一个Solver来计算必要的改变来减少所有系统默认参数的错误。hkpWorldCinfo有一些方法来让你设置这个Sovler的类型。每种Solver为模拟提供不同的速度或者准确度。Solver的行为取决于Solver在每一步计算变化、tau值、阻尼值时进行多少次演算。(原句是:The solver behavior depends on how many iterations the solver goes through in each step when calculating the changes, and the tau and damping values used by the solver.)。你可以在Solver介绍中读到更多在模拟中关于Solver的信息。一般来说,检测次数越多,准确性越好。如果你觉得这太危险,你可以直接设置solver的参数,否则你可以看hkpWorldCinfo里完整的Solver类型列表。
l 碰撞偏差。这允许你指定hkpWorld的碰撞偏差的值——默认是0.1(或者如果你使用推荐的米计量单位,就是10cm了)。你可以在碰撞检测这一章找到关于这个值和它的影响的信息。
l 钝化。在一般的场景中许多物体是不会动的,因此他们不需要和那些可移动物体一样来更新。许多数据在模拟步中都是保持不变的。世界可以通过时间进程监视它们的相对运动来判断出哪些是应该被弄失效的物体。它是根据两个频率监视移动来减少相同频率摆动的物体发生钝化。有一个标志m_enableDeactivation来控制监视的开关。为了节省一些CPU,我们并不是每帧都对所有对象进行检查,而是每个第四帧检查(这是高频率检测),还有一个每个第16帧检查的辅助检测(低频检测)。如果一个组里的所有对象的标志都是钝化,那么这个组就被钝化了。一般的,这个组就是一个岛(island),然而因为执行的原因,引擎可能会将独立的组合并成一个“稀疏”岛。
l 线性抛出。线性抛出是使用凸边形搜索世界找碰撞点的技术(能力)。这对角色和运动的精确接近检测很有帮助。这种抛出是一种迭代算法,因此迭代的最大次数受执行的限制,精确性的改进受容许残留值m_iteraiveLinearCastEarlyOutDistance的影响。如果你改变了碰撞残留值,那么这个变量亦应该改变,通常是碰撞残留值的十分之一。
l 混杂的碰撞参数。当通过动态链接库(as opposed to by itself for just collision detection)使用hkpCollide时,你可能需要扭曲碰撞偏差。这在hkpWorldCinfo中可能会被袒露出来,除了先前提到的主要的碰撞偏差。其他的一些参数在碰撞检测章节会有更多的信息,在hkpWorldCinfo的参考手册中也有说明。
l 连续模拟参数。连续模拟和碰撞检测使用一组内部安全的最优的参数。它们大多来自hkpWorldCinfo中暴露出来的参数。
表 2.1. 连续模拟初始化参数
Parameter |
Purpose, Values |
m_simulationType |
选择模拟类型. 类型有SIMULATION_TYPE_DISCRETE, SIMULATION_TYPE_CONTINUOUS, SIMULATION_TYPE_MULTITHREADED |
m_expectedMaxLinearVelocity |
假定物体的最大线速度.这并不是在对象中设置线速度.如果以后, 钢铁如果明显的快于这个速度, it might tunnel through other objects even if its qualityType is set to critical. 默认是200 meter/second |
m_expectedMinPsiDeltaTime |
Minimum expected physical simulation delta time. Defaults to 30 Hertz |
m_contactPointGeneration |
允许接触点设置在负的距离, 者可以加速模拟, 但是对于小物体来说并不是很好. See Collision Detection chapter for details. It defaults to CONTACT_POINT_REJECT_MANY. See the Reference Manual for details. |
下面的例子显示了如何创建一个hkpWorld。正如你所看到的,你简单的创建一个kpWorldCinfo,设置你想要设置的值,然后将它传给hkpWorld的构造函数就可以了。
hkpWorldCinfo info;
info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_DISCRETE;
info.m_gravity.set( 0,-9.8f,0);
info.m_collisionTolerance = 0.1f;
info.setBroadPhaseWorldSize( 150.0f );
info.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM );
m_world = new hkpWorld( info );
一旦你创建了hkpWorld,你可以使用hkpWorld的函数来得到或者设置所有hkWorldCinfo的值。
注意:
当你是将Havok融入到你的游戏中,而不是使用我们的示例框架时,你就需要确保在创建和使用hkpWorld之前hkBaseSystem::init()被调用来初始化Havok内存系统和其他系统服务。
在示例框架中者被相关的图形系统接口动态调用了。你可以在Havok基础库章节的BaseSystem部分找到更多关于这个函数的信息。
模拟元素比如刚体、模型、系统规定系数、动作和监听器,需要添加到hkpWorld里来参与模拟。hkpWorld提供了许多函数来添加和移除不同种类的模拟元素——比如,你添加一个约束就用addConstraint()。你可以在本章之后的部分找到更多关于如何使用这些函数的信息。
注意:
hkpWorld::add(hkSerializable*)被串行化框架在内部使用。你也可以用它来添加任何可串行化的物体到hkpWorld。但是它所做的一切只是检查串行类型和相应的添加方法。
添加到hkpWorld中的被模拟的物理物体叫做实体。实体的基类是hkpEntity,该类提供了许多函数和数据成员。目前在Havok中只有一种实体类型,就是hkpRigidBody。
任何真实世界的物体并不改变他的形状——从汽车框架到一个滚下山的卵石都是这样的——可以在Havok中作为刚体来进行模拟。
刚体是Havok动力系统的中心,如果你用