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