|
@@ -0,0 +1,133 @@
|
|
|
+#include <igl/colon.h>
|
|
|
+#include <igl/directed_edge_orientations.h>
|
|
|
+#include <igl/directed_edge_parents.h>
|
|
|
+#include <igl/forward_kinematics.h>
|
|
|
+#include <igl/PI.h>
|
|
|
+#include <igl/lbs_matrix.h>
|
|
|
+#include <igl/deform_skeleton.h>
|
|
|
+#include <igl/dqs.h>
|
|
|
+#include <igl/readDMAT.h>
|
|
|
+#include <igl/readOFF.h>
|
|
|
+#include <igl/svd3x3/arap.h>
|
|
|
+#include <igl/viewer/Viewer.h>
|
|
|
+
|
|
|
+#include <Eigen/Geometry>
|
|
|
+#include <Eigen/StdVector>
|
|
|
+#include <vector>
|
|
|
+#include <algorithm>
|
|
|
+#include <iostream>
|
|
|
+
|
|
|
+typedef
|
|
|
+ std::vector<Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> >
|
|
|
+ RotationList;
|
|
|
+
|
|
|
+const Eigen::RowVector3d sea_green(70./255.,252./255.,167./255.);
|
|
|
+Eigen::MatrixXd V,U;
|
|
|
+Eigen::MatrixXi F;
|
|
|
+Eigen::VectorXi S,b;
|
|
|
+Eigen::RowVector3d mid;
|
|
|
+double anim_t = 0.0;
|
|
|
+double anim_t_dir = 0.03;
|
|
|
+igl::ARAPData arap_data;
|
|
|
+
|
|
|
+bool pre_draw(igl::Viewer & viewer)
|
|
|
+{
|
|
|
+ using namespace Eigen;
|
|
|
+ using namespace std;
|
|
|
+ MatrixXd bc(b.size(),V.cols());
|
|
|
+ for(int i = 0;i<b.size();i++)
|
|
|
+ {
|
|
|
+ bc.row(i) = V.row(b(i));
|
|
|
+ switch(S(b(i)))
|
|
|
+ {
|
|
|
+ case 0:
|
|
|
+ {
|
|
|
+ const double r = mid(0)*0.25;
|
|
|
+ bc(i,0) += r*sin(0.5*anim_t*2.*igl::PI);
|
|
|
+ bc(i,1) -= r+r*cos(igl::PI+0.5*anim_t*2.*igl::PI);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 1:
|
|
|
+ {
|
|
|
+ const double r = mid(1)*0.15;
|
|
|
+ bc(i,1) += r+r*cos(igl::PI+0.15*anim_t*2.*igl::PI);
|
|
|
+ bc(i,2) -= r*sin(0.15*anim_t*2.*igl::PI);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 2:
|
|
|
+ {
|
|
|
+ const double r = mid(1)*0.15;
|
|
|
+ bc(i,2) += r+r*cos(igl::PI+0.35*anim_t*2.*igl::PI);
|
|
|
+ bc(i,0) += r*sin(0.35*anim_t*2.*igl::PI);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ igl::arap_solve(bc,arap_data,U);
|
|
|
+ viewer.set_vertices(U);
|
|
|
+ viewer.compute_normals();
|
|
|
+ if(viewer.core.is_animating)
|
|
|
+ {
|
|
|
+ anim_t += anim_t_dir;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool key_down(igl::Viewer &viewer, unsigned char key, int mods)
|
|
|
+{
|
|
|
+ switch(key)
|
|
|
+ {
|
|
|
+ case ' ':
|
|
|
+ viewer.core.is_animating = !viewer.core.is_animating;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char *argv[])
|
|
|
+{
|
|
|
+ using namespace Eigen;
|
|
|
+ using namespace std;
|
|
|
+ igl::readOFF("../shared/decimated-knight.off",V,F);
|
|
|
+ U=V;
|
|
|
+ igl::readDMAT("../shared/decimated-knight-selection.dmat",S);
|
|
|
+
|
|
|
+ // vertices in selection
|
|
|
+ igl::colon<int>(0,V.rows()-1,b);
|
|
|
+ b.conservativeResize(stable_partition( b.data(), b.data()+b.size(),
|
|
|
+ [](int i)->bool{return S(i)>=0;})-b.data());
|
|
|
+ // Centroid
|
|
|
+ mid = 0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff());
|
|
|
+ // Precomputation
|
|
|
+ arap_data.max_iter = 100;
|
|
|
+ igl::arap_precomputation(V,F,V.cols(),b,arap_data);
|
|
|
+
|
|
|
+ // Set color based on selection
|
|
|
+ MatrixXd C(F.rows(),3);
|
|
|
+ RowVector3d purple(80.0/255.0,64.0/255.0,255.0/255.0);
|
|
|
+ RowVector3d gold(255.0/255.0,228.0/255.0,58.0/255.0);
|
|
|
+ for(int f = 0;f<F.rows();f++)
|
|
|
+ {
|
|
|
+ if( S(F(f,0))>=0 && S(F(f,1))>=0 && S(F(f,2))>=0)
|
|
|
+ {
|
|
|
+ C.row(f) = purple;
|
|
|
+ }else
|
|
|
+ {
|
|
|
+ C.row(f) = gold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Plot the mesh with pseudocolors
|
|
|
+ igl::Viewer viewer;
|
|
|
+ viewer.set_mesh(U, F);
|
|
|
+ viewer.set_colors(C);
|
|
|
+ viewer.callback_pre_draw = &pre_draw;
|
|
|
+ viewer.callback_key_down = &key_down;
|
|
|
+ viewer.core.is_animating = false;
|
|
|
+ viewer.core.animation_max_fps = 30.;
|
|
|
+ cout<<
|
|
|
+ "Press [space] to toggle animation"<<endl;
|
|
|
+ viewer.launch();
|
|
|
+}
|