Developer Documentation
StatusNodesT_impl.hh
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 
43 //=============================================================================
44 //
45 // CLASS StatusNodeT - IMPLEMENTATION
46 //
47 //=============================================================================
48 
49 
50 #define ACG_STATUS_NODES_C
51 
52 
53 //== INCLUDES =================================================================
54 
55 
56 #include "StatusNodesT.hh"
57 #include "../GL/gl.hh"
58 
59 //== NAMESPACES ===============================================================
60 
61 
62 namespace ACG {
63 namespace SceneGraph {
64 
65 
66 //== IMPLEMENTATION ==========================================================
67 
68 template <class Mesh, class Mod>
70 StatusNodeT( const Mesh& _mesh,
71  BaseNode* _parent,
72  const std::string& _name )
73  : BaseClass(_parent, _name), mesh_(_mesh),
74  drawMesh_(NULL),
75  bbMin_(FLT_MAX, FLT_MAX, FLT_MAX),
76  bbMax_(-FLT_MAX, -FLT_MAX, -FLT_MAX),
77  invalidGeometry_(true),
78  vertexIndexInvalid_(true),
79  halfedgeCacheInvalid_(true),
80  edgeIndexInvalid_(true),
81  faceIndexInvalid_(true)
82 {
83  this->set_line_width(3);
84  this->set_point_size(5);
85 }
86 
87 
88 //----------------------------------------------------------------------------
89 
90 
91 template <class Mesh, class Mod>
92 void
94 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
95 {
96  _bbMin.minimize(bbMin_);
97  _bbMax.maximize(bbMax_);
98 }
99 
100 
101 //----------------------------------------------------------------------------
102 
103 
104 template <class Mesh, class Mod>
107 availableDrawModes() const
108 {
109  return (DrawModes::POINTS |
110  DrawModes::WIREFRAME |
111  DrawModes::EDGES |
112  DrawModes::SOLID_FLAT_SHADED);
113 }
114 
115 
116 //----------------------------------------------------------------------------
117 
118 
119 template <class Mesh, class Mod>
120 void
123 {
124  if (invalidGeometry_) {
125 
126  // Vertices, Edges and Faces use the mesh geometry.
127  // However Halfedge selection buffers are computed.
128  // Therefore we have to invalidate them when
129  // the geometry changes to force a recomputation.
130  halfedgeCacheInvalid_ = true;
131 
132  bbMin_ = Vec3d(FLT_MAX, FLT_MAX, FLT_MAX);
133  bbMax_ = Vec3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);
134 
135  typename Mesh::ConstVertexIter v_it(mesh_.vertices_sbegin()), v_end(mesh_.vertices_end());
136 
137  for (; v_it != v_end; ++v_it) {
138  bbMin_.minimize(mesh_.point(*v_it));
139  bbMax_.maximize(mesh_.point(*v_it));
140  }
141 
142  invalidGeometry_ = false;
143 
144  }
145 
146  /*
147  * Hack: Force rebuild of buffers so that mapVertexToVBOIndex call doesn't SEGFAULT.
148  */
149  if (vertexIndexInvalid_ || edgeIndexInvalid_ || halfedgeCacheInvalid_ || faceIndexInvalid_)
150  if (drawMesh_)
151  drawMesh_->getVBO();
152 
153  // Update the indices for selected vertices
154  if (vertexIndexInvalid_) {
155  v_cache_.clear();
156  v_cache_.reserve(mesh_.n_vertices()/4);
157 
158  typename Mesh::ConstVertexIter v_it(mesh_.vertices_sbegin()), v_begin(mesh_.vertices_sbegin()), v_end(mesh_.vertices_end());
159  for (v_it = v_begin; v_it != v_end; ++v_it) {
160  if (this->is_vertex_selected(mesh_, *v_it)) {
161  unsigned int vertexIndex = v_it->idx();
162  // use correct index for vbo, if available
163  v_cache_.push_back(drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vertexIndex) : vertexIndex);
164  }
165  }
166  std::vector<unsigned int>(v_cache_.begin(), v_cache_.end()).swap(v_cache_);
167  if(v_cache_.size() > 0)
168  updateIBOData(vIBO_, v_cache_.size(), sizeof(v_cache_[0]), v_cache_.data());
169  vertexIndexInvalid_ = false;
170  }
171 
172  // Update index list of selected edges
173  if (edgeIndexInvalid_) {
174 
175  e_cache_.clear();
176  e_cache_.reserve(mesh_.n_edges()/4);
177 
178  typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_begin(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
179  for (e_it = e_begin; e_it != e_end; ++e_it) {
180  if (this->is_edge_selected(mesh_, *e_it)) {
181  typename Mesh::VertexHandle vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 0));
182  unsigned int vidx = vh.idx();
183 
184  e_cache_.push_back(drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vidx) : vidx);
185 
186  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 1));
187  vidx = vh.idx();
188 
189  e_cache_.push_back(drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vidx) : vidx);
190  }
191  }
192 
193  std::vector<unsigned int>(e_cache_.begin(), e_cache_.end()).swap(e_cache_);
194  // update edge index buffer
195  if(e_cache_.size() > 0)
196  updateIBOData(eIBO_, e_cache_.size() , sizeof(e_cache_[0]) , e_cache_.data());
197  edgeIndexInvalid_ = false;
198  }
199 
200 
201  // Update index list of selected halfedges
202  if (halfedgeCacheInvalid_) {
203  he_points_.clear();
204  he_points_.reserve(mesh_.n_halfedges()/4);
205  he_normals_.clear();
206  he_normals_.reserve(he_points_.size());
207 
208  typename Mesh::ConstHalfedgeIter he_it(mesh_.halfedges_sbegin()), he_begin(mesh_.halfedges_sbegin()), he_end(mesh_.halfedges_end());
209  for (he_it = he_begin; he_it != he_end; ++he_it) {
210  if (this->is_halfedge_selected(mesh_, *he_it)) {
211  // add vertices
212  he_points_.push_back(halfedge_point(*he_it));
213  he_points_.push_back(halfedge_point(mesh_.prev_halfedge_handle(*he_it)));
214 
215  // add normals
216  FaceHandle fh;
217  if (!mesh_.is_boundary(*he_it))
218  fh = mesh_.face_handle(*he_it);
219  else
220  fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(*he_it));
221 
222  he_normals_.push_back(mesh_.normal(fh));
223  he_normals_.push_back(mesh_.normal(fh));
224  }
225  }
226 
227  std::vector<Point>(he_points_.begin(), he_points_.end()).swap(he_points_);
228  std::vector<Normal>(he_normals_.begin(), he_normals_.end()).swap(he_normals_);
229  //update the Halfedge VBO
230  if(he_points_.size() > 0)
231  updateHEVBOPoints(he_points_.size() , sizeof(he_points_[0]) , he_points_.data());
232  halfedgeCacheInvalid_ = false;
233  }
234 
235 
236  // update index list of selected faces
237  if (faceIndexInvalid_) {
238 
239  fh_cache_.clear(); //constant time, facehandle is trivially destructible
240  fh_cache_.reserve(mesh_.n_faces()/4);// maximum 2 new allocations will be performed using push_back
241 
242  typename Mesh::ConstFaceIter f_it(mesh_.faces_sbegin()), f_begin(mesh_.faces_sbegin()), f_end(mesh_.faces_end());
243  for (f_it = f_begin; f_it != f_end; ++f_it)
244  if (this->is_face_selected(mesh_, *f_it))
245  fh_cache_.push_back(*f_it);
246 
247  std::vector<FaceHandle>(fh_cache_.begin(), fh_cache_.end()).swap(fh_cache_);//shrink to fit
248 
249  if (mesh_.is_trimesh())
250  {
251  f_cache_.resize(fh_cache_.size()*3);
252  for (size_t i = 0; i < fh_cache_.size(); ++i)
253  {
254  typename Mesh::ConstFaceVertexIter fv_it = mesh_.cfv_iter(fh_cache_[i]);
255  unsigned int vidx = fv_it->idx();
256  f_cache_[i*3] = (drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vidx) : vidx);
257 
258  ++fv_it;
259  vidx = fv_it->idx();
260  f_cache_[i*3+1] = (drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vidx) : vidx);
261 
262  ++fv_it;
263  vidx = fv_it->idx();
264  f_cache_[i*3+2] = (drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vidx) : vidx);
265  }
266  }
267  else {
268  // triangulate poly-list
269  poly_cache_.clear();
270  poly_cache_.reserve(fh_cache_.size()*4);
271 
272  typename std::vector<FaceHandle>::const_iterator fh_it(fh_cache_.begin()), fh_end(fh_cache_.end());
273  for (fh_it = fh_cache_.begin(); fh_it != fh_end; ++fh_it) {
274  typename Mesh::CFVIter fv_it = mesh_.cfv_iter(*fh_it);
275 
276  // 1. polygon vertex
277  unsigned int v0 = fv_it->idx();
278 
279  // go to next vertex
280  ++fv_it;
281  unsigned int vPrev = fv_it->idx();
282  ++fv_it;
283 
284  // create triangle fans pointing towards v0
285  for (; fv_it.is_valid(); ++fv_it) {
286  poly_cache_.push_back(drawMesh_ ? drawMesh_->mapVertexToVBOIndex(v0) : v0);
287  poly_cache_.push_back(drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vPrev) : vPrev);
288 
289  vPrev = fv_it->idx();
290  poly_cache_.push_back(drawMesh_ ? drawMesh_->mapVertexToVBOIndex(vPrev) : vPrev);
291  }
292  }
293 
294  std::vector<unsigned int>(poly_cache_.begin(), poly_cache_.end()).swap(poly_cache_);//shrink to fit
295  }
296  // update trimesh face index buffer
297  if(f_cache_.size() > 0)
298  updateIBOData(fIBO_, f_cache_.size(), sizeof(f_cache_[0]), f_cache_.data());
299  // update polymesh face index buffer
300  if(poly_cache_.size() > 0)
301  updateIBOData(pIBO_, poly_cache_.size(), sizeof(poly_cache_[0]), poly_cache_.data());
302  faceIndexInvalid_ = false;
303  }
304 
305 }
306 
307 
308 //----------------------------------------------------------------------------
309 
310 
311 template <class Mesh, class Mod>
312 void
314 draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
315 {
316  // Call updater function before doing anything
317  update_cache();
318 
319  // using static bitflags for drawmodes is no longer recommended
320  // read from properties instead:
321 
322  bool shaded = false;
323  bool smooth = false;
324  bool
325  wires = ((this->drawMode() == DrawModes::DEFAULT) ||
326  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_WIREFRAME) >= 0 ||
327  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_WIREFRAME) >= 0),
328  points = ((this->drawMode() == DrawModes::DEFAULT) ||
329  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POINT) >= 0 ||
330  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POINT) >= 0),
331  edges = (this->drawMode() == DrawModes::DEFAULT ||
332  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_EDGE) >= 0 ||
333  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_EDGE) >= 0),
334  halfedges = ((this->drawMode() == DrawModes::DEFAULT) ||
335  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_HALFEDGE) >= 0 ||
336  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_HALFEDGE) >= 0),
337  faces = ((this->drawMode() == DrawModes::DEFAULT) ||
338  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POLYGON) >= 0 ||
339  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POLYGON) >= 0);
340 
341  for (unsigned int i = 0; i < _drawMode.getNumLayers(); ++i)
342  {
343  const DrawModes::DrawModeProperties* props = _drawMode.getLayer(i);
344 
345  if (props->lighting())
346  shaded = true;
347 
348  if (props->normalSource() == DrawModes::NORMAL_PER_VERTEX ||
349  props->normalSource() == DrawModes::NORMAL_PER_HALFEDGE)
350  smooth = true;
351  }
352 
353  // force shaded selections
354  shaded = true;
355 
356 
357  GLenum prev_depth = _state.depthFunc();
358 
359  ACG::GLState::depthFunc(GL_LEQUAL);
360 
361  if (shaded) ACG::GLState::enable(GL_LIGHTING);
362  else ACG::GLState::disable(GL_LIGHTING);
363 
364  if (smooth) ACG::GLState::shadeModel(GL_SMOOTH);
365  else ACG::GLState::shadeModel(GL_FLAT);
366 
367  if (drawMesh_)
368  {
369  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, drawMesh_->getVBO());
370  drawMesh_->getVertexDeclaration()->activateFixedFunction();
371 
372  // disable unwanted attributes from drawmesh vbo
373  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
374  ACG::GLState::disableClientState(GL_TEXTURE_COORD_ARRAY);
375 
376  ACG::GLState::disable(GL_TEXTURE_2D);
377  ACG::GLState::bindTexture(GL_TEXTURE_2D, 0);
378  }
379  else
380  {
381  // use buffers from open mesh
382  if (shaded && mesh_.has_vertex_normals()) {
383  ACG::GLState::enableClientState(GL_NORMAL_ARRAY);
384  ACG::GLState::normalPointer(mesh_.vertex_normals());
385  }
386 
387  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
388  ACG::GLState::vertexPointer(mesh_.points());
389  }
390 
391 
392  // points
393  if (points)
394  draw_points();
395 
396 
397  // edges
398  if (edges)
399  draw_edges();
400 
401 
402  if (shaded && !smooth)
403  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
404 
405 
406  // faces
407  if (faces) {
408  if (wires) {
409  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
410  draw_faces(smooth);
411  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
412  } else {
413 
414  glPushAttrib( GL_ENABLE_BIT );
415 
416  ACG::GLState::enable(GL_POLYGON_OFFSET_FILL);
417 
418  glPolygonOffset(0.001f, 0.0f);
419  draw_faces(smooth);
420 
421  glPopAttrib();
422  }
423  }
424 
425  // disable gpu buffer for halfedges
426  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, 0);
427  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
428 
429 
430  // half edges
431  if (halfedges)
432  draw_halfedges();
433 
434  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
435  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
436 
437  ACG::GLState::depthFunc(prev_depth);
438 }
439 
440 
441 //----------------------------------------------------------------------------
442 
443 
444 template <class Mesh, class Mod>
445 void
447 draw_points()
448 {
449  if ( !v_cache_.empty() )
450  glDrawElements(GL_POINTS,
451  int( v_cache_.size() ),
452  GL_UNSIGNED_INT,
453  &v_cache_[0]);
454 }
455 
456 
457 //----------------------------------------------------------------------------
458 
459 
460 template <class Mesh, class Mod>
461 void
463 draw_edges()
464 {
465  if ( !e_cache_.empty() )
466  glDrawElements( GL_LINES,
467  int(e_cache_.size()),
468  GL_UNSIGNED_INT,
469  &e_cache_[0]);
470 }
471 
472 
473 //----------------------------------------------------------------------------
474 
475 
476 template <class Mesh, class Mod>
477 void
479 draw_halfedges() {
480  if ( !he_points_.empty()) {
481  ACG::GLState::enableClientState(GL_NORMAL_ARRAY);
482 
483  ACG::GLState::vertexPointer(&he_points_[0]);
484 
485  if ( !he_normals_.empty())
486  ACG::GLState::normalPointer(&he_normals_[0]);
487 
488  glDrawArrays(GL_LINES, 0, int(he_points_.size() ) );
489  }
490 
491 }
492 
493 
494 //----------------------------------------------------------------------------
495 
496 
497 template <class Mesh, class Mod>
498 void
500 draw_faces(bool _per_vertex)
501 {
502  typename std::vector<FaceHandle>::const_iterator fh_it(fh_cache_.begin()),
503  fh_end(fh_cache_.end());
504  typename Mesh::CFVIter fv_it;
505 
506 
507  // TRIANGLES
508  if (mesh_.is_trimesh()) {
509 
510  if (!_per_vertex) {
511  glBegin(GL_TRIANGLES);
512  for (; fh_it!=fh_end; ++fh_it) {
513  glNormal(mesh_.normal(*fh_it));
514  glVertex(mesh_.point(*(fv_it=mesh_.cfv_iter(*fh_it))));
515  glVertex(mesh_.point(*(++fv_it)));
516  glVertex(mesh_.point(*(++fv_it)));
517  }
518 
519  glEnd();
520  } else {
521 
522  if ( !f_cache_.empty() )
523  glDrawElements(GL_TRIANGLES,
524  int(f_cache_.size()),
525  GL_UNSIGNED_INT,
526  &f_cache_[0]);
527  }
528 
529  // POLYGONS
530  } else {
531 
532  if (!_per_vertex) {
533 
534  for (; fh_it!=fh_end; ++fh_it) {
535  glBegin(GL_POLYGON);
536  glNormal(mesh_.normal(*fh_it));
537  for (fv_it=mesh_.cfv_iter(*fh_it); fv_it.is_valid(); ++fv_it)
538  glVertex(mesh_.point(*fv_it));
539  glEnd();
540  }
541 
542  } else {
543 
544  for (; fh_it!=fh_end; ++fh_it) {
545  glBegin(GL_POLYGON);
546  for (fv_it=mesh_.cfv_iter(*fh_it); fv_it.is_valid(); ++fv_it) {
547  glNormal(mesh_.normal(*fv_it));
548 
549  if (drawMesh_) // map to vbo index
550  glArrayElement(drawMesh_->mapVertexToVBOIndex(fv_it->idx()));
551  else
552  glArrayElement(fv_it->idx());
553  }
554  glEnd();
555  }
556 
557  }
558  }
559 }
560 
561 
562 //----------------------------------------------------------------------------
563 
564 
565 template <class Mesh, class Mod>
566 typename Mesh::Point
568 halfedge_point(const HalfedgeHandle _heh)
569 {
570  typename Mesh::Point p = mesh_.point(mesh_.to_vertex_handle (_heh));
571  typename Mesh::Point pp = mesh_.point(mesh_.from_vertex_handle(_heh));
572  typename Mesh::Point pn = mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_heh)));
573 
574  // typename Mesh::Point n = (p-pp)%(pn-p);
575  typename Mesh::Point fn;
576  if( !mesh_.is_boundary(_heh))
577  fn = mesh_.normal(mesh_.face_handle(_heh));
578  else
579  fn = mesh_.normal(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
580 
581  typename Mesh::Point upd = ((fn%(pn-p)).normalize() + (fn%(p-pp)).normalize()).normalize();
582 
583  upd *= ((pn-p).norm()+(p-pp).norm())*0.08;
584 
585 
586  return (p+upd);
587 
588  // double alpha = 0.1;
589  // // correct weighting for concave triangles (or at concave boundaries)
590  // if( (fn | n) < 0.0) alpha *=-1.0;
591 
592  // return (p*(1.0-2.0*alpha) + pp*alpha + pn*alpha);
593 }
594 
595 //----------------------------------------------------------------------------
596 
597 template <class Mesh, class Mod>
599  GLState& _state,
600  const DrawModes::DrawMode& _drawMode,
601  const class Material* _mat)
602 {
603  // Call updater function before doing anything
604  update_cache();
605 
606  bool shaded = false,
607  points = ((this->drawMode() == DrawModes::DEFAULT) ||
608  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POINT) >= 0 ||
609  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POINT) >= 0),
610  edges = (this->drawMode() == DrawModes::DEFAULT ||
611  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_EDGE) >= 0 ||
612  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_EDGE) >= 0),
613  halfedges = ((this->drawMode() == DrawModes::DEFAULT) ||
614  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_HALFEDGE) >= 0 ||
615  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_HALFEDGE) >= 0),
616  faces = ((this->drawMode() == DrawModes::DEFAULT) ||
617  this->drawMode().getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POLYGON) >= 0 ||
618  _drawMode.getLayerIndexByPrimitive(DrawModes::PRIMITIVE_POLYGON) >= 0);
619 
620  RenderObject ro;
621  ro.debugName = "StatusNode";
622  ro.initFromState(&_state);
623 
624  ro.depthTest = true;
625  ro.depthFunc = GL_LEQUAL;
626 
627  // Use the material from the underlying materialnode
628  ro.setMaterial(&MaterialNode::material());
629 
630  pointVertexDecl_.clear();
631  pointVertexDecl_.addElement(GL_DOUBLE, 3, VERTEX_USAGE_POSITION, mesh_.points());
632 
633  if (shaded && mesh_.has_vertex_normals())
634  pointVertexDecl_.addElement(GL_DOUBLE, 3, VERTEX_USAGE_NORMAL, mesh_.vertex_normals());
635 
636  pointVertexDecl_.setVertexStride(24); // separated buffers, double3: 24 bytes
637 
638 
639  // draw status later than scene
640  ro.priority = 1;
641 
642 
643  // enable lighting
644  if (shaded)
645  ro.shaderDesc.shadeMode = SG_SHADE_GOURAUD;
646 
647  if (drawMesh_)
648  {
649  ro.vertexBuffer = drawMesh_->getVBO();
650  ro.vertexDecl = drawMesh_->getVertexDeclaration();
651  //ro.indexBuffer = drawMesh_->getIBO();
652  }
653  else
654  ro.vertexDecl = &pointVertexDecl_;
655 
656  // point list
657  if (points && !v_cache_.empty())
658  {
659  // use shaders to simulate line width
660  QString geomTemplate = ShaderProgGenerator::getShaderDir();
661  geomTemplate += "PointSize/geometry.tpl";
662 
663  QString fragTemplate = ShaderProgGenerator::getShaderDir();
664  fragTemplate += "PointSize/fragment.tpl";
665 
666  ro.shaderDesc.geometryTemplateFile = geomTemplate;
667  ro.shaderDesc.fragmentTemplateFile = fragTemplate;
668  ro.indexBuffer = vIBO_;
669 
670  ro.setUniform("screenSize", Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
671  ro.setUniform("pointSize", MaterialNode::point_size());
672 
673  ro.glDrawElements(GL_POINTS, static_cast<GLsizei>(v_cache_.size()), GL_UNSIGNED_INT, (void *)0);
674  _renderer->addRenderObject(&ro);
675 
676  ro.shaderDesc.geometryTemplateFile = "";
677  ro.shaderDesc.fragmentTemplateFile = "";
678  }
679 
680  // edge list
681  if (edges && !e_cache_.empty())
682  {
683  // use shaders to simulate line width
684  QString geomTemplate = ShaderProgGenerator::getShaderDir();
685  geomTemplate += "Wireframe/geom_line2quad.tpl";
686 
687  ro.shaderDesc.geometryTemplateFile = geomTemplate;
688  ro.indexBuffer = eIBO_;
689 
690  ro.setUniform("screenSize", Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
691  ro.setUniform("lineWidth", MaterialNode::line_width());
692 
693  ro.glDrawElements(GL_LINES, static_cast<GLsizei>(e_cache_.size()), GL_UNSIGNED_INT, (void *)0);
694  _renderer->addRenderObject(&ro);
695 
696  ro.shaderDesc.geometryTemplateFile = "";
697  ro.shaderDesc.fragmentTemplateFile = "";
698  }
699 
700 
701  if (faces)
702  {
703  if (mesh_.is_trimesh() && !f_cache_.empty())
704  {
705  ro.indexBuffer = fIBO_;
706  ro.glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(f_cache_.size()), GL_UNSIGNED_INT, (void *)0);
707  _renderer->addRenderObject(&ro);
708  }
709  else if (!poly_cache_.empty()) //if mesh is not a triangle mesh, poly_cache is always empty
710  {
711  ro.indexBuffer = pIBO_;
712  ro.glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(poly_cache_.size()), GL_UNSIGNED_INT, (void *)0);
713  _renderer->addRenderObject(&ro);
714  }
715  }
716 
717 
718  // halfedge list
719  if (halfedges && !he_points_.empty())
720  {
721  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
722 
723  halfedgeVertexDecl_.clear();
724  halfedgeVertexDecl_.addElement(GL_DOUBLE, 3, VERTEX_USAGE_POSITION, (void *)0);
725 
726  ro.vertexBuffer = heVBO_;
727  ro.vertexDecl = &halfedgeVertexDecl_;
728  ro.indexBuffer = 0;
729 
730  ro.glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(he_points_.size()) );
731  _renderer->addRenderObject(&ro);
732  }
733 
734 
735 }
736 
737 
738 //----------------------------------------------------------------------------
739 
740 template <class Mesh, class Mod>
742  invalidGeometry_ = true;
743 }
744 
745 
746 template <class Mesh, class Mod>
748  vertexIndexInvalid_ = true;
749  halfedgeCacheInvalid_ = true;
750  edgeIndexInvalid_ = true;
751  faceIndexInvalid_ = true;
752 
753 }
754 
755 template <class Mesh, class Mod>
757  vertexIndexInvalid_ = true;
758  halfedgeCacheInvalid_ = true;
759  edgeIndexInvalid_ = true;
760  faceIndexInvalid_ = true;
761 
762 }
763 
764 template <class Mesh, class Mod>
766  drawMesh_ = _drawmesh;
767 }
768 
769 
770 //=============================================================================
771 } // namespace SceneGraph
772 } // namespace ACG
773 //=============================================================================
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
void setUniform(const char *_name, GLint _value)
set values for int uniforms
int getLayerIndexByPrimitive(DrawModePrimitive _type) const
search for layer with specified primitive
Definition: DrawModes.cc:626
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1729
Kernel::ConstFaceVertexIter ConstFaceVertexIter
Circulator.
Definition: PolyMeshT.hh:177
void glNormal(const Vec3f &_n)
Wrapper: glNormal for Vec3f.
Definition: gl.hh:135
int viewport_width() const
get viewport width
Definition: GLState.hh:822
bool lighting() const
Is lighting enabled?
Definition: DrawModes.hh:216
Namespace providing different geometric functions concerning angles.
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1868
ShaderGenDesc shaderDesc
Drawmode and other shader params.
static constexpr bool is_trimesh()
Determine whether this is a PolyMeshT or TriMeshT (This function does not check the per face vertex c...
Definition: TriMeshT.hh:104
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:568
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
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
Definition: GLState.cc:1918
float line_width() const
get line width
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition: GLState.cc:1584
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:824
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:540
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
float point_size() const
get point size
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:95
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition: DrawModes.hh:177
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
StatusNodeT(const Mesh &_mesh, BaseNode *_parent=0, const std::string &_name="<StatusNode>")
constructor
int priority
Priority to allow sorting of objects.
Mesh Drawing Class.
Definition: DrawMesh.hh:173
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition: DrawModes.cc:535
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
size_t getNumLayers() const
returns the layer count
Definition: DrawModes.cc:531
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition: GLState.cc:1820
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
ACG::SceneGraph::Material & material()
Get material object reference.
static void normalPointer(GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glNormalPointer, supports locking
Definition: GLState.cc:1940