Ogre 中,每个节点有AABB(轴对齐包围盒),通过包围盒,可以实现碰撞检测判断。具体实现过程如下:
通过Ogre::SceneNode::_getWorldAABB()可以取得这个叶子节点的AABB(Ogre::AxisAlignedBox),Ogre::AxisAlignedBox封装了对AABB的支持,该类的成员函数Ogre::AxisAlignedBox::intersects()可以判断一个AABB和"球体、点、面以及其他面"的相交情况(碰撞情况)。
Code
m_SphereNode; //树的叶子,挂了一个"球"
m_CubeNode; //树的叶子,挂了一个"正方体"
AxisAlignedBox spbox=m_SphereNode->_getWorldAABB();
AxisAlignedBox cbbox=m_CubeNode->_getWorldAABB();
if(spbox.intersects(cbbox))
{
//相交
}
m_SphereNode; //树的叶子,挂了一个"球"
m_CubeNode; //树的叶子,挂了一个"正方体"
AxisAlignedBox spbox=m_SphereNode->_getWorldAABB();
AxisAlignedBox cbbox=m_CubeNode->_getWorldAABB();
if(spbox.intersects(cbbox))
{
//相交
}
下面是测试2个节点通过AABB判断碰撞的程序代码:
Code
#ifndef __gkd4_h_
#define __gkd4_h_
#include "ExampleApplication.h"
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include "../res/resource.h"
#endif
#include <CEGUI.h>
#include <CEGUISystem.h>
#include <CEGUISchemeManager.h>
#include <OgreCEGUIRenderer.h>
//两个场景节点
SceneNode*node1;
SceneNode* node2;
CEGUI::MouseButton convertOISMouseButtonToCegui(int buttonID)
{
switch (buttonID)
{
case 0: return CEGUI::LeftButton;
case 1: return CEGUI::RightButton;
case 2: return CEGUI::MiddleButton;
case 3: return CEGUI::X1Button;
default: return CEGUI::LeftButton;
}
}
class gkd4FrameListener : public ExampleFrameListener, public OIS::KeyListener, public OIS::MouseListener
{
private:
SceneManager* mSceneMgr;
CEGUI::Renderer* mGUIRenderer;
bool mShutdownRequested;
bool mUseBufferedInputKeys, mUseBufferedInputMouse, mInputTypeSwitchingOn;
public:
gkd4FrameListener(SceneManager *sceneMgr, RenderWindow* win, Camera* cam, CEGUI::Renderer* renderer)
: ExampleFrameListener(win, cam, false, true),
mGUIRenderer(renderer),
mShutdownRequested(false),
mUseBufferedInputKeys(false),
mUseBufferedInputMouse(true),
mSceneMgr(sceneMgr)
{
mMouse->setEventCallback(this);
mKeyboard->setEventCallback(this);
mInputTypeSwitchingOn = mUseBufferedInputKeys || mUseBufferedInputMouse;
}
bool frameStarted(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::frameStarted(evt);
if(mUseBufferedInputMouse)
{
CEGUI::MouseCursor::getSingleton().show( );
}
else
{
CEGUI::MouseCursor::getSingleton().hide( );
}
AxisAlignedBox spbox=node1->_getWorldAABB();
AxisAlignedBox cbbox=node2->_getWorldAABB();
if(spbox.intersects(cbbox))
{
node2->setScale(10,10,10);
}
return ret;
}
bool processUnbufferedKeyInput(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::processUnbufferedKeyInput(evt);
// see if switching is on, and you want to toggle
if (mInputTypeSwitchingOn && mKeyboard->isKeyDown(OIS::KC_M) && mTimeUntilNextToggle <= 0)
{
switchMouseMode();
mTimeUntilNextToggle = 1;
}
if (mInputTypeSwitchingOn && mKeyboard->isKeyDown(OIS::KC_K) && mTimeUntilNextToggle <= 0)
{
// must be going from immediate keyboard to buffered keyboard
switchKeyMode();
mTimeUntilNextToggle = 1;
}
return ret;
}
void requestShutdown(void)
{
mShutdownRequested = true;
}
void switchMouseMode()
{
mUseBufferedInputMouse = !mUseBufferedInputMouse;
mMouse->setBuffered(mUseBufferedInputMouse);
}
//-------------------------------------------------------------------------------------
void switchKeyMode()
{
mUseBufferedInputKeys = !mUseBufferedInputKeys;
mKeyboard->setBuffered(mUseBufferedInputKeys);
}
bool frameEnded(const FrameEvent& evt)
{
if (mShutdownRequested)
return false;
else
return ExampleFrameListener::frameEnded(evt);
}
//----------------------------------------------------------------//
bool mouseMoved( const OIS::MouseEvent &arg )
{
CEGUI::System::getSingleton().injectMouseMove( arg.state.X.rel, arg.state.Y.rel );
return true;
}
//----------------------------------------------------------------//
bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
return true;
}
//----------------------------------------------------------------//
bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
return true;
}
//----------------------------------------------------------------//
bool keyPressed( const OIS::KeyEvent &arg )
{
if( arg.key == OIS::KC_ESCAPE )
mShutdownRequested = true;
CEGUI::System::getSingleton().injectKeyDown( arg.key );
CEGUI::System::getSingleton().injectChar( arg.text );
return true;
}
//----------------------------------------------------------------//
bool keyReleased( const OIS::KeyEvent &arg )
{
if( arg.key == OIS::KC_M )
mMouse->setBuffered( !mMouse->buffered() );
else if( arg.key == OIS::KC_K )
mKeyboard->setBuffered( !mKeyboard->buffered() );
CEGUI::System::getSingleton().injectKeyUp( arg.key );
return true;
}
};
class gkd4App : public ExampleApplication
{
private:
CEGUI::OgreCEGUIRenderer* mGUIRenderer;
CEGUI::System* mGUISystem;
public:
gkd4App()
: mGUIRenderer(0),
mGUISystem(0)
{}
~gkd4App()
{
if(mGUISystem)
{
delete mGUISystem;
mGUISystem = 0;
}
if(mGUIRenderer)
{
delete mGUIRenderer;
mGUIRenderer = 0;
}
}
protected:
virtual void createCamera(void)
{
// Create the camera
mCamera = mSceneMgr->createCamera("PlayerCam");
// Position it at 500 in Z direction
mCamera->setPosition(Vector3(0,0,80));
// Look back along -Z
mCamera->lookAt(Vector3(0,0,-300));
mCamera->setNearClipDistance(5);
}
virtual bool configure(void)
{
// Show the configuration dialog and initialise the system
// You can skip this and use root.restoreConfig() to load configuration
// settings if you were sure there are valid ones saved in ogre.cfg
if(mRoot->showConfigDialog())
{
// If returned true, user clicked OK so initialise
// Here we choose to let the system create a default rendering window by passing 'true'
mWindow = mRoot->initialise(true);
// Let's add a nice window icon
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
HWND hwnd;
mWindow->getCustomAttribute("WINDOW", (void*)&hwnd);
LONG iconID = (LONG)LoadIcon( GetModuleHandle(0), MAKEINTRESOURCE(IDI_APPICON) );
SetClassLong( hwnd, GCL_HICON, iconID );
#endif
return true;
}
else
{
return false;
}
}
// Just override the mandatory create scene method
virtual void createScene(void)
{
// setup GUI system
mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow,
Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
mGUISystem = new CEGUI::System(mGUIRenderer);
CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
// load scheme and set up defaults
CEGUI::SchemeManager::getSingleton().loadScheme(
(CEGUI::utf8*)"TaharezLookSkin.scheme");
mGUISystem->setDefaultMouseCursor(
(CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
CEGUI::MouseCursor::getSingleton().show( );
setupEventHandlers();
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);
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
// Create a light
Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
}
// Create new frame listener
void createFrameListener(void)
{
mFrameListener= new gkd4FrameListener(mSceneMgr, mWindow, mCamera, mGUIRenderer);
mRoot->addFrameListener(mFrameListener);
}
void setupEventHandlers(void)
{
}
bool handleQuit(const CEGUI::EventArgs& e)
{
static_cast<gkd4FrameListener*>(mFrameListener)->requestShutdown();
return true;
}
};
#endif // #ifndef __gkd4_h_
#ifndef __gkd4_h_
#define __gkd4_h_
#include "ExampleApplication.h"
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include "../res/resource.h"
#endif
#include <CEGUI.h>
#include <CEGUISystem.h>
#include <CEGUISchemeManager.h>
#include <OgreCEGUIRenderer.h>
//两个场景节点
SceneNode*node1;
SceneNode* node2;
CEGUI::MouseButton convertOISMouseButtonToCegui(int buttonID)
{
switch (buttonID)
{
case 0: return CEGUI::LeftButton;
case 1: return CEGUI::RightButton;
case 2: return CEGUI::MiddleButton;
case 3: return CEGUI::X1Button;
default: return CEGUI::LeftButton;
}
}
class gkd4FrameListener : public ExampleFrameListener, public OIS::KeyListener, public OIS::MouseListener
{
private:
SceneManager* mSceneMgr;
CEGUI::Renderer* mGUIRenderer;
bool mShutdownRequested;
bool mUseBufferedInputKeys, mUseBufferedInputMouse, mInputTypeSwitchingOn;
public:
gkd4FrameListener(SceneManager *sceneMgr, RenderWindow* win, Camera* cam, CEGUI::Renderer* renderer)
: ExampleFrameListener(win, cam, false, true),
mGUIRenderer(renderer),
mShutdownRequested(false),
mUseBufferedInputKeys(false),
mUseBufferedInputMouse(true),
mSceneMgr(sceneMgr)
{
mMouse->setEventCallback(this);
mKeyboard->setEventCallback(this);
mInputTypeSwitchingOn = mUseBufferedInputKeys || mUseBufferedInputMouse;
}
bool frameStarted(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::frameStarted(evt);
if(mUseBufferedInputMouse)
{
CEGUI::MouseCursor::getSingleton().show( );
}
else
{
CEGUI::MouseCursor::getSingleton().hide( );
}
AxisAlignedBox spbox=node1->_getWorldAABB();
AxisAlignedBox cbbox=node2->_getWorldAABB();
if(spbox.intersects(cbbox))
{
node2->setScale(10,10,10);
}
return ret;
}
bool processUnbufferedKeyInput(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::processUnbufferedKeyInput(evt);
// see if switching is on, and you want to toggle
if (mInputTypeSwitchingOn && mKeyboard->isKeyDown(OIS::KC_M) && mTimeUntilNextToggle <= 0)
{
switchMouseMode();
mTimeUntilNextToggle = 1;
}
if (mInputTypeSwitchingOn && mKeyboard->isKeyDown(OIS::KC_K) && mTimeUntilNextToggle <= 0)
{
// must be going from immediate keyboard to buffered keyboard
switchKeyMode();
mTimeUntilNextToggle = 1;
}
return ret;
}
void requestShutdown(void)
{
mShutdownRequested = true;
}
void switchMouseMode()
{
mUseBufferedInputMouse = !mUseBufferedInputMouse;
mMouse->setBuffered(mUseBufferedInputMouse);
}
//-------------------------------------------------------------------------------------
void switchKeyMode()
{
mUseBufferedInputKeys = !mUseBufferedInputKeys;
mKeyboard->setBuffered(mUseBufferedInputKeys);
}
bool frameEnded(const FrameEvent& evt)
{
if (mShutdownRequested)
return false;
else
return ExampleFrameListener::frameEnded(evt);
}
//----------------------------------------------------------------//
bool mouseMoved( const OIS::MouseEvent &arg )
{
CEGUI::System::getSingleton().injectMouseMove( arg.state.X.rel, arg.state.Y.rel );
return true;
}
//----------------------------------------------------------------//
bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
return true;
}
//----------------------------------------------------------------//
bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
return true;
}
//----------------------------------------------------------------//
bool keyPressed( const OIS::KeyEvent &arg )
{
if( arg.key == OIS::KC_ESCAPE )
mShutdownRequested = true;
CEGUI::System::getSingleton().injectKeyDown( arg.key );
CEGUI::System::getSingleton().injectChar( arg.text );
return true;
}
//----------------------------------------------------------------//
bool keyReleased( const OIS::KeyEvent &arg )
{
if( arg.key == OIS::KC_M )
mMouse->setBuffered( !mMouse->buffered() );
else if( arg.key == OIS::KC_K )
mKeyboard->setBuffered( !mKeyboard->buffered() );
CEGUI::System::getSingleton().injectKeyUp( arg.key );
return true;
}
};
class gkd4App : public ExampleApplication
{
private:
CEGUI::OgreCEGUIRenderer* mGUIRenderer;
CEGUI::System* mGUISystem;
public:
gkd4App()
: mGUIRenderer(0),
mGUISystem(0)
{}
~gkd4App()
{
if(mGUISystem)
{
delete mGUISystem;
mGUISystem = 0;
}
if(mGUIRenderer)
{
delete mGUIRenderer;
mGUIRenderer = 0;
}
}
protected:
virtual void createCamera(void)
{
// Create the camera
mCamera = mSceneMgr->createCamera("PlayerCam");
// Position it at 500 in Z direction
mCamera->setPosition(Vector3(0,0,80));
// Look back along -Z
mCamera->lookAt(Vector3(0,0,-300));
mCamera->setNearClipDistance(5);
}
virtual bool configure(void)
{
// Show the configuration dialog and initialise the system
// You can skip this and use root.restoreConfig() to load configuration
// settings if you were sure there are valid ones saved in ogre.cfg
if(mRoot->showConfigDialog())
{
// If returned true, user clicked OK so initialise
// Here we choose to let the system create a default rendering window by passing 'true'
mWindow = mRoot->initialise(true);
// Let's add a nice window icon
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
HWND hwnd;
mWindow->getCustomAttribute("WINDOW", (void*)&hwnd);
LONG iconID = (LONG)LoadIcon( GetModuleHandle(0), MAKEINTRESOURCE(IDI_APPICON) );
SetClassLong( hwnd, GCL_HICON, iconID );
#endif
return true;
}
else
{
return false;
}
}
// Just override the mandatory create scene method
virtual void createScene(void)
{
// setup GUI system
mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow,
Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
mGUISystem = new CEGUI::System(mGUIRenderer);
CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
// load scheme and set up defaults
CEGUI::SchemeManager::getSingleton().loadScheme(
(CEGUI::utf8*)"TaharezLookSkin.scheme");
mGUISystem->setDefaultMouseCursor(
(CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
CEGUI::MouseCursor::getSingleton().show( );
setupEventHandlers();
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);
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
// Create a light
Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
}
// Create new frame listener
void createFrameListener(void)
{
mFrameListener= new gkd4FrameListener(mSceneMgr, mWindow, mCamera, mGUIRenderer);
mRoot->addFrameListener(mFrameListener);
}
void setupEventHandlers(void)
{
}
bool handleQuit(const CEGUI::EventArgs& e)
{
static_cast<gkd4FrameListener*>(mFrameListener)->requestShutdown();
return true;
}
};
#endif // #ifndef __gkd4_h_