orbit_view_controller.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "orbit_view_controller.h"
00031 #include "rviz/viewport_mouse_event.h"
00032 #include "rviz/visualization_manager.h"
00033 
00034 #include <OGRE/OgreCamera.h>
00035 #include <OGRE/OgreSceneManager.h>
00036 #include <OGRE/OgreSceneNode.h>
00037 #include <OGRE/OgreVector3.h>
00038 #include <OGRE/OgreQuaternion.h>
00039 #include <OGRE/OgreViewport.h>
00040 
00041 #include <ogre_tools/shape.h>
00042 
00043 #include <stdint.h>
00044 #include <sstream>
00045 
00046 namespace rviz
00047 {
00048 
00049 static const float MIN_DISTANCE = 0.01;
00050 static const float PITCH_LIMIT_HIGH = Ogre::Math::HALF_PI - 0.001; 
00051 static const float PITCH_LIMIT_LOW = -PITCH_LIMIT_HIGH;
00052 static const float PITCH_START = Ogre::Math::HALF_PI / 2.0;
00053 static const float YAW_START = Ogre::Math::HALF_PI * 0.5;
00054 
00055 OrbitViewController::OrbitViewController(VisualizationManager* manager, const std::string& name, Ogre::SceneNode* target_scene_node)
00056 : ViewController(manager, name, target_scene_node)
00057 , focal_point_( Ogre::Vector3::ZERO )
00058 , yaw_( YAW_START )
00059 , pitch_( PITCH_START )
00060 , distance_( 10.0f )
00061 {
00062   focal_shape_ = new ogre_tools::Shape(ogre_tools::Shape::Sphere, manager_->getSceneManager(), target_scene_node_);
00063   focal_shape_->setScale(Ogre::Vector3(0.05f, 0.05f, 0.01f));
00064   focal_shape_->setColor(1.0f, 1.0f, 0.0f, 0.5f);
00065   focal_shape_->getRootNode()->setVisible(false);
00066 }
00067 
00068 OrbitViewController::~OrbitViewController()
00069 {
00070   delete focal_shape_;
00071 }
00072 
00073 void OrbitViewController::handleMouseEvent(ViewportMouseEvent& event)
00074 {
00075   bool moved = false;
00076   if( event.type == QEvent::MouseButtonPress )
00077   {
00078     focal_shape_->getRootNode()->setVisible(true);
00079     moved = true;
00080   }
00081   else if( event.type == QEvent::MouseButtonRelease )
00082   {
00083     focal_shape_->getRootNode()->setVisible(false);
00084     moved = true;
00085   }
00086   else if( event.type == QEvent::MouseMove )
00087   {
00088     int32_t diff_x = event.x - event.last_x;
00089     int32_t diff_y = event.y - event.last_y;
00090 
00091     // regular left-button drag
00092     if( event.left() && !event.shift() )
00093     {
00094       yaw( diff_x*0.005 );
00095       pitch( -diff_y*0.005 );
00096     }
00097     // middle or shift-left drag
00098     else if( event.middle() || (event.shift() && event.left()) )
00099     {
00100       float fovY = camera_->getFOVy().valueRadians();
00101       float fovX = 2.0f * atan( tan( fovY / 2.0f ) * camera_->getAspectRatio() );
00102 
00103       int width = camera_->getViewport()->getActualWidth();
00104       int height = camera_->getViewport()->getActualHeight();
00105 
00106       move( -((float)diff_x / (float)width) * distance_ * tan( fovX / 2.0f ) * 2.0f,
00107             ((float)diff_y / (float)height) * distance_ * tan( fovY / 2.0f ) * 2.0f,
00108             0.0f );
00109     }
00110     else if( event.right() )
00111     {
00112       if( event.shift() )
00113       {
00114         move(0.0f, 0.0f, diff_y * 0.1 * (distance_ / 10.0f));
00115       }
00116       else
00117       {
00118         zoom( -diff_y * 0.1 * (distance_ / 10.0f) );
00119       }
00120     }
00121 
00122     moved = true;
00123   }
00124 
00125   if( event.wheel_delta != 0 )
00126   {
00127     int diff = event.wheel_delta;
00128     if( event.shift() )
00129     {
00130       move(0.0f, 0.0f, -diff * 0.01 * (distance_ / 10.0f));
00131     }
00132     else
00133     {
00134       zoom( diff * 0.01 * (distance_ / 10.0f) );
00135     }
00136 
00137     moved = true;
00138   }
00139 
00140   if( moved )
00141   {
00142     manager_->queueRender();
00143   }
00144 }
00145 
00146 void OrbitViewController::onActivate()
00147 {
00148   if (camera_->getProjectionType() == Ogre::PT_ORTHOGRAPHIC)
00149   {
00150     camera_->setProjectionType(Ogre::PT_PERSPECTIVE);
00151   }
00152   else
00153   {
00154     Ogre::Vector3 position = camera_->getPosition();
00155     Ogre::Quaternion orientation = camera_->getOrientation();
00156 
00157     // Determine the distance from here to the reference frame, and use that as the distance our focal point should be at
00158     distance_ = position.length();
00159 
00160     Ogre::Vector3 direction = orientation * (Ogre::Vector3::NEGATIVE_UNIT_Z * distance_);
00161     focal_point_ = position + direction;
00162 
00163     calculatePitchYawFromPosition( position );
00164   }
00165 }
00166 
00167 void OrbitViewController::onDeactivate()
00168 {
00169   focal_shape_->getRootNode()->setVisible(false);
00170   camera_->setFixedYawAxis(false);
00171 }
00172 
00173 void OrbitViewController::onUpdate(float dt, float ros_dt)
00174 {
00175   updateCamera();
00176 }
00177 
00178 void OrbitViewController::lookAt( const Ogre::Vector3& point )
00179 {
00180   Ogre::Vector3 camera_position = camera_->getPosition();
00181   focal_point_ = target_scene_node_->getOrientation().Inverse() * (point - target_scene_node_->getPosition());
00182   distance_ = focal_point_.distance( camera_position );
00183 
00184   calculatePitchYawFromPosition(camera_position);
00185 }
00186 
00187 void OrbitViewController::onTargetFrameChanged(const Ogre::Vector3& old_reference_position, const Ogre::Quaternion& old_reference_orientation)
00188 {
00189   focal_point_ += old_reference_position - reference_position_;
00190 }
00191 
00192 void OrbitViewController::normalizePitch()
00193 {
00194   if ( pitch_ < PITCH_LIMIT_LOW )
00195   {
00196     pitch_ = PITCH_LIMIT_LOW;
00197   }
00198   else if ( pitch_ > PITCH_LIMIT_HIGH )
00199   {
00200     pitch_ = PITCH_LIMIT_HIGH;
00201   }
00202 }
00203 
00204 void OrbitViewController::normalizeYaw()
00205 {
00206   yaw_ = fmod( yaw_, Ogre::Math::TWO_PI );
00207 
00208   if ( yaw_ < 0.0f )
00209   {
00210     yaw_ = Ogre::Math::TWO_PI + yaw_;
00211   }
00212 }
00213 
00214 void OrbitViewController::updateCamera()
00215 {
00216   float x = distance_ * cos( yaw_ ) * cos( pitch_ ) + focal_point_.x;
00217   float y = distance_ * sin( yaw_ ) * cos( pitch_ ) + focal_point_.y;
00218   float z = distance_ *               sin( pitch_ ) + focal_point_.z;
00219 
00220   Ogre::Vector3 pos( x, y, z );
00221 
00222   camera_->setPosition(pos);
00223   camera_->setFixedYawAxis(true, target_scene_node_->getOrientation() * Ogre::Vector3::UNIT_Z);
00224   camera_->setDirection(target_scene_node_->getOrientation() * (focal_point_ - pos));
00225 
00226 //  ROS_INFO_STREAM( camera_->getDerivedDirection() );
00227 
00228   focal_shape_->setPosition(focal_point_);
00229 }
00230 
00231 void OrbitViewController::yaw( float angle )
00232 {
00233   yaw_ -= angle;
00234 
00235   normalizeYaw();
00236 }
00237 
00238 void OrbitViewController::pitch( float angle )
00239 {
00240   pitch_ -= angle;
00241 
00242   normalizePitch();
00243 }
00244 
00245 void OrbitViewController::calculatePitchYawFromPosition( const Ogre::Vector3& position )
00246 {
00247   float x = position.x - focal_point_.x;
00248   float y = position.y - focal_point_.y;
00249   float z = position.z - focal_point_.z;
00250 
00251   pitch_ = asin( z / distance_ );
00252 
00253   normalizePitch();
00254 
00255   yaw_ = atan2( y, x );
00256 }
00257 
00258 void OrbitViewController::zoom( float amount )
00259 {
00260   distance_ -= amount;
00261 
00262   if ( distance_ <= MIN_DISTANCE )
00263   {
00264     distance_ = MIN_DISTANCE;
00265   }
00266 }
00267 
00268 void OrbitViewController::move( float x, float y, float z )
00269 {
00270   focal_point_ += camera_->getOrientation() * Ogre::Vector3( x, y, z );
00271 }
00272 
00273 void OrbitViewController::fromString(const std::string& str)
00274 {
00275   std::istringstream iss(str);
00276 
00277   iss >> pitch_;
00278   iss.ignore();
00279   iss >> yaw_;
00280   iss.ignore();
00281   iss >> distance_;
00282   iss.ignore();
00283   iss >> focal_point_.x;
00284   iss.ignore();
00285   iss >> focal_point_.y;
00286   iss.ignore();
00287   iss >> focal_point_.z;
00288 }
00289 
00290 std::string OrbitViewController::toString()
00291 {
00292   std::ostringstream oss;
00293   oss << pitch_ << " " << yaw_ << " " << distance_ << " " << focal_point_.x << " " << focal_point_.y << " " << focal_point_.z;
00294 
00295   return oss.str();
00296 }
00297 
00298 
00299 }


rviz_qt
Author(s): Dave Hershberger
autogenerated on Fri Dec 6 2013 20:56:52