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