QtBaseViewerPicking.cc 19.4 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2
3
*                                                                            *
*                              OpenFlipper                                   *
Martin Schultz's avatar
Martin Schultz committed
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
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
*                                                                            *
40
41
42
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
43
44
45
46
47
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
48
\*===========================================================================*/
Jan Möbius's avatar
   
Jan Möbius committed
49
50
51
52
53
54




//=============================================================================
//
Jan Möbius's avatar
   
Jan Möbius committed
55
//  CLASS glViewer - IMPLEMENTATION
Jan Möbius's avatar
   
Jan Möbius committed
56
57
58
59
60
61
62
63
64
65
//
//=============================================================================


//== INCLUDES =================================================================

#include "QtBaseViewer.hh"
#include "QtGLGraphicsScene.hh"
#include "QtGLGraphicsView.hh"

66
#if QT_VERSION < 0x050000
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
67
68
69
70
#include <QGLFramebufferObject>
#else
#include <QOpenGLFramebufferObject>
#endif
Jan Möbius's avatar
Jan Möbius committed
71

Jan Möbius's avatar
   
Jan Möbius committed
72
73
74
75
76
//== NAMESPACES ===============================================================

//== IMPLEMENTATION ==========================================================


Jan Möbius's avatar
   
Jan Möbius committed
77
bool glViewer::pick( ACG::SceneGraph::PickTarget _pickTarget,
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
78
                     const QPoint&               _mousePos,
79
80
                     size_t&                     _nodeIdx,
                     size_t&                     _targetIdx,
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
81
82
83
84
                     ACG::Vec3d*                 _hitPointPtr )
{
  if (sceneGraphRoot_)
  {
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
85
86
87
    // unsigned int node, target;
    // QTime time;
    // time.start ();
Jan Möbius's avatar
Jan Möbius committed
88
89
90
91
92
    int rv = pickFromCache (_pickTarget, _mousePos, _nodeIdx, _targetIdx, _hitPointPtr);

    // cache will return -1 if a update is needed or caching is not supported
    if (rv < 0)
      rv = pickColor (_pickTarget, _mousePos, _nodeIdx, _targetIdx, _hitPointPtr);
Dirk Wilden's avatar
Dirk Wilden committed
93

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
94
    // printf ("ColorPicking took %d msec\n",time.restart ());
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
95

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
96
97
    // if (rv > 0 && (node != _nodeIdx || target != _targetIdx))
    //   printf ("***** Picking difference Color %d/%d GL %d/%d\n",node, target, _nodeIdx, _targetIdx);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
98
99
100
101
102
103
104
105
106
107
    if (rv > 0)
      return rv;
  }
  return false;
}


//-----------------------------------------------------------------------------

int glViewer::pickColor( ACG::SceneGraph::PickTarget _pickTarget,
Jan Möbius's avatar
   
Jan Möbius committed
108
                         const QPoint&               _mousePos,
109
110
                         size_t&                     _nodeIdx,
                         size_t&                     _targetIdx,
Jan Möbius's avatar
   
Jan Möbius committed
111
112
                         ACG::Vec3d*                 _hitPointPtr )
{
113
114
115
116
117
  GLint         w = glWidth(),
                h = glHeight(),
                l = scenePos().x(),
                b = scene()->height () - scenePos().y() - h,
                x = _mousePos.x(),
Jan Möbius's avatar
Jan Möbius committed
118
119
120
                y = scene()->height () - _mousePos.y(),
                pW = 1,
                pH = 1;
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
121
  GLubyte       pixels[9][4];
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
122
123
  GLfloat       depths[9];
  int           hit = -1;
Jan Möbius's avatar
Jan Möbius committed
124
125

  // traversing order (center, top, bottom, ...)
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
126
127
  unsigned char order[9] = { 4, 7, 1, 3, 5, 0, 2, 6, 8 };

128
129
130
  // prepare GL state
  makeCurrent();

Jan Möbius's avatar
Jan Möbius committed
131
132
133
134
135
136
137
138
139
140
141
  if (pickCacheSupported_)
  {
    // delete pick cache if the size changed
    if (pickCache_ && pickCache_->size () != QSize (glWidth (), glHeight ()))
    {
      delete pickCache_;
      pickCache_ = NULL;
    }
    // create a new pick cache frambuffer object
    if (!pickCache_)
    {
142
      pickCache_ = new QFramebufferObject (glWidth (), glHeight (), QFramebufferObject::Depth);
Jan Möbius's avatar
Jan Möbius committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
      if (!pickCache_->isValid ())
      {
        pickCacheSupported_ = false;
        delete pickCache_;
        pickCache_ = NULL;
      }
    }
    if (pickCache_)
    {
      // the viewport for the framebuffer object
      l = 0;
      b = 0;
      x = _mousePos.x() - scenePos().x();
      y = glHeight() - (_mousePos.y() - scenePos().y());

      // we can only pick inside of our window
      if (x < 0 || y < 0 || x >= (int)glWidth() || y >= (int)glHeight())
        return 0;

      pickCache_->bind ();
    }
  }

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
166
167
168
  const ACG::GLMatrixd&  modelview  = properties_.glState().modelview();
  const ACG::GLMatrixd&  projection = properties_.glState().projection();

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
169
170
171
  ACG::Vec4f clear_color = properties_.glState().clear_color();
  properties_.glState().set_clear_color (ACG::Vec4f (0.0, 0.0, 0.0, 0.0));

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
172

173
  glViewport (l, b, w, h);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
174
175
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
176

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
177
178
179
  glMultMatrixd(projection.get_raw_data());
  glMatrixMode(GL_MODELVIEW);
  glLoadMatrixd(modelview.get_raw_data());
180
181
182
  ACG::GLState::disable(GL_LIGHTING);
  ACG::GLState::disable(GL_BLEND);
  ACG::GLState::enable(GL_DEPTH_TEST);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
183
184
185
186
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  properties_.glState().pick_init (true);

  // do the picking
Jan Möbius's avatar
Jan Möbius committed
187
  ACG::SceneGraph::PickAction action(properties_.glState(), _pickTarget, properties_.drawMode());
188
  ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action,properties_.glState() );
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
189
190
191
192
193
194

  // restore GL state
  glMatrixMode( GL_PROJECTION );
  glLoadMatrixd(projection.get_raw_data());
  glMatrixMode( GL_MODELVIEW );
  glLoadMatrixd(modelview.get_raw_data());
195
  ACG::GLState::enable(GL_LIGHTING);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
196

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
197
198
  properties_.glState().set_clear_color (clear_color);

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
199
  if (properties_.glState().pick_error ())
Jan Möbius's avatar
Jan Möbius committed
200
201
202
  {
    if (pickCache_ && pickCache_->isBound ())
      pickCache_->release ();
203
204

    std::cerr << "error - picking color stack invalid" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    return -1;
  }

  glPixelStorei(GL_PACK_ALIGNMENT, 1);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

  // we can only read inside our viewport
  if (x + 1 < w)
    pW++;

  if (y + 1 < h)
    pH++;

  if (x > 0)
  {
    x--;
    pW++;
  }
  if (y > 0)
  {
    y--;
    pH++;
  }

  if (pH != 3 || pW != 3)
  {
    // initialize unused values with 0
    for (int i = 0; i < 9; i++)
    {
      pixels[i][0] = 0;
      pixels[i][1] = 0;
      pixels[i][2] = 0;
      pixels[i][3] = 0;
      depths[i] = 0.0;
    }
  }

  // read from framebuffer
  glReadPixels (x, y, pW, pH, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  glReadPixels (x, y, pW, pH, GL_DEPTH_COMPONENT, GL_FLOAT, depths);

  // unbind pick cache
  if (pickCache_ && pickCache_->isBound ())
  {
    pickCache_->release ();
    updatePickCache_ = false;
251
    pickCacheTarget_ = _pickTarget;
Jan Möbius's avatar
Jan Möbius committed
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  }

  // get first found pixel
  for (int i = 0; i < 9; i++)
  {
    if (hit < 0 && (pixels[order[i]][2] != 0 || pixels[order[i]][1] != 0 || pixels[order[i]][0] != 0 || pixels[order[i]][3] != 0))
    {
      hit = order[i];
      break;
    }
  }

  if (hit < 0)
    return 0;


  ACG::Vec4uc rgba;
  rgba[0] = pixels[hit][0];
  rgba[1] = pixels[hit][1];
  rgba[2] = pixels[hit][2];
  rgba[3] = pixels[hit][3];

274
  std::vector<size_t> rv = properties_.glState().pick_color_to_stack (rgba);
Jan Möbius's avatar
Jan Möbius committed
275
276
277

  // something wrong with the color stack ?
  if (rv.size () < 2)
278
279
  {
    std::cerr << "error - picking color not found in stack" << std::endl;
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
280
    return -1;
281
  }
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
282

Jan Möbius's avatar
Jan Möbius committed
283
284
285
  _nodeIdx   = rv[1];
  _targetIdx = rv[0];

286
287
288
289
290
291
292
293
294
295
296
//   // Debug Code to visualize picking cache ( DO NOT REMOVE!!!! Jan )
//   QImage murks(glWidth (),glHeight (),QImage::Format_ARGB32);
//   murks = pickCache_->toImage();
//   for ( int i = 0 ; i < glWidth() ; ++i ) 
//     for ( int j = 0 ; j < glHeight() ; ++j )  {
//       QColor bla (murks.pixel(i,j));
//       bla.setAlpha(255);
//       murks.setPixel(i,j,bla.rgba());
//     }
//   murks.save("murks.png");

Jan Möbius's avatar
Jan Möbius committed
297
298
299
300
301
302
303
304
305
306
307
308
309
  if (_hitPointPtr)
  {
    *_hitPointPtr = properties_.glState().unproject (
      ACG::Vec3d(_mousePos.x(), scene()->height () - _mousePos.y(),depths[hit]));
  }

  return 1;
}

//-----------------------------------------------------------------------------

int glViewer::pickFromCache( ACG::SceneGraph::PickTarget _pickTarget,
                             const QPoint&               _mousePos,
310
311
                             size_t&                     _nodeIdx,
                             size_t&                     _targetIdx,
Jan Möbius's avatar
Jan Möbius committed
312
313
314
                             ACG::Vec3d*                 _hitPointPtr )
{
  // do we need an update?
315
316
  if (!pickCacheSupported_ || updatePickCache_ || !pickCache_ ||
      pickCacheTarget_ != _pickTarget)
Jan Möbius's avatar
Jan Möbius committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    return -1;

  GLint         x = _mousePos.x() - scenePos().x(),
                y = glHeight() - (_mousePos.y() - scenePos().y()),
                pW = 1,
                pH = 1;
  GLubyte       pixels[9][4];
  GLfloat       depths[9];
  int           hit = -1;

  // traversing order (center, top, bottom, ...)
  unsigned char order[9] = { 4, 7, 1, 3, 5, 0, 2, 6, 8 };

  // can't pick outside
  if (x < 0 || y < 0 || x >= (int)glWidth() || y >= (int)glHeight())
    return 0;

  // bind cache framebuffer object
  pickCache_->bind ();

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
337
338
339
  glPixelStorei(GL_PACK_ALIGNMENT, 1);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

Jan Möbius's avatar
Jan Möbius committed
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  // we can only read inside our viewport
  if (x + 1 < (int)glWidth ())
    pW++;

  if (y + 1 < (int)glHeight ())
    pH++;

  if (x > 0)
  {
    x--;
    pW++;
  }
  if (y > 0)
  {
    y--;
    pH++;
  }

  if (pH != 3 || pW != 3)
  {
    // initialize unused values with 0
    for (int i = 0; i < 9; i++)
    {
      pixels[i][0] = 0;
      pixels[i][1] = 0;
      pixels[i][2] = 0;
      pixels[i][3] = 0;
      depths[i] = 0.0;
    }
  }

  // read from framebuffer
  glReadPixels (x, y, pW, pH, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  glReadPixels (x, y, pW, pH, GL_DEPTH_COMPONENT, GL_FLOAT, depths);

  // unbind
  pickCache_->release ();
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
377

Jan Möbius's avatar
Jan Möbius committed
378
  // get first found pixel
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
379
  for (int i = 0; i < 9; i++)
Jan Möbius's avatar
   
Jan Möbius committed
380
  {
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
381
    if (hit < 0 && (pixels[order[i]][2] != 0 || pixels[order[i]][1] != 0 || pixels[order[i]][0] != 0 || pixels[order[i]][3] != 0))
Jan Möbius's avatar
   
Jan Möbius committed
382
    {
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
383
384
385
386
387
388
389
      hit = order[i];
      break;
    }
  }

  if (hit < 0)
    return 0;
Jan Möbius's avatar
   
Jan Möbius committed
390
391


Jan Möbius's avatar
Dennis:    
Jan Möbius committed
392
393
394
395
396
  ACG::Vec4uc rgba;
  rgba[0] = pixels[hit][0];
  rgba[1] = pixels[hit][1];
  rgba[2] = pixels[hit][2];
  rgba[3] = pixels[hit][3];
Jan Möbius's avatar
   
Jan Möbius committed
397

398
  std::vector<size_t> rv = properties_.glState().pick_color_to_stack (rgba);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
399

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
400
401
402
403
404
405
406
407
408
  // something wrong with the color stack ?
  if (rv.size () < 2)
    return -1;

  _nodeIdx   = rv[1];
  _targetIdx = rv[0];

  if (_hitPointPtr)
  {
Jan Möbius's avatar
Jan Möbius committed
409
410
    *_hitPointPtr = properties_.glState().unproject(
      ACG::Vec3d(_mousePos.x(), scene()->height () - _mousePos.y(),depths[hit]));
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
411
412
413
414
415
416
417
  }

  return 1;
}

//-----------------------------------------------------------------------------

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
418
419
bool glViewer::pick_region( ACG::SceneGraph::PickTarget                _pickTarget,
                            const QRegion&                             _region,
420
                            QList<QPair<size_t, size_t> >&             _list,
421
422
                            QVector<float>*                            _depths,
                            QVector<ACG::Vec3d>*                       _points)
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
423
{
424
  QRect    rect = _region.boundingRect();
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
425
426
427
  GLint    w = glWidth(),
           h = glHeight(),
           l = scenePos().x(),
428
429
430
           b = scene()->height () - scenePos().y() - h,
           x = rect.x(),
           y = scene()->height () - rect.bottom();
431
432
433

  GLubyte* buffer = 0;
  GLfloat* depths = 0;
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
434

435
436
437
438
439
  
  // prepare GL state
  makeCurrent();
  
  
440
441
442
443
444
445
446
447
448
449
450
  if (pickCacheSupported_)
  {
    // delete pick cache if the size changed
    if (pickCache_ && pickCache_->size () != QSize (glWidth (), glHeight ()))
    {
      delete pickCache_;
      pickCache_ = NULL;
    }
    // create a new pick cache frambuffer object
    if (!pickCache_)
    {
451
      pickCache_ = new QFramebufferObject (glWidth (), glHeight (), QFramebufferObject::Depth);
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
      if (!pickCache_->isValid ())
      {
        pickCacheSupported_ = false;
        delete pickCache_;
        pickCache_ = NULL;
      }
    }
    if (pickCache_)
    {
      // the viewport for the framebuffer object
      l = 0;
      b = 0;
      x = rect.x() - scenePos().x();
      y = glHeight() - (rect.bottom() - scenePos().y());

      // we can only pick inside of our window
      if (x < 0 || y < 0 || x >= (int)glWidth() || y >= (int)glHeight())
        return 0;

      pickCache_->bind ();
    }
  }
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
474
475
476
477

  const ACG::GLMatrixd&  modelview  = properties_.glState().modelview();
  const ACG::GLMatrixd&  projection = properties_.glState().projection();

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
478
479
480
  ACG::Vec4f clear_color = properties_.glState().clear_color();
  properties_.glState().set_clear_color (ACG::Vec4f (0.0, 0.0, 0.0, 0.0));

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
481
482
483
484
485
486
487
488

  glViewport (l, b, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  glMultMatrixd(projection.get_raw_data());
  glMatrixMode(GL_MODELVIEW);
  glLoadMatrixd(modelview.get_raw_data());
489
490
491
  ACG::GLState::disable(GL_LIGHTING);
  ACG::GLState::disable(GL_BLEND);
  ACG::GLState::enable(GL_DEPTH_TEST);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
492
493
494
495
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  properties_.glState().pick_init (true);

  // do the picking
Jan Möbius's avatar
Jan Möbius committed
496
  ACG::SceneGraph::PickAction action(properties_.glState(), _pickTarget, properties_.drawMode());
497
  ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action,properties_.glState());
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
498
499
500
501
502
503

  // restore GL state
  glMatrixMode( GL_PROJECTION );
  glLoadMatrixd(projection.get_raw_data());
  glMatrixMode( GL_MODELVIEW );
  glLoadMatrixd(modelview.get_raw_data());
504
505
  ACG::GLState::enable(GL_LIGHTING);
  ACG::GLState::enable(GL_BLEND);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
506

507
  properties_.glState().set_clear_color(clear_color);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
508

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
509
  if (properties_.glState().pick_error ())
510
511
512
  {
    if (pickCache_ && pickCache_->isBound ())
      pickCache_->release ();
Jan Möbius's avatar
Jan Möbius committed
513
    return false;
514
  }
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
515

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
516
  buffer = new GLubyte[4 * rect.width() * rect.height()];
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
517

Henrik Zimmer's avatar
Henrik Zimmer committed
518
519
520
521
522
523
524
525


  glPixelStorei(GL_PACK_ALIGNMENT, 1);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

  glReadPixels (x, y, rect.width(),
                rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, buffer);

526
527
528
  if (_depths || _points ) {
    depths = new GLfloat[ rect.width() * rect.height() ];
    glReadPixels (x, y, rect.width(), rect.height(), GL_DEPTH_COMPONENT, GL_FLOAT, depths);
Henrik Zimmer's avatar
Henrik Zimmer committed
529

530
531
    /*  Debug code, writing out the depth image
    QImage depthmapimage(rect.width(), rect.height(), QImage::Format_Indexed8);
Henrik Zimmer's avatar
Henrik Zimmer committed
532

533
534
535
    // color map
    for ( int i = 0 ; i <= 255 ; i++ )
      depthmapimage.setColor( i, qRgb( i, i, i ) );
Henrik Zimmer's avatar
Henrik Zimmer committed
536

537
538
    for ( int i = 0 ; i < rect.width() ; i++ )
      for ( int j = 0 ; j < rect.height() ; j++ )
Henrik Zimmer's avatar
Henrik Zimmer committed
539
      {
540
        depthmapimage.setPixel(i,rect.height()-j-1, (unsigned int)(depths[j*rect.width()+i]*255));
Henrik Zimmer's avatar
Henrik Zimmer committed
541
542
      }

543
544
    depthmapimage.save("test.png");
    */
Henrik Zimmer's avatar
Henrik Zimmer committed
545
546
  }

547
  // Iterate over the bounding rectangle of the region
Henrik Zimmer's avatar
Henrik Zimmer committed
548
549
550
551
  for (int y = 0; y < rect.height (); y++)
    for (int x = 0; x < rect.width (); x++)
    {

552
553
      // Check if the current point is in the polygon of the region
      if (_region.contains (QPoint (rect.x() + x, rect.y() + y)))
Henrik Zimmer's avatar
Henrik Zimmer committed
554
555
      {

556
557
        // Calculate position inside the buffer
        const int bPos = (((rect.height () - (y + 1)) * rect.width ()) + x) * 4;
Henrik Zimmer's avatar
Henrik Zimmer committed
558

559
        // Get the picking color from the buffer at the current position
Henrik Zimmer's avatar
Henrik Zimmer committed
560
561
562
563
564
565
566
567
        if (buffer[bPos + 2] != 0 || buffer[bPos + 1] != 0 || buffer[bPos] != 0 || buffer[bPos + 3] != 0)
        {
          ACG::Vec4uc rgba;
          rgba[0] = buffer[bPos];
          rgba[1] = buffer[bPos + 1];
          rgba[2] = buffer[bPos + 2];
          rgba[3] = buffer[bPos + 3];

568
          std::vector<size_t> rv = properties_.glState().pick_color_to_stack (rgba);
Henrik Zimmer's avatar
Henrik Zimmer committed
569
570
571
          if (rv.size () < 2)
            continue;

572
          QPair<size_t, size_t> curr(rv[1], rv[0]);
Henrik Zimmer's avatar
Henrik Zimmer committed
573
574
575
576
577
578
          
          // added a new (targetidx/nodeidx) pair
          if( !_list.contains(curr))
          {
            _list << curr;

579
            if ( _depths  || _points ) {
Henrik Zimmer's avatar
Henrik Zimmer committed
580

581
582
583
584
585
586
587
588
589
590
              const double curr_depth(depths[(rect.height()-(y+1))*rect.width() + x]);

              // If depths should be returned, we extract it here
              if (_depths)
                (*_depths) << curr_depth;

              // unproject depth to real (3D) depth value
              if ( _points )
                (*_points) << properties_.glState().unproject(ACG::Vec3d(x+rect.x(),h-(y+rect.y()),curr_depth));
            }
Henrik Zimmer's avatar
Henrik Zimmer committed
591
592
593
594
595
          }
        }
      }
    }

596
  delete[] buffer;
597
598
599

  if ( _depths  || _points )
    delete[] depths;
Henrik Zimmer's avatar
Henrik Zimmer committed
600
601
602
603
604
605
606
607
608
609
610
611
612

  // unbind pick cache
  if (pickCache_ && pickCache_->isBound ())
  {
    pickCache_->release ();
    updatePickCache_ = false;
    pickCacheTarget_ = _pickTarget;
  }

  return true;
}


Jan Möbius's avatar
Dennis:    
Jan Möbius committed
613
614
//-----------------------------------------------------------------------------

Jan Möbius's avatar
   
Jan Möbius committed
615
bool
Jan Möbius's avatar
   
Jan Möbius committed
616
glViewer::
Jan Möbius's avatar
   
Jan Möbius committed
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
fast_pick( const QPoint&  _mousePos,
           ACG::Vec3d&    _hitPoint )
{
  // get x,y,z values of pixel
  GLint     x(_mousePos.x()), y(glHeight() - _mousePos.y());
  GLfloat   z;


  makeCurrent();
  glPixelStorei(GL_PACK_ALIGNMENT, 1);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);


  if (z < 0.99999)
  {
633
    _hitPoint = properties_.glState().unproject( ACG::Vec3d(x, y, z) );
Jan Möbius's avatar
   
Jan Möbius committed
634
635
636
637
638
639
640
641
642
    return true;
  }
  else return false;
}


//=============================================================================

//=============================================================================