CoordsysNode.cc 20.8 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1 2 3
/*===========================================================================*\
 *                                                                           *
 *                              OpenFlipper                                  *
Jan Möbius's avatar
Jan Möbius committed
4
 *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
Jan Möbius's avatar
Jan Möbius committed
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
 *                           www.openflipper.org                             *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenFlipper.                                        *
 *                                                                           *
 *  OpenFlipper is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenFlipper is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenFlipper. If not,                                  *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
37
 *   $Revision$                                                       *
Jan Möbius's avatar
Jan Möbius committed
38 39 40 41
 *   $Author$                                                      *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
42 43 44 45 46 47 48 49 50 51 52 53 54




//=============================================================================
//
//  CLASS CoordsysNode - IMPLEMENTATION
//
//=============================================================================

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

#include "CoordsysNode.hh"
55 56
#include <ACG/GL/gl.hh>

Jan Möbius's avatar
 
Jan Möbius committed
57 58 59 60 61 62 63 64 65 66 67 68 69
#include <iostream>
#include <math.h>


//== NAMESPACES ===============================================================

namespace ACG {
namespace SceneGraph {


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


70 71 72 73 74 75 76 77 78 79 80 81
CoordsysNode::CoordsysNode(BaseNode* _parent, std::string _name, CoordsysMode _mode, ProjectionMode _projectionMode) :
        BaseNode(_parent, _name),
        mode_(_mode),
        projectionMode_(_projectionMode)
{
  const double bodyRadius = 0.004;
  const double topRadius = 0.01;
  const int slices = 10;
  const int stacks = 10;

  sphere_   = new ACG::GLSphere(slices,stacks);
  cylinder_ = new ACG::GLCylinder(slices, stacks, bodyRadius,false,false);
Jan Möbius's avatar
Jan Möbius committed
82
  cone_     = new ACG::GLCone(slices, stacks, 0, topRadius , false,true);
83 84 85
}


Jan Möbius's avatar
 
Jan Möbius committed
86 87
void
CoordsysNode::
88
boundingBox(Vec3d& /*_bbMin*/, Vec3d& /*_bbMax*/)
Jan Möbius's avatar
 
Jan Möbius committed
89 90 91 92 93 94 95 96
{
	//_bbMin.minimize( Vect3f  )
}


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


Jan Möbius's avatar
Jan Möbius committed
97
DrawModes::DrawMode
Jan Möbius's avatar
 
Jan Möbius committed
98
CoordsysNode::
Jan Möbius's avatar
Jan Möbius committed
99
availableDrawModes() const
Jan Möbius's avatar
 
Jan Möbius committed
100 101 102 103 104 105 106 107 108 109 110 111 112
{
  return ( DrawModes::POINTS |
	        DrawModes::POINTS_SHADED |
	        DrawModes::POINTS_COLORED );
}


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

void
CoordsysNode::
drawCoordsys( GLState&  _state) {

113 114 115 116 117 118 119
  const double topRadius    = 0.01;
  const double arrowLength  = 0.03;
  const double bodyRadius   = 0.004;
  const double bodyLength   = 0.06;
  const int slices          = 10;
  const int stacks          = 10;
  const double sphereRadius = 0.01;
Jan Möbius's avatar
 
Jan Möbius committed
120 121 122

  // Origin
  glColor3f(0.5, 0.5, 0.5);
123
  sphere_->draw(_state,sphereRadius);
124
  
Jan Möbius's avatar
 
Jan Möbius committed
125 126
  // X-Axis
  glColor3f(1.0, 0.0, 0.0);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
127 128 129
  _state.push_modelview_matrix ();
  _state.rotate (-90, 0, 1, 0);
  _state.translate ( 0, 0, -bodyLength );
130
  cylinder_->draw(_state,bodyLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
131
  _state.translate ( 0, 0, -arrowLength );
132
  cone_->draw(_state,arrowLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
133
  _state.pop_modelview_matrix ();
Jan Möbius's avatar
 
Jan Möbius committed
134 135 136

  // Y-Axis
  glColor3f(0.0, 1.0, 0.0);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
137 138 139
  _state.push_modelview_matrix ();
  _state.rotate (90, 1, 0, 0);
  _state.translate ( 0, 0, -bodyLength );
140
  cylinder_->draw(_state,bodyLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
141
  _state.translate ( 0, 0, -arrowLength );
142
  cone_->draw(_state,arrowLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
143
  _state.pop_modelview_matrix ();
Jan Möbius's avatar
 
Jan Möbius committed
144 145 146

  // Z-Axis
  glColor3f(0.0, 0.0, 1.0);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
147 148 149
  _state.push_modelview_matrix ();
  _state.rotate (180, 0, 1, 0);
  _state.translate ( 0, 0, -bodyLength );
150
  cylinder_->draw(_state,bodyLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
151
  _state.translate ( 0, 0, -arrowLength );
152
  cone_->draw(_state,arrowLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
153
  _state.pop_modelview_matrix ();
Jan Möbius's avatar
 
Jan Möbius committed
154 155 156 157 158 159 160 161

}

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

void
CoordsysNode::drawCoordsysPick( GLState&  _state) {

162 163 164 165 166 167 168
  const double topRadius    = 0.01;
  const double arrowLength  = 0.03;
  const double bodyRadius   = 0.004;
  const double bodyLength   = 0.06;
  const int slices          = 10;
  const int stacks          = 10;
  const double sphereRadius = 0.01;
Jan Möbius's avatar
 
Jan Möbius committed
169 170

  // Origin
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
171
  _state.pick_set_name (1);
172
  sphere_->draw(_state,sphereRadius);
Jan Möbius's avatar
 
Jan Möbius committed
173 174

  // X-Axis
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
175 176 177 178
  _state.pick_set_name (2);
  _state.push_modelview_matrix ();
  _state.rotate (-90, 0, 1, 0);
  _state.translate ( 0, 0, -bodyLength );
179
  cylinder_->draw(_state,bodyLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
180
  _state.translate ( 0, 0, -arrowLength );
181
  cone_->draw(_state,arrowLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
182
  _state.pop_modelview_matrix ();
Jan Möbius's avatar
 
Jan Möbius committed
183

184

Jan Möbius's avatar
 
Jan Möbius committed
185
  // Y-Axis
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
186 187 188 189
  _state.pick_set_name (3);
  _state.push_modelview_matrix ();
  _state.rotate (90, 1, 0, 0);
  _state.translate ( 0, 0, -bodyLength );
190
  cylinder_->draw(_state,bodyLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
191
  _state.translate ( 0, 0, -arrowLength );
192
  cone_->draw(_state,arrowLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
193
  _state.pop_modelview_matrix ();
Jan Möbius's avatar
 
Jan Möbius committed
194 195

  // Z-Axis
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
196 197 198 199
  _state.pick_set_name (4);
  _state.push_modelview_matrix ();
  _state.rotate (180, 0, 1, 0);
  _state.translate ( 0, 0, -bodyLength );
200
  cylinder_->draw(_state,bodyLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
201
  _state.translate ( 0, 0, -arrowLength );
202
  cone_->draw(_state,arrowLength);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
203 204
  _state.pop_modelview_matrix ();

Jan Möbius's avatar
 
Jan Möbius committed
205 206 207 208 209 210 211 212
}


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


void
CoordsysNode::
213
draw(GLState&  _state  , const DrawModes::DrawMode& /*_drawMode*/)
Jan Möbius's avatar
 
Jan Möbius committed
214
{
215 216
  GLenum prev_depth = _state.depthFunc();
    
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
217 218 219
  GLboolean colorMask[4];
  glGetBooleanv (GL_COLOR_WRITEMASK, colorMask);
  
Jan Möbius's avatar
 
Jan Möbius committed
220 221 222 223 224 225
  // Push Modelview-Matrix
  _state.push_modelview_matrix();

  Vec4f lastBaseColor = _state.base_color();

  glPushAttrib( GL_LIGHTING_BIT ); // STACK_ATTRIBUTES <- LIGHTING_ATTRIBUTE
226
  ACG::GLState::enable(GL_LIGHTING);
Jan Möbius's avatar
 
Jan Möbius committed
227
  glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
228 229
  ACG::GLState::enable(GL_COLOR_MATERIAL);
  ACG::GLState::shadeModel(GL_SMOOTH);
Jan Möbius's avatar
 
Jan Möbius committed
230 231 232 233 234 235 236

  // Init state - changes when mode_ != POSITION
  Vec3d pos3D(0.0,0.0,0.0);

  if ( mode_ == SCREENPOS ) {

    int left, bottom, width, height;
237
    double aspect = _state.aspect();
238

Jan Möbius's avatar
 
Jan Möbius committed
239 240 241 242
    _state.get_viewport(left, bottom, width, height);

    // Projection reset
    _state.push_projection_matrix();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
243
    _state.reset_projection();
Jan Möbius's avatar
 
Jan Möbius committed
244

245 246 247
    if (projectionMode_ == PERSPECTIVE_PROJECTION)
        _state.perspective(45.0, aspect, 0.8, 20.0);
    else
248
        _state.ortho(-0.65*aspect, 0.65*aspect, -0.65, 0.65, 0.8, 20.0);
Jan Möbius's avatar
 
Jan Möbius committed
249

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
250 251
    _state.push_modelview_matrix();
    _state.reset_modelview();
Jan Möbius's avatar
 
Jan Möbius committed
252

253 254 255 256 257 258
    float rel_size = 50.0;
    float projdist = sqrt ( (width*height) / rel_size );

    float posx = left + width - projdist ;
    float posy = bottom + height - projdist ;

259
    // get our desired coordsys position in scene coordinates
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
260 261
    pos3D = _state.unproject (Vec3d (posx, posy, 0.5));
    _state.pop_modelview_matrix();
Jan Möbius's avatar
 
Jan Möbius committed
262

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
263
    // reset scene translation
264
    // we want only the scene rotation to rotate the coordsys
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
265
    GLMatrixd modelview = _state.modelview();
Jan Möbius's avatar
 
Jan Möbius committed
266

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
267 268 269
    modelview(0,3) = 0.0;
    modelview(1,3) = 0.0;
    modelview(2,3) = 0.0;
Jan Möbius's avatar
 
Jan Möbius committed
270

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
271
    _state.set_modelview (modelview);
272
    _state.translate (pos3D[0], pos3D[1], pos3D[2], MULT_FROM_LEFT);
Jan Möbius's avatar
 
Jan Möbius committed
273

274 275

    // clear the depth buffer behind the coordsys
Jan Möbius's avatar
Jan Möbius committed
276
    ACG::GLState::depthRange (1.0, 1.0);
277
    ACG::GLState::depthFunc (GL_ALWAYS);
278 279

    drawCoordsys(_state);
280

Jan Möbius's avatar
Jan Möbius committed
281
    ACG::GLState::depthRange (0.0, 1.0);
282
    ACG::GLState::depthFunc (GL_LESS);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
283

284
    // draw coordsys
Jan Möbius's avatar
 
Jan Möbius committed
285 286
    drawCoordsys(_state);

287
    // set depth buffer to 0 so that nothing can paint over cordsys
Jan Möbius's avatar
Jan Möbius committed
288
    ACG::GLState::depthRange (0.0, 0.0);
289
    ACG::GLState::depthFunc (GL_ALWAYS);
290
    glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
291

292 293 294
    // Koordinatensystem zeichnen
    drawCoordsys(_state);

Jan Möbius's avatar
Jan Möbius committed
295
    ACG::GLState::depthRange (0.0, 1.0);
296
    ACG::GLState::depthFunc (prev_depth);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
297
    glColorMask (colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
298

Jan Möbius's avatar
 
Jan Möbius committed
299 300
    // Projection reload
    _state.pop_projection_matrix();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
301

Jan Möbius's avatar
 
Jan Möbius committed
302 303 304

  } else if (mode_ == POSITION) { /* mode_ == POSITION */

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
305 306 307 308 309 310 311
    GLMatrixd modelview = _state.modelview();

    modelview(0,3) = 0.0;
    modelview(1,3) = 0.0;
    modelview(2,3) = 0.0;

    _state.set_modelview (modelview);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
312

313
    // clear depth buffer in coordsys region
Jan Möbius's avatar
Jan Möbius committed
314
    ACG::GLState::depthRange (1.0, 1.0);
315
    ACG::GLState::depthFunc (GL_ALWAYS);
316 317 318 319 320

    // Koordinatensystem zeichnen
    drawCoordsys(_state);

    // draw coordsys in normal mode
Jan Möbius's avatar
Jan Möbius committed
321
    ACG::GLState::depthRange (0.0, 1.0);
322
    ACG::GLState::depthFunc (GL_LESS);
323

324
    // Koordinatensystem zeichnen
Jan Möbius's avatar
 
Jan Möbius committed
325 326
    drawCoordsys(_state);

327
    // set depth buffer to 0 so that nothing can paint over cordsys
Jan Möbius's avatar
Jan Möbius committed
328
    ACG::GLState::depthRange (0.0, 0.0);
329
    ACG::GLState::depthFunc (GL_ALWAYS);
330 331 332 333
    glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);

    // Koordinatensystem zeichnen
    drawCoordsys(_state);
334

335
    // reset to default
Jan Möbius's avatar
Jan Möbius committed
336
    ACG::GLState::depthRange (0.0, 1.0);
337
    ACG::GLState::depthFunc (prev_depth);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
338
    glColorMask (colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
Jan Möbius's avatar
 
Jan Möbius committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
  }

  glPopAttrib();

  glColor4fv(lastBaseColor.data());

  // Reload old configuration
  _state.pop_modelview_matrix();
}


void
CoordsysNode::
setMode(const CoordsysMode _mode)
{
  mode_ = _mode;
}

357 358 359 360 361 362 363
void
CoordsysNode::
setProjectionMode(const ProjectionMode _mode)
{
  projectionMode_ = _mode;
}

Jan Möbius's avatar
 
Jan Möbius committed
364 365 366 367 368 369 370 371 372 373 374 375 376 377
void
CoordsysNode::
setPosition(const Vec3f& _pos)
{
  pos3f_ = _pos;
}

CoordsysNode::CoordsysMode
CoordsysNode::
getMode() const
{
  return mode_;
}

378 379 380 381 382 383 384
CoordsysNode::ProjectionMode
CoordsysNode::
getProjectionMode() const
{
  return projectionMode_;
}

Jan Möbius's avatar
 
Jan Möbius committed
385 386 387
void
CoordsysNode::pick(GLState& _state, PickTarget _target)
{
388 389
  GLenum prev_depth = _state.depthFunc();  
    
Jan Möbius's avatar
Jan Möbius committed
390 391
  if (_target == PICK_ANYTHING) {

Jan Möbius's avatar
Jan Möbius committed
392 393
    GLdouble mat[16];

Jan Möbius's avatar
 
Jan Möbius committed
394
    // Push Modelview-Matrix
Jan Möbius's avatar
Jan Möbius committed
395
    _state.push_modelview_matrix();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
396
    _state.pick_set_maximum (5);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
397
    _state.pick_set_name (0);
Jan Möbius's avatar
 
Jan Möbius committed
398 399

    // Init state - changes when mode_ != POSITION
Jan Möbius's avatar
Jan Möbius committed
400
    Vec3d pos3D(0.0,0.0,0.0);
Jan Möbius's avatar
 
Jan Möbius committed
401

Jan Möbius's avatar
Jan Möbius committed
402
    if ( mode_ == SCREENPOS ) {
Jan Möbius's avatar
 
Jan Möbius committed
403

Jan Möbius's avatar
Jan Möbius committed
404
      int left, bottom, width, height;
405
      double aspect = _state.aspect();
406

Jan Möbius's avatar
Jan Möbius committed
407
      _state.get_viewport(left, bottom, width, height);
408
      
Jan Möbius's avatar
Jan Möbius committed
409 410
      // Projection reset
      _state.push_projection_matrix();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
411
      _state.reset_projection();
Jan Möbius's avatar
 
Jan Möbius committed
412

413 414 415
      if (projectionMode_ == PERSPECTIVE_PROJECTION)
        _state.perspective(45.0, aspect, 0.8, 20.0);
      else
416
        _state.ortho(-0.65*aspect, 0.65*aspect, -0.65, 0.65, 0.8, 20.0);
Jan Möbius's avatar
 
Jan Möbius committed
417

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
418 419
      _state.push_modelview_matrix();
      _state.reset_modelview();
Jan Möbius's avatar
 
Jan Möbius committed
420

421 422 423 424 425 426 427
      float rel_size = 50.0;
      float projdist = sqrt ( (width*height) / rel_size );

      float posx = left + width - projdist ;
      float posy = bottom + height - projdist ;

      // get our desired coordsys position in scene coordinates
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
428 429
      pos3D = _state.unproject (Vec3d (posx, posy, 0.5));
      _state.pop_modelview_matrix();
Jan Möbius's avatar
 
Jan Möbius committed
430

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
431 432
      // reset scene translation
      GLMatrixd modelview = _state.modelview();
Jan Möbius's avatar
 
Jan Möbius committed
433

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
434 435 436
      modelview(0,3) = 0.0;
      modelview(1,3) = 0.0;
      modelview(2,3) = 0.0;
Jan Möbius's avatar
 
Jan Möbius committed
437

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
438
      _state.set_modelview (modelview);
439
      _state.translate (pos3D[0], pos3D[1], pos3D[2], MULT_FROM_LEFT);
Jan Möbius's avatar
 
Jan Möbius committed
440

441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
      // We don't have access to the pick matrix used during selection buffer picking
      // so we can't draw our pick area circle in this case
      if (_state.color_picking ())
      {
        // clear depth buffer behind coordsys node
        clearPickArea(_state, true, 1.0);

        // Koordinatensystem zeichnen
        drawCoordsysPick(_state);

        // set depth buffer to 0.0 so that nothing can paint above
        clearPickArea(_state, false, 0.0);
      }
      else
      {
        // clear depth buffer in coordsys region
Jan Möbius's avatar
Jan Möbius committed
457
        ACG::GLState::depthRange (1.0, 1.0);
458
        ACG::GLState::depthFunc (GL_ALWAYS);
459 460 461 462 463

        // Koordinatensystem zeichnen
        drawCoordsys(_state);

        // draw coordsys in normal mode
Jan Möbius's avatar
Jan Möbius committed
464
        ACG::GLState::depthRange (0.0, 1.0);
465
        ACG::GLState::depthFunc (GL_LESS);
466 467 468 469 470

        // Koordinatensystem zeichnen
        drawCoordsys(_state);

        // set depth buffer to 0 so tah nothing can paint over cordsys
Jan Möbius's avatar
Jan Möbius committed
471
        ACG::GLState::depthRange (0.0, 0.0);
472
        ACG::GLState::depthFunc (GL_ALWAYS);
473 474 475 476 477 478
        glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);

        // Koordinatensystem zeichnen
        drawCoordsys(_state);

        // reset to default
Jan Möbius's avatar
Jan Möbius committed
479
        ACG::GLState::depthRange (0.0, 1.0);
480
        ACG::GLState::depthFunc (prev_depth);
481 482
        glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      }
Jan Möbius's avatar
Jan Möbius committed
483

484 485
      // Projection reload
      _state.pop_projection_matrix();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
486

Jan Möbius's avatar
Jan Möbius committed
487 488
    } else if (mode_ == POSITION) { /* mode_ == POSITION */

489 490 491
      // The selection buffer picking method might have set a 
      // pick matrix that has been multiplied with the projection matrix.
      // This is the only way to get the gl pick matrix again
Jan Möbius's avatar
Jan Möbius committed
492 493 494 495 496 497 498 499 500 501 502 503 504
      glMatrixMode(GL_PROJECTION);

      glPushMatrix ();
      glMultMatrixd( _state.inverse_projection().get_raw_data());

      glGetDoublev(GL_PROJECTION_MATRIX, mat);

      glPopMatrix ();

      GLMatrixd pickMat (mat);

      glMatrixMode(GL_MODELVIEW);

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
505 506 507 508 509 510
      GLMatrixd modelview = _state.modelview();

      modelview(0,3) = 0.0;
      modelview(1,3) = 0.0;
      modelview(2,3) = 0.0;

511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
      // We don't have access to the pick matrix used during selection buffer picking
      // so we can't draw our pick area circle in this case
      if (_state.color_picking ())
      {
        // clear depth buffer behind coordsys node
        clearPickArea(_state, true, 1.0);

        // Koordinatensystem zeichnen
        drawCoordsysPick(_state);

        // set depth buffer to 0.0 so that nothing can paint above
        clearPickArea(_state, false, 0.0);
      }
      else
      {
        // clear depth buffer in coordsys region
Jan Möbius's avatar
Jan Möbius committed
527
        ACG::GLState::depthRange (1.0, 1.0);
528
        ACG::GLState::depthFunc (GL_ALWAYS);
529 530 531 532 533

        // Koordinatensystem zeichnen
        drawCoordsys(_state);

        // draw coordsys in normal mode
Jan Möbius's avatar
Jan Möbius committed
534
        ACG::GLState::depthRange (0.0, 1.0);
535
        ACG::GLState::depthFunc (GL_LESS);
536 537 538 539 540

        // Koordinatensystem zeichnen
        drawCoordsys(_state);

        // set depth buffer to 0 so tah nothing can paint over cordsys
Jan Möbius's avatar
Jan Möbius committed
541
        ACG::GLState::depthRange (0.0, 0.0);
542
        ACG::GLState::depthFunc (GL_ALWAYS);
543 544 545 546 547 548
        glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);

        // Koordinatensystem zeichnen
        drawCoordsys(_state);

        // reset to default
Jan Möbius's avatar
Jan Möbius committed
549
        ACG::GLState::depthRange (0.0, 1.0);
550
        ACG::GLState::depthFunc (prev_depth);
551 552
        glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      }
Jan Möbius's avatar
 
Jan Möbius committed
553
    }
Jan Möbius's avatar
Jan Möbius committed
554 555 556 557
    // Reload old configuration
    _state.pop_modelview_matrix();

  }
Jan Möbius's avatar
 
Jan Möbius committed
558 559
}

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
560 561
//----------------------------------------------------------------------------

562
void CoordsysNode::clearPickArea(GLState&  _state, bool _draw, GLfloat _depth)
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
563
{
564 565
  GLenum prev_depth = _state.depthFunc();
    
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
566 567 568 569 570 571 572
  std::vector<Vec2f> points;
  Vec2f center;
  float radius;

  int left, bottom, width, height;
  _state.get_viewport(left, bottom, width, height);

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
573 574 575
  GLboolean colorMask[4];
  glGetBooleanv (GL_COLOR_WRITEMASK, colorMask);

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
  GLUquadricObj *quadric = gluNewQuadric();

  // respect sphere radius
  Vec3d proj = _state.project (Vec3d (-0.01, -0.01, -0.01));
  points.push_back (Vec2f (proj[0], proj[1]));

  proj = _state.project (Vec3d (0.1, 0.0, 0.0));
  points.push_back (Vec2f (proj[0], proj[1]));

  proj = _state.project (Vec3d (0.0, 0.1, 0.0));
  points.push_back (Vec2f (proj[0], proj[1]));

  proj = _state.project (Vec3d (0.0, 0.0, 0.1));
  points.push_back (Vec2f (proj[0], proj[1]));


  // get bounding circle of projected 4 points of the coord node
  boundingCircle(points, center, radius);

  _state.push_projection_matrix();
  _state.reset_projection();
Jan Möbius's avatar
Jan Möbius committed
597

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
598 599 600 601
  _state.ortho (left, left + width, bottom, bottom + height, 0.0, 1.0);

  _state.push_modelview_matrix();
  _state.reset_modelview();
602
  ACG::GLState::depthFunc (GL_ALWAYS);
Jan Möbius's avatar
Jan Möbius committed
603
  ACG::GLState::depthRange (_depth, _depth);
604
  _state.translate (center[0], center[1], -0.5);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
605

606
  if (_draw)
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
607 608 609 610 611 612 613
    _state.pick_set_name (0);
  else
    glColorMask(false, false, false, false);

  // 10% more to ensure everything is in
  gluDisk( quadric, 0, radius * 1.1, 10, 10 );

614
  ACG::GLState::depthFunc (prev_depth);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
615 616 617
  _state.pop_modelview_matrix();
  _state.pop_projection_matrix();

Jan Möbius's avatar
Jan Möbius committed
618
  ACG::GLState::depthRange (0.0, 1.0);
619 620

  if (!_draw)
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
621
    glColorMask (colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
622

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
  gluDeleteQuadric(quadric);
}

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

void CoordsysNode::boundingCircle(std::vector<Vec2f> &_in, Vec2f &_center, float &_radius)
{
  if (_in.size () == 0)
    return;
  if (_in.size () < 2)
  {
    _center = _in[0];
    _radius = 0.0f;
    return;
  }
  bool found = false;

  // try all circumcircles of all possible lines
  for (unsigned int i = 0; i < _in.size () - 1; i++)
    for (unsigned int j = i + 1; j < _in.size (); j++)
    {
      Vec2f cen = (_in[i] + _in[j]) * 0.5;
      float rad = (_in[i] - cen).length ();
      bool allin = true;

      for (unsigned int k = 0; k < _in.size (); k++)
        if (k != i && k != j && (_in[k] - cen).length () > rad)
        {
          allin = false;
          break;
        }

      if (!allin)
        continue;

      if (found)
      {
        if (rad < _radius)
        {
          _center = cen;
          _radius = rad;
        }
      }
      else
      {
        found = true;
        _center = cen;
        _radius = rad;
      }
    }

  if (found)
    return;

  // try all circumcircles of all possible triangles
  for (unsigned int i = 0; i < _in.size () - 2; i++)
    for (unsigned int j = i + 1; j < _in.size () - 1; j++)
      for (unsigned int k = j + 1; k < _in.size (); k++)
      {
        float v = ((_in[k][0]-_in[j][0])*((_in[i][0]*_in[i][0])+(_in[i][1]*_in[i][1]))) +
                  ((_in[i][0]-_in[k][0])*((_in[j][0]*_in[j][0])+(_in[j][1]*_in[j][1]))) +
                  ((_in[j][0]-_in[i][0])*((_in[k][0]*_in[k][0])+(_in[k][1]*_in[k][1])));
        float u = ((_in[j][1]-_in[k][1])*((_in[i][0]*_in[i][0])+(_in[i][1]*_in[i][1]))) +
                  ((_in[k][1]-_in[i][1])*((_in[j][0]*_in[j][0])+(_in[j][1]*_in[j][1]))) +
                  ((_in[i][1]-_in[j][1])*((_in[k][0]*_in[k][0])+(_in[k][1]*_in[k][1])));
        float d = (_in[i][0]*_in[j][1])+(_in[j][0]*_in[k][1])+(_in[k][0]*_in[i][1]) -
                  (_in[i][0]*_in[k][1])-(_in[j][0]*_in[i][1])-(_in[k][0]*_in[j][1]);
        Vec2f cen(0.5 * (u/d), 0.5 * (v/d));
        float rad = (_in[i] - cen).length ();
        bool allin = true;

        for (unsigned int l = 0; l < _in.size (); l++)
          if (l != i && l != j && l != k && (_in[l] - cen).length () > rad)
          {
            allin = false;
            break;
          }

        if (!allin)
          continue;

        if (found)
        {
          if (rad < _radius)
          {
            _center = cen;
            _radius = rad;
          }
        }
        else
        {
          found = true;
          _center = cen;
          _radius = rad;
        }
      }
}

Jan Möbius's avatar
 
Jan Möbius committed
721 722 723 724
//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================