This is the source for Intermediate Tutorial 3
IntermediateTutorial3.h
Copy to clipboard
#ifndef __IntermediateTutorial3_h_ #define __IntermediateTutorial3_h_ #include "BaseApplication.h" #include <CEGUISystem.h> #include <CEGUISchemeManager.h> #include <RendererModules/Ogre/CEGUIOgreRenderer.h> class IntermediateTutorial3 : public BaseApplication { public: IntermediateTutorial3(void); virtual ~IntermediateTutorial3(void); enum QueryFlags { NINJA_MASK = 1<<0, ROBOT_MASK = 1<<1 }; protected: virtual void createScene(void); virtual void chooseSceneManager(void); virtual void createFrameListener(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& arg); virtual bool mouseMoved(const OIS::MouseEvent& arg); virtual bool mousePressed(const OIS::MouseEvent& arg, OIS::MouseButtonID id); virtual bool mouseReleased(const OIS::MouseEvent& arg, OIS::MouseButtonID id); virtual bool keyPressed(const OIS::KeyEvent& arg); Ogre::SceneNode *mCurrentObject; //pointer to our currently selected object Ogre::RaySceneQuery* mRayScnQuery; //pointer to our ray scene query CEGUI::Renderer* mGUIRenderer; //our CEGUI renderer bool bLMouseDown, bRMouseDown; //true if mouse buttons are held down int mCount; //number of objects created float mRotateSpeed; //the rotation speed for the camera bool bRobotMode; //if true we place robots in the world }; #endif // #ifndef __IntermediateTutorial3_h_
IntermediateTutorial3.cpp
Copy to clipboard
#include "IntermediateTutorial3.h" //------------------------------------------------------------------------------------- IntermediateTutorial3::IntermediateTutorial3(void): mCount(0), mCurrentObject(0), bLMouseDown(false), bRMouseDown(false), mRotateSpeed(0.1f), bRobotMode(true) { } //------------------------------------------------------------------------------------- IntermediateTutorial3::~IntermediateTutorial3(void) { mSceneMgr->destroyQuery(mRayScnQuery); } //------------------------------------------------------------------------------------- void IntermediateTutorial3::createScene(void) { //Scene setup mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f)); mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8); //World geometry mSceneMgr->setWorldGeometry("terrain.cfg"); //camera setup mCamera->setPosition(40, 100, 580); mCamera->pitch(Ogre::Degree(-30)); mCamera->yaw(Ogre::Degree(-45)); //CEGUI setup mGUIRenderer = &CEGUI::OgreRenderer::bootstrapSystem(); //show the CEGUI cursor CEGUI::SchemeManager::getSingleton().create((CEGUI::utf8*)"TaharezLook.scheme"); CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow"); } void IntermediateTutorial3::chooseSceneManager(void) { //create a scene manager that is meant for handling outdoor scenes mSceneMgr = mRoot->createSceneManager(Ogre::ST_EXTERIOR_CLOSE); } void IntermediateTutorial3::createFrameListener(void) { //we still want to create the frame listener from the base app BaseApplication::createFrameListener(); //but we also want to set up our raySceneQuery after everything has been initialized mRayScnQuery = mSceneMgr->createRayQuery(Ogre::Ray()); } bool IntermediateTutorial3::frameRenderingQueued(const Ogre::FrameEvent& arg) { //we want to run everything in the previous frameRenderingQueued call //but we also want to do something afterwards, so lets start off with this if(!BaseApplication::frameRenderingQueued(arg)) { return false; } /* This next big chunk basically sends a raycast straight down from the camera's position It then checks to see if it is under world geometry and if it is we move the camera back up */ Ogre::Vector3 camPos = mCamera->getPosition(); Ogre::Ray cameraRay(Ogre::Vector3(camPos.x, 5000.0f, camPos.z), Ogre::Vector3::NEGATIVE_UNIT_Y); mRayScnQuery->setRay(cameraRay); /* here we tell it not to sort the raycast results world geometry would be at the end of the list so sorting would be bad in this case since we are iterating through everything */ mRayScnQuery->setSortByDistance(false); Ogre::RaySceneQueryResult& result = mRayScnQuery->execute(); Ogre::RaySceneQueryResult::iterator iter = result.begin(); for(iter; iter != result.end(); iter++) { if(iter->worldFragment) { //gets the results, fixes camera height and breaks the loop Ogre::Real terrainHeight = iter->worldFragment->singleIntersection.y; if((terrainHeight + 10.0f) > camPos.y) { mCamera->setPosition(camPos.x, terrainHeight + 10.0f, camPos.z); } break; } } return true; } bool IntermediateTutorial3::mouseMoved(const OIS::MouseEvent& arg) { //updates CEGUI with mouse movement CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel); //if the left mouse button is held down if(bLMouseDown) { //find the current mouse position CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition(); //create a raycast straight out from the camera at the mouse's location Ogre::Ray mouseRay = mCamera->getCameraToViewportRay(mousePos.d_x/float(arg.state.width), mousePos.d_y/float(arg.state.height)); mRayScnQuery->setRay(mouseRay); mRayScnQuery->setSortByDistance(false); //world geometry is at the end of the list if we sort it, so lets not do that Ogre::RaySceneQueryResult& result = mRayScnQuery->execute(); Ogre::RaySceneQueryResult::iterator iter = result.begin(); //check to see if the mouse is pointing at the world and put our current object at that location for(iter; iter != result.end(); iter++) { if(iter->worldFragment) { mCurrentObject->setPosition(iter->worldFragment->singleIntersection); break; } } } else if(bRMouseDown) //if the right mouse button is held down, be rotate the camera with the mouse { mCamera->yaw(Ogre::Degree(-arg.state.X.rel * mRotateSpeed)); mCamera->pitch(Ogre::Degree(-arg.state.Y.rel * mRotateSpeed)); } return true; } bool IntermediateTutorial3::mousePressed(const OIS::MouseEvent& arg, OIS::MouseButtonID id) { if(id == OIS::MB_Left) { //show that the current object has been deselected by removing the bounding box visual if(mCurrentObject) { mCurrentObject->showBoundingBox(false); } //find the current mouse position CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition(); //then send a raycast straight out from the camera at the mouse's position Ogre::Ray mouseRay = mCamera->getCameraToViewportRay(mousePos.d_x/float(arg.state.width), mousePos.d_y/float(arg.state.height)); mRayScnQuery->setRay(mouseRay); mRayScnQuery->setSortByDistance(true); mRayScnQuery->setQueryMask(bRobotMode ? ROBOT_MASK : NINJA_MASK); //will return objects with the query mask in the results /* This next chunk finds the results of the raycast If the mouse is pointing at world geometry we spawn a robot at that position */ Ogre::RaySceneQueryResult& result = mRayScnQuery->execute(); Ogre::RaySceneQueryResult::iterator iter = result.begin(); for(iter; iter != result.end(); iter++) { //if you clicked on a robot or ninja it becomes selected if(iter->movable && iter->movable->getName().substr(0, 5) != "tile[") { mCurrentObject = iter->movable->getParentSceneNode(); break; } //otherwise we spawn a new one at the mouse location else if(iter->worldFragment) { char name[16]; Ogre::Entity* ent; //if we are in robot mode we spawn a robot at the mouse location if(bRobotMode) { sprintf(name, "Robot%d", mCount++); ent = mSceneMgr->createEntity(name, "robot.mesh"); ent->setQueryFlags(ROBOT_MASK); } //otherwise we spawn a ninja else { sprintf(name, "Ninja%d", mCount++); ent = mSceneMgr->createEntity(name, "ninja.mesh"); ent->setQueryFlags(NINJA_MASK); } //attach the object to a scene node mCurrentObject = mSceneMgr->getRootSceneNode()->createChildSceneNode(std::string(name) + "Node", iter->worldFragment->singleIntersection); mCurrentObject->attachObject(ent); //lets shrink the object, only because the terrain is pretty small mCurrentObject->setScale(0.1f, 0.1f, 0.1f); break; } } //now we show the bounding box so the user can see that this object is selected if(mCurrentObject) { mCurrentObject->showBoundingBox(true); } bLMouseDown = true; } else if(id == OIS::MB_Right) // if the right mouse button is held we hide the mouse cursor for view mode { CEGUI::MouseCursor::getSingleton().hide(); bRMouseDown = true; } return true; } bool IntermediateTutorial3::mouseReleased(const OIS::MouseEvent& arg, OIS::MouseButtonID id) { if(id == OIS::MB_Left) { bLMouseDown = false; } else if(id == OIS::MB_Right) //when the right mouse is released we then unhide the cursor { CEGUI::MouseCursor::getSingleton().show(); bRMouseDown = false; } return true; } bool IntermediateTutorial3::keyPressed(const OIS::KeyEvent& arg) { //check and see if the spacebar was hit, and this will switch which mesh is spawned if(arg.key == OIS::KC_SPACE) { bRobotMode = !bRobotMode; } //then we return the base app keyPressed function so that we get all of the functionality //and the return value in one line return BaseApplication::keyPressed(arg); } #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #ifdef __cplusplus extern "C" { #endif #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char *argv[]) #endif { // Create application object IntermediateTutorial3 app; try { app.go(); } catch( Ogre::Exception& e ) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl; #endif } return 0; } #ifdef __cplusplus } #endif