Developer Documentation

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
45
46 //=============================================================================
47 //
48 // CLASS QtBaseViewer - IMPLEMENTATION
49 //
50 //=============================================================================
51
52
53 //== INCLUDES =================================================================
54 #include <ACG/GL/acg_glew.hh>
55 #include "QtBaseViewer.hh"
56 #include "QtGLGraphicsScene.hh"
57 #include "QtGLGraphicsView.hh"
58
59 #include "../GL/GLState.hh"
60 #include "../Scenegraph/SceneGraph.hh"
61
62 //== NAMESPACES ===============================================================
63
64 namespace ACG {
65 namespace QtWidgets {
66
67 //== IMPLEMENTATION ==========================================================
68
69 static const unsigned int SELECTION_BUFFER_SIZE = 10000;
70 static const unsigned int NAME_STACK_SIZE = 2;
71
72 //== IMPLEMENTATION ==========================================================
73
74
75 void QtBaseViewer::renderPicking(bool _renderPicking, ACG::SceneGraph::PickTarget _mode) {
76 renderPicking_ = _renderPicking;
77 pickRendererMode_ = _mode;
78 }
79
80 //-----------------------------------------------------------------------------
81
82
83 bool QtBaseViewer::pick( SceneGraph::PickTarget _pickTarget,
84 const QPoint& _mousePos,
85 unsigned int& _nodeIdx,
86 unsigned int& _targetIdx,
87 Vec3d* _hitPointPtr )
88 {
89 if (sceneGraphRoot_)
90 {
91 GLint w = glWidth(),
92 h = glHeight(),
93 x = _mousePos.x(),
94 y = h - _mousePos.y();
95 GLint viewport[4] = {0,0,w,h};
96 GLuint nameBuffer[ NAME_STACK_SIZE ];
97
98 // reduce stack usage
99 std::vector<GLuint> selectionBuffer(SELECTION_BUFFER_SIZE);
100
101
102 // Initialize name buffer
103 nameBuffer[0] = 0;
104 nameBuffer[1] = 0;
105
106 const GLMatrixd& modelview = glstate_->modelview();
107 const GLMatrixd& projection = glstate_->projection();
108
109
110 // prepare GL state
111 makeCurrent();
112
113 glSelectBuffer( SELECTION_BUFFER_SIZE, &selectionBuffer[0] );
114 glRenderMode(GL_SELECT);
115 glMatrixMode(GL_PROJECTION);
116 glLoadIdentity();
117 // gluPickMatrix((GLdouble) x, (GLdouble) y, 3, 3, viewport);
118 // gluPickMatrix implementation as in mesa3d
119 // Translate and scale the picked region to the entire window
120 const float deltax = 3.0f, deltay = 3.0f;
121 glTranslatef(float(viewport[2] - 2 * (x - viewport[0])) / deltax,
122 float(viewport[3] - 2 * (y - viewport[1])) / deltay, 0.0f);
123 glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);
124
125 glMultMatrixd(projection.get_raw_data());
126 glMatrixMode(GL_MODELVIEW);
127 glLoadMatrixd(modelview.get_raw_data());
128 ACG::GLState::disable(GL_LIGHTING);
129 glClear(GL_DEPTH_BUFFER_BIT);
130 glstate_->pick_init (false);
131
132 // do the picking
133 SceneGraph::PickAction action(*glstate_, _pickTarget, curDrawMode_);
134 SceneGraph::traverse(sceneGraphRoot_, action);
135 int hits = glRenderMode(GL_RENDER);
136
137 // restore GL state
138 glMatrixMode( GL_PROJECTION );
139 glLoadMatrixd(projection.get_raw_data());
140 glMatrixMode( GL_MODELVIEW );
141 glLoadMatrixd(modelview.get_raw_data());
142 ACG::GLState::enable(GL_LIGHTING);
143
144
145 // process hit record
146 if ( hits > 0 )
147 {
148 GLuint *ptr = &selectionBuffer[0],
149 z,
150 min_z=~(0u),
151 max_z=0;
152
153 for (int i=0; i<hits; ++i)
154 {
155 const GLuint num_names = *ptr++;
156 if ( num_names != NAME_STACK_SIZE )
157 {
158 std::cerr << "QtBaseViewer::pick() : namestack error\n\n";
159 return false;
160 }
161
162 if ( (z = *ptr++) < min_z )
163 {
164 min_z = z;
165 max_z = *ptr++;
166 for (unsigned int j=0; j<num_names; ++j)
167 nameBuffer[j] = *ptr++;
168 }
169 else ptr += 1+num_names;
170 }
171
172 _nodeIdx = nameBuffer[0];
173 _targetIdx = nameBuffer[1];
174
175 if (_hitPointPtr)
176 {
177 GLuint zscale=~(0u);
178 GLdouble min_zz = ((GLdouble)min_z) / ((GLdouble)zscale);
179 GLdouble max_zz = ((GLdouble)max_z) / ((GLdouble)zscale);
180 GLdouble zz = 0.5F * (min_zz + max_zz);
181 *_hitPointPtr = glstate_->unproject(Vec3d(x,y,zz));
182 }
183
184 return true;
185 }
186 else if (hits < 0)
187 std::cerr << "QtBaseViewer::pick() : selection buffer overflow\n\n";
188 }
189
190 return false;
191 }
192
193
194 //-----------------------------------------------------------------------------
195
196
197 bool
198 QtBaseViewer::
199 fast_pick( const QPoint& _mousePos,
200 Vec3d& _hitPoint )
201 {
202 // get x,y,z values of pixel
203 GLint x(_mousePos.x()), y(glHeight() - _mousePos.y());
204 GLfloat z;
205
206
207 makeCurrent();
208 glPixelStorei(GL_PACK_ALIGNMENT, 1);
209 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
210 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
211
212
213 if (z < 0.99999)
214 {
215 _hitPoint = glstate_->unproject( Vec3d(x, y, z) );
216 return true;
217 }
218 else return false;
219 }
220
221 //-----------------------------------------------------------------------------
222
223
224 void QtBaseViewer::pickMode( int _id )
225 {
226 if (_id < (int) pick_modes_.size() )
227 {
228 pick_mode_idx_ = _id;
229 pick_mode_name_ = pick_modes_[pick_mode_idx_].name;
230
231 // adjust mouse tracking
232 if ( actionMode_ == PickingMode )
233 trackMouse(pick_modes_[pick_mode_idx_].tracking);
234
235 // adjust Cursor
236 if ( actionMode_ == PickingMode )
237 glView_->setCursor(pick_modes_[pick_mode_idx_].cursor);
238
239 // emit signal
240 emit(signalPickModeChanged(pick_mode_name_));
241 }
242 }
243
244
245 //-----------------------------------------------------------------------------
246
247
248 void QtBaseViewer::addPickMode(const std::string& _name,
249 bool _tracking,
250 int _pos,
251 bool _visible,
252 QCursor _cursor)
253 {
254 if ((unsigned int)_pos < pick_modes_.size())
255 {
256 std::vector<PickMode>::iterator it = pick_modes_.begin();
257 it += _pos+1;
258 pick_modes_.insert(it, PickMode(_name, _tracking, _visible, _cursor));
259 }
260 else
261 pick_modes_.push_back(PickMode(_name, _tracking, _visible, _cursor));
262
263 updatePickMenu();
264 }
265
266 //-----------------------------------------------------------------------------
267
268 void QtBaseViewer::setPickModeCursor(const std::string& _name, QCursor _cursor)
269 {
270 for (uint i=0; i < pick_modes_.size(); i++)
271 if ( pick_modes_[i].name == _name ){
272 pick_modes_[i].cursor = _cursor;
273
274 //switch cursor if pickMode is active
275 if (pick_mode_name_ == _name && actionMode_ == PickingMode)
276 glView_->setCursor(_cursor);
277 break;
278 }
279 }
280
281 //-----------------------------------------------------------------------------
282
283 void QtBaseViewer::setPickModeMouseTracking(const std::string& _name, bool _mouseTracking)
284 {
285 for (uint i=0; i < pick_modes_.size(); i++)
286 if ( pick_modes_[i].name == _name ){
287 pick_modes_[i].tracking = _mouseTracking;
288
289 //switch cursor if pickMode is active
290 if (pick_mode_name_ == _name && actionMode_ == PickingMode)
291 trackMouse(_mouseTracking);
292 break;
293 }
294 }
295
296 //-----------------------------------------------------------------------------
297
298
299 void QtBaseViewer::clearPickModes()
300 {
301 pick_modes_.clear();
302 pick_mode_idx_ = -1;
303 pick_mode_name_ = "";
304 updatePickMenu();
305 }
306
307
308 //-----------------------------------------------------------------------------
309
310
311 const std::string& QtBaseViewer::pickMode() const
312 {
313 return pick_mode_name_;
314 }
315
316
317 //-----------------------------------------------------------------------------
318
319
320 void QtBaseViewer::pickMode(const std::string& _name)
321 {
322 for (unsigned int i=0; i<pick_modes_.size(); ++i)
323 {
324 if (pick_modes_[i].name == _name)
325 {
326 pickMode( i );
327 updatePickMenu();
328 return;
329 }
330 }
331 }
332
333 //-----------------------------------------------------------------------------
334
335 void QtBaseViewer::pickingMode() {
336 actionMode(PickingMode);
337 }
338
339
340 //=============================================================================
341 } // namespace QtWidgets
342 } // namespace ACG
343 //=============================================================================
ACG::QtWidgets::QtBaseViewer::fast_pick
bool fast_pick(const QPoint &_mousePos, Vec3d &_hitPoint)
Definition: QtBaseViewerPicking.cc:199
ACG::QtWidgets::QtBaseViewer::trackMouse
void trackMouse(bool _track)
Enable/disable mouse tracking (move events with no button press)
Definition: QtBaseViewer.cc:437
ACG::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
ACG::QtWidgets::QtBaseViewer::pickMode
const std::string & pickMode() const
Definition: QtBaseViewerPicking.cc:311
ACG::GLState::pick_init
void pick_init(bool _color)
initialize name/color picking stack (like glInitNames())
Definition: GLState.cc:1043
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::QtWidgets::QtBaseViewer::setPickModeCursor
void setPickModeCursor(const std::string &_name, QCursor _cursor)
set a new cursor for the pick mode
Definition: QtBaseViewerPicking.cc:268
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::QtWidgets::QtBaseViewer::renderPicking
void renderPicking(bool _renderPicking, ACG::SceneGraph::PickTarget _mode)
Definition: QtBaseViewerPicking.cc:75
ACG::QtWidgets::QtBaseViewer::makeCurrent
virtual void makeCurrent()
Makes this widget the current widget for OpenGL operations.
Definition: QtBaseViewer_qt.cc:131
ACG::QtWidgets::QtBaseViewer::pickRendererMode_
ACG::SceneGraph::PickTarget pickRendererMode_
Definition: QtBaseViewer.hh:1300
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
ACG::QtWidgets::QtBaseViewer::renderPicking_
bool renderPicking_
Definition: QtBaseViewer.hh:1294
ACG::GLState::unproject
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
ACG::QtWidgets::QtBaseViewer::glWidth
unsigned int glWidth() const
get width of QGLWidget
Definition: QtBaseViewer.cc:1727
ACG::GLState::disable
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
ACG::GLMatrixT< double >
ACG::QtWidgets::QtBaseViewer::pick_mode_idx_
int pick_mode_idx_
Definition: QtBaseViewer.hh:1290
ACG::QtWidgets::QtBaseViewer::pick_modes_
std::vector< PickMode > pick_modes_
Definition: QtBaseViewer.hh:1282
ACG::QtWidgets::QtBaseViewer::updatePickMenu
void updatePickMenu()
update pick mode menu
Definition: QtBaseViewer.cc:2152
ACG::QtWidgets::QtBaseViewer::pick_mode_name_
std::string pick_mode_name_
Definition: QtBaseViewer.hh:1286
ACG::QtWidgets::QtBaseViewer::setPickModeMouseTracking
void setPickModeMouseTracking(const std::string &_name, bool _mouseTracking)
set mouseTracking for the pick mode
Definition: QtBaseViewerPicking.cc:283
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:248
ACG::QtWidgets::QtBaseViewer::PickMode
Definition: QtBaseViewer.hh:1257
ACG::QtWidgets::QtBaseViewer::clearPickModes
void clearPickModes()
Definition: QtBaseViewerPicking.cc:299
ACG::QtWidgets::QtBaseViewer::actionMode
ActionMode actionMode() const
get action mode
Definition: QtBaseViewer.hh:384
ACG::GLState::modelview
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
ACG::QtWidgets::QtBaseViewer::pick
bool pick(SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, Vec3d *_hitPointPtr=0)
Definition: QtBaseViewerPicking.cc:83
ACG::GLState::projection
const GLMatrixd & projection() const
get projection matrix
Definition: GLState.hh:786
ACG::Matrix4x4T::get_raw_data
const Scalar * get_raw_data() const
Definition: Matrix4x4T.hh:256
ACG::SceneGraph::traverse
void traverse(BaseNode *_node, Action &_action)
Definition: SceneGraph.hh:137
ACG::QtWidgets::QtBaseViewer::glHeight
unsigned int glHeight() const
get height of QGLWidget
Definition: QtBaseViewer.cc:1730
ACG::QtWidgets::QtBaseViewer::PickingMode
Definition: QtBaseViewer.hh:365
ACG::QtWidgets::QtBaseViewer::pickingMode
virtual void pickingMode()
Definition: QtBaseViewerPicking.cc:335
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
ACG::QtWidgets::QtBaseViewer::signalPickModeChanged
void signalPickModeChanged(const std::string &)
ACG::SceneGraph::PickAction
Definition: SceneGraph.hh:746