OgreOpcode几乎是不使用物理引擎时Ogre下的唯一选择,但是这个天杀的库文档实在是太少了,约等于没有。下面把这两天使用它的经验整理一下。
下载&编译
OgreOpcode没有任何Release,获取它的唯一办法是从SVN中下载源代码进行编译,SVN地址如下:
https://ogreconglo.svn.sourceforge.net/svnroot/ogreconglo/ogreopcode/trunk
在script文件夹找到自己用的编译器的项目文件,直接编译就可以了。需要注意的是,SVN中的exmples是无法正确编译的–这些例子运行所需要的一些文件没有在SVN里面!另外就是doc目录中的Doxygen配置文件中居然用的是绝对路径,不经修改是无法运行的。此外我在使用VS2005的时候发现,它的项目文件中少包含了一个叫OgreCapsuleMeshCollisionShape.cpp的文件,导致编译无法通过。需要自己把它加到OgreOpcode项目中才可以编译成功。另外在项目的“生成后事件”中会执行一个拷贝的命令,但是在svn的文件夹结构中目标文件夹是不存在的!这也会导致编译失败。
实在是被这个项目的维护人员打败了…这么多纰漏…
我知道是个人都会觉得从svn里面编译很麻烦,所以我吧它编译好了上传上来了,点这里下载ogreopcodebin。里面包括编译好的debug和release版的dll。
使用
要使用OgreOpcode,基本上可以分为这么几步:
- 创建一个Manager
- 创建一个Context
- 加入参加碰撞的物体
- 碰撞检测
初始化
// 创建Manager。这个Manager使用Singleton实现
CollisionManager* mCollisionMgr = new CollisionManager(sceneMgr);
// 创建context 不同的context中可以添加不同的物体,发生不同的碰撞关系
mCollisionContext = mCollisionMgr->createContext( "test" );
// 创建碰撞类,并且设置不同类型之间碰撞的检测方式
mCollisionMgr->addCollClass("charactor");
mCollisionMgr->addCollClass("scene");
// COLLTYPE_QUICK 表示两个charactor之间的碰撞使用简单的球体进行检测
mCollisionMgr->addCollType("charactor", "charactor", COLLTYPE_QUICK);
// COLLTYPE_IGNORE 表示忽略场景物体之间的碰撞
mCollisionMgr->addCollType("scene", "scene", COLLTYPE_IGNORE);
// COLLTYPE_EXACT 表示计算charactor和scene碰撞时的所有交点
mCollisionMgr->addCollType("charactor", "scene", COLLTYPE_EXACT);
加入物体
OgreOpcode中的物体主要有以下几种:Box, Capsule, Sphere, Terrain, Mesh, Entity, Ptr,调用CollisionManager::createXXXXCollisionShape函数来创建。从函这些物体的名称大体上可以才到它的用法。其中Ptr是从一个三角形数组中得到一个碰撞物体的形状。
// 根据一个entity的网格模型信息来创建碰撞形状
EntityCollisionShape *shape = CollisionManager::getSingletonPtr()->
createEntityCollisionShape(ent->getName());
// 制定该shape所关联的entity
shape->load(ent);
// 创建一个碰撞物体
CollisionObject* pCollisionObject = mCollisionContext->createObject( ent->getName() );
// 设置该物体的类型,这里应该是第一步中设置的"charactor","scene"之一
pCollisionObject->setCollClass( type.c_str() );
// 设置object的形状
pCollisionObject->setShape( shape );
pCollisionObject->setForcedUpdate(forceupdate);
// 把这个object加到我们创建的CollisionContext中去
mCollisionContext->addObject( pCollisionObject );
其他设置
在每一帧都需要调用CollisionContext::Collide(time)来更新状态,否则是无法检测到碰撞的。
另外在所有物体都已经添加到CollisionContext中了以后需要调用一次CollisionContext::reset()。
碰撞检测
OgreOpcode中的碰撞检测包括射线(rayCheck)、球体(sphereCheck)、移动球体(sweptSphereCheck)三种方式。rayCheck就是传入一个Ray对象,检查射线上有没有和其他物体相交。sphereCheck则是创建一个虚拟的球体,检查这个球体有没有碰撞。sweptSphereCheck则是创建一个虚拟球体,并且让它沿着某个方向移动,检查在这个过程中是否有交点。
下面给出一个rayCheck的例子:
Ogre::Ray ray(Vector(0,30,0), Vector(0,-1,0));
Ogre::Real dist = 100;
std::vector vectorList;
CollisionPair** collisionPair = NULL;
if( mCollisionContext->rayCheck(ray, dist ,
COLLTYPE_EXACT, COLLTYPE_ALWAYS_EXACT, collisionPair ) > 0)
{
int count= mCollisionContext->getNumCollisions();
for( int i = 0; i < count; i ++ )
{
vectorList.push_back( collisionPair [i]->contact );
}
}
其他
其实OgreOpcode的接口并不是那么那么的复杂,但是没有文档使得使用它变成了一个比较头疼的事情。官方网站也仅仅是一个并不活跃的论坛,让人很是怀疑这个库是不是值得去深入学习。其它的碰撞检测库如GIMPACT虽然文档上好很多,但是却没有Ogre下的wrapper。说不是什么时候我心血来潮了就会写一个这样的wrapper?
近期评论