1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkCamera.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 "vtkCamera.h"
16 
17 #include "vtkMath.h"
18 #include "vtkTimeStamp.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkPerspectiveTransform.h"
21 #include "vtkTransform.h"
22 #include "vtkCallbackCommand.h"
23 #include "vtkRenderer.h"
24 
25 #include <cassert>
26 #include <cmath>
27 
28 //----------------------------------------------------------------------------
29 // Needed when we don't use the vtkStandardNewMacro.
30 vtkAbstractObjectFactoryNewMacro(vtkCamera)
31 
32 vtkCxxSetObjectMacro(vtkCamera, EyeTransformMatrix, vtkMatrix4x4);
33 vtkCxxSetObjectMacro(vtkCamera, ModelTransformMatrix, vtkMatrix4x4);
34 vtkCxxSetObjectMacro(vtkCamera, ExplicitProjectionTransformMatrix, vtkMatrix4x4)
35 
36 //-----------------------------------------------------------------------------
37 class vtkCameraCallbackCommand : public vtkCommand
38 {
39 public:
New()40   static vtkCameraCallbackCommand *New()
41     { return new vtkCameraCallbackCommand; }
42   vtkCamera *Self;
Execute(vtkObject *,unsigned long,void *)43   void Execute(vtkObject *, unsigned long, void *) override
44   {
45       if (this->Self)
46       {
47         this->Self->Modified();
48         this->Self->ComputeViewTransform();
49         this->Self->ComputeDistance();
50         this->Self->ComputeCameraLightTransform();
51       }
52   }
53 protected:
vtkCameraCallbackCommand()54   vtkCameraCallbackCommand() { this->Self = nullptr; }
55   ~vtkCameraCallbackCommand() override = default;
56 };
57 
58 //----------------------------------------------------------------------------
59 // Construct camera instance with its focal point at the origin,
60 // and position=(0,0,1). The view up is along the y-axis,
61 // view angle is 30 degrees, and the clipping range is (.1,1000).
vtkCamera()62 vtkCamera::vtkCamera()
63 {
64   this->FocalPoint[0] = 0.0;
65   this->FocalPoint[1] = 0.0;
66   this->FocalPoint[2] = 0.0;
67 
68   this->Position[0] = 0.0;
69   this->Position[1] = 0.0;
70   this->Position[2] = 1.0;
71 
72   this->ViewUp[0] = 0.0;
73   this->ViewUp[1] = 1.0;
74   this->ViewUp[2] = 0.0;
75 
76   this->DirectionOfProjection[0] = 0.0;
77   this->DirectionOfProjection[1] = 0.0;
78   this->DirectionOfProjection[2] = 0.0;
79 
80   this->ViewAngle = 30.0;
81   this->UseHorizontalViewAngle = 0;
82 
83   this->UseOffAxisProjection  = 0;
84 
85   this->ScreenBottomLeft[0] = -0.5;
86   this->ScreenBottomLeft[1] = -0.5;
87   this->ScreenBottomLeft[2] = -0.5;
88 
89   this->ScreenBottomRight[0] =  0.5;
90   this->ScreenBottomRight[1] = -0.5;
91   this->ScreenBottomRight[2] = -0.5;
92 
93   this->ScreenTopRight[0] =  0.5;
94   this->ScreenTopRight[1] =  0.5;
95   this->ScreenTopRight[2] = -0.5;
96 
97   this->EyeSeparation = 0.06;
98 
99   this->WorldToScreenMatrix = vtkMatrix4x4::New();
100   this->WorldToScreenMatrix->Identity();
101 
102   this->EyeTransformMatrix = vtkMatrix4x4::New();
103   this->EyeTransformMatrix->Identity();
104 
105   this->ModelTransformMatrix = vtkMatrix4x4::New();
106   this->ModelTransformMatrix->Identity();
107 
108   this->ClippingRange[0] = 0.01;
109   this->ClippingRange[1] = 1000.01;
110   this->Thickness = 1000.0;
111 
112   this->ParallelProjection = 0;
113   this->ParallelScale = 1.0;
114 
115   this->EyeAngle = 2.0;
116   this->Stereo = 0;
117   this->LeftEye = 1;
118 
119   this->WindowCenter[0] = 0.0;
120   this->WindowCenter[1] = 0.0;
121 
122   this->ViewShear[0] = 0.0;
123   this->ViewShear[1] = 0.0;
124   this->ViewShear[2] = 1.0;
125 
126   this->FocalDisk = 1.0;
127 
128   this->Transform = vtkPerspectiveTransform::New();
129   this->ViewTransform = vtkTransform::New();
130   this->ProjectionTransform = vtkPerspectiveTransform::New();
131   this->CameraLightTransform = vtkTransform::New();
132   this->ModelViewTransform = vtkTransform::New();
133   this->ExplicitProjectionTransformMatrix = nullptr;
134   this->UseExplicitProjectionTransformMatrix = false;
135   this->UserTransform = nullptr;
136   this->UserViewTransform = nullptr;
137   this->UserViewTransformCallbackCommand = nullptr;
138 
139   // initialize the ViewTransform
140   this->ComputeViewTransform();
141   this->ComputeDistance();
142   this->ComputeCameraLightTransform();
143 
144   this->FreezeFocalPoint = false;
145   this->UseScissor = false;
146 }
147 
148 //----------------------------------------------------------------------------
~vtkCamera()149 vtkCamera::~vtkCamera()
150 {
151   this->WorldToScreenMatrix->Delete();
152   this->WorldToScreenMatrix = nullptr;
153 
154   this->EyeTransformMatrix->Delete();
155   this->EyeTransformMatrix = nullptr;
156 
157   this->ModelTransformMatrix->Delete();
158   this->ModelTransformMatrix = nullptr;
159 
160   this->Transform->Delete();
161   this->ViewTransform->Delete();
162   this->ProjectionTransform->Delete();
163   this->CameraLightTransform->Delete();
164   this->ModelViewTransform->Delete();
165   if (this->ExplicitProjectionTransformMatrix)
166   {
167     this->ExplicitProjectionTransformMatrix->UnRegister(this);
168     this->ExplicitProjectionTransformMatrix = nullptr;
169   }
170   if (this->UserTransform)
171   {
172     this->UserTransform->UnRegister(this);
173     this->UserTransform = nullptr;
174   }
175   if (this->UserViewTransform)
176   {
177     this->UserViewTransform->RemoveObserver(
178       this->UserViewTransformCallbackCommand);
179     this->UserViewTransform->UnRegister(this);
180     this->UserViewTransform = nullptr;
181   }
182   if (this->UserViewTransformCallbackCommand)
183   {
184     this->UserViewTransformCallbackCommand->Delete();
185   }
186 }
187 
188 //----------------------------------------------------------------------------
SetScissorRect(vtkRecti scissorRect)189 void vtkCamera::SetScissorRect(vtkRecti scissorRect)
190 {
191   this->ScissorRect = scissorRect;
192 }
193 
194 //----------------------------------------------------------------------------
GetScissorRect(vtkRecti & scissorRect)195 void vtkCamera::GetScissorRect(vtkRecti& scissorRect)
196 {
197   scissorRect = this->ScissorRect;
198 }
199 
200 //----------------------------------------------------------------------------
201 // The first set of methods deal exclusively with the ViewTransform, which
202 // is the only transform which is set up entirely in the camera.  The
203 // perspective transform must be set up by the Renderer because the
204 // Camera doesn't know the Renderer's aspect ratio.
205 //----------------------------------------------------------------------------
SetPosition(double x,double y,double z)206 void vtkCamera::SetPosition(double x, double y, double z)
207 {
208   if (x == this->Position[0] &&
209       y == this->Position[1] &&
210       z == this->Position[2])
211   {
212     return;
213   }
214 
215   this->Position[0] = x;
216   this->Position[1] = y;
217   this->Position[2] = z;
218 
219   vtkDebugMacro(<< " Position set to ( " <<  this->Position[0] << ", "
220                 << this->Position[1] << ", " << this->Position[2] << ")");
221 
222   this->ComputeViewTransform();
223   // recompute the focal distance
224   this->ComputeDistance();
225   this->ComputeCameraLightTransform();
226 
227   this->Modified();
228 }
229 
230 //----------------------------------------------------------------------------
SetUserTransform(vtkHomogeneousTransform * transform)231 void vtkCamera::SetUserTransform(vtkHomogeneousTransform *transform)
232 {
233   if (transform == this->UserTransform)
234   {
235     return;
236   }
237   if (this->UserTransform)
238   {
239     this->UserTransform->Delete();
240     this->UserTransform = nullptr;
241   }
242   if (transform)
243   {
244     this->UserTransform = transform;
245     this->UserTransform->Register(this);
246   }
247   this->Modified();
248 }
249 
250 //----------------------------------------------------------------------------
SetUserViewTransform(vtkHomogeneousTransform * transform)251 void vtkCamera::SetUserViewTransform(vtkHomogeneousTransform *transform)
252 {
253   if (transform == this->UserViewTransform)
254   {
255     return;
256   }
257   if (this->UserViewTransform)
258   {
259     this->UserViewTransform->RemoveObserver(
260       this->UserViewTransformCallbackCommand);
261     this->UserViewTransform->Delete();
262     this->UserViewTransform = nullptr;
263   }
264   if (transform)
265   {
266     this->UserViewTransform = transform;
267     this->UserViewTransform->Register(this);
268     if (!this->UserViewTransformCallbackCommand)
269     {
270       this->UserViewTransformCallbackCommand = vtkCameraCallbackCommand::New();
271       this->UserViewTransformCallbackCommand->Self = this;
272     }
273     this->UserViewTransform->AddObserver(
274       vtkCommand::ModifiedEvent,
275       this->UserViewTransformCallbackCommand);
276   }
277   this->Modified();
278   this->ComputeViewTransform();
279   this->ComputeDistance();
280   this->ComputeCameraLightTransform();
281 }
282 
283 //----------------------------------------------------------------------------
SetFocalPoint(double x,double y,double z)284 void vtkCamera::SetFocalPoint(double x, double y, double z)
285 {
286   if (x == this->FocalPoint[0] &&
287       y == this->FocalPoint[1] &&
288       z == this->FocalPoint[2])
289   {
290     return;
291   }
292 
293   this->FocalPoint[0] = x;
294   this->FocalPoint[1] = y;
295   this->FocalPoint[2] = z;
296 
297   vtkDebugMacro(<< " FocalPoint set to ( " <<  this->FocalPoint[0] << ", " << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")");
298 
299   this->ComputeViewTransform();
300   // recompute the focal distance
301   this->ComputeDistance();
302   this->ComputeCameraLightTransform();
303 
304   this->Modified();
305 }
306 
307 //----------------------------------------------------------------------------
SetViewUp(double x,double y,double z)308 void vtkCamera::SetViewUp(double x, double y, double z)
309 {
310   // normalize ViewUp, but do _not_ orthogonalize it by default
311   double norm = sqrt(x*x + y*y + z*z);
312 
313   if(norm != 0)
314   {
315     x /= norm;
316     y /= norm;
317     z /= norm;
318   }
319   else
320   {
321     x = 0;
322     y = 1;
323     z = 0;
324   }
325 
326   if (x == this->ViewUp[0] &&
327       y == this->ViewUp[1] &&
328       z == this->ViewUp[2])
329   {
330     return;
331   }
332 
333   this->ViewUp[0] = x;
334   this->ViewUp[1] = y;
335   this->ViewUp[2] = z;
336 
337   vtkDebugMacro(<< " ViewUp set to ( " <<  this->ViewUp[0] << ", "
338     << this->ViewUp[1] << ", " << this->ViewUp[2] << ")");
339 
340   this->ComputeViewTransform();
341   this->ComputeCameraLightTransform();
342   this->Modified();
343 }
344 
345 //----------------------------------------------------------------------------
346 // The ViewTransform depends on only three ivars:  the Position, the
347 // FocalPoint, and the ViewUp vector.  All the other methods are there
348 // simply for the sake of the users' convenience.
ComputeViewTransform()349 void vtkCamera::ComputeViewTransform()
350 {
351   // main view through the camera
352   this->Transform->Identity();
353   if (this->UserViewTransform)
354   {
355     this->Transform->Concatenate(this->UserViewTransform);
356   }
357   this->Transform->SetupCamera(this->Position, this->FocalPoint, this->ViewUp);
358   this->ViewTransform->Identity();
359   this->ViewTransform->Concatenate(this->Transform->GetMatrix());
360 }
361 
362 //----------------------------------------------------------------------------
ComputeCameraLightTransform()363 void vtkCamera::ComputeCameraLightTransform()
364 {
365   vtkTransform *t;
366   double d;
367 
368   // assumes a valid view transform and valid camera distance
369 
370   t = this->CameraLightTransform;
371   t->Identity();
372   t->SetMatrix(this->ViewTransform->GetMatrix());
373   t->Inverse();
374 
375   d = this->Distance;
376   t->Scale(d, d, d);
377   t->Translate(0.0, 0.0, -1.0);
378 }
379 
380 //----------------------------------------------------------------------------
ComputeWorldToScreenMatrix()381 void vtkCamera::ComputeWorldToScreenMatrix()
382 {
383   // Avoid recalculating screen orientation if we don't need to.
384   if(this->WorldToScreenMatrixMTime.GetMTime() < this->GetMTime())
385   {
386     double xAxis[3];
387     double yAxis[3];
388     double zAxis[3];
389 
390     for(int i = 0; i < 3; ++i)
391     {
392       xAxis[i] = this->ScreenBottomRight[i] - this->ScreenBottomLeft[i];
393       yAxis[i] = this->ScreenTopRight[i]    - this->ScreenBottomRight[i];
394     }
395 
396     vtkMath::Normalize(xAxis);
397     vtkMath::Normalize(yAxis);
398     vtkMath::Cross(xAxis, yAxis, zAxis);
399     vtkMath::Normalize(zAxis);
400 
401     // Setting individual elements of the matrix.
402 
403     // Make it column major and then invert it to make sure the translation is correct
404     // This is using column major (vectors are copied into the column)
405     // \Note: while the initial element assignments are made in column-major
406     // ordering, the matrix will be inverted, resulting in a row-major
407     // matrix that provides the transformation from World to Screen space.
408     this->WorldToScreenMatrix->SetElement(0, 0, xAxis[0]);
409     this->WorldToScreenMatrix->SetElement(1, 0, xAxis[1]);
410     this->WorldToScreenMatrix->SetElement(2, 0, xAxis[2]);
411 
412     this->WorldToScreenMatrix->SetElement(0, 1, yAxis[0]);
413     this->WorldToScreenMatrix->SetElement(1, 1, yAxis[1]);
414     this->WorldToScreenMatrix->SetElement(2, 1, yAxis[2]);
415 
416     this->WorldToScreenMatrix->SetElement(0, 2, zAxis[0]);
417     this->WorldToScreenMatrix->SetElement(1, 2, zAxis[1]);
418     this->WorldToScreenMatrix->SetElement(2, 2, zAxis[2]);
419 
420     this->WorldToScreenMatrix->SetElement(0, 3, this->ScreenBottomLeft[0]);
421     this->WorldToScreenMatrix->SetElement(1, 3, this->ScreenBottomLeft[1]);
422     this->WorldToScreenMatrix->SetElement(2, 3, this->ScreenBottomLeft[2]);
423 
424     this->WorldToScreenMatrix->SetElement(3, 3, 1.0);
425 
426     // The reason for doing this as an Invert as the goal here is to put
427     // the translation through the rotation that we've just assigned ie.
428     // the translation has to be put into screen space too.
429     this->WorldToScreenMatrix->Invert();
430 
431     this->WorldToScreenMatrixMTime.Modified();
432   }
433 }
434 
435 //----------------------------------------------------------------------------
ComputeOffAxisProjectionFrustum()436 void vtkCamera::ComputeOffAxisProjectionFrustum()
437 {
438   this->ComputeWorldToScreenMatrix();
439 
440   // \NOTE: Variable names reflect naming convention used in
441   // "High Resolution Virtual Reality", in Proc.
442   // SIGGRAPH '92, Computer Graphics, pages 195-202, 1992.
443 
444   // OffAxis calculations.
445 
446 
447   // vtkMatrix::MultiplyPoint expect homogeneous coordinate.
448   double E[4] = {0.0, 0.0, 0.0, 1.0};
449 
450   double L[4] = {this->ScreenBottomLeft[0], this->ScreenBottomLeft[1], this->ScreenBottomLeft[2], 1.0};
451   double H[4] = {this->ScreenTopRight[0],   this->ScreenTopRight[1], this->ScreenTopRight[2], 1.0};
452 
453   double eyeSeparationCorrectionFactor = 10.0;
454   double shiftDistance = this->EyeSeparation / (2.0 * eyeSeparationCorrectionFactor);
455   if(this->Distance < 1.0)
456   {
457     shiftDistance *= this->Distance;
458   }
459   if(this->LeftEye)
460   {
461     E[0] -= shiftDistance;
462   }
463   else
464   {
465     E[0] += shiftDistance;
466   }
467 
468   // First transform the eye to new position.
469   this->EyeTransformMatrix->MultiplyPoint(E, E);
470 
471   // Now transform the eye and screen corner points into the screen
472   // coordinate system.
473   this->WorldToScreenMatrix->MultiplyPoint(E, E);
474   this->WorldToScreenMatrix->MultiplyPoint(H, H);
475   this->WorldToScreenMatrix->MultiplyPoint(L, L);
476 
477   double matrix[4][4];
478   double width  = H[0] - L[0];
479   double height = H[1] - L[1];
480 
481   // Back and front are not traditional near and far.
482   // Front (aka near)
483   double F = E[2] - (this->Distance + this->Thickness);//E[2] - 10000.0;//this->ClippingRange[1];
484   // Back (aka far)
485   double nearDistanceCorrectionFactor  = 1000.0;
486   double B = E[2] - (this->Distance / nearDistanceCorrectionFactor);//E[2] - .1;//this->ClippingRange[0];
487 
488   double depth = B - F;
489   matrix[0][0] =  ( 2*E[2] ) / width;
490   matrix[1][0] =  0;
491   matrix[2][0] =  0;
492   matrix[3][0] =  0;
493 
494   matrix[0][1] =  0;
495   matrix[1][1] =  ( 2*E[2] )/ height;
496   matrix[2][1] =  0;
497   matrix[3][1] =  0;
498 
499   matrix[0][2] = ( H[0]+L[0] - 2*E[0] )/width;
500   matrix[1][2] = ( H[1]+L[1] - 2*E[1] )/height;
501   matrix[2][2] = ( B+F-2*E[2] )/depth;
502   matrix[3][2] = -1;
503 
504   matrix[0][3] = ( -E[2]*( H[0]+L[0] ) )/width;
505   matrix[1][3] = ( -E[2]*( H[1]+L[1] ) )/height;
506   matrix[2][3] = B-E[2]- ( B *( B+F - 2*E[2] )/depth );
507   matrix[3][3] = E[2];
508 
509   for ( int i=0; i<4; i++ )
510   {
511     for ( int j=0; j<4; j++ )
512     {
513       this->ProjectionTransform->GetMatrix()->SetElement( i,j,  matrix[i][j] ) ;
514     }
515   }
516 
517   //  Now move the world into display space.
518   vtkMatrix4x4::Multiply4x4(this->ProjectionTransform->GetMatrix(), this->WorldToScreenMatrix,
519                             this->ProjectionTransform->GetMatrix());
520 }
521 
522 //----------------------------------------------------------------------------
ComputeModelViewMatrix()523 void vtkCamera::ComputeModelViewMatrix()
524 {
525   if(this->ModelViewTransform->GetMTime() < this->ModelTransformMatrix->GetMTime() ||
526      this->ModelViewTransform->GetMTime() < this->ViewTransform->GetMTime())
527   {
528     vtkMatrix4x4::Multiply4x4(this->ViewTransform->GetMatrix(), this->ModelTransformMatrix,
529                               this->ModelViewTransform->GetMatrix());
530   }
531 }
532 
533 //----------------------------------------------------------------------------
OrthogonalizeViewUp()534 void vtkCamera::OrthogonalizeViewUp()
535 {
536   // the orthogonalized ViewUp is just the second row of the view matrix
537   vtkMatrix4x4 *matrix = this->ViewTransform->GetMatrix();
538   this->ViewUp[0] = matrix->GetElement(1,0);
539   this->ViewUp[1] = matrix->GetElement(1,1);
540   this->ViewUp[2] = matrix->GetElement(1,2);
541 
542   this->Modified();
543 }
544 
545 //----------------------------------------------------------------------------
546 // Set the distance of the focal point from the camera. The focal point is
547 // modified accordingly. This should be positive.
SetDistance(double d)548 void vtkCamera::SetDistance(double d)
549 {
550   if (this->Distance == d)
551   {
552     return;
553   }
554 
555   this->Distance = d;
556 
557   // Distance should be greater than .0002
558   if (this->Distance < 0.0002)
559   {
560     this->Distance = 0.0002;
561     vtkDebugMacro(<< " Distance is set to minimum.");
562   }
563 
564   // we want to keep the camera pointing in the same direction
565   double *vec = this->DirectionOfProjection;
566 
567   // recalculate FocalPoint
568   this->FocalPoint[0] = this->Position[0] + vec[0]*this->Distance;
569   this->FocalPoint[1] = this->Position[1] + vec[1]*this->Distance;
570   this->FocalPoint[2] = this->Position[2] + vec[2]*this->Distance;
571 
572   vtkDebugMacro(<< " Distance set to ( " <<  this->Distance << ")");
573 
574   this->ComputeViewTransform();
575   this->ComputeCameraLightTransform();
576   this->Modified();
577 }
578 
579 //----------------------------------------------------------------------------
580 // This method must be called when the focal point or camera position changes
ComputeDistance()581 void vtkCamera::ComputeDistance()
582 {
583   double dx = this->FocalPoint[0] - this->Position[0];
584   double dy = this->FocalPoint[1] - this->Position[1];
585   double dz = this->FocalPoint[2] - this->Position[2];
586 
587   this->Distance = sqrt(dx*dx + dy*dy + dz*dz);
588 
589   if (this->Distance < 1e-20)
590   {
591     this->Distance = 1e-20;
592     vtkDebugMacro(<< " Distance is set to minimum.");
593 
594     double *vec = this->DirectionOfProjection;
595 
596     // recalculate FocalPoint
597     this->FocalPoint[0] = this->Position[0] + vec[0]*this->Distance;
598     this->FocalPoint[1] = this->Position[1] + vec[1]*this->Distance;
599     this->FocalPoint[2] = this->Position[2] + vec[2]*this->Distance;
600   }
601 
602   this->DirectionOfProjection[0] = dx/this->Distance;
603   this->DirectionOfProjection[1] = dy/this->Distance;
604   this->DirectionOfProjection[2] = dz/this->Distance;
605 
606   this->ComputeViewPlaneNormal();
607 }
608 
609 //----------------------------------------------------------------------------
610 // Move the position of the camera along the view plane normal. Moving
611 // towards the focal point (e.g., > 1) is a dolly-in, moving away
612 // from the focal point (e.g., < 1) is a dolly-out.
Dolly(double amount)613 void vtkCamera::Dolly(double amount)
614 {
615   if (amount <= 0.0)
616   {
617     return;
618   }
619 
620   // dolly moves the camera towards the focus
621   double d = this->Distance/amount;
622 
623   this->SetPosition(this->FocalPoint[0] - d*this->DirectionOfProjection[0],
624                     this->FocalPoint[1] - d*this->DirectionOfProjection[1],
625                     this->FocalPoint[2] - d*this->DirectionOfProjection[2]);
626 }
627 
628 //----------------------------------------------------------------------------
629 // Set the roll angle of the camera about the direction of projection
SetRoll(double roll)630 void vtkCamera::SetRoll(double roll)
631 {
632   // roll is a rotation of camera view up about the direction of projection
633   vtkDebugMacro(<< " Setting Roll to " << roll << "");
634 
635   // subtract the current roll
636   roll -= this->GetRoll();
637 
638   if (fabs(roll) < 0.00001)
639   {
640     return;
641   }
642 
643   this->Roll(roll);
644 }
645 
646 //----------------------------------------------------------------------------
647 // Returns the roll of the camera.
GetRoll()648 double vtkCamera::GetRoll()
649 {
650   double orientation[3];
651   this->ViewTransform->GetOrientation(orientation);
652   return orientation[2];
653 }
654 
655 //----------------------------------------------------------------------------
656 // Rotate the camera around the view plane normal.
Roll(double angle)657 void vtkCamera::Roll(double angle)
658 {
659   double newViewUp[3];
660   this->Transform->Identity();
661 
662   // rotate ViewUp about the Direction of Projection
663   this->Transform->RotateWXYZ(angle,this->DirectionOfProjection);
664 
665   // okay, okay, TransformPoint shouldn't be used on vectors -- but
666   // the transform is rotation with no translation so this works fine.
667   this->Transform->TransformPoint(this->ViewUp,newViewUp);
668   this->SetViewUp(newViewUp);
669 }
670 
671 //----------------------------------------------------------------------------
672 // Rotate the focal point about the view up vector centered at the camera's
673 // position.
Yaw(double angle)674 void vtkCamera::Yaw(double angle)
675 {
676   double newFocalPoint[3];
677   double *pos = this->Position;
678   this->Transform->Identity();
679 
680   // translate the camera to the origin,
681   // rotate about axis,
682   // translate back again
683   this->Transform->Translate(+pos[0],+pos[1],+pos[2]);
684   this->Transform->RotateWXYZ(angle,this->ViewUp);
685   this->Transform->Translate(-pos[0],-pos[1],-pos[2]);
686 
687   // now transform focal point
688   this->Transform->TransformPoint(this->FocalPoint,newFocalPoint);
689   this->SetFocalPoint(newFocalPoint);
690 }
691 
692 //----------------------------------------------------------------------------
693 // Rotate the focal point about the cross product of the view up vector
694 // and the negative of the , centered at the camera's position.
Pitch(double angle)695 void vtkCamera::Pitch(double angle)
696 {
697   double axis[3], newFocalPoint[3], savedViewUp[3];
698   double *pos = this->Position;
699   this->Transform->Identity();
700 
701   // the axis is the first row of the view transform matrix
702   axis[0] = this->ViewTransform->GetMatrix()->GetElement(0,0);
703   axis[1] = this->ViewTransform->GetMatrix()->GetElement(0,1);
704   axis[2] = this->ViewTransform->GetMatrix()->GetElement(0,2);
705 
706   // temporarily set the view up with the transformation applied
707   // to avoid bad cross product computations during SetFocalPoint call
708   this->GetViewUp(savedViewUp);
709   this->Transform->RotateWXYZ(angle, axis);
710   this->Transform->TransformPoint(this->ViewUp, this->ViewUp);
711   this->Transform->Identity();
712 
713   // translate the camera to the origin,
714   // rotate about axis,
715   // translate back again
716   this->Transform->Translate(+pos[0],+pos[1],+pos[2]);
717   this->Transform->RotateWXYZ(angle,axis);
718   this->Transform->Translate(-pos[0],-pos[1],-pos[2]);
719 
720   // now transform focal point
721   this->Transform->TransformPoint(this->FocalPoint,newFocalPoint);
722   this->SetFocalPoint(newFocalPoint);
723 
724   // restore the previous ViewUp vector
725   this->ViewUp[0] = savedViewUp[0];
726   this->ViewUp[1] = savedViewUp[1];
727   this->ViewUp[2] = savedViewUp[2];
728   // this is needed since the last time Modified was called (in SetFocalPoint),
729   // the ViewUp was not same as savedViewUp. Since we're changing its value
730   // here, we need to fire Modified event. We don't call `SetViewUp` since we
731   // don't want the computation of the view transform to happen again.
732   this->Modified();
733 }
734 
735 //----------------------------------------------------------------------------
736 // Rotate the camera about the view up vector centered at the focal point.
Azimuth(double angle)737 void vtkCamera::Azimuth(double angle)
738 {
739   double newPosition[3];
740   double *fp = this->FocalPoint;
741   this->Transform->Identity();
742 
743   // translate the focal point to the origin,
744   // rotate about view up,
745   // translate back again
746   this->Transform->Translate(+fp[0],+fp[1],+fp[2]);
747   this->Transform->RotateWXYZ(angle,this->ViewUp);
748   this->Transform->Translate(-fp[0],-fp[1],-fp[2]);
749 
750   // apply the transform to the position
751   this->Transform->TransformPoint(this->Position,newPosition);
752   this->SetPosition(newPosition);
753 }
754 
755 //----------------------------------------------------------------------------
756 // Rotate the camera about the cross product of the negative of the
757 // direction of projection and the view up vector centered on the focal point.
Elevation(double angle)758 void vtkCamera::Elevation(double angle)
759 {
760   double axis[3], newPosition[3], savedViewUp[3];
761   double *fp = this->FocalPoint;
762   this->Transform->Identity();
763 
764   // snatch the axis from the view transform matrix
765   axis[0] = -this->ViewTransform->GetMatrix()->GetElement(0,0);
766   axis[1] = -this->ViewTransform->GetMatrix()->GetElement(0,1);
767   axis[2] = -this->ViewTransform->GetMatrix()->GetElement(0,2);
768 
769   // temporarily set the view up with the transformation applied
770   // to avoid bad cross product computations during SetPosition call
771   this->GetViewUp(savedViewUp);
772   this->Transform->RotateWXYZ(angle, axis);
773   this->Transform->TransformPoint(this->ViewUp, this->ViewUp);
774   this->Transform->Identity();
775 
776     // translate the focal point to the origin,
777   // rotate about axis,
778   // translate back again
779   this->Transform->Translate(+fp[0],+fp[1],+fp[2]);
780   this->Transform->RotateWXYZ(angle,axis);
781   this->Transform->Translate(-fp[0],-fp[1],-fp[2]);
782 
783   // now transform position
784   this->Transform->TransformPoint(this->Position,newPosition);
785   this->SetPosition(newPosition);
786 
787   // restore the previous ViewUp vector
788   this->ViewUp[0] = savedViewUp[0];
789   this->ViewUp[1] = savedViewUp[1];
790   this->ViewUp[2] = savedViewUp[2];
791   // this is needed since the last time Modified was called (in SetPosition),
792   // the ViewUp was not same as savedViewUp. Since we're changing its value
793   // here, we need to fire Modified event. We don't call `SetViewUp` since we
794   // don't want the computation of the view transform to happen again.
795   this->Modified();
796 }
797 
798 //----------------------------------------------------------------------------
799 // Apply Transform to camera
ApplyTransform(vtkTransform * t)800 void vtkCamera::ApplyTransform(vtkTransform *t)
801 {
802   double posOld[4], posNew[4], fpOld[4], fpNew[4], vuOld[4], vuNew[4];
803 
804   this->GetPosition(posOld);
805   this->GetFocalPoint(fpOld);
806   this->GetViewUp(vuOld);
807 
808   posOld[3] = 1.0;
809   fpOld[3] = 1.0;
810   vuOld[3] = 1.0;
811 
812   vuOld[0] += posOld[0];
813   vuOld[1] += posOld[1];
814   vuOld[2] += posOld[2];
815 
816   t->MultiplyPoint(posOld, posNew);
817   t->MultiplyPoint(fpOld, fpNew);
818   t->MultiplyPoint(vuOld, vuNew);
819 
820   vuNew[0] -= posNew[0];
821   vuNew[1] -= posNew[1];
822   vuNew[2] -= posNew[2];
823 
824   this->SetPosition(posNew);
825   this->SetFocalPoint(fpNew);
826   this->SetViewUp(vuNew);
827 }
828 
829 //----------------------------------------------------------------------------
830 //----------------------------------------------------------------------------
831 // The following methods set up the information that the Renderer needs
832 // to set up the perspective transform.  The transformation matrix is
833 // created using the GetPerspectiveTransformMatrix method.
834 //----------------------------------------------------------------------------
835 //----------------------------------------------------------------------------
836 
837 //----------------------------------------------------------------------------
SetParallelProjection(vtkTypeBool flag)838 void vtkCamera::SetParallelProjection(vtkTypeBool flag)
839 {
840   if ( this->ParallelProjection != flag )
841   {
842     this->ParallelProjection = flag;
843     this->Modified();
844     this->ViewingRaysModified();
845   }
846 }
847 
848 //----------------------------------------------------------------------------
SetViewAngle(double angle)849 void vtkCamera::SetViewAngle(double angle)
850 {
851   double min = 0.00000001;
852   double max = 179.0;
853 
854   if ( this->ViewAngle != angle )
855   {
856     this->ViewAngle = (angle<min?min:(angle>max?max:angle));
857     this->Modified();
858     this->ViewingRaysModified();
859   }
860 }
861 
862 //----------------------------------------------------------------------------
SetUseHorizontalViewAngle(vtkTypeBool flag)863 void vtkCamera::SetUseHorizontalViewAngle(vtkTypeBool flag)
864 {
865   if (flag == this->UseHorizontalViewAngle)
866   {
867     return;
868   }
869   this->UseHorizontalViewAngle = flag;
870   this->Modified();
871   this->ViewingRaysModified();
872 }
873 
874 //----------------------------------------------------------------------------
SetParallelScale(double scale)875 void vtkCamera::SetParallelScale(double scale)
876 {
877   if ( this->ParallelScale != scale )
878   {
879     this->ParallelScale = scale;
880     this->Modified();
881     this->ViewingRaysModified();
882   }
883 }
884 
885 //----------------------------------------------------------------------------
886 // Change the ViewAngle (for perspective) or the ParallelScale (for parallel)
887 // so that more or less of a scene occupies the viewport.  A value > 1 is a
888 // zoom-in. A value < 1 is a zoom-out.
Zoom(double amount)889 void vtkCamera::Zoom(double amount)
890 {
891   if (amount <= 0.0)
892   {
893     return;
894   }
895 
896   if (this->ParallelProjection)
897   {
898     this->SetParallelScale(this->ParallelScale/amount);
899   }
900   else
901   {
902     this->SetViewAngle(this->ViewAngle/amount);
903   }
904 }
905 
906 //----------------------------------------------------------------------------
SetClippingRange(double nearz,double farz)907 void vtkCamera::SetClippingRange(double nearz, double farz)
908 {
909   double thickness;
910 
911   // check the order
912   if ( nearz > farz )
913   {
914     vtkDebugMacro(<< " Front and back clipping range reversed");
915     double temp = nearz;
916     nearz = farz;
917     farz = temp;
918   }
919 
920   thickness = farz - nearz;
921 
922   // thickness should be greater than 1e-20
923   if (thickness < 1e-20)
924   {
925     thickness = 1e-20;
926     vtkDebugMacro(<< " ClippingRange thickness is set to minimum.");
927 
928     // set back plane
929     farz = nearz + thickness;
930   }
931 
932   if (nearz == this->ClippingRange[0] &&
933       farz == this->ClippingRange[1] &&
934       this->Thickness == thickness)
935   {
936     return;
937   }
938 
939   this->ClippingRange[0] = nearz;
940   this->ClippingRange[1] = farz;
941   this->Thickness = thickness;
942 
943   vtkDebugMacro(<< " ClippingRange set to ( " <<  this->ClippingRange[0]
944     << ", "  << this->ClippingRange[1] << ")");
945 
946   this->Modified();
947 }
948 
949 //----------------------------------------------------------------------------
950 // Set the distance between clipping planes.
951 // This method adjusts the back clipping plane to the specified thickness
952 // behind the front clipping plane
SetThickness(double s)953 void vtkCamera::SetThickness(double s)
954 {
955   if (this->Thickness == s)
956   {
957     return;
958   }
959 
960   this->Thickness = s;
961 
962   // thickness should be greater than 1e-20
963   if (this->Thickness < 1e-20)
964   {
965     this->Thickness = 1e-20;
966     vtkDebugMacro(<< " ClippingRange thickness is set to minimum.");
967   }
968 
969   // set back plane
970   this->ClippingRange[1] = this->ClippingRange[0] + this->Thickness;
971 
972   vtkDebugMacro(<< " ClippingRange set to ( " <<  this->ClippingRange[0]
973     << ", " << this->ClippingRange[1] << ")");
974 
975   this->Modified();
976 }
977 
978 //----------------------------------------------------------------------------
SetWindowCenter(double x,double y)979 void vtkCamera::SetWindowCenter(double x, double y)
980 {
981   if (this->WindowCenter[0] != x || this->WindowCenter[1] != y)
982   {
983     this->Modified();
984     this->ViewingRaysModified();
985     this->WindowCenter[0] = x;
986     this->WindowCenter[1] = y;
987   }
988 }
989 
990 //----------------------------------------------------------------------------
SetObliqueAngles(double alpha,double beta)991 void vtkCamera::SetObliqueAngles(double alpha, double beta)
992 {
993   alpha = vtkMath::RadiansFromDegrees( alpha );
994   beta = vtkMath::RadiansFromDegrees( beta );
995 
996   double cotbeta = cos( beta ) / sin( beta );
997   double dxdz = cos( alpha ) * cotbeta;
998   double dydz = sin( alpha ) * cotbeta;
999 
1000   this->SetViewShear( dxdz, dydz, 1.0 );
1001 }
1002 
1003 //----------------------------------------------------------------------------
1004 // Set the shear transform of the viewing frustum.  Parameters are
1005 // dx/dz, dy/dz, and center.  center is a factor that describes where
1006 // to shear around. The distance dshear from the camera where
1007 // no shear occurs is given by (dshear = center * FocalDistance).
1008 //
SetViewShear(double dxdz,double dydz,double center)1009 void vtkCamera::SetViewShear(double dxdz, double dydz, double center)
1010 {
1011   if(dxdz   != this->ViewShear[0] ||
1012      dydz   != this->ViewShear[1] ||
1013      center != this->ViewShear[2])
1014   {
1015     this->Modified();
1016     this->ViewingRaysModified();
1017 
1018     this->ViewShear[0] = dxdz;
1019     this->ViewShear[1] = dydz;
1020     this->ViewShear[2] = center;
1021 
1022     this->ComputeViewPlaneNormal();
1023   }
1024 }
1025 //----------------------------------------------------------------------------
1026 
SetViewShear(double d[3])1027 void vtkCamera::SetViewShear(double d[3])
1028 {
1029   this->SetViewShear(d[0], d[1], d[2]);
1030 }
1031 
1032 //----------------------------------------------------------------------------
1033 // Compute the projection transform matrix. This is used in converting
1034 // between view and world coordinates.
ComputeProjectionTransform(double aspect,double nearz,double farz)1035 void vtkCamera::ComputeProjectionTransform(double aspect,
1036                                            double nearz, double farz)
1037 {
1038   this->ProjectionTransform->Identity();
1039 
1040   // apply user defined transform last if there is one
1041   if ( this->UserTransform )
1042   {
1043     this->ProjectionTransform->Concatenate( this->UserTransform->GetMatrix() );
1044   }
1045 
1046   if (this->UseExplicitProjectionTransformMatrix)
1047   {
1048     assert(this->ExplicitProjectionTransformMatrix != nullptr);
1049     this->ProjectionTransform->Concatenate(
1050           this->ExplicitProjectionTransformMatrix);
1051     return;
1052   }
1053 
1054   // adjust Z-buffer range
1055   this->ProjectionTransform->AdjustZBuffer( -1, +1, nearz, farz );
1056 
1057   if ( this->ParallelProjection )
1058   {
1059     // set up a rectangular parallelipiped
1060 
1061     double width = this->ParallelScale * aspect;
1062     double height = this->ParallelScale;
1063 
1064     double xmin = ( this->WindowCenter[0] - 1.0 ) * width;
1065     double xmax = ( this->WindowCenter[0] + 1.0 ) * width;
1066     double ymin = ( this->WindowCenter[1] - 1.0 ) * height;
1067     double ymax = ( this->WindowCenter[1] + 1.0 ) * height;
1068 
1069     this->ProjectionTransform->Ortho( xmin, xmax, ymin, ymax,
1070                                       this->ClippingRange[0],
1071                                       this->ClippingRange[1] );
1072   }
1073   else if(this->UseOffAxisProjection)
1074   {
1075     this->ComputeOffAxisProjectionFrustum();
1076   }
1077   else
1078   {
1079     // set up a perspective frustum
1080 
1081     double tmp = tan( vtkMath::RadiansFromDegrees( this->ViewAngle ) / 2. );
1082     double width;
1083     double height;
1084     if ( this->UseHorizontalViewAngle )
1085     {
1086       width = this->ClippingRange[0] * tmp;
1087       height = this->ClippingRange[0] * tmp / aspect;
1088     }
1089     else
1090     {
1091       width = this->ClippingRange[0] * tmp * aspect;
1092       height = this->ClippingRange[0] * tmp;
1093     }
1094 
1095     double xmin = ( this->WindowCenter[0] - 1.0 ) * width;
1096     double xmax = ( this->WindowCenter[0] + 1.0 ) * width;
1097     double ymin = ( this->WindowCenter[1] - 1.0 ) * height;
1098     double ymax = ( this->WindowCenter[1] + 1.0 ) * height;
1099 
1100     this->ProjectionTransform->Frustum( xmin, xmax, ymin, ymax,
1101                                         this->ClippingRange[0],
1102                                         this->ClippingRange[1] );
1103   }
1104 
1105   if ( this->Stereo && !this->UseOffAxisProjection)
1106   {
1107     // set up a shear for stereo views
1108     if ( this->LeftEye )
1109     {
1110       this->ProjectionTransform->Stereo( -this->EyeAngle/2,
1111                                           this->Distance );
1112     }
1113     else
1114     {
1115       this->ProjectionTransform->Stereo( +this->EyeAngle/2,
1116                                           this->Distance );
1117     }
1118   }
1119 
1120   if ( this->ViewShear[0] != 0.0 || this->ViewShear[1] != 0.0 )
1121   {
1122     this->ProjectionTransform->Shear( this->ViewShear[0],
1123                                       this->ViewShear[1],
1124                                       this->ViewShear[2] * this->Distance );
1125   }
1126 
1127 }
1128 
1129 //----------------------------------------------------------------------------
1130 // Return the projection transform matrix. See ComputeProjectionTransform.
GetProjectionTransformMatrix(vtkRenderer * ren)1131 vtkMatrix4x4 *vtkCamera::GetProjectionTransformMatrix(vtkRenderer *ren)
1132 {
1133   double aspect[2];
1134   int  lowerLeft[2];
1135   int usize, vsize;
1136   vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
1137 
1138   ren->GetTiledSizeAndOrigin(&usize, &vsize, lowerLeft, lowerLeft+1);
1139 
1140   // some renderer subclasses may have more complicated computations for the
1141   // aspect ratio. So take that into account by computing the difference
1142   // between our simple aspect ratio and what the actual renderer is reporting.
1143   ren->ComputeAspect();
1144   ren->GetAspect(aspect);
1145   double aspect2[2];
1146   ren->vtkViewport::ComputeAspect();
1147   ren->vtkViewport::GetAspect(aspect2);
1148   double aspectModification = aspect[0] * aspect2[1] / (aspect[1] * aspect2[0]);
1149 
1150   if (usize && vsize)
1151   {
1152     matrix->DeepCopy(this->GetProjectionTransformMatrix(
1153                        aspectModification * usize / vsize, -1, 1));
1154     matrix->Transpose();
1155   }
1156 
1157   return matrix;
1158 }
1159 
1160 //----------------------------------------------------------------------------
1161 // Return the projection transform matrix. See ComputeProjectionTransform.
GetProjectionTransformMatrix(double aspect,double nearz,double farz)1162 vtkMatrix4x4 *vtkCamera::GetProjectionTransformMatrix(double aspect,
1163                                                       double nearz,
1164                                                       double farz)
1165 {
1166   this->ComputeProjectionTransform(aspect, nearz, farz);
1167 
1168   // return the transform
1169   return this->ProjectionTransform->GetMatrix();
1170 }
1171 
1172 //----------------------------------------------------------------------------
1173 // Return the projection transform object. See ComputeProjectionTransform.
GetProjectionTransformObject(double aspect,double nearz,double farz)1174 vtkPerspectiveTransform *vtkCamera::GetProjectionTransformObject(double aspect,
1175                                                                  double nearz,
1176                                                                  double farz)
1177 {
1178   this->ComputeProjectionTransform(aspect, nearz, farz);
1179 
1180   // return the transform
1181   return this->ProjectionTransform;
1182 }
1183 
1184 //----------------------------------------------------------------------------
1185 // Return the projection transform matrix. See ComputeProjectionTransform.
GetCompositeProjectionTransformMatrix(double aspect,double nearz,double farz)1186 vtkMatrix4x4 *vtkCamera::GetCompositeProjectionTransformMatrix(double aspect,
1187                                                                double nearz,
1188                                                                double farz)
1189 {
1190   // turn off stereo, the CompositeProjectionTransformMatrix is used for
1191   // picking, not for rendering.
1192   int stereo = this->Stereo;
1193   this->Stereo = 0;
1194 
1195   this->Transform->Identity();
1196   this->Transform->Concatenate(this->GetProjectionTransformMatrix(aspect,
1197                                                                   nearz,
1198                                                                   farz));
1199   this->Transform->Concatenate(this->GetViewTransformMatrix());
1200 
1201   this->Stereo = stereo;
1202 
1203   // return the transform
1204   return this->Transform->GetMatrix();
1205 }
1206 
1207 //----------------------------------------------------------------------------
1208 // Return the attached light transform matrix.
GetCameraLightTransformMatrix()1209 vtkMatrix4x4 *vtkCamera::GetCameraLightTransformMatrix()
1210 {
1211   // return the transform
1212   return this->CameraLightTransform->GetMatrix();
1213 }
1214 
1215 
1216 //----------------------------------------------------------------------------
ComputeViewPlaneNormal()1217 void vtkCamera::ComputeViewPlaneNormal()
1218 {
1219   if (this->ViewShear[0] != 0.0 || this->ViewShear[1] != 0.0)
1220   {
1221     // set the VPN in camera coordinates
1222     this->ViewPlaneNormal[0] = this->ViewShear[0];
1223     this->ViewPlaneNormal[1] = this->ViewShear[1];
1224     this->ViewPlaneNormal[2] = 1.0;
1225     // transform the VPN to world coordinates using inverse of view transform
1226     this->ViewTransform->GetLinearInverse()->TransformNormal(
1227                                               this->ViewPlaneNormal,
1228                                               this->ViewPlaneNormal);
1229   }
1230   else
1231   {
1232     // VPN is -DOP
1233     this->ViewPlaneNormal[0] = -this->DirectionOfProjection[0];
1234     this->ViewPlaneNormal[1] = -this->DirectionOfProjection[1];
1235     this->ViewPlaneNormal[2] = -this->DirectionOfProjection[2];
1236   }
1237 }
1238 
1239 //----------------------------------------------------------------------------
1240 // Return the 6 planes (Ax + By + Cz + D = 0) that bound
1241 // the view frustum.
GetFrustumPlanes(double aspect,double planes[24])1242 void vtkCamera::GetFrustumPlanes(double aspect, double planes[24])
1243 {
1244   int i;
1245   double f, normals[6][4], matrix[4][4];
1246 
1247   // set up the normals
1248   for (i = 0; i < 6; i++)
1249   {
1250     normals[i][0] = 0.0;
1251     normals[i][1] = 0.0;
1252     normals[i][2] = 0.0;
1253     normals[i][3] = 1.0;
1254     // if i is even set to -1, if odd set to +1
1255     normals[i][i/2] = 1 - (i%2)*2;
1256   }
1257 
1258   // get the composite perspective matrix
1259   vtkMatrix4x4::DeepCopy(
1260     *matrix,
1261     this->GetCompositeProjectionTransformMatrix(aspect,-1,+1));
1262 
1263   // transpose the matrix for use with normals
1264   vtkMatrix4x4::Transpose(*matrix,*matrix);
1265 
1266   // transform the normals to world coordinates
1267   for (i = 0; i < 6; i++)
1268   {
1269     vtkMatrix4x4::MultiplyPoint(*matrix,normals[i],normals[i]);
1270 
1271     f = 1.0/sqrt(normals[i][0]*normals[i][0] +
1272                  normals[i][1]*normals[i][1] +
1273                  normals[i][2]*normals[i][2]);
1274 
1275     planes[4*i + 0] = normals[i][0]*f;
1276     planes[4*i + 1] = normals[i][1]*f;
1277     planes[4*i + 2] = normals[i][2]*f;
1278     planes[4*i + 3] = normals[i][3]*f;
1279   }
1280 }
1281 
1282 //----------------------------------------------------------------------------
GetViewingRaysMTime()1283 vtkMTimeType vtkCamera::GetViewingRaysMTime()
1284 {
1285   return this->ViewingRaysMTime.GetMTime();
1286 }
1287 
1288 //----------------------------------------------------------------------------
ViewingRaysModified()1289 void vtkCamera::ViewingRaysModified()
1290 {
1291   this->ViewingRaysMTime.Modified();
1292 }
1293 
1294 // ----------------------------------------------------------------------------
1295 // Description:
1296 // Copy the properties of `source' into `this'.
1297 // Copy pointers of matrices.
1298 // \pre source_exists!=0
1299 // \pre not_this: source!=this
ShallowCopy(vtkCamera * source)1300 void vtkCamera::ShallowCopy(vtkCamera *source)
1301 {
1302   assert("pre: source_exists" && source!=nullptr);
1303   assert("pre: not_this" && source!=this);
1304 
1305   this->PartialCopy(source);
1306 
1307   // Shallow copy of matrices:
1308   if(this->UserTransform!=nullptr)
1309   {
1310     this->UserTransform->Delete();
1311   }
1312   this->UserTransform=source->UserTransform;
1313   if(this->UserTransform!=nullptr)
1314   {
1315     this->UserTransform->Register(this);
1316   }
1317   if(this->UserViewTransform!=nullptr)
1318   {
1319     this->UserViewTransform->Delete();
1320   }
1321   this->UserViewTransform=source->UserViewTransform;
1322   if(this->UserViewTransform!=nullptr)
1323   {
1324     this->UserViewTransform->Register(this);
1325   }
1326 
1327   if(this->ViewTransform!=nullptr)
1328   {
1329     this->ViewTransform->Delete();
1330   }
1331   this->ViewTransform=source->ViewTransform;
1332   if(this->ViewTransform!=nullptr)
1333   {
1334     this->ViewTransform->Register(this);
1335   }
1336 
1337   if(this->ProjectionTransform!=nullptr)
1338   {
1339     this->ProjectionTransform->Delete();
1340   }
1341   this->ProjectionTransform=source->ProjectionTransform;
1342   if(this->ProjectionTransform!=nullptr)
1343   {
1344     this->ProjectionTransform->Register(this);
1345   }
1346 
1347   if(this->Transform!=nullptr)
1348   {
1349     this->Transform->Delete();
1350   }
1351   this->Transform=source->Transform;
1352   if(this->Transform!=nullptr)
1353   {
1354     this->Transform->Register(this);
1355   }
1356 
1357   if(this->CameraLightTransform!=nullptr)
1358   {
1359     this->CameraLightTransform->Delete();
1360   }
1361   this->CameraLightTransform=source->CameraLightTransform;
1362   if(this->CameraLightTransform!=nullptr)
1363   {
1364     this->CameraLightTransform->Register(this);
1365   }
1366 
1367   if (this->EyeTransformMatrix != nullptr)
1368   {
1369     this->EyeTransformMatrix->Delete();
1370   }
1371   this->EyeTransformMatrix = source->EyeTransformMatrix;
1372   if (this->EyeTransformMatrix!=nullptr)
1373   {
1374     this->EyeTransformMatrix->Register(this);
1375   }
1376 
1377   if (this->WorldToScreenMatrix != nullptr)
1378   {
1379     this->WorldToScreenMatrix->Delete();
1380   }
1381   this->WorldToScreenMatrix = source->WorldToScreenMatrix;
1382   if (this->WorldToScreenMatrix!=nullptr)
1383   {
1384     this->WorldToScreenMatrix->Register(this);
1385   }
1386 
1387   if (this->ModelTransformMatrix != nullptr)
1388   {
1389     this->ModelTransformMatrix->Delete();
1390   }
1391   this->ModelTransformMatrix = source->ModelTransformMatrix;
1392   if (this->ModelTransformMatrix!=nullptr)
1393   {
1394     this->ModelTransformMatrix->Register(this);
1395   }
1396 
1397   if (this->ModelViewTransform != nullptr)
1398   {
1399     this->ModelViewTransform->Delete();
1400   }
1401   this->ModelViewTransform = source->ModelViewTransform;
1402   if (this->ModelViewTransform!=nullptr)
1403   {
1404     this->ModelViewTransform->Register(this);
1405   }
1406 }
1407 
1408 // ----------------------------------------------------------------------------
1409 // Description:
1410 // Copy the properties of `source' into `this'.
1411 // Copy the contents of the matrices.
1412 // \pre source_exists!=0
1413 // \pre not_this: source!=this
DeepCopy(vtkCamera * source)1414 void vtkCamera::DeepCopy(vtkCamera *source)
1415 {
1416   assert("pre: source_exists" && source!=nullptr);
1417   assert("pre: not_this" && source!=this);
1418 
1419   this->PartialCopy(source);
1420 
1421   // Deep copy the matrices:
1422   if(source->UserTransform==nullptr)
1423   {
1424     if(this->UserTransform!=nullptr)
1425     {
1426       this->UserTransform->UnRegister(this);
1427       this->UserTransform=nullptr;
1428     }
1429   }
1430   else
1431   {
1432     if(this->UserTransform==nullptr)
1433     {
1434       this->UserTransform=
1435         static_cast<vtkHomogeneousTransform *>(
1436           source->UserTransform->MakeTransform());
1437     }
1438     this->UserTransform->DeepCopy(source->UserTransform);
1439   }
1440 
1441   if(source->UserViewTransform==nullptr)
1442   {
1443     if(this->UserViewTransform!=nullptr)
1444     {
1445       this->UserViewTransform->UnRegister(this);
1446       this->UserViewTransform=nullptr;
1447     }
1448   }
1449   else
1450   {
1451     if(this->UserViewTransform==nullptr)
1452     {
1453       this->UserViewTransform=
1454         static_cast<vtkHomogeneousTransform *>(
1455           source->UserViewTransform->MakeTransform());
1456     }
1457     this->UserViewTransform->DeepCopy(source->UserViewTransform);
1458   }
1459 
1460   if(source->ViewTransform==nullptr)
1461   {
1462     if(this->ViewTransform!=nullptr)
1463     {
1464       this->ViewTransform->UnRegister(this);
1465       this->ViewTransform=nullptr;
1466     }
1467   }
1468   else
1469   {
1470     if(this->ViewTransform==nullptr)
1471     {
1472       this->ViewTransform=
1473         static_cast<vtkTransform *>(
1474           source->ViewTransform->MakeTransform());
1475     }
1476     this->ViewTransform->DeepCopy(source->ViewTransform);
1477   }
1478 
1479   if(source->ProjectionTransform==nullptr)
1480   {
1481     if(this->ProjectionTransform!=nullptr)
1482     {
1483       this->ProjectionTransform->UnRegister(this);
1484       this->ProjectionTransform=nullptr;
1485     }
1486   }
1487   else
1488   {
1489     if(this->ProjectionTransform==nullptr)
1490     {
1491       this->ProjectionTransform=
1492         static_cast<vtkPerspectiveTransform *>(
1493           source->ProjectionTransform->MakeTransform());
1494     }
1495     this->ProjectionTransform->DeepCopy(source->ProjectionTransform);
1496   }
1497 
1498   if(source->Transform==nullptr)
1499   {
1500     if(this->Transform!=nullptr)
1501     {
1502       this->Transform->UnRegister(this);
1503       this->Transform=nullptr;
1504     }
1505   }
1506   else
1507   {
1508     if(this->Transform==nullptr)
1509     {
1510       this->Transform=
1511         static_cast<vtkPerspectiveTransform *>(
1512           source->Transform->MakeTransform());
1513     }
1514     this->Transform->DeepCopy(source->Transform);
1515   }
1516 
1517   if(source->CameraLightTransform==nullptr)
1518   {
1519     if(this->CameraLightTransform!=nullptr)
1520     {
1521       this->CameraLightTransform->UnRegister(this);
1522       this->CameraLightTransform=nullptr;
1523     }
1524   }
1525   else
1526   {
1527     if(this->CameraLightTransform==nullptr)
1528     {
1529       this->CameraLightTransform=
1530         static_cast<vtkTransform *>(
1531           source->CameraLightTransform->MakeTransform());
1532     }
1533     this->CameraLightTransform->DeepCopy(source->CameraLightTransform);
1534   }
1535 
1536   if(source->ModelViewTransform==nullptr)
1537   {
1538     if(this->ModelViewTransform!=nullptr)
1539     {
1540       this->ModelViewTransform->UnRegister(this);
1541       this->ModelViewTransform=nullptr;
1542     }
1543   }
1544   else
1545   {
1546     if(this->ModelViewTransform==nullptr)
1547     {
1548       this->ModelViewTransform=
1549         static_cast<vtkTransform *>(
1550           source->ModelViewTransform->MakeTransform());
1551     }
1552     this->ModelViewTransform->DeepCopy(source->ModelViewTransform);
1553   }
1554 
1555   if(source->ModelTransformMatrix == nullptr)
1556   {
1557     if(this->ModelTransformMatrix != nullptr)
1558     {
1559       this->ModelTransformMatrix->UnRegister(this);
1560       this->ModelTransformMatrix = nullptr;
1561     }
1562   }
1563   else
1564   {
1565     if(this->ModelTransformMatrix==nullptr)
1566     {
1567       this->ModelTransformMatrix=
1568         static_cast<vtkMatrix4x4 *>(
1569           source->ModelTransformMatrix->NewInstance());
1570     }
1571     this->ModelTransformMatrix->DeepCopy(source->ModelTransformMatrix);
1572   }
1573 
1574   if(source->EyeTransformMatrix == nullptr)
1575   {
1576     if(this->EyeTransformMatrix != nullptr)
1577     {
1578       this->EyeTransformMatrix->UnRegister(this);
1579       this->EyeTransformMatrix = nullptr;
1580     }
1581   }
1582   else
1583   {
1584     if(this->EyeTransformMatrix==nullptr)
1585     {
1586       this->EyeTransformMatrix=
1587         static_cast<vtkMatrix4x4 *>(
1588           source->EyeTransformMatrix->NewInstance());
1589     }
1590     this->EyeTransformMatrix->DeepCopy(source->EyeTransformMatrix);
1591   }
1592 
1593   if(source->WorldToScreenMatrix == nullptr)
1594   {
1595     if(this->WorldToScreenMatrix != nullptr)
1596     {
1597       this->WorldToScreenMatrix->UnRegister(this);
1598       this->WorldToScreenMatrix = nullptr;
1599     }
1600   }
1601   else
1602   {
1603     if(this->WorldToScreenMatrix==nullptr)
1604     {
1605       this->WorldToScreenMatrix=
1606         static_cast<vtkMatrix4x4 *>(
1607           source->WorldToScreenMatrix->NewInstance());
1608     }
1609     this->WorldToScreenMatrix->DeepCopy(source->WorldToScreenMatrix);
1610   }
1611 }
1612 
1613 // ----------------------------------------------------------------------------
1614 // Description:
1615 // Copy the ivars. Do nothing for the matrices.
1616 // Called by ShallowCopy() and DeepCopy()
1617 // \pre source_exists!=0
1618 // \pre not_this: source!=this
PartialCopy(vtkCamera * source)1619 void vtkCamera::PartialCopy(vtkCamera *source)
1620 {
1621   assert("pre: source_exists" && source!=nullptr);
1622   assert("pre: not_this" && source!=this);
1623 
1624   int i;
1625 
1626   i=0;
1627   while(i<2)
1628   {
1629     this->WindowCenter[i]=source->WindowCenter[i];
1630     this->ObliqueAngles[i]=source->ObliqueAngles[i];
1631     this->ClippingRange[i]=source->ClippingRange[i];
1632     ++i;
1633   }
1634   i=0;
1635   while(i<3)
1636   {
1637     this->FocalPoint[i]=source->FocalPoint[i];
1638     this->Position[i]=source->Position[i];
1639     this->ViewUp[i]=source->ViewUp[i];
1640     this->DirectionOfProjection[i]=source->DirectionOfProjection[i];
1641     this->ViewPlaneNormal[i]=source->ViewPlaneNormal[i];
1642     this->ViewShear[i]=source->ViewShear[i];
1643 
1644     this->ScreenBottomLeft[i]=source->ScreenBottomLeft[i];
1645     this->ScreenBottomRight[i]=source->ScreenBottomRight[i];
1646     this->ScreenTopRight[i]=source->ScreenTopRight[i];
1647     ++i;
1648   }
1649 
1650   this->ViewAngle=source->ViewAngle;
1651   this->EyeAngle=source->EyeAngle;
1652   this->ParallelProjection=source->ParallelProjection;
1653   this->ParallelScale=source->ParallelScale;
1654   this->Stereo=source->Stereo;
1655   this->LeftEye=source->LeftEye;
1656   this->Thickness=source->Thickness;
1657   this->Distance=source->Distance;
1658   this->UseHorizontalViewAngle=source->UseHorizontalViewAngle;
1659   this->UseOffAxisProjection=source->UseOffAxisProjection;
1660 
1661   this->FocalDisk=source->FocalDisk;
1662   this->EyeSeparation=source->EyeSeparation;
1663   this->WorldToScreenMatrixMTime=source->WorldToScreenMatrixMTime;
1664 
1665   this->ViewingRaysMTime=source->ViewingRaysMTime;
1666 }
1667 
1668 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1669 void vtkCamera::PrintSelf(ostream& os, vtkIndent indent)
1670 {
1671   this->Superclass::PrintSelf(os,indent);
1672 
1673   os << indent << "ClippingRange: (" << this->ClippingRange[0] << ", "
1674      << this->ClippingRange[1] << ")\n";
1675   os << indent << "DirectionOfProjection: (" << this->DirectionOfProjection[0]
1676      << ", " << this->DirectionOfProjection[1]
1677      << ", " << this->DirectionOfProjection[2] << ")\n";
1678   os << indent << "Distance: " << this->Distance << "\n";
1679   os << indent << "EyeAngle: " << this->EyeAngle << "\n";
1680   os << indent << "FocalDisk: " << this->FocalDisk << "\n";
1681   os << indent << "FocalPoint: (" << this->FocalPoint[0] << ", "
1682      << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")\n";
1683   os << indent << "ViewShear: (" << this->ViewShear[0]
1684      << ", " << this->ViewShear[1]
1685      << ", " << this->ViewShear[2] << ")\n";
1686   os << indent << "ParallelProjection: " <<
1687     (this->ParallelProjection ? "On\n" : "Off\n");
1688   os << indent << "ParallelScale: " << this->ParallelScale << "\n";
1689   os << indent << "Position: (" << this->Position[0] << ", "
1690      << this->Position[1] << ", " << this->Position[2] << ")\n";
1691   os << indent << "Stereo: " << (this->Stereo ? "On\n" : "Off\n");
1692   os << indent << "Left Eye: " << this->LeftEye << endl;
1693   os << indent << "Thickness: " << this->Thickness << "\n";
1694   os << indent << "ViewAngle: " << this->ViewAngle << "\n";
1695   os << indent << "UseHorizontalViewAngle: " << this->UseHorizontalViewAngle
1696      << "\n";
1697   os << indent << "UserTransform: ";
1698   if (this->UserTransform)
1699   {
1700     os << this->UserTransform << "\n";
1701   }
1702   else
1703   {
1704     os << "(none)\n";
1705   }
1706   if (this->UserViewTransform)
1707   {
1708     os << this->UserViewTransform << "\n";
1709   }
1710   else
1711   {
1712     os << "(none)\n";
1713   }
1714   os << indent << "FreezeFocalPoint: ";
1715   if( this->FreezeFocalPoint )
1716   {
1717     os << this->FreezeFocalPoint << "\n";
1718   }
1719   else
1720   {
1721     os << "(none)\n";
1722   }
1723   os << indent << "ViewPlaneNormal: (" << this->ViewPlaneNormal[0]
1724      << ", " << this->ViewPlaneNormal[1]
1725      << ", " << this->ViewPlaneNormal[2] << ")\n";
1726   os << indent << "ViewUp: (" << this->ViewUp[0] << ", "
1727      << this->ViewUp[1] << ", " << this->ViewUp[2] << ")\n";
1728   os << indent << "WindowCenter: (" << this->WindowCenter[0] << ", "
1729      << this->WindowCenter[1] << ")\n";
1730 
1731   os << indent << "UseOffAxisProjection: (" << this->UseOffAxisProjection
1732      << ")\n";
1733 
1734   os << indent << "ScreenBottomLeft: (" << this->ScreenBottomLeft[0]
1735      << ", " << this->ScreenBottomLeft[1] << ", " << this->ScreenBottomLeft[2]
1736      << ")\n";
1737 
1738   os << indent << "ScreenBottomRight: (" << this->ScreenBottomRight[0]
1739      << ", " << this->ScreenBottomRight[1] << ", " << this->ScreenBottomRight[2]
1740      << ")\n";
1741 
1742   os << indent << "ScreenTopRight: (" << this->ScreenTopRight[0]
1743      << ", " << this->ScreenTopRight[1] << ", " << this->ScreenTopRight[2]
1744      << ")\n";
1745 
1746   os << indent << "EyeSeparation: (" << this->EyeSeparation
1747      << ")\n";
1748 
1749   os << indent << "WorldToScreenMatrix: (" << this->WorldToScreenMatrix << "\n";
1750   this->WorldToScreenMatrix->PrintSelf(os, indent.GetNextIndent());
1751   os << indent << ")\n";
1752 
1753   os << indent << "EyeTransformMatrix: (" << this->EyeTransformMatrix << "\n";
1754   this->EyeTransformMatrix->PrintSelf(os, indent.GetNextIndent());
1755   os << indent << ")\n";
1756 
1757   os << indent << "ModelTransformMatrix: (" << this->ModelTransformMatrix << "\n";
1758   this->ModelTransformMatrix->PrintSelf(os, indent.GetNextIndent());
1759   os << indent << ")\n";
1760 
1761   os << indent << "ProjectionTransform: (" << this->ProjectionTransform << "\n";
1762   this->ProjectionTransform->PrintSelf(os, indent.GetNextIndent());
1763   os << indent << ")\n";
1764 }
1765 
1766 //-----------------------------------------------------------------------------
SetEyePosition(double eyePosition[3])1767 void vtkCamera::SetEyePosition(double eyePosition[3])
1768 {
1769   if(!eyePosition)
1770   {
1771     vtkErrorMacro(<< "ERROR: Invalid or nullptr eye position\n");
1772     return;
1773   }
1774 
1775   this->EyeTransformMatrix->SetElement(0, 3, eyePosition[0]);
1776   this->EyeTransformMatrix->SetElement(1, 3, eyePosition[1]);
1777   this->EyeTransformMatrix->SetElement(2, 3, eyePosition[2]);
1778 
1779   this->Modified();
1780 }
1781 
1782 //-----------------------------------------------------------------------------
GetEyePosition(double eyePosition[3])1783 void vtkCamera::GetEyePosition(double eyePosition[3])
1784 {
1785   if(!eyePosition)
1786   {
1787     vtkErrorMacro(<< "ERROR: Invalid or nullptr eye position\n");
1788     return;
1789   }
1790 
1791   eyePosition[0] = this->EyeTransformMatrix->GetElement(0, 3);
1792   eyePosition[1] = this->EyeTransformMatrix->GetElement(1, 3);
1793   eyePosition[2] = this->EyeTransformMatrix->GetElement(2, 3);
1794 }
1795 
1796 //-----------------------------------------------------------------------------
GetEyePlaneNormal(double normal[3])1797 void vtkCamera::GetEyePlaneNormal(double normal[3])
1798 {
1799   if(!normal)
1800   {
1801     vtkErrorMacro(<< "ERROR: Invalid or nullptr normal\n");
1802     return;
1803   }
1804 
1805   // Homogeneous normal.
1806   double localNormal[4];
1807 
1808   // Get the normal from the screen orientation.
1809   localNormal[0] = this->WorldToScreenMatrix->GetElement(2, 0);
1810   localNormal[1] = this->WorldToScreenMatrix->GetElement(2, 1);
1811   localNormal[2] = this->WorldToScreenMatrix->GetElement(2, 2);
1812   localNormal[3] = 0.0;
1813 
1814   // Just to be sure.
1815   vtkMath::Normalize(localNormal);
1816 
1817   normal[0] = localNormal[0];
1818   normal[1] = localNormal[1];
1819   normal[2] = localNormal[2];
1820 }
1821 
1822 //-----------------------------------------------------------------------------
GetModelViewTransformMatrix()1823 vtkMatrix4x4 *vtkCamera::GetModelViewTransformMatrix()
1824 {
1825   this->ComputeModelViewMatrix();
1826 
1827   return this->ModelViewTransform->GetMatrix();
1828 }
1829 
1830 //-----------------------------------------------------------------------------
GetModelViewTransformObject()1831 vtkTransform *vtkCamera::GetModelViewTransformObject()
1832 {
1833   this->ComputeModelViewMatrix();
1834 
1835   return this->ModelViewTransform;
1836 }
1837 
1838 //-----------------------------------------------------------------------------
GetViewTransformMatrix()1839 vtkMatrix4x4 *vtkCamera::GetViewTransformMatrix()
1840 {
1841   return this->GetModelViewTransformMatrix();
1842 }
1843 
1844 //-----------------------------------------------------------------------------
GetViewTransformObject()1845 vtkTransform *vtkCamera::GetViewTransformObject()
1846 {
1847   return this->GetModelViewTransformObject();
1848 }
1849 
1850 //-----------------------------------------------------------------------------
GetOrientation()1851 double *vtkCamera::GetOrientation()
1852 { return this->ViewTransform->GetOrientation(); };
1853 
1854 //-----------------------------------------------------------------------------
GetOrientationWXYZ()1855 double *vtkCamera::GetOrientationWXYZ()
1856 { return this->ViewTransform->GetOrientationWXYZ(); };
1857 
1858 // ----------------------------------------------------------------------------
SetEyeTransformMatrix(const double elements[16])1859 void vtkCamera::SetEyeTransformMatrix(const double elements[16])
1860 {
1861   this->EyeTransformMatrix->Element[0][0] = elements[0];
1862   this->EyeTransformMatrix->Element[0][1] = elements[1];
1863   this->EyeTransformMatrix->Element[0][2] = elements[2];
1864   this->EyeTransformMatrix->Element[0][3] = elements[3];
1865 
1866   this->EyeTransformMatrix->Element[1][0] = elements[4];
1867   this->EyeTransformMatrix->Element[1][1] = elements[5];
1868   this->EyeTransformMatrix->Element[1][2] = elements[6];
1869   this->EyeTransformMatrix->Element[1][3] = elements[7];
1870 
1871   this->EyeTransformMatrix->Element[2][0] = elements[8];
1872   this->EyeTransformMatrix->Element[2][1] = elements[9];
1873   this->EyeTransformMatrix->Element[2][2] = elements[10];
1874   this->EyeTransformMatrix->Element[2][3] = elements[11];
1875 
1876   this->EyeTransformMatrix->Element[3][0] = elements[12];
1877   this->EyeTransformMatrix->Element[3][1] = elements[13];
1878   this->EyeTransformMatrix->Element[3][2] = elements[14];
1879   this->EyeTransformMatrix->Element[3][3] = elements[15];
1880   this->Modified();
1881 }
1882 
1883 // ----------------------------------------------------------------------------
SetModelTransformMatrix(const double elements[16])1884 void vtkCamera::SetModelTransformMatrix(const double elements[16])
1885 {
1886   this->ModelTransformMatrix->Element[0][0] = elements[0];
1887   this->ModelTransformMatrix->Element[0][1] = elements[1];
1888   this->ModelTransformMatrix->Element[0][2] = elements[2];
1889   this->ModelTransformMatrix->Element[0][3] = elements[3];
1890 
1891   this->ModelTransformMatrix->Element[1][0] = elements[4];
1892   this->ModelTransformMatrix->Element[1][1] = elements[5];
1893   this->ModelTransformMatrix->Element[1][2] = elements[6];
1894   this->ModelTransformMatrix->Element[1][3] = elements[7];
1895 
1896   this->ModelTransformMatrix->Element[2][0] = elements[8];
1897   this->ModelTransformMatrix->Element[2][1] = elements[9];
1898   this->ModelTransformMatrix->Element[2][2] = elements[10];
1899   this->ModelTransformMatrix->Element[2][3] = elements[11];
1900 
1901   this->ModelTransformMatrix->Element[3][0] = elements[12];
1902   this->ModelTransformMatrix->Element[3][1] = elements[13];
1903   this->ModelTransformMatrix->Element[3][2] = elements[14];
1904   this->ModelTransformMatrix->Element[3][3] = elements[15];
1905   this->Modified();
1906 }
1907