Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
QtBaseViewerPicking.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $Author$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50
51
52 //=============================================================================
53 //
54 // CLASS QtBaseViewer - IMPLEMENTATION
55 //
56 //=============================================================================
57
58
59 //== INCLUDES =================================================================
60
61 #include "QtBaseViewer.hh"
62 #include "QtGLGraphicsScene.hh"
63 #include "QtGLGraphicsView.hh"
64
65 //== NAMESPACES ===============================================================
66
67 namespace ACG {
68 namespace QtWidgets {
69
70 //== IMPLEMENTATION ==========================================================
71
72 static const unsigned int SELECTION_BUFFER_SIZE = 10000;
73 static const unsigned int NAME_STACK_SIZE = 2;
74
75 //== IMPLEMENTATION ==========================================================
76
77
78 void QtBaseViewer::renderPicking(bool _renderPicking, ACG::SceneGraph::PickTarget _mode) {
79 renderPicking_ = _renderPicking;
80 pickRendererMode_ = _mode;
81 }
82
83 //-----------------------------------------------------------------------------
84
85
86 bool QtBaseViewer::pick( SceneGraph::PickTarget _pickTarget,
87 const QPoint& _mousePos,
88 unsigned int& _nodeIdx,
89 unsigned int& _targetIdx,
90 Vec3d* _hitPointPtr )
91 {
92 if (sceneGraphRoot_)
93 {
94 GLint w = glWidth(),
95 h = glHeight(),
96 x = _mousePos.x(),
97 y = h - _mousePos.y();
98 GLint viewport[4] = {0,0,w,h};
99 GLuint nameBuffer[ NAME_STACK_SIZE ];
100
101 // reduce stack usage
102 std::vector<GLuint> selectionBuffer(SELECTION_BUFFER_SIZE);
103
104
105 // Initialize name buffer
106 nameBuffer[0] = 0;
107 nameBuffer[1] = 0;
108
109 const GLMatrixd& modelview = glstate_->modelview();
110 const GLMatrixd& projection = glstate_->projection();
111
112
113 // prepare GL state
114 makeCurrent();
115
116 glSelectBuffer( SELECTION_BUFFER_SIZE, &selectionBuffer[0] );
117 glRenderMode(GL_SELECT);
118 glMatrixMode(GL_PROJECTION);
119 glLoadIdentity();
120 // gluPickMatrix((GLdouble) x, (GLdouble) y, 3, 3, viewport);
121 // gluPickMatrix implementation as in mesa3d
122 // Translate and scale the picked region to the entire window
123 const float deltax = 3.0f, deltay = 3.0f;
124 glTranslatef(float(viewport[2] - 2 * (x - viewport[0])) / deltax,
125 float(viewport[3] - 2 * (y - viewport[1])) / deltay, 0.0f);
126 glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);
127
128 glMultMatrixd(projection.get_raw_data());
129 glMatrixMode(GL_MODELVIEW);
130 glLoadMatrixd(modelview.get_raw_data());
131 ACG::GLState::disable(GL_LIGHTING);
132 glClear(GL_DEPTH_BUFFER_BIT);
133 glstate_->pick_init (false);
134
135 // do the picking
136 SceneGraph::PickAction action(*glstate_, _pickTarget, curDrawMode_);
137 SceneGraph::traverse(sceneGraphRoot_, action);
138 int hits = glRenderMode(GL_RENDER);
139
140 // restore GL state
141 glMatrixMode( GL_PROJECTION );
142 glLoadMatrixd(projection.get_raw_data());
143 glMatrixMode( GL_MODELVIEW );
144 glLoadMatrixd(modelview.get_raw_data());
145 ACG::GLState::enable(GL_LIGHTING);
146
147
148 // process hit record
149 if ( hits > 0 )
150 {
151 GLuint *ptr = &selectionBuffer[0],
152 z,
153 min_z=~(0u),
154 max_z=0;
155
156 for (int i=0; i<hits; ++i)
157 {
158 const GLuint num_names = *ptr++;
159 if ( num_names != NAME_STACK_SIZE )
160 {
161 std::cerr << "QtBaseViewer::pick() : namestack error\n\n";
162 return false;
163 }
164
165 if ( (z = *ptr++) < min_z )
166 {
167 min_z = z;
168 max_z = *ptr++;
169 for (unsigned int j=0; j<num_names; ++j)
170 nameBuffer[j] = *ptr++;
171 }
172 else ptr += 1+num_names;
173 }
174
175 _nodeIdx = nameBuffer[0];
176 _targetIdx = nameBuffer[1];
177
178 if (_hitPointPtr)
179 {
180 GLuint zscale=~(0u);
181 GLdouble min_zz = ((GLdouble)min_z) / ((GLdouble)zscale);
182 GLdouble max_zz = ((GLdouble)max_z) / ((GLdouble)zscale);
183 GLdouble zz = 0.5F * (min_zz + max_zz);
184 *_hitPointPtr = glstate_->unproject(Vec3d(x,y,zz));
185 }
186
187 return true;
188 }
189 else if (hits < 0)
190 std::cerr << "QtBaseViewer::pick() : selection buffer overflow\n\n";
191 }
192
193 return false;
194 }
195
196
197 //-----------------------------------------------------------------------------
198
199
200 bool
201 QtBaseViewer::
202 fast_pick( const QPoint& _mousePos,
203 Vec3d& _hitPoint )
204 {
205 // get x,y,z values of pixel
206 GLint x(_mousePos.x()), y(glHeight() - _mousePos.y());
207 GLfloat z;
208
209
210 makeCurrent();
211 glPixelStorei(GL_PACK_ALIGNMENT, 1);
212 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
213 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
214
215
216 if (z < 0.99999)
217 {
218 _hitPoint = glstate_->unproject( Vec3d(x, y, z) );
219 return true;
220 }
221 else return false;
222 }
223
224 //-----------------------------------------------------------------------------
225
226
227 void QtBaseViewer::pickMode( int _id )
228 {
229 if (_id < (int) pick_modes_.size() )
230 {
231 pick_mode_idx_ = _id;
232 pick_mode_name_ = pick_modes_[pick_mode_idx_].name;
233
234 // adjust mouse tracking
235 if ( actionMode_ == PickingMode )
236 trackMouse(pick_modes_[pick_mode_idx_].tracking);
237
238 // adjust Cursor
239 if ( actionMode_ == PickingMode )
240 glView_->setCursor(pick_modes_[pick_mode_idx_].cursor);
241
242 // emit signal
243 emit(signalPickModeChanged(pick_mode_name_));
244 }
245 }
246
247
248 //-----------------------------------------------------------------------------
249
250
251 void QtBaseViewer::addPickMode(const std::string& _name,
252 bool _tracking,
253 int _pos,
254 bool _visible,
255 QCursor _cursor)
256 {
257 if ((unsigned int)_pos < pick_modes_.size())
258 {
259 std::vector<PickMode>::iterator it = pick_modes_.begin();
260 it += _pos+1;
261 pick_modes_.insert(it, PickMode(_name, _tracking, _visible, _cursor));
262 }
263 else
264 pick_modes_.push_back(PickMode(_name, _tracking, _visible, _cursor));
265
266 updatePickMenu();
267 }
268
269 //-----------------------------------------------------------------------------
270
271 void QtBaseViewer::setPickModeCursor(const std::string& _name, QCursor _cursor)
272 {
273 for (uint i=0; i < pick_modes_.size(); i++)
274 if ( pick_modes_[i].name == _name ){
275 pick_modes_[i].cursor = _cursor;
276
277 //switch cursor if pickMode is active
278 if (pick_mode_name_ == _name && actionMode_ == PickingMode)
279 glView_->setCursor(_cursor);
280 break;
281 }
282 }
283
284 //-----------------------------------------------------------------------------
285
286 void QtBaseViewer::setPickModeMouseTracking(const std::string& _name, bool _mouseTracking)
287 {
288 for (uint i=0; i < pick_modes_.size(); i++)
289 if ( pick_modes_[i].name == _name ){
290 pick_modes_[i].tracking = _mouseTracking;
291
292 //switch cursor if pickMode is active
293 if (pick_mode_name_ == _name && actionMode_ == PickingMode)
294 trackMouse(_mouseTracking);
295 break;
296 }
297 }
298
299 //-----------------------------------------------------------------------------
300
301
302 void QtBaseViewer::clearPickModes()
303 {
304 pick_modes_.clear();
305 pick_mode_idx_ = -1;
306 pick_mode_name_ = "";
307 updatePickMenu();
308 }
309
310
311 //-----------------------------------------------------------------------------
312
313
314 const std::string& QtBaseViewer::pickMode() const
315 {
316 return pick_mode_name_;
317 }
318
319
320 //-----------------------------------------------------------------------------
321
322
323 void QtBaseViewer::pickMode(const std::string& _name)
324 {
325 for (unsigned int i=0; i<pick_modes_.size(); ++i)
326 {
327 if (pick_modes_[i].name == _name)
328 {
329 pickMode( i );
330 updatePickMenu();
331 return;
332 }
333 }
334 }
335
336 //-----------------------------------------------------------------------------
337
338 void QtBaseViewer::pickingMode() {
339 actionMode(PickingMode);
340 }
341
342
343 //=============================================================================
344 } // namespace QtWidgets
345 } // namespace ACG
346 //=============================================================================
ACG::QtWidgets::QtBaseViewer::pickMode
const std::string & pickMode() const
Definition: QtBaseViewerPicking.cc:314
ACG::QtWidgets::QtBaseViewer::clearPickModes
void clearPickModes()
Definition: QtBaseViewerPicking.cc:302
ACG::QtWidgets::QtBaseViewer::pick_modes_
std::vector< PickMode > pick_modes_
Definition: QtBaseViewer.hh:1283
ACG::GLState::enable
static void enable(GLenum _cap)
replaces glEnable, but supports locking
Definition: GLState.cc:1490
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::QtWidgets::QtBaseViewer::glWidth
unsigned int glWidth() const
get width of QGLWidget
Definition: QtBaseViewer.cc:2059
ACG::SceneGraph::PickAction
Definition: SceneGraph.hh:752
ACG::QtWidgets::QtBaseViewer::pick
bool pick(SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, Vec3d *_hitPointPtr=0)
Definition: QtBaseViewerPicking.cc:86
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
ACG::QtWidgets::QtBaseViewer::PickingMode
Definition: QtBaseViewer.hh:368
ACG::QtWidgets::QtBaseViewer::pick_mode_name_
std::string pick_mode_name_
Definition: QtBaseViewer.hh:1287
ACG::QtWidgets::QtBaseViewer::PickMode
Definition: QtBaseViewer.hh:1258
ACG::GLState::unproject
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:649
ACG::QtWidgets::QtBaseViewer::setPickModeMouseTracking
void setPickModeMouseTracking(const std::string &_name, bool _mouseTracking)
set mouseTracking for the pick mode
Definition: QtBaseViewerPicking.cc:286
ACG::QtWidgets::QtBaseViewer::pickingMode
virtual void pickingMode()
Definition: QtBaseViewerPicking.cc:338
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
ACG::GLState::modelview
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:794
ACG::GLState::projection
const GLMatrixd & projection() const
get projection matrix
Definition: GLState.hh:789
ACG::QtWidgets::QtBaseViewer::signalPickModeChanged
void signalPickModeChanged(const std::string &)
ACG::GLMatrixT< double >
ACG::QtWidgets::QtBaseViewer::pick_mode_idx_
int pick_mode_idx_
Definition: QtBaseViewer.hh:1291
ACG::QtWidgets::QtBaseViewer::updatePickMenu
void updatePickMenu()
update pick mode menu
Definition: QtBaseViewer.cc:2484
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::QtWidgets::QtBaseViewer::fast_pick
bool fast_pick(const QPoint &_mousePos, Vec3d &_hitPoint)
Definition: QtBaseViewerPicking.cc:202
ACG::QtWidgets::QtBaseViewer::renderPicking
void renderPicking(bool _renderPicking, ACG::SceneGraph::PickTarget _mode)
Definition: QtBaseViewerPicking.cc:78
ACG::QtWidgets::QtBaseViewer::makeCurrent
virtual void makeCurrent()
Makes this widget the current widget for OpenGL operations.
Definition: QtBaseViewer.cc:377
ACG::GLState::pick_init
void pick_init(bool _color)
initialize name/color picking stack (like glInitNames())
Definition: GLState.cc:1039
ACG::QtWidgets::QtBaseViewer::renderPicking_
bool renderPicking_
Definition: QtBaseViewer.hh:1295
ACG::QtWidgets::QtBaseViewer::pickRendererMode_
ACG::SceneGraph::PickTarget pickRendererMode_
Definition: QtBaseViewer.hh:1301
ACG::QtWidgets::QtBaseViewer::setPickModeCursor
void setPickModeCursor(const std::string &_name, QCursor _cursor)
set a new cursor for the pick mode
Definition: QtBaseViewerPicking.cc:271
ACG::GLState::disable
static void disable(GLenum _cap)
replaces glDisable, but supports locking
Definition: GLState.cc:1504
ACG::QtWidgets::QtBaseViewer::addPickMode
void addPickMode(const std::string &_name, bool _mouse_tracking=false, int _pos=-1, bool _visible=true, QCursor _cursor=Qt::ArrowCursor)
add pick mode
Definition: QtBaseViewerPicking.cc:251
ACG::SceneGraph::traverse
void traverse(BaseNode *_node, Action &_action)
Definition: SceneGraph.hh:143
ACG::QtWidgets::QtBaseViewer::trackMouse
void trackMouse(bool _track)
Enable/disable mouse tracking (move events with no button press)
Definition: QtBaseViewer.cc:450
ACG::QtWidgets::QtBaseViewer::glHeight
unsigned int glHeight() const
get height of QGLWidget
Definition: QtBaseViewer.cc:2062
ACG::Matrix4x4T::get_raw_data
const Scalar * get_raw_data() const
Definition: Matrix4x4T.hh:262
ACG::QtWidgets::QtBaseViewer::actionMode
ActionMode actionMode() const
get action mode
Definition: QtBaseViewer.hh:387