这里谈到的基于最新的2010的版本的havok,基本的初始化,更新,卸载都可以参考StandAloneDemos\ConsoleExampleMt 这是一个唯一的例子脱离了havok晦涩的框架,一些简单的测试都可以从这个开始。
值得提到的关键几点:
1. 怎么跟渲染引擎结合: 大部分物理引擎跟渲染引擎结合,基本上都是
while(notquit)
{
update_physics();
update_render();
}
根据物理更新的结果来更新渲染。
比较好的更新方式:
static float curTime = 0;
static float timeStep = 1.0f/60.0f;
static int maxSteps = 20;
curTime += dt;
if(curTime > (maxSteps + 1) * timeStep)
curTime = (maxSteps + 1) * timeStep
while(curTime >= 1.0f/60.0f)
{
update_physics();
curTime -= timeStep;
}
updaerRender();
这样的更新方式保证了物理以60fps的频率更新,同时也避免了在渲染耗时的情况,物理得不到足够的更新的情况。
更新完物理,就可以可以跟新渲染物体的位置了, 一般的情况我们都有列表一个维护所有物体,但是我们不需要遍历整个列表来更新我们的渲染物体,只需要从active simulation islands中取出我们的物体
更新他们的坐标和旋转就可以了,因为在active island中的物体才会有所变化, 2个盒子发生碰撞的时候,在别的地方的刚体we don`t care:)
const hkArray<hkpSimulationIsland*>& activeIslands = mhkpWorld->getActiveSimulationIslands();
for(int i = 0; i < activeIslands.getSize(); ++i)
{
const hkArray<hkpEntity*>& activeEntities = activeIslands[i]->getEntities();
for(int j = 0; j < activeEntities.getSize(); ++j)
{
hkpRigidBody* rigidBody = static_cast<hkpRigidBody*>(activeEntities[j]);
if (!rigidBody->getUserData())
{
continue;
}
RigidbodyObject* obj = (RigidbodyObject*)(rigidBody->getUserData());
obj->postStep(mTimeStep);
}
}
userData里维护着我们包裹的object的指针, 通过取出havok刚体的transfrom就可以更新了,下面是RigidbodyObject postStep的实现。
void RigidbodyObject::postStep( float dt )
{
if (!mRenderObj)
{
return;
}
hkTransform transform;
mRigidBody->approxCurrentTransform( transform );
mRenderObj->SetPosition(nsHavokUtility::convertFromhkvector4(transform.getTranslation()));
hkQuaternion qua(transform.getRotation());
mRenderObj->SetOrientation(Qua(qua(3),qua(0),qua(1),qua(2))); // x,y,z,w -> w,x,y,z
} // mRenderObj 是我们的渲染物体的指针, IRenderObject类型的纯抽象接口,不同的渲染引擎实现他的接口就行了, so 不需要care 是ogre还是irrlicht还是别的。
2. havok的头文件分的非常细,非常多, 按照功能分的很明确, 大量使用了前置声明以减少头文件的依赖,缺点是如果你想使用某个模块或是功能都需要自己去手动include,不像ogre的ogre.h包含基本上所有的头文件。
3. 用Havok也是向着他的character controller去的, 我只用过Physx 对physx的cc表示遗憾,还是太简陋了, havok自带的cc基本满足了fps的所有的功能, 行走 跳跃 爬梯, 可扩展的character state满足特殊的需求.
小小提一下 characterProxy的checkSupport这个非常的好用,通过修改传入方向可以知道人物8个方向是否被碰撞, 用来判断某些自定义的cc状态入口很有效,比如wall running : )
4. Havok\Source\Physics\Utilities注意这个目录,这个工具目录很多好玩的东西,比如weapon目录下有重力枪的实现 : ), action的目录下有mousespring的实现,就是用鼠标拖着某个物体移动. 还有一些游戏里
常用的比如triggervolume, 破碎,爆炸的实现.
havok东西太多了,我还没摸到animation sdk,光physics sdk已经让我觉得博大精深 东西太多了,基本也都是靠着摸索研究。inter的那个论坛跟Physx的一样,人气很低, 有兴趣的同学可以一起研究研究。