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>
62 #include <OpenMesh/Tools/Utils/Timer.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 //
91 bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB;
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 {
111 OpenMesh::IO::binary<MyMesh::Point>::restore( ifs, p, swap );
112 mesh_.add_vertex(p);
113 }
114
115 for (i=0; i<n_base_faces_; ++i)
116 {
117 OpenMesh::IO::binary<unsigned int>::restore( ifs, i0, swap);
118 OpenMesh::IO::binary<unsigned int>::restore( ifs, i1, swap);
119 OpenMesh::IO::binary<unsigned int>::restore( ifs, i2, swap);
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 {
129 OpenMesh::IO::binary<MyMesh::Point>::restore( ifs, p, swap );
130 OpenMesh::IO::binary<unsigned int>::restore( ifs, v1, swap );
131 OpenMesh::IO::binary<unsigned int>::restore( ifs, vl, swap );
132 OpenMesh::IO::binary<unsigned int>::restore( ifs, vr, swap );
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
279 OpenMesh::Utils::Timer t;
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 //=============================================================================
ProgViewerWidget::refine
void refine(unsigned int _n)
refine mesh up to _n vertices
Definition: ProgViewerWidget.cc:178
OpenMesh::IO::write_mesh
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
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
OpenMesh::Utils::Timer::as_string
std::string as_string(Format format=Automatic)
OpenMesh::Utils::Timer::seconds
double seconds(void) const
Returns measured time in seconds, if the timer is in state &#39;Stopped&#39;.
OpenMesh::TriMeshT::vertex_split
HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1, VertexHandle _vl, VertexHandle _vr)
Vertex Split: inverse operation to collapse().
Definition: TriMeshT.hh:214
ProgViewerWidget::PMInfo
Definition: ProgViewerWidget.hh:126
OpenMesh::Utils::Timer::stop
void stop(void)
Stop measurement.
ProgViewerWidget::open_prog_mesh
void open_prog_mesh(const char *_filename)
open progressive mesh
Definition: ProgViewerWidget.cc:76
OpenMesh::Endian::LSB
Little endian (Intel family and clones)
Definition: Endian.hh:78
OpenMesh::PolyMeshT::update_vertex_normals
void update_vertex_normals()
Update normal vectors for all vertices.
Definition: PolyMeshT_impl.hh:550
Timer.hh
OpenMesh::PolyMeshT::add_vertex
SmartVertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
OpenMesh::PolyMeshT::update_face_normals
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT_impl.hh:335
Qt
OpenMesh::Utils::Timer::start
void start(void)
Start measurement.
OpenMesh::Utils::Timer
Definition: Timer.hh:82
ProgViewerWidget::coarsen
void coarsen(unsigned int _n)
coarsen mesh down to _n vertices
Definition: ProgViewerWidget.cc:203
OpenMesh::IO::binary
Definition: SR_binary.hh:100
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
OpenMesh::Endian::local
static Type local()
Return endian type of host system.
Definition: Endian.hh:83