Get XZ coordinates         Mouse picking on the XZ plane

This is a short snippet of code on how to get the XZ coordinates, your mouse is pointing at. This comes in handy when you are making some kind of basic level or prop editor.
Xz_intersection.png

To perform a {LEX()}Ray{LEX} we must have something it can intersect with. For this "thing", we will use an Ogre::Plane. We will create a flat plane and place it at the position (0,0,0) and when we click the left mouse button, we will create a ninja and place it wherever the mouse is pointing at.

First off, create a Plane and a {LEX()}SceneNode{LEX} which we can attach our ninja to:

Plane mPlane(Vector3::UNIT_Y, 0);

// If you don't want to display the plane, comment this function call:
Ogre::MeshManager::getSingleton().createPlane("ground",
   ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
   mPlane,
   1500,1500,
   20,20,
   true,
   1,
   1500,1500,
   Vector3::UNIT_Z
   );

// create the ninja node
mNinjaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();


Next we create a Ninja {LEX()}entity{LEX} and attach it to a SceneNode:

bool YourMouseListenerClass::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) {
    switch(id) {
        case OIS::MB_Left:
            Ogre::Entity ent = mSceneMgr->createEntity("Ninja", "ninja.mesh");
                        mNinjaNode->attachObject(ent);

            break;
    }
    return true;
}


Now, whenever we move the mouse over the plane, we'd like to position the ninja node somewhere on the floor (i.e Y = 0) the mouse pointer is pointing at. To accomplish this we have to set up a {LEX()}Ray{LEX} from the mouse pointer's offset of the camera. Ogre provides us the Ogre::Camera::getCameraToViewportRay() function which will do the job. getCameraToViewportRay() requeries a 0-1 range for the mouse offset, and since in this case we are using absolute mouse offsets we need to convert.

bool YourMouseListenerClass::mouseMoved(const OIS::MouseEvent &arg){
   // get window height and width
   Ogre::Real screenWidth = Ogre::Root::getSingleton().getAutoCreatedWindow()->getWidth();
   Ogre::Real screenHeight = Ogre::Root::getSingleton().getAutoCreatedWindow()->getHeight();

   // convert to 0-1 offset
   Ogre::Real offsetX = arg.state.X.abs / screenWidth;
   Ogre::Real offsetY = arg.state.Y.abs / screenHeight;

   // set up the ray
   Ray mouseRay = mCamera->getCameraToViewportRay(offsetX, offsetY);

   // check if the ray intersects our plane
   // intersects() will return whether it intersects or not (the bool value) and
   // what distance (the Real value) along the ray the intersection is
   std::pair<bool, Real> result = mouseRay.intersects(mPlane);

    if(result.first) {
           // if the ray intersect the plane, we have a distance value
           // telling us how far from the ray origin the intersection occurred.
           // the last thing we need is the point of the intersection.
           // Ray provides us getPoint() function which returns a point
           // along the ray, supplying it with a distance value.

           // get the point where the intersection is
       Vector3 point = mouseRay.getPoint(result.second);
          
           // position our ninja to that point  
       mNinjaNode->setPosition(point);
    }
    return true;
}

Discussion & Questions

Check out this thread for discussion and/or further questions

See also


Alias: Mouse ray Mouse_ray