Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
SubdivideWidget.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 //
51 // CLASS SubdivideWidget - IMPLEMENTATION
52 //
53 //=============================================================================
54
55 #ifndef SUBDIVIDEWIDGET_CC
56 #define SUBDIVIDEWIDGET_CC
57
58 //== INCLUDES =================================================================
59
60
61 // Qt
62 #include <QApplication>
63 #include <QFileDialog>
64 #include <QButtonGroup>
65 #include <QRadioButton>
66 #include <QVBoxLayout>
67 #include <QHBoxLayout>
68 #include <QPushButton>
69 #include <QLabel>
70 #include <QString>
71 #include <QMessageBox>
72
73 // OpenMesh
74 #include <OpenMesh/Core/IO/MeshIO.hh>
75 #include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
76 #include <OpenMesh/Tools/Subdivider/Uniform/CompositeLoopT.hh>
77 #include <OpenMesh/Tools/Subdivider/Uniform/CompositeSqrt3T.hh>
78 #include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>
79 #include <OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh>
80 #include <OpenMesh/Tools/Subdivider/Uniform/Sqrt3InterpolatingSubdividerLabsikGreinerT.hh>
81 #include <OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh>
82 #include <OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh>
83
84 #include <OpenMesh/Apps/Subdivider/SubdivideWidget.hh>
85
86
87 using namespace OpenMesh::Subdivider;
88
89 //== IMPLEMENTATION ==========================================================
90
91
92 SubdivideWidget::
93 SubdivideWidget(QWidget* _parent, const char* _name)
94 : QWidget(_parent),
95 timer_(NULL), animate_step_(0), max_animate_steps_(4), msecs_(0)
96 {
97
98 setWindowTitle( QString(_name) );
99
100 QVBoxLayout* vbox = new QVBoxLayout();
101
102 cur_topo_type = SOP_Undefined;
103 // sel_topo_type will be set when adding the radio button.;
104
105 // examiner widget
106 viewer_widget_ = new MeshViewerWidget();
107
108 vbox->addWidget(viewer_widget_);
109
110 QHBoxLayout* hbox = new QHBoxLayout();
111 // hbox->setFixedSize(400, 30);
112 vbox->addLayout(hbox);
113
114 // insert subdivision pushbutton
115 QPushButton* subdiv_button = new QPushButton( "Subdivide");
116 subdiv_button->setMinimumWidth(50);
117 QObject::connect( subdiv_button, SIGNAL( clicked() ),
118 this, SLOT( subdiv_slot() ) );
119 hbox->addWidget(subdiv_button);
120
121 // insert load pushbutton
122 QPushButton* load_button = new QPushButton( "Load Mesh");
123 load_button->setMinimumWidth(50);
124 QObject::connect( load_button, SIGNAL( clicked() ),
125 this, SLOT( load_slot() ) );
126 hbox->addWidget(load_button);
127
128 // insert save pushbutton
129 QPushButton* save_button = new QPushButton( "Save Mesh");
130 save_button->setMinimumWidth(50);
131 QObject::connect( save_button, SIGNAL( clicked() ),
132 this, SLOT( save_slot() ) );
133 hbox->addWidget(save_button);
134
135
136 // insert reset pushbutton
137 QPushButton* reset_button = new QPushButton( "Reset");
138 reset_button->setMinimumWidth(50);
139 QObject::connect( reset_button, SIGNAL( clicked() ),
140 this, SLOT( reset_slot() ) );
141 hbox->addWidget(reset_button);
142
143
144 // Create an exclusive button group: Topology Operators
145 // QButtonGroup *bgrp1 = new QButtonGroup( 1, QGroupBox::Vertical,"Subdivision Operators:");
146
147 QButtonGroup* buttonGroup = new QButtonGroup();
148
149 buttonGroup->setExclusive( true );
150
151 // insert 2 radiobuttons
152 QRadioButton* radio1 = new QRadioButton( "Comp. Loop" );
153 QRadioButton* radio2 = new QRadioButton( "Comp. SQRT(3)" );
154 QRadioButton* radio3 = new QRadioButton( "Loop" );
155 QRadioButton* radio4 = new QRadioButton( "Sqrt(3)" );
156 QRadioButton* radio5 = new QRadioButton( "Interpolating Sqrt3" );
157 QRadioButton* radio6 = new QRadioButton( "Modified Butterfly" );
158 // QRadioButton* radio7 = new QRadioButton( "Catmull Clark" ); // Disabled, as it needs a quad mesh!
159 radio3->setChecked( true );
160 sel_topo_type = SOP_UniformLoop;
161
162 buttonGroup->addButton(radio1, SOP_UniformCompositeLoop);
163 buttonGroup->addButton(radio2, SOP_UniformCompositeSqrt3);
164 buttonGroup->addButton(radio3, SOP_UniformLoop);
165 buttonGroup->addButton(radio4, SOP_UniformSqrt3);
166 buttonGroup->addButton(radio5, SOP_UniformInterpolatingSqrt3);
167 buttonGroup->addButton(radio6, SOP_ModifiedButterfly);
168 //buttonGroup->addButton(radio7, SOP_CatmullClark);
169
170 vbox->addWidget(radio1);
171 vbox->addWidget(radio2);
172 vbox->addWidget(radio3);
173 vbox->addWidget(radio4);
174 vbox->addWidget(radio5);
175 vbox->addWidget(radio6);
176 // vbox->addWidget(radio7);
177
178 QObject::connect( buttonGroup, SIGNAL( buttonPressed(int) ),
179 this, SLOT( slot_select_sop(int) ) );
180
181
182 status_bar = new QStatusBar();
183 status_bar->setFixedHeight(20);
184 status_bar->showMessage("0 Faces, 0 Edges, 0 Vertices");
185 vbox->addWidget(status_bar);
186
187
188 setLayout(vbox);
189
190
191 // animation
192 timer_ = new QTimer(this);
193 connect( timer_, SIGNAL( timeout() ), this, SLOT( animate_slot() ) );
194
195 // --------------------
196
197 subdivider_[SOP_UniformCompositeLoop] = new Uniform::CompositeLoopT<Mesh>;
198 subdivider_[SOP_UniformCompositeSqrt3] = new Uniform::CompositeSqrt3T<Mesh>;
199 subdivider_[SOP_UniformLoop] = new Uniform::LoopT<Mesh>;
200 subdivider_[SOP_UniformSqrt3] = new Uniform::Sqrt3T<Mesh>;
201 subdivider_[SOP_UniformInterpolatingSqrt3] = new Uniform::InterpolatingSqrt3LGT< Mesh >;
202 subdivider_[SOP_ModifiedButterfly] = new Uniform::ModifiedButterflyT<Mesh>;
203 subdivider_[SOP_CatmullClark] = new Uniform::CatmullClarkT<Mesh>;
204
205 }
206
207
208 //-----------------------------------------------------------------------------
209
210 void SubdivideWidget::slot_select_sop(int i)
211 {
212 switch(i)
213 {
214 case SOP_UniformCompositeLoop:
215 case SOP_UniformCompositeSqrt3:
216 case SOP_UniformLoop:
217 case SOP_UniformSqrt3:
218 case SOP_UniformInterpolatingSqrt3:
219 case SOP_ModifiedButterfly:
220 case SOP_CatmullClark: sel_topo_type = (SOPType)i; break;
221 default: sel_topo_type = SOP_Undefined;
222 }
223 }
224
225
226 //-----------------------------------------------------------------------------
227
228 void SubdivideWidget::keyPressEvent( QKeyEvent *k )
229 {
230 bool timerStopped = false;
231 if ( timer_->isActive())
232 {
233 timer_->stop();
234 timerStopped = true;
235 }
236
237 switch ( k->key() )
238 {
239 case Qt::Key_R: // reset
240 reset_slot();
241 break;
242 case Qt::Key_S: // save
243 save_slot();
244 break;
245 case Qt::Key_L: // load
246 load_slot();
247 break;
248
249 case Qt::Key_A:
250
251 if ( timerStopped )
252 break;
253
254 if (timer_->isActive())
255 {
256 timer_->stop();
257 }
258 else
259 {
260 reset_slot();
261 timer_->setSingleShot( true );
262 timer_->start(0);
263 }
264 break;
265
266 case ' ': // subdivide
267 subdiv_slot();
268 }
269 }
270
271
272
273 //-----------------------------------------------------------------------------
274
275
276 void SubdivideWidget::update()
277 {
278 size_t n_faces = viewer_widget_->mesh().n_faces();
279 size_t n_edges = viewer_widget_->mesh().n_edges();
280 size_t n_vertices = viewer_widget_->mesh().n_vertices();
281 QString message(""), temp;
282 message.append(temp.setNum(n_faces));
283 message.append(" Faces, ");
284 message.append(temp.setNum(n_edges));
285 message.append(" Edges, ");
286 message.append(temp.setNum(n_vertices));
287 message.append(" Vertices. ");
288 if (msecs_)
289 {
290 message.append(temp.setNum(msecs_/1000.0));
291 message.append("s");
292 }
293 status_bar->showMessage(message);
294 }
295
296
297 //-----------------------------------------------------------------------------
298
299
300 void SubdivideWidget::reset_slot()
301 {
302 if (cur_topo_type != SOP_Undefined)
303 subdivider_[cur_topo_type]->detach();
304
305 viewer_widget_->mesh() = viewer_widget_->orig_mesh();
306 viewer_widget_->mesh().update_face_normals();
307 viewer_widget_->mesh().update_vertex_normals();
308 viewer_widget_->updateGL();
309 update();
310 cur_topo_type = SOP_Undefined;
311 }
312
313
314
315 //-----------------------------------------------------------------------------
316
317
318 void SubdivideWidget::subdiv_slot()
319 {
320 assert( sel_topo_type != SOP_Undefined );
321
322 //QTime t;
323 using namespace OpenMesh::Subdivider::Uniform;
324
325 status_bar->showMessage( "processing subdivision step...");
326
327 if (cur_topo_type != sel_topo_type)
328 {
329 if (cur_topo_type!=SOP_Undefined)
330 subdivider_[cur_topo_type]->detach();
331 subdivider_[cur_topo_type=sel_topo_type]->attach(viewer_widget_->mesh());
332 }
333
334 std::clog << "subdiving...\n";
335 (*subdivider_[sel_topo_type])(1);
336 std::clog << "subdiving...done\n";
337
338 // Update viewer
339 viewer_widget_->mesh().update_normals();
340 viewer_widget_->updateGL();
341
342 // Update status bar information
343 update();
344 }
345
346
347 //-----------------------------------------------------------------------------
348
349 bool
350 SubdivideWidget::open_mesh(const char* _filename)
351 {
352 OpenMesh::IO::Options opt;
353
354 if (viewer_widget_->open_mesh(_filename, opt))
355 {
356 update();
357 return true;
358 }
359
360 return false;
361 }
362
363
364 //-----------------------------------------------------------------------------
365
366 void
367 SubdivideWidget::save_slot()
368 {
369 using OpenMesh::IO::IOManager;
370
371 QString write_filter(IOManager().qt_write_filters().c_str());
372 QString filename = QFileDialog::getSaveFileName(this, "", "", write_filter);
373
374 if (!filename.isEmpty()){
375 if (OpenMesh::IO::write_mesh(viewer_widget_->mesh(), filename.toStdString(),
376 OpenMesh::IO::Options::Binary) )
377 std::cerr << "ok\n";
378 else
379 std::cerr << "FAILED\n";
380 }
381 }
382
383
384 //-----------------------------------------------------------------------------
385
386 void
387 SubdivideWidget::load_slot()
388 {
389 using OpenMesh::IO::IOManager;
390
391 QString read_filter(IOManager().qt_read_filters().c_str());
392 QString filename =
393 QFileDialog::getOpenFileName(this, "", "", read_filter);
394
395 if (!filename.isNull())
396 {
397
398 if (cur_topo_type != SOP_Undefined)
399 subdivider_[cur_topo_type]->detach();
400
401 OpenMesh::IO::Options opt;
402 std::string file( filename.toStdString() );
403
404 if ( !viewer_widget_->open_mesh(file.c_str() , opt) )
405 {
406 QString msg = "Cannot read mesh from file ";
407 QMessageBox::critical( this,"", msg + filename, QMessageBox::Ok );
408 }
409
410 update();
411 cur_topo_type = SOP_Undefined;
412 }
413 }
414
415
416 //-----------------------------------------------------------------------------
417
418 void
419 SubdivideWidget::animate_slot()
420 {
421 if (++animate_step_ < max_animate_steps_)
422 {
423 subdiv_slot();
424 }
425 else
426 {
427 reset_slot();
428 animate_step_ = 0;
429 }
430 timer_->setSingleShot(true);
431 timer_->start( 500 );
432 }
433
434 //=============================================================================
435 #endif //SUBDIVIDEWIDGET_CC deifined
436 //=============================================================================
OpenMesh::Subdivider::Uniform::Sqrt3T
Definition: Sqrt3T.hh:103
OpenMesh::Subdivider::Uniform
SubdivideWidget::open_mesh
bool open_mesh(const char *_filename)
open mesh from _filename
Definition: SubdivideWidget.cc:350
Sqrt3InterpolatingSubdividerLabsikGreinerT.hh
SubdivideWidget::status_bar
QStatusBar * status_bar
Updates Status Bar Information.
Definition: SubdivideWidget.hh:108
OpenMesh::Subdivider::Uniform::ModifiedButterflyT
Definition: ModifiedButterFlyT.hh:99
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:95
OpenMesh::Subdivider::Uniform::LoopT
Definition: LoopT.hh:96
SubdivideWidget::SubdivideWidget
SubdivideWidget(QWidget *_parent=0, const char *_name=0)
constructor
Definition: SubdivideWidget.cc:93
OpenMesh::Subdivider::Uniform::CompositeSqrt3T
Definition: CompositeSqrt3T.hh:81
CompositeSqrt3T.hh
OpenMesh::Subdivider::Uniform::CatmullClarkT
Definition: CatmullClarkT.hh:92
ModifiedButterFlyT.hh
OpenMesh::Subdivider
MeshViewerWidget::open_mesh
bool open_mesh(const char *_filename, OpenMesh::IO::Options _opt)
open mesh
Definition: MeshViewerWidget.hh:88
OpenMesh::Subdivider::Uniform::CompositeLoopT
Definition: CompositeLoopT.hh:81
MeshViewerWidget
Definition: MeshViewerWidget.hh:80
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:105
CompositeLoopT.hh
OpenMesh::Subdivider::Uniform::InterpolatingSqrt3LGT
Definition: Sqrt3InterpolatingSubdividerLabsikGreinerT.hh:113
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:199
LoopT.hh
OpenMesh::IO::IOManager
_IOManager_ & IOManager()
Definition: IOManager.cc:77
Sqrt3T.hh
CatmullClarkT.hh