Developer Documentation
Loading...
Searching...
No Matches
ProgViewerWidget.cc
1/* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2025, 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
71using namespace Qt;
72//== IMPLEMENTATION ==========================================================
73
74
75void
77{
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
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
178void 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
203void 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
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
229void 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
316void 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//=============================================================================
@ LSB
Little endian (Intel family and clones)
Definition Endian.hh:78
static Type local()
Return endian type of host system.
Definition Endian.hh:83
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition PolyMeshT.hh:136
void update_face_normals()
Update normal vectors for all faces.
SmartVertexHandle add_vertex(const Point _p)
Definition PolyMeshT.hh:255
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition PolyMeshT.hh:137
Kernel::ConstVertexIter ConstVertexIter
Scalar type.
Definition PolyMeshT.hh:148
void update_vertex_normals()
Update normal vectors for all vertices.
Kernel::Point Point
Coordinate type.
Definition PolyMeshT.hh:112
HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1, VertexHandle _vl, VertexHandle _vr)
Vertex Split: inverse operation to collapse().
Definition TriMeshT.hh:218
void stop(void)
Stop measurement.
double seconds(void) const
Returns measured time in seconds, if the timer is in state 'Stopped'.
std::string as_string(Format format=Automatic)
void start(void)
Start measurement.
void open_prog_mesh(const char *_filename)
open progressive mesh
void refine(unsigned int _n)
refine mesh up to _n vertices
void coarsen(unsigned int _n)
coarsen mesh down 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:190
static size_t restore(std::istream &, value_type &, bool=false, bool=true)
Restore a value of T and return the number of bytes read.
Definition SR_binary.hh:125