bool pre_draw(igl::opengl::glfw::Viewer & viewer) { using namespace Eigen; // Determine boundary conditions if(viewer.core().is_animating) { bc_frac += bc_dir; bc_dir *= (bc_frac>=1.0 || bc_frac<=0.0?-1.0:1.0); } const MatrixXd U_bc_anim = V_bc+bc_frac*(U_bc-V_bc); if(deformation_field) { MatrixXd D; MatrixXd D_bc = U_bc_anim - V_bc; igl::harmonic(V,F,b,D_bc,2,D); U = V+D; }else { igl::harmonic(V,F,b,U_bc_anim,2.,U); } viewer.data().set_vertices(U); viewer.data().compute_normals(); return false; }
void update_visualization(igl::opengl::glfw::Viewer & viewer) { using namespace Eigen; using namespace std; Eigen::Vector4d plane( 0,0,1,-((1-slice_z)*V.col(2).minCoeff()+slice_z*V.col(2).maxCoeff())); MatrixXd V_vis; MatrixXi F_vis; VectorXi J; { SparseMatrix<double> bary; // Value of plane's implicit function at all vertices const VectorXd IV = (V.col(0)*plane(0) + V.col(1)*plane(1) + V.col(2)*plane(2)).array() + plane(3); igl::marching_tets(V,T,IV,V_vis,F_vis,J,bary); } VectorXd W_vis; igl::slice(W,J,W_vis); MatrixXd C_vis; // color without normalizing igl::parula(W_vis,false,C_vis); const auto & append_mesh = [&C_vis,&F_vis,&V_vis]( const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, const RowVector3d & color) { F_vis.conservativeResize(F_vis.rows()+F.rows(),3); F_vis.bottomRows(F.rows()) = F.array()+V_vis.rows(); V_vis.conservativeResize(V_vis.rows()+V.rows(),3); V_vis.bottomRows(V.rows()) = V; C_vis.conservativeResize(C_vis.rows()+F.rows(),3); C_vis.bottomRows(F.rows()).rowwise() = color; }; switch(overlay) { case OVERLAY_INPUT: append_mesh(V,F,RowVector3d(1.,0.894,0.227)); break; case OVERLAY_OUTPUT: append_mesh(V,G,RowVector3d(0.8,0.8,0.8)); break; default: break; } viewer.data().clear(); viewer.data().set_mesh(V_vis,F_vis); viewer.data().set_colors(C_vis); viewer.data().set_face_based(true); }
bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods) { switch(key) { case ' ': viewer.core().is_animating = !viewer.core().is_animating; return true; case 'D': case 'd': deformation_field = !deformation_field; return true; } return false; }
// This function is called every time a keyboard button is pressed bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier) { switch(key) { case '1': viewer.data().set_normals(N_faces); return true; case '2': viewer.data().set_normals(N_vertices); return true; case '3': viewer.data().set_normals(N_corners); return true; default: break; } return false; }
bool pre_draw(igl::opengl::glfw::Viewer & viewer) { using namespace Eigen; using namespace std; if(viewer.core.is_animating) { // Interpolate pose and identity RotationList anim_pose(pose.size()); for(int e = 0;e<pose.size();e++) { anim_pose[e] = pose[e].slerp(anim_t,Quaterniond::Identity()); } // Propagate relative rotations via FK to retrieve absolute transformations RotationList vQ; vector<Vector3d> vT; igl::forward_kinematics(C,BE,P,anim_pose,vQ,vT); const int dim = C.cols(); MatrixXd T(BE.rows()*(dim+1),dim); for(int e = 0;e<BE.rows();e++) { Affine3d a = Affine3d::Identity(); a.translate(vT[e]); a.rotate(vQ[e]); T.block(e*(dim+1),0,dim+1,dim) = a.matrix().transpose().block(0,0,dim+1,dim); } // Compute deformation via LBS as matrix multiplication U = M*T; // Also deform skeleton edges MatrixXd CT; MatrixXi BET; igl::deform_skeleton(C,BE,T,CT,BET); viewer.data().set_vertices(U); viewer.data().set_edges(CT,BET,sea_green); viewer.data().compute_normals(); anim_t += anim_t_dir; anim_t_dir *= (anim_t>=1.0 || anim_t<=0.0?-1.0:1.0); } return false; }
void solve(igl::opengl::glfw::Viewer &viewer) { using namespace std; igl::active_set_params as; as.max_iter = 8; igl::active_set(Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,as,Z); // Pseudo-color based on solution Eigen::MatrixXd C; igl::jet(Z,0,1,C); viewer.data().set_colors(C); }
void drawField(igl::opengl::glfw::Viewer &viewer, const Eigen::MatrixXd &field, const Eigen::RowVector3d &color) { for (int n=0; n<2; ++n) { Eigen::MatrixXd VF = field.block(0,n*3,F.rows(),3); Eigen::VectorXd c = VF.rowwise().norm(); viewer.data().add_edges(B - global_scale*VF, B + global_scale*VF , color); } }
bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier) { if (key == '1') show_uv = false; else if (key == '2') show_uv = true; if (key == ' ') { timer.start(); igl::scaf_solve(scaf_data, 1); std::cout << "time = " << timer.getElapsedTime() << std::endl; } const auto& V_uv = uv_scale * scaf_data.w_uv.topRows(V.rows()); if (show_uv) { viewer.data().clear(); viewer.data().set_mesh(V_uv,F); viewer.data().set_uv(V_uv); viewer.core.align_camera_center(V_uv,F); } else { viewer.data().set_mesh(V,F); viewer.data().set_uv(V_uv); viewer.core.align_camera_center(V,F); } viewer.data().compute_normals(); return false; }
void drawConstraints(igl::opengl::glfw::Viewer &viewer) { for (int n=0; n<2; ++n) { Eigen::MatrixXd Bc = igl::slice(B, b, 1); Eigen::MatrixXd color; color.setZero(b.rows(),3); color.col(2).setOnes(); for (int i =0; i<b.rows(); ++i) if (blevel[i] ==1 && n>0) color.row(i)<<0.7,0.7,0.7; // Eigen::RowVector3d color; color<<0.5,0.5,0.5; viewer.data().add_edges(Bc - global_scale*bc.block(0,n*3,bc.rows(),3), Bc + global_scale*bc.block(0,n*3,bc.rows(),3) , color); } }
void drawCuts(igl::opengl::glfw::Viewer& viewer, const Eigen::MatrixXi &cuts) { int maxCutNum = cuts.sum(); Eigen::MatrixXd start(maxCutNum,3); Eigen::MatrixXd end(maxCutNum,3); int ind = 0; for (unsigned int i=0;i<F.rows();i++) for (int j=0;j<3;j++) if (cuts(i,j)) { start.row(ind) = V.row(F(i,j)); end.row(ind) = V.row(F(i,(j+1)%3)); ind++; } viewer.data().add_edges(start, end , Eigen::RowVector3d(1.,0,1.)); }
void update_display(igl::opengl::glfw::Viewer& viewer) { using namespace std; using namespace Eigen; viewer.data().clear(); viewer.data().lines.resize(0,9); viewer.data().points.resize(0,6); viewer.data().show_texture = false; if (display_mode == 1) { cerr<< "Displaying original field, its singularities and its cuts" <<endl; viewer.data().set_mesh(V, F); // Highlight in red the constrained faces MatrixXd C = MatrixXd::Constant(F.rows(),3,1); for (unsigned i=0; i<b.size();++i) C.row(b(i)) << 1, 0, 0; viewer.data().set_colors(C); //Draw constraints drawConstraints(viewer); // Draw Field Eigen::RowVector3d color; color<<0,0,1; drawField(viewer,two_pv_ori,color); // Draw Cuts drawCuts(viewer,cuts_ori); //Draw Singularities Eigen::MatrixXd singular_points = igl::slice(V, singularities_ori, 1); viewer.data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.)); } if (display_mode == 2) { cerr<< "Displaying current field, its singularities and its cuts" <<endl; viewer.data().set_mesh(V, F); // Highlight in red the constrained faces MatrixXd C = MatrixXd::Constant(F.rows(),3,1); for (unsigned i=0; i<b.size();++i) C.row(b(i)) << 1, 0, 0; viewer.data().set_colors(C); //Draw constraints drawConstraints(viewer); // Draw Field Eigen::RowVector3d color; color<<0,0,1; drawField(viewer,two_pv,color); // Draw Cuts drawCuts(viewer,cuts); //Draw Singularities Eigen::MatrixXd singular_points = igl::slice(V, singularities, 1); viewer.data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.)); } if (display_mode == 3) { cerr<< "Displaying original field and its curl" <<endl; viewer.data().set_mesh(Vbs, Fbs); Eigen::MatrixXd C; colorEdgeMeshFaces(curl_ori, 0, 0.2, C); viewer.data().set_colors(C); // Draw Field Eigen::RowVector3d color; color<<1,1,1; drawField(viewer,two_pv_ori,color); } if (display_mode == 4) { cerr<< "Displaying current field and its curl" <<endl; viewer.data().set_mesh(Vbs, Fbs); Eigen::MatrixXd C; colorEdgeMeshFaces(curl, 0, 0.2, C); viewer.data().set_colors(C); // Draw Field Eigen::RowVector3d color; color<<1,1,1; drawField(viewer,two_pv,color); } if (display_mode == 5) { cerr<< "Displaying original poisson-integrated field and original poisson error" <<endl; viewer.data().set_mesh(V, F); Eigen::MatrixXd C; igl::jet(poisson_error_ori, 0, 0.5, C); viewer.data().set_colors(C); // Draw Field Eigen::RowVector3d color; color<<1,1,1; drawField(viewer,two_pv_poisson_ori,color); } if (display_mode == 6) { cerr<< "Displaying current poisson-integrated field and current poisson error" <<endl; viewer.data().set_mesh(V, F); Eigen::MatrixXd C; igl::jet(poisson_error, 0, 0.5, C); viewer.data().set_colors(C); // Draw Field Eigen::RowVector3d color; color<<1,1,1; drawField(viewer,two_pv_poisson,color); } if (display_mode == 7) { cerr<< "Displaying original texture with cuts and singularities" <<endl; viewer.data().set_mesh(V, F); MatrixXd C = MatrixXd::Constant(F.rows(),3,1); viewer.data().set_colors(C); viewer.data().set_uv(uv_scale*scalars_ori, Fcut_ori); viewer.data().set_texture(texture_R, texture_B, texture_G); viewer.data().show_texture = true; // Draw Cuts drawCuts(viewer,cuts_ori); //Draw Singularities Eigen::MatrixXd singular_points = igl::slice(V, singularities_ori, 1); viewer.data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.)); } if (display_mode == 8) { cerr<< "Displaying current texture with cuts and singularities" <<endl; viewer.data().set_mesh(V, F); MatrixXd C = MatrixXd::Constant(F.rows(),3,1); viewer.data().set_colors(C); viewer.data().set_uv(uv_scale*scalars, Fcut); viewer.data().set_texture(texture_R, texture_B, texture_G); viewer.data().show_texture = true; // Draw Cuts drawCuts(viewer,cuts); //Draw Singularities Eigen::MatrixXd singular_points = igl::slice(V, singularities, 1); viewer.data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.)); } if (display_mode == 9) { cerr<< "Displaying original field overlaid onto the current integrated field" <<endl; viewer.data().set_mesh(V, F); // Highlight in red the constrained faces MatrixXd C = MatrixXd::Constant(F.rows(),3,1); for (unsigned i=0; i<b.size();++i) C.row(b(i)) << 1, 0, 0; viewer.data().set_colors(C); // Draw Field Eigen::RowVector3d color; color<<0,0,1; drawField(viewer,two_pv_ori,color); // Draw Integrated Field color<<.2,.2,.2; drawField(viewer,two_pv_poisson_ori,color); } if (display_mode == 0) { cerr<< "Displaying current field overlaid onto the current integrated field" <<endl; viewer.data().set_mesh(V, F); // Highlight in red the constrained faces MatrixXd C = MatrixXd::Constant(F.rows(),3,1); for (unsigned i=0; i<b.size();++i) C.row(b(i)) << 1, 0, 0; viewer.data().set_colors(C); // Draw Field Eigen::RowVector3d color; color<<0,0,1; drawField(viewer,two_pv,color); // Draw Integrated Field color<<.2,.2,.2; drawField(viewer,two_pv_poisson,color); } }
void set_color(igl::opengl::glfw::Viewer &viewer) { Eigen::MatrixXd C; igl::jet(W.col(selected).eval(),true,C); viewer.data().set_colors(C); }
void update_visualization(igl::opengl::glfw::Viewer & viewer) { using namespace Eigen; using namespace std; Eigen::Vector4d plane( 0,0,1,-((1-slice_z)*V.col(2).minCoeff()+slice_z*V.col(2).maxCoeff())); MatrixXd V_vis; MatrixXi F_vis; // Extract triangle mesh slice through volume mesh and subdivide nasty // triangles { VectorXi J; SparseMatrix<double> bary; { // Value of plane's implicit function at all vertices const VectorXd IV = (V.col(0)*plane(0) + V.col(1)*plane(1) + V.col(2)*plane(2)).array() + plane(3); igl::slice_tets(V,T,IV,V_vis,F_vis,J,bary); igl::writeOBJ("vis.obj",V_vis,F_vis); } while(true) { MatrixXd l; igl::edge_lengths(V_vis,F_vis,l); l /= (V_vis.colwise().maxCoeff() - V_vis.colwise().minCoeff()).norm(); const double max_l = 0.03; if(l.maxCoeff()<max_l) { break; } Array<bool,Dynamic,1> bad = l.array().rowwise().maxCoeff() > max_l; MatrixXi F_vis_bad, F_vis_good; igl::slice_mask(F_vis,bad,1,F_vis_bad); igl::slice_mask(F_vis,(bad!=true).eval(),1,F_vis_good); igl::upsample(V_vis,F_vis_bad); F_vis = igl::cat(1,F_vis_bad,F_vis_good); } } // Compute signed distance VectorXd S_vis; { VectorXi I; MatrixXd N,C; // Bunny is a watertight mesh so use pseudonormal for signing signed_distance_pseudonormal(V_vis,V,F,tree,FN,VN,EN,EMAP,S_vis,I,C,N); } // push to [0,1] range S_vis.array() = 0.5*(S_vis.array()/max_distance)+0.5; MatrixXd C_vis; // color without normalizing igl::parula(S_vis,false,C_vis); const auto & append_mesh = [&C_vis,&F_vis,&V_vis]( const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, const RowVector3d & color) { F_vis.conservativeResize(F_vis.rows()+F.rows(),3); F_vis.bottomRows(F.rows()) = F.array()+V_vis.rows(); V_vis.conservativeResize(V_vis.rows()+V.rows(),3); V_vis.bottomRows(V.rows()) = V; C_vis.conservativeResize(C_vis.rows()+V.rows(),3); C_vis.bottomRows(V.rows()).rowwise() = color; }; if(overlay) { append_mesh(V,F,RowVector3d(0.8,0.8,0.8)); } viewer.data().clear(); viewer.data().set_mesh(V_vis,F_vis); viewer.data().set_colors(C_vis); viewer.core.lighting_factor = overlay; }