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
VDPMSynthesizerViewerWidget.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 newClass - IMPLEMENTATION
52 //
53 //=============================================================================
54
55 //== INCLUDES =================================================================
56
57 #ifdef _MSC_VER
58 # pragma warning(disable: 4267 4311)
59 #endif
60
61 #include <iostream>
62 #include <fstream>
63 #include <map>
64
65 #include <QApplication>
66 #include <QDateTime>
67 #include <QFileDialog>
68 #include <QDataStream>
69
70 #ifdef ARCH_DARWIN
71 #include <glut.h>
72 #else
73 #include <GL/glut.h>
74 #endif
75
76
77 #include <OpenMesh/Core/IO/MeshIO.hh>
78 #include <OpenMesh/Core/IO/BinaryHelper.hh>
79 #include <OpenMesh/Core/Utils/Endian.hh>
80 #include <OpenMesh/Tools/Utils/Timer.hh>
81 #include <OpenMesh/Apps/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.hh>
82
83
84 //== NAMESPACES ===============================================================
85
86
87 namespace OpenMesh {
88
89
90 //== IMPLEMENTATION ==========================================================
91
92 VDPMSynthesizerViewerWidget::VDPMSynthesizerViewerWidget(QWidget* _parent, const char* _name)
93 : MeshViewerWidget(_parent)
94 {
95 adaptive_mode_ = true;
96 }
97
98 VDPMSynthesizerViewerWidget::~VDPMSynthesizerViewerWidget()
99 {
100
101 }
102
103 void
104 VDPMSynthesizerViewerWidget::
105 draw_scene(const std::string &_draw_mode)
106 {
107 if (adaptive_mode_ == true)
108 {
109 adaptive_refinement();
110 }
111 MeshViewerWidget::draw_scene(_draw_mode);
112 }
113
114
115 void
116 VDPMSynthesizerViewerWidget::
117 adaptive_refinement()
118 {
119 update_viewing_parameters();
120
121 VDPMMesh::HalfedgeHandle v0v1;
122
123 float fovy = viewing_parameters_.fovy();
124
125 float tolerance_square = viewing_parameters_.tolerance_square();
126 float tan_value = tanf(fovy / 2.0f);
127
128 kappa_square_ = 4.0f * tan_value * tan_value * tolerance_square;
129
130 //assert( !vfront_.end() );
131
132 for ( vfront_.begin(); !vfront_.end(); )
133 {
134 VHierarchyNodeHandle
135 node_handle = vfront_.node_handle(),
136 parent_handle = vhierarchy_.parent_handle(node_handle);
137
138 if (vhierarchy_.is_leaf_node(node_handle) != true &&
139 qrefine(node_handle) == true)
140 {
141 force_vsplit(node_handle);
142 }
143 else if (vhierarchy_.is_root_node(node_handle) != true &&
144 ecol_legal(parent_handle, v0v1) == true &&
145 qrefine(parent_handle) != true)
146 {
147 ecol(parent_handle, v0v1);
148 }
149 else
150 {
151 vfront_.next();
152 }
153 }
154
155 // free memories tagged as 'deleted'
156 mesh_.garbage_collection(false, true, true);
157 mesh_.update_face_normals();
158 }
159
160
161 bool
162 VDPMSynthesizerViewerWidget::
163 qrefine(VHierarchyNodeHandle _node_handle)
164 {
165 VHierarchyNode &node = vhierarchy_.node(_node_handle);
166 Vec3f p = mesh_.point(node.vertex_handle());
167 Vec3f eye_dir = p - viewing_parameters_.eye_pos();;
168
169 float distance = eye_dir.length();
170 float distance2 = distance * distance;
171 float product_value = dot(eye_dir, node.normal());
172
173 if (outside_view_frustum(p, node.radius()) == true)
174 return false;
175
176 if (oriented_away(node.sin_square(), distance2, product_value) == true)
177 return false;
178
179 if (screen_space_error(node.mue_square(),
180 node.sigma_square(),
181 distance2,
182 product_value) == true)
183 return false;
184
185 return true;
186 }
187
188
189 void
190 VDPMSynthesizerViewerWidget::
191 force_vsplit(VHierarchyNodeHandle node_handle)
192 {
193 VDPMMesh::VertexHandle vl, vr;
194
195 get_active_cuts(node_handle, vl, vr);
196
197 while (vl == vr)
198 {
199 force_vsplit(mesh_.data(vl).vhierarchy_node_handle());
200 get_active_cuts(node_handle, vl, vr);
201 }
202
203 vsplit(node_handle, vl, vr);
204 }
205
206
207
208 void
209 VDPMSynthesizerViewerWidget::
210 vsplit(VHierarchyNodeHandle _node_handle,
211 VDPMMesh::VertexHandle vl,
212 VDPMMesh::VertexHandle vr)
213 {
214 // refine
215 VHierarchyNodeHandle
216 lchild_handle = vhierarchy_.lchild_handle(_node_handle),
217 rchild_handle = vhierarchy_.rchild_handle(_node_handle);
218
219 VDPMMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle);
220 VDPMMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle);
221
222 mesh_.vertex_split(v0, v1, vl, vr);
223 mesh_.set_normal(v0, vhierarchy_.normal(lchild_handle));
224 mesh_.set_normal(v1, vhierarchy_.normal(rchild_handle));
225 mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle);
226 mesh_.data(v1).set_vhierarchy_node_handle(rchild_handle);
227 mesh_.status(v0).set_deleted(false);
228 mesh_.status(v1).set_deleted(false);
229
230 vfront_.remove(_node_handle);
231 vfront_.add(lchild_handle);
232 vfront_.add(rchild_handle);
233 }
234
235
236 void
237 VDPMSynthesizerViewerWidget::
238 ecol(VHierarchyNodeHandle _node_handle, const VDPMMesh::HalfedgeHandle& v0v1)
239 {
240 VHierarchyNodeHandle
241 lchild_handle = vhierarchy_.lchild_handle(_node_handle),
242 rchild_handle = vhierarchy_.rchild_handle(_node_handle);
243
244 VDPMMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle);
245 VDPMMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle);
246
247 // coarsen
248 mesh_.collapse(v0v1);
249 mesh_.set_normal(v1, vhierarchy_.normal(_node_handle));
250 mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle);
251 mesh_.data(v1).set_vhierarchy_node_handle(_node_handle);
252 mesh_.status(v0).set_deleted(false);
253 mesh_.status(v1).set_deleted(false);
254
255 vfront_.add(_node_handle);
256 vfront_.remove(lchild_handle);
257 vfront_.remove(rchild_handle);
258 }
259
260
261 bool
262 VDPMSynthesizerViewerWidget::
263 ecol_legal(VHierarchyNodeHandle _parent_handle, VDPMMesh::HalfedgeHandle& v0v1)
264 {
265 VHierarchyNodeHandle
266 lchild_handle = vhierarchy_.lchild_handle(_parent_handle),
267 rchild_handle = vhierarchy_.rchild_handle(_parent_handle);
268
269 // test whether lchild & rchild present in the current vfront
270 if ( vfront_.is_active(lchild_handle) != true ||
271 vfront_.is_active(rchild_handle) != true)
272 return false;
273
274 VDPMMesh::VertexHandle v0, v1;
275
276 v0 = vhierarchy_.vertex_handle(lchild_handle);
277 v1 = vhierarchy_.vertex_handle(rchild_handle);
278
279 v0v1 = mesh_.find_halfedge(v0, v1);
280
281 return mesh_.is_collapse_ok(v0v1);
282 }
283
284 void
285 VDPMSynthesizerViewerWidget::
286 get_active_cuts(const VHierarchyNodeHandle _node_handle,
287 VDPMMesh::VertexHandle &vl, VDPMMesh::VertexHandle &vr)
288 {
289 VDPMMesh::VertexVertexIter vv_it;
290 VHierarchyNodeHandle nnode_handle;
291
292 VHierarchyNodeIndex
293 nnode_index,
294 fund_lcut_index = vhierarchy_.fund_lcut_index(_node_handle),
295 fund_rcut_index = vhierarchy_.fund_rcut_index(_node_handle);
296
297 vl = VDPMMesh::InvalidVertexHandle;
298 vr = VDPMMesh::InvalidVertexHandle;
299
300 for (vv_it=mesh_.vv_iter(vhierarchy_.vertex_handle(_node_handle));
301 vv_it.is_valid(); ++vv_it)
302 {
303 nnode_handle = mesh_.data(*vv_it).vhierarchy_node_handle();
304 nnode_index = vhierarchy_.node_index(nnode_handle);
305
306 if (vl == VDPMMesh::InvalidVertexHandle &&
307 vhierarchy_.is_ancestor(nnode_index, fund_lcut_index) == true)
308 vl = *vv_it;
309
310 if (vr == VDPMMesh::InvalidVertexHandle &&
311 vhierarchy_.is_ancestor(nnode_index, fund_rcut_index) == true)
312 vr = *vv_it;
313
314 /*if (vl == VDPMMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_lcut_index) == true)
315 vl = *vv_it;
316 if (vr == VDPMMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_rcut_index) == true)
317 vr = *vv_it;*/
318
319 if (vl != VDPMMesh::InvalidVertexHandle &&
320 vr != VDPMMesh::InvalidVertexHandle)
321 break;
322 }
323 }
324
325
326 bool
327 VDPMSynthesizerViewerWidget::
328 outside_view_frustum(const Vec3f &pos, float radius)
329 {
330 #if 0
331 return
332 (frustum_plane_[0].signed_distance(pos) < -radius) ||
333 (frustum_plane_[1].signed_distance(pos) < -radius) ||
334 (frustum_plane_[2].signed_distance(pos) < -radius) ||
335 (frustum_plane_[3].signed_distance(pos) < -radius);
336 #else
337
338 Plane3d frustum_plane[4];
339
340 viewing_parameters_.frustum_planes(frustum_plane);
341
342 for (int i = 0; i < 4; i++) {
343 if (frustum_plane[i].singed_distance(pos) < -radius)
344 return true;
345 }
346 return false;
347 #endif
348 }
349
350 bool
351 VDPMSynthesizerViewerWidget::
352 oriented_away(float sin_square, float distance_square, float product_value)
353 {
354 #if 0
355 return (product_value > 0)
356 && ((product_value * product_value) > (distance_square * sin_square));
357 #else
358 if (product_value > 0 &&
359 product_value * product_value > distance_square * sin_square)
360 return true;
361 else
362 return false;
363 #endif
364 }
365
366
367 bool
368 VDPMSynthesizerViewerWidget::
369 screen_space_error(float mue_square, float sigma_square,
370 float distance_square, float product_value)
371 {
372 #if 0
373 float ks_ds = kappa_square_ * distance_square;
374 float pv_pv = product_value * product_value;
375 return (mue_square >= ks_ds)
376 || (sigma_square*( distance_square - pv_pv) >= ks_ds*distance_square);
377 #else
378 if ((mue_square >= kappa_square_ * distance_square) ||
379 (sigma_square * (distance_square - product_value * product_value) >= kappa_square_ * distance_square * distance_square))
380 return false;
381 else
382 return true;
383 #endif
384 }
385
386 void
387 VDPMSynthesizerViewerWidget::
388 open_vd_prog_mesh(const char* _filename)
389 {
390 unsigned int i;
391 unsigned int value;
392 unsigned int fvi[3];
393 char fileformat[16];
394 Vec3f p, normal;
395 float radius, sin_square, mue_square, sigma_square;
396 VHierarchyNodeHandleContainer roots;
397 VertexHandle vertex_handle;
398 VHierarchyNodeIndex node_index;
399 VHierarchyNodeIndex lchild_node_index, rchild_node_index;
400 VHierarchyNodeIndex fund_lcut_index, fund_rcut_index;
401 VHierarchyNodeHandle node_handle;
402 VHierarchyNodeHandle lchild_node_handle, rchild_node_handle;
403
404 std::map<VHierarchyNodeIndex, VHierarchyNodeHandle> index2handle_map;
405
406 std::ifstream ifs(_filename, std::ios::binary);
407
408 if (!ifs)
409 {
410 std::cerr << "read error\n";
411 exit(1);
412 }
413
414 //
415 bool swap = Endian::local() != Endian::LSB;
416
417 // read header
418 ifs.read(fileformat, 10); fileformat[10] = '\0';
419 if (std::string(fileformat) != std::string("VDProgMesh"))
420 {
421 std::cerr << "Wrong file format.\n";
422 ifs.close();
423 exit(1);
424 }
425
426 IO::restore(ifs, n_base_vertices_, swap);
427 IO::restore(ifs, n_base_faces_, swap);
428 IO::restore(ifs, n_details_, swap);
429
430 mesh_.clear();
431 vfront_.clear();
432 vhierarchy_.clear();
433
434 vhierarchy_.set_num_roots(n_base_vertices_);
435
436 // load base mesh
437 for (i=0; i<n_base_vertices_; ++i)
438 {
439 IO::restore(ifs, p, swap);
440 IO::restore(ifs, radius, swap);
441 IO::restore(ifs, normal, swap);
442 IO::restore(ifs, sin_square, swap);
443 IO::restore(ifs, mue_square, swap);
444 IO::restore(ifs, sigma_square, swap);
445
446 vertex_handle = mesh_.add_vertex(p);
447 node_index = vhierarchy_.generate_node_index(i, 1);
448 node_handle = vhierarchy_.add_node();
449
450 VHierarchyNode &node = vhierarchy_.node(node_handle);
451
452 node.set_index(node_index);
453 node.set_vertex_handle(vertex_handle);
454 mesh_.data(vertex_handle).set_vhierarchy_node_handle(node_handle);
455
456 node.set_radius(radius);
457 node.set_normal(normal);
458 node.set_sin_square(sin_square);
459 node.set_mue_square(mue_square);
460 node.set_sigma_square(sigma_square);
461 mesh_.set_normal(vertex_handle, normal);
462
463 index2handle_map[node_index] = node_handle;
464 roots.push_back(node_handle);
465 }
466 vfront_.init(roots, n_details_);
467
468 for (i=0; i<n_base_faces_; ++i)
469 {
470 IO::restore(ifs, fvi[0], swap);
471 IO::restore(ifs, fvi[1], swap);
472 IO::restore(ifs, fvi[2], swap);
473
474 mesh_.add_face(mesh_.vertex_handle(fvi[0]),
475 mesh_.vertex_handle(fvi[1]),
476 mesh_.vertex_handle(fvi[2]));
477 }
478
479 // load details
480 for (i=0; i<n_details_; ++i)
481 {
482 // position of v0
483 IO::restore(ifs, p, swap);
484
485 // vsplit info.
486 IO::restore(ifs, value, swap);
487 node_index = VHierarchyNodeIndex(value);
488
489 IO::restore(ifs, value, swap);
490 fund_lcut_index = VHierarchyNodeIndex(value);
491
492 IO::restore(ifs, value, swap);
493 fund_rcut_index = VHierarchyNodeIndex(value);
494
495
496 node_handle = index2handle_map[node_index];
497 vhierarchy_.make_children(node_handle);
498
499 VHierarchyNode &node = vhierarchy_.node(node_handle);
500 VHierarchyNode &lchild = vhierarchy_.node(node.lchild_handle());
501 VHierarchyNode &rchild = vhierarchy_.node(node.rchild_handle());
502
503 node.set_fund_lcut(fund_lcut_index);
504 node.set_fund_rcut(fund_rcut_index);
505
506 vertex_handle = mesh_.add_vertex(p);
507 lchild.set_vertex_handle(vertex_handle);
508 rchild.set_vertex_handle(node.vertex_handle());
509
510 index2handle_map[lchild.node_index()] = node.lchild_handle();
511 index2handle_map[rchild.node_index()] = node.rchild_handle();
512
513 // view-dependent parameters
514 IO::restore(ifs, radius, swap);
515 IO::restore(ifs, normal, swap);
516 IO::restore(ifs, sin_square, swap);
517 IO::restore(ifs, mue_square, swap);
518 IO::restore(ifs, sigma_square, swap);
519 lchild.set_radius(radius);
520 lchild.set_normal(normal);
521 lchild.set_sin_square(sin_square);
522 lchild.set_mue_square(mue_square);
523 lchild.set_sigma_square(sigma_square);
524
525 IO::restore(ifs, radius, swap);
526 IO::restore(ifs, normal, swap);
527 IO::restore(ifs, sin_square, swap);
528 IO::restore(ifs, mue_square, swap);
529 IO::restore(ifs, sigma_square, swap);
530 rchild.set_radius(radius);
531 rchild.set_normal(normal);
532 rchild.set_sin_square(sin_square);
533 rchild.set_mue_square(mue_square);
534 rchild.set_sigma_square(sigma_square);
535 }
536
537 ifs.close();
538
539 // update face and vertex normals
540 mesh_.update_face_normals();
541
542 // bounding box
543 VDPMMesh::ConstVertexIter
544 vIt(mesh_.vertices_begin()),
545 vEnd(mesh_.vertices_end());
546
547 VDPMMesh::Point bbMin, bbMax;
548
549 bbMin = bbMax = mesh_.point(*vIt);
550 for (; vIt!=vEnd; ++vIt)
551 {
552 bbMin.minimize(mesh_.point(*vIt));
553 bbMax.maximize(mesh_.point(*vIt));
554 }
555
556 // set center and radius
557 set_scene_pos(0.5f*(bbMin + bbMax), 0.5*(bbMin - bbMax).norm());
558
559 // info
560 std::cerr << mesh_.n_vertices() << " vertices, "
561 << mesh_.n_edges() << " edge, "
562 << mesh_.n_faces() << " faces, "
563 << n_details_ << " detail vertices\n";
564
565 updateGL();
566 }
567
568
569 void VDPMSynthesizerViewerWidget::keyPressEvent(QKeyEvent* _event)
570 {
571 switch (_event->key())
572 {
573 case Key_Home:
574 updateGL();
575 break;
576
577 case Key_End:
578 updateGL();
579 break;
580
581 case Key_Minus:
582 viewing_parameters_.increase_tolerance();
583 std::cout << "Scree-space error tolerance^2 is increased by "
584 << viewing_parameters_.tolerance_square() << std::endl;
585 updateGL();
586 break;
587
588 case Key_Plus:
589 viewing_parameters_.decrease_tolerance();
590 std::cout << "Screen-space error tolerance^2 is decreased by "
591 << viewing_parameters_.tolerance_square() << std::endl;
592 updateGL();
593 break;
594
595 case Key_A:
596 adaptive_mode_ = !(adaptive_mode_);
597 std::cout << "Adaptive refinement mode is "
598 << (adaptive_mode_ ? "on" : "off") << std::endl;
599 updateGL();
600 break;
601
602 case Key_O:
603 qFilename_ = QFileDialog::getOpenFileName(0,"", "", "*.spm");
604 open_vd_prog_mesh( qFilename_.toStdString().c_str() );
605 break;
606
607 default:
608 MeshViewerWidget::keyPressEvent( _event );
609 }
610
611 }
612
613
614
615
616
617 void
618 VDPMSynthesizerViewerWidget::
619 update_viewing_parameters()
620 {
621 viewing_parameters_.set_modelview_matrix(modelview_matrix());
622 viewing_parameters_.set_aspect((float) width()/ (float) height());
623 viewing_parameters_.set_fovy(fovy());
624
625 viewing_parameters_.update_viewing_configurations();
626 }
627
628
629 //=============================================================================
630 } // namespace OpenMesh
631 //=============================================================================
OpenMesh::VectorT::swap
void swap(VectorT< Scalar, DIM > &_v1, VectorT< Scalar, DIM > &_v2) noexcept(noexcept(_v1.swap(_v2)))
Definition: Vector11T.hh:715
OpenMesh
Definition: MeshItems.hh:64
OpenMesh::VectorT::dot
Scalar dot(const VectorT< Scalar, N > &_v1, const VectorT< Scalar, N > &_v2)
Definition: MeshNode2T.cc:263
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
OpenMesh::PolyMeshT::add_vertex
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:236
Timer.hh
OpenMesh::VectorT< float, 3 >
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:125
OpenMesh::PolyMeshT::update_face_normals
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT.cc:259
MeshViewerWidget
Definition: MeshViewerWidget.hh:80
MeshViewerWidgetT< MyMesh >::draw_scene
virtual void draw_scene(const std::string &_draw_mode)
inherited drawing method
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:213
OpenVolumeMesh::Geometry::VectorT
Definition: Vector11T.hh:78