00001 /*========================================================================= 00002 00003 Program: Medical Imaging & Interaction Toolkit 00004 Language: C++ 00005 Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ 00006 Version: $Revision: 21975 $ 00007 00008 Copyright (c) German Cancer Research Center, Division of Medical and 00009 Biological Informatics. All rights reserved. 00010 See MITKCopyright.txt or https://www.mitk.org/copyright.html for details. 00011 00012 This software is distributed WITHOUT ANY WARRANTY; without even 00013 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00014 PURPOSE. See the above copyright notices for more information. 00015 00016 =========================================================================*/ 00017 00018 #include "mitkSpaceNavigatorVtkCameraController.h" 00019 #include "mitkVtkPropRenderer.h" 00020 #include "vtkCamera.h" 00021 #include "vtkRenderer.h" 00022 #include "vtkTransform.h" 00023 #include "mitkVector.h" 00024 #include "mitkInteractionConst.h" 00025 #include "mitkStateEvent.h" 00026 #include "mitkGlobalInteraction.h" 00027 #include "vtkMath.h" 00028 00029 #include <mitkSpaceNavigatorEvent.h> 00030 00031 const double TRANSLATIONSENSITIVITY = 2.0; 00032 const double ROTATIONSENSIVITY = 3.5; 00033 const double ANGLESENSITIVITY = 3.5; 00034 00035 00036 mitk::SpaceNavigatorVtkCameraController::SpaceNavigatorVtkCameraController() 00037 : CameraController("SpaceNavigatorInteraction") 00038 { 00039 //connect method this->OnSpaceNavigatorEvent to StateMachineEventMechanism 00040 CONNECT_ACTION(AcONSPACENAVIGATORMOUSEINPUT, OnSpaceNavigatorEvent); 00041 CONNECT_ACTION(AcONPACENAVIGATORKEYDOWN, OnSpaceNavigatorKeyDown); 00042 m_ClippingRangeIsSet = false; 00043 } 00044 00045 mitk::SpaceNavigatorVtkCameraController::~SpaceNavigatorVtkCameraController() 00046 { 00047 } 00048 00049 bool mitk::SpaceNavigatorVtkCameraController::OnSpaceNavigatorEvent(mitk::Action* a, const mitk::StateEvent* e) 00050 { 00051 //only if 3D rendering 00052 const mitk::BaseRenderer* br = mitk::GlobalInteraction::GetInstance()->GetFocus(); 00053 this->SetRenderer( br ); 00054 mitk::BaseRenderer::MapperSlotId id = ((mitk::BaseRenderer*)(br))->GetMapperID(); 00055 if (id != mitk::BaseRenderer::Standard3D) 00056 return true; 00057 00058 //only if focused by the FocusManager 00059 if (this->GetRenderer() != mitk::GlobalInteraction::GetInstance()->GetFocus()) 00060 return true; 00061 00062 //pre-checking for safety 00063 vtkRenderer* vtkRenderer = ((mitk::VtkPropRenderer*)this->GetRenderer())->GetVtkRenderer(); 00064 if (vtkRenderer == NULL) 00065 return false; 00066 00067 00068 vtkCamera* vtkCam = (vtkCamera*)vtkRenderer->GetActiveCamera(); 00069 00070 if(!m_ClippingRangeIsSet) 00071 vtkCam->SetClippingRange(0.1, 1000000); 00072 00073 const mitk::SpaceNavigatorEvent* snevent = dynamic_cast<const mitk::SpaceNavigatorEvent*>(e->GetEvent()); 00074 if (snevent == NULL) 00075 { 00076 MITK_ERROR <<"Wrong event for SpaceNavigatorVtkCameraController!"; 00077 return false; 00078 } 00079 00080 //get the information from the mouse 00081 mitk::Vector3D translation = snevent->GetTranslation(); 00082 mitk::Vector3D rotation = snevent->GetRotation(); 00083 mitk::ScalarType angle = snevent->GetAngle(); 00084 00085 //output for debug 00086 //std::cout<<"translation: "<<translation[0]<<" "<<translation[1]<<" "<<translation[2]<<" "<<"\n"; 00087 //std::cout<<"rotation: "<<rotation[0]<<" "<<rotation[1]<<" "<<rotation[2]<<" "<<"\n"; 00088 //std::cout<<"angle: "<<angle<<"\n \n"; 00089 00090 00091 //empirically gained max and min valued from driver: 00092 // MAXIMA: 00093 // translation: 0.83 1.17 1.02 00094 // rotation: 1.00 1.00 1.00 00095 // angle: 0.83 00096 // MINIMA: 00097 // translation: -1.00 -1.03 -0.88 00098 // rotation: -1.00 -1.00 -1.00 00099 // angle: 0.00 00100 00101 //compute current sensitivity according to current BoundingBox of the whole scene! 00102 double sceneSensivity = 1.0; 00103 00104 mitk::DataStorage* ds = m_Renderer->GetDataStorage(); 00105 mitk::BoundingBox::Pointer bb = ds->ComputeBoundingBox(); 00106 mitk::BoundingBox::AccumulateType length = bb->GetDiagonalLength2(); 00107 if (length > 0.00001)//if length not zero 00108 sceneSensivity *= 100.0 / (sqrt(length)) ; 00109 00110 //sensivity to adapt to mitk speed 00111 translation *= sceneSensivity * TRANSLATIONSENSITIVITY; 00112 rotation *= sceneSensivity * ROTATIONSENSIVITY; 00113 angle *= sceneSensivity * ANGLESENSITIVITY; 00114 00115 //compute the global space coordinates from the relative mouse coordinate 00116 //first we need the position of the camera 00117 mitk::Vector3D camPosition; 00118 double camPositionTemp[3]; 00119 vtkCam->GetPosition(camPositionTemp); 00120 camPosition[0] = camPositionTemp[0]; camPosition[1] = camPositionTemp[1]; camPosition[2] = camPositionTemp[2]; 00121 00122 //then the upvector of the camera 00123 mitk::Vector3D upCamVector; 00124 double upCamTemp[3]; 00125 vtkCam->GetViewUp(upCamTemp); 00126 upCamVector[0] = upCamTemp[0]; upCamVector[1] = upCamTemp[1]; upCamVector[2] = upCamTemp[2]; 00127 upCamVector.Normalize(); 00128 00129 //then the vector to which the camera is heading at (focalpoint) 00130 mitk::Vector3D focalPoint; 00131 double focalPointTemp[3]; 00132 vtkCam->GetFocalPoint(focalPointTemp); 00133 focalPoint[0] = focalPointTemp[0]; focalPoint[1] = focalPointTemp[1]; focalPoint[2] = focalPointTemp[2]; 00134 mitk::Vector3D focalVector; 00135 focalVector = focalPoint - camPosition; 00136 focalVector.Normalize(); 00137 00138 //orthogonal vector to focalVector and upCamVector 00139 mitk::Vector3D crossVector; 00140 crossVector = CrossProduct(upCamVector, focalVector); 00141 crossVector.Normalize(); 00142 00143 //now we have the current orientation so we can adapt it according to the current information, which we got from the TDMouse 00144 00145 //new position of the camera: 00146 //left/right = camPosition + crossVector * translation[0]; 00147 mitk::Vector3D vectorX = crossVector * -translation[0]; //changes the magnitude, not the direction 00148 double nextCamPosition[3]; 00149 nextCamPosition[0] = camPosition[0] + vectorX[0]; 00150 nextCamPosition[1] = camPosition[1] + vectorX[1]; 00151 nextCamPosition[2] = camPosition[2] + vectorX[2]; 00152 00153 //now the up/down movement 00154 mitk::Vector3D vectorY = upCamVector * translation[1]; //changes the magnitude, not the direction 00155 nextCamPosition[0] += vectorY[0]; 00156 nextCamPosition[1] += vectorY[1]; 00157 nextCamPosition[2] += vectorY[2]; 00158 00159 //forward/backward movement 00160 mitk::Vector3D vectorZ = focalVector * -translation[2]; //changes the magnitude, not the direction 00161 nextCamPosition[0] += vectorZ[0]; 00162 nextCamPosition[1] += vectorZ[1]; 00163 nextCamPosition[2] += vectorZ[2]; 00164 00165 //set the next position 00166 double nextPosition[3]; 00167 nextPosition[0] = nextCamPosition[0]; nextPosition[1] = nextCamPosition[1]; nextPosition[2] = nextCamPosition[2]; 00168 vtkCam->SetPosition(nextPosition); 00169 00170 //adapt the focal point the same way 00171 double currentFocalPoint[3], nextFocalPoint[3]; 00172 vtkCam->GetFocalPoint(currentFocalPoint); 00173 nextFocalPoint[0] = currentFocalPoint[0] + vectorX[0] + vectorY[0] + vectorZ[0]; 00174 nextFocalPoint[1] = currentFocalPoint[1] + vectorX[1] + vectorY[1] + vectorZ[1]; ; 00175 nextFocalPoint[2] = currentFocalPoint[2] + vectorX[2] + vectorY[2] + vectorZ[2]; 00176 vtkCam->SetFocalPoint(nextFocalPoint); 00177 00178 00179 //now adapt the rotation of the mouse and adapt the camera according to it 00180 00181 //Pitch: 00182 //Rotate the focal point about the cross product of the view up vector and the direction of 00183 //projection, centered at the camera's position. 00184 vtkCam->Pitch(rotation[0]*angle); 00185 00186 //Yaw: 00187 //Rotate the focal point about the view up vector centered at the camera's position. 00188 //Note that the view up vector is not necessarily perpendicular to the direction of projection. 00189 vtkCam->Yaw(rotation[1]*angle); 00190 00191 //Roll: 00192 //Rotate the camera about the direction of projection. 00193 vtkCam->Roll(-rotation[2]*angle * 1.5);//*1.5 to speed up the rotation[2] a little bit 00194 00195 //Recompute the ViewUp vector to force it to be perpendicular to camera->focalpoint vector. 00196 //Unless you are going to use Yaw or Azimuth on the camera, there is no need to do this. 00197 vtkCam->OrthogonalizeViewUp(); 00198 00199 //no zooming, only translating to the front or back 00200 // dolly: Move the position of the camera along the direction 00201 // of projection. Moving towards the focal point (e.g., greater 00202 // than 1) is a dolly-in, moving away from the focal point 00203 // (e.g., less than 1) is a dolly-out. 00204 //double distance = ((tdevent->GetTranslation())[1] / 10.0);//make it less sensitive in comparison to translation and rotatipn 00205 //vtkCam->Dolly(1.0 + distance ); 00206 00207 00208 //Reset the camera clipping range based on the bounds of the visible actors. 00209 //This ensures that no props are cut off 00210 vtkRenderer->ResetCameraClippingRange(); 00211 00212 mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(mitk::GlobalInteraction::GetInstance()->GetFocus()->GetRenderWindow()); 00213 00214 return true; 00215 } 00216 00217 00218 bool mitk::SpaceNavigatorVtkCameraController::OnSpaceNavigatorKeyDown(mitk::Action* a, const mitk::StateEvent* e) 00219 { 00220 //reset the camera, so that the objects shown in the scene can be seen. 00221 const mitk::VtkPropRenderer* glRenderer = dynamic_cast<const mitk::VtkPropRenderer*>(m_Renderer); 00222 if (glRenderer) 00223 { 00224 vtkRenderer* vtkRenderer = glRenderer->GetVtkRenderer(); 00225 mitk::DataStorage* ds = m_Renderer->GetDataStorage(); 00226 if (ds == NULL) 00227 return false; 00228 00229 mitk::BoundingBox::Pointer bb = ds->ComputeBoundingBox(); 00230 00231 mitk::Point3D middle =bb->GetCenter(); 00232 vtkRenderer->GetActiveCamera()->SetFocalPoint(middle[0],middle[1],middle[2]); 00233 00234 vtkRenderer->ResetCamera(); 00235 mitk::RenderingManager::GetInstance()->RequestUpdateAll(); 00236 return true; 00237 } 00238 return false; 00239 }