1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkProp3DFollower.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 "vtkProp3DFollower.h"
16
17 #include "vtkCamera.h"
18 #include "vtkMath.h"
19 #include "vtkMatrix4x4.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkProperty.h"
22 #include "vtkRenderer.h"
23 #include "vtkTexture.h"
24 #include "vtkTransform.h"
25 #include "vtkAssemblyPaths.h"
26
27 #include <cmath>
28
29 vtkStandardNewMacro(vtkProp3DFollower);
30
31 vtkCxxSetObjectMacro(vtkProp3DFollower,Camera,vtkCamera);
32
33 //----------------------------------------------------------------------
34 // Creates a follower with no camera set
vtkProp3DFollower()35 vtkProp3DFollower::vtkProp3DFollower()
36 {
37 this->Camera = nullptr;
38 this->Device = nullptr;
39
40 this->InternalMatrix = vtkMatrix4x4::New();
41 }
42
43 //----------------------------------------------------------------------
~vtkProp3DFollower()44 vtkProp3DFollower::~vtkProp3DFollower()
45 {
46 if (this->Camera)
47 {
48 this->Camera->UnRegister(this);
49 }
50
51 if (this->Device)
52 {
53 this->Device->Delete();
54 }
55
56 this->InternalMatrix->Delete();
57 }
58
59 //----------------------------------------------------------------------------
SetProp3D(vtkProp3D * prop)60 void vtkProp3DFollower::SetProp3D(vtkProp3D *prop)
61 {
62 if (this->Device != prop)
63 {
64 if ( this->Device != nullptr )
65 {
66 this->Device->Delete();
67 }
68 this->Device = prop;
69 if ( this->Device != nullptr )
70 {
71 this->Device->Register(this);
72 }
73 this->Modified();
74 }
75 }
76
77
78 //----------------------------------------------------------------------------
GetProp3D()79 vtkProp3D *vtkProp3DFollower::GetProp3D()
80 {
81 return this->Device;
82 }
83
84
85 //----------------------------------------------------------------------------
ComputeMatrix()86 void vtkProp3DFollower::ComputeMatrix()
87 {
88 if ( this->GetMTime() > this->MatrixMTime ||
89 (this->Camera && this->Camera->GetMTime() > this->MatrixMTime) )
90 {
91 this->GetOrientation();
92 this->Transform->Push();
93 this->Transform->Identity();
94 this->Transform->PostMultiply();
95
96 this->Transform->Translate(-this->Origin[0],
97 -this->Origin[1],
98 -this->Origin[2]);
99 // scale
100 this->Transform->Scale(this->Scale[0],
101 this->Scale[1],
102 this->Scale[2]);
103
104 // rotate
105 this->Transform->RotateY(this->Orientation[1]);
106 this->Transform->RotateX(this->Orientation[0]);
107 this->Transform->RotateZ(this->Orientation[2]);
108
109 if (this->Camera)
110 {
111 double *pos, *vup, distance;
112 double Rx[3], Ry[3], Rz[3];
113
114 vtkMatrix4x4 *matrix = this->InternalMatrix;
115 matrix->Identity();
116
117 // do the rotation
118 // first rotate y
119 pos = this->Camera->GetPosition();
120 vup = this->Camera->GetViewUp();
121
122 if (this->Camera->GetParallelProjection())
123 {
124 this->Camera->GetDirectionOfProjection(Rz);
125 Rz[0] = -Rz[0];
126 Rz[1] = -Rz[1];
127 Rz[2] = -Rz[2];
128 }
129 else
130 {
131 distance = sqrt(
132 (pos[0] - this->Position[0])*(pos[0] - this->Position[0]) +
133 (pos[1] - this->Position[1])*(pos[1] - this->Position[1]) +
134 (pos[2] - this->Position[2])*(pos[2] - this->Position[2]));
135 for (int i = 0; i < 3; i++)
136 {
137 Rz[i] = (pos[i] - this->Position[i])/distance;
138 }
139 }
140
141 //instead use the view right angle:
142 double dop[3], vur[3];
143 this->Camera->GetDirectionOfProjection(dop);
144
145 vtkMath::Cross(dop,vup,vur);
146 vtkMath::Normalize(vur);
147
148 vtkMath::Cross(Rz, vur, Ry);
149 vtkMath::Normalize(Ry);
150 vtkMath::Cross(Ry,Rz,Rx);
151
152 matrix->Element[0][0] = Rx[0];
153 matrix->Element[1][0] = Rx[1];
154 matrix->Element[2][0] = Rx[2];
155 matrix->Element[0][1] = Ry[0];
156 matrix->Element[1][1] = Ry[1];
157 matrix->Element[2][1] = Ry[2];
158 matrix->Element[0][2] = Rz[0];
159 matrix->Element[1][2] = Rz[1];
160 matrix->Element[2][2] = Rz[2];
161
162 this->Transform->Concatenate(matrix);
163 }
164
165 // translate to projection reference point PRP
166 // this is the camera's position blasted through
167 // the current matrix
168 this->Transform->Translate(this->Origin[0] + this->Position[0],
169 this->Origin[1] + this->Position[1],
170 this->Origin[2] + this->Position[2]);
171
172 // apply user defined matrix last if there is one
173 if (this->UserMatrix)
174 {
175 this->Transform->Concatenate(this->UserMatrix);
176 }
177
178 this->Transform->PreMultiply();
179 this->Transform->GetMatrix(this->Matrix);
180 this->MatrixMTime.Modified();
181 this->Transform->Pop();
182 }
183 }
184
185 //-----------------------------------------------------------------------------
GetBounds()186 double *vtkProp3DFollower::GetBounds()
187 {
188 if ( this->Device )
189 {
190 this->ComputeMatrix();
191 this->Device->SetUserMatrix(this->Matrix);
192 return this->Device->GetBounds();
193 }
194 else
195 {
196 return nullptr;
197 }
198 }
199
200
201 //-----------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * w)202 void vtkProp3DFollower::ReleaseGraphicsResources(vtkWindow *w)
203 {
204 if ( this->Device )
205 {
206 this->Device->ReleaseGraphicsResources(w);
207 }
208 }
209
210 //-----------------------------------------------------------------------------
211 // Description:
212 // Does this prop have some translucent polygonal geometry?
HasTranslucentPolygonalGeometry()213 vtkTypeBool vtkProp3DFollower::HasTranslucentPolygonalGeometry()
214 {
215 if ( this->Device )
216 {
217 return this->Device->HasTranslucentPolygonalGeometry();
218 }
219 else
220 {
221 return 0;
222 }
223 }
224
225 //----------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * vp)226 int vtkProp3DFollower::RenderOpaqueGeometry(vtkViewport *vp)
227 {
228 if ( this->Device )
229 {
230 this->ComputeMatrix();
231 this->Device->SetUserMatrix(this->Matrix);
232 if (this->GetPropertyKeys())
233 {
234 this->Device->SetPropertyKeys(this->GetPropertyKeys());
235 }
236 if (this->GetVisibility())
237 {
238 return this->Device->RenderOpaqueGeometry(vp);
239 }
240 }
241 return 0;
242 }
243
244 //-----------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport * vp)245 int vtkProp3DFollower::RenderTranslucentPolygonalGeometry(vtkViewport *vp)
246 {
247 if ( this->Device )
248 {
249 this->ComputeMatrix();
250 this->Device->SetUserMatrix(this->Matrix);
251 if (this->GetPropertyKeys())
252 {
253 this->Device->SetPropertyKeys(this->GetPropertyKeys());
254 }
255 if (this->GetVisibility())
256 {
257 return this->Device->RenderTranslucentPolygonalGeometry(vp);
258 }
259 }
260 return 0;
261 }
262
263 //----------------------------------------------------------------------
RenderVolumetricGeometry(vtkViewport * vp)264 int vtkProp3DFollower::RenderVolumetricGeometry(vtkViewport *vp)
265 {
266 if ( this->Device )
267 {
268 this->ComputeMatrix();
269 this->Device->SetUserMatrix(this->Matrix);
270 if (this->GetPropertyKeys())
271 {
272 this->Device->SetPropertyKeys(this->GetPropertyKeys());
273 }
274 if (this->GetVisibility())
275 {
276 return this->Device->RenderVolumetricGeometry(vp);
277 }
278 }
279 return 0;
280 }
281
282 //----------------------------------------------------------------------
ShallowCopy(vtkProp * prop)283 void vtkProp3DFollower::ShallowCopy(vtkProp *prop)
284 {
285 vtkProp3DFollower *f = vtkProp3DFollower::SafeDownCast(prop);
286 if ( f != nullptr )
287 {
288 this->SetCamera(f->GetCamera());
289 }
290
291 // Now do superclass
292 this->vtkProp3D::ShallowCopy(prop);
293 }
294
295 //----------------------------------------------------------------------------
InitPathTraversal()296 void vtkProp3DFollower::InitPathTraversal()
297 {
298 if ( this->Device )
299 {
300 this->Device->InitPathTraversal();
301 }
302 }
303
304 //----------------------------------------------------------------------------
GetNextPath()305 vtkAssemblyPath *vtkProp3DFollower::GetNextPath()
306 {
307 if ( this->Device )
308 {
309 return this->Device->GetNextPath();
310 }
311 else
312 {
313 return nullptr;
314 }
315 }
316
317 //----------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)318 void vtkProp3DFollower::PrintSelf(ostream& os, vtkIndent indent)
319 {
320 this->Superclass::PrintSelf(os,indent);
321
322 if ( this->Camera )
323 {
324 os << indent << "Camera:\n";
325 this->Camera->PrintSelf(os,indent.GetNextIndent());
326 }
327 else
328 {
329 os << indent << "Camera: (none)\n";
330 }
331 }
332