《电子技术应用》
您所在的位置:首页 > 其他 > 设计应用 > 碰撞检测在三维场景漫游中的研究与实现
碰撞检测在三维场景漫游中的研究与实现
来源:微型机与应用2012年第24期
王良燕, 高 敏
安徽三联学院, 安徽 合肥230601
摘要: 碰撞检测是三维漫游中的一项重要功能。通过面向对象图形渲染引擎(OGRE)构建了一个模拟三维漫游系统,利用OgreNewt结合Newton库在系统中实现碰撞检测功能。碰撞检测包围盒均采用3DSMax创建,利用OgreNewt中的碰撞检测树解析,既保证了碰撞的精确性,又节省了编码工作量。适用于层次结构较复杂的三维场景的加载和碰撞检测。
Abstract:
Key words :

摘  要: 碰撞检测三维漫游中的一项重要功能。通过面向对象图形渲染引擎(OGRE)构建了一个模拟三维漫游系统,利用OgreNewt结合Newton库在系统中实现碰撞检测功能。碰撞检测包围盒均采用3DSMax创建,利用OgreNewt中的碰撞检测树解析,既保证了碰撞的精确性,又节省了编码工作量。适用于层次结构较复杂的三维场景的加载和碰撞检测。
关键词: 碰撞检测; 三维漫游; 面向对象图形渲染引擎

    虚拟现实是当今计算机领域的一项热门技术,其中一个重要功能是虚拟三维漫游,实现这一功能需要借助计算机图形引擎。OGRE[1]是一款专门处理三维场景的图形引擎,具有开源免费、跨平台等多种优点,目前在虚拟现实领域已有非常广泛的应用[2-3]。
    实现三维漫游需要考虑的一个重要问题是碰撞检测,OGRE引擎本身不具备这项功能,需要借助第三方引擎实现,常用的第三方引擎库有Newton[4]、ODE[5]等。Newton在碰撞检测方面性能更出色,它是一款开源免费的碰撞检测引擎库,OgreNewt是对Newton库的一层面向对象封装。可以结合OgreNewt和OGRE,在三维场景中实现碰撞检测功能。本文主要探讨如何在OGRE基础上,结合OgreNewt及Newton库,实现具有碰撞检测功能的三维漫游系统。
1 OGRE、Newton和OgreNewt
    OGRE是用C++开发的跨平台的3D引擎,底层基于OpenGL和DirectX实现,具有高效的三维场景管理性能,能很好地兼容第三方库以实现一些特定功能。一个基本的OGRE系统主要包括Root、SceneManager、Entity、SceneNode、Material和Camera等几部分。Root是整个系统的入口点,通过它可以获取系统中的其他对象。Entity是三维物体模型,Material是模型的材质,每个Entity 都挂载到一个SceneNode上,所有SceneNode共同组成一个树状结构,由SceneManager统一管理。通过Camera来实现观看场景。
    OGRE引擎通过OgreNewt与Newton库衔接。OgreNewt通过Newton库中的一些基本的元素来描述物理世界,主要包括World、Collision和Body等。World是最基本的类,通过它可以建立一个空间,所有其他物体都在这个空间里创建。空间中的物体参加碰撞检测时需要有一个包围盒,通过包围盒计算来判断是否发生了碰撞,Collision用于定义包围盒的形状,基本形状有Boxes、Ellipsoids、Cylinders、Capsules等。Body用于定义碰撞检测包围盒的实体,它可以与空间中的其他实体相互作用,比如发生碰撞、摩擦等。它需要根据Collision定义好的形状来创建。此外还有Joint、MaterialID、MaterialPair等,都有其他用途。
2 三维漫游系统
2.1虚拟场景构建

    建立一个三维漫游系统,首先要构建虚拟场景,主要步骤如下:
    首先建立并取得Root,再读取所有资源路径并添加到资源组管理器中,接着创建场景管理器、相机并为相机创建视口;然后创建场景,解析资源配置文件并加载所有资源。漫游需要键盘、鼠标等外设控制,需要在程序中创建帧监听器,以监听每一帧的变化;最后是对场景进行渲染显示。
2.2 碰撞检测
    进行三维漫游时,如果发生碰撞,需要添加碰撞检测。基于Newton库,通过OgreNewt建立碰撞检测步骤及代码如下:
    (1)创建World
    首先要创建一个碰撞检测空间:
    OgreNewt::World* m_World = new OgreNewt::World();
    (2)为漫游者添加碰撞检测包围盒
    由于漫游采用第一人称视角,可以有一个基本形状来表示漫游者。这里通过一个球体来代替:
    OgreNewt::CollisionPrimitives::Ellipsoid sphere(m_pWorld, Ogre:: Vector3(PLAYER_WIDTH/2.0, PLAYER_WIDTH/2.0,
PLAYER_WIDTH/2.0));
    m_pPlayerBody=new OgreNewt::Body(m_pWorld, &sphere);
    由于这个球体代替漫游者,它与别的物体碰撞时会有力的作用,因此,它既有质量也有惯性。这些值必须要设置:
    Ogre::Vector3 inertia = OgreNewt::MomentOfInertia::CalcSphereSolid(PLAYER_WEIGHT, PLAYER_WIDTH / 2.0);
    m_pPlayerBody->setMassMatrix(PLAYER_WEIGHT,inertia);
  (3)为其他物体添加碰撞检测包围盒
     碰撞的作用是相互的,不仅漫游者需要碰撞检测包围盒,场景中其他所有物体都需要。在大规模三维场景中,三维模型比较多,形状也各不相同,因此完全在程序中为每个物体按照其形状创建包围盒会极大增加代码量;如果都用简单的基本形状来表示,进行碰撞时又不够精确。为了解决这一问题,利用碰撞检测树和3DSMax配合来实现。首先在空间中创建一个碰撞检测树场景解析器TreeCollisionSceneParser,只需要将OGRE场景中的碰撞检测根节点给它,它就会解析这个根节点所对应的节点树,并将这棵树上的所有子节点纳入碰撞检测范围。关键代码如下:
    Ogre::SceneNode* pRootNode =
             Ogre::Root::getSingleton().getSceneManager(DEFAULT_
            SCENE_MANAGER)
             ->getSceneNode(sCollisionRootNode.c_str());
    OgreNewt::CollisionPrimitives::TreeCollisionSceneParser
        parser(m_pWorld);
     parser.parseScene(pRootNode, true);
     OgreNewt::Body* pRootBody=new OgreNewt::Body(m_p
        World, &parser);
    pRootBody->attachToNode(pRootNode);
    sCollisionRootNode即为碰撞检测树根节点,场景中所有其他三维模型的碰撞检测包围盒应作为子节点挂在这棵树上。这些包围盒都在3DSMax中创建。只要是纳入碰撞检测范围的模型,就为它添加一个副本,不是特别复杂的模型,副本的形状、大小、位置可以与模型完全相同;对于较复杂的模型,可以通过基本形状组合成模型轮廓作为副本。这些副本就是模型的包围盒。然后将这些包围盒作为子节点挂在sCollisionRootNode下,最后整个场景就会形成一棵碰撞检测树,树上的所有包围盒在碰撞时都会被程序检测到并参加计算。
    (4)注册回调函数
  漫游者与其他物体发生碰撞时可能会发生位置、方向等的变化,这些变化需要被及时获知并实时显示,这一功能可以通过回调函数实现。这里定义两个回调函数,一个回调函数用于在漫游者受到其他物体的作用力时产生一个速度。主要代码为:
     void CBasicInputListener::CustomForceAndTorqueCallback
        (OgreNewt::Body* me)
    {    SceneNode* pPlayerNode =
            Root::getSingleton().getSceneManager(DEFAULT_
                SCENE_MANAGER)->
           getSceneNode(DEFAULT_CAMERA_NODE);
          me->setVelocity(pPlayerNode->getWorldOrientation()*
         m_TranslateVector + Vector3(0, -DEFAULT_GRAVI-
        TY, 0));
      }
     另一个回调函数用于漫游者发生变化时。比如相机切换或漫游者移动,都会发生位置方向的改变,因此需要及时进行变化,主要代码如下:
    void CBasicInputListener::CustomTransformCallback(Ogre
        Newt::Body* me, const Quaternion& orient, const
        Vector3& pos)
     {    ……
          pPlayerNode->setPosition(pos.x,     
             pos.y + PLAYER_HEIGHT - PLAYER_WIDTH
            /2.0, pos.z);    
         ……
     }
3 运行效果
    在Windows平台下,基于OGRE1.4.9、OgreNewt 0.11和Newton1.5.3实现了一个具有碰撞检测的模拟三维漫游系统,其中的三维场景模型采用3DSMax 8创建。图1为漫游时与墙壁发生碰撞的截图,图2为与树碰撞时的截图。当发生碰撞时,漫游者将无法前进,必须向其他方向移动才能绕过阻挡物体。墙壁的三维模型不是很复杂,因此碰撞检测包围盒的形状和墙壁相同。而树的形状比较复杂,如果用完全相同的形状会极大增加计算量,因此在3DSMax中为其添加了一个球体加圆柱体的轮廓作为包围盒,如图3所示为树的包围盒网格。

 

 

    本文介绍了如何在OGRE引擎中,通过OGRENewt结合Newton库,创建一个具有碰撞检测的三维漫游系统的方法,并实现了一个模拟系统。所使用的引擎库皆为开源免费,并具有较高的效率和良好的体验效果,可以在实际中应用。
参考文献
[1] http://www.ogre3d.org/
[2] Xie Mei, Zhen Zheng, Zhang Fan, et al. A cross-platform  extendable 3D Virtual Reality system based on OGRE and Python[C]. Communications, Circuits and Systems, 2009. ICCCAS 2009:502-506.
[3] Liu Xiuling, Du Huanping, Wang Hongrui,et al. Design  and development of a distributed Virtual Reality system[C]. Machine Learning and Cybernetics, 2009:889-894.
[4] http://newtondynamics.com/.
[5] 高嵩,陈先桥,杨菊.基于OGRE和ODE的驾驶模拟系统的设计与实现[J].交通与计算机,2006,24(1):101-104.

此内容为AET网站原创,未经授权禁止转载。