转自:http://blog.csdn.net/weiqubo/article/details/7108363

Ogre采用树桩管理场景中的各种"元素"(摄像机、灯光、物体等),所有的东西都挂在"树"上,不在"树"上的东西不会被渲染。
Ogre::SceneManager就是"树"的管理者,Ogre::SceneNode是从SceneManager中创建的(当然BSP和8*树的管理也和这两个类有关,这暂时不讨论)。

AABB(轴对齐包围盒)

这个东西是碰撞检测的基础,和它类似的还有OBB(有向包围盒),由于OBB创建复杂,所以Ogre采用了AABB。

最简单的碰撞检测

通过Ogre::SceneNode::_getWorldAABB()可以取得这个叶子节点的AABB(Ogre::AxisAlignedBox),Ogre::AxisAlignedBox封装了对AABB的支持,该类的成员函数Ogre::AxisAlignedBox::intersects()可以判断一个AABB和"球体、点、面以及其他面"的相交情况(碰撞情况)。

m_SphereNode树的叶子,挂了一个"球"
m_CubeNode树的叶子,挂了一个"正方体"

  1. AxisAlignedBox spbox = m_SphereNode->_getWorldAABB();
  2. AxisAlignedBox cbbox = m_CubeNode->_getWorldAABB();
  3. if(spbox.intersects(cbbox))
  4. {
  5. //相交
  6. }
AxisAlignedBox spbox = m_SphereNode->_getWorldAABB();
AxisAlignedBox cbbox = m_CubeNode->_getWorldAABB();
if(spbox.intersects(cbbox))
{
//相交
}
 
附上简单的AABB测试程序,碰撞之后模型放大十倍,当然碰撞之后的事情你可以随意修改
  1. #include"ExampleApplication.h"
  2. #include <stdio.h>
  3. class CollionFrameListener:public ExampleFrameListener
  4. {
  5. private:
  6. SceneNode* m_node;
  7. SceneNode*m_node2;
  8. SceneManager* mSceneMgr;
  9. public:
  10. CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneNode*node22,SceneManager* manager)
  11. :ExampleFrameListener(win,cam),m_node(node),m_node2(node22),mSceneMgr(manager)
  12. {
  13. }
  14. bool frameStarted(const FrameEvent& evt)
  15. {
  16. AxisAlignedBox spbox=m_node->_getWorldAABB();
  17. AxisAlignedBox cbbox=m_node2->_getWorldAABB();
  18. if(spbox.intersects(cbbox))
  19. {
  20. m_node2->setScale(10,10,10);
  21. }
  22. return ExampleFrameListener::frameStarted(evt);
  23. }
  24. };
  25. class CollionApplication:public ExampleApplication
  26. {
  27. protected:
  28. SceneNode*node1;
  29. SceneNode* node2;
  30. void createScene()
  31. {
  32. mSceneMgr->setAmbientLight(ColourValue(1,1,1));
  33. Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
  34. node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
  35. node1->attachObject(ent1);
  36. Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
  37. node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
  38. node2->attachObject(ent2);
  39. }
  40. void createFrameListener()
  41. {
  42. mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,node2,mSceneMgr);
  43. mFrameListener->showDebugOverlay(true);
  44. mRoot->addFrameListener(mFrameListener);
  45. }
  46. };
  47. INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE,  LPSTR, int )
  48. {
  49. CollionApplication app;
  50. app.go();
  51. }
#include"ExampleApplication.h"
#include <stdio.h>
class CollionFrameListener:public ExampleFrameListener
{
private:
SceneNode* m_node;
SceneNode*m_node2;
SceneManager* mSceneMgr;
public:
CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneNode*node22,SceneManager* manager)
:ExampleFrameListener(win,cam),m_node(node),m_node2(node22),mSceneMgr(manager)
{
}
bool frameStarted(const FrameEvent& evt)
{
AxisAlignedBox spbox=m_node->_getWorldAABB();
AxisAlignedBox cbbox=m_node2->_getWorldAABB();
if(spbox.intersects(cbbox))
{
m_node2->setScale(10,10,10);
}
return ExampleFrameListener::frameStarted(evt);
}
}; class CollionApplication:public ExampleApplication
{
protected:
SceneNode*node1;
SceneNode* node2;
void createScene()
{
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
node1->attachObject(ent1);
Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
node2->attachObject(ent2); }
void createFrameListener()
{
mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,node2,mSceneMgr);
mFrameListener->showDebugOverlay(true);
mRoot->addFrameListener(mFrameListener);
}
};
INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
CollionApplication app;
app.go();
}
区域查询:

简单的讲就是,查询某一区域中有什么东西,分为AABB、球体、面查询。

  1. //创建一个球体查询,这里的100是m_SphereNode挂着的那个球体的半径
  2. SphereSceneQuery * pQuery=m_SceneMgr->createSphereQuery(Sphere(m_SphereNode->getPosition(),100));
  3. //执行这个查询
  4. SceneQueryResult QResult=pQuery->execute();
  5. //遍历查询列表找出范围内的物体
  6. for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  7. {
  8. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  9. if(pObject)
  10. {
  11. if(pObject->getMovableType()=="Entity")
  12. {
  13. Entity* ent = static_cast<Entity*>(pObject);
  14. //这里简化了操作,由于只有一个"球体"和一个"正方体",
  15. //所以只判断了球体和正方体的相交
  16. if(ent->getName()=="cube")
  17. {
  18. //改变位置防止物体重叠
  19. vtl=-vtl;
  20. m_SphereNode->translate(vtl);
  21. break;
  22. }
  23. }
  24. }
  25. }
    //创建一个球体查询,这里的100是m_SphereNode挂着的那个球体的半径
SphereSceneQuery * pQuery=m_SceneMgr->createSphereQuery(Sphere(m_SphereNode->getPosition(),100));
//执行这个查询
SceneQueryResult QResult=pQuery->execute();
//遍历查询列表找出范围内的物体
for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
{
MovableObject* pObject=static_cast<MovableObject*>(*iter);
if(pObject)
{
if(pObject->getMovableType()=="Entity")
{
Entity* ent = static_cast<Entity*>(pObject);
//这里简化了操作,由于只有一个"球体"和一个"正方体",
//所以只判断了球体和正方体的相交 if(ent->getName()=="cube")
{
//改变位置防止物体重叠
vtl=-vtl;
m_SphereNode->translate(vtl);
break;
}
}
}
}
新建一个空的ogre程序,将这个代码添加到你的cpp文件中就可以运行,这个例子是如果碰撞就将模型放大十倍,当然碰撞之后的代码你可以随便修改
  1. #include"ExampleApplication.h"
  2. #include <stdio.h>
  3. class CollionFrameListener:public ExampleFrameListener
  4. {
  5. private:
  6. SceneNode* m_node;
  7. SceneManager* mSceneMgr;
  8. public:
  9. CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneManager* manager)
  10. :ExampleFrameListener(win,cam),m_node(node),mSceneMgr(manager)
  11. {
  12. }
  13. bool frameStarted(const FrameEvent& evt)
  14. {
  15. SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(m_node->getPosition(),10));
  16. SceneQueryResult QResult=pQuery->execute();
  17. for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  18. {
  19. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  20. if(pObject)
  21. {
  22. if(pObject->getMovableType()=="Entity")
  23. {
  24. Entity* ent = static_cast<Entity*>(pObject);
  25. if(ent->getName()=="ogrehead")
  26. {
  27. m_node->setScale(10,10,10);
  28. break;
  29. }
  30. }
  31. }
  32. }
  33. return ExampleFrameListener::frameStarted(evt);
  34. }
  35. };
  36. class CollionApplication:public ExampleApplication
  37. {
  38. protected:
  39. SceneNode*node1;
  40. void createScene()
  41. {
  42. mSceneMgr->setAmbientLight(ColourValue(1,1,1));
  43. Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
  44. node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
  45. node1->attachObject(ent1);
  46. Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
  47. SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
  48. node2->attachObject(ent2);
  49. }
  50. void createFrameListener()
  51. {
  52. mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,mSceneMgr);
  53. mFrameListener->showDebugOverlay(true);
  54. mRoot->addFrameListener(mFrameListener);
  55. }
  56. };
  57. INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE,  LPSTR, int )
  58. {
  59. CollionApplication app;
  60. app.go();
  61. }
#include"ExampleApplication.h"
#include <stdio.h>
class CollionFrameListener:public ExampleFrameListener
{
private:
SceneNode* m_node;
SceneManager* mSceneMgr;
public:
CollionFrameListener(RenderWindow* win, Camera* cam,SceneNode* node,SceneManager* manager)
:ExampleFrameListener(win,cam),m_node(node),mSceneMgr(manager)
{
}
bool frameStarted(const FrameEvent& evt)
{
SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(m_node->getPosition(),10));
SceneQueryResult QResult=pQuery->execute();
for (SceneQueryResultMovableList::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
{
MovableObject* pObject=static_cast<MovableObject*>(*iter);
if(pObject)
{
if(pObject->getMovableType()=="Entity")
{
Entity* ent = static_cast<Entity*>(pObject);
if(ent->getName()=="ogrehead")
{
m_node->setScale(10,10,10);
break;
}
}
}
}
return ExampleFrameListener::frameStarted(evt);
}
}; class CollionApplication:public ExampleApplication
{
protected:
SceneNode*node1;
void createScene()
{
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
Entity* ent1=mSceneMgr->createEntity("robot","robot.mesh");
node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("robotnode");
node1->attachObject(ent1);
Entity *ent2=mSceneMgr->createEntity("ogrehead","ogreHead.mesh");
SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreheadnode",Vector3(2,0,0));
node2->attachObject(ent2);
}
void createFrameListener()
{
mFrameListener=new CollionFrameListener(mWindow,mCamera,node1,mSceneMgr);
mFrameListener->showDebugOverlay(true);
mRoot->addFrameListener(mFrameListener);
}
}; INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
CollionApplication app;
app.go();
}

相交查询:

遍历所有的对象,找到一对一对的相交物体(废话呀,相交当然至少两个物体)。

  1. //创建相交检测
  2. IntersectionSceneQuery* pISQuery=m_SceneMgr->createIntersectionQuery();
  3. //执行查询
  4. IntersectionSceneQueryResult QResult=pISQuery->execute();
  5. //遍历查询列表找出两个相交的物体
  6. for (SceneQueryMovableIntersectionList::iterator iter = QResult.movables2movables.begin();
  7. iter != QResult.movables2movables.end();++iter)
  8. {
  9. SceneQueryMovableObjectPair pObject=static_cast<SceneQueryMovableObjectPair>(*iter);
  10. //if(pObject)
  11. {
  12. String strFirst=pObject.first->getName();
  13. String strSecond=pObject.second->getName();
  14. //下面加入你自己的两个物体相交判断代码,或者简单的用AABB的判断方法,
  15. }
  16. }
//创建相交检测
IntersectionSceneQuery* pISQuery=m_SceneMgr->createIntersectionQuery();
//执行查询
IntersectionSceneQueryResult QResult=pISQuery->execute();
//遍历查询列表找出两个相交的物体
for (SceneQueryMovableIntersectionList::iterator iter = QResult.movables2movables.begin();
iter != QResult.movables2movables.end();++iter)
{ SceneQueryMovableObjectPair pObject=static_cast<SceneQueryMovableObjectPair>(*iter);
//if(pObject)
{
String strFirst=pObject.first->getName();
String strSecond=pObject.second->getName();
//下面加入你自己的两个物体相交判断代码,或者简单的用AABB的判断方法,
}
}

在Ogre中,可以创建一个查询器,比如球体查询器,AABB查询器,面查询器等。下面我们以最常用的球形查询器为例来说明:

如下面的代码,我们首先创建一个球形查询器,它需要定义一个球体,我们把它的位置,设置为摄像机的位置,半径为10,掩码为第二个参数,默认为-1,

通过掩码,可以把碰撞的物体分成不同的组,比如我们设置球形场景查询器的掩码为0x1,则它只检测和它掩码相同物体的碰撞。该摄像机检测到entity对象后,就把摄像机位置沿摄像机方向,向后移动一个单位,这样会实现碰撞检测,但是摄像机因为向后有个移动,所以会有抖动。

  1. //创建球形查询器,第二个参数表示掩码,默认情况下为-1
  2. SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(mCamera->getPosition(),10));
  3. SceneQueryResult QResult=pQuery->execute();
  4. for (std::list<MovableObject*>::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  5. {
  6. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  7. if(pObject)
  8. {
  9. if(pObject->getMovableType()=="Entity")
  10. {
  11. Entity* ent = static_cast<Entity*>(pObject);
  12. //if(ent->getName()=="Head")
  13. //{
  14. //    //m_node->setScale(10,10,10);
  15. //    pObject->getParentNode()->scale(0.5,0.5,0.5);
  16. //    break;
  17. //}
  18. Ogre::Vector3 v = mCamera->getPosition();
  19. Ogre::Vector3 d = mCamera->getDirection();
  20. v = v + d*(-1);
  21. mCamera->setPosition(v);
  22. }
  23. }
  24. }全部的代码:
  //创建球形查询器,第二个参数表示掩码,默认情况下为-1
SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(mCamera->getPosition(),10));
SceneQueryResult QResult=pQuery->execute();
for (std::list<MovableObject*>::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
{
MovableObject* pObject=static_cast<MovableObject*>(*iter);
if(pObject)
{
if(pObject->getMovableType()=="Entity")
{
Entity* ent = static_cast<Entity*>(pObject);
//if(ent->getName()=="Head")
//{
// //m_node->setScale(10,10,10);
// pObject->getParentNode()->scale(0.5,0.5,0.5);
// break;
//}
Ogre::Vector3 v = mCamera->getPosition();
Ogre::Vector3 d = mCamera->getDirection();
v = v + d*(-1);
mCamera->setPosition(v); }
}
}全部的代码:
  1. #include "ExampleApplication.h"
  2. RaySceneQuery* raySceneQuery = 0;
  3. // Event handler to add ability to alter curvature
  4. class TerrainFrameListener : public ExampleFrameListener
  5. {
  6. public:
  7. SceneManager* mSceneMgr;
  8. TerrainFrameListener(SceneManager *sceneMgr,RenderWindow* win, Camera* cam)
  9. : ExampleFrameListener(win, cam)
  10. {
  11. // Reduce move speed
  12. mMoveSpeed = 50;
  13. mSceneMgr = sceneMgr;
  14. }
  15. bool frameRenderingQueued(const FrameEvent& evt)
  16. {
  17. if( ExampleFrameListener::frameRenderingQueued(evt) == false )
  18. return false;
  19. // clamp to terrain
  20. static Ray updateRay;
  21. updateRay.setOrigin(mCamera->getPosition());
  22. updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
  23. raySceneQuery->setRay(updateRay);
  24. RaySceneQueryResult& qryResult = raySceneQuery->execute();
  25. RaySceneQueryResult::iterator i = qryResult.begin();
  26. if (i != qryResult.end() && i->worldFragment)//把摄像机定在地形10个单位高的地方。
  27. {
  28. mCamera->setPosition(mCamera->getPosition().x,
  29. i->worldFragment->singleIntersection.y + 10,
  30. mCamera->getPosition().z);
  31. }
  32. //创建球形查询器,第二个参数表示掩码,默认情况下为-1
  33. SphereSceneQuery * pQuery=mSceneMgr->createSphereQuery(Sphere(mCamera->getPosition(),10));
  34. SceneQueryResult QResult=pQuery->execute();
  35. for (std::list<MovableObject*>::iterator iter = QResult.movables.begin(); iter != QResult.movables.end();++iter)
  36. {
  37. MovableObject* pObject=static_cast<MovableObject*>(*iter);
  38. if(pObject)
  39. {
  40. if(pObject->getMovableType()=="Entity")
  41. {
  42. Entity* ent = static_cast<Entity*>(pObject);
  43. //if(ent->getName()=="Head")
  44. //{
  45. //    //m_node->setScale(10,10,10);
  46. //    pObject->getParentNode()->scale(0.5,0.5,0.5);
  47. //    break;
  48. //}
  49. Ogre::Vector3 v = mCamera->getPosition();
  50. Ogre::Vector3 d = mCamera->getDirection();
  51. v = v + d*(-1);
  52. mCamera->setPosition(v);
  53. }
  54. }
  55. }
  56. return true;
  57. }
  58. };
  59. class TerrainApplication : public ExampleApplication
  60. {
  61. public:
  62. TerrainApplication() {}
  63. ~TerrainApplication()
  64. {
  65. delete raySceneQuery;
  66. }
  67. protected:
  68. virtual void chooseSceneManager(void)
  69. {
  70. // Get the SceneManager, in this case a generic one
  71. mSceneMgr = mRoot->createSceneManager("TerrainSceneManager");
  72. }
  73. virtual void createCamera(void)
  74. {
  75. // Create the camera
  76. mCamera = mSceneMgr->createCamera("PlayerCam");
  77. // Position it at 500 in Z direction
  78. mCamera->setPosition(Vector3(128,25,128));
  79. // Look back along -Z
  80. mCamera->lookAt(Vector3(0,0,-300));
  81. mCamera->setNearClipDistance( 1 );
  82. mCamera->setFarClipDistance( 1000 );
  83. }
  84. // Just override the mandatory create scene method
  85. void createScene(void)
  86. {
  87. // Set ambient light
  88. mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
  89. // Create a light
  90. Light* l = mSceneMgr->createLight("MainLight");
  91. // Accept default settings: point light, white diffuse, just set position
  92. // NB I could attach the light to a SceneNode if I wanted it to move automatically with
  93. //  other objects, but I don't
  94. l->setPosition(20,80,50);
  95. // Fog
  96. // NB it's VERY important to set this before calling setWorldGeometry
  97. // because the vertex program picked will be different
  98. ColourValue fadeColour(0.93, 0.86, 0.76);
  99. mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
  100. mWindow->getViewport(0)->setBackgroundColour(fadeColour);
  101. std::string terrain_cfg("terrain.cfg");
  102. mSceneMgr -> setWorldGeometry( terrain_cfg );
  103. // Infinite far plane?
  104. if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
  105. {
  106. mCamera->setFarClipDistance(0);
  107. }
  108. // Set a nice viewpoint
  109. mCamera->setPosition(707,2500,528);
  110. mCamera->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
  111. //mRoot -> showDebugOverlay( true );
  112. raySceneQuery = mSceneMgr->createRayQuery(
  113. Ray(mCamera->getPosition(), Vector3::NEGATIVE_UNIT_Y));//光线的位置和方向,垂直向下
  114. Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
  115. //创建ogre head实体,测试通过射线查询movable来实现摄像机碰撞检测
  116. SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ogreHead");
  117. headNode->attachObject(ogreHead);
  118. headNode->setPosition(500.0, 100.0, 500.0);
  119. headNode->scale(Vector3(2,2,2));
  120. }
  121. // Create new frame listener
  122. void createFrameListener(void)
  123. {
  124. mFrameListener= new TerrainFrameListener(mSceneMgr,mWindow, mCamera);
  125. mRoot->addFrameListener(mFrameListener);
  126. }
  127. };

最新文章

  1. LeetCode Remove Duplicate Letters
  2. 20145225《Java程序设计》 第8周学习总结
  3. Docker学习笔记整理
  4. ReactiveCocoa中信号的使用
  5. rabbitMq 转自 http://gaoyangang.iteye.com/blog/1566600
  6. hdu 4000 树状数组
  7. NYIST OJ 题目38 布线问题
  8. python3爬取女神图片,破解盗链问题
  9. Status bar could not find cached time string image. Rendering in-process?
  10. 使用Jupyter lab前应该读的几篇文章
  11. wampserver 403forbidden问题
  12. ThinPHP3.2中 addAll()批量插入数据
  13. ABAP术语-Update Module
  14. TW实习日记:第八天
  15. [How to] 使用HBase协处理器---Endpoint客户端代码的实现
  16. java socket 长连接 短连接
  17. SQL SERVER 导入、导出数据到Exce(使用OpenRowset,、OpenDataSource函数)以及访问远程数据库(openrowset/opendatasource/openquery)
  18. NET对象的跨应用程序域
  19. Java流(一)
  20. String和StringBuffer的机制差别

热门文章

  1. 【bzoj1057】棋盘制作
  2. addEventListener,attachEvent
  3. Java GC系列(3):垃圾回收器种类
  4. css样式初始化
  5. 20145236 《Java程序设计》实验二实验报告
  6. 创建PO/SO
  7. js事件知识整理
  8. econ
  9. ANGULAR JS WATCH监听使用
  10. linux 一些命令