void practice_1(const Mesh& mesh) { // Print vertex information. std::cout << "** Vertex Information **" << std::endl; for (Mesh::ConstVertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) { const Mesh::VertexHandle vh(*v_it); const int vid = vh.idx(); std::cout << "vid: [" << vid << "]" << std::endl; // Check whether it is on boundary. std::cout << " - boundary: "; if (mesh.is_boundary(vh)) std::cout << "yes" << std::endl; else std::cout << "no" << std::endl; // Print vertex position and normal. const Vec3f p = mesh.point(vh); std::cout << " - position: (" << p[0] << ", " << p[1] << ", " << p[2] << ")" << std::endl; const Vec3f n = mesh.normal(vh); std::cout << " - normal: (" << n[0] << ", " << n[1] << ", " << n[2] << ")" << std::endl; // Print neighbor vertex indices. std::cout << " - neighbors vertices: "; for (Mesh::ConstVertexVertexIter vv_it = mesh.cvv_begin(vh); vv_it != mesh.cvv_end(vh); ++vv_it) { const Mesh::VertexHandle n_vh(*vv_it); const int n_vid = n_vh.idx(); std::cout << n_vid << " "; } std::cout << std::endl; // NOTE: // This is the same loop with the above. for (Mesh::ConstVertexVertexIter vv_it = mesh.cvv_iter(vh); vv_it.is_valid(); ++vv_it) { const Mesh::VertexHandle n_vh(*vv_it); // Do something. } // Print neighbor face indices. std::cout << " - neighbors faces: "; for (Mesh::ConstVertexFaceIter vf_it = mesh.cvf_begin(vh); vf_it != mesh.cvf_end(vh); ++vf_it) { const Mesh::FaceHandle n_fh(*vf_it); const int n_fid = n_fh.idx(); std::cout << n_fid << " "; } std::cout << std::endl; } std::cout << std::endl; }
void practice_3(const Mesh& mesh) { // Print face information. std::cout << "** Face Information **" << std::endl; for (Mesh::ConstFaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) { const Mesh::FaceHandle fh(*f_it); const int fid = fh.idx(); std::cout << "fid: [" << fid << "]" << std::endl; // Print face centroid. const Vec3f c = mesh.calc_face_centroid(fh); std::cout << " - centroid: (" << c[0] << ", " << c[1] << ", " << c[2] << ")" << std::endl; // Print face area. // You can make your own method for computing face area. // Here 'calc_sector_area()' function is used with an incident halfedge. const Mesh::EdgeHandle eh(*mesh.cfe_begin(fh)); // Two halfedges. const Mesh::HalfedgeHandle heh_0 = mesh.halfedge_handle(eh, 0); const Mesh::HalfedgeHandle heh_1 = mesh.halfedge_handle(eh, 1); float area = 0; if (mesh.face_handle(heh_0) == fh) area = mesh.calc_sector_area(heh_0); else if (mesh.face_handle(heh_1) == fh) area = mesh.calc_sector_area(heh_1); else assert(false); std::cout << " - area: " << area << std::endl; // Print neighbor vertex indices. std::cout << " - neighbors vertices: "; for (Mesh::ConstFaceVertexIter fv_it = mesh.cfv_begin(fh); fv_it != mesh.cfv_end(fh); ++fv_it) { const Mesh::VertexHandle n_vh(*fv_it); const int n_vid = n_vh.idx(); std::cout << n_vid << " "; } std::cout << std::endl; } std::cout << std::endl; }
void practice_2(const Mesh& mesh) { // Print connectivity information. std::cout << "** Connectivity Information **" << std::endl; // For each vertex, print its connected edge information. for (Mesh::ConstVertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) { const Mesh::VertexHandle vh(*v_it); const int vid = vh.idx(); std::cout << "vid: [" << vid << "]" << std::endl; // Print connected edge information. std::cout << " - connected edges: " << std::endl; for (Mesh::ConstVertexOHalfedgeIter vohe_it = mesh.cvoh_begin(vh); vohe_it != mesh.cvoh_end(vh); ++vohe_it) { const Mesh::HalfedgeHandle ohe(*vohe_it); // Get from and to vertices. const Mesh::VertexHandle from_vh = mesh.from_vertex_handle(ohe); const Mesh::VertexHandle to_vh = mesh.to_vertex_handle(ohe); assert(from_vh == vh); // Get the opposite halfedge. const Mesh::HalfedgeHandle ihe = mesh.opposite_halfedge_handle(ohe); // Get incident faces. const Mesh::FaceHandle n_fh_0 = mesh.face_handle(ohe); const Mesh::FaceHandle n_fh_1 = mesh.face_handle(ihe); // Compute edge length. const float length = mesh.calc_edge_length(ohe); std::cout << " to_vid = " << to_vh.idx() << ", n_fid = (" << n_fh_0.idx() << ", " << n_fh_1.idx() << "), length = " << length << std::endl; } } std::cout << std::endl; }
bool operator()(Mesh::VertexHandle _v0, Mesh::VertexHandle _v1) const { Mesh &mesh = *meshPtr; // std::set needs UNIQUE keys -> handle equal priorities return ((priority(mesh,_v0) == priority(mesh,_v1)) ? (_v0.idx() < _v1.idx()) : (priority(mesh,_v0) < priority(mesh,_v1))); }
int main(int argc, char **argv) { // Define the mesh type. Here we use OpenMesh defaults. typedef OpenMesh::TriMesh_ArrayKernelT<> Mesh; // Load the triangulated sphere. std::string pathToSource = std::string(DEFORM_ETC_DIR) + std::string("/sphere.obj"); Mesh mesh; if (!OpenMesh::IO::read_mesh(mesh, pathToSource)) { std::cerr << "Failed to read mesh" << std::endl; return -1; } // Mesh-deform is independent of the types used to represent triangular surfaces. // We need to provide an adapter so that Mesh-deform is able to handle OpenMesh. // For OpenMesh a ready-to-use adapter is provided. typedef deform::OpenMeshAdapter<> Adapter; Adapter ma(mesh); // Instance the deformation algorithm. deform::AsRigidAsPossibleDeformation<Adapter> arap(ma); // Set anchors. Semantically anchors are vertices that are pinned to a specific location. // Here we just pin one vertex to its initial location. Mesh::VertexHandle va = mesh.vertex_handle(37); arap.setConstraint(va.idx(), deform::convert::toEigen(mesh.point(va))); // Motion related variables Mesh::Point p = mesh.point(mesh.vertex_handle(32)); double pi = -M_PI_2; double add = 0.01; // Create an OSG viewer to visualize incremental deformation. deform::example::OSGViewer viewer(mesh, {37}, {32}); viewer.onFrame([&p, &pi, &add, &arap](Mesh &mesh, double time) { // Update motion pi += add; if (std::abs(pi) > M_PI_2) { add *= -1.0; pi += add; } // Set handles. Semantically handles are vertices that are dragged around by some motion. Note, // although semantically they have a different meaning conceptually its the same as pinning a vertex // to a location. Mesh::VertexHandle vh = mesh.vertex_handle(32); arap.setConstraint(vh.idx(), deform::convert::toEigen(p + Mesh::Point(0, 0, (float)(std::sin(pi))))); // Run the algorithm for 5 iterations. Usually enough when the target constrain locations are not // far from the initial locations. Mesh is automatically updated when method completes. arap.deform(5); return true; }); viewer.run(); return 0; }