Developer Documentation
MeshNode2T_impl.hh
1 #pragma once
2 /*===========================================================================*\
3  * *
4  * OpenFlipper *
5  * Copyright (c) 2001-2015, RWTH-Aachen University *
6  * Department of Computer Graphics and Multimedia *
7  * All rights reserved. *
8  * www.openflipper.org *
9  * *
10  *---------------------------------------------------------------------------*
11  * This file is part of OpenFlipper. *
12  *---------------------------------------------------------------------------*
13  * *
14  * Redistribution and use in source and binary forms, with or without *
15  * modification, are permitted provided that the following conditions *
16  * are met: *
17  * *
18  * 1. Redistributions of source code must retain the above copyright notice, *
19  * this list of conditions and the following disclaimer. *
20  * *
21  * 2. Redistributions in binary form must reproduce the above copyright *
22  * notice, this list of conditions and the following disclaimer in the *
23  * documentation and/or other materials provided with the distribution. *
24  * *
25  * 3. Neither the name of the copyright holder nor the names of its *
26  * contributors may be used to endorse or promote products derived from *
27  * this software without specific prior written permission. *
28  * *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
32  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
33  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
34  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
35  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
36  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
37  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
38  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
40  * *
41 \*===========================================================================*/
42 
43 
44 
45 
46 
47 
48 //=============================================================================
49 //
50 // CLASS MeshNodeT - IMPLEMENTATION
51 //
52 //=============================================================================
53 
54 #define ACG_MESHNODE_C
55 
56 #include "MeshNode2T.hh"
57 
58 #include <ACG/Geometry/GPUCacheOptimizer.hh>
59 #include <ACG/GL/DrawMesh.hh>
60 #include <ACG/GL/GLError.hh>
61 #include <ACG/GL/GLState.hh>
62 
63 //== NAMESPACES ===============================================================
64 
65 
66 namespace ACG {
67 namespace SceneGraph {
68 
69 
70 //== INCLUDES =================================================================
71 
72 
73 
74 template<class Mesh>
76 MeshNodeT(Mesh& _mesh,
77  BaseNode* _parent,
78  const std::string& _name ):
79  MeshNodeBase(_parent, _name),
80  mesh_(_mesh),
81  drawMesh_(0),
82  enableNormals_(true),
83  enableColors_(true),
84  enabled_arrays_(0),
85  updateVertexPicking_(true),
86  vertexPickingBaseIndex_(0),
87  updateEdgePicking_(true),
88  edgePickingBaseIndex_(0),
89  updateFacePicking_(true),
90  facePickingBaseIndex_(0),
91  updateAnyPicking_(true),
92  anyPickingBaseIndex_(0),
93  perFaceTextureIndexAvailable_(false),
94  textureMap_(0),
95  draw_with_offset_(false)
96 {
97 
99 
100  drawMesh_ = new DrawMeshT<Mesh>(mesh_);
101 
102  // Hand draw mesh down to super class.
103  MeshNodeBase::supplyDrawMesh(drawMesh_);
104 }
105 
106 template<class Mesh>
109 {
110  // Delete all allocated buffers
111  delete drawMesh_;
112 }
113 
114 template<class Mesh>
118  DrawModes::DrawMode drawModes(DrawModes::NONE);
119 
120  // We can always render points and a wireframe.
121  drawModes |= DrawModes::POINTS;
122  drawModes |= DrawModes::HIDDENLINE;
123  drawModes |= DrawModes::WIREFRAME;
124  drawModes |= DrawModes::HALFEDGES;
125 
126  if (mesh_.has_vertex_normals())
127  {
128  drawModes |= DrawModes::POINTS_SHADED;
129  drawModes |= DrawModes::SOLID_SMOOTH_SHADED;
130  drawModes |= DrawModes::SOLID_PHONG_SHADED;
131  }
132 
133  if (mesh_.has_face_normals())
134  drawModes |= DrawModes::SOLID_FLAT_SHADED;
135 
136  if (mesh_.has_halfedge_normals())
137  drawModes |= DrawModes::SOLID_SMOOTH_SHADED_FEATURES;
138 
139  if (mesh_.has_vertex_colors())
140  {
141  drawModes |= DrawModes::POINTS_COLORED;
142  drawModes |= DrawModes::SOLID_POINTS_COLORED;
143 
144  if (mesh_.has_vertex_normals())
145  drawModes |= DrawModes::SOLID_POINTS_COLORED_SHADED;
146  }
147 
148  if(mesh_.has_edge_colors())
149  {
150  drawModes |= DrawModes::EDGES_COLORED;
151  }
152 
153  if(mesh_.has_halfedge_colors())
154  {
155  drawModes |= DrawModes::HALFEDGES_COLORED;
156  }
157 
158  bool enableTexturedFaces = drawMesh_->perFaceTextureCoordinateAvailable() != 0;
159 
160  if (mesh_.has_face_colors()) {
161  drawModes |= DrawModes::SOLID_FACES_COLORED;
162 
163  if( mesh_.has_face_normals() )
164  drawModes |= DrawModes::SOLID_FACES_COLORED_FLAT_SHADED;
165 
166  if (mesh().has_vertex_normals()) {
167  drawModes |= DrawModes::SOLID_FACES_COLORED_SMOOTH_SHADED;
168 
169  if (enableTexturedFaces)
170  drawModes |= DrawModes::SOLID_FACES_COLORED_2DTEXTURED_FACE_SMOOTH_SHADED;
171  }
172  }
173 
174  if ( mesh_.has_vertex_texcoords2D() ) {
175  drawModes |= DrawModes::SOLID_TEXTURED;
176 
177  if (mesh_.has_vertex_normals())
178  drawModes |= DrawModes::SOLID_TEXTURED_SHADED;
179  }
180 
181  if ( enableTexturedFaces ) {
182  drawModes |= DrawModes::SOLID_2DTEXTURED_FACE;
183 
184  if (mesh_.has_face_normals())
185  drawModes |= DrawModes::SOLID_2DTEXTURED_FACE_SHADED;
186  }
187 
188  return drawModes;
189 }
190 
191 template<class Mesh>
192 void
194 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax) {
195  _bbMin.minimize(bbMin_);
196  _bbMax.maximize(bbMax_);
197 }
198 
199 template<class Mesh>
200 void
202 draw(GLState& _state, const DrawModes::DrawMode& _drawMode) {
203 
204 /*
205  if ( ( _drawMode & DrawModes::SOLID_FLAT_SHADED ) ||
206  ( _drawMode & DrawModes::SOLID_FACES_COLORED_FLAT_SHADED) ||
207  ( _drawMode & DrawModes::SOLID_TEXTURED) ||
208  ( _drawMode & DrawModes::SOLID_2DTEXTURED_FACE))
209  {
210  drawMesh_->setFlatShading();
211  }
212  else
213  drawMesh_->setSmoothShading();
214 
215 
216  if ( (_drawMode & DrawModes::SOLID_FACES_COLORED ||
217  _drawMode & DrawModes::SOLID_FACES_COLORED_FLAT_SHADED))
218  {
219  drawMesh_->usePerFaceColors();
220  }
221  else
222  drawMesh_->usePerVertexColors();
223 */
224 
225 
226  glPushAttrib(GL_ENABLE_BIT);
227 
228  GLenum prev_depth_offset = _state.depthFunc();
229  if(draw_with_offset_)
230  {
231  ACG::GLState::enable(GL_POLYGON_OFFSET_FILL);
232  glPolygonOffset(-1.0f, -10.0f);
233  ACG::GLState::depthFunc(GL_LEQUAL);
234  }
235 
236  GLenum prev_depth = _state.depthFunc();
237 
239  GLuint lastBuffer = ACG::GLState::getBoundTextureBuffer();
240  GLenum lastTarget = ACG::GLState::getBoundTextureTarget();
241 
242  // Unbind to avoid painting textures on non textured primitives
243  ACG::GLState::bindTexture(lastTarget,0);
244 
245 
246  if ( (_drawMode & DrawModes::POINTS) || (_drawMode & DrawModes::POINTS_COLORED) || (_drawMode & DrawModes::POINTS_SHADED ) ) {
247 
248  _state.set_color( _state.specular_color() );
249 
250  ACG::GLState::shadeModel(GL_FLAT);
251 
252  if ( _drawMode & DrawModes::POINTS_SHADED ) {
253  ACG::GLState::enable(GL_LIGHTING);
254  } else
255  ACG::GLState::disable(GL_LIGHTING);
256 
257  // Use Colors in this mode if allowed
258  if ( enableColors_ && (_drawMode & DrawModes::POINTS_COLORED) )
259  {
260  drawMesh_->usePerVertexColors();
261 
262  // If we have colors and lighting with normals, we have to use colormaterial
263  if ( enableNormals_ && (_drawMode & DrawModes::POINTS_SHADED ) )
264  ACG::GLState::enable(GL_COLOR_MATERIAL);
265  else
266  ACG::GLState::disable(GL_COLOR_MATERIAL);
267  }
268  else
269  drawMesh_->disableColors();
270 
271  // Bring the arrays online
272 // enable_arrays(arrays);
273 
274  // Draw vertices
275  draw_vertices();
276  }
277 
278 
280  if (_drawMode & DrawModes::WIREFRAME)
281  {
282 
283  const Vec4f oldColor = _state.color();
284 
285  // If the mode is atomic, we use the specular, otherwise we take the overlay color
286  if (_drawMode.isAtomic() )
287  _state.set_color( _state.specular_color() );
288  else
289  _state.set_color( _state.overlay_color() );
290 
291  ACG::GLState::disable(GL_LIGHTING);
292  ACG::GLState::shadeModel(GL_FLAT);
293 
294  drawMesh_->disableColors();
295 
296  draw_lines();
297 
298  _state.set_color(oldColor);
299  }
300 
301  if (_drawMode & DrawModes::HIDDENLINE)
302  {
303 // enable_arrays(VERTEX_ARRAY);
304 
305  // First:
306  // Render all faces in background color to initialize z-buffer
307  ACG::GLState::disable(GL_LIGHTING);
308  ACG::GLState::shadeModel(GL_FLAT);
309  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
310 
311 // drawMesh_->SetFlatShading();
312  drawMesh_->disableColors();
313 
314  Vec4f clear_color = _state.clear_color();
315  clear_color[3] = 1.0;
316  _state.set_color( clear_color );
317 
318  ACG::GLState::depthRange(0.01, 1.0);
319  draw_faces();
320  ACG::GLState::depthRange(0.0, 1.0);
321 
322  // Second
323  // Render the lines. All lines not on the front will be skipped in z-test
324 // enable_arrays(VERTEX_ARRAY|LINE_INDEX_ARRAY);
325  ACG::GLState::depthFunc(GL_LEQUAL);
326 
327  _state.set_color( _state.specular_color() );
328 
329  draw_lines();
330 
331  //restore depth buffer comparison function for the next draw calls inside this function
332  ACG::GLState::depthFunc(prev_depth);
333  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
334  }
335 
336 
337  if (_drawMode & DrawModes::EDGES_COLORED)
338  {
339  enable_arrays( PER_EDGE_VERTEX_ARRAY | PER_EDGE_COLOR_ARRAY );
340  ACG::GLState::disable(GL_LIGHTING);
341  ACG::GLState::shadeModel(GL_FLAT);
342  draw_lines();
343  }
344 
345  if (_drawMode & DrawModes::HALFEDGES)
346  {
347  _state.set_color( _state.specular_color() );
348 
349  enable_arrays( PER_HALFEDGE_VERTEX_ARRAY);
350  ACG::GLState::disable(GL_LIGHTING);
351  ACG::GLState::shadeModel(GL_FLAT);
352  draw_halfedges();
353  }
354 
355  if (_drawMode & DrawModes::HALFEDGES_COLORED)
356  {
357  enable_arrays( PER_HALFEDGE_VERTEX_ARRAY | PER_HALFEDGE_COLOR_ARRAY );
358  ACG::GLState::disable(GL_LIGHTING);
359  ACG::GLState::shadeModel(GL_FLAT);
360  draw_halfedges();
361  }
362 
363  if ( ( _drawMode & DrawModes::SOLID_POINTS_COLORED ) && mesh_.has_vertex_colors() )
364  {
365  ACG::GLState::disable(GL_LIGHTING);
366  ACG::GLState::shadeModel(GL_SMOOTH);
367  ACG::GLState::depthRange(0.01, 1.0);
368 
369  drawMesh_->usePerVertexColors();
370 
371  draw_faces();
372  ACG::GLState::depthRange(0.0, 1.0);
373  }
374 
375  if ( ( _drawMode & DrawModes::SOLID_POINTS_COLORED_SHADED ) && mesh_.has_vertex_colors() && mesh_.has_vertex_normals() )
376  {
377  ACG::GLState::enable(GL_LIGHTING);
378  ACG::GLState::shadeModel(GL_SMOOTH);
379  ACG::GLState::depthRange(0.01, 1.0);
380  if ( enableNormals_ ) {
381  ACG::GLState::enable(GL_COLOR_MATERIAL);
382  } else {
383  ACG::GLState::disable(GL_COLOR_MATERIAL);
384  }
385 
386  drawMesh_->usePerVertexColors();
387 
388  draw_faces();
389  ACG::GLState::depthRange(0.0, 1.0);
390  }
391 
392  if ( ( _drawMode & DrawModes::SOLID_FLAT_SHADED ) && mesh_.has_face_normals() && mesh_.n_faces() > 0)
393  {
394  ACG::GLState::enable(GL_LIGHTING);
395  ACG::GLState::shadeModel(GL_FLAT);
396  ACG::GLState::depthRange(0.01, 1.0);
397 
398  drawMesh_->setFlatShading();
399  drawMesh_->disableColors();
400 
401  draw_faces();
402  ACG::GLState::depthRange(0.0, 1.0);
403  }
404 
405  if ( ( _drawMode & DrawModes::SOLID_SMOOTH_SHADED ) && mesh_.has_vertex_normals() )
406  {
407  ACG::GLState::enable(GL_LIGHTING);
408  ACG::GLState::shadeModel(GL_SMOOTH);
409  ACG::GLState::depthRange(0.01, 1.0);
410 
411  drawMesh_->usePerVertexNormals();
412  drawMesh_->setSmoothShading();
413  drawMesh_->disableColors();
414  draw_faces();
415  ACG::GLState::depthRange(0.0, 1.0);
416  }
417 
418  if ( ( _drawMode & DrawModes::SOLID_PHONG_SHADED ) && mesh_.has_vertex_normals() )
419  {
421  // if ( parent() != 0 ) {
422  // if ( parent()->className() == "ShaderNode" ) {
423  //
424  // ShaderNode* node = dynamic_cast< ShaderNode* > ( parent() );
425  //
426  // GLSL::PtrProgram program = node->getShader( DrawModes::SOLID_PHONG_SHADED );
427  //
428  // // Enable own Phong shader
429  // program->use();
430 // enable_arrays(VERTEX_ARRAY | NORMAL_VERTEX_ARRAY );
431  ACG::GLState::disable(GL_LIGHTING);
432  ACG::GLState::shadeModel(GL_SMOOTH);
433  ACG::GLState::depthRange(0.01, 1.0);
434 
435  drawMesh_->usePerVertexNormals();
436  drawMesh_->setSmoothShading();
437  drawMesh_->disableColors();
438 
439  draw_faces();
440  ACG::GLState::depthRange(0.0, 1.0);
441 
442  //disable own Phong shader
443  // program->disable();
444  // }
445  // }
446  }
447 
448 
449  if ( ( _drawMode & DrawModes::SOLID_FACES_COLORED ) && mesh_.has_face_colors() && mesh_.n_faces() > 0)
450  {
451  Vec4f base_color_backup = _state.base_color();
452 
453  ACG::GLState::disable(GL_LIGHTING);
454  ACG::GLState::shadeModel(GL_FLAT);
455  ACG::GLState::depthRange(0.01, 1.0);
456 // enable_arrays(PER_FACE_VERTEX_ARRAY | PER_FACE_COLOR_ARRAY);
457 
458  drawMesh_->usePerFaceColors();
459 
460  draw_faces();
461  ACG::GLState::depthRange(0.0, 1.0);
462 
463  _state.set_base_color(base_color_backup);
464  }
465 
466 
467  if ( ( _drawMode & DrawModes::SOLID_SMOOTH_SHADED_FEATURES ) && mesh_.has_halfedge_normals() && mesh_.n_faces() > 0)
468  {
469  ACG::GLState::enable(GL_LIGHTING);
470  ACG::GLState::shadeModel(GL_SMOOTH);
471  ACG::GLState::depthRange(0.01, 1.0);
472 
473  drawMesh_->disableColors();
474  drawMesh_->setSmoothShading();
475  drawMesh_->usePerHalfedgeNormals();
476 
477  draw_faces();
478 
479  ACG::GLState::depthRange(0.0, 1.0);
480  }
481 
482  if ( ( _drawMode & DrawModes::SOLID_FACES_COLORED_FLAT_SHADED ) && mesh_.has_face_colors() && mesh_.has_face_normals() && mesh_.n_faces() > 0 )
483  {
484  Vec4f base_color_backup = _state.base_color();
485  ACG::GLState::enable(GL_LIGHTING);
486 
487  ACG::GLState::shadeModel(GL_FLAT);
488  ACG::GLState::depthRange(0.01, 1.0);
489 // enable_arrays(PER_FACE_VERTEX_ARRAY | PER_FACE_COLOR_ARRAY | PER_FACE_NORMAL_ARRAY );
490 
491  drawMesh_->setFlatShading();
492  drawMesh_->usePerFaceColors();
493 
494  draw_faces();
495  ACG::GLState::depthRange(0.0, 1.0);
496 
497  _state.set_base_color(base_color_backup);
498  }
499 
500 
501  if ( ( _drawMode & DrawModes::SOLID_FACES_COLORED_SMOOTH_SHADED ) && mesh_.has_face_colors() && mesh_.has_vertex_normals() && mesh_.n_faces() > 0)
502  {
503  Vec4f base_color_backup = _state.base_color();
504 
505  ACG::GLState::enable(GL_LIGHTING);
506  ACG::GLState::shadeModel(GL_SMOOTH);
507  ACG::GLState::depthRange(0.01, 1.0);
508 
509  drawMesh_->setSmoothShading();
510  drawMesh_->usePerVertexNormals();
511  drawMesh_->usePerFaceColors();
512 
513 
514  drawMesh_->draw(textureMap_, true);
515  ACG::GLState::depthRange(0.0, 1.0);
516 
517  _state.set_base_color(base_color_backup);
518  }
519 
520  // Rebind the previous texture
521  ACG::GLState::bindTexture(lastTarget,lastBuffer);
522 
523 
524  if ((_drawMode & DrawModes::SOLID_FACES_COLORED_2DTEXTURED_FACE_SMOOTH_SHADED) && mesh_.has_face_colors() && mesh_.has_vertex_normals() && mesh_.n_faces() > 0)
525  {
526  // face colors, texturing via halfedge texcoords, smooth shading of lighting color
527 
528  Vec4f base_color_backup = _state.base_color();
529 
530  ACG::GLState::enable(GL_TEXTURE_2D);
531 
532  ACG::GLState::enable(GL_LIGHTING);
533  ACG::GLState::shadeModel(GL_SMOOTH);
534  ACG::GLState::depthRange(0.01, 1.0);
535 
536  drawMesh_->setSmoothShading();
537  drawMesh_->usePerVertexNormals();
538  drawMesh_->usePerFaceColors();
539  drawMesh_->usePerHalfedgeTexcoords();
540 
541  drawMesh_->draw(textureMap_, true);
542  ACG::GLState::depthRange(0.0, 1.0);
543 
544  ACG::GLState::disable(GL_TEXTURE_2D);
545 
546  _state.set_base_color(base_color_backup);
547  }
548 
549  if ( ( _drawMode & DrawModes::SOLID_TEXTURED ) && mesh_.has_vertex_texcoords2D())
550  {
551  ACG::GLState::enable(GL_TEXTURE_2D);
552  ACG::GLState::disable(GL_LIGHTING);
553  ACG::GLState::shadeModel(GL_FLAT);
554  ACG::GLState::depthRange(0.01, 1.0);
555 
556  drawMesh_->disableColors();
557  drawMesh_->usePerVertexTexcoords();
558 
559 
560  // texture environment: fragment color = texture sample
561  GLint prevTexEnvMode = 0;
562  glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &prevTexEnvMode);
563  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
564 
565  draw_faces();
566  ACG::GLState::depthRange(0.0, 1.0);
567  ACG::GLState::disable(GL_TEXTURE_2D);
568 
569  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, prevTexEnvMode);
570  }
571 
572  if ((_drawMode & DrawModes::SOLID_ENV_MAPPED) && mesh_.has_vertex_normals())
573  {
574  ACG::GLState::enable(GL_TEXTURE_2D);
575  ACG::GLState::disable(GL_LIGHTING);
576  ACG::GLState::shadeModel(GL_FLAT);
577  ACG::GLState::depthRange(0.01, 1.0);
578 
579  drawMesh_->disableColors();
580  drawMesh_->usePerVertexTexcoords();
581 
582 
583  // texture environment: fragment color = texture sample
584  GLint prevTexEnvMode = 0;
585  glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &prevTexEnvMode);
586  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
587 
588  draw_faces();
589  ACG::GLState::depthRange(0.0, 1.0);
590  ACG::GLState::disable(GL_TEXTURE_2D);
591 
592  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, prevTexEnvMode);
593  }
594 
595  if ( ( _drawMode & DrawModes::SOLID_TEXTURED_SHADED ) && mesh_.has_vertex_texcoords2D() && mesh_.has_vertex_normals())
596  {
597 // enable_arrays(VERTEX_ARRAY | NORMAL_VERTEX_ARRAY | TEXCOORD_VERTEX_ARRAY);
598  ACG::GLState::enable(GL_TEXTURE_2D);
599  ACG::GLState::enable(GL_LIGHTING);
600  ACG::GLState::shadeModel(GL_SMOOTH);
601  ACG::GLState::depthRange(0.01, 1.0);
602 
603  drawMesh_->setSmoothShading();
604  drawMesh_->disableColors();
605  drawMesh_->usePerVertexTexcoords();
606 
607  draw_faces();
608  ACG::GLState::depthRange(0.0, 1.0);
609  ACG::GLState::disable(GL_TEXTURE_2D);
610  }
611 
612 
613  // Textured by using coordinates stored in halfedges ... arrays generated by stripprocessor
614  if ( (_drawMode & DrawModes::SOLID_2DTEXTURED_FACE) && mesh_.n_faces() > 0 )
615  {
616  ACG::GLState::enable(GL_TEXTURE_2D);
617 
618 // enable_arrays( PER_FACE_VERTEX_ARRAY | PER_FACE_TEXCOORD_ARRAY );
619 
620  ACG::GLState::disable(GL_LIGHTING);
621  ACG::GLState::shadeModel(GL_FLAT);
622  ACG::GLState::depthRange(0.01, 1.0);
623 
624  drawMesh_->disableColors();
625  drawMesh_->usePerHalfedgeTexcoords();
626 
627  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
628 
629  draw_faces();
630  ACG::GLState::depthRange(0.0, 1.0);
631 
632  ACG::GLState::disable(GL_TEXTURE_2D);
633  }
634 
635 
636  // Textured by using coordinates stored in halfedges
637  if ( ( _drawMode & DrawModes::SOLID_2DTEXTURED_FACE_SHADED ) && mesh_.has_face_normals() && mesh_.n_faces() > 0)
638  {
639  ACG::GLState::enable(GL_TEXTURE_2D);
640 
641  // enable_arrays( PER_FACE_VERTEX_ARRAY | PER_FACE_TEXCOORD_ARRAY | PER_FACE_PER_VERTEX_NORMAL_ARRAY );
642 
643  ACG::GLState::enable(GL_LIGHTING);
644  ACG::GLState::shadeModel(GL_FLAT);
645  ACG::GLState::depthRange(0.01, 1.0);
646 
647  drawMesh_->setFlatShading();
648  drawMesh_->disableColors();
649  drawMesh_->usePerHalfedgeTexcoords();
650 
651  draw_faces();
652  ACG::GLState::depthRange(0.0, 1.0);
653  ACG::GLState::disable(GL_TEXTURE_2D);
654 
655  }
656 
657  enable_arrays(0);
658 
659  // Unbind all remaining buffers
660  ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB , 0 );
661 
662  if(draw_with_offset_)
663  {
664  ACG::GLState::depthFunc(prev_depth_offset);
665  }
666 
667  glPopAttrib();
668 }
669 
670 
671 template <class Mesh>
672 void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const Material* _mat )
673 {
674  RenderObject ro;
675 
676  ro.debugName = "MeshNode";
677 
678  // shader gen setup (lighting, shademode, vertex-colors..)
679 
680  for (unsigned int i = 0; i < _drawMode.getNumLayers(); ++i)
681  {
682  const DrawModes::DrawModeProperties* props = _drawMode.getLayer(i);
683 
684  // reset renderobject
685  ro.initFromState(&_state);
686  ro.priority = 0;
687  ro.depthRange = Vec2f(0.0f, 1.0f);
688  ro.depthTest = true; // some previous node disabled depth testing
689  ro.depthWrite = true;
690  ro.depthFunc = GL_LESS;
691  ro.setMaterial(_mat);
692 
693 
694  ro.shaderDesc.vertexTemplateFile.clear(); //QString(props->vertexShader().c_str());
695  ro.shaderDesc.geometryTemplateFile.clear(); //QString(props->geometryShader().c_str());
696  ro.shaderDesc.fragmentTemplateFile.clear(); //QString(props->fragmentShader().c_str());
697 
699 
700  // ------------------------
701  // 1. setup drawMesh based on property source
702 
703 
704  ro.shaderDesc.vertexColors = true;
705 
706  switch (props->colorSource())
707  {
708  case DrawModes::COLOR_PER_VERTEX: drawMesh_->usePerVertexColors(); break;
709  case DrawModes::COLOR_PER_FACE: drawMesh_->usePerFaceColors(); break;
710  default:
711  {
712  drawMesh_->disableColors();
713  ro.shaderDesc.vertexColors = false;
714  } break;
715  }
716 
717  // only the polygon primitives can set the normal source
718  if (props->primitive() == DrawModes::PRIMITIVE_POLYGON)
719  {
720  switch (props->normalSource())
721  {
722  case DrawModes::NORMAL_PER_VERTEX: drawMesh_->usePerVertexNormals(); break;
723  case DrawModes::NORMAL_PER_HALFEDGE: drawMesh_->usePerHalfedgeNormals(); break;
724  default: break;
725  }
726 
727  if (props->flatShaded())
728  drawMesh_->setFlatShading();
729  else
730  drawMesh_->setSmoothShading();
731  }
732 
733 
734  ro.shaderDesc.addTextureType(GL_TEXTURE_2D,false,0);
735 
736  switch (props->texcoordSource())
737  {
738  case DrawModes::TEXCOORD_PER_VERTEX: drawMesh_->usePerVertexTexcoords(); break;
739  case DrawModes::TEXCOORD_PER_HALFEDGE: drawMesh_->usePerHalfedgeTexcoords(); break;
740  default:
741  {
743  }break;
744  }
745 
746  // ------------------------
747  // 2. prepare renderobject
748 
749 
750  // enable / disable lighting
751  ro.shaderDesc.numLights = props->lighting() ? 0 : -1;
752 
753  // Enable/Disable twoSided Lighting
754  ro.shaderDesc.twoSidedLighting = _state.twosided_lighting();
755 
756  // TODO: better handling of attribute sources in shader gen
757  switch (props->lightStage())
758  {
759  case DrawModes::LIGHTSTAGE_SMOOTH:
760  ro.shaderDesc.shadeMode = SG_SHADE_GOURAUD;
761  break;
762  case DrawModes::LIGHTSTAGE_PHONG:
763  ro.shaderDesc.shadeMode = SG_SHADE_PHONG;
764  break;
765  case DrawModes::LIGHTSTAGE_UNLIT:
766  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
767  break;
768  }
769 
770  if (props->flatShaded())
771  ro.shaderDesc.shadeMode = SG_SHADE_FLAT;
772 
773  if (props->normalSource() == DrawModes::NORMAL_PER_FACE)
775  else
777 
778  // handle 'special' primitives (wireframe, hiddenline, primitives in sysmem buffers)..
779 
780  if (props->primitive() == DrawModes::PRIMITIVE_WIREFRAME)
781  {
782  ro.debugName = "MeshNode.Wireframe";
783 
784  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
785  drawMesh_->disableColors();
786 
787  // use specular color for lines
788  if (_drawMode.isAtomic() )
789  ro.emissive = ro.specular;
790  else
791  ro.emissive = OpenMesh::color_cast<ACG::Vec3f>(_state.overlay_color());
792 
793  // allow wireframe + solid mode
794  ro.depthFunc = GL_LEQUAL;
795  ro.priority = -1; // render before polygon
796 
797  ro.setupLineRendering(_state.line_width(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
798 
799  applyRenderObjectSettings(props->primitive(), &ro);
800  drawMesh_->addLineRenderObjects(_renderer, &ro);
801  }
802 
803  if (props->primitive() == DrawModes::PRIMITIVE_HIDDENLINE)
804  {
805  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
806  drawMesh_->disableColors();
807 
808  // use specular color for lines
809  if (_drawMode.isAtomic() )
810  ro.emissive = ro.specular;
811  else
812  ro.emissive = OpenMesh::color_cast<ACG::Vec3f>(_state.overlay_color());
813 
814  // eventually prepare depthbuffer first
815  int polyLayer = _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POLYGON);
816  if ( (polyLayer > int(i) || polyLayer < 0) && ( mesh_.n_faces() != 0 ))
817  {
818  ro.priority = 0;
819 
820  applyRenderObjectSettings(DrawModes::PRIMITIVE_POLYGON, &ro);
821 
822  // disable color write
823  ro.glColorMask(0,0,0,0);
824 
825  ro.debugName = "MeshNode.HiddenLine.faces";
826  add_face_RenderObjects(_renderer, &ro);
827  }
828 
829 
830  // draw lines after depth image
831  ro.priority = 1;
832  ro.glColorMask(1,1,1,1);
833  ro.depthFunc = GL_LEQUAL;
834 
835  ro.setupLineRendering(_state.line_width(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
836 
837  applyRenderObjectSettings(DrawModes::PRIMITIVE_HIDDENLINE, &ro);
838 
839  ro.debugName = "MeshNode.HiddenLine.lines";
840  drawMesh_->addLineRenderObjects(_renderer, &ro);
841  }
842 
843  if (props->colored() && props->primitive() == DrawModes::PRIMITIVE_EDGE)
844  {
845  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
846  ro.shaderDesc.vertexColors = true;
847 
848  // use specular color for lines
849  ro.emissive = ro.specular;
850 
851  // line thickness
852  ro.setupLineRendering(_state.line_width(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
853 
854  applyRenderObjectSettings(props->primitive(), &ro);
855  ro.debugName = "MeshNode.Edges";
856  drawMesh_->addLineRenderObjects(_renderer, &ro);
857 
858  // skip other edge primitives for this drawmode layer
859  continue;
860  }
861 
862  if (props->primitive() == DrawModes::PRIMITIVE_HALFEDGE)
863  {
864  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
865 
866  // buffers in system memory
867  drawMesh_->updateEdgeHalfedgeVertexDeclarations();
868  halfedgeDecl.clear();
869  halfedgeDecl.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, (void *)0);
870 
871  ro.vertexDecl = &halfedgeDecl;
872  // use specular color for lines
873  ro.emissive = ro.specular;
874  ro.vertexBuffer = drawMesh_->getHEVBO();
875  ro.indexBuffer = 0;
876  ro.glDrawArrays(GL_LINES, 0, int(mesh_.n_halfedges() * 2));
877 
878  ro.debugName = "MeshNode.HalfEdges";
879  _renderer->addRenderObject(&ro);
880  }
881 
882 
883  // -----------------------------------------------------
884  // take care of all the other primitives
885 
886  ro.depthRange = Vec2f(0.01f, 1.0f);
887 
888  switch (props->primitive())
889  {
890  case DrawModes::PRIMITIVE_POINT:
891  {
892  if (ro.shaderDesc.shadeMode == SG_SHADE_UNLIT)
893  {
894  // use specular color for points
895  if (_drawMode.isAtomic() )
896  ro.emissive = ro.specular;
897  else
898  ro.emissive = OpenMesh::color_cast<ACG::Vec3f>(_state.overlay_color());
899  }
900 
901  // use shaders to simulate point size
902  ro.setupPointRendering(_mat->pointSize(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
903 
904  applyRenderObjectSettings(props->primitive(), &ro);
905  ro.debugName = "MeshNode.Points";
906  add_point_RenderObjects(_renderer, &ro);
907  } break;
908  case DrawModes::PRIMITIVE_EDGE:
909  {
910  // use specular color for lines
911  ro.emissive = ro.specular;
912 
913  // use shaders to simulate line width
914  ro.setupLineRendering(_state.line_width(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
915 
916  applyRenderObjectSettings(props->primitive(), &ro);
917  ro.debugName = "MeshNode.Edges";
918  drawMesh_->addLineRenderObjects(_renderer, &ro);
919  } break;
920  case DrawModes::PRIMITIVE_POLYGON:
921  {
922  applyRenderObjectSettings(props->primitive(), &ro);
923 
924  if (!ro.shaderDesc.vertexTemplateFile.isEmpty())
925  drawMesh_->scanVertexShaderForInput(ro.shaderDesc.vertexTemplateFile.toStdString());
926 
927  bool useNonIndexed = (props->colorSource() == DrawModes::COLOR_PER_FACE) && (props->lightStage() == DrawModes::LIGHTSTAGE_SMOOTH) && !props->flatShaded();
928  if (!useNonIndexed && props->colorSource() == DrawModes::COLOR_PER_FACE)
930 
931  ro.debugName = "MeshNode.Faces";
932  add_face_RenderObjects(_renderer, &ro, useNonIndexed);
933 
935  } break;
936  default: break;
937  }
938  }
939 
940 }
941 
942 
943 template<class Mesh>
944 void
946 add_point_RenderObjects(IRenderer* _renderer, const RenderObject* _baseObj) {
947  drawMesh_->addPointRenderObjects(_renderer, _baseObj);
948 }
949 
950 template<class Mesh>
951 void
954  drawMesh_->drawVertices();
955 }
956 
957 template<class Mesh>
958 void
961 
962  if ((enabled_arrays_ & PER_EDGE_COLOR_ARRAY) && (enabled_arrays_ & PER_EDGE_VERTEX_ARRAY))
963  {
964  // colored edges still slow
965  glDrawArrays(GL_LINES, 0, int(mesh_.n_edges() * 2));
966  }
967  else
968  drawMesh_->drawLines();
969 }
970 
971 template<class Mesh>
972 void
975  // If we are rendering per edge per vertex attributes, we need to use a seperated vertex buffer!
976  if ( enabled_arrays_ & PER_HALFEDGE_VERTEX_ARRAY )
977  glDrawArrays(GL_LINES, 0, int(mesh_.n_halfedges() * 2));
978  // Something went wrong here!
979  else
980  std::cerr << "Unable to Draw! halfedge array configuration is invalid!!" << std::endl;
981 }
982 
983 template<class Mesh>
984 void
987  drawMesh_->draw(textureMap_);
988 }
989 
990 template<class Mesh>
991 void
993 add_face_RenderObjects(IRenderer* _renderer, const RenderObject* _baseObj, bool _nonindexed) {
994  drawMesh_->addTriRenderObjects(_renderer, _baseObj, textureMap_, _nonindexed);
995 }
996 
997 template<class Mesh>
998 void
1000 enable_arrays(unsigned int _arrays) {
1001 
1002  // Unbind everything to ensure sane settings
1003  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1004  ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1005 
1006  //===================================================================
1007  // per Edge Vertex Array
1008  //===================================================================
1009 
1010  // Check if we should enable the per face vertex array
1011  if (_arrays & PER_EDGE_VERTEX_ARRAY) {
1012 
1013  // Check if its already enabled
1014  if (!(enabled_arrays_ & PER_EDGE_VERTEX_ARRAY)) {
1015  enabled_arrays_ |= PER_EDGE_VERTEX_ARRAY;
1016 
1017  // For this version we load the colors directly not from vbo
1018  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1019  ACG::GLState::vertexPointer( drawMesh_->perEdgeVertexBuffer() );
1020 
1021  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1022 
1023  }
1024  } else if (enabled_arrays_ & PER_EDGE_VERTEX_ARRAY) {
1025  // Disable Vertex array
1026  enabled_arrays_ &= ~PER_EDGE_VERTEX_ARRAY;
1027  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1028  }
1029 
1030  //===================================================================
1031  // per Edge Color Array
1032  //===================================================================
1033 
1034  // Check if we should enable the per face vertex array
1035  if ( mesh_.has_edge_colors() && ( _arrays & PER_EDGE_COLOR_ARRAY) ) {
1036 
1037  // Check if its already enabled
1038  if (!(enabled_arrays_ & PER_EDGE_COLOR_ARRAY)) {
1039  enabled_arrays_ |= PER_EDGE_COLOR_ARRAY;
1040 
1041  // For this version we load the colors directly not from vbo
1042  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1043  ACG::GLState::colorPointer( drawMesh_->perEdgeColorBuffer() );
1044 
1045  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1046 
1047  }
1048  } else if (enabled_arrays_ & PER_EDGE_COLOR_ARRAY) {
1049  // Disable Vertex array
1050  enabled_arrays_ &= ~PER_EDGE_COLOR_ARRAY;
1051  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1052  }
1053 
1054 
1055  //===================================================================
1056  // per Halfedge Vertex Array
1057  //===================================================================
1058 
1059  // Check if we should enable the per face vertex array
1060  if (_arrays & PER_HALFEDGE_VERTEX_ARRAY) {
1061 
1062  // Check if its already enabled
1063  if (!(enabled_arrays_ & PER_HALFEDGE_VERTEX_ARRAY)) {
1064  enabled_arrays_ |= PER_HALFEDGE_VERTEX_ARRAY;
1065 
1066  // For this version we load the colors directly not from vbo
1067  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1068  ACG::GLState::vertexPointer( drawMesh_->perHalfedgeVertexBuffer() );
1069 
1070  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1071 
1072  }
1073  } else if (enabled_arrays_ & PER_HALFEDGE_VERTEX_ARRAY) {
1074  // Disable Vertex array
1075  enabled_arrays_ &= ~PER_HALFEDGE_VERTEX_ARRAY;
1076  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1077  }
1078 
1079  //===================================================================
1080  // per Halfedge Color Array
1081  //===================================================================
1082 
1083  // Check if we should enable the per face vertex array
1084  if ( mesh_.has_halfedge_colors() && ( _arrays & PER_HALFEDGE_COLOR_ARRAY) ) {
1085 
1086  // Check if its already enabled
1087  if (!(enabled_arrays_ & PER_HALFEDGE_COLOR_ARRAY)) {
1088  enabled_arrays_ |= PER_HALFEDGE_COLOR_ARRAY;
1089 
1090  // For this version we load the colors directly not from vbo
1091  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1092  ACG::GLState::colorPointer( drawMesh_->perHalfedgeColorBuffer() );
1093 
1094  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1095 
1096  }
1097  } else if (enabled_arrays_ & PER_HALFEDGE_COLOR_ARRAY) {
1098  // Disable Vertex array
1099  enabled_arrays_ &= ~PER_HALFEDGE_COLOR_ARRAY;
1100  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1101  }
1102 
1103  //===================================================================
1104  // Check for OpenGL Errors
1105  //===================================================================
1106  glCheckErrors();
1107 }
1108 
1109 template<class Mesh>
1110 void
1112 pick(GLState& _state, PickTarget _target) {
1113 
1114  switch (_target)
1115  {
1116  case PICK_VERTEX:
1117  {
1118  pick_vertices(_state);
1119  break;
1120  }
1121  case PICK_FRONT_VERTEX:
1122  {
1123  pick_vertices(_state, true);
1124  break;
1125  }
1126 
1127  case PICK_ANYTHING:
1128  {
1129  pick_any(_state);
1130  break;
1131  }
1132  case PICK_FACE:
1133  {
1134  pick_faces(_state);
1135  break;
1136  }
1137 
1138  case PICK_EDGE:
1139  {
1140  pick_edges(_state);
1141  break;
1142  }
1143 
1144  case PICK_FRONT_EDGE:
1145  {
1146  pick_edges(_state, true);
1147  break;
1148  }
1149 
1150  default:
1151  break;
1152  }
1153 
1154 }
1155 
1156 template<class Mesh>
1157 void
1159 pick_vertices(GLState& _state, bool _front)
1160 {
1161  GLenum prev_depth = _state.depthFunc();
1162 
1163  if (!_state.pick_set_maximum (static_cast<unsigned int>(mesh_.n_vertices()))) {
1164  omerr() << "MeshNode::pick_vertices: color range too small, " << "picking failed\n";
1165  return;
1166  }
1167 
1168  if ( mesh_.n_vertices() == 0 ) {
1169  std::cerr << "pick_vertices: No vertices in Mesh!" << std::endl;
1170  return;
1171  }
1172 
1173  if (_front && ( mesh_.n_faces() != 0 ) ) {
1174 
1175  Vec4f clear_color = _state.clear_color();
1176  Vec4f base_color = _state.base_color();
1177  clear_color[3] = 1.0;
1178 
1179  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1180  glColor(clear_color);
1181 
1182  ACG::GLState::depthRange(0.01, 1.0);
1183  draw_faces();
1184  ACG::GLState::depthRange(0.0, 1.0);
1185 
1186  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1187  ACG::GLState::depthFunc(GL_LEQUAL);
1188  glColor(base_color);
1189 
1190  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1191  }
1192 
1193  // picking implementations:
1194  // 0 -> render mesh with picking color buffer (compatibility mode, add. mem alloc: 16 bytes per openmesh vertex)
1195  // 1 -> render mesh with picking shader (optimized, add. mem alloc: none for point-clouds, otherwise 4 bytes per openmesh vertex on gpu)
1196  int pickImplementationMethod = 0;
1197 
1198  // use optimized picking if supported (the function actually checks whether the shader was linked and bound)
1199  // which shader should be used only depends on the available OpenGL version
1200  if (drawMesh_->supportsPickingVertices_opt())
1201  pickImplementationMethod = openGLVersionTest(3,2) ? 1 : 0;
1202 
1203  if (_state.color_picking () ) {
1204 
1205  if ( updateVertexPicking_ || _state.pick_current_index () != vertexPickingBaseIndex_) {
1206  if (pickImplementationMethod == 0)
1207  drawMesh_->updatePickingVertices(_state);
1208  else
1209  drawMesh_->updatePickingVertices_opt(_state);
1210  vertexPickingBaseIndex_ = _state.pick_current_index ();
1211  updateVertexPicking_ = false;
1212  }
1213 
1214  if (mesh_.n_vertices()) {
1215 
1216  if (pickImplementationMethod == 0) {
1217  // For this version we load the colors directly not from vbo
1218  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1219  ACG::GLState::colorPointer( drawMesh_->pickVertexColorBuffer() );
1220  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1221 
1222  // vertex positions
1223  ACG::GLState::vertexPointer( drawMesh_->pickVertexBuffer() );
1224  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1225 
1226  // Draw color picking
1227  glDrawArrays(GL_POINTS, 0, int(mesh_.n_vertices()));
1228 
1229  // Disable color array
1230  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1231 
1232  // disable vertex array
1233  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1234  }
1235  else if (pickImplementationMethod == 1){
1236 
1237  // optimized rendering of picking ids with shaders
1238  drawMesh_->drawPickingVertices_opt(_state.projection() * _state.modelview(), vertexPickingBaseIndex_);
1239 
1240  }
1241 
1242 
1243  } else {
1244  std::cerr << "pick_vertices: No vertices in Mesh!" << std::endl;
1245  }
1246 
1247  } else {
1248  std::cerr << "No fallback pick_vertices!" << std::endl;
1249  }
1250 
1251  ACG::GLState::depthFunc(prev_depth);
1252 
1253 }
1254 
1255 template<class Mesh>
1256 void
1258 pick_edges(GLState& _state, bool _front)
1259 {
1260  GLenum prev_depth = _state.depthFunc();
1261 
1262  if (!_state.pick_set_maximum (static_cast<unsigned int>(mesh_.n_edges()))) {
1263  omerr() << "MeshNode::pick_edges: color range too small, " << "picking failed\n";
1264  return;
1265  }
1266 
1267  if ( mesh_.n_vertices() == 0 ) {
1268  std::cerr << "pick_edges: No vertices in Mesh!" << std::endl;
1269  return;
1270  }
1271 
1272  if ( _front && ( mesh_.n_faces() != 0 ) ) {
1273 
1274  Vec4f clear_color = _state.clear_color();
1275  Vec4f base_color = _state.base_color();
1276  clear_color[3] = 1.0;
1277 
1278  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1279  glColor(clear_color);
1280 
1281  ACG::GLState::depthRange(0.01, 1.0);
1282  draw_faces();
1283  ACG::GLState::depthRange(0.0, 1.0);
1284 
1285  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1286  ACG::GLState::depthFunc(GL_LEQUAL);
1287  glColor(base_color);
1288 
1289  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1290 
1291  // disable all other arrays
1292  enable_arrays(0);
1293  }
1294 
1295  if (_state.color_picking () && drawMesh_ ) {
1296 
1297  // picking implementations:
1298  // 0 -> render mesh with picking color buffer (compatibility mode, add. mem alloc: 32 bytes per openmesh edge)
1299  // 1 -> render mesh with picking shader (add. mem alloc: none)
1300  int pickImplementationMethod = 0;
1301 
1302  // use optimized picking if supported
1303  if (drawMesh_->supportsPickingEdges_opt())
1304  pickImplementationMethod = openGLVersionTest(3,2) ? 1 : 0;
1305 
1306  if ( updateEdgePicking_ || _state.pick_current_index () != edgePickingBaseIndex_) {
1307  if (pickImplementationMethod == 0)
1308  drawMesh_->updatePickingEdges(_state);
1309  else
1310  drawMesh_->updatePickingEdges_opt(_state);
1311  edgePickingBaseIndex_ = _state.pick_current_index ();
1312  updateEdgePicking_ = false;
1313  }
1314 
1315  if ( mesh_.n_edges() != 0 && drawMesh_) {
1316 
1317  if (pickImplementationMethod == 0){
1318  // For this version we load the colors directly not from vbo
1319  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1320 
1321  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1322  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1323 
1324  ACG::GLState::vertexPointer(drawMesh_->perEdgeVertexBuffer());
1325  ACG::GLState::colorPointer(drawMesh_->pickEdgeColorBuffer());
1326 
1327  glDrawArrays(GL_LINES, 0, int(mesh_.n_edges() * 2));
1328 
1329  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1330  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1331 
1332  // disable all other arrays
1333  enable_arrays(0);
1334  }
1335  else if (pickImplementationMethod == 1){
1336  // optimized rendering of edge ids
1337  drawMesh_->drawPickingEdges_opt(_state.projection() * _state.modelview(), edgePickingBaseIndex_);
1338  }
1339 
1340 
1341  }
1342 
1343  } else {
1344  std::cerr << "No fallback pick_edges!" << std::endl;
1345  }
1346 
1347  ACG::GLState::depthFunc(prev_depth);
1348 
1349 }
1350 
1351 template<class Mesh>
1352 void
1355 {
1356 
1357  if ( mesh_.n_vertices() == 0 ) {
1358  std::cerr << "pick_faces: No vertices in Mesh!" << std::endl;
1359  return;
1360  }
1361 
1362  if ( mesh_.n_faces() > 0 ) {
1363  if (!_state.pick_set_maximum (static_cast<unsigned int>(mesh_.n_faces()))) {
1364  omerr() << "MeshNode::pick_faces: color range too small, " << "picking failed\n";
1365  return;
1366  }
1367  } else {
1368  if (!_state.pick_set_maximum (1)) {
1369  omerr() << "Strange pickSetMAximum failed for index 1 in MeshNode\n";
1370  return;
1371  }
1372  }
1373 
1374  // picking implementations:
1375  // 0 -> render mesh with picking color buffer (compatibility mode, add. mem alloc: 48 bytes per triangle)
1376  // 1 -> render mesh with picking shader (optimized, add. mem alloc: 4 bytes per triangle on gpu)
1377  int pickImplementationMethod = 0;
1378 
1379 
1380  // use optimized picking if supported
1381  if (drawMesh_->supportsPickingFaces_opt())
1382  pickImplementationMethod = openGLVersionTest(3,2) ? 1 : 0;
1383 
1384 // pickImplementationMethod = 0;
1385 
1386  if (_state.color_picking ()) {
1387 
1388  if (pickImplementationMethod == 0) {
1389  // compatibility mode (unoptimized)
1390 
1391  if ( updateFacePicking_ || _state.pick_current_index () != facePickingBaseIndex_) {
1392  drawMesh_->updatePickingFaces(_state);
1393  facePickingBaseIndex_ = _state.pick_current_index ();
1394  updateFacePicking_ = false;
1395  }
1396 
1397  if ( mesh_.n_faces() != 0 ) {
1398 
1399  // For this version we load the colors directly not from vbo
1400  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1401 
1402  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1403  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1404 
1405  ACG::GLState::vertexPointer(drawMesh_->pickFaceVertexBuffer());
1406  ACG::GLState::colorPointer(drawMesh_->pickFaceColorBuffer());
1407 
1408  glDrawArrays(GL_TRIANGLES, 0, int(3 * drawMesh_->getNumTris()));
1409 
1410  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1411  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1412 
1413  // disable all other arrays
1414  enable_arrays(0);
1415 
1416  }
1417 
1418  }
1419  else if (pickImplementationMethod == 1) {
1420 
1421  // render mesh with face picking shader (optimized)
1422 
1423  if ( updateFacePicking_ || _state.pick_current_index () != facePickingBaseIndex_) {
1424  drawMesh_->updatePickingFaces_opt(_state);
1425  facePickingBaseIndex_ = _state.pick_current_index ();
1426  updateFacePicking_ = false;
1427  }
1428 
1429  if ( mesh_.n_faces() != 0 ) {
1430 
1431  drawMesh_->drawPickingFaces_opt(_state.projection() * _state.modelview(), facePickingBaseIndex_);
1432 
1433  /* debug: print color id of first face
1434  Vec4uc facePickingOffsetColor = _state.pick_get_name_color(0);
1435 
1436  std::cout << "base_color: " << int(facePickingOffsetColor[0]) << " " <<
1437  int(facePickingOffsetColor[1]) << " " <<
1438  int(facePickingOffsetColor[2]) << " " <<
1439  int(facePickingOffsetColor[3]) << " " << std::endl;
1440  Vec4uc facePickingOffsetColor = _state.pick_get_name_color(0);
1441  */
1442  }
1443  }
1444  else
1445  std::cerr << "Unknown picking method in pick_faces!" << std::endl;
1446 
1447 
1448  } else
1449  std::cerr << "No fallback pick_faces!" << std::endl;
1450 
1451 }
1452 
1453 template<class Mesh>
1454 void
1457 {
1458  GLenum prev_depth = _state.depthFunc();
1459  size_t numElements = mesh_.n_faces() + mesh_.n_edges() + mesh_.n_vertices();
1460 
1461  if ( mesh_.n_vertices() == 0 ) {
1462  std::cerr << "pick_any: No vertices in Mesh!" << std::endl;
1463  return;
1464  }
1465 
1466  // nothing to pick ?
1467  if (numElements == 0) {
1468  std::cerr << "pick_any: Number of elements : 0 " << std::endl;
1469  return;
1470  }
1471 
1472  if (!_state.pick_set_maximum (static_cast<unsigned int>(numElements)))
1473  {
1474  omerr() << "MeshNode::pick_any: color range too small, " << "picking failed\n";
1475  return;
1476  }
1477 
1478  if (_state.color_picking() && drawMesh_) {
1479 
1480  // picking implementations:
1481  // 0 -> render mesh with picking color buffer (compatibility mode, add. mem alloc: 48 bytes per triangle + 32 bytes per edge + 16 bytes per vertex)
1482  // 1 -> render mesh with picking shader (optimized, add. mem alloc: none [ shared memory with optimized vertex,edge,face picking ])
1483  int pickImplementationMethod = 0;
1484 
1485  // use optimized picking if supported
1486  if (drawMesh_->supportsPickingAny_opt())
1487  pickImplementationMethod = openGLVersionTest(3,2) ? 1 : 0;
1488 
1489 
1490  if ( updateAnyPicking_ || _state.pick_current_index () != anyPickingBaseIndex_) {
1491  if (pickImplementationMethod == 0)
1492  drawMesh_->updatePickingAny(_state);
1493  else
1494  drawMesh_->updatePickingAny_opt(_state);
1495  anyPickingBaseIndex_ = _state.pick_current_index ();
1496  updateAnyPicking_ = false;
1497  }
1498 
1499  if (pickImplementationMethod == 0){
1500  // For this version we load the colors directly, not from vbo
1501  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1502 
1503  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
1504  ACG::GLState::disableClientState(GL_TEXTURE_COORD_ARRAY);
1505 
1506  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1507  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1508 
1509  // If we do not have any faces, we generate an empty list here.
1510  if ( mesh_.n_faces() != 0 && drawMesh_) {
1511 
1512  ACG::GLState::vertexPointer(drawMesh_->pickFaceVertexBuffer());
1513  ACG::GLState::colorPointer(drawMesh_->pickAnyFaceColorBuffer());
1514 
1515  glDrawArrays(GL_TRIANGLES, 0, int(3 * drawMesh_->getNumTris()));
1516  }
1517 
1518  ACG::GLState::depthFunc(GL_LEQUAL);
1519 
1520  // If we do not have any edges, we generate an empty list here.
1521  if ( mesh_.n_edges() != 0 && drawMesh_) {
1522 
1523  ACG::GLState::vertexPointer(drawMesh_->perEdgeVertexBuffer());
1524  ACG::GLState::colorPointer(drawMesh_->pickAnyEdgeColorBuffer());
1525 
1526  glDrawArrays(GL_LINES, 0, int(mesh_.n_edges() * 2));
1527  }
1528 
1529  // For this version we load the colors directly not from vbo
1530  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1531  ACG::GLState::vertexPointer( drawMesh_->pickVertexBuffer() );
1532  ACG::GLState::colorPointer(drawMesh_->pickAnyVertexColorBuffer());
1533 
1534  // Draw color picking
1535  glDrawArrays(GL_POINTS, 0, int(mesh_.n_vertices()));
1536 
1537  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1538  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1539 
1540  // disable all other arrays
1541  enable_arrays(0);
1542  } else {
1543  // optimized version of any picking with shaders
1544  drawMesh_->drawPickingAny_opt(_state.projection() * _state.modelview(), anyPickingBaseIndex_);
1545  }
1546 
1547  } else
1548  std::cerr << "No fallback pick_any!" << std::endl;
1549 
1550  //restore depth buffer comparison function for the active display list
1551  ACG::GLState::depthFunc(prev_depth);
1552 
1553  glCheckErrors();
1554 }
1555 
1556 template<class Mesh>
1557 void
1561  /*
1562  updateFaceList_ = true;
1563  updateAnyList_ = true;
1564  */
1565 
1566  updateVertexPicking_ = true;
1567  updateEdgePicking_ = true;
1568  updateFacePicking_ = true;
1569  updateAnyPicking_ = true;
1570 
1571  // Set per edge arrays to invalid as they have to be regenerated
1572  drawMesh_->invalidatePerEdgeBuffers();
1573 
1574  // Set per halfedge arrays to invalid as they have to be regenerated
1575  drawMesh_->invalidatePerHalfedgeBuffers();
1576 
1577  drawMesh_->updateGeometry();
1578 
1579  drawMesh_->invalidateFullVBO();
1580 
1581  // First of all, we update the bounding box:
1582  bbMin_ = Vec3d(FLT_MAX, FLT_MAX, FLT_MAX);
1583  bbMax_ = Vec3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);
1584  typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
1585 
1586  for (; v_it!=v_end; ++v_it)
1587  {
1588  bbMin_.minimize(mesh_.point(*v_it));
1589  bbMax_.maximize(mesh_.point(*v_it));
1590  }
1591 }
1592 
1593 template<class Mesh>
1594 void
1597 
1598  drawMesh_->invalidatePerEdgeBuffers();
1599  drawMesh_->invalidatePerHalfedgeBuffers();
1600 
1601 
1602  drawMesh_->updateTopology();
1603 
1604  // Unbind the buffer after the work has been done
1605  ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1606 }
1607 
1608 template<class Mesh>
1609 void
1612  drawMesh_->updateTextures();
1613 
1614  updateVertexPicking_ = true;
1615  updateFacePicking_ = true;
1616  updateAnyPicking_ = true;
1617 }
1618 
1619 
1620 
1621 template<class Mesh>
1622 void
1625 
1626  drawMesh_->invalidatePerEdgeBuffers();
1627  drawMesh_->invalidatePerHalfedgeBuffers();
1628 
1629  // TODO: optimize update strategy:
1630  // if only vertex colors have changed, then call UpdateGeometry() (faster)
1631  // for face colors we have to use UpdateFull()
1632  drawMesh_->updateFull();
1633 }
1634 
1635 template<class Mesh>
1636 void
1638 setIndexPropertyName( std::string _indexPropertyName ) {
1639 
1640  drawMesh_->setTextureIndexPropertyName(_indexPropertyName);
1641  perFaceTextureIndexAvailable_ = drawMesh_->perFaceTextureIndexAvailable() != 0;
1642 }
1643 
1644 template<class Mesh>
1645 const std::string&
1648 
1649  return drawMesh_->getTextureIndexPropertyName();
1650 }
1651 
1652 template<class Mesh>
1653 void
1655 setHalfedgeTextcoordPropertyName( std::string _halfedgeTextcoordPropertyName ){
1656  drawMesh_->setPerFaceTextureCoordinatePropertyName(_halfedgeTextcoordPropertyName);
1657 }
1658 
1659 
1660 
1661 
1662 template<class Mesh>
1663 unsigned int
1665 {
1666  unsigned int res = 0;
1667 
1668  if (drawMesh_)
1669  res += drawMesh_->getMemoryUsage();
1670 
1671  return res;
1672 }
1673 
1674 
1675 template<class Mesh>
1678 {
1679  return drawMesh_;
1680 }
1681 
1682 
1683 
1684 
1685 //=============================================================================
1686 } // namespace SceneGraph
1687 } // namespace ACG
1688 //=============================================================================
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
bool color_picking() const
Is color picking active?
Definition: GLState.cc:1141
static GLuint getBoundTextureBuffer()
get bound texture
Definition: GLState.cc:1948
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:144
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
int getLayerIndexByPrimitive(DrawModePrimitive _type) const
search for layer with specified primitive
Definition: DrawModes.cc:618
void pointSize(float _sz)
set point size (default: 1.0)
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1729
picks edges (may not be implemented for all nodes)
Definition: PickTarget.hh:80
const Vec4f & specular_color() const
get specular color
Definition: GLState.hh:966
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
bool flatShaded() const
Is flat shading used (Normals per face)?
Definition: DrawModes.hh:225
bool isAtomic() const
Check if this is an atomic draw Mode.
Definition: DrawModes.cc:504
int viewport_width() const
get viewport width
Definition: GLState.hh:847
bool lighting() const
Is lighting enabled?
Definition: DrawModes.hh:216
Namespace providing different geometric functions concerning angles.
picks only visible front verices (may not be implemented for all nodes)
Definition: PickTarget.hh:89
const Vec4f & overlay_color() const
Get overlay color.
Definition: GLState.hh:980
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat) override
Draws the object deferred.
const Vec4f & color()
set color
Definition: GLState.hh:941
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
Draws the object.
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1911
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:951
ShaderGenDesc shaderDesc
Drawmode and other shader params.
size_t pick_current_index() const
Returns the current color picking index (can be used for caching)
Definition: GLState.cc:1131
void clearTextures()
disables texture support and removes all texture types
QString vertexColorsInterpolator
interpolation qualifier for input vertex colors: "flat", "smooth", "noperspective" ...
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:587
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:941
void glCheckErrors()
Definition: GLError.hh:96
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
Definition: GLState.cc:1961
void setupLineRendering(float _lineWidth, const Vec2f &_screenSize)
Setup rendering of thick lines.
bool colored() const
Are colors used?
Definition: DrawModes.hh:222
bool ACGDLLEXPORT openGLVersionTest(const int _major, const int _minor)
Definition: gl.hh:275
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
Definition: GLState.cc:1757
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
Vec2f depthRange
glDepthRange: (znear, zmax)
unsigned int getMemoryUsage()
measures the size in bytes of allocated memory
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
void setupPointRendering(float _pointSize, const Vec2f &_screenSize)
Setup rendering of circle points.
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition: GLState.cc:1584
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
QString vertexNormalInterpolator
interpolation qualifier for vertex shader normal outputs: "flat", "smooth", "noperspective" ...
picks verices (may not be implemented for all nodes)
Definition: PickTarget.hh:82
GLuint indexBuffer
Use vertex array object.
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
Definition: GLState.cc:1570
int viewport_height() const
get viewport height
Definition: GLState.hh:849
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:559
picks only visible front edges (may not be implemented for all nodes)
Definition: PickTarget.hh:87
static GLenum getBoundTextureTarget()
get bound texture target
Definition: GLState.cc:1953
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition: DrawModes.hh:177
void set_color(const Vec4f &_col)
set color
Definition: GLState.cc:691
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
static void colorPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glColorPointer, supports locking
Definition: GLState.cc:2005
void addTextureType(GLenum _type, bool _shadow, size_t _stage)
adds a texture type to the shader and enables texturing.
int priority
Priority to allow sorting of objects.
Mesh Drawing Class.
Definition: DrawMesh.hh:171
MeshNodeT(Mesh &_mesh, BaseNode *_parent=0, const std::string &_name="<MeshNode>")
Default constructor.
void set_base_color(const Vec4f &_col)
set base color (used when lighting is off)
Definition: GLState.cc:677
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:816
float line_width() const
get line width
Definition: GLState.hh:1000
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition: DrawModes.cc:527
const GLMatrixd & projection() const
get projection matrix
Definition: GLState.hh:811
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
size_t getNumLayers() const
returns the layer count
Definition: DrawModes.cc:523
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:946
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition: GLState.cc:1820
bool twosided_lighting()
get whether transparenet or solid objects should be drawn
Definition: GLState.hh:1065