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: TriangleMeshRayListener Demo
View page
Source of version: 8
(current)
{img src="img/wiki_up/ODE_logo2.png" alt="" imalign="right"} Note: The implementation below uses OgreOde Rays to position an entity's height over a mesh. If you want the benefits of creating a mesh and using that to make a terrain this code is for you =). I've written a short demo application, and it tested fine on my machine. If for some reason it doesn't work, just re-use the parts of code that work best for you. Also, I didn't spend much time working on this, so the camera view and comments aren't all that great. That being said..enjoy! __Edit: Updated 9-13-2012__ {CODE(wrap="1", colors="c++")} #include "ExampleApplication.h" // include OgreOde files #include "OgreOde_Core.h" #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #ifdef __cplusplus extern "C" { #endif typedef struct { std::string charName; Ogre::SceneNode* charNode; OgreOde::RayGeometry* charRay; // radius used to position ray above actual node position (at feet) Ogre::Real radius; } ODE_CHAR_INFO; // Declare a subclass of the ExampleFrameListener class class MyListener : public ExampleFrameListener , public OgreOde::CollisionListener , public OgreOde::StepListener , public OgreOde::TriangleMeshRayListener { public: MyListener( Ogre::RenderWindow* win, Ogre::Camera* cam , Ogre::SceneManager* sMgr, Ogre::Root* mRoot ) : ExampleFrameListener( win, cam ) { mSceneMgr = sMgr; // create OgreOde World - from SimpleScenes demo world = new OgreOde::World( mSceneMgr ); world->setGravity( Ogre::Vector3( 0, -9.80665, 0 )); world->setCFM( 10e-5 ); world->setERP( 0.8 ); world->setAutoSleep( true ); world->setContactCorrectionVelocity( 1.0 ); world->setCollisionListener( this ); world->setAutoSleepAngularThreshold( OgreOde::Utility::Infinity ); // Create something that will step the world, but don't do // it automatically stepper = new OgreOde::StepHandler( world , OgreOde::StepHandler::QuickStep , Ogre::Real( 0.01 ) // Step size , Ogre::Real( 1.0 / 4 ) // Max interval , Ogre::Real( 1.0 )); // Time scale stepper->setStepListener( this ); //create_ODE_Terrain( "yourTerrainFile.mesh", position, size ); create_ODE_Terrain( "racingcircuit.mesh" , Ogre::Vector3::ZERO , Ogre::Vector3( 10, 10, 10 )); /*Entity* ent = mSceneMgr->createEntity( "yourEntityName" , "yourEntityFile.mesh" ); */ Ogre::Entity* ent = mSceneMgr->createEntity( "Ninja" , "ninja.mesh" ); Ogre::SceneNode* entNode = mSceneMgr->getRootSceneNode()-> createChildSceneNode( "NinjaNode" , Ogre::Vector3( 0, 15, 0 )); entNode->attachObject( ent ); entNode->setScale( 0.05, 0.05, 0.05 ); create_ODE_character( "Ninja", entNode ); // attach and position the camera entNode->attachObject( cam ); cam->setPosition( 0, 20, 150 ); } ~MyListener( void ) { // destroy to remove the characters, terrain and stepper // before destroying the OgreOde world destroy_ALL_ODE_characters(); if( terrainTriMeshGeom ) delete terrainTriMeshGeom; delete stepper; stepper = NULL; delete world; world = NULL; } bool frameStarted( const Ogre::FrameEvent& evt ) { //mKeyboard->capture(); // quit app if( mKeyboard->isKeyDown( OIS::KC_ESCAPE )) return false; // basic movement Ogre::Vector3 direction; if( mKeyboard->isKeyDown( OIS::KC_UP )) { direction = ode_characters[ 0 ].charNode-> _getDerivedOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z; ode_characters[ 0 ].charNode->translate( direction * ( evt.timeSinceLastFrame * 100 )); } if( mKeyboard->isKeyDown( OIS::KC_DOWN )) { direction = ode_characters[ 0 ].charNode-> _getDerivedOrientation() * Ogre::Vector3::UNIT_Z; ode_characters[ 0 ].charNode->translate( direction * ( evt.timeSinceLastFrame * 100 )); } if( mKeyboard->isKeyDown( OIS::KC_LEFT )) { ode_characters[ 0 ].charNode->rotate( Ogre::Vector3::UNIT_Y, ( Ogre::Radian( 0.1 )) * ( evt.timeSinceLastFrame * 100 )); } if( mKeyboard->isKeyDown( OIS::KC_RIGHT )) { ode_characters[ 0 ].charNode-> rotate( Ogre::Vector3::UNIT_Y , ( Ogre::Radian( -0.1 )) * ( evt.timeSinceLastFrame * 100 )); } simulatePhysics( evt ); return true; } bool frameEnded( const FrameEvent& evt ) { return ExampleFrameListener::frameEnded( evt ); } // OgreOde::CollisionListener function bool collision( OgreOde::Contact* contact ) { // search through ode_characters and adjust each // charNode's height for( std::vector< ODE_CHAR_INFO >::iterator it = ode_characters.begin(); it != ode_characters.end(); it++ ) { if( contact->getFirstGeometry()->getID() == it->charRay->getID() || contact->getSecondGeometry()->getID() == it->charRay->getID() ) { // Clamp the charNode to the terrain on ray contact. Ogre::Vector3 pos = it->charNode->getPosition(); it->charNode->setPosition( Ogre::Vector3( pos.x , contact->getPosition().y + 1 , pos.z )); //it->charNode->setPosition( contact->getPosition() ); break; } } return true; } // OgreOde::StepListener function bool preStep( Ogre::Real time ) { return true; } // reposition OgreOde Ray(s) void simulatePhysics( const FrameEvent &evt ) { stepper->step( evt.timeSinceLastFrame ); world->synchronise(); Vector3 position; for( std::vector< ODE_CHAR_INFO >::iterator it = ode_characters.begin(); it != ode_characters.end(); it++ ) { // raise desired ray position a little above character's // scenenode. position = it->charNode->getPosition(); // may need to raise it higher for better accuracy position.y += ( it->radius * 2 ); //position.y += ( it->radius ); // fire ray downward it->charRay->setDefinition( position , Ogre::Vector3::NEGATIVE_UNIT_Y ); // add ray to collisionListener it->charRay->collide( terrainTriMeshGeom, this ); } } // Create the tri-mesh terrain from a mesh void create_ODE_Terrain( std::string meshFile , Ogre::Vector3 position, Ogre::Vector3 size ) { Ogre::SceneNode* sn = mSceneMgr->getRootSceneNode()->createChildSceneNode( "TerrainNode", position ); Ogre::Entity* ent = mSceneMgr->createEntity( "Terrain", meshFile.c_str() ); sn->attachObject( ent ); sn->setScale( size ); OgreOde::EntityInformer ei( ent, sn->_getFullTransform() ); terrainTriMeshGeom = ei.createStaticTriangleMesh( world , world->getDefaultSpace() ); terrainTriMeshGeom->setRayListener( this ); } // create the character object void create_ODE_character( std::string name , Ogre::SceneNode* baseNode ) { Ogre::AxisAlignedBox aab = baseNode->getAttachedObject( name.c_str() )->getBoundingBox(); Ogre::Vector3 min = aab.getMinimum() * baseNode->getScale(); Ogre::Vector3 max = aab.getMaximum() * baseNode->getScale(); Ogre::Vector3 size( fabs( max.x - min.x ) , fabs( max.y - min.y ) , fabs( max.z - min.z )); float radius = ( size.x > size.z ) ? size.z / 2.0 : size.x / 2; // create ray for character // associate node with array. Store data ODE_CHAR_INFO c; c.charName = name; c.charNode = baseNode; // may want to adjust the length of the ray for accuracy c.charRay = new OgreOde::RayGeometry( 100, world , world->getDefaultSpace() ); c.radius = radius; ode_characters.push_back( c ); } void destroy_ODE_character( std::string name ) { for( std::vector< ODE_CHAR_INFO >::iterator it = ode_characters.begin(); it != ode_characters.end(); it++ ) { if( it->charName == name ) { it->charNode = NULL; delete it->charRay; ode_characters.erase( it ); break; } } } void destroy_ALL_ODE_characters() { for( std::vector< ODE_CHAR_INFO >::iterator it = ode_characters.begin(); it != ode_characters.end(); it++ ) { it->charNode = NULL; delete it->charRay; } ode_characters.clear(); } private: std::vector< ODE_CHAR_INFO > ode_characters; OgreOde::World* world; OgreOde::StepHandler* stepper; Ogre::SceneManager* mSceneMgr; OgreOde::TriangleMeshGeometry* terrainTriMeshGeom; }; // Declare a subclass of the ExampleApplication class class SampleApp : public ExampleApplication { public: SampleApp( void ) {} protected: // Define what is in the scene void createScene( void ) {} // Create new frame listener void createFrameListener( void ) { mFrameListener = new MyListener( mWindow, mCamera, mSceneMgr, mRoot ); mRoot->addFrameListener( mFrameListener ); } }; #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 SampleApp 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 std::cerr << "An exception has occured: " << e.getFullDescription(); #endif } return 0; } #ifdef __cplusplus } #endif {CODE} Another note to add: The length of the ray and where it starts (how much above the character) may need to be adjusted to work properly. For example, a Ray length of 1000 and position of 200 above the character should work fine. I have found strange effects when walking over parts of the mesh which overlap itself, such as a terrain with a built in bridge. One thing to try is to make the bridge as a separate trimesh and see if the character correctly walks over it.
Search by Tags
Search Wiki by Freetags
Latest Changes
IDE Eclipse
FMOD SoundManager
HDRlib
Building Ogre V2 with CMake
Ogre 2.1 FAQ
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
...more
Search
Find
Advanced
Search Help
Online Users
132 online users