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