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
RemesherPlugin.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
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 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50
51 #include "RemesherPlugin.hh"
52
53 #include "Algorithms/AdaptiveRemesherT.hh"
54 #include "Algorithms/UniformRemesherT.hh"
55
56 /*
57 * STILL \TODO:
58 *
59 * - Emit status updates when remeshing
60 */
61
62 // ----------------------------------------------------------------------------------------
63
64 RemesherPlugin::RemesherPlugin() :
65 progress_(0) {
66
67 if ( OpenFlipper::Options::gui() ) {
68 progress_ = new ProgressEmitter();
69
70 connect(progress_, SIGNAL(signalJobState(QString,int)), this, SIGNAL(setJobState(QString,int)), Qt::QueuedConnection);
71 connect(progress_, SIGNAL(changeDescription(QString,QString)), this, SIGNAL(setJobDescription(QString,QString)), Qt::QueuedConnection);
72 }
73 }
74
75 // ----------------------------------------------------------------------------------------
76
77 RemesherPlugin::~RemesherPlugin() {
78 if ( OpenFlipper::Options::gui() ) {
79 delete progress_;
80 }
81 }
82
83 // ----------------------------------------------------------------------------------------
84
86 void RemesherPlugin::pluginsInitialized(){
87
88 emit setSlotDescription("adaptiveRemeshing(int,double,double,double,uint,bool)", "Adaptive Remeshing with vertex selection",
89 QString("object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(","),
90 QString("id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(","));
91 emit setSlotDescription("adaptiveRemeshing(int,double,double,double,uint)", "Adaptive Remeshing with vertex selection and projection method",
92 QString("object_id,error,min_edge_length,max_edge_length,iterations").split(","),
93 QString("id of an object,error,minimal target edge length,maximal target edge length,iterations").split(","));
94
95 emit setSlotDescription("adaptiveRemeshingFaceSelection(int,double,double,double,uint,bool)", "Adaptive Remeshing with face selection",
96 QString("object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(","),
97 QString("id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(","));
98 emit setSlotDescription("adaptiveRemeshingFaceSelection(int,double,double,double,uint)", "Adaptive Remeshing with face selection and projection method",
99 QString("object_id,error,min_edge_length,max_edge_length,iterations").split(","),
100 QString("id of an object,error,minimal target edge length,maximal target edge length,iterations").split(","));
101
102
103 emit setSlotDescription("uniformRemeshing(int,double,uint,uint,bool)", "Uniform Remeshing with vertex selection",
104 QString("object_id,edge_length,iterations,area_iterations,use_projection").split(","),
105 QString("id of an object,target edge length,iterations,area iterations,use projection method").split(","));
106 emit setSlotDescription("uniformRemeshing(int,double,uint,uint)", "Uniform Remeshing with vertex selection and projection method",
107 QString("object_id,edge_length,iterations,area_iterations").split(","),
108 QString("id of an object,target edge length,iterations,area iterations").split(","));
109
110 emit setSlotDescription("uniformRemeshingFaceSelection(int,double,uint,uint,bool)", "Uniform Remeshing with face selection",
111 QString("object_id,edge_length,iterations,area_iterations,use_projection").split(","),
112 QString("id of an object,target edge length,iterations,area iterations,use projection method").split(","));
113 emit setSlotDescription("uniformRemeshingFaceSelection(int,double,uint,uint)", "Uniform Remeshing with face selection and projection method",
114 QString("object_id,edge_length,iterations,area_iterations").split(","),
115 QString("id of an object,target edge length,iterations,area iterations").split(","));
116 }
117
118 // ----------------------------------------------------------------------------------------
119
121 void RemesherPlugin::initializePlugin() {
122
123 if ( OpenFlipper::Options::gui() ) {
124 tool_ = new RemesherToolBox();
125
126 // Connect buttons
127 connect(tool_->adaptive_button, SIGNAL(clicked()), this, SLOT(adaptiveRemeshingButtonClicked()) );
128 //connect(tool_->anisotropic_button, SIGNAL(clicked()), this, SLOT(anisotropicRemeshingButtonClicked()) );
129 connect(tool_->uniform_button, SIGNAL(clicked()), this, SLOT(uniformRemeshingButtonClicked()) );
130
131 connect(tool_->adaptive_initial_values, SIGNAL(clicked()), this, SLOT(computeInitValues()));
132 connect(tool_->uniform_initial_values, SIGNAL(clicked()), this, SLOT(computeInitValues()));
133
134 tool_->tabWidget->setCurrentIndex(0);
135
136 toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"remesher.png");
137 emit addToolbox( tr("Remesher") , tool_ , toolIcon_);
138 }
139
140 connect(this, SIGNAL( finishJob(QString)), this, SLOT(threadFinished(QString)), Qt::QueuedConnection);
141 }
142
143 // ----------------------------------------------------------------------------------------
144
145 void RemesherPlugin::threadFinished(QString _jobId) {
146
147 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)) ;
148 o_it != PluginFunctions::objectsEnd(); ++o_it) {
149
150 if ( operation_ == REMESH_ADAPTIVE ) {
151 emit updatedObject(o_it->id(), UPDATE_TOPOLOGY );
152 emit createBackup(o_it->id(), "Adaptive remeshing", UPDATE_TOPOLOGY);
153 } else if ( operation_ == REMESH_UNIFORM ) {
154 emit updatedObject(o_it->id(), UPDATE_TOPOLOGY );
155 emit createBackup(o_it->id(), "Uniform remeshing", UPDATE_TOPOLOGY);
156 }
157 }
158
159 // Detach job from progress emitter
160 progress_->detachJob();
161 }
162
163 // ----------------------------------------------------------------------------------------
164
165 void RemesherPlugin::computeInitValues() {
166
167 if(OpenFlipper::Options::nogui()) return;
168
169 double mean_edge = 0.0;
170 double max_feature_angle = 0.0;
171
172 //read one target objects
173 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)) ;
174 o_it != PluginFunctions::objectsEnd(); ++o_it) {
175
176 if(o_it->dataType() == DATA_TRIANGLE_MESH) {
177
178 TriMesh* mesh = PluginFunctions::triMesh(o_it->id());
179 if(!mesh) return;
180
181 mesh->update_face_normals();
182
183 for(TriMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
184
185 TriMesh::HalfedgeHandle he = mesh->halfedge_handle(*e_it, 0);
186
187 ACG::Vec3d vec_e = mesh->point(mesh->to_vertex_handle(he)) - mesh->point(mesh->from_vertex_handle(he));
188
189 mean_edge += vec_e.length();
190
191 // Estimate feature angle
192 TriMesh::FaceHandle fh1 = mesh->face_handle(he);
193 TriMesh::FaceHandle fh2 = mesh->face_handle(mesh->opposite_halfedge_handle(he));
194
195 // Boundary halfedge?
196 if ( !fh1.is_valid() || !fh2.is_valid() )
197 continue;
198
199 TriMesh::Normal n1 = mesh->normal(fh1);
200 TriMesh::Normal n2 = mesh->normal(fh2);
201
202 double feature_angle = (1.0 - (n1 | n2));
203
204 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
205 }
206
207 mean_edge /= (double)mesh->n_edges();
208
209 } else {
210 // DATA_POLY_MESH
211
212 PolyMesh* mesh = PluginFunctions::polyMesh(o_it->id());
213 if(!mesh) return;
214
215 mesh->update_face_normals();
216
217 for(PolyMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
218
219 PolyMesh::HalfedgeHandle he = mesh->halfedge_handle(*e_it, 0);
220
221 ACG::Vec3d vec_e = mesh->point(mesh->to_vertex_handle(he)) - mesh->point(mesh->from_vertex_handle(he));
222
223 mean_edge += vec_e.length();
224
225 // Estimate feature angle
226 PolyMesh::FaceHandle fh1 = mesh->face_handle(he);
227 PolyMesh::FaceHandle fh2 = mesh->face_handle(mesh->opposite_halfedge_handle(he));
228
229 // Boundary halfedge?
230 if ( !fh1.is_valid() || !fh2.is_valid() )
231 continue;
232
233 PolyMesh::Normal n1 = mesh->normal(fh1);
234 PolyMesh::Normal n2 = mesh->normal(fh2);
235
236 double feature_angle = (1.0 - (n1 | n2));
237
238 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
239 }
240
241 mean_edge /= (double)mesh->n_edges();
242 }
243
244 // Convert feature angle to radian
245 max_feature_angle = max_feature_angle * (M_PI / 2.0);
246
247 // Set adaptive values
248 tool_->adaptive_error->setValue(mean_edge * 0.1); // 10% of mean value
249 tool_->adaptive_min_edge->setValue(mean_edge - (mean_edge * 0.1)); // mean - 10%
250 tool_->adaptive_max_edge->setValue(mean_edge + (mean_edge * 0.1)); // mean + 10%
251
252 // Set uniform values
253 tool_->uniform_edge_length->setValue(mean_edge);
254
255 return; // Just take first object
256 }
257 }
258
259 // ----------------------- Adaptive Remeshing ---------------------------------------------
260
261 void RemesherPlugin::adaptiveRemeshingButtonClicked() {
262
263 QString jobId = name() + "AdaptiveRemeshing";
264 OpenFlipperThread* thread = new OpenFlipperThread(jobId);
265
266 connect(thread, SIGNAL( finished(QString)), this, SIGNAL(finishJob(QString)));
267 connect(thread, SIGNAL( function() ), this, SLOT(adaptiveRemeshing()),Qt::DirectConnection);
268
269
270 emit startJob( jobId, "Adaptive remeshing" , 0 , 100 , true);
271
272 // Attach job to progress emitter
273 progress_->attachJob(jobId);
274
275 thread->start();
276 thread->startProcessing();
277
278 }
279
280 // ----------------------------------------------------------------------------------------
281
282 void RemesherPlugin::adaptiveRemeshing() {
283
284 if(OpenFlipper::Options::nogui()) return;
285
286 //read one target objects
287 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_TRIANGLE_MESH)) ;
288 o_it != PluginFunctions::objectsEnd(); ++o_it) {
289
290 // Check data type.
291 // Note that adaptive remeshing is restricted
292 // to triangle meshes only since it relies
293 // on edge flips which are only defined
294 // for triangle configurations.
295
296 // Get parameters from GUI
297 double error = tool_->adaptive_error->value();
298 double min_edge = tool_->adaptive_min_edge->value();
299 double max_edge = tool_->adaptive_max_edge->value();
300 unsigned int iters = tool_->adaptive_iters->text().toInt();
301 bool projection = tool_->adaptive_projection->isChecked();
302 bool vertexSelection = (tool_->adaptive_selection->currentIndex() == 0);
303
304 slotAdaptiveRemeshing(o_it->id(), error, min_edge, max_edge, iters, projection,vertexSelection);
305
306 }
307 }
308
309 // ----------------------------------------------------------------------------------------
310
311 void RemesherPlugin::slotAdaptiveRemeshing(int _objectID,
312 double _error,
313 double _min_edge_length,
314 double _max_edge_length,
315 unsigned int _iters,
316 bool _use_projection,
317 bool _vertex_selection) {
318
319 operation_ = REMESH_ADAPTIVE;
320
321 BaseObjectData* object = 0;
322
323 if (PluginFunctions::getObject(_objectID, object)) {
324
325 // Check data type
326 if (object->dataType(DATA_TRIANGLE_MESH)) {
327
328 TriMesh* mesh = PluginFunctions::triMesh(object);
329
330 Remeshing::AdaptiveRemesherT<TriMesh> remesher(*mesh, progress_);
331
332 Remeshing::BaseRemesherT<TriMesh>::Selection selection = (_vertex_selection) ? Remeshing::BaseRemesherT<TriMesh>::VERTEX_SELECTION : Remeshing::BaseRemesherT<TriMesh>::FACE_SELECTION;
333
334 remesher.remesh(_error, _min_edge_length, _max_edge_length, _iters, _use_projection, selection);
335
336 mesh->update_normals();
337
338
339 QString projectionString = "\"FALSE\"";
340 if (_use_projection)
341 projectionString = "\"TRUE\"";
342
343 emit scriptInfo("adaptiveRemeshing(" + QString::number(_objectID) + ", "
344 + QString::number(_error) + ", "
345 + QString::number(_min_edge_length) + ", "
346 + QString::number(_max_edge_length) + ", "
347 + QString::number(_iters) + ", "
348 + projectionString + ")");
349
350 return;
351 }
352 }
353 }
354
355 // ----------------------- Uniform Remeshing ---------------------------------------------
356
357 void RemesherPlugin::uniformRemeshingButtonClicked() {
358
359 OpenFlipperThread* thread = new OpenFlipperThread(name() + "UniformRemeshing");
360
361 connect(thread, SIGNAL( state(QString, int)), this, SIGNAL(setJobState(QString, int)));
362 connect(thread, SIGNAL( finished(QString)), this, SIGNAL(finishJob(QString)));
363 connect(thread, SIGNAL( function() ), this, SLOT(uniformRemeshing()),Qt::DirectConnection);
364
365 emit startJob( name() + "UniformRemeshing", "Uniform remeshing" , 0 , 100 , true);
366
367 thread->start();
368 thread->startProcessing();
369
370 }
371
372 // ----------------------------------------------------------------------------------------
373
374 void RemesherPlugin::uniformRemeshing(){
375
376 if(OpenFlipper::Options::nogui()) return;
377
378 // Get parameters from GUI
379 double edge_length = tool_->uniform_edge_length->value();
380 unsigned int iters = tool_->uniform_iters->text().toInt();
381 unsigned int area_iters = tool_->uniform_area_iters->text().toInt();
382 bool projection = tool_->uniform_projection->isChecked();
383 bool vertex_selection = (tool_->uniform_selection->currentIndex() == 0);
384
385 //read one target objects
386 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_TRIANGLE_MESH)) ;
387 o_it != PluginFunctions::objectsEnd(); ++o_it) {
388
389 // Set incident vertices to feature edges to be feature vertices
390 TriMesh* mesh = PluginFunctions::triMesh(o_it->id());
391 if(!mesh) continue;
392 for(TriMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
393 if(mesh->status(*e_it).feature()) {
394 mesh->status(mesh->to_vertex_handle(mesh->halfedge_handle(*e_it, 0))).set_feature(true);
395 mesh->status(mesh->from_vertex_handle(mesh->halfedge_handle(*e_it, 0))).set_feature(true);
396 }
397 }
398
399 // Check data type.
400 // Note that uniform remeshing is restricted
401 // to triangle meshes only since it also relies
402 // on edge flips which are only defined
403 // for triangle configurations.
404
405 slotUniformRemeshing(o_it->id(), edge_length, iters, area_iters, projection,vertex_selection);
406 }
407 }
408
409 // ----------------------------------------------------------------------------------------
410
411 void RemesherPlugin::slotUniformRemeshing(int _objectID,
412 double _edge_length,
413 unsigned int _iters,
414 unsigned int _area_iters,
415 bool _use_projection,
416 bool _vertex_selection) {
417
418 operation_ = REMESH_UNIFORM;
419
420 BaseObjectData* object = 0;
421
422 if (PluginFunctions::getObject(_objectID, object)) {
423
424 // Check data type
425 if (object->dataType(DATA_TRIANGLE_MESH)) {
426
427 TriMesh* mesh = PluginFunctions::triMesh(object);
428
429 Remeshing::UniformRemesherT<TriMesh> remesher(*mesh, progress_);
430
431 Remeshing::BaseRemesherT<TriMesh>::Selection selection = (_vertex_selection) ? Remeshing::BaseRemesherT<TriMesh>::VERTEX_SELECTION : Remeshing::BaseRemesherT<TriMesh>::FACE_SELECTION;
432
433 remesher.remesh(_edge_length, _iters, _area_iters, _use_projection, selection);
434
435 mesh->update_normals();
436
437 QString projectionString = "\"FALSE\"";
438 if (_use_projection)
439 projectionString = "\"TRUE\"";
440
441 emit scriptInfo("uniformRemeshing(" + QString::number(_objectID) + ", "
442 + QString::number(_edge_length) + ", "
443 + QString::number(_iters) + ", "
444 + QString::number(_area_iters) + ", "
445 + QString::number(_iters) + ", "
446 + projectionString + ")");
447
448 return;
449 }
450 }
451
452 }
453
454 // ----------------------------------------------------------------------------------------
455
456 void RemesherPlugin::adaptiveRemeshing(int _objectID,
457 double _error,
458 double _min_edge_length,
459 double _max_edge_length,
460 unsigned int _iters,
461 bool _use_projection) {
462
463 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection);
464 emit updatedObject(_objectID, UPDATE_TOPOLOGY );
465 emit createBackup(_objectID, "Adaptive remeshing", UPDATE_TOPOLOGY);
466
467 }
468
469 // ----------------------------------------------------------------------------------------
470
471 void RemesherPlugin::uniformRemeshing(int _objectID,
472 double _edge_length,
473 unsigned int _iters,
474 unsigned int _area_iters,
475 bool _use_projection) {
476
477 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection);
478 emit updatedObject(_objectID, UPDATE_TOPOLOGY );
479 emit createBackup(_objectID, "Uniform remeshing", UPDATE_TOPOLOGY);
480
481 }
482
483 // ----------------------------------------------------------------------------------------
484
485 void RemesherPlugin::adaptiveRemeshingFaceSelection(int _objectID,
486 double _error,
487 double _min_edge_length,
488 double _max_edge_length,
489 unsigned int _iters,
490 bool _use_projection) {
491
492 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection,false);
493 emit updatedObject(_objectID, UPDATE_TOPOLOGY );
494 emit createBackup(_objectID, "Adaptive remeshing", UPDATE_TOPOLOGY);
495
496 }
497
498 // ----------------------------------------------------------------------------------------
499
500 void RemesherPlugin::uniformRemeshingFaceSelection(int _objectID,
501 double _edge_length,
502 unsigned int _iters,
503 unsigned int _area_iters,
504 bool _use_projection) {
505
506 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection,false);
507 emit updatedObject(_objectID, UPDATE_TOPOLOGY );
508 emit createBackup(_objectID, "Uniform remeshing", UPDATE_TOPOLOGY);
509
510 }
511
512 // ----------------------------------------------------------------------------------------
513
514 #if QT_VERSION < 0x050000
515 Q_EXPORT_PLUGIN2( remesherplugin, RemesherPlugin );
516 #endif
517
RemesherToolBox
Definition: RemesherToolbox.hh:60
OpenMesh::PolyMesh_ArrayKernelT
Definition: PolyMesh_ArrayKernelT.hh:98
ProgressEmitter
Definition: ProgressEmitter.hh:56
BaseObjectData
Definition: BaseObjectData.hh:105
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:134
RemesherPlugin::computeInitValues
void computeInitValues()
Compute mean edge length and set values.
Definition: RemesherPlugin.cc:165
RemesherPlugin
Definition: RemesherPlugin.hh:69
RemesherPlugin::pluginsInitialized
void pluginsInitialized()
Initialize the plugin.
Definition: RemesherPlugin.cc:86
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
Remeshing::BaseRemesherT
Definition: BaseRemesherT.hh:86
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:140
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:452
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:187
OpenMesh::VectorT
Definition: Vector11T.hh:83
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
OpenMesh::PolyMeshT::update_face_normals
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT.cc:259
OpenFlipperThread
Thread handling class for OpenFlipper.
Definition: OpenFlipperThread.hh:83
UPDATE_TOPOLOGY
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
OpenMesh::Attributes::Normal
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:87
DataType
Predefined datatypes.
Definition: DataTypes.hh:96
Remeshing::AdaptiveRemesherT
Definition: AdaptiveRemesherT.hh:78
Remeshing::UniformRemesherT
Definition: UniformRemesherT.hh:75
OpenFlipperThread::startProcessing
void startProcessing()
start processing
Definition: OpenFlipperThread.cc:118
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
RemesherPlugin::initializePlugin
void initializePlugin()
init the Toolbox
Definition: RemesherPlugin.cc:121
OpenMesh::PolyMeshT::Normal
Kernel::Normal Normal
Normal type.
Definition: PolyMeshT.hh:117