History: IntermediateTutorial3Source
Source of version: 4 (current)
Copy to clipboard
This is the source for ((Intermediate Tutorial 3))
IntermediateTutorial3.h
{CODE(wrap="1",colors="c++")}
#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_
{CODE}
IntermediateTutorial3.cpp
{CODE(wrap="1",colors="c++")}
#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
{CODE}