1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkScenePicker.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 "vtkScenePicker.h"
16
17 #include "vtkCommand.h"
18 #include "vtkDataObject.h"
19 #include "vtkHardwareSelector.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkProp.h"
22 #include "vtkRenderWindow.h"
23 #include "vtkRenderWindowInteractor.h"
24 #include "vtkRenderer.h"
25
26 class vtkScenePickerSelectionRenderCommand : public vtkCommand
27 {
28 public:
29 vtkScenePicker* m_Picker;
New()30 static vtkScenePickerSelectionRenderCommand* New()
31 {
32 return new vtkScenePickerSelectionRenderCommand;
33 }
34
Execute(vtkObject * vtkNotUsed (o),unsigned long event,void *)35 void Execute(vtkObject* vtkNotUsed(o), unsigned long event, void*) override
36 {
37 if (event == vtkCommand::StartInteractionEvent)
38 {
39 this->InteractiveRender = true;
40 }
41 else if (event == vtkCommand::EndInteractionEvent)
42 {
43 this->InteractiveRender = false;
44 }
45 else if (event == vtkCommand::EndEvent)
46 {
47 if (!this->InteractiveRender)
48 {
49 m_Picker->PickRender();
50 }
51 this->m_Picker->SetRenderer(this->m_Picker->Renderer);
52 }
53 }
54
55 protected:
vtkScenePickerSelectionRenderCommand()56 vtkScenePickerSelectionRenderCommand()
57 : InteractiveRender(false)
58 {
59 }
60 ~vtkScenePickerSelectionRenderCommand() override = default;
61 bool InteractiveRender;
62 };
63
64 vtkStandardNewMacro(vtkScenePicker);
65
66 //------------------------------------------------------------------------------
vtkScenePicker()67 vtkScenePicker::vtkScenePicker()
68 {
69 this->EnableVertexPicking = 1;
70 this->Renderer = nullptr;
71 this->Interactor = nullptr;
72 this->Selector = vtkHardwareSelector::New();
73 this->NeedToUpdate = false;
74 this->VertId = -1;
75 this->CellId = -1;
76 this->Prop = nullptr;
77 this->SelectionRenderCommand = vtkScenePickerSelectionRenderCommand::New();
78 this->SelectionRenderCommand->m_Picker = this;
79 }
80
81 //------------------------------------------------------------------------------
~vtkScenePicker()82 vtkScenePicker::~vtkScenePicker()
83 {
84 this->SetRenderer(nullptr);
85 this->Selector->Delete();
86 this->SelectionRenderCommand->Delete();
87 }
88
89 //------------------------------------------------------------------------------
SetRenderer(vtkRenderer * r)90 void vtkScenePicker::SetRenderer(vtkRenderer* r)
91 {
92 vtkRenderWindowInteractor* rwi = nullptr;
93 if (r && r->GetRenderWindow())
94 {
95 rwi = r->GetRenderWindow()->GetInteractor();
96 }
97 this->SetInteractor(rwi);
98
99 if (this->Renderer == r)
100 {
101 return;
102 }
103 if (r && !r->GetRenderWindow())
104 {
105 vtkErrorMacro(<< "Renderer: " << this->Renderer << " does not have its render window set.");
106 return;
107 }
108
109 if (this->Renderer)
110 {
111 this->Renderer->GetRenderWindow()->RemoveObserver(this->SelectionRenderCommand);
112 }
113
114 vtkSetObjectBodyMacro(Renderer, vtkRenderer, r);
115
116 if (this->Renderer)
117 {
118 this->Renderer->GetRenderWindow()->AddObserver(
119 vtkCommand::EndEvent, this->SelectionRenderCommand, 0.01);
120 }
121
122 this->Selector->SetRenderer(this->Renderer);
123 }
124
125 //------------------------------------------------------------------------------
SetInteractor(vtkRenderWindowInteractor * rwi)126 void vtkScenePicker::SetInteractor(vtkRenderWindowInteractor* rwi)
127 {
128 if (this->Interactor == rwi)
129 {
130 return;
131 }
132 if (this->Interactor)
133 {
134 this->Interactor->RemoveObserver(this->SelectionRenderCommand);
135 }
136
137 vtkSetObjectBodyMacro(Interactor, vtkRenderWindowInteractor, rwi);
138
139 if (this->Interactor)
140 {
141 this->Interactor->AddObserver(
142 vtkCommand::StartInteractionEvent, this->SelectionRenderCommand, 0.01);
143 this->Interactor->AddObserver(
144 vtkCommand::EndInteractionEvent, this->SelectionRenderCommand, 0.01);
145 }
146 }
147
148 //------------------------------------------------------------------------------
149 // Do a selection render.. for caching object selection stuff.
150 // This is used for Object selection . We have to perform
151 // "select" and "mouse over" and "mouse out" as the mouse moves around the
152 // scene (or the mouse is clicked in the case of "select"). I do not want
153 // to do a conventional pick for this function because it's too darn slow.
154 // The Selector will be used here to pick-render the entire
155 // screen, store on a buffer the colored cells and read back as
156 // the mouse moves around the moused pick. This extra render from the
157 // Selector will be done only if the camera isn't in motion,
158 // otherwise motion would be too frickin slow.
159 //
PickRender()160 void vtkScenePicker::PickRender()
161 {
162 if (!this->Renderer || !this->Renderer->GetRenderWindow())
163 {
164 return;
165 }
166
167 double vp[4];
168 this->Renderer->GetViewport(vp);
169 int size[2] = { this->Renderer->GetRenderWindow()->GetSize()[0],
170 this->Renderer->GetRenderWindow()->GetSize()[1] };
171
172 int rx1 = static_cast<int>(vp[0] * (size[0] - 1));
173 int ry1 = static_cast<int>(vp[1] * (size[1] - 1));
174 int rx2 = static_cast<int>(vp[2] * (size[0] - 1));
175 int ry2 = static_cast<int>(vp[3] * (size[1] - 1));
176
177 this->PickRender(rx1, ry1, rx2, ry2);
178 }
179
180 //------------------------------------------------------------------------------
181 // Do a selection render.. for caching object selection stuff.
PickRender(int x0,int y0,int x1,int y1)182 void vtkScenePicker::PickRender(int x0, int y0, int x1, int y1)
183 {
184 this->Renderer->GetRenderWindow()->RemoveObserver(this->SelectionRenderCommand);
185
186 if (this->EnableVertexPicking)
187 {
188 this->Selector->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_POINTS);
189 }
190 else
191 {
192 this->Selector->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_CELLS);
193 }
194 cout << "Area: " << x0 << ", " << y0 << ", " << x1 << ", " << y1 << endl;
195 this->Selector->SetArea(x0, y0, x1, y1);
196 if (!this->Selector->CaptureBuffers())
197 {
198 vtkErrorMacro("Failed to capture buffers.");
199 }
200 this->NeedToUpdate = true;
201 this->PickRenderTime.Modified();
202 this->Renderer->GetRenderWindow()->AddObserver(
203 vtkCommand::EndEvent, this->SelectionRenderCommand, 0.01);
204 }
205
206 //------------------------------------------------------------------------------
GetCellId(int displayPos[2])207 vtkIdType vtkScenePicker::GetCellId(int displayPos[2])
208 {
209 if (this->EnableVertexPicking)
210 {
211 return -1;
212 }
213 this->Update(displayPos);
214 return this->CellId;
215 }
216
217 //------------------------------------------------------------------------------
GetViewProp(int displayPos[2])218 vtkProp* vtkScenePicker::GetViewProp(int displayPos[2])
219 {
220 this->Update(displayPos);
221 return this->Prop;
222 }
223
224 //------------------------------------------------------------------------------
GetVertexId(int displayPos[2])225 vtkIdType vtkScenePicker::GetVertexId(int displayPos[2])
226 {
227 if (!this->EnableVertexPicking)
228 {
229 return -1;
230 }
231 this->Update(displayPos);
232 return this->CellId;
233 }
234
235 //------------------------------------------------------------------------------
Update(int displayPos[2])236 void vtkScenePicker::Update(int displayPos[2])
237 {
238 if (this->PickRenderTime <= this->GetMTime())
239 {
240 this->PickRender();
241 }
242
243 if (this->NeedToUpdate || this->LastQueriedDisplayPos[0] != displayPos[0] ||
244 this->LastQueriedDisplayPos[1] != displayPos[1])
245 {
246 this->Prop = nullptr;
247 unsigned int dpos[2] = { 0, 0 };
248 if (displayPos[0] >= 0 && displayPos[1] >= 0)
249 {
250 dpos[0] = static_cast<unsigned int>(displayPos[0]);
251 dpos[1] = static_cast<unsigned int>(displayPos[1]);
252 vtkHardwareSelector::PixelInformation info = this->Selector->GetPixelInformation(dpos);
253 this->CellId = info.AttributeID;
254 this->Prop = info.Prop;
255 }
256 this->LastQueriedDisplayPos[0] = displayPos[0];
257 this->LastQueriedDisplayPos[1] = displayPos[1];
258 this->NeedToUpdate = false;
259 }
260 }
261
262 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)263 void vtkScenePicker::PrintSelf(ostream& os, vtkIndent indent)
264 {
265 this->Superclass::PrintSelf(os, indent);
266 os << indent << "Renderer: " << this->Renderer << endl;
267 os << indent << "EnableVertexPicking: " << this->EnableVertexPicking << endl;
268 }
269