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