Developer Documentation
ProgViewerWidget.cc
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
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$ *
45  * $Date$ *
46  * *
47 \*===========================================================================*/
48 
49 
50 //== INCLUDES =================================================================
51 
52 #ifdef _MSC_VER
53 # pragma warning(disable: 4267 4311)
54 #endif
55 
56 #include <iostream>
57 #include <fstream>
58 // --------------------
59 #include <QApplication>
60 #include <QFileInfo>
61 #include <QKeyEvent>
62 // --------------------
63 #include <OpenMesh/Apps/ProgViewer/ProgViewerWidget.hh>
64 #include <OpenMesh/Core/IO/BinaryHelper.hh>
65 #include <OpenMesh/Core/IO/MeshIO.hh>
66 #include <OpenMesh/Core/Utils/Endian.hh>
68 // --------------------
69 
70 #ifdef ARCH_DARWIN
71  #include <OpenGL/gl.h>
72 #else
73 # include <GL/gl.h>
74 #endif
75 
76 using namespace Qt;
77 //== IMPLEMENTATION ==========================================================
78 
79 
80 void
81 ProgViewerWidget::open_prog_mesh(const char* _filename)
82 {
83  MyMesh::Point p;
84  unsigned int i, i0, i1, i2;
85  unsigned int v1, vl, vr;
86  char c[10];
87 
88  std::ifstream ifs(_filename, std::ios::binary);
89  if (!ifs)
90  {
91  std::cerr << "read error\n";
92  exit(1);
93  }
94 
95  //
97 
98  // read header
99  ifs.read(c, 8); c[8] = '\0';
100  if (std::string(c) != std::string("ProgMesh"))
101  {
102  std::cerr << "Wrong file format.\n";
103  exit(1);
104  }
105  OpenMesh::IO::binary<size_t>::restore( ifs, n_base_vertices_, swap );
106  OpenMesh::IO::binary<size_t>::restore( ifs, n_base_faces_, swap );
107  OpenMesh::IO::binary<size_t>::restore( ifs, n_detail_vertices_, swap );
108 
109  n_max_vertices_ = n_base_vertices_ + n_detail_vertices_;
110 
111  // load base mesh
112  mesh_.clear();
113 
114  for (i=0; i<n_base_vertices_; ++i)
115  {
117  mesh_.add_vertex(p);
118  }
119 
120  for (i=0; i<n_base_faces_; ++i)
121  {
125  mesh_.add_face(mesh_.vertex_handle(i0),
126  mesh_.vertex_handle(i1),
127  mesh_.vertex_handle(i2));
128  }
129 
130 
131  // load progressive detail
132  for (i=0; i<n_detail_vertices_; ++i)
133  {
138 
139  PMInfo pminfo;
140  pminfo.p0 = p;
141  pminfo.v1 = MyMesh::VertexHandle(v1);
142  pminfo.vl = MyMesh::VertexHandle(vl);
143  pminfo.vr = MyMesh::VertexHandle(vr);
144  pminfos_.push_back(pminfo);
145  }
146  pmiter_ = pminfos_.begin();
147 
148 
149  // update face and vertex normals
150  mesh_.update_face_normals();
151  mesh_.update_vertex_normals();
152 
153  // bounding box
154  MyMesh::ConstVertexIter
155  vIt(mesh_.vertices_begin()),
156  vEnd(mesh_.vertices_end());
157 
158  MyMesh::Point bbMin, bbMax;
159 
160  bbMin = bbMax = mesh_.point(*vIt);
161  for (; vIt!=vEnd; ++vIt)
162  {
163  bbMin.minimize(mesh_.point(*vIt));
164  bbMax.maximize(mesh_.point(*vIt));
165  }
166 
167  // set center and radius
168  set_scene_pos(0.5f*(bbMin + bbMax), 0.5*(bbMin - bbMax).norm());
169 
170  // info
171  std::cerr << mesh_.n_vertices() << " vertices, "
172  << mesh_.n_edges() << " edge, "
173  << mesh_.n_faces() << " faces, "
174  << n_detail_vertices_ << " detail vertices\n";
175 
176  setWindowTitle( QFileInfo(_filename).fileName() );
177 }
178 
179 
180 //-----------------------------------------------------------------------------
181 
182 
183 void ProgViewerWidget::refine(unsigned int _n)
184 {
185  size_t n_vertices = mesh_.n_vertices();
186 
187  while (n_vertices < _n && pmiter_ != pminfos_.end())
188  {
189  pmiter_->v0 = mesh_.add_vertex(pmiter_->p0);
190  mesh_.vertex_split(pmiter_->v0,
191  pmiter_->v1,
192  pmiter_->vl,
193  pmiter_->vr);
194  ++pmiter_;
195  ++n_vertices;
196  }
197 
198  mesh_.update_face_normals();
199  mesh_.update_vertex_normals();
200 
201  std::cerr << n_vertices << " vertices\n";
202 }
203 
204 
205 //-----------------------------------------------------------------------------
206 
207 
208 void ProgViewerWidget::coarsen(unsigned int _n)
209 {
210  size_t n_vertices = mesh_.n_vertices();
211 
212  while (n_vertices > _n && pmiter_ != pminfos_.begin())
213  {
214  --pmiter_;
215 
216  MyMesh::HalfedgeHandle hh =
217  mesh_.find_halfedge(pmiter_->v0, pmiter_->v1);
218 
219  mesh_.collapse(hh);
220 
221  --n_vertices;
222  }
223 
224  mesh_.garbage_collection();
225  mesh_.update_face_normals();
226  mesh_.update_vertex_normals();
227 
228  std::cerr << n_vertices << " vertices\n";
229 }
230 
231 
232 //-----------------------------------------------------------------------------
233 
234 void ProgViewerWidget::keyPressEvent(QKeyEvent* _event)
235 {
236  switch (_event->key())
237  {
238  case Key_Minus:
239  if ( _event->modifiers() & ShiftModifier)
240  coarsen(mesh_.n_vertices()-1);
241  else
242  coarsen((unsigned int)(0.9*mesh_.n_vertices()));
243  updateGL();
244  break;
245 
246  case Key_Plus:
247  if (_event->modifiers() & ShiftModifier)
248  refine(mesh_.n_vertices()+1);
249  else
250  refine((unsigned int)(std::max( 1.1*mesh_.n_vertices(),
251  mesh_.n_vertices()+1.0) ));
252  updateGL();
253  break;
254 
255  case Key_Home:
256  coarsen(n_base_vertices_);
257  updateGL();
258  break;
259 
260  case Key_A:
261  if (timer_->isActive())
262  {
263  timer_->stop();
264  std::cout << "animation stopped!" << std::endl;
265  }
266  else
267  {
268  timer_->setSingleShot(true);
269  timer_->start(0);
270  std::cout << "animation started!" << std::endl;
271  }
272  break;
273 
274  case Key_End:
275  refine(n_base_vertices_ + n_detail_vertices_);
276  updateGL();
277  break;
278 
279  case Key_P:
280  {
281  const size_t refine_max = 100000;
282  const size_t n_loop = 5;
283 
285  size_t count;
286 
287  coarsen(0); count = mesh_.n_vertices();
288  refine(refine_max); count = mesh_.n_vertices() - count;
289 
290  t.start();
291  for (size_t i=0; i<n_loop; ++i)
292  {
293  coarsen(0);
294  refine(100000);
295  }
296  t.stop();
297 
298  std::cout << "# collapses/splits: " << 2*(n_loop+1)*count << " in "
299  << t.as_string() << std::endl;
300  std::cout << "# collapses or splits per seconds: "
301  << 2*(n_loop+1)*count/t.seconds() << "\n";
302 
303  coarsen(0);
304 
305 
306  updateGL();
307 
308  break;
309  }
310 
311  case Key_S:
312  if (OpenMesh::IO::write_mesh( mesh_, "result.off" ))
313  std::clog << "Current mesh stored in 'result.off'\n";
314  break;
315 
316  default:
317  this->Base::keyPressEvent(_event);
318  }
319 }
320 
321 void ProgViewerWidget::animate( void )
322 {
323  if (animateRefinement_)
324  {
325  refine((unsigned int)( 1.1*(mesh_.n_vertices()+1) ));
326  if ( mesh_.n_vertices() > n_base_vertices_+(0.5*n_detail_vertices_))
327  animateRefinement_ = false;
328  }
329  else
330  {
331  coarsen((unsigned int)(0.9*(mesh_.n_vertices()-1)));
332  if ( mesh_.n_vertices() == n_base_vertices_ )
333  animateRefinement_ = true;
334  }
335  updateGL();
336  timer_->setSingleShot(true);
337  timer_->start(300);
338 }
339 
340 //=============================================================================
Little endian (Intel family and clones)
Definition: Endian.hh:83
void refine(unsigned int _n)
refine mesh up to _n vertices
void start(void)
Start measurement.
void open_prog_mesh(const char *_filename)
open progressive mesh
void coarsen(unsigned int _n)
coarsen mesh down to _n vertices
double seconds(void) const
Returns measured time in seconds, if the timer is in state &#39;Stopped&#39;.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:236
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT.cc:259
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
std::string as_string(Format format=Automatic)
void update_vertex_normals()
Update normal vectors for all vertices.
Definition: PolyMeshT.cc:448
void stop(void)
Stop measurement.
static Type local()
Return endian type of host system.
Definition: Endian.hh:88
bool write_mesh(const Mesh &_mesh, const std::string &_filename, Options _opt=Options::Default, std::streamsize _precision=6)
Write a mesh to the file _filename.
Definition: MeshIO.hh:199
HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1, VertexHandle _vl, VertexHandle _vr)
Vertex Split: inverse operation to collapse().
Definition: TriMeshT.hh:213