OGRE Wiki
Support and community documentation for Ogre3D
Ogre Forums
ogre3d.org
Log in
Username:
Password:
CapsLock is on.
Remember me (for 1 year)
Log in
Home
Tutorials
Tutorials Home
Basic Tutorials
Intermediate Tutorials
Mad Marx Tutorials
In Depth Tutorials
Older Tutorials
External Tutorials
Cookbook
Cookbook Home
CodeBank
Snippets
Experiences
Ogre Articles
Libraries
Libraries Home
Alternative Languages
Assembling A Toolset
Development Tools
OGRE Libraries
List of Libraries
Tools
Tools Home
DCC Tools
DCC Tutorials
DCC Articles
DCC Resources
Assembling a production pipeline
Development
Development Home
Roadmap
Building Ogre
Installing the Ogre SDK
Setting Up An Application
Ogre Wiki Tutorial Framework
Frequently Asked Questions
Google Summer Of Code
Help Requested
Ogre Core Articles
Community
Community Home
Projects Using Ogre
Recommended Reading
Contractors
Wiki
Immediate Wiki Tasklist
Wiki Ideas
Wiki Guidelines
Article Writing Guidelines
Wiki Styles
Wiki Page Tracker
Ogre Wiki Help
Ogre Wiki Help Overview
Help - Basic Syntax
Help - Images
Help - Pages and Structures
Help - Wiki Plugins
Toolbox
Freetags
Categories
List Pages
Structures
Trackers
Statistics
Rankings
List Galleries
Ogre Lexicon
Comments
History: Go on
View page
Source of version: 3
(current)
__im_tutorial1.cpp__ {CODE(wrap="1", colors="c++")}/* ************************************************************** file: im_tutorial1.cpp description: Intermediate tutorial, modified to manage an arbitrary number of points and robots, and a collision avoidance algorithm ****************************************************************/ #include "ExampleApplication.h" #include "singleton.h" #include "im_tutorial1.h" #include <deque> using namespace std; // RobotAnimator //////////////////////////////////////////////////// // programmer: Andres Vogel // description: controller for single robot being // animated // ///////////////////////////////////// // class for animation of robots // // ///////////////////////////////////// // namepsace IntermediateTutorial1 // programmer: Andres Vogel // description: this is the intermediate tutorial //------------------------------------------------------------------------ namespace IntermediateTutorial1 { //-------------------------------------------------------------------------- // class RobotRayDataManager // Based on the Singleton class // class RobotRayDataManager : public IntermediateTutorial1::Singleton<RobotRayDataManager> { friend class Singleton<RobotRayDataManager>; friend class std::auto_ptr<RobotRayDataManager>; private: Ogre::SceneManager* mSceneMgr; Ogre::RaySceneQuery* mRaySceneQuery; RobotRayDataManager() : mRaySceneQuery(0), mSceneMgr(0) { } ~RobotRayDataManager() { } public: Vector3 getRayIntersection(Ogre::Ray ray) { mRaySceneQuery->setRay( ray ); // Execute query RaySceneQueryResult &result = mRaySceneQuery->execute(); RaySceneQueryResult::iterator itr = result.begin( ); // Get results, create a node/entity on the position if ( itr != result.end() && itr->worldFragment ) { return itr->worldFragment->singleIntersection; } return Vector3::ZERO; } Vector3 getViewportRayIntersection(Camera* cam, Real x, Real y) { Ogre::Ray ray = cam->getCameraToViewportRay(x, y); return getRayIntersection(ray); } void clearResults(void) { mRaySceneQuery->clearResults(); } void setSceneMgr(Ogre::SceneManager* sceneMgr) { mSceneMgr = sceneMgr; mRaySceneQuery = mSceneMgr->createRayQuery( Ogre::Ray() ); } Ogre::SceneManager* getSceneMgr() { return mSceneMgr; } }; // // end RobotRayDataManager //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // ---------------------------------------------------------------------- // class RobotAnimator // class for animating robots across the screen. Do not // use new on this class, simply use the createRobot // factory method on the RobotAnimatorManager class // programmer: Andres Vogel class RobotAnimator : public Ogre::UserDefinedObject { // creator defines the creator object for this // class CREATOR_CLASS(RobotAnimatorManager); CREATOR_CLASS(RobotAnimatorManagerMulti); public: // enums, types, etc. enum RobotTypes { RBT_TYPE_NORMAL, RBT_TYPE_USER }; typedef std::list<RobotAnimator*> RobotAnimatorList; typedef std::list<RobotAnimator*>::iterator RobotAnimatorIterator; private: // class instance variables // the entity that represents the robot Ogre::Entity* mEntity; // the state of the robot at a given moment enum RobotState { RBT_BEGIN_WALK, RBT_WALKING, RBT_IDLE } mRobotState; Ogre::SceneNode* mNode; // robots node std::deque<Vector3> mWalkList; // The list of points we are walking to bool mWalking; // whether the robot is walking Ogre::Real mDistance; // the distance to a destination point Ogre::Vector3 mDirection; // the movement direction Ogre::Vector3 mDestination; // the destination vector Ogre::AnimationState* mAnimationState; // the state of the robot animation RobotTypes mRobotType; // sets the type of robot (not used really) Ogre::RaySceneQuery* mRaySceneQuery; // current scene query data Real mWalkSpeed; // the walking speed of the robot // ///////////////////// // constants // // ///////////////////// static const Real DEFAULT_WALK_SPEED; // the walking speed for the robot static const Real AVOIDANCE_FACTOR; // avoidance factor for robots protected: // // private constructor since we don't want just anyone // creating random RobotAnimators! // RobotAnimator(Entity* ent, SceneNode* node) : // initialize instance variables mEntity(ent), mNode(node), mWalkSpeed(DEFAULT_WALK_SPEED), mWalking(false), mRobotType(RBT_TYPE_NORMAL) { if ( nextLocation() ) { // Set walking animation setAnimationState(true, true, "Walk"); mWalking = true; } // if else { setAnimationState(true, true, "Idle"); mWalking = false; } // else } public: // methods ~RobotAnimator() { } Ogre::String getName(void) { return mEntity->getName(); } inline long getTypeID(void) { return mRobotType; } //----------------------------------------------------- // testGround(): make sure robots feet are on the // the ground void testGround(void) { // get current node position Vector3 nodePos = this->getPosition( ); Ray nodeRay( Vector3(nodePos.x, 5000.0f, nodePos.z), Vector3::NEGATIVE_UNIT_Y ); Vector3 vIntersect = RobotRayDataManager::getSingleton(). getRayIntersection(nodeRay); vIntersect.y += 3.0f; mNode->setPosition( vIntersect ); // clear results of the query RobotRayDataManager::getSingleton().clearResults(); } //------------------------------------------------- // testCollide(): test for a local collide between // robots void testCollide(RobotAnimator* rbt) { if(rbt == this) return; Ogre::Vector3 vRbtPos = rbt->getPosition(); Ogre::Vector3 vMyPos = mNode->getPosition(); Ogre::Vector3 totalMovement = Vector3::ZERO; // get the distance, better to be squared (easier to calc) Real tr = (vRbtPos - vMyPos).squaredLength(); // this is kinda a magic number ;) I multiply the inverse // of the distance by an avoidance factor to create a stronger // avoidance vector as things get close enough to collide Real trFactor = (1.0 / tr) * AVOIDANCE_FACTOR; // if we are closer than about 44-45 units ( sqrt[2000] ) if(tr < 2000) { if(vRbtPos.x < vMyPos.x) totalMovement.x = trFactor; if(vRbtPos.x > vMyPos.x) totalMovement.x = -trFactor; if(vRbtPos.z < vMyPos.z) totalMovement.z = trFactor; if(vRbtPos.z > vMyPos.z) totalMovement.z = -trFactor; // add random noise (makes them wiggle a little) totalMovement.x += Ogre::Math::RangeRandom(-0.1, 0.1); totalMovement.z += Ogre::Math::RangeRandom(-0.1, 0.1); mNode->translate(totalMovement); } } //------------------------------------------------------- // testCollide(RobotAnimatorList): test for multiple // robot collisions with this robot void testCollide(RobotAnimatorList robots) { RobotAnimatorIterator rbIterator; // go through each item in the robot list for ( rbIterator = robots.begin( ); rbIterator != robots.end( ); rbIterator++ ) { ( *rbIterator )->testCollide( this ); } } Ogre::Vector3 getPosition(void) { return mNode->getPosition(); } //----------------------------------------------------- // doFrame(): performs the translation actions on the // robot animation void doFrame(const FrameEvent &evt) { if ( mWalking ) { Real move = mWalkSpeed * evt.timeSinceLastFrame; mDistance -= move; // if we reach a waypoint, check for the next location if (mDistance <= 0.0f) { mNode->setPosition( mDestination ); mDirection = Vector3::ZERO; if (! nextLocation( ) ) { // no other locations found, Idle setAnimationState(true, true, "Idle"); mWalking = false; } // if } // if else // if we are inbetween waypoints, move toward the next one { mNode->translate( mDirection * move ); } // else // make sure we are walking on the ground //testGround(); } // play out animation mAnimationState->addTime(evt.timeSinceLastFrame); } void setAnimationState(bool enable, bool loop, Ogre::String state) { mAnimationState = mEntity->getAnimationState( state ); mAnimationState->setLoop( true ); mAnimationState->setEnabled( true ); } void setWalkSpeed(Ogre::Real walk) { mWalkSpeed = walk; } Real getWalkSpeed(void) { return mWalkSpeed; } bool nextLocation( ) { if ( mWalkList.empty() ) return false; mDestination = mWalkList.front( ); // this gets the front of the deque mWalkList.pop_front( ); // this removes the front of the deque mDirection = mDestination - mNode->getPosition( ); mDistance = mDirection.normalise( ); Vector3 src = mNode->getOrientation( ) * Vector3::UNIT_X; // we must zero out all y components to ensure that // the object stays oriented towards a given point src.y = 0; mDirection.y = 0; if ( (1.0f + src.dotProduct( mDirection )) < 0.0001f ) mNode->yaw( Degree(180) ); else { Ogre::Quaternion quat = src.getRotationTo( mDirection ); mNode->rotate( quat ); } // else return true; } // nextLocation // add a location to the robot walk list void addLocation( Ogre::Vector3 loc ) { mWalkList.push_back(loc); if( !mWalking ) { setAnimationState(true, true, "Walk"); mWalking = true; nextLocation(); } } // addLocation }; /* TODO (dreprog#1#): setup avoidance factor to be controlled by accessor functions */ const Real RobotAnimator::DEFAULT_WALK_SPEED = 35.0f; const Real RobotAnimator::AVOIDANCE_FACTOR = 1500.0f; // end class RobotAnimator //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // RobotAnimatorManager // // Maintains a list of robots that are being managed // programmer: Andres Vogel // description: This class manages all the robots // in the class, I chose not to implement // as a seperate factory and manager // because the manager doesn't have // much responsiblity, and I placed // the responsiblity of animating // in the hands of the RobotAnimator // objects themselves, and the manager // simply brokers the call to the // doFrame() methods of the RobotAnimators // class RobotAnimatorManager : public IntermediateTutorial1::Singleton<RobotAnimatorManager> { friend class Singleton<RobotAnimatorManager>; friend class std::auto_ptr<RobotAnimatorManager>; private: // this is the list of robots being managed RobotAnimator::RobotAnimatorList mRobots; // the scene manager managing the current scene Ogre::SceneManager* mSceneMgr; int mRobotCount; static bool sDestroyed; RobotAnimatorManager() : mRobotCount(0) { } // ~RobotAnimatorManager() { } public: ~RobotAnimatorManager() { // clean up all the robots RobotAnimator::RobotAnimatorIterator rbIterator; // go through each item in the robot list for ( rbIterator = mRobots.begin( ); rbIterator != mRobots.end( ); rbIterator++ ) { // update frame information for each robot delete ( *rbIterator ); // test for a collision between robots // ( *rbIterator )->testCollide(mRobots); } } // attempting to call getSingleton after a destroySingleton // will leave you with a null pointer! RobotAnimator* createRobot(Ogre::Entity* ent, Ogre::SceneNode* sn) { RobotAnimator* rbt = new RobotAnimator(ent, sn); // mRob = rbt; mRobots.push_back( rbt ); mRobotCount++; return rbt; } // doFrame(const FrameEvent &evt) // does a frame event for each void doFrame(const FrameEvent& evt) { RobotAnimator::RobotAnimatorIterator rbIterator; // go through each item in the robot list for ( rbIterator = mRobots.begin( ); rbIterator != mRobots.end( ); rbIterator++ ) { // update frame information for each robot ( *rbIterator )->doFrame(evt); // test for a collision between robots ( *rbIterator )->testCollide(mRobots); } } }; // end RobotAnimationManager //------------------------------------------------------------------- //--------------------------------------------------------------------------- // RobotAnimatorManagerMulti (Non-singleton version) // // Maintains a list of robots that are being managed // programmer: Andres Vogel // description: This class manages all the robots // in the class, I chose not to implement // as a seperate factory and manager // because the manager doesn't have // much responsiblity, and I placed // the responsiblity of animating // in the hands of the RobotAnimator // objects themselves, and the manager // simply brokers the call to the // doFrame() methods of the RobotAnimators // class RobotAnimatorManagerMulti { private: // this is the list of robots being managed RobotAnimator::RobotAnimatorList mRobots; // the scene manager managing the current scene Ogre::SceneManager* mSceneMgr; int mRobotCount; static bool sDestroyed; public: RobotAnimatorManagerMulti() : mRobotCount(0) { } // ~RobotAnimatorManager() { } ~RobotAnimatorManagerMulti() { // clean up all the robots RobotAnimator::RobotAnimatorIterator rbIterator; // go through each item in the robot list for ( rbIterator = mRobots.begin( ); rbIterator != mRobots.end( ); rbIterator++ ) { // update frame information for each robot delete ( *rbIterator ); // test for a collision between robots // ( *rbIterator )->testCollide(mRobots); } } // attempting to call getSingleton after a destroySingleton // will leave you with a null pointer! RobotAnimator* createRobot(Ogre::Entity* ent, Ogre::SceneNode* sn) { RobotAnimator* rbt = new RobotAnimator(ent, sn); // mRob = rbt; mRobots.push_back( rbt ); mRobotCount++; return rbt; } // doFrame(const FrameEvent &evt) // does a frame event for each void doFrame(const FrameEvent& evt) { RobotAnimator::RobotAnimatorIterator rbIterator; // go through each item in the robot list for ( rbIterator = mRobots.begin( ); rbIterator != mRobots.end( ); rbIterator++ ) { // update frame information for each robot ( *rbIterator )->doFrame(evt); // test for a collision between robots ( *rbIterator )->testCollide(mRobots); } } }; // // end RobotAnimatorManagerMulti //------------------------------------------------------------------- //--------------------------------------------------------------- // RobotAnimationListener // class RobotAnimatorListener : public ExampleFrameListener { public: // enums, typedefs, etc // typedef std::list<Ogre::Entity*> EntityList; // typedef std::list<Ogre::Entity*>::iterator EntityListIterator; // typedef std::list<Ogre::Entity*> EntityList; // typedef std::list<Ogre::Entity*>::iterator EntityListIterator; // typedef Ogre::MapIterator<EntityNodeMap> EntityNodeMapIterator public: // methods RobotAnimatorListener(RenderWindow* win, Camera* cam, Ogre::SceneManager* sceneMgr) : ExampleFrameListener(win, cam, false, false) { // EntityListIterator elIterator; // for ( elIterator = entlist.begin( ); elIterator != entlist.end( ); // elIterator++ ) // { // mRobots.push_back( // static_cast<RobotAnimator*> // (( *elIterator )->getUserObject()) ); // } mRobotManager = RobotAnimatorManager::getSingletonPtr(); RobotRayDataManager::getSingleton().setSceneMgr(sceneMgr); } ~RobotAnimatorListener() { // delete mRobotManager; } bool frameStarted(const FrameEvent &evt) { mRobotManager->doFrame(evt); return ExampleFrameListener::frameStarted(evt); } RobotAnimator::RobotAnimatorList mRobots; RobotAnimatorManager* mRobotManager; }; // end RobotAnimatorListener //-------------------------------------------------------------------------- } // // end namespace IntermediateTutorial1 //------------------------------------------------------------------------ using namespace IntermediateTutorial1; class MoveDemoApplication : public ExampleApplication { protected: public: MoveDemoApplication() { } ~MoveDemoApplication() { } protected: Entity *mEntity; // The entity of the object we are animating SceneNode *mNode; // The SceneNode of the object we are moving std::deque<Vector3> mWalkList; // A deque containing the waypoints void createScene(void) { // Set the default lighting. mSceneMgr->setAmbientLight( ColourValue( 1.0f, 1.0f, 1.0f ) ); // Create the entity mEntity = mSceneMgr->createEntity( "Robot", "robot.mesh" ); // Create the scene node mNode = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode", Vector3( 0.0f, 0.0f, 25.0f ) ); mNode->attachObject( mEntity ); // add another robot //////////////////////////////////////// Entity* ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" ); // Create the scene node SceneNode* nd2 = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode2", Vector3( 0.0f, 0.0f, 25.0f ) ); nd2->attachObject( ent2 ); nd2->translate(10,0,100); Entity* ent3 = mSceneMgr->createEntity( "Robot3", "robot.mesh" ); // Create the scene node SceneNode* nd3 = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode3", Vector3( 0.0f, 0.0f, 25.0f ) ); nd3->attachObject( ent3 ); nd3->translate(-20,0,-15); Entity* ent4 = mSceneMgr->createEntity( "Robot4", "robot.mesh" ); // Create the scene node SceneNode* nd4 = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode4", Vector3( 0.0f, 0.0f, 25.0f ) ); nd4->attachObject( ent4 ); nd4->translate(200,0,40); Entity* ent5 = mSceneMgr->createEntity( "Robot5", "robot.mesh" ); // Create the scene node SceneNode* nd5 = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode5", Vector3( 0.0f, 0.0f, 25.0f ) ); nd5->attachObject( ent5 ); nd5->translate(-100,0,-30); Entity* ent6 = mSceneMgr->createEntity( "Robot6", "robot.mesh" ); // Create the scene node SceneNode* nd6 = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode6", Vector3( 0.0f, 0.0f, 25.0f ) ); nd6->attachObject( ent6 ); nd6->translate(-200,0,-40); Entity* ent7 = mSceneMgr->createEntity( "Robot7", "robot.mesh" ); // Create the scene node SceneNode* nd7 = mSceneMgr->getRootSceneNode( )-> createChildSceneNode( "RobotNode7", Vector3( 0.0f, 0.0f, 25.0f ) ); nd7->attachObject( ent7 ); nd7->translate(92,0,12); // add another robot //////////////////////////////////////// // ////////////////////////////////////// robot animator code RobotAnimatorManager* rbtMgr = RobotAnimatorManager::getSingletonPtr(); RobotAnimator* rbtAnimator = rbtMgr->createRobot(mEntity, mNode); rbtAnimator->addLocation( Vector3( 550.0f, 0.0f, 50.0f ) ); rbtAnimator->addLocation( Vector3(-100.0f, 0.0f, -200.0f ) ); mEntity->setUserObject( rbtAnimator ); rbtAnimator = rbtMgr->createRobot(ent2, nd2); rbtAnimator->addLocation( Vector3( 600.0, 0.0f, 20.0f ) ); rbtAnimator->addLocation( Vector3(50.0f, 0.0f, -400.0f ) ); rbtAnimator->setWalkSpeed(35.0f); ent2->setUserObject( rbtAnimator ); rbtAnimator = rbtMgr->createRobot(ent3, nd3); rbtAnimator->addLocation( Vector3( -100.0f, 0.0f, 4.0f ) ); rbtAnimator->addLocation( Vector3(200.0f, 0.0f, 500.0f ) ); rbtAnimator->setWalkSpeed(13.0f); ent3->setUserObject( rbtAnimator ); rbtAnimator = rbtMgr->createRobot(ent4, nd4); rbtAnimator->addLocation( Vector3(1000.0f, 0.0f, -300.0f ) ); rbtAnimator->addLocation( Vector3(-304.0f, 0.0f, 200.0f ) ); rbtAnimator->setWalkSpeed(45.0f); ent4->setUserObject( rbtAnimator ); rbtAnimator = rbtMgr->createRobot(ent5, nd5); rbtAnimator->addLocation( Vector3(90.0f, 0.0f, -12.0f ) ); rbtAnimator->addLocation( Vector3(-491.0f, 0.0f, 392.0f ) ); rbtAnimator->setWalkSpeed(120.0f); ent5->setUserObject( rbtAnimator ); rbtAnimator = rbtMgr->createRobot(ent6, nd6); rbtAnimator->addLocation( Vector3(399.0f, 0.0f, -300.0f ) ); rbtAnimator->addLocation( Vector3(192.0f, 0.0f, 600.0f ) ); rbtAnimator->setWalkSpeed(30.0f); ent6->setUserObject( rbtAnimator ); rbtAnimator = rbtMgr->createRobot(ent7, nd7); rbtAnimator->addLocation( Vector3(522.0f, 0.0f, 100.0f ) ); rbtAnimator->addLocation( Vector3(-900.0f, 0.0f, -200.0f ) ); rbtAnimator->setWalkSpeed(90.0f); ent7->setUserObject( rbtAnimator ); // ////////////////////////////////////// end robot animator code // Create the walking list // ////////////////////////////////////// code commented for animator // mWalkList.push_back( Vector3( 550.0f, 0.0f, 50.0f ) ); // ////////////////////////////////////// robot animator code // mWalkList.push_back( Vector3(-100.0f, 0.0f, -200.0f ) ); // mWalkList.push_back( Vector3(-400.0f, 0.0f, -100.0f ) ); // Create objects so we can see movement Entity *ent; SceneNode *node; ent = mSceneMgr->createEntity( "Knot1", "knot.mesh" ); node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot1Node", Vector3( 0.0f, -10.0f, 25.0f ) ); node->attachObject( ent ); node->setScale( 0.1f, 0.1f, 0.1f ); ent = mSceneMgr->createEntity( "Knot2", "knot.mesh" ); node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot2Node", Vector3( 550.0f, -10.0f, 50.0f ) ); node->attachObject( ent ); node->setScale( 0.1f, 0.1f, 0.1f ); ent = mSceneMgr->createEntity( "Knot3", "knot.mesh" ); node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot3Node", Vector3(-100.0f, -10.0f,-200.0f ) ); node->attachObject( ent ); node->setScale( 0.1f, 0.1f, 0.1f ); // // ent = mSceneMgr->createEntity( "Knot4", "knot.mesh" ); // node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot4Node", // Vector3(-400.0f, -10.0f,-100.0f ) ); // node->attachObject( ent ); // node->setScale( 0.1f, 0.1f, 0.1f ); // Set the camera to look at our handywork mCamera->setPosition( 90.0f, 280.0f, 535.0f ); mCamera->pitch( Degree(-30.0f) ); mCamera->yaw( Degree(-15.0f) ); } void createFrameListener(void) { // ////////////////////////////////////// code commented for animator // // mFrameListener= new MoveDemoListener(mWindow, mCamera, mNode, // mEntity, mWalkList); // ////////////////////////////////////// end code commented for animator // ////////////////////////////////////// code added for animator mFrameListener = new RobotAnimatorListener(mWindow, mCamera, mSceneMgr); // ////////////////////////////////////// end code added for animator mFrameListener->showDebugOverlay(true); mRoot->addFrameListener(mFrameListener); } }; #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char **argv) #endif { // Create application object MoveDemoApplication app; try { app.go(); } catch( 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 fprintf(stderr, "An exception has occured: %s\n", e.getFullDescription().c_str()); #endif } return 0; } {CODE}
Search by Tags
Search Wiki by Freetags
Latest Changes
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
Critter AI
Mogre Add-ons
MOGRE
Mogre MyGUI wrapper
MOGRE Editable Terrain Manager
...more
Search
Find
Advanced
Search Help
Online Users
45 online users