1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkInteractorStyleFlight.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkInteractorStyleFlight.h"
16 
17 #include "vtkCamera.h"
18 #include "vtkPerspectiveTransform.h"
19 #include "vtkRenderer.h"
20 #include "vtkMath.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkRenderWindowInteractor.h"
23 #include "vtkCallbackCommand.h"
24 #include "vtkWindows.h"
25 
26 vtkStandardNewMacro(vtkInteractorStyleFlight);
27 
28 class CPIDControl
29 {
30 public:
31   int    m_iDeltaT;
32   int    m_iDeltaTf;
33   double m_dPrevX;
34   double m_dKp;
35   double m_dKd;
36   double m_dKi;
37   double m_dXSum;
38   double m_dDelta;
39 
40   double m_dVelSum;
41   int    m_iVelCount;
42   double m_dVelAvg;
43 public:
44   CPIDControl(double dKp, double dKd, double dKi);
45   double PIDCalc(double dX,double dFinalX);
46   void SetCoefficients(double dKp, double dKd, double dKi);
47 };
48 
CPIDControl(double dKp,double dKd,double dKi)49 CPIDControl::CPIDControl(double dKp, double dKd, double dKi)
50 {
51   m_dXSum     = 0.0;
52   m_dPrevX    = 0.0;
53   m_dDelta    = 0.0;
54   m_iDeltaT   = 0;
55   m_iDeltaTf  = 0;
56   m_dVelSum   = 0.0;
57   m_iVelCount = 0;
58   m_dVelAvg   = 0.0;
59   this->SetCoefficients(dKp, dKd, dKi);
60 }
61 
62 ///////////////////////////////////////////////////////////////////////////////
63 ///////////////////////////////////////////////////////////////////////////////
PIDCalc(double dX,double dFinalX)64 double CPIDControl::PIDCalc(double dX, double dFinalX)
65 {
66   double dVal = dX - dFinalX;
67   m_dXSum     = m_dXSum + dVal;
68   // Calculate the velocity
69   dVal = m_dPrevX - dX;
70   // Average the velocity
71   m_dVelSum += dVal;
72   m_iVelCount++;
73   if(m_iVelCount >= 10)
74   {
75     m_dVelAvg = m_dVelSum/m_iVelCount;
76     m_iVelCount = 0;
77     m_dVelSum = 0.0;
78   }
79   m_dDelta = m_dKp*dX + m_dKd*m_dVelAvg + m_dKi*m_dXSum;
80   m_dPrevX = dX;
81 
82   return m_dDelta;
83 }
84 
85 ///////////////////////////////////////////////////////////////////////////////
86 ///////////////////////////////////////////////////////////////////////////////
SetCoefficients(double dKp,double dKd,double dKi)87 void CPIDControl::SetCoefficients(double dKp, double dKd, double dKi)
88 {
89   m_dKp = dKp;
90   m_dKd = dKd;
91   m_dKi = dKi;
92   // should reset internal params here, but no need for this simple usage
93 }
94 
95 
96 //---------------------------------------------------------------------------
vtkInteractorStyleFlight()97 vtkInteractorStyleFlight::vtkInteractorStyleFlight()
98 {
99   this->KeysDown     = 0;
100   this->UseTimers    = 1;
101 
102   this->DiagonalLength           = 1.0;
103   this->MotionStepSize           = 1.0/250.0;
104   this->MotionUserScale          = 1.0;  // +/- key adjustment
105   this->MotionAccelerationFactor = 10.0;
106   this->AngleStepSize            = 1.0;
107   this->AngleAccelerationFactor  = 5.0;
108 
109   this->DisableMotion      = 0;
110   this->RestoreUpVector    = 1;
111   this->DefaultUpVector[0] = 0;
112   this->DefaultUpVector[1] = 0;
113   this->DefaultUpVector[2] = 1;
114   //
115   PID_Yaw     = new CPIDControl(-0.05, 0.0, -0.0008);
116   PID_Pitch   = new CPIDControl(-0.05, 0.0, -0.0008);
117   Transform = vtkPerspectiveTransform::New();
118 }
119 
120 //---------------------------------------------------------------------------
~vtkInteractorStyleFlight()121 vtkInteractorStyleFlight::~vtkInteractorStyleFlight()
122 {
123     Transform->Delete();
124     delete PID_Yaw;
125     delete PID_Pitch;
126 }
127 //---------------------------------------------------------------------------
ForwardFly()128 void vtkInteractorStyleFlight::ForwardFly()
129 {
130   if (this->CurrentRenderer == nullptr)
131   {
132     return;
133   }
134   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
135   //
136   if (this->KeysDown)
137   {
138     this->FlyByKey(camera);
139   }
140   else
141   {
142     this->UpdateSteering(camera);
143     this->FlyByMouse(camera);
144   }
145   //
146   this->FinishCamera(camera);
147 }
148 //---------------------------------------------------------------------------
ReverseFly()149 void vtkInteractorStyleFlight::ReverseFly()
150 {
151     // The code is the same, just the state variable that is tracked...
152     ForwardFly();
153 }
154 
155 //----------------------------------------------------------------------------
StartForwardFly()156 void vtkInteractorStyleFlight::StartForwardFly()
157 {
158   if (this->State != VTKIS_NONE)
159   {
160     return;
161   }
162   this->StartState(VTKIS_FORWARDFLY);
163 }
164 
165 //----------------------------------------------------------------------------
EndForwardFly()166 void vtkInteractorStyleFlight::EndForwardFly()
167 {
168   if (this->State != VTKIS_FORWARDFLY)
169   {
170     return;
171   }
172   this->StopState();
173 }
174 
175 //----------------------------------------------------------------------------
StartReverseFly()176 void vtkInteractorStyleFlight::StartReverseFly()
177 {
178   if (this->State != VTKIS_NONE)
179   {
180     return;
181   }
182   this->StartState(VTKIS_REVERSEFLY);
183 }
184 
185 //----------------------------------------------------------------------------
EndReverseFly()186 void vtkInteractorStyleFlight::EndReverseFly()
187 {
188   if (this->State != VTKIS_REVERSEFLY)
189   {
190     return;
191   }
192   this->StopState();
193 }
194 
195 //---------------------------------------------------------------------------
196 // All actual motion is performed in the timer
197 //---------------------------------------------------------------------------
OnTimer()198 void vtkInteractorStyleFlight::OnTimer()
199 {
200   switch (this->State)
201   {
202     case VTKIS_FORWARDFLY:
203       this->ForwardFly();
204       break;
205 
206     case VTKIS_REVERSEFLY:
207       this->ReverseFly();
208       break;
209 
210     default:
211       break;
212   }
213 }
214 
215 //---------------------------------------------------------------------------
216 // Mouse event handlers
217 //---------------------------------------------------------------------------
OnMouseMove()218 void vtkInteractorStyleFlight::OnMouseMove()
219 {
220   int x = this->Interactor->GetEventPosition()[0];
221   int y = this->Interactor->GetEventPosition()[1];
222   this->FindPokedRenderer(x, y);
223   vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
224   switch (this->State)
225   {
226     case VTKIS_FORWARDFLY:
227     case VTKIS_REVERSEFLY:
228       this->UpdateMouseSteering(cam);
229       this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
230       break;
231   }
232 }
233 
234 //---------------------------------------------------------------------------
OnLeftButtonDown()235 void vtkInteractorStyleFlight::OnLeftButtonDown()
236 {
237   int x = this->Interactor->GetEventPosition()[0];
238   int y = this->Interactor->GetEventPosition()[1];
239   this->FindPokedRenderer(x, y);
240   if (this->CurrentRenderer == nullptr)
241   {
242     return;
243   }
244 
245   //
246   this->GrabFocus(this->EventCallbackCommand);
247   vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
248   switch (this->State)
249   {
250     case VTKIS_REVERSEFLY:
251       this->State = VTKIS_FORWARDFLY;
252       break;
253     default :
254       this->SetupMotionVars(cam);
255       this->StartForwardFly();
256       break;
257   }
258 }
259 
260 //---------------------------------------------------------------------------
OnLeftButtonUp()261 void vtkInteractorStyleFlight::OnLeftButtonUp()
262 {
263   switch (this->State)
264   {
265     case VTKIS_FORWARDFLY:
266       this->EndForwardFly();
267       break;
268     default :
269       break;
270   }
271   if ( this->Interactor )
272   {
273     this->ReleaseFocus();
274   }
275 }
276 
277 //---------------------------------------------------------------------------
OnMiddleButtonDown()278 void vtkInteractorStyleFlight::OnMiddleButtonDown()
279 {
280 }
281 
282 //---------------------------------------------------------------------------
OnMiddleButtonUp()283 void vtkInteractorStyleFlight::OnMiddleButtonUp()
284 {
285 }
286 
287 //---------------------------------------------------------------------------
OnRightButtonDown()288 void vtkInteractorStyleFlight::OnRightButtonDown()
289 {
290   int x = this->Interactor->GetEventPosition()[0];
291   int y = this->Interactor->GetEventPosition()[1];
292   this->FindPokedRenderer(x, y);
293   if (this->CurrentRenderer == nullptr)
294   {
295     return;
296   }
297 
298   //
299   this->GrabFocus(this->EventCallbackCommand);
300   vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
301   switch (this->State)
302   {
303     case VTKIS_FORWARDFLY:
304       this->State = VTKIS_REVERSEFLY;
305       break;
306     default :
307       this->SetupMotionVars(cam);
308       this->StartReverseFly();
309       break;
310   }
311 }
312 
313 //---------------------------------------------------------------------------
OnRightButtonUp()314 void vtkInteractorStyleFlight::OnRightButtonUp()
315 {
316   switch (this->State)
317   {
318     case VTKIS_REVERSEFLY:
319       this->EndReverseFly();
320       break;
321     default :
322       break;
323   }
324   if ( this->Interactor )
325   {
326     this->ReleaseFocus();
327   }
328 }
329 
330 //---------------------------------------------------------------------------
331 // Keyboard event handlers
332 // Note, OnChar is a key press down and then up event
333 // Note, OnKeyDown/OnKeyUp are more sensitive for controlling motion
334 //---------------------------------------------------------------------------
OnKeyDown()335 void vtkInteractorStyleFlight::OnKeyDown()
336 {
337   // New Flight mode behaviour
338   // Note that we'll need #defines for ARROW key defs under non win32 OS
339 #ifdef _WIN32
340   switch (this->Interactor->GetKeyCode())
341   {
342     case VK_LEFT        : this->KeysDown |=1;  break;
343     case VK_RIGHT       : this->KeysDown |=2;  break;
344     case VK_UP          : this->KeysDown |=4;  break;
345     case VK_DOWN        : this->KeysDown |=8;  break;
346     case 'a':
347     case 'A'            : this->KeysDown |=16; break;
348     case 'z':
349     case 'Z'            : this->KeysDown |=32; break;
350   }
351   if ((this->KeysDown & (32+16)) == (32+16))
352   {
353     if (this->State==VTKIS_FORWARDFLY)
354     {
355       this->EndForwardFly();
356     }
357     if (this->State==VTKIS_REVERSEFLY)
358     {
359       this->EndReverseFly();
360     }
361   }
362   else if ((this->KeysDown & 32) == 32)
363   {
364     if (this->State==VTKIS_FORWARDFLY)
365     {
366       this->EndForwardFly();
367     }
368     this->StartReverseFly();
369   }
370   else if ((this->KeysDown & 16) == 16)
371   {
372     if (this->State==VTKIS_REVERSEFLY)
373     {
374       this->EndReverseFly();
375     }
376     this->StartForwardFly();
377   }
378 #else
379   // the following if statement is a dummy one to prevent keycode not used
380   // warnings under unix, (until the correct keycodes are supplied)
381   if (this->Interactor->GetKeyCode() == 0x7F)
382   {
383     vtkWarningMacro(<<"Dummy test to prevent compiler warning");
384   }
385 #endif
386 }
387 
388 //---------------------------------------------------------------------------
OnKeyUp()389 void vtkInteractorStyleFlight::OnKeyUp()
390 {
391 #ifdef _WIN32
392   switch (this->Interactor->GetKeyCode())
393   {
394     case VK_LEFT        : this->KeysDown &= ~1;  break;
395     case VK_RIGHT       : this->KeysDown &= ~2;  break;
396     case VK_UP          : this->KeysDown &= ~4;  break;
397     case VK_DOWN        : this->KeysDown &= ~8;  break;
398     case 'a':
399     case 'A'            : this->KeysDown &= ~16; break;
400     case 'z':
401     case 'Z'            : this->KeysDown &= ~32; break;
402   }
403   switch (this->State)
404   {
405     case VTKIS_FORWARDFLY:
406       if ((this->KeysDown & 16) == 0)
407       {
408         this->EndForwardFly();
409       }
410       break;
411     case VTKIS_REVERSEFLY:
412       if ((this->KeysDown & 32) == 0)
413       {
414         this->EndReverseFly();
415       }
416       break;
417   }
418 #else
419   // the following if statement is a dummy one to prevent keycode not used
420   // warnings under unix, (until the correct keycodes are supplied)
421   if (this->Interactor->GetKeyCode() == 0x7F)
422   {
423     vtkWarningMacro(<<"Dummy test to prevent compiler warning");
424   }
425 #endif
426 }
427 
428 //---------------------------------------------------------------------------
OnChar()429 void vtkInteractorStyleFlight::OnChar()
430 {
431   switch (this->Interactor->GetKeyCode())
432   {
433     case '+' :
434       this->MotionUserScale *= 2.0;
435       break;
436     case '-' :
437       this->MotionUserScale *= 0.5;
438       break;
439     default:
440       this->Superclass::OnChar();
441       break;
442   }
443 }
444 
445 //---------------------------------------------------------------------------
JumpTo(double campos[3],double focpos[3])446 void vtkInteractorStyleFlight::JumpTo(double campos[3], double focpos[3])
447 {
448   if (this->CurrentRenderer == nullptr)
449   {
450     return;
451   }
452   vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
453   cam->SetPosition(campos);
454   cam->SetFocalPoint(focpos);
455   FinishCamera(cam);
456   this->Interactor->Render();
457 }
458 
FinishCamera(vtkCamera * cam)459 void vtkInteractorStyleFlight::FinishCamera(vtkCamera* cam)
460 {
461     cam->OrthogonalizeViewUp();
462     if (this->RestoreUpVector)
463     {
464       double delta[3];
465       cam->GetViewUp(delta);
466       double weight = vtkMath::Dot(this->DefaultUpVector,delta);
467       // only correct up if we're close to it already...
468       if (weight>0.3) {
469         weight = 0.25*fabs(weight);
470         delta[0] = delta[0] + (this->DefaultUpVector[0]-delta[0])*weight;
471         delta[1] = delta[1] + (this->DefaultUpVector[1]-delta[1])*weight;
472         delta[2] = delta[2] + (this->DefaultUpVector[2]-delta[2])*weight;
473         cam->SetViewUp(delta);
474       }
475     }
476     if (this->AutoAdjustCameraClippingRange)
477     {
478       this->CurrentRenderer->ResetCameraClippingRange();
479     }
480     if (this->Interactor->GetLightFollowCamera())
481     {
482       this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
483     }
484 }
485 
486 //---------------------------------------------------------------------------
487 // Use this mouse pos and last mouse pos to get the amount of motion
488 // Compute an "Ideal" focal point, The flight will sterr towards this ideal
489 // point, but will be damped in Yaw/Pitch by our PID Controllers.
490 // The damping and motion is done in the timer event.
491 //---------------------------------------------------------------------------
UpdateMouseSteering(vtkCamera * cam)492 void vtkInteractorStyleFlight::UpdateMouseSteering(vtkCamera *cam)
493 {
494   int *thispos = this->Interactor->GetEventPosition();
495   int *lastpos = this->Interactor->GetLastEventPosition();
496 
497   double aspeed = this->AngleStepSize*(this->Interactor->GetShiftKey() ?
498       this->AngleAccelerationFactor : 1.0);
499   //
500   // we want to steer by an amount proportional to window viewangle and size
501   // compute dx and dy increments relative to last mouse click
502   int *size = this->Interactor->GetSize();
503   double scalefactor = 5*cam->GetViewAngle()/size[0];
504   double dx = - (thispos[0] - lastpos[0])*scalefactor*aspeed;
505   double dy =   (thispos[1] - lastpos[1])*scalefactor*aspeed;
506 
507   // Temporary until I get smooth flight working
508   this->DeltaPitch = dy;
509   this->DeltaYaw = dx;
510 /*
511   Not happy with smooth flight yet, please leave this code here
512   until I get around to experimenting : JB July 2002
513 
514   // dx and dy need to be converted to a new 'ideal' camera focal point
515   // we maintain an actual FocalPoint and an IdealFocalPoint so that we can
516   // smooth the motion using our PID controllers (one for yaw, one for pitch).
517   cam->OrthogonalizeViewUp();
518   double LRaxis[3];
519   double *ViewUp     = cam->GetViewUp();
520   double *Position   = cam->GetPosition();
521   double *FocalPoint = cam->GetFocalPoint();
522   this->GetLRVector(LRaxis, cam);
523   //
524   this->Transform->Identity();
525   this->Transform->Translate(+Position[0],+Position[1],+Position[2]);
526   this->Transform->RotateWXYZ(dx, ViewUp);
527   this->Transform->RotateWXYZ(dy, LRaxis);
528   this->Transform->Translate(-Position[0],-Position[1],-Position[2]);
529   this->Transform->TransformPoint(this->IdealFocalPoint,this->IdealFocalPoint);
530 */
531 }
532 
533 // We know the ideal and actual focal points. We now want to reduce these
534 // to a 2D Yaw+Pitch form so that we can smooth the motion on each
UpdateSteering(vtkCamera * vtkNotUsed (cam))535 void vtkInteractorStyleFlight::UpdateSteering(vtkCamera *vtkNotUsed(cam))
536 {
537 /*
538   #define D2R 0.01745329251994329576923690768    // degrees to radians
539   #define R2D 57.2957795130823208767981548141    // radians to degrees
540 
541   Not happy with smooth flight yet, please leave this code here
542   until I get around to experimenting : JB July 2002
543 
544   cam->OrthogonalizeViewUp();
545   double *Position = cam->GetPosition();
546   double *FocalPoint = cam->GetFocalPoint();
547   double vec1[3], vec2[3], norm1[3], norm2[3];
548   vec1[0] = FocalPoint[0]-Position[0];
549   vec1[1] = FocalPoint[1]-Position[1];
550   vec1[2] = FocalPoint[2]-Position[2];
551   vec2[0] = this->IdealFocalPoint[0]-Position[0];
552   vec2[1] = this->IdealFocalPoint[1]-Position[1];
553   vec2[2] = this->IdealFocalPoint[2]-Position[2];
554   // what's the azimuthal angle between the Ideal and actual focal points
555   // angle between planes given by Up/Focus and Up/IdealFocus
556   double *ViewUp = cam->GetViewUp();
557   vtkMath::Cross(vec1, ViewUp, norm1);
558   vtkMath::Cross(vec2, ViewUp, norm2);
559   vtkMath::Normalize(norm1);
560   vtkMath::Normalize(norm2);
561   //
562   double dot = vtkMath::Dot(norm1, norm2);
563   if (dot>1.0) {
564     dot = 1.0;
565   }
566   else if (dot<-1.0) {
567     dot =-1.0;
568   }
569   double yaw = R2D*acos(dot);
570   // we know the angle, but is it +ve or -ve (which side is new focal point)
571   double d1,d2;
572   d1 = vtkMath::Dot(norm1,this->IdealFocalPoint);
573   d2 = vtkMath::Dot(norm1,FocalPoint);
574   if (d1-d2>0) yaw = -yaw;
575   //
576   // what's the elevation angle between the Ideal and actual focal points
577   // angle between planes given by LR/Focus and LR/IdealFocus
578   double LRaxis[3];
579   this->GetLRVector(LRaxis, cam);
580   vtkMath::Cross(vec1, LRaxis, norm1);
581   vtkMath::Cross(vec2, LRaxis, norm2);
582   vtkMath::Normalize(norm1);
583   vtkMath::Normalize(norm2);
584   //
585   dot = vtkMath::Dot(norm1, norm2);
586   if (dot>1.0) {
587     dot = 1.0;
588   } else if (dot<-1.0) {
589     dot =-1.0;
590   }
591   double pitch = R2D*acos(dot);
592   d1 = vtkMath::Dot(norm1,this->IdealFocalPoint);
593   d2 = vtkMath::Dot(norm1,FocalPoint);
594   if (d1-d2>0) pitch = -pitch;
595 
596   // use our motion dampers to reduce the yaw/pitch errors to zero gradually
597 //  this->DeltaYaw   = PID_Yaw->PIDCalc(yaw, 0);
598 //  this->DeltaPitch = PID_Pitch->PIDCalc(pitch, 0);
599 
600   this->DeltaPitch = 0.75*pitch + 0.25*lPitch;
601   lPitch = pitch;
602 
603   this->DeltaYaw = 0.75*yaw + 0.25*lYaw;
604   lYaw = yaw;
605 
606 */
607 }
608 
609 //---------------------------------------------------------------------------
610 // useful utility functions
611 //---------------------------------------------------------------------------
SetupMotionVars(vtkCamera * cam)612 void vtkInteractorStyleFlight::SetupMotionVars(vtkCamera *cam)
613 {
614   lPitch = 0;
615   lYaw   = 0;
616   cam->GetFocalPoint(IdealFocalPoint);
617 
618   double bounds[6];
619   this->CurrentRenderer->ComputeVisiblePropBounds( bounds );
620   if ( !vtkMath::AreBoundsInitialized(bounds) )
621   {
622     this->DiagonalLength = 1.0;
623   }
624   else
625   {
626     this->DiagonalLength =
627       sqrt( (bounds[0] - bounds[1]) * (bounds[0] - bounds[1]) +
628             (bounds[2] - bounds[3]) * (bounds[2] - bounds[3]) +
629             (bounds[4] - bounds[5]) * (bounds[4] - bounds[5]) );
630   }
631 }
632 
633 //---------------------------------------------------------------------------
MotionAlongVector(double vector[3],double amount,vtkCamera * cam)634 void vtkInteractorStyleFlight::MotionAlongVector(double vector[3],
635     double amount, vtkCamera* cam)
636 {
637   double oldcampos[3], oldcamfoc[3];
638   cam->GetPosition(oldcampos);
639   cam->GetFocalPoint(oldcamfoc);
640   // move camera and focus along DirectionOfProjection
641   cam->SetPosition(
642     oldcampos[0] - amount * vector[0],
643     oldcampos[1] - amount * vector[1],
644     oldcampos[2] - amount * vector[2]);
645   cam->SetFocalPoint(
646     oldcamfoc[0] - amount * vector[0],
647     oldcamfoc[1] - amount * vector[1],
648     oldcamfoc[2] - amount * vector[2]);
649 }
650 
651 //---------------------------------------------------------------------------
GetLRVector(double vector[3],vtkCamera * cam)652 void vtkInteractorStyleFlight::GetLRVector(double vector[3], vtkCamera* cam)
653 {
654   vtkMatrix4x4 *vtm;
655   vtm = cam->GetViewTransformMatrix();
656   vector[0] = vtm->GetElement(0,0);
657   vector[1] = vtm->GetElement(0,1);
658   vector[2] = vtm->GetElement(0,2);
659 }
660 
661 //---------------------------------------------------------------------------
662 // Perform the motion
663 //---------------------------------------------------------------------------
FlyByMouse(vtkCamera * cam)664 void vtkInteractorStyleFlight::FlyByMouse(vtkCamera* cam)
665 {
666   double a_vector[3];
667   double speed  = this->DiagonalLength * this->MotionStepSize * this->MotionUserScale;
668   speed = speed * ( this->Interactor->GetShiftKey() ? this->MotionAccelerationFactor : 1.0);
669   if (this->DisableMotion)
670   {
671     speed = 0;
672   }
673   // Sidestep (convert steering angles to left right movement :
674   // only because I added this after doing the angles earlier
675   if (this->Interactor->GetControlKey())
676   {
677     if (this->DeltaYaw!=0.0)
678     {
679       this->GetLRVector(a_vector, cam);
680       this->MotionAlongVector(a_vector,-this->DeltaYaw*speed/2.0, cam);
681     }
682     if (this->DeltaPitch!=0.0)
683     {
684       cam->GetViewUp(a_vector);
685       this->MotionAlongVector(a_vector,-this->DeltaPitch*speed/2.0, cam);
686     }
687   }
688   else
689   {
690     cam->Yaw(this->DeltaYaw);
691     cam->Pitch(this->DeltaPitch);
692     this->DeltaYaw = 0;
693     this->DeltaPitch = 0;
694     // cam->SetFocalPoint(this->IdealFocalPoint);
695   }
696   //
697   if (!this->Interactor->GetControlKey())
698   {
699     cam->GetDirectionOfProjection(a_vector); // reversed (use -speed)
700     switch (this->State)
701     {
702       case VTKIS_FORWARDFLY:
703         this->MotionAlongVector(a_vector, -speed, cam);
704         break;
705       case VTKIS_REVERSEFLY:
706         this->MotionAlongVector(a_vector, speed, cam);
707         break;
708     }
709   }
710 }
711 
712 //---------------------------------------------------------------------------
FlyByKey(vtkCamera * cam)713 void vtkInteractorStyleFlight::FlyByKey(vtkCamera* cam)
714 {
715   double speed  = this->DiagonalLength * this->MotionStepSize * this->MotionUserScale;
716   speed = speed * ( this->Interactor->GetShiftKey() ? this->MotionAccelerationFactor : 1.0);
717   if (this->DisableMotion)
718   {
719     speed = 0;
720   }
721   //
722   double aspeed = this->AngleStepSize* (this->Interactor->GetShiftKey() ? this->AngleAccelerationFactor : 1.0);
723   double a_vector[3];
724   // Left and right
725   if (this->Interactor->GetControlKey())
726   { // Sidestep
727     this->GetLRVector(a_vector, cam);
728     if (this->KeysDown & 1)
729     {
730       this->MotionAlongVector(a_vector,-speed, cam);
731     }
732     if (this->KeysDown & 2)
733     {
734       this->MotionAlongVector(a_vector, speed, cam);
735     }
736   }
737   else
738   {
739     if (this->KeysDown & 1)
740     {
741       cam->Yaw( aspeed);
742     }
743     if (this->KeysDown & 2)
744     {
745       cam->Yaw(-aspeed);
746     }
747   }
748 
749   // Up and Down
750   if (this->Interactor->GetControlKey())
751   { // Sidestep
752     cam->GetViewUp(a_vector);
753     if (this->KeysDown & 4)
754     {
755       this->MotionAlongVector(a_vector,-speed, cam);
756     }
757     if (this->KeysDown & 8)
758     {
759       this->MotionAlongVector(a_vector, speed, cam);
760     }
761   }
762   else
763   {
764     if (this->KeysDown & 4)
765     {
766       cam->Pitch(-aspeed);
767     }
768     if (this->KeysDown & 8)
769     {
770       cam->Pitch( aspeed);
771     }
772   }
773 
774   // forward and backward
775   cam->GetDirectionOfProjection(a_vector);
776   if (this->KeysDown & 16)
777   {
778     this->MotionAlongVector(a_vector, speed, cam);
779   }
780   if (this->KeysDown & 32)
781   {
782     this->MotionAlongVector(a_vector,-speed, cam);
783   }
784 }
785 
786 //---------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)787 void vtkInteractorStyleFlight::PrintSelf(ostream& os, vtkIndent indent)
788 {
789   this->Superclass::PrintSelf(os,indent);
790   os << indent << "MotionStepSize: "
791      << this->MotionStepSize << "\n";
792   os << indent << "MotionAccelerationFactor: "
793      << this->MotionAccelerationFactor << "\n";
794   os << indent << "AngleStepSize: "
795      << this->AngleStepSize << "\n";
796   os << indent << "AngleAccelerationFactor: "
797      << this->AngleAccelerationFactor << "\n";
798   os << indent << "MotionUserScale: "
799      << this->MotionUserScale << "\n";
800   os << indent << "DisableMotion: "
801      << this->DisableMotion << "\n";
802   os << indent << "RestoreUpVector: "
803      << this->RestoreUpVector << "\n";
804   os << indent << "DefaultUpVector: "
805      << this->DefaultUpVector[0] << " "
806      << this->DefaultUpVector[1] << " "
807      << this->DefaultUpVector[2] << "\n";
808 }
809 
810 
811