vtkInteractorStyleFlight.cxx 22.5 KB
Newer Older
1 2 3 4 5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkInteractorStyleFlight.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     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 19
#include "vtkPerspectiveTransform.h"
#include "vtkRenderer.h"
20
#include "vtkMath.h"
21
#include "vtkObjectFactory.h"
22
#include "vtkRenderWindowInteractor.h"
23
#include "vtkCallbackCommand.h"
24
#include "vtkWindows.h"
25

Brad King's avatar
Brad King committed
26 27
vtkStandardNewMacro(vtkInteractorStyleFlight);

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
class CPIDControl
{
public:
  int    m_iDeltaT;
  int    m_iDeltaTf;
  double m_dPrevX;
  double m_dKp;
  double m_dKd;
  double m_dKi;
  double m_dXSum;
  double m_dDelta;

  double m_dVelSum;
  int    m_iVelCount;
  double m_dVelAvg;
public:
  CPIDControl(double dKp, double dKd, double dKi);
  double PIDCalc(double dX,double dFinalX);
  void SetCoefficients(double dKp, double dKd, double dKi);
};

CPIDControl::CPIDControl(double dKp, double dKd, double dKi)
{
  m_dXSum     = 0.0;
  m_dPrevX    = 0.0;
  m_dDelta    = 0.0;
  m_iDeltaT   = 0;
  m_iDeltaTf  = 0;
  m_dVelSum   = 0.0;
  m_iVelCount = 0;
  m_dVelAvg   = 0.0;
  this->SetCoefficients(dKp, dKd, dKi);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
double CPIDControl::PIDCalc(double dX, double dFinalX)
{
  double dVal = dX - dFinalX;
  m_dXSum     = m_dXSum + dVal;
  // Calculate the velocity
  dVal = m_dPrevX - dX;
  // Average the velocity
  m_dVelSum += dVal;
  m_iVelCount++;
  if(m_iVelCount >= 10)
  {
75
    m_dVelAvg = m_dVelSum/m_iVelCount;
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    m_iVelCount = 0;
    m_dVelSum = 0.0;
  }
  m_dDelta = m_dKp*dX + m_dKd*m_dVelAvg + m_dKi*m_dXSum;
  m_dPrevX = dX;

  return m_dDelta;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void CPIDControl::SetCoefficients(double dKp, double dKd, double dKi)
{
  m_dKp = dKp;
  m_dKd = dKd;
  m_dKi = dKi;
  // should reset internal params here, but no need for this simple usage
}


96 97 98 99
//---------------------------------------------------------------------------
vtkInteractorStyleFlight::vtkInteractorStyleFlight()
{
  this->KeysDown     = 0;
100
  this->UseTimers    = 1;
101

102 103 104 105 106 107
  this->DiagonalLength           = 1.0;
  this->MotionStepSize           = 1.0/250.0;
  this->MotionUserScale          = 1.0;  // +/- key adjustment
  this->MotionAccelerationFactor = 10.0;
  this->AngleStepSize            = 1.0;
  this->AngleAccelerationFactor  = 5.0;
108

109 110 111 112 113 114 115 116 117
  this->DisableMotion      = 0;
  this->RestoreUpVector    = 1;
  this->DefaultUpVector[0] = 0;
  this->DefaultUpVector[1] = 0;
  this->DefaultUpVector[2] = 1;
  //
  PID_Yaw     = new CPIDControl(-0.05, 0.0, -0.0008);
  PID_Pitch   = new CPIDControl(-0.05, 0.0, -0.0008);
  Transform = vtkPerspectiveTransform::New();
118
}
Sebastien Barre's avatar
Sebastien Barre committed
119

120
//---------------------------------------------------------------------------
121 122 123 124 125 126 127 128
vtkInteractorStyleFlight::~vtkInteractorStyleFlight()
{
    Transform->Delete();
    delete PID_Yaw;
    delete PID_Pitch;
}
//---------------------------------------------------------------------------
void vtkInteractorStyleFlight::ForwardFly()
129
{
130
  if (this->CurrentRenderer == nullptr)
131
  {
132
    return;
133
  }
134 135 136
  vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
  //
  if (this->KeysDown)
137
  {
138
    this->FlyByKey(camera);
139
  }
140
  else
141
  {
142 143
    this->UpdateSteering(camera);
    this->FlyByMouse(camera);
144
  }
145 146 147 148 149 150 151 152 153
  //
  this->FinishCamera(camera);
}
//---------------------------------------------------------------------------
void vtkInteractorStyleFlight::ReverseFly()
{
    // The code is the same, just the state variable that is tracked...
    ForwardFly();
}
154

155 156 157 158
//----------------------------------------------------------------------------
void vtkInteractorStyleFlight::StartForwardFly()
{
  if (this->State != VTKIS_NONE)
159
  {
160
    return;
161
  }
162
  this->StartState(VTKIS_FORWARDFLY);
163
}
Sebastien Barre's avatar
Sebastien Barre committed
164

165 166
//----------------------------------------------------------------------------
void vtkInteractorStyleFlight::EndForwardFly()
167
{
168
  if (this->State != VTKIS_FORWARDFLY)
169
  {
170
    return;
171
  }
172
  this->StopState();
173
}
Sebastien Barre's avatar
Sebastien Barre committed
174

175 176
//----------------------------------------------------------------------------
void vtkInteractorStyleFlight::StartReverseFly()
177
{
178
  if (this->State != VTKIS_NONE)
179
  {
180
    return;
181
  }
182 183 184 185 186 187 188
  this->StartState(VTKIS_REVERSEFLY);
}

//----------------------------------------------------------------------------
void vtkInteractorStyleFlight::EndReverseFly()
{
  if (this->State != VTKIS_REVERSEFLY)
189
  {
190
    return;
191
  }
192
  this->StopState();
193
}
Sebastien Barre's avatar
Sebastien Barre committed
194

195
//---------------------------------------------------------------------------
196
// All actual motion is performed in the timer
197
//---------------------------------------------------------------------------
198
void vtkInteractorStyleFlight::OnTimer()
199
{
200
  switch (this->State)
201
  {
202 203 204 205 206 207 208
    case VTKIS_FORWARDFLY:
      this->ForwardFly();
      break;

    case VTKIS_REVERSEFLY:
      this->ReverseFly();
      break;
209

210 211
    default:
      break;
212
  }
213
}
Sebastien Barre's avatar
Sebastien Barre committed
214

215
//---------------------------------------------------------------------------
216 217
// Mouse event handlers
//---------------------------------------------------------------------------
218
void vtkInteractorStyleFlight::OnMouseMove()
219
{
220 221 222 223 224
  int x = this->Interactor->GetEventPosition()[0];
  int y = this->Interactor->GetEventPosition()[1];
  this->FindPokedRenderer(x, y);
  vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
  switch (this->State)
225
  {
226 227 228
    case VTKIS_FORWARDFLY:
    case VTKIS_REVERSEFLY:
      this->UpdateMouseSteering(cam);
229
      this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
230
      break;
231
  }
232
}
Sebastien Barre's avatar
Sebastien Barre committed
233

234
//---------------------------------------------------------------------------
235
void vtkInteractorStyleFlight::OnLeftButtonDown()
236
{
237 238 239
  int x = this->Interactor->GetEventPosition()[0];
  int y = this->Interactor->GetEventPosition()[1];
  this->FindPokedRenderer(x, y);
240
  if (this->CurrentRenderer == nullptr)
241
  {
242
    return;
243
  }
244

245
  //
246
  this->GrabFocus(this->EventCallbackCommand);
247 248
  vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
  switch (this->State)
249
  {
250 251 252 253 254 255 256
    case VTKIS_REVERSEFLY:
      this->State = VTKIS_FORWARDFLY;
      break;
    default :
      this->SetupMotionVars(cam);
      this->StartForwardFly();
      break;
257
  }
258
}
Sebastien Barre's avatar
Sebastien Barre committed
259

260
//---------------------------------------------------------------------------
261
void vtkInteractorStyleFlight::OnLeftButtonUp()
262
{
263
  switch (this->State)
264
  {
265 266 267 268 269
    case VTKIS_FORWARDFLY:
      this->EndForwardFly();
      break;
    default :
      break;
270
  }
271
  if ( this->Interactor )
272
  {
273
    this->ReleaseFocus();
274
  }
275
}
Sebastien Barre's avatar
Sebastien Barre committed
276

277
//---------------------------------------------------------------------------
278
void vtkInteractorStyleFlight::OnMiddleButtonDown()
279
{
280
}
Sebastien Barre's avatar
Sebastien Barre committed
281

282
//---------------------------------------------------------------------------
283
void vtkInteractorStyleFlight::OnMiddleButtonUp()
284
{
285
}
Sebastien Barre's avatar
Sebastien Barre committed
286

287
//---------------------------------------------------------------------------
288
void vtkInteractorStyleFlight::OnRightButtonDown()
289
{
290 291 292
  int x = this->Interactor->GetEventPosition()[0];
  int y = this->Interactor->GetEventPosition()[1];
  this->FindPokedRenderer(x, y);
293
  if (this->CurrentRenderer == nullptr)
294
  {
295
    return;
296
  }
297

298
  //
299
  this->GrabFocus(this->EventCallbackCommand);
300 301
  vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
  switch (this->State)
302
  {
303 304 305 306 307 308 309
    case VTKIS_FORWARDFLY:
      this->State = VTKIS_REVERSEFLY;
      break;
    default :
      this->SetupMotionVars(cam);
      this->StartReverseFly();
      break;
310
  }
311
}
Sebastien Barre's avatar
Sebastien Barre committed
312

313
//---------------------------------------------------------------------------
314
void vtkInteractorStyleFlight::OnRightButtonUp()
315
{
316
  switch (this->State)
317
  {
318 319 320 321 322
    case VTKIS_REVERSEFLY:
      this->EndReverseFly();
      break;
    default :
      break;
323
  }
324
  if ( this->Interactor )
325
  {
326
    this->ReleaseFocus();
327
  }
328
}
Sebastien Barre's avatar
Sebastien Barre committed
329

330 331 332 333 334
//---------------------------------------------------------------------------
// Keyboard event handlers
// Note, OnChar is a key press down and then up event
// Note, OnKeyDown/OnKeyUp are more sensitive for controlling motion
//---------------------------------------------------------------------------
335
void vtkInteractorStyleFlight::OnKeyDown()
336
{
337
  // New Flight mode behaviour
338 339
  // Note that we'll need #defines for ARROW key defs under non win32 OS
#ifdef _WIN32
340
  switch (this->Interactor->GetKeyCode())
341
  {
342 343 344 345
    case VK_LEFT        : this->KeysDown |=1;  break;
    case VK_RIGHT       : this->KeysDown |=2;  break;
    case VK_UP          : this->KeysDown |=4;  break;
    case VK_DOWN        : this->KeysDown |=8;  break;
Ken Martin's avatar
Ken Martin committed
346
    case 'a':
347
    case 'A'            : this->KeysDown |=16; break;
Ken Martin's avatar
Ken Martin committed
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 360
      this->EndReverseFly();
    }
361
  }
362
  else if ((this->KeysDown & 32) == 32)
363
  {
364
    if (this->State==VTKIS_FORWARDFLY)
365
    {
366 367
      this->EndForwardFly();
    }
368 369
    this->StartReverseFly();
  }
370
  else if ((this->KeysDown & 16) == 16)
371
  {
372
    if (this->State==VTKIS_REVERSEFLY)
373
    {
374
      this->EndReverseFly();
375
    }
376 377
    this->StartForwardFly();
  }
378 379 380
#else
  // the following if statement is a dummy one to prevent keycode not used
  // 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 386 387 388
#endif
}

//---------------------------------------------------------------------------
389
void vtkInteractorStyleFlight::OnKeyUp()
390 391
{
#ifdef _WIN32
392
  switch (this->Interactor->GetKeyCode())
393
  {
394 395 396 397
    case VK_LEFT        : this->KeysDown &= ~1;  break;
    case VK_RIGHT       : this->KeysDown &= ~2;  break;
    case VK_UP          : this->KeysDown &= ~4;  break;
    case VK_DOWN        : this->KeysDown &= ~8;  break;
Ken Martin's avatar
Ken Martin committed
398
    case 'a':
399
    case 'A'            : this->KeysDown &= ~16; break;
Ken Martin's avatar
Ken Martin committed
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 411
      break;
    case VTKIS_REVERSEFLY:
412
      if ((this->KeysDown & 32) == 0)
413
      {
414
        this->EndReverseFly();
415
      }
416
      break;
417
  }
418 419 420
#else
  // the following if statement is a dummy one to prevent keycode not used
  // 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 426
#endif
}
Sebastien Barre's avatar
Sebastien Barre committed
427

428
//---------------------------------------------------------------------------
429
void vtkInteractorStyleFlight::OnChar()
430
{
431
  switch (this->Interactor->GetKeyCode())
432
  {
433 434 435 436 437 438 439
    case '+' :
      this->MotionUserScale *= 2.0;
      break;
    case '-' :
      this->MotionUserScale *= 0.5;
      break;
    default:
440
      this->Superclass::OnChar();
441
      break;
442
  }
443
}
Sebastien Barre's avatar
Sebastien Barre committed
444

445
//---------------------------------------------------------------------------
446
void vtkInteractorStyleFlight::JumpTo(double campos[3], double focpos[3])
447
{
448
  if (this->CurrentRenderer == nullptr)
449
  {
450
    return;
451
  }
452 453 454 455 456
  vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
  cam->SetPosition(campos);
  cam->SetFocalPoint(focpos);
  FinishCamera(cam);
  this->Interactor->Render();
457
}
Sebastien Barre's avatar
Sebastien Barre committed
458

459
void vtkInteractorStyleFlight::FinishCamera(vtkCamera* cam)
460
{
461 462
    cam->OrthogonalizeViewUp();
    if (this->RestoreUpVector)
463
    {
Sebastien Barre's avatar
Sebastien Barre committed
464
      double delta[3];
465 466 467 468 469 470 471 472 473 474
      cam->GetViewUp(delta);
      double weight = vtkMath::Dot(this->DefaultUpVector,delta);
      // only correct up if we're close to it already...
      if (weight>0.3) {
        weight = 0.25*fabs(weight);
        delta[0] = delta[0] + (this->DefaultUpVector[0]-delta[0])*weight;
        delta[1] = delta[1] + (this->DefaultUpVector[1]-delta[1])*weight;
        delta[2] = delta[2] + (this->DefaultUpVector[2]-delta[2])*weight;
        cam->SetViewUp(delta);
      }
475
    }
476
    if (this->AutoAdjustCameraClippingRange)
477
    {
478
      this->CurrentRenderer->ResetCameraClippingRange();
479
    }
480
    if (this->Interactor->GetLightFollowCamera())
481
    {
482
      this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
483
    }
484
}
Sebastien Barre's avatar
Sebastien Barre committed
485

486
//---------------------------------------------------------------------------
487 488 489 490 491 492
// Use this mouse pos and last mouse pos to get the amount of motion
// Compute an "Ideal" focal point, The flight will sterr towards this ideal
// point, but will be damped in Yaw/Pitch by our PID Controllers.
// The damping and motion is done in the timer event.
//---------------------------------------------------------------------------
void vtkInteractorStyleFlight::UpdateMouseSteering(vtkCamera *cam)
493
{
494 495
  int *thispos = this->Interactor->GetEventPosition();
  int *lastpos = this->Interactor->GetLastEventPosition();
496

497 498 499 500 501 502
  double aspeed = this->AngleStepSize*(this->Interactor->GetShiftKey() ?
      this->AngleAccelerationFactor : 1.0);
  //
  // we want to steer by an amount proportional to window viewangle and size
  // compute dx and dy increments relative to last mouse click
  int *size = this->Interactor->GetSize();
503
  double scalefactor = 5*cam->GetViewAngle()/size[0];
504 505 506 507 508 509 510
  double dx = - (thispos[0] - lastpos[0])*scalefactor*aspeed;
  double dy =   (thispos[1] - lastpos[1])*scalefactor*aspeed;

  // Temporary until I get smooth flight working
  this->DeltaPitch = dy;
  this->DeltaYaw = dx;
/*
luz.paz's avatar
luz.paz committed
511
  Not happy with smooth flight yet, please leave this code here
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
  until I get around to experimenting : JB July 2002

  // dx and dy need to be converted to a new 'ideal' camera focal point
  // we maintain an actual FocalPoint and an IdealFocalPoint so that we can
  // smooth the motion using our PID controllers (one for yaw, one for pitch).
  cam->OrthogonalizeViewUp();
  double LRaxis[3];
  double *ViewUp     = cam->GetViewUp();
  double *Position   = cam->GetPosition();
  double *FocalPoint = cam->GetFocalPoint();
  this->GetLRVector(LRaxis, cam);
  //
  this->Transform->Identity();
  this->Transform->Translate(+Position[0],+Position[1],+Position[2]);
  this->Transform->RotateWXYZ(dx, ViewUp);
  this->Transform->RotateWXYZ(dy, LRaxis);
  this->Transform->Translate(-Position[0],-Position[1],-Position[2]);
  this->Transform->TransformPoint(this->IdealFocalPoint,this->IdealFocalPoint);
*/
531
}
Sebastien Barre's avatar
Sebastien Barre committed
532

533 534
// We know the ideal and actual focal points. We now want to reduce these
// to a 2D Yaw+Pitch form so that we can smooth the motion on each
Sebastien Barre's avatar
Sebastien Barre committed
535
void vtkInteractorStyleFlight::UpdateSteering(vtkCamera *vtkNotUsed(cam))
536
{
537
/*
538 539 540
  #define D2R 0.01745329251994329576923690768    // degrees to radians
  #define R2D 57.2957795130823208767981548141    // radians to degrees

luz.paz's avatar
luz.paz committed
541
  Not happy with smooth flight yet, please leave this code here
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
  until I get around to experimenting : JB July 2002

  cam->OrthogonalizeViewUp();
  double *Position = cam->GetPosition();
  double *FocalPoint = cam->GetFocalPoint();
  double vec1[3], vec2[3], norm1[3], norm2[3];
  vec1[0] = FocalPoint[0]-Position[0];
  vec1[1] = FocalPoint[1]-Position[1];
  vec1[2] = FocalPoint[2]-Position[2];
  vec2[0] = this->IdealFocalPoint[0]-Position[0];
  vec2[1] = this->IdealFocalPoint[1]-Position[1];
  vec2[2] = this->IdealFocalPoint[2]-Position[2];
  // what's the azimuthal angle between the Ideal and actual focal points
  // angle between planes given by Up/Focus and Up/IdealFocus
  double *ViewUp = cam->GetViewUp();
  vtkMath::Cross(vec1, ViewUp, norm1);
  vtkMath::Cross(vec2, ViewUp, norm2);
  vtkMath::Normalize(norm1);
  vtkMath::Normalize(norm2);
561
  //
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
  double dot = vtkMath::Dot(norm1, norm2);
  if (dot>1.0) {
    dot = 1.0;
  }
  else if (dot<-1.0) {
    dot =-1.0;
  }
  double yaw = R2D*acos(dot);
  // we know the angle, but is it +ve or -ve (which side is new focal point)
  double d1,d2;
  d1 = vtkMath::Dot(norm1,this->IdealFocalPoint);
  d2 = vtkMath::Dot(norm1,FocalPoint);
  if (d1-d2>0) yaw = -yaw;
  //
  // what's the elevation angle between the Ideal and actual focal points
  // angle between planes given by LR/Focus and LR/IdealFocus
  double LRaxis[3];
  this->GetLRVector(LRaxis, cam);
  vtkMath::Cross(vec1, LRaxis, norm1);
  vtkMath::Cross(vec2, LRaxis, norm2);
  vtkMath::Normalize(norm1);
  vtkMath::Normalize(norm2);
  //
  dot = vtkMath::Dot(norm1, norm2);
  if (dot>1.0) {
    dot = 1.0;
  } else if (dot<-1.0) {
    dot =-1.0;
  }
  double pitch = R2D*acos(dot);
  d1 = vtkMath::Dot(norm1,this->IdealFocalPoint);
  d2 = vtkMath::Dot(norm1,FocalPoint);
  if (d1-d2>0) pitch = -pitch;

  // use our motion dampers to reduce the yaw/pitch errors to zero gradually
//  this->DeltaYaw   = PID_Yaw->PIDCalc(yaw, 0);
//  this->DeltaPitch = PID_Pitch->PIDCalc(pitch, 0);

  this->DeltaPitch = 0.75*pitch + 0.25*lPitch;
  lPitch = pitch;

  this->DeltaYaw = 0.75*yaw + 0.25*lYaw;
  lYaw = yaw;

*/
607
}
Sebastien Barre's avatar
Sebastien Barre committed
608

609 610 611
//---------------------------------------------------------------------------
// useful utility functions
//---------------------------------------------------------------------------
612
void vtkInteractorStyleFlight::SetupMotionVars(vtkCamera *cam)
613
{
614 615 616 617
  lPitch = 0;
  lYaw   = 0;
  cam->GetFocalPoint(IdealFocalPoint);

Ken Martin's avatar
Ken Martin committed
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 627 628 629
    this->DiagonalLength =
      sqrt( (bounds[0] - bounds[1]) * (bounds[0] - bounds[1]) +
            (bounds[2] - bounds[3]) * (bounds[2] - bounds[3]) +
            (bounds[4] - bounds[5]) * (bounds[4] - bounds[5]) );
630
  }
631
}
Sebastien Barre's avatar
Sebastien Barre committed
632

633
//---------------------------------------------------------------------------
634 635
void vtkInteractorStyleFlight::MotionAlongVector(double vector[3],
    double amount, vtkCamera* cam)
636 637
{
  double oldcampos[3], oldcamfoc[3];
638 639 640 641
  cam->GetPosition(oldcampos);
  cam->GetFocalPoint(oldcamfoc);
  // move camera and focus along DirectionOfProjection
  cam->SetPosition(
642 643 644
    oldcampos[0] - amount * vector[0],
    oldcampos[1] - amount * vector[1],
    oldcampos[2] - amount * vector[2]);
645
  cam->SetFocalPoint(
646 647 648
    oldcamfoc[0] - amount * vector[0],
    oldcamfoc[1] - amount * vector[1],
    oldcamfoc[2] - amount * vector[2]);
649
}
Sebastien Barre's avatar
Sebastien Barre committed
650

651
//---------------------------------------------------------------------------
652
void vtkInteractorStyleFlight::GetLRVector(double vector[3], vtkCamera* cam)
653
{
654 655 656 657 658
  vtkMatrix4x4 *vtm;
  vtm = cam->GetViewTransformMatrix();
  vector[0] = vtm->GetElement(0,0);
  vector[1] = vtm->GetElement(0,1);
  vector[2] = vtm->GetElement(0,2);
659
}
Sebastien Barre's avatar
Sebastien Barre committed
660

661 662 663
//---------------------------------------------------------------------------
// Perform the motion
//---------------------------------------------------------------------------
664
void vtkInteractorStyleFlight::FlyByMouse(vtkCamera* cam)
665 666 667
{
  double a_vector[3];
  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 674
  // Sidestep (convert steering angles to left right movement :
  // only because I added this after doing the angles earlier
675
  if (this->Interactor->GetControlKey())
676
  {
677
    if (this->DeltaYaw!=0.0)
678
    {
679 680
      this->GetLRVector(a_vector, cam);
      this->MotionAlongVector(a_vector,-this->DeltaYaw*speed/2.0, cam);
681
    }
682
    if (this->DeltaPitch!=0.0)
683
    {
684 685 686
      cam->GetViewUp(a_vector);
      this->MotionAlongVector(a_vector,-this->DeltaPitch*speed/2.0, cam);
    }
687
  }
688
  else
689
  {
690 691 692 693 694
    cam->Yaw(this->DeltaYaw);
    cam->Pitch(this->DeltaPitch);
    this->DeltaYaw = 0;
    this->DeltaPitch = 0;
    // cam->SetFocalPoint(this->IdealFocalPoint);
695
  }
696
  //
697
  if (!this->Interactor->GetControlKey())
698
  {
699 700
    cam->GetDirectionOfProjection(a_vector); // reversed (use -speed)
    switch (this->State)
701
    {
702 703 704 705 706 707
      case VTKIS_FORWARDFLY:
        this->MotionAlongVector(a_vector, -speed, cam);
        break;
      case VTKIS_REVERSEFLY:
        this->MotionAlongVector(a_vector, speed, cam);
        break;
708
    }
709
  }
710
}
Sebastien Barre's avatar
Sebastien Barre committed
711

712
//---------------------------------------------------------------------------
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 724
  double a_vector[3];
  // 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
}
Sebastien Barre's avatar
Sebastien Barre committed
785

786
//---------------------------------------------------------------------------
787
void vtkInteractorStyleFlight::PrintSelf(ostream& os, vtkIndent indent)
788
{
Brad King's avatar
Brad King committed
789
  this->Superclass::PrintSelf(os,indent);
790 791 792 793 794 795 796 797 798 799
  os << indent << "MotionStepSize: "
     << this->MotionStepSize << "\n";
  os << indent << "MotionAccelerationFactor: "
     << this->MotionAccelerationFactor << "\n";
  os << indent << "AngleStepSize: "
     << this->AngleStepSize << "\n";
  os << indent << "AngleAccelerationFactor: "
     << this->AngleAccelerationFactor << "\n";
  os << indent << "MotionUserScale: "
     << this->MotionUserScale << "\n";
800 801
  os << indent << "DisableMotion: "
     << this->DisableMotion << "\n";
802 803 804 805 806 807
  os << indent << "RestoreUpVector: "
     << this->RestoreUpVector << "\n";
  os << indent << "DefaultUpVector: "
     << this->DefaultUpVector[0] << " "
     << this->DefaultUpVector[1] << " "
     << this->DefaultUpVector[2] << "\n";
808 809 810
}