Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
StatusNodesT.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
5  * www.openflipper.org *
6  * *
7  *---------------------------------------------------------------------------*
8  * This file is part of OpenFlipper. *
9  * *
10  * OpenFlipper is free software: you can redistribute it and/or modify *
11  * it under the terms of the GNU Lesser General Public License as *
12  * published by the Free Software Foundation, either version 3 of *
13  * the License, or (at your option) any later version with the *
14  * following exceptions: *
15  * *
16  * If other files instantiate templates or use macros *
17  * or inline functions from this file, or you compile this file and *
18  * link it with other files to produce an executable, this file does *
19  * not by itself cause the resulting executable to be covered by the *
20  * GNU Lesser General Public License. This exception does not however *
21  * invalidate any other reasons why the executable file might be *
22  * covered by the GNU Lesser General Public License. *
23  * *
24  * OpenFlipper is distributed in the hope that it will be useful, *
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27  * GNU Lesser General Public License for more details. *
28  * *
29  * You should have received a copy of the GNU LesserGeneral Public *
30  * License along with OpenFlipper. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36  * *
37  * $Revision: 12560 $ *
38  * $Author: moebius $ *
39  * $Date: 2011-10-10 08:23:41 +0200 (Mo, 10 Okt 2011) $ *
40  * *
41 \*===========================================================================*/
42 
43 
44 
45 
46 //=============================================================================
47 //
48 // CLASS StatusNodeT - IMPLEMENTATION
49 //
50 //=============================================================================
51 
52 
53 #define ACG_STATUS_NODES_C
54 
55 
56 //== INCLUDES =================================================================
57 
58 
59 #include "StatusNodesT.hh"
60 #include "../GL/gl.hh"
61 
62 //== NAMESPACES ===============================================================
63 
64 
65 namespace ACG {
66 namespace SceneGraph {
67 
68 
69 //== IMPLEMENTATION ==========================================================
70 
71 
72 template <class Mesh, class Mod>
74 StatusNodeT( const Mesh& _mesh,
75  BaseNode* _parent,
76  const std::string& _name )
77  : MaterialNode(_parent, _name), mesh_(_mesh),
78  bbMin_(FLT_MAX, FLT_MAX, FLT_MAX),
79  bbMax_(-FLT_MAX, -FLT_MAX, -FLT_MAX),
80  invalidGeometry_(true),
81  vertexIndexInvalid_(true),
82  halfedgeCacheInvalid_(true),
83  edgeIndexInvalid_(true),
84  faceIndexInvalid_(true)
85 {
86  set_line_width(3);
87  set_point_size(5);
88 }
89 
90 
91 //----------------------------------------------------------------------------
92 
93 
94 template <class Mesh, class Mod>
95 void
97 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
98 {
99  _bbMin.minimize(bbMin_);
100  _bbMax.maximize(bbMax_);
101 }
102 
103 
104 //----------------------------------------------------------------------------
105 
106 
107 template <class Mesh, class Mod>
111 {
112  return (DrawModes::POINTS |
115 }
116 
117 
118 //----------------------------------------------------------------------------
119 
120 
121 template <class Mesh, class Mod>
122 void
125 {
126  if ( invalidGeometry_ ) {
127  bbMin_ = Vec3d(FLT_MAX, FLT_MAX, FLT_MAX);
128  bbMax_ = Vec3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);
129 
130  typename Mesh::ConstVertexIter v_it(mesh_.vertices_sbegin()),
131  v_end(mesh_.vertices_end());
132 
133  for (; v_it!=v_end; ++v_it) {
134  bbMin_.minimize(mesh_.point(v_it));
135  bbMax_.maximize(mesh_.point(v_it));
136  }
137 
138  invalidGeometry_ = false;
139  }
140 
141 }
142 
143 
144 //----------------------------------------------------------------------------
145 
146 
147 template <class Mesh, class Mod>
148 void
150 draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
151 {
152  // Call updater function before doing anything
153  update_cache();
154 
155  bool shaded = (_drawMode & ( DrawModes::SOLID_FLAT_SHADED |
160 
161  bool wires = (_drawMode & ( DrawModes::WIREFRAME |
163 
164  bool smooth = (_drawMode & ( DrawModes::SOLID_SMOOTH_SHADED |
167 
168  bool points = ((drawMode() == DrawModes::DEFAULT) |
169  (_drawMode & DrawModes::POINTS));
170 
171  bool edges = ((drawMode() == DrawModes::DEFAULT) |
172  (_drawMode & DrawModes::WIREFRAME));
173 
174  bool halfedges = ((drawMode() == DrawModes::DEFAULT) |
175  (_drawMode & DrawModes::WIREFRAME));
176 
177  bool faces = ((drawMode() == DrawModes::DEFAULT) |
178  (_drawMode & DrawModes::SOLID_FLAT_SHADED));
179 
180 
181  GLenum prev_depth = _state.depthFunc();
182 
183  ACG::GLState::depthFunc(GL_LEQUAL);
184 
185  if (shaded) ACG::GLState::enable(GL_LIGHTING);
186  else ACG::GLState::disable(GL_LIGHTING);
187 
188  if (smooth) ACG::GLState::shadeModel(GL_SMOOTH);
189  else ACG::GLState::shadeModel(GL_FLAT);
190 
191 
192  if (shaded && mesh_.has_vertex_normals()) {
193  ACG::GLState::enableClientState(GL_NORMAL_ARRAY);
194  ACG::GLState::normalPointer(mesh_.vertex_normals());
195  }
196 
197 
198  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
199  ACG::GLState::vertexPointer(mesh_.points());
200 
201 
202  // points
203  if (points)
204  draw_points();
205 
206 
207  // edges
208  if (edges)
209  draw_edges();
210 
211 
212  if (shaded && !smooth)
213  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
214 
215 
216  // faces
217  if (faces) {
218  if (wires) {
219  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
220  draw_faces(smooth);
221  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
222  } else {
223 
224  glPushAttrib( GL_ENABLE_BIT );
225 
226  ACG::GLState::enable(GL_POLYGON_OFFSET_FILL);
227 
228  glPolygonOffset(0.001, 0.0);
229  draw_faces(smooth);
230 
231  glPopAttrib();
232  }
233  }
234 
235  // half edges
236  if (halfedges)
237  draw_halfedges();
238 
239  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
240  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
241 
242  ACG::GLState::depthFunc(prev_depth);
243 }
244 
245 
246 //----------------------------------------------------------------------------
247 
248 
249 template <class Mesh, class Mod>
250 void
251 StatusNodeT<Mesh, Mod>::
252 draw_points()
253 {
254 
255  // Update the indices for selected vertices
256  if ( vertexIndexInvalid_ ) {
257 
258  typename Mesh::ConstVertexIter v_it(mesh_.vertices_sbegin()),
259  v_end(mesh_.vertices_end());
260 
261  v_cache_.clear();
262  for (; v_it!=v_end; ++v_it) {
263  if (Mod::is_vertex_selected(mesh_, v_it.handle())) {
264  v_cache_.push_back(v_it.handle().idx());
265  }
266  }
267 
268  vertexIndexInvalid_ = false;
269  }
270 
271  if ( !v_cache_.empty() )
272  glDrawElements(GL_POINTS,
273  v_cache_.size(),
274  GL_UNSIGNED_INT,
275  &v_cache_[0]);
276 }
277 
278 
279 //----------------------------------------------------------------------------
280 
281 
282 template <class Mesh, class Mod>
283 void
284 StatusNodeT<Mesh, Mod>::
285 draw_edges()
286 {
287  // Update index list of selected edges
288  if ( edgeIndexInvalid_ ) {
289 
290  typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()),
291  e_end(mesh_.edges_end());
292  typename Mesh::VertexHandle vh;
293 
294  e_cache_.clear();
295  for (; e_it!=e_end; ++e_it) {
296  if (Mod::is_edge_selected(mesh_, e_it)) {
297  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(e_it, 0));
298  e_cache_.push_back(vh.idx());
299  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(e_it, 1));
300  e_cache_.push_back(vh.idx());
301  }
302  }
303 
304  edgeIndexInvalid_ = false;
305  }
306 
307  if ( !e_cache_.empty() )
308  glDrawElements(GL_LINES,
309  e_cache_.size(),
310  GL_UNSIGNED_INT,
311  &e_cache_[0]);
312 }
313 
314 
315 //----------------------------------------------------------------------------
316 
317 
318 template <class Mesh, class Mod>
319 void
320 StatusNodeT<Mesh, Mod>::
321 draw_halfedges() {
322 
323  // Update index list of selected halfedges
324  if ( halfedgeCacheInvalid_) {
325 
326  typename Mesh::ConstHalfedgeIter he_it(mesh_.halfedges_sbegin()),
327  he_end(mesh_.halfedges_end());
328 
329  he_points_.clear();
330  he_normals_.clear();
331  for (; he_it!=he_end; ++he_it) {
332  if (Mod::is_halfedge_selected(mesh_, he_it)) {
333  // add vertices
334  he_points_.push_back( halfedge_point(he_it));
335  he_points_.push_back( halfedge_point(mesh_.prev_halfedge_handle(he_it)));
336 
337  // add normals
338  FaceHandle fh;
339  if(!mesh_.is_boundary(he_it))
340  fh = mesh_.face_handle(he_it);
341  else
342  fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(he_it));
343 
344  he_normals_.push_back( mesh_.normal(fh));
345  he_normals_.push_back( mesh_.normal(fh));
346  }
347  }
348 
349  halfedgeCacheInvalid_ = false;
350  }
351 
352 
353 
354  if ( !he_points_.empty()) {
355  ACG::GLState::enableClientState(GL_NORMAL_ARRAY);
356 
357  ACG::GLState::vertexPointer(&he_points_[0]);
358 
359  if ( !he_normals_.empty())
360  ACG::GLState::normalPointer(&he_normals_[0]);
361 
362  glDrawArrays(GL_LINES, 0, he_points_.size() );
363  }
364 
365 }
366 
367 
368 //----------------------------------------------------------------------------
369 
370 
371 template <class Mesh, class Mod>
372 void
373 StatusNodeT<Mesh, Mod>::
374 draw_faces(bool _per_vertex)
375 {
376 
377  // update index list of selected faces
378  if ( faceIndexInvalid_ ) {
379 
380  typename Mesh::ConstFaceIter f_it(mesh_.faces_sbegin()),
381  f_end(mesh_.faces_end());
382  typename Mesh::ConstFaceVertexIter fv_it;
383 
384  f_cache_.clear();
385  fh_cache_.clear();
386  for (; f_it!=f_end; ++f_it) {
387  if (Mod::is_face_selected(mesh_, f_it)) {
388  fv_it = mesh_.cfv_iter(f_it);
389  f_cache_.push_back(fv_it.handle().idx()); ++fv_it;
390  f_cache_.push_back(fv_it.handle().idx()); ++fv_it;
391  f_cache_.push_back(fv_it.handle().idx());
392  fh_cache_.push_back(f_it);
393  }
394  }
395  faceIndexInvalid_ = false;
396  }
397 
398  typename std::vector<FaceHandle>::const_iterator fh_it(fh_cache_.begin()),
399  fh_end(fh_cache_.end());
400  typename Mesh::CFVIter fv_it;
401 
402 
403  // TRIANGLES
404  if (mesh_.is_trimesh()) {
405 
406  if (!_per_vertex) {
407  glBegin(GL_TRIANGLES);
408  for (; fh_it!=fh_end; ++fh_it) {
409  glNormal(mesh_.normal(*fh_it));
410  glVertex(mesh_.point(fv_it=mesh_.cfv_iter(*fh_it)));
411  glVertex(mesh_.point(++fv_it));
412  glVertex(mesh_.point(++fv_it));
413  }
414 
415  glEnd();
416  } else {
417 
418  if ( !f_cache_.empty() )
419  glDrawElements(GL_TRIANGLES,
420  f_cache_.size(),
421  GL_UNSIGNED_INT,
422  &f_cache_[0]);
423  }
424 
425  // POLYGONS
426  } else {
427 
428  if (!_per_vertex) {
429 
430  for (; fh_it!=fh_end; ++fh_it) {
431  glBegin(GL_POLYGON);
432  glNormal(mesh_.normal(*fh_it));
433  for (fv_it=mesh_.cfv_iter(*fh_it); fv_it; ++fv_it)
434  glVertex(mesh_.point(fv_it));
435  glEnd();
436  }
437 
438  } else {
439 
440  for (; fh_it!=fh_end; ++fh_it) {
441  glBegin(GL_POLYGON);
442  for (fv_it=mesh_.cfv_iter(*fh_it); fv_it; ++fv_it) {
443  glNormal(mesh_.normal(fv_it));
444  glArrayElement(fv_it.handle().idx());
445  }
446  glEnd();
447  }
448 
449  }
450  }
451 }
452 
453 
454 //----------------------------------------------------------------------------
455 
456 
457 template <class Mesh, class Mod>
458 typename Mesh::Point
459 StatusNodeT<Mesh, Mod>::
460 halfedge_point(const HalfedgeHandle _heh)
461 {
462  typename Mesh::Point p = mesh_.point(mesh_.to_vertex_handle (_heh));
463  typename Mesh::Point pp = mesh_.point(mesh_.from_vertex_handle(_heh));
464  typename Mesh::Point pn = mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_heh)));
465 
466  // typename Mesh::Point n = (p-pp)%(pn-p);
467  typename Mesh::Point fn;
468  if( !mesh_.is_boundary(_heh))
469  fn = mesh_.normal(mesh_.face_handle(_heh));
470  else
471  fn = mesh_.normal(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
472 
473  typename Mesh::Point upd = ((fn%(pn-p)).normalize() + (fn%(p-pp)).normalize()).normalize();
474 
475  upd *= ((pn-p).norm()+(p-pp).norm())*0.08;
476 
477 
478  return (p+upd);
479 
480  // double alpha = 0.1;
481  // // correct weighting for concave triangles (or at concave boundaries)
482  // if( (fn | n) < 0.0) alpha *=-1.0;
483 
484  // return (p*(1.0-2.0*alpha) + pp*alpha + pn*alpha);
485 }
486 
487 template <class Mesh, class Mod>
489  invalidGeometry_ = true;
490 }
491 
492 template <class Mesh, class Mod>
494  vertexIndexInvalid_ = true;
495  halfedgeCacheInvalid_ = true;
496  edgeIndexInvalid_ = true;
497  faceIndexInvalid_ = true;
498 
499 }
500 
501 template <class Mesh, class Mod>
503  vertexIndexInvalid_ = true;
504  halfedgeCacheInvalid_ = true;
505  edgeIndexInvalid_ = true;
506  faceIndexInvalid_ = true;
507 
508 }
509 
510 
511 //=============================================================================
512 } // namespace SceneGraph
513 } // namespace ACG
514 //=============================================================================