Requirements - What do I need to run NxOgre?

  • Ogre, compiled and working
  • A working PhysX installation

Go to http://developer.nvidia.com/object/physx_downloads.html and download and install the latest PhysX System Software and the nVidia PhysX SDK.

  • Download NxOgre from SVN

TortoiseSVN is suggested for this - http://tortoisesvn.tigris.org/. After that, create an empty folder and right click, choosing 'SVN checkout...' from the context menu. In the opened window input the URL: http://svn.nxogre.org/branches/1.0/NxOgre and hit OK, letting it download the NxOgre source.

  • Create environmental variables

Go into My Computer Properties/Advanced/Environmental Variable. Add new variable PHYSX_DIR and enter full path for the SDK (ie. 'c:/program files/nVidia/Physx 2.x.x'). If you don't want change directories in my tutorials add another variable with 'NXOGRE_DIR' along with the path to NxOgre( ie. 'c:/foo/NxOgre').

Compiling NxOgre

If you set up environmental variables correctly you won't need to change anything. :-) Just hit compile and wait. Compile debug and release.

Creating a new NxOgre project

  • First, create a new C++ project
  • Open project properties and add new include directories:
    • $(OGRE_HOME)\include
    • $(OGRE_HOME)\samples\include
    • $(NXOGRE_DIR)\include
    • $(PHYSX_DIR)\SDKs\Cooking\include
    • $(PHYSX_DIR)\SDKs\NxCharacter\include
    • $(PHYSX_DIR)\SDKs\Foundation\include
    • $(PHYSX_DIR)\SDKs\Physics\include
    • $(PHYSX_DIR)\SDKs\PhysXLoader\include"
    • Samples/include is solely for the example application framework. You may omit it if you do not with to use the example framework.
  • Add new linker library directories:
    • $(OGRE_HOME)\lib
    • $(NXOGRE_DIR)\lib
    • $(PHYSX_DIR)\SDKs\lib\Win32
  • Add additional library dependencies:
    • OgreMain_d.lib / OgreMain.lib
    • OIS_d.lib / OIS.lib
    • NxOgre_d.lib / NxOgre.lib
    • PhysXLoader.lib
    • NxCooking.lib
    • NxCharacter.lib
    • Libs with _d at end are for debug mode, without for release

PhysX Params

Before using NxOgre you need to understand the following. When creating things like an actor or world you need to use params. You can define it either by passing in a String or instantiating a params class. Take a look at these two examples:

//String params
 World* mWorld = new World("log: yes, time-controller: ogre");

 //Params class
 PhysXParams params;
 params.mLog = true;
 params.mTimeController = PhysXParams::TC_Ogre;
 World* mWorld = new World(params);

The first one is creating world using string params, the second class. Using string params is easier but sometimes you may need to use class params.
The name each String Param takes is a slight modification of the name of its C++ equivalent: it is converted to lower-case, the “m” prefix is dropped, and the camel case of the name is split using a hyphen.

For example:

mLog -> "log"
 mTimeController -> "time-controller"
 mImplictSweepCacheSize -> "implicit-sweep-cache-size"

Passing on the value to a String Param is pretty much the same as in C++, as integers and other basic types all behave in the same way. The only restriction is that a comma cannot be part of the string, as it is regarded as the end of the previous param and the start of another.

"integer: 4"
 "bool: true"
 "bool: no"
 "floating-point: 4.3"
 "double: 4.4323"
 "string: This is a string name."
 "vector3: 1 2 3"
 "quaternion: 1 0 0 0"

NxOgre objects



The main object of NxOgre is World. There can be only one and it can have an infinite size.

Inside the world there are Scenes. You can have up to 32 scenes. Objects from one scene cannot collide with objects from another.

Inside a scene there are units called Actors. These can be houses, boxes, characters, or trees, etc... Actors can be organized into Groups. Actors aren't visible until you turn debug renderer.

Each actor is made from one or more shapes. When a shape collides with a shape from another body, it’ll need to know how to react properly. This behavior is defined by a few properties which make up a shape’s Material.

There is also thing called a body. It's an actor and ogre sceneNode in one object. Bodies are visible.

Initializing NxOgre

Initialization of NxOgre is very easy. You need create main object 'World'. Ogre time controller means that ogre will care about timing. Logging is optional.

NxOgre::World*    mNxWorld = new NxOgre::World("time-controller:ogre, log:yes");

Then create your first scene. You can use infinite floor, or setup gravity (yes/no/0 -9.788 0). Ogre will be used as the renderer and gravity is enabled by default.

NxOgre::Scene*    mNxScene = mNxWorld->createScene("NxOgreScene", mSceneMgr, "gravity:yes, floor:yes, renderer:ogre");

There is also a handy tool called the debug renderer. You can use it to make actors visible. Just write:

mNxWorld->createDebugRenderer(mSceneMgr);

mSceneMgr is an instantiation of Ogre::SceneManager.

Shapes

Evrything in NxOgre is built from shapes, smallest elements. There are 7 types of shapes:

  • Cube
  • Sphere
  • Capsule
  • Ground
  • Convex
  • TriangleMesh
  • Terrain




You can achieve most anything from these types. Each shape has the same initialization, for example cube:

new Cube(1,"");

The last argument here is a ShapeParam. Another arguments is the shape specified. If you are not using a ShapeParam you don't need to use "". I'll write more about them in another tutorial.

Creating actors

Remember that actors aren't visible until you turn on the debug renderer or use the remote debugger.

Creation is very simple:

Actor* actor = mNxScene->createActor(name,shape,positon,params);
  • name is actor unique name
  • actor shape, look at shape section
  • position in Vector3(x,y,z)
  • actorParams:
    • mass: 10
    • density: 10 - if u set mass to zero NxOgre will calculate mass using density and volume
    • group: groupname
    • static: yes - make actor static, it can't be moved or change position, you can get it also be setting mass and density to 0




That is an example of making a simple 1x1x1 box named "box" that is 5 units off the ground and has a mass of 10:

Actor* actor = mNxScene->createActor("box", new Cube(1), Vector3(0,5,0), "mass:10");

Creating bodies



A Body is an actor and ogre sceneNode combined so you need to create a sceneNode first:

Ogre::Entity *ent = mSceneMgr->createEntity( "box_entity", "cube.mesh" );
 ent->setMaterialName("Examples/10PointBlock");
 Ogre::SceneNode *boxNode= mSceneMgr->getRootSceneNode()->createChildSceneNode( "box_node" );
 boxNode->attachObject( ent );

Then comes a time when you can't use string params. To make the body visible you need to set up NodeRenderableParams:

NodeRenderableParams nrp;
 nrp.setToDefault();
 nrp.mIdentifierUsage = NxOgre::NodeRenderableParams::IU_Use;
 nrp.mIdentifier = boxNode->getName();

And the last and easiest thing is to create body using createBody(name,shape,pos,nrp,actorparams).

NxOgre::Body *body = mNxScene->createBody("box_body",new Cube(1),Vector3(0,10,0),nrp,"mass:10");

Serial box creation



Each box must have unique name to work. It's not hard, just add variable that will controll number of created bodies. For example you can create your create box function that will look like that:

void createBox(Vector3 pos,float scale = 1)
 {
     //    this is a scale between Ogre and NxOgre
     //    for example if u set scale to 5 it will be 0.1 in Ogre and 10 in NxOgre
     static const Real mesh_scale = 0.02;
     static const Real physics_scale = 2.0;
     //    create a name for object
     String name = "Box_" + StringConverter::toString(createdObjects);
     //    incrase number of objects
     createdObjects++;
 
     //    [OGRE] create box, set material and scale it
     Ogre::Entity *E = mSceneMgr->createEntity( name+"_entity", "cube.mesh" );
     E->setMaterialName("Examples/10PointBlock");
     Ogre::SceneNode *sn = mSceneMgr->getRootSceneNode()->createChildSceneNode( name+"_node" );
     sn->attachObject( E );
     sn->scale( Vector3::UNIT_SCALE * mesh_scale * scale );
 
     //    create node renderable parms for body
     NodeRenderableParams nrp;
     nrp.setToDefault();
     nrp.mIdentifierUsage = NxOgre::NodeRenderableParams::IU_Use;
     nrp.mIdentifier = sn->getName();
 
     //    create body (name,shape,position,node rednderable params,actor params)
     //    actor params is for example mass
     NxOgre::Body *body = mNxScene->createBody(name+"_body",new Cube(scale*2),pos,nrp,"mass:10");
 }

Source code


simple_sample.cpp

/*    NxOgre Tutorial 1: Simple Sample by radsun    */
 
 #include "simple_sample.h"
 
 //    startup
 INT WINAPI WinMain(HINSTANCE , HINSTANCE, LPSTR, INT)
 {
     SimpleSampleApplication app;
 
     //    aplication setup and loop
     try {
         app.go();
     } catch( Ogre::Exception& e ) {
         MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
     }
 
     return 0;
 }

simple_sample.h


//    NxOgre tutorials is using ogre example application framework
 #include "ExampleApplication.h"
 
 //    only file you need to include to use NxOgre
 #include "NxOgre.h"
 
 //    NxOgre have his own namespace, remember to use it
 using namespace NxOgre;
 
 //    frame listener
 class SimpleSampleFrameListener : public ExampleFrameListener
 {
 public:
     SimpleSampleFrameListener(RenderWindow* win, Camera* cam) : ExampleFrameListener( win, cam )
     {
     }
 
     bool frameStarted( const FrameEvent& evt )
     {
         if( ExampleFrameListener::frameStarted(evt) == false )
             return false;
 
         return true;
     }
 };
 
 //    application
 class SimpleSampleApplication : public ExampleApplication
 {
 public:
     SimpleSampleApplication()
     {
         createdObjects = 0;
     }
 
 protected:
     virtual void createFrameListener(void)
     {
         mFrameListener= new SimpleSampleFrameListener(mWindow, mCamera);
         mRoot->addFrameListener(mFrameListener);
     }
 
     // create box on with given position and scale
     void createBox(Vector3 pos,float scale = 1)
     {
         //    this is a scale between Ogre and NxOgre
         //    for example if u set scale to 5 it will be 0.1 in Ogre and 10 in NxOgre
         static const Real mesh_scale = 0.02;
         static const Real physics_scale = 2.0;
         //    create a name for object
         String name = "Box_" + StringConverter::toString(createdObjects);
         //    incrase number of objects
         createdObjects++;
 
         //    [OGRE] create box, set material and scale it
         Ogre::Entity *E = mSceneMgr->createEntity( name+"_entity", "cube.mesh" );
         E->setMaterialName("Examples/10PointBlock");
         Ogre::SceneNode *sn = mSceneMgr->getRootSceneNode()->createChildSceneNode( name+"_node" );
         sn->attachObject( E );
         sn->scale( Vector3::UNIT_SCALE * mesh_scale * scale );
 
         //    create node renderable parms for body
         NodeRenderableParams nrp;
         nrp.setToDefault();
         nrp.mIdentifierUsage = NxOgre::NodeRenderableParams::IU_Use;
         nrp.mIdentifier = sn->getName();
 
         //    create body (name,shape,position,node rednderable params,actor params)
         //    actor params is for example mass
         NxOgre::Body *body = mNxScene->createBody(name+"_body",new Cube(scale*physics_scale),pos,nrp,"mass:10");
     }
 
     void createScene(void)
     {
         //    [OGRE] set up camera
         mCamera->setPosition(Vector3(0,10,20));
         mCamera->lookAt(Vector3(0,0,0));
         mCamera->setNearClipDistance(1);
 
         //    [OGRE] build floor
         int i = 0;
         StaticGeometry* s;
         s = mSceneMgr->createStaticGeometry("StaticFloor");
         s->setRegionDimensions(Vector3(160.0, 100.0, 160.0));
         s->setOrigin(Vector3::ZERO);
         for (Real z = -80.0;z <= 80.0;z += 20.0)
         {
             for (Real x = -80.0;x <= 80.0;x += 20.0)
             {
                 String name = String("Plane_") + StringConverter::toString(i++);
             
                 Entity* entity = mSceneMgr->createEntity(name, "plane.mesh");
                 entity->setQueryFlags (0);
                 entity->setCastShadows(false);
                 s->addEntity(entity, Vector3(x,0,z));
             }
         }
         s->build();
 
             //    [OGRE] create a skybox
             mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox");
 
         //    create NxWorld, a main physic object
         //    log: yes/no
         //    ogre time controller means rhat ogre will care about it
         mNxWorld = new NxOgre::World("time-controller:ogre, log:yes");
 
         //    create scene, you can have maximum 32 scenes, object from one scene can't
         //    collide with objects from another (maybe in another versions :D )
         //    gravity: yes/no/0 -9.788 0
         //    floor: create infinity floor, yes/no
         //    ogre will be used as debug renderer
         mNxScene = mNxWorld->createScene("NxOgreScene", mSceneMgr,"gravity:yes, floor:yes, renderer:ogre");
 
         //    create some boxes
         createBox(Vector3(0,10,0));
         createBox(Vector3(1,15,0));
         //    create small box
         createBox(Vector3(2,30,0),0.5);
 
         //mNxScene->createActor(new Terrain(
     }
 private:
     // NxOgre stuff
     World*    mNxWorld;
     Scene*    mNxScene;
     //    number of objects, it's used to give unique names to new objects
     int        createdObjects;
 };

Binary and code download



No dll's, you may need to download PhysX_Game_installer and
Visual C++ Runtime Redistributables - VC++ 2005 SP1 if udon't have it.

http://twormz.republika.pl/nxogretut/tutsimplesample.rar

Getting help


Problems? Questions? http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=7938