From delta3d Wiki
Jump to: navigation, search

Object Motion Model Part II

In the previous two tutorials we learned about motion models as applied to cameras and objects. Those tutorials used a specific motion model called the orbit model. Delta3d currently includes 3 additional default motion models: fly, ufo, and walk. In this tutorial we will expand on our motion model code to explore these additional motion models, as well as learn more about handing user input.

You are currently in tutorial 2/3 of the object motion model series.

Additional Tutorials that will apply:
HelloWorld2

The Header File

In your HelloWorldApp header file simply:

  1. Change the name of your mTextObject to mBoxObject.
  2. Add a public virtual bool KeyPressed(const dtCore::Keyboard* kb, int key) function (we will get more into this later)
class HelloWorldApp : public dtABC::Application
{
   public:
      HelloWorldApp(const std::string& configFilename);

      // Override this function to setup your scene.
      virtual void Config();
      virtual bool KeyPressed(const dtCore::Keyboard* kb, int key);

   protected:
      // Destructors for subclasses of dtCore::Base must have a protected
      // destructor. Otherwise use of RefPtrs will cause some serious
      // problems if the objects are allocated on the stack.
      virtual ~HelloWorldApp();

   private:
      // dtCore::RefPtr is a template for a smart pointer that takes
      // care of reference counting for objects allocated on the heap.
      // It is good practice to store all objects that derive from
      // dtCore::Base inside a RefPtr.
      dtCore::RefPtr<dtCore::Object> mBoxObject;
      dtCore::RefPtr<dtCore::MotionModel> mMotionModel;
};

The Implementation File

We will first need to add some terrain to our scene in order to make our Box model more interactive. Fortunately, Deltat3d supports Procedural Terrain Modeling (were terrain is generated on the fly via algorithms). We will also remove the "Hello World" mTextObject model from the code to simplify the scene and replace it with the Box model. Finally we will override the Application::KeyPressed function to set input that can trigger a switch between the different motion model types, as well as toggle the motion model target between the Box the camera:

  1. Add terrain to scene
  2. Replace mTextObject with mBoxObject
  3. Override Application::KeyPressed

Your new code after completing steps #1 and #2 will look like this:

void HelloWorldApp::Config()
{
   // Call the parent class, in case something important is happening there
   Application::Config();

   GetWindow()->SetWindowTitle("Orbit Mode");

   // Adjust the Camera position by instantiating a transform object to
   // store the camera position and attitude.
   dtCore::Transform camPosition;
   camPosition.Set(-300.f, -300.f, 100.f,   //position 
		      0.f,    0.f,   0.f,   //lookat
		      0.f,    0.f,   1.f);  //up Vector
   
   //Set transform to the camera
   GetCamera()->SetTransform(camPosition);

   // Setting a motion model for the camera
   mMotionModel = new dtCore::OrbitMotionModel(GetKeyboard(), GetMouse());

   // Allocate a dtCore::Object. This class will be your basic container
   // for 3D meshes.
   mBoxObject = new dtCore::Object("Box");

   // Load the model file, in this case an OpenFlight model (.flt) from the zip provided
   mBoxObject->LoadFile("box2.3DS");

   // Setting the camera as a target for the motion model. The camera will
   // will be static, and the camera will move the object using the right
   // clicked mouse.
   mMotionModel->SetTarget(mBoxObject);

   // Add the Object to the scene. Since the object is a RefPtr, we must
   // pull the internal point out to pass it to the Scene.
   AddDrawable(new dtCore::InfiniteTerrain);
   AddDrawable(mBoxObject.get());
}

Now comes step #3 in which we override the Application::KeyPressed function. Paying attention to the comments will help to understand the source:

//Override the Application::KeyPressed function
//This function gets called whenever the user enters any input (as implemented by the Application class)
//We want to have the F1-F4 buttons change between the different motion model types
//Finally we want to be able to change the target of the motion model to be either the camera or the box via F5
bool HelloWorldApp::KeyPressed(const dtCore::Keyboard* kb, int key)
{
   bool ret = false;

   //Retreive the current target of our motion model
   //This is important because if we want to retain the previous target in the new motion model
   dtCore::Transformable* target = mMotionModel.get()->GetTarget();

   //Check which key has been pressed
   switch(key)
   {
   //osgGA::GUIEventAdapter provides the input values
   case osgGA::GUIEventAdapter::KEY_F1: //F1
      {
         //Set the motion model to be of the Orbit type
	 mMotionModel = new dtCore::OrbitMotionModel(GetKeyboard(), GetMouse());	
			
	 //Retain the previous target 
	 if(target == mBoxObject)
	 {
	    mMotionModel->SetTarget(mBoxObject);
	 }
	 else
	 {
	    mMotionModel->SetTarget(GetCamera());
	 }

	 GetWindow()->SetWindowTitle("Orbit Mode");
	 ret = true;
	 break;
      } 
   case osgGA::GUIEventAdapter::KEY_F2: //F2
      {
         //Set the motion model to be of the Fly type
	 mMotionModel = new dtCore::FlyMotionModel(GetKeyboard(), GetMouse());

	 //Retain the previous target
	 if(target == mBoxObject)
	 {
	    mMotionModel->SetTarget(mBoxObject);
	 }
	 else
	 {
	    mMotionModel->SetTarget(GetCamera());
	 }

	 GetWindow()->SetWindowTitle("Fly Mode");
	 ret = true;
	 break;
      } 
   case osgGA::GUIEventAdapter::KEY_F3: //F3
      {
         //Set the motion model to be of the UFO type
	 mMotionModel = new dtCore::UFOMotionModel(GetKeyboard(), GetMouse());

 	 //Retain the previous target
	 if(target == mBoxObject)
	 {
	    mMotionModel->SetTarget(mBoxObject);
	 }
	 else
	 {
	    mMotionModel->SetTarget(GetCamera());
	 }

	 GetWindow()->SetWindowTitle("UFO Mode");
	 ret = true;
	 break;
      } 
   case osgGA::GUIEventAdapter::KEY_F4: //F4
      {
         //Set the motion model to be of the Walk type
	 mMotionModel = new dtCore::WalkMotionModel(GetKeyboard(), GetMouse());

	 //Retain the previous target
	 if(target == mBoxObject)
	 {
	    mMotionModel->SetTarget(mBoxObject);
	 }
	 else
	 {
	    mMotionModel->SetTarget(GetCamera());
	 }

	 GetWindow()->SetWindowTitle("Walk Mode");
	 ret = true;
	 break;
   } 
   case osgGA::GUIEventAdapter::KEY_F5:
      {
         //If the target was the box then change to the camera, or vice versa
	 if(target == mBoxObject)
	 {
	    mMotionModel->SetTarget(GetCamera());
	 }
	 else
	 {
	    mMotionModel->SetTarget(mBoxObject);
	 }
      }
   default:
      {
	 ret = false;
	 break;
      }
   }

   return ret;
}

Everything else in the .h .cpp files remains the same.

Running

Now let's compile and run the app! You should see an screen similar to this: Hello World 3 new.png

Pressing F1-F4 will change you between the different motion model types:

    • The orbit motion model simulates the standard controls to manipulate a 3D scene for viewing from arbitrary point (i.e. translate, rotation, and zoom).
    • The fly motion model simulates the control of an object in flight.
    • The UFO motion model allows the camera to easily move along a horizontal plane easily, while additional controls let camera move up/down and turn left/right.
    • The walk motion model simulates walking or driving.

Pressing F5 will toggle the target of the motion model between the Box and the camera.

The controls for each model are:

  Orbit Motion Model:
  Left   Mouse Button - Rotate camera
  Right  Mouse Button - Translate camera
  Middle Mouse Button - Zoom camera

  Fly Motion Model:
  Up     -  Look up
  Down   -  Look down
  Left   -  Turn left
  Right  -  Turn right
  S      -  Move forward
  W      -  Move backward
  Left  Mouse Button - Look up/down, turn left/right
  Right Mouse Button - Move forward/backward

  UFO Motion Model:
  Up     -  Move forward
  Down   -  Move backward
  Left   -  Strafe left
  Right  -  Strafe right
  A      -  Turn left
  D      -  Turn right
  S      -  Move up
  W      -  Move down
  Left  Mouse Button - Move forward/backward, strafe   left/right
  Right Mouse Button - Move up/down, turn left/right

  Walk Motion Model:
  Up     -  Move forward
  Down   -  Move backward
  Left   -  Turn left
  Right  -  Turn right	
  A      -  Strafe left
  D      -  Strafe right
  Left  Mouse Button - Move forward/backward, turn   left/right
  Right Mouse Button - Strafe left/right


That's the end of the Delta3D Object Motion Model Part II tutorial. To better learn the application, play with it a little: search the web for others 3D models and change the motion model used to see how it will behave. Remember that you may need to adjust the camera position depending on the model used to get a good initial view!

Complete files to download: Hello_World_3_Models.zip