diff --git a/.gitignore b/.gitignore index 43aafc335..3999aa681 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ external/tinyxml2/tinyxml2.pc external/yimg/showpng README.html tutorial/readme.html +tutorial/tutorial.html tutorial/*/build/* tutorial/*/Makefile external/glew/build diff --git a/build/Makefile b/build/Makefile index 766ee2625..0cfbfe149 100644 --- a/build/Makefile +++ b/build/Makefile @@ -125,7 +125,7 @@ obj/%.o: ../include/igl/%.cpp ../include/igl/%.h clean: rm -rf ../lib/igl.framework/ - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libigl.a make -C ../examples clean for p in $(EXTRA_DIRS); \ diff --git a/build/Makefile_bbw b/build/Makefile_bbw index 5f42c390c..fded5daa3 100644 --- a/build/Makefile_bbw +++ b/build/Makefile_bbw @@ -54,5 +54,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglbbw.a diff --git a/build/Makefile_boost b/build/Makefile_boost index d0ca613a9..ffd3298f7 100644 --- a/build/Makefile_boost +++ b/build/Makefile_boost @@ -40,5 +40,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglboost.a diff --git a/build/Makefile_cgal b/build/Makefile_cgal index 88b4ad7a2..6f7f6ad14 100644 --- a/build/Makefile_cgal +++ b/build/Makefile_cgal @@ -41,5 +41,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglcgal.a diff --git a/build/Makefile_embree b/build/Makefile_embree index 2250735ba..1b49d0023 100644 --- a/build/Makefile_embree +++ b/build/Makefile_embree @@ -43,5 +43,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglembree.a diff --git a/build/Makefile_matlab b/build/Makefile_matlab index 5a55bb40c..7bcdbc486 100644 --- a/build/Makefile_matlab +++ b/build/Makefile_matlab @@ -42,5 +42,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglmatlab.a diff --git a/build/Makefile_mosek b/build/Makefile_mosek index 71e890481..85d3879c6 100644 --- a/build/Makefile_mosek +++ b/build/Makefile_mosek @@ -49,5 +49,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglmosek.a diff --git a/build/Makefile_png b/build/Makefile_png index 8e6f2b54a..d8345f537 100644 --- a/build/Makefile_png +++ b/build/Makefile_png @@ -38,5 +38,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglpng.a diff --git a/build/Makefile_svd3x3 b/build/Makefile_svd3x3 index 4a49e8288..746e46b80 100644 --- a/build/Makefile_svd3x3 +++ b/build/Makefile_svd3x3 @@ -48,5 +48,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglsvd3x3.a diff --git a/build/Makefile_tetgen b/build/Makefile_tetgen index f795f47d6..ebffe48c0 100644 --- a/build/Makefile_tetgen +++ b/build/Makefile_tetgen @@ -40,5 +40,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libigltetgen.a diff --git a/build/Makefile_triangle b/build/Makefile_triangle index 19085bc7c..e8a4d380f 100644 --- a/build/Makefile_triangle +++ b/build/Makefile_triangle @@ -40,5 +40,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libigltriangle.a diff --git a/build/Makefile_viewer b/build/Makefile_viewer index c25639f45..213372e33 100644 --- a/build/Makefile_viewer +++ b/build/Makefile_viewer @@ -46,5 +46,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglmatlab.a diff --git a/build/Makefile_xml b/build/Makefile_xml index d67f559e8..81387fdeb 100644 --- a/build/Makefile_xml +++ b/build/Makefile_xml @@ -53,5 +53,5 @@ obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC) clean: - rm -f obj/*.o + rm -f $(OBJ_FILES) rm -f ../lib/libiglxml.a diff --git a/include/igl/arap_rhs.cpp b/include/igl/arap_rhs.cpp index a9e16197c..838010e7b 100644 --- a/include/igl/arap_rhs.cpp +++ b/include/igl/arap_rhs.cpp @@ -10,6 +10,7 @@ #include "verbose.h" #include "repdiag.h" #include "cat.h" +#include IGL_INLINE void igl::arap_rhs( const Eigen::MatrixXd & V, @@ -19,6 +20,7 @@ IGL_INLINE void igl::arap_rhs( Eigen::SparseMatrix& K) { using namespace igl; + using namespace std; using namespace Eigen; // Number of dimensions int Vdim = V.cols(); diff --git a/include/igl/repdiag.cpp b/include/igl/repdiag.cpp index 033fb65cc..77629ffba 100644 --- a/include/igl/repdiag.cpp +++ b/include/igl/repdiag.cpp @@ -6,11 +6,7 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "repdiag.h" -#ifndef IGL_NO_OPENGL - -// Bug in unsupported/Eigen/SparseExtra needs iostream first -#include -#include +#include template IGL_INLINE void igl::repdiag( @@ -18,27 +14,52 @@ IGL_INLINE void igl::repdiag( const int d, Eigen::SparseMatrix& B) { + using namespace std; + using namespace Eigen; int m = A.rows(); int n = A.cols(); - B.resize(m*d,n*d); - // Reserve enough space for new non zeros - B.reserve(d*A.nonZeros()); - - // loop over reps - for(int i=0;i > IJV; + IJV.reserve(A.nonZeros()*d); + // Loop outer level + for (int k=0; k::InnerIterator it(A,k); it; ++it) { - // loop inner level - for (typename Eigen::SparseMatrix::InnerIterator it(A,k); it; ++it) + for(int i = 0;i(i*m+it.row(),i*n+it.col(),it.value())); } } } - B.makeCompressed(); + B.resize(m*d,n*d); + B.setFromTriplets(IJV.begin(),IJV.end()); + + + // Q: Why is this **Very** slow? + + //int m = A.rows(); + //int n = A.cols(); + + //B.resize(m*d,n*d); + //// Reserve enough space for new non zeros + //B.reserve(d*A.nonZeros()); + + //// loop over reps + //for(int i=0;i::InnerIterator it(A,k); it; ++it) + // { + // B.insert(i*m+it.row(),i*n+it.col()) = it.value(); + // } + // } + //} + //B.makeCompressed(); } template @@ -73,4 +94,3 @@ template void igl::repdiag(Eigen::SparseMatrix const&, i // generated by autoexplicit.sh template Eigen::SparseMatrix igl::repdiag >(Eigen::SparseMatrix const&, int); #endif -#endif diff --git a/include/igl/svd3x3/arap.cpp b/include/igl/svd3x3/arap.cpp index e65d34a07..29cf661f0 100644 --- a/include/igl/svd3x3/arap.cpp +++ b/include/igl/svd3x3/arap.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "fit_rotations.h" #include #include @@ -95,13 +96,11 @@ IGL_INLINE bool igl::arap_precomputation( // Get covariance scatter matrix, when applied collects the covariance // matrices used to fit rotations to during optimization covariance_scatter_matrix(ref_V,ref_F,eff_energy,data.CSM); - assert(data.CSM.rows() == ref_F.rows()*data.dim); if(flat) { data.CSM = (data.CSM * ref_map_dim.transpose()).eval(); } assert(data.CSM.cols() == V.rows()*data.dim); - assert(data.CSM.rows() == ref_F.rows()*data.dim); // Get group sum scatter matrix, when applied sums all entries of the same // group according to G @@ -216,6 +215,9 @@ IGL_INLINE bool igl::arap_solve( assert(U.cols() == data.dim); // As if U.col(2) was 0 MatrixXd S = data.CSM * Udim; + // THIS NORMALIZATION IS IMPORTANT TO GET SINGLE PRECISION SVD CODE TO WORK + // CORRECTLY. + S /= S.array().abs().maxCoeff(); const int Rdim = data.dim; MatrixXd R(Rdim,data.CSM.rows()); @@ -224,11 +226,12 @@ IGL_INLINE bool igl::arap_solve( fit_rotations_planar(S,R); }else { -#ifdef __SSE__ // fit_rotations_SSE will convert to float if necessary - fit_rotations_SSE(S,R); -#else - fit_rotations(S,true,R); -#endif + fit_rotations(S,true,R); +//#ifdef __SSE__ // fit_rotations_SSE will convert to float if necessary +// fit_rotations_SSE(S,R); +//#else +// fit_rotations(S,true,R); +//#endif } //for(int k = 0;k<(data.CSM.rows()/dim);k++) //{ @@ -299,6 +302,7 @@ IGL_INLINE bool igl::arap_solve( // Keep track of velocity for next time data.vel = (U-U0)/data.h; } + return true; } diff --git a/include/igl/viewer/Viewer.cpp b/include/igl/viewer/Viewer.cpp index a530ae8eb..a0959297b 100644 --- a/include/igl/viewer/Viewer.cpp +++ b/include/igl/viewer/Viewer.cpp @@ -940,6 +940,13 @@ namespace igl data.set_texture(R,G,B); } + void Viewer::set_points( + const Eigen::MatrixXd& P, + const Eigen::MatrixXd& C) + { + data.set_points(P,C); + } + void Viewer::add_points(const Eigen::MatrixXd& P, const Eigen::MatrixXd& C) { data.add_points(P,C); diff --git a/include/igl/viewer/Viewer.h b/include/igl/viewer/Viewer.h index 92112abc8..518718e63 100644 --- a/include/igl/viewer/Viewer.h +++ b/include/igl/viewer/Viewer.h @@ -93,8 +93,28 @@ namespace igl const Eigen::Matrix& G, const Eigen::Matrix& B); + // Sets points given a list of point vertices. In constrast to `set_points` + // this will (purposefully) clober existing points. + // + // Inputs: + // P #P by 3 list of vertex positions + // C #P|1 by 3 color(s) + void set_points( + const Eigen::MatrixXd& P, + const Eigen::MatrixXd& C); void add_points(const Eigen::MatrixXd& P, const Eigen::MatrixXd& C); - void set_edges (const Eigen::MatrixXd& P, const Eigen::MatrixXi& E, const Eigen::MatrixXd& C); + // Sets edges given a list of edge vertices and edge indices. In + // constrast + // to `add_edges` this will (purposefully) clober existing edges. + // + // Inputs: + // P #P by 3 list of vertex positions + // E #E by 2 list of edge indices into P + // C #E|1 by 3 color(s) + void set_edges( + const Eigen::MatrixXd& P, + const Eigen::MatrixXi& E, + const Eigen::MatrixXd& C); void add_edges (const Eigen::MatrixXd& P1, const Eigen::MatrixXd& P2, const Eigen::MatrixXd& C); void add_label (const Eigen::VectorXd& P, const std::string& str); diff --git a/include/igl/viewer/ViewerData.cpp b/include/igl/viewer/ViewerData.cpp index e2d93ddfd..eff372afa 100644 --- a/include/igl/viewer/ViewerData.cpp +++ b/include/igl/viewer/ViewerData.cpp @@ -213,6 +213,15 @@ IGL_INLINE void igl::ViewerData::set_texture( dirty |= DIRTY_TEXTURE; } +IGL_INLINE void igl::ViewerData::set_points( + const Eigen::MatrixXd& P, + const Eigen::MatrixXd& C) +{ + // clear existing points + points.resize(0,0); + add_points(P,C); +} + IGL_INLINE void igl::ViewerData::add_points(const Eigen::MatrixXd& P, const Eigen::MatrixXd& C) { Eigen::MatrixXd P_temp; diff --git a/include/igl/viewer/ViewerData.h b/include/igl/viewer/ViewerData.h index a6412057c..b4ec86f18 100644 --- a/include/igl/viewer/ViewerData.h +++ b/include/igl/viewer/ViewerData.h @@ -66,6 +66,15 @@ public: const Eigen::Matrix& G, const Eigen::Matrix& B); + // Sets points given a list of point vertices. In constrast to `set_points` + // this will (purposefully) clober existing points. + // + // Inputs: + // P #P by 3 list of vertex positions + // C #P|1 by 3 color(s) + IGL_INLINE void set_points( + const Eigen::MatrixXd& P, + const Eigen::MatrixXd& C); IGL_INLINE void add_points(const Eigen::MatrixXd& P, const Eigen::MatrixXd& C); // Sets edges given a list of edge vertices and edge indices. In constrast // to `add_edges` this will (purposefully) clober existing edges. diff --git a/tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt b/tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt new file mode 100644 index 000000000..64863d6d0 --- /dev/null +++ b/tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.6) +project(406_FastAutomaticSkinningTransformations) + +include("../CMakeLists.shared") + +set(SOURCES +${PROJECT_SOURCE_DIR}/main.cpp +) + +add_executable(${PROJECT_NAME}_bin ${SOURCES} ${SHARED_SOURCES}) +target_link_libraries(${PROJECT_NAME}_bin ${SHARED_LIBRARIES}) diff --git a/tutorial/406_FastAutomaticSkinningTransformations/main.cpp b/tutorial/406_FastAutomaticSkinningTransformations/main.cpp new file mode 100755 index 000000000..b19fe392d --- /dev/null +++ b/tutorial/406_FastAutomaticSkinningTransformations/main.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +typedef + std::vector > + RotationList; + +const Eigen::RowVector3d sea_green(70./255.,252./255.,167./255.); +Eigen::MatrixXd V,U,M; +Eigen::MatrixXi F; +Eigen::VectorXi S,b; +Eigen::MatrixXd L; +Eigen::RowVector3d mid; +double anim_t = 0.0; +double anim_t_dir = 0.03; +double bbd = 1.0; +bool resolve = true; +igl::ARAPData arap_data,arap_grouped_data; +igl::ArapDOFData arap_dof_data; +Eigen::SparseMatrix Aeq; + +enum ModeType +{ + MODE_TYPE_ARAP = 0, + MODE_TYPE_ARAP_GROUPED = 1, + MODE_TYPE_ARAP_DOF = 2, + NUM_MODE_TYPES = 4 +} mode = MODE_TYPE_ARAP; + +bool pre_draw(igl::Viewer & viewer) +{ + using namespace Eigen; + using namespace std; + if(resolve) + { + MatrixXd bc(b.size(),V.cols()); + VectorXd Beq(3*b.size()); + for(int i = 0;i S = W.array().rowwise().maxCoeff()==1; + //igl::colon(0,V.rows()-1,b); + //b.conservativeResize(stable_partition( b.data(), b.data()+b.size(), + // [&](int i)->bool{return S(i);})-b.data()); + + { + VectorXd maxW; + igl::mat_max(W,1,maxW,b); + } + + // Precomputation for FAST + // number of weights + const int m = W.cols(); + Aeq.resize(m*3,m*3*(3+1)); + vector > ijv; + for(int i = 0;i(3*i + d,i + c*m*3 + d*m, homo(c))); + } + } + } + Aeq.setFromTriplets(ijv.begin(),ijv.end()); + igl::arap_dof_precomputation(V,F,M,G,arap_dof_data); + igl::arap_dof_recomputation(VectorXi(),Aeq,arap_dof_data); + // Initialize + MatrixXd Istack = MatrixXd::Identity(3,3+1).replicate(1,m); + igl::columnize(Istack,m,2,L); + + // Precomputation for ARAP + arap_data.max_iter = 1; + igl::arap_precomputation(V,F,V.cols(),b,arap_data); + // Grouped arap + arap_grouped_data.max_iter = 2; + arap_grouped_data.G = G; + igl::arap_precomputation(V,F,V.cols(),b,arap_grouped_data); + + + // bounding box diagonal + bbd = (V.colwise().maxCoeff()- V.colwise().minCoeff()).norm(); + + // Plot the mesh with pseudocolors + igl::Viewer viewer; + viewer.set_mesh(U, F); + viewer.add_points(igl::slice(V,b,1),sea_green); + viewer.core.show_lines = false; + 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"<