forked from Kitware/VTK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vtkOpenVRPropPicker.cxx
206 lines (178 loc) · 5.5 KB
/
vtkOpenVRPropPicker.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenVRPropPicker.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkOpenVRPropPicker.h"
#include "vtkAssemblyNode.h"
#include "vtkAssemblyPath.h"
#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkRenderer.h"
#include "vtkMath.h"
#include "vtkCamera.h"
#include "vtkBox.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor3D.h"
#include "vtkTransform.h"
vtkStandardNewMacro(vtkOpenVRPropPicker);
vtkOpenVRPropPicker::vtkOpenVRPropPicker()
{
}
vtkOpenVRPropPicker::~vtkOpenVRPropPicker()
{
}
// set up for a pick
void vtkOpenVRPropPicker::Initialize()
{
this->vtkAbstractPropPicker::Initialize();
}
// Pick from the given collection
int vtkOpenVRPropPicker::Pick3DRay(double pos[3], double wori[4], vtkRenderer *renderer)
{
//Compute event orientation
vtkRenderWindowInteractor3D* iren = vtkRenderWindowInteractor3D::SafeDownCast(
renderer->GetRenderWindow()->GetInteractor());
if (!iren)
{
vtkErrorMacro(<< "Couldn't get 3D interactor");
return 0;
}
if (this->PickFromList)
{
return this->PickProp3DRay(pos, wori, renderer,
this->PickList);
}
else
{
return this->PickProp3DRay(pos, wori, renderer,
renderer->GetViewProps());
}
}
// Pick from the given collection
int vtkOpenVRPropPicker::PickProp3DRay(
double selectionPt[3], double wori[4],
vtkRenderer *renderer, vtkPropCollection* propCollection)
{
// Initialize picking process
this->Initialize();
this->Renderer = renderer;
// Invoke start pick method if defined
this->InvokeEvent(vtkCommand::StartPickEvent, nullptr);
//Event position - Ray start position
double p0[4];
p0[0] = selectionPt[0];
p0[1] = selectionPt[1];
p0[2] = selectionPt[2];
p0[3] = 1.0;
//Compute ray direction
vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
trans->RotateWXYZ(wori[0], wori[1], wori[2], wori[3]);
double* rayDirection = trans->TransformDoubleVector(0.0, 0.0, -1.0);
vtkCamera* cam = renderer->GetActiveCamera();
if (!cam)
{
return 0;
}
//Ray length
double rayLength = cam->GetClippingRange()[1];
//Ray end point
double p1[4];
p1[0] = p0[0] + rayLength * rayDirection[0];
p1[1] = p0[1] + rayLength * rayDirection[1];
p1[2] = p0[2] + rayLength * rayDirection[2];
p1[3] = 1.0;
//Construct the ray
double ray[3];
ray[0] = p1[0] - p0[0];
ray[1] = p1[1] - p0[1];
ray[2] = p1[2] - p0[2];
vtkAssemblyPath *result = nullptr;
vtkAssemblyPath *insideResult = nullptr;
vtkCollectionSimpleIterator pit;
vtkProp *prop = nullptr;
vtkAssemblyPath *path;
vtkProp *propCandidate;
double t_min = VTK_DOUBLE_MAX;
double hitPos[3];
//For all props, return the closest prop intersected by the ray.
//If we pick inside a prop, it will be returned only if no other vtkProps are
//intersected by the ray. WARNING: Intersection checking uses bounds. This is
//confusing when the prop isn't fully filling its bounds. Improve this by :
//-returning the prop which bounds center is the closest to the ray, or
//-computing intersection with the geometry itself (see vtkCellPicker).
for (propCollection->InitTraversal(pit);
(prop = propCollection->GetNextProp(pit));)
{
for (prop->InitPathTraversal(); (path = prop->GetNextPath());)
{
propCandidate = path->GetFirstNode()->GetViewProp();
if (propCandidate->GetPickable() && propCandidate->GetVisibility()
&& propCandidate->GetUseBounds())
{
double *bnds = propCandidate->GetBounds();
if (bnds)
{
double t;
double xyz[3];
//Check for box intersection
if (vtkBox::IntersectBox(bnds, const_cast<double*>(p0), ray, xyz, t))
{
//Inside a prop, save its path in case nothing else is picked
if (!(t > 0))
{
insideResult = path;
hitPos[0] = selectionPt[0];
hitPos[1] = selectionPt[1];
hitPos[2] = selectionPt[2];
}
//Something was picked by the ray, save its path and update t_min
if (t > 0 && t < t_min)
{
result = path;
t_min = t;
hitPos[0] = xyz[0];
hitPos[1] = xyz[1];
hitPos[2] = xyz[2];
}
}
}
}
}
}
// If the ray didn't intersect anything, we might be inside a prop
if (!result)
{
result = insideResult;
}
// If something was picked..
if (result)
{
result->GetFirstNode()->GetViewProp()->Pick();
this->InvokeEvent(vtkCommand::PickEvent, nullptr);
//Update the picked position
this->PickPosition[0] = hitPos[0];
this->PickPosition[1] = hitPos[1];
this->PickPosition[2] = hitPos[2];
}
this->SetPath(result);
this->InvokeEvent(vtkCommand::EndPickEvent, nullptr);
// Call Pick on the Prop that was picked, and return 1 for success
if (result)
{
return 1;
}
else
{
return 0;
}
}
void vtkOpenVRPropPicker::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}