/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkInteractorStyleTrackballCamera.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkInteractorStyleTrackballCamera.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" vtkCxxRevisionMacro(vtkInteractorStyleTrackballCamera, "$Revision: 1.32 $"); vtkStandardNewMacro(vtkInteractorStyleTrackballCamera); //---------------------------------------------------------------------------- vtkInteractorStyleTrackballCamera::vtkInteractorStyleTrackballCamera() { this->MotionFactor = 10.0; } //---------------------------------------------------------------------------- vtkInteractorStyleTrackballCamera::~vtkInteractorStyleTrackballCamera() { } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnMouseMove() { int x = this->Interactor->GetEventPosition()[0]; int y = this->Interactor->GetEventPosition()[1]; switch (this->State) { case VTKIS_ROTATE: this->FindPokedRenderer(x, y); this->Rotate(); this->InvokeEvent(vtkCommand::InteractionEvent, NULL); break; case VTKIS_PAN: this->FindPokedRenderer(x, y); this->Pan(); this->InvokeEvent(vtkCommand::InteractionEvent, NULL); break; case VTKIS_DOLLY: this->FindPokedRenderer(x, y); this->Dolly(); this->InvokeEvent(vtkCommand::InteractionEvent, NULL); break; case VTKIS_SPIN: this->FindPokedRenderer(x, y); this->Spin(); this->InvokeEvent(vtkCommand::InteractionEvent, NULL); break; } } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnLeftButtonDown() { this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == NULL) { return; } if (this->Interactor->GetShiftKey()) { if (this->Interactor->GetControlKey()) { this->StartDolly(); } else { this->StartPan(); } } else { if (this->Interactor->GetControlKey()) { this->StartSpin(); } else { this->StartRotate(); } } } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnLeftButtonUp() { switch (this->State) { case VTKIS_DOLLY: this->EndDolly(); break; case VTKIS_PAN: this->EndPan(); break; case VTKIS_SPIN: this->EndSpin(); break; case VTKIS_ROTATE: this->EndRotate(); break; } } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnMiddleButtonDown() { this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == NULL) { return; } this->StartPan(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnMiddleButtonUp() { switch (this->State) { case VTKIS_PAN: this->EndPan(); break; } } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnRightButtonDown() { this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == NULL) { return; } this->StartDolly(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnRightButtonUp() { switch (this->State) { case VTKIS_DOLLY: this->EndDolly(); break; } } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnMouseWheelForward() { this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == NULL) { return; } this->StartDolly(); double factor = this->MotionFactor * 0.2 * this->MouseWheelMotionFactor; this->Dolly(pow((double)1.1, factor)); this->EndDolly(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::OnMouseWheelBackward() { this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == NULL) { return; } this->StartDolly(); double factor = this->MotionFactor * -0.2 * this->MouseWheelMotionFactor; this->Dolly(pow((double)1.1, factor)); this->EndDolly(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::Rotate() { if (this->CurrentRenderer == NULL) { return; } vtkRenderWindowInteractor *rwi = this->Interactor; int dx = rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0]; int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; int *size = this->CurrentRenderer->GetRenderWindow()->GetSize(); double delta_elevation = -20.0 / size[1]; double delta_azimuth = -20.0 / size[0]; double rxf = (double)dx * delta_azimuth * this->MotionFactor; double ryf = (double)dy * delta_elevation * this->MotionFactor; vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); camera->Azimuth(rxf); camera->Elevation(ryf); camera->OrthogonalizeViewUp(); if (this->AutoAdjustCameraClippingRange) { this->CurrentRenderer->ResetCameraClippingRange(); } if (rwi->GetLightFollowCamera()) { this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); } rwi->Render(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::Spin() { if (this->CurrentRenderer == NULL) { return; } vtkRenderWindowInteractor *rwi = this->Interactor; double *center = this->CurrentRenderer->GetCenter(); double newAngle = atan2((double)rwi->GetEventPosition()[1] - (double)center[1], (double)rwi->GetEventPosition()[0] - (double)center[0]); double oldAngle = atan2((double)rwi->GetLastEventPosition()[1] - (double)center[1], (double)rwi->GetLastEventPosition()[0] - (double)center[0]); newAngle *= vtkMath::RadiansToDegrees(); oldAngle *= vtkMath::RadiansToDegrees(); vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); camera->Roll(newAngle - oldAngle); camera->OrthogonalizeViewUp(); rwi->Render(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::Pan() { if (this->CurrentRenderer == NULL) { return; } vtkRenderWindowInteractor *rwi = this->Interactor; double viewFocus[4], focalDepth, viewPoint[3]; double newPickPoint[4], oldPickPoint[4], motionVector[3]; // Calculate the focal depth since we'll be using it a lot vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); camera->GetFocalPoint(viewFocus); this->ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2], viewFocus); focalDepth = viewFocus[2]; this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0], (double)rwi->GetEventPosition()[1], focalDepth, newPickPoint); // Has to recalc old mouse point since the viewport has moved, // so can't move it outside the loop this->ComputeDisplayToWorld((double)rwi->GetLastEventPosition()[0], (double)rwi->GetLastEventPosition()[1], focalDepth, oldPickPoint); // Camera motion is reversed motionVector[0] = oldPickPoint[0] - newPickPoint[0]; motionVector[1] = oldPickPoint[1] - newPickPoint[1]; motionVector[2] = oldPickPoint[2] - newPickPoint[2]; camera->GetFocalPoint(viewFocus); camera->GetPosition(viewPoint); camera->SetFocalPoint(motionVector[0] + viewFocus[0], motionVector[1] + viewFocus[1], motionVector[2] + viewFocus[2]); camera->SetPosition(motionVector[0] + viewPoint[0], motionVector[1] + viewPoint[1], motionVector[2] + viewPoint[2]); if (rwi->GetLightFollowCamera()) { this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); } rwi->Render(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::Dolly() { if (this->CurrentRenderer == NULL) { return; } vtkRenderWindowInteractor *rwi = this->Interactor; double *center = this->CurrentRenderer->GetCenter(); int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; double dyf = this->MotionFactor * (double)(dy) / (double)(center[1]); this->Dolly(pow((double)1.1, dyf)); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::Dolly(double factor) { if (this->CurrentRenderer == NULL) { return; } vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); if (camera->GetParallelProjection()) { camera->SetParallelScale(camera->GetParallelScale() / factor); } else { camera->Dolly(factor); if (this->AutoAdjustCameraClippingRange) { this->CurrentRenderer->ResetCameraClippingRange(); } } if (this->Interactor->GetLightFollowCamera()) { this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); } this->Interactor->Render(); } //---------------------------------------------------------------------------- void vtkInteractorStyleTrackballCamera::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); }