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