60 #include <OpenMesh/Core/IO/MeshIO.hh>
61 #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
62 #include <OpenMesh/Core/Utils/Endian.hh>
64 #include <OpenMesh/Tools/Utils/getopt.h>
66 #include <OpenMesh/Tools/VDPM/StreamingDef.hh>
67 #include <OpenMesh/Tools/VDPM/ViewingParameters.hh>
68 #include <OpenMesh/Tools/VDPM/VHierarchy.hh>
69 #include <OpenMesh/Tools/VDPM/VFront.hh>
100 VHierarchyNodeHandle vhierarchy_node_handle()
101 {
return node_handle_; }
103 void set_vhierarchy_node_handle(VHierarchyNodeHandle _node_handle)
104 { node_handle_ = _node_handle; }
106 bool is_ancestor(
const VHierarchyNodeIndex &_other)
111 VHierarchyNodeHandle node_handle_;
121 vhierarchy_leaf_node_handle()
122 {
return leaf_node_handle_; }
125 set_vhierarchy_leaf_node_handle(VHierarchyNodeHandle _leaf_node_handle)
126 { leaf_node_handle_ = _leaf_node_handle; }
130 VHierarchyNodeHandle leaf_node_handle_;
153 typedef std::vector<PMInfo> PMInfoContainer;
154 typedef PMInfoContainer::iterator PMInfoIter;
155 typedef std::vector<VertexHandle> VertexHandleContainer;
156 typedef std::vector<Vec3f> ResidualContainer;
162 void open_prog_mesh(
const std::string &_filename);
165 void save_vd_prog_mesh(
const std::string &_filename);
169 void locate_fund_cut_vertices();
171 void create_vertex_hierarchy();
175 void refine(
unsigned int _n);
178 void coarsen(
unsigned int _n);
180 void vdpm_analysis();
182 void get_leaf_node_handles(VHierarchyNodeHandle node_handle,
183 VHierarchyNodeHandleContainer &leaf_nodes);
184 void compute_bounding_box(VHierarchyNodeHandle node_handle,
185 VHierarchyNodeHandleContainer &leaf_nodes);
186 void compute_cone_of_normals(VHierarchyNodeHandle node_handle,
187 VHierarchyNodeHandleContainer &leaf_nodes);
188 void compute_screen_space_error(VHierarchyNodeHandle node_handle,
189 VHierarchyNodeHandleContainer &leaf_nodes);
190 void compute_mue_sigma(VHierarchyNodeHandle node_handle,
191 ResidualContainer &residuals);
194 point2triangle_residual(
const Vec3f &p,
195 const Vec3f tri[3],
float &s,
float &t);
198 void PrintOutFundCuts();
199 void PrintVertexNormals();
205 PMInfoContainer pminfos_;
208 VHierarchy vhierarchy_;
210 unsigned int n_base_vertices_, n_base_faces_, n_details_;
211 unsigned int n_current_res_;
212 unsigned int n_max_res_;
213 bool verbose =
false;
218 void usage_and_exit(
int xcode)
222 cout <<
"Usage: vdpmanalyzer [-h] [-o output.spm] input.pm\n";
231 replace_extension( std::string& _s,
const std::string& _e )
233 std::string::size_type
dot = _s.rfind(
".");
234 if (dot == std::string::npos)
237 { _s = _s.substr(0,dot+1)+_e; }
245 basename(
const std::string& _f)
247 std::string::size_type dot = _f.rfind(
"/");
248 if (dot == std::string::npos)
250 return _f.substr(dot+1, _f.length()-(dot+1));
257 typedef std::vector<OpenMesh::Vec3f> MyPoints;
258 typedef MyPoints::iterator MyPointsIter;
260 MyPoints projected_points;
261 MyPoints original_points;
267 int main(
int argc,
char **argv)
273 while ( (c=getopt(argc, argv,
"o:"))!=-1 )
277 case 'v': verbose =
true;
break;
278 case 'o': ofname = optarg;
break;
279 case 'h': usage_and_exit(0);
280 default: usage_and_exit(1);
287 ifname = argv[optind];
289 if (ofname ==
"." || ofname ==
".." )
290 ofname +=
"/" + basename(ifname);
291 std::string spmfname = ofname.empty() ? ifname : ofname;
292 replace_extension(spmfname,
"spm");
294 if ( ifname.empty() || spmfname.empty() )
301 open_prog_mesh(ifname);
303 save_vd_prog_mesh(spmfname);
305 catch( std::bad_alloc& )
307 std::cerr <<
"Error: out of memory!\n" << std::endl;
310 catch( std::exception& x )
312 std::cerr <<
"Error: " << x.what() << std::endl;
317 std::cerr <<
"Fatal! Unknown error!\n";
327 open_prog_mesh(
const std::string& _filename)
330 unsigned int i, i0, i1, i2;
331 unsigned int v1, vl, vr;
334 VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle;
335 VHierarchyNodeIndex node_index;
337 std::ifstream ifs(_filename.c_str(), std::ios::binary);
340 std::cerr <<
"read error\n";
348 ifs.read(c, 8); c[8] =
'\0';
349 if (std::string(c) != std::string(
"ProgMesh"))
351 std::cerr <<
"Wrong file format.\n";
355 IO::restore(ifs, n_base_vertices_, swap);
356 IO::restore(ifs, n_base_faces_, swap);
357 IO::restore(ifs, n_details_, swap);
359 vhierarchy_.set_num_roots(n_base_vertices_);
361 for (i=0; i<n_base_vertices_; ++i)
363 IO::restore(ifs, p, swap);
366 node_index = vhierarchy_.generate_node_index(i, 1);
367 node_handle = vhierarchy_.add_node();
369 vhierarchy_.node(node_handle).set_index(node_index);
370 vhierarchy_.node(node_handle).set_vertex_handle(vertex_handle);
371 mesh_.data(vertex_handle).set_vhierarchy_node_handle(node_handle);
374 for (i=0; i<n_base_faces_; ++i)
376 IO::restore(ifs, i0, swap);
377 IO::restore(ifs, i1, swap);
378 IO::restore(ifs, i2, swap);
379 mesh_.add_face(mesh_.vertex_handle(i0),
380 mesh_.vertex_handle(i1),
381 mesh_.vertex_handle(i2));
385 for (i=0; i<n_details_; ++i)
387 IO::restore(ifs, p, swap);
388 IO::restore(ifs, v1, swap);
389 IO::restore(ifs, vl, swap);
390 IO::restore(ifs, vr, swap);
398 pminfos_.push_back(pminfo);
400 node_handle = mesh_.data(pminfo.v1).vhierarchy_node_handle();
402 vhierarchy_.make_children(node_handle);
403 lchild_handle = vhierarchy_.lchild_handle(node_handle);
404 rchild_handle = vhierarchy_.rchild_handle(node_handle);
406 mesh_.data(pminfo.v0).set_vhierarchy_node_handle(lchild_handle);
407 mesh_.data(pminfo.v1).set_vhierarchy_node_handle(rchild_handle);
408 vhierarchy_.node(lchild_handle).set_vertex_handle(pminfo.v0);
409 vhierarchy_.node(rchild_handle).set_vertex_handle(pminfo.v1);
416 for (i=0; i<n_base_vertices_; ++i)
418 node_handle = vhierarchy_.root_handle(i);
419 vertex_handle = vhierarchy_.node(node_handle).vertex_handle();
421 mesh_.data(vertex_handle).set_vhierarchy_node_handle(node_handle);
424 pmiter_ = pminfos_.begin();
426 n_max_res_ = n_details_;
434 Mesh::ConstVertexIter
435 vIt(mesh_.vertices_begin()),
436 vEnd(mesh_.vertices_end());
440 bbMin = bbMax = mesh_.point(*vIt);
441 for (; vIt!=vEnd; ++vIt)
443 bbMin.minimize(mesh_.point(*vIt));
444 bbMax.maximize(mesh_.point(*vIt));
448 std::cerr << mesh_.n_vertices() <<
" vertices, "
449 << mesh_.n_edges() <<
" edge, "
450 << mesh_.n_faces() <<
" faces, "
451 << n_details_ <<
" detail vertices\n";
458 save_vd_prog_mesh(
const std::string &_filename)
464 float radius, sin_square, mue_square, sigma_square;
466 Mesh::HalfedgeHandle hh;
468 VHierarchyNodeIndex node_index;
469 VHierarchyNodeIndex fund_lcut_index, fund_rcut_index;
470 VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle;
471 std::map<VertexHandle, unsigned int> handle2index_map;
473 std::ofstream ofs(_filename.c_str(), std::ios::binary);
476 std::cerr <<
"write error\n";
486 IO::store(ofs, n_base_vertices_, swap);
487 IO::store(ofs, n_base_faces_, swap);
488 IO::store(ofs, n_details_, swap);
492 mesh_.garbage_collection(
false,
true,
true );
494 for (i=0; i<n_base_vertices_; ++i)
496 node_handle = vhierarchy_.root_handle(i);
497 vh = vhierarchy_.node(node_handle).vertex_handle();
500 radius = vhierarchy_.node(node_handle).radius();
501 normal = vhierarchy_.node(node_handle).normal();
502 sin_square = vhierarchy_.node(node_handle).sin_square();
503 mue_square = vhierarchy_.node(node_handle).mue_square();
504 sigma_square = vhierarchy_.node(node_handle).sigma_square();
506 IO::store(ofs, p, swap);
507 IO::store(ofs, radius, swap);
508 IO::store(ofs, normal, swap);
509 IO::store(ofs, sin_square, swap);
510 IO::store(ofs, mue_square, swap);
511 IO::store(ofs, sigma_square, swap);
513 handle2index_map[vh] = i;
517 for (f_it=mesh_.faces_begin(); f_it!=mesh_.faces_end(); ++f_it) {
518 hh = mesh_.halfedge_handle(*f_it);
519 vh = mesh_.to_vertex_handle(hh);
520 fvi[0] = handle2index_map[vh];
522 hh = mesh_.next_halfedge_handle(hh);
523 vh = mesh_.to_vertex_handle(hh);
524 fvi[1] = handle2index_map[vh];
526 hh = mesh_.next_halfedge_handle(hh);
527 vh = mesh_.to_vertex_handle(hh);
528 fvi[2] = handle2index_map[vh];
530 IO::store(ofs, fvi[0], swap);
531 IO::store(ofs, fvi[1], swap);
532 IO::store(ofs, fvi[2], swap);
538 for (i=0; i<n_details_; ++i)
540 PMInfo pminfo = *pmiter_;
542 p = mesh_.point(pminfo.v0);
544 IO::store(ofs, p, swap);
547 node_handle = mesh_.data(pminfo.v1).vhierarchy_node_handle();
548 lchild_handle = vhierarchy_.lchild_handle(node_handle);
549 rchild_handle = vhierarchy_.rchild_handle(node_handle);
551 node_index = vhierarchy_.node(node_handle).node_index();
552 fund_lcut_index = vhierarchy_.node(node_handle).fund_lcut_index();
553 fund_rcut_index = vhierarchy_.node(node_handle).fund_rcut_index();
555 IO::store(ofs, node_index.value(), swap);
556 IO::store(ofs, fund_lcut_index.value(), swap);
557 IO::store(ofs, fund_rcut_index.value(), swap);
559 radius = vhierarchy_.node(lchild_handle).radius();
560 normal = vhierarchy_.node(lchild_handle).normal();
561 sin_square = vhierarchy_.node(lchild_handle).sin_square();
562 mue_square = vhierarchy_.node(lchild_handle).mue_square();
563 sigma_square = vhierarchy_.node(lchild_handle).sigma_square();
565 IO::store(ofs, radius, swap);
566 IO::store(ofs, normal, swap);
567 IO::store(ofs, sin_square, swap);
568 IO::store(ofs, mue_square, swap);
569 IO::store(ofs, sigma_square, swap);
571 radius = vhierarchy_.node(rchild_handle).radius();
572 normal = vhierarchy_.node(rchild_handle).normal();
573 sin_square = vhierarchy_.node(rchild_handle).sin_square();
574 mue_square = vhierarchy_.node(rchild_handle).mue_square();
575 sigma_square = vhierarchy_.node(rchild_handle).sigma_square();
577 IO::store(ofs, radius, swap);
578 IO::store(ofs, normal, swap);
579 IO::store(ofs, sin_square, swap);
580 IO::store(ofs, mue_square, swap);
581 IO::store(ofs, sigma_square, swap);
588 std::cout <<
"save view-dependent progressive mesh" << std::endl;
593 void refine(
unsigned int _n)
595 while (n_current_res_ < _n && pmiter_ != pminfos_.end())
603 parent_handle = mesh_.data(pmiter_->v1).vhierarchy_node_handle();
606 lchild_handle = vhierarchy_.lchild_handle(parent_handle),
607 rchild_handle = vhierarchy_.rchild_handle(parent_handle);
609 mesh_.data(pmiter_->v0).set_vhierarchy_node_handle(lchild_handle);
610 mesh_.data(pmiter_->v1).set_vhierarchy_node_handle(rchild_handle);
621 void coarsen(
unsigned int _n)
623 while (n_current_res_ > _n && pmiter_ != pminfos_.begin())
627 Mesh::HalfedgeHandle hh =
628 mesh_.find_halfedge(pmiter_->v0, pmiter_->v1);
632 rchild_handle = mesh_.data(pmiter_->v1).vhierarchy_node_handle();
635 parent_handle = vhierarchy_.parent_handle(rchild_handle);
637 mesh_.data(pmiter_->v1).set_vhierarchy_node_handle(parent_handle);
652 Mesh::VertexIter v_it;
653 Mesh::HalfedgeIter h_it;
654 Mesh::HalfedgeHandle h, o, hn, op, hpo, on, ono;
665 std::cout <<
"Init view-dependent PM analysis" << std::endl;
668 for (h_it=mesh_.halfedges_begin(); h_it!=mesh_.halfedges_end(); ++h_it)
670 vh = mesh_.to_vertex_handle(*h_it);
671 mesh_.data(*h_it).set_vhierarchy_leaf_node_handle(mesh_.data(vh).vhierarchy_node_handle());
674 for (v_it=mesh_.vertices_begin(); v_it!=mesh_.vertices_end(); ++v_it)
677 node_handle = mesh_.data(*v_it).vhierarchy_node_handle();
679 vhierarchy_.node(node_handle).set_normal(mesh_.normal(*v_it));
682 std::cout <<
"Start view-dependent PM analysis" << std::endl;
687 for (i=n_max_res_; i>0; --i)
690 PMInfo pminfo = pminfos_[i-1];
693 std::cout <<
"Analyzing " << i <<
"-th detail vertex" << std::endl;
696 h = mesh_.find_halfedge(pminfo.v0, pminfo.v1);
697 o = mesh_.opposite_halfedge_handle(h);
698 hn = mesh_.next_halfedge_handle(h);
699 hpo = mesh_.opposite_halfedge_handle(mesh_.prev_halfedge_handle(h));
700 op = mesh_.prev_halfedge_handle(o);
701 on = mesh_.next_halfedge_handle(o);
702 ono = mesh_.opposite_halfedge_handle(on);
705 rchild_handle = mesh_.data(pminfo.v1).vhierarchy_node_handle();
708 parent_handle = vhierarchy_.parent_handle(rchild_handle);
710 if (pminfo.vl != Mesh::InvalidVertexHandle)
713 fund_lcut_handle = mesh_.data(hn).vhierarchy_leaf_node_handle();
716 left_leaf_handle = mesh_.data(hpo).vhierarchy_leaf_node_handle();
718 mesh_.data(hn).set_vhierarchy_leaf_node_handle(left_leaf_handle);
720 vhierarchy_.node(parent_handle).
721 set_fund_lcut(vhierarchy_.node_index(fund_lcut_handle));
724 if (pminfo.vr != Mesh::InvalidVertexHandle)
727 fund_rcut_handle = mesh_.data(on).vhierarchy_leaf_node_handle(),
728 right_leaf_handle = mesh_.data(ono).vhierarchy_leaf_node_handle();
730 mesh_.data(op).set_vhierarchy_leaf_node_handle(right_leaf_handle);
732 vhierarchy_.node(parent_handle).
733 set_fund_rcut(vhierarchy_.node_index(fund_rcut_handle));
740 get_leaf_node_handles(parent_handle, leaf_nodes);
741 compute_bounding_box(parent_handle, leaf_nodes);
742 compute_cone_of_normals(parent_handle, leaf_nodes);
743 compute_screen_space_error(parent_handle, leaf_nodes);
749 std::cout <<
" radius of bounding sphere: "
750 << vhierarchy_.node(parent_handle).radius() << std::endl;
751 std::cout <<
" direction of cone of normals: "
752 << vhierarchy_.node(parent_handle).normal() << std::endl;
753 std::cout <<
" sin(semi-angle of cone of normals) ^2: "
754 << vhierarchy_.node(parent_handle).sin_square() << std::endl;
755 std::cout <<
" (mue^2, sigma^2) : ("
756 << vhierarchy_.node(parent_handle).mue_square() <<
", "
757 << vhierarchy_.node(parent_handle).sigma_square() <<
")"
759 std::cout <<
"- " << t.
as_string() << std::endl;
765 std::cout <<
"Analyzing step completed in "
773 get_leaf_node_handles(VHierarchyNodeHandle node_handle,
774 VHierarchyNodeHandleContainer &leaf_nodes)
776 if (vhierarchy_.node(node_handle).is_leaf())
778 leaf_nodes.push_back(node_handle);
782 get_leaf_node_handles(vhierarchy_.node(node_handle).lchild_handle(),
784 get_leaf_node_handles(vhierarchy_.node(node_handle).rchild_handle(),
793 compute_bounding_box(VHierarchyNodeHandle node_handle, VHierarchyNodeHandleContainer &leaf_nodes)
797 VHierarchyNodeHandleContainer::iterator n_it, n_end(leaf_nodes.end());
800 VertexHandle vh = vhierarchy_.node(node_handle).vertex_handle();
802 for ( n_it = leaf_nodes.begin(); n_it != n_end; ++n_it )
804 lp = mesh_.point(vhierarchy_.vertex_handle(*n_it));
805 max_distance = std::max(max_distance, (p - lp).length());
808 vhierarchy_.node(node_handle).set_radius(max_distance);
815 compute_cone_of_normals(VHierarchyNodeHandle node_handle,
816 VHierarchyNodeHandleContainer &leaf_nodes)
819 VertexHandle vh = vhierarchy_.node(node_handle).vertex_handle();
820 VHierarchyNodeHandleContainer::iterator n_it, n_end(leaf_nodes.end());
823 float max_angle = 0.0f;
825 n_it = leaf_nodes.begin();
826 while( n_it != n_end )
828 ln = vhierarchy_.node(*n_it).normal();
829 const float angle = acosf(
dot(n,ln) );
830 max_angle = std::max(max_angle, angle );
835 max_angle = std::min(max_angle,
float(M_PI_2));
836 mesh_.set_normal(vh, n);
837 vhierarchy_.node(node_handle).set_normal(n);
838 vhierarchy_.node(node_handle).set_semi_angle(max_angle);
845 compute_screen_space_error(VHierarchyNodeHandle node_handle, VHierarchyNodeHandleContainer &leaf_nodes)
847 std::vector<Vec3f> residuals;
849 Mesh::HalfedgeHandle heh;
854 #if (_MSC_VER >= 1900 )
856 Vec3f tri[3]{ {},{},{} };
861 VHierarchyNodeHandleContainer::iterator n_it, n_end(leaf_nodes.end());
863 for ( n_it = leaf_nodes.begin(); n_it != n_end; ++n_it )
865 lp = mesh_.point(vhierarchy_.node(*n_it).vertex_handle());
868 vh = vhierarchy_.node(node_handle).vertex_handle();
869 residual = lp - mesh_.point(vh);
870 float min_distance = residual.length();
872 for (vf_it=mesh_.vf_iter(vh); vf_it.is_valid(); ++vf_it)
874 heh = mesh_.halfedge_handle(*vf_it);
875 tri[0] = mesh_.point(mesh_.to_vertex_handle(heh));
876 heh = mesh_.next_halfedge_handle(heh);
877 tri[1] = mesh_.point(mesh_.to_vertex_handle(heh));
878 heh = mesh_.next_halfedge_handle(heh);
879 tri[2] = mesh_.point(mesh_.to_vertex_handle(heh));
881 res = point2triangle_residual(lp, tri, s, t);
883 if (res.length() < min_distance)
886 min_distance = res.length();
890 residuals.push_back(residual);
893 compute_mue_sigma(node_handle, residuals);
900 compute_mue_sigma(VHierarchyNodeHandle node_handle,
901 ResidualContainer &residuals)
904 float max_inner, max_cross;
905 ResidualContainer::iterator r_it, r_end(residuals.end());
907 max_inner = max_cross = 0.0f;
908 vn = mesh_.normal(vhierarchy_.node(node_handle).vertex_handle());
909 for (r_it = residuals.begin(); r_it != r_end; ++r_it)
911 float inner = fabsf(
dot(*r_it, vn));
914 max_inner = std::max(max_inner, inner);
915 max_cross = std::max(max_cross, cross);
918 if (max_cross < 1.0e-7)
920 vhierarchy_.node(node_handle).set_mue(max_cross);
921 vhierarchy_.node(node_handle).set_sigma(max_inner);
924 float ratio = std::max(1.0f, max_inner/max_cross);
925 float whole_degree = acosf(1.0f/ratio);
930 for (r_it = residuals.begin(); r_it != r_end; ++r_it)
933 float res_length = res.length();
936 float degree = acosf(
dot(vn,res) / res_length);
938 if (degree < 0.0f) degree = -degree;
939 if (degree >
float(M_PI_2)) degree = float(M_PI) - degree;
941 if (degree < whole_degree)
942 mue = cosf(whole_degree - degree) * res_length;
946 max_mue = std::max(max_mue, mue);
949 vhierarchy_.node(node_handle).set_mue(max_mue);
950 vhierarchy_.node(node_handle).set_sigma(ratio*max_mue);
958 point2triangle_residual(
const Vec3f &p,
const Vec3f tri[3],
float &s,
float &t)
964 float a =
dot(E0, E0);
965 float b =
dot(E0, E1);
966 float c =
dot(E1, E1);
967 float d =
dot(E0, D);
968 float e =
dot(E1, D);
970 float det = fabsf(a*c - b*b);
1038 else if ( t < 0.0f )
1060 float inv_det = 1.0f/det;
1068 float tmp0, tmp1, numer, denom;
1076 numer = tmp1 - tmp0;
1078 if ( numer >= denom )
1099 else if ( e >= 0.0f )
1111 else if ( t < 0.0f )
1117 numer = tmp1 - tmp0;
1119 if ( numer >= denom )
1140 else if ( d >= 0.0f )
1154 numer = c + e - b - d;
1155 if ( numer <= 0.0f )
1164 if ( numer >= denom )
1180 residual = p - (B + s*E0 + t*E1);
void stop(void)
Stop measurement.
Kernel::Point Point
Coordinate type.
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Normal calc_vertex_normal(VertexHandle _vh) const
Calculate vertex normal for one specific vertex.
static Type local()
Return endian type of host system.
std::string as_string(Format format=Automatic)
#define VertexTraits
Macro for defining the vertex traits. See Specifying your MyMesh.
Little endian (Intel family and clones)
Handle for a vertex entity.
#define FaceAttributes(_i)
Macro for defining the face attributes. See Specifying your MyMesh.
#define EdgeAttributes(_i)
Macro for defining the edge attributes. See Specifying your MyMesh.
void update_vertex_normals()
Update normal vectors for all vertices.
void update_face_normals()
Update normal vectors for all faces.
Add storage for previous halfedge (halfedges). The bit is set by default in the DefaultTraits.
void start(void)
Start measurement.
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
#define HalfedgeTraits
Macro for defining the halfedge traits. See Specifying your MyMesh.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Add normals to mesh item (vertices/faces)
HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1, VertexHandle _vl, VertexHandle _vr)
Vertex Split: inverse operation to collapse().
Add status to mesh item (all items)
Kernel::VertexFaceIter VertexFaceIter
Circulator.
T angle(T _cos_angle, T _sin_angle)
#define VertexAttributes(_i)
Macro for defining the vertex attributes. See Specifying your MyMesh.
std::vector< VHierarchyNodeHandle > VHierarchyNodeHandleContainer
Container for vertex hierarchy node handles.
#define HalfedgeAttributes(_i)
Macro for defining the halfedge attributes. See Specifying your MyMesh.