├── README.md ├── .gitattributes ├── .gitignore ├── Header Files └── DeformationGraph.h └── Source Files ├── optimization.cpp └── DeformationGraph.cpp /README.md: -------------------------------------------------------------------------------- 1 | # Embedded Deformation for Shape Manipulation 2 | C++ implementation of Embedded Deformation for Shape Manipulation 3 | 4 | As for creating a deformation graph from a mesh, I suggest you use MeshLab to sample a point set first. 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /Header Files/DeformationGraph.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEFORMATION_GRAPH_H__ 2 | #define __DEFORMATION_GRAPH_H__ 3 | 4 | #ifndef __OPENCV_HPP__ 5 | #define __OPENCV_HPP__ 6 | #include 7 | using namespace cv; 8 | #endif 9 | 10 | typedef double Node[3]; 11 | typedef double Rotation[9]; 12 | typedef double Translation[3]; 13 | 14 | 15 | class DeformationGraph{ 16 | public: 17 | DeformationGraph(); 18 | //create a deformation graph according to nodes data, mesh vertices data and k 19 | DeformationGraph(int n_nodes, Node *nodes, int n_vertices, double **vertices, int k); 20 | //input nodes and edges data to create a deformation graph 21 | DeformationGraph(int n_nodes, Node *nodes, int n_edges, bool **edges); 22 | 23 | ~DeformationGraph(); 24 | 25 | void findNearestNodes(const double *vertex, int k, int *idx)const; 26 | 27 | //calculate the weight of a vertex 28 | //weights is a double array, contains k-nearest nodes' weights 29 | //idx is an int array, contain k+1-nearest nodes' indexes 30 | void computeWeights(const double *vertex, double *weights, int *idx) const; 31 | 32 | // set k of k-nearest node(s) 33 | void setK(int k){ k_nearest = k; } 34 | 35 | //set weights of Erot, Ereg and Econ 36 | inline void setWeights(double w_rot, double w_reg, double w_con){ 37 | this->w_rot = w_rot; 38 | this->w_reg = w_reg; 39 | this->w_con = w_con; 40 | } 41 | 42 | //predict the position of a vertex or a node 43 | //if the number of nodes of deformation graph is 0, the output will be (0,0,0) 44 | void predict(const double *v, double *_v) const; 45 | 46 | double Erot(); //compute the rotation error 47 | double Ereg(); //compute the regularization error 48 | double Econ(const int p, double **v, double **q); //compute the constraints error 49 | 50 | friend void computef(const DeformationGraph &dg, int &p, double **v, double **q, OutputArray f); 51 | friend void computeJ(const DeformationGraph &dg, const int &p, double **v, double **q, OutputArray J); 52 | friend double F(DeformationGraph &dg, Mat &x, int p, double **v, double **q); //x is used to update dg 53 | friend void gaussNewton(DeformationGraph &dg, int p, double **v, double **q); 54 | 55 | private: 56 | int n_nodes; //number of nodes 57 | int n_edges; //number of edges 58 | int k_nearest; //number of k (k-nearest nodes) 59 | Node *nodes; //nodes array 60 | bool **edges; //edges, a adjacency matrix, n_nodes * n_nodes dimensions 61 | Rotation *rot; //rotation matrixes 62 | Translation *trans; //translation vectors 63 | double w_rot; //rotation error weight 64 | double w_reg; //regularization error weight 65 | double w_con; //constraints error weig 66 | }; 67 | 68 | #endif -------------------------------------------------------------------------------- /Source Files/optimization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DeformationGraph.h" 3 | 4 | 5 | void computef(const DeformationGraph &dg, int &p, double **v, double **q, OutputArray f){ 6 | double _v[3]; 7 | int idx = 0; 8 | Mat fx = Mat::zeros(6*dg.n_nodes+6*dg.n_edges+3*p,1,CV_64F); 9 | //Erot 10 | for(int j=0; j(idx++) = (dg.rot[j][0]*dg.rot[j][3]+dg.rot[j][1]*dg.rot[j][4]+dg.rot[j][2]*dg.rot[j][5])*sqrt(dg.w_rot); 12 | fx.at(idx++) = (dg.rot[j][0]*dg.rot[j][6]+dg.rot[j][1]*dg.rot[j][7]+dg.rot[j][2]*dg.rot[j][8])*sqrt(dg.w_rot); 13 | fx.at(idx++) = (dg.rot[j][3]*dg.rot[j][6]+dg.rot[j][4]*dg.rot[j][7]+dg.rot[j][5]*dg.rot[j][8])*sqrt(dg.w_rot); 14 | fx.at(idx++) = (dg.rot[j][0]*dg.rot[j][0]+dg.rot[j][1]*dg.rot[j][1]+dg.rot[j][2]*dg.rot[j][2]-1)*sqrt(dg.w_rot); 15 | fx.at(idx++) = (dg.rot[j][3]*dg.rot[j][3]+dg.rot[j][4]*dg.rot[j][4]+dg.rot[j][5]*dg.rot[j][5]-1)*sqrt(dg.w_rot); 16 | fx.at(idx++) = (dg.rot[j][6]*dg.rot[j][6]+dg.rot[j][7]*dg.rot[j][7]+dg.rot[j][8]*dg.rot[j][8]-1)*sqrt(dg.w_rot); 17 | } 18 | //Ereg 19 | for(int j=0; j(idx++) = (dg.rot[j][i]*(dg.nodes[k][0]-dg.nodes[j][0]) 24 | +dg.rot[j][i+3]*(dg.nodes[k][1]-dg.nodes[j][1]) 25 | +dg.rot[j][i+6]*(dg.nodes[k][2]-dg.nodes[j][2]) 26 | +dg.nodes[j][i]+dg.trans[j][i]-dg.nodes[k][i]-dg.trans[k][i])*sqrt(dg.w_reg); 27 | } 28 | } 29 | } 30 | //Econ 31 | for(int l=0; l(idx++) = (_v[i]-q[l][i])*sqrt(dg.w_con); 34 | } 35 | //f(x) 36 | fx.copyTo(f); 37 | } 38 | 39 | 40 | void computeJ(const DeformationGraph &dg, const int &p, double **v, double **q, OutputArray J){ 41 | double *w = new double[dg.k_nearest]; 42 | int idx = 0, *index = new int[dg.k_nearest+1]; 43 | Mat Jacobi= Mat::zeros(6*dg.n_nodes+6*dg.n_edges+3*p, 12*dg.n_nodes, CV_64F); 44 | //Erot 45 | for(int j=0; j(idx,0+12*j) = dg.rot[j][3]*sqrt(dg.w_rot);Jacobi.at(idx,1+12*j) = dg.rot[j][4]*sqrt(dg.w_rot);Jacobi.at(idx,2+12*j) = dg.rot[j][5]*sqrt(dg.w_rot); 47 | Jacobi.at(idx,3+12*j) = dg.rot[j][0]*sqrt(dg.w_rot);Jacobi.at(idx,4+12*j) = dg.rot[j][1]*sqrt(dg.w_rot);Jacobi.at(idx++,5+12*j) = dg.rot[j][2]*sqrt(dg.w_rot); 48 | 49 | Jacobi.at(idx,0+12*j) = dg.rot[j][6]*sqrt(dg.w_rot);Jacobi.at(idx,1+12*j) = dg.rot[j][7]*sqrt(dg.w_rot);Jacobi.at(idx,2+12*j) = dg.rot[j][8]*sqrt(dg.w_rot); 50 | Jacobi.at(idx,6+12*j) = dg.rot[j][0]*sqrt(dg.w_rot);Jacobi.at(idx,7+12*j) = dg.rot[j][1]*sqrt(dg.w_rot);Jacobi.at(idx++,8+12*j) = dg.rot[j][2]*sqrt(dg.w_rot); 51 | 52 | Jacobi.at(idx,3+12*j) = dg.rot[j][6]*sqrt(dg.w_rot);Jacobi.at(idx,4+12*j) = dg.rot[j][7]*sqrt(dg.w_rot);Jacobi.at(idx,5+12*j) = dg.rot[j][8]*sqrt(dg.w_rot); 53 | Jacobi.at(idx,6+12*j) = dg.rot[j][3]*sqrt(dg.w_rot);Jacobi.at(idx,7+12*j) = dg.rot[j][4]*sqrt(dg.w_rot);Jacobi.at(idx++,8+12*j) = dg.rot[j][5]*sqrt(dg.w_rot); 54 | 55 | for(int i=0; i<9; i++){ 56 | if(i == 3 || i == 6) ++idx; 57 | Jacobi.at(idx,i+12*j) = 2*dg.rot[j][i]*sqrt(dg.w_rot); 58 | } 59 | ++idx; 60 | } 61 | //Ereg 62 | for(int j=0; j(idx,12*j+3*ii+i) = (dg.nodes[k][ii]-dg.nodes[j][ii])*sqrt(dg.w_reg); 68 | Jacobi.at(idx,12*j+i+9) = sqrt(dg.w_reg); 69 | Jacobi.at(idx++,12*k+i+9) = -sqrt(dg.w_reg); 70 | } 71 | } 72 | } 73 | } 74 | //Econ 75 | for(int l=0; l(idx,ii*3+i+12*index[j]) = w[j]*(v[l][ii]-dg.nodes[index[j]][ii])*sqrt(dg.w_con); 80 | Jacobi.at(idx,9+i+12*index[j]) = w[j]*sqrt(dg.w_con); 81 | } 82 | ++idx; 83 | } 84 | } 85 | //J 86 | Jacobi.copyTo(J); 87 | delete[] w; w = NULL; 88 | delete[] index; index = NULL; 89 | } 90 | 91 | 92 | double F(DeformationGraph &dg, Mat &x, int p, double **v, double **q){ 93 | for(int j=0; j(12*j+i); 95 | for(int i=0; i<3; ++i) dg.trans[j][i] = x.at(12*j+i+9); 96 | } 97 | double e_rot = dg.Erot(); 98 | double e_reg = dg.Ereg(); 99 | double e_con = dg.Econ(p,v,q); 100 | std::cout<<"Erot = "< 2 | #include "DeformationGraph.h" 3 | 4 | 5 | DeformationGraph::DeformationGraph() 6 | :n_nodes(0), 7 | n_edges(0), 8 | k_nearest(1), 9 | w_rot(1), 10 | w_reg(1), 11 | w_con(1){ 12 | nodes = NULL; 13 | edges = NULL; 14 | rot = NULL; 15 | trans = NULL; 16 | } 17 | 18 | 19 | DeformationGraph::DeformationGraph(int n_nodes, Node *nodes, int n_vertices, double **vertices, int k) 20 | :n_nodes(n_nodes), 21 | n_edges(0), 22 | k_nearest(k), 23 | w_rot(1), 24 | w_reg(1), 25 | w_con(1){ 26 | this->nodes = new Node[n_nodes]; 27 | this->edges = new bool*[n_nodes]; 28 | rot = new Rotation[n_nodes]; 29 | trans = new Translation[n_nodes]; 30 | for(int j=0; jnodes[j][i] = nodes[j][i]; 33 | //initialize edges 34 | this->edges[j] = new bool[n_nodes]; 35 | for(int i=0; inodes = new Node[n_nodes]; 67 | this->edges = new bool*[n_nodes]; 68 | rot = new Rotation[n_nodes]; 69 | trans = new Translation[n_nodes]; 70 | for(int j=0; jnodes[j][i] = nodes[j][i]; 73 | //initialize edges 74 | this->edges[j] = new bool[n_nodes]; 75 | for(int i=0; iedges[j][i] = edges[j][i]; 76 | //initialize rotation matrixes 77 | for(int i=0; i<9; i++) rot[j][i] = 0.1; 78 | rot[j][0] = 0.9; rot[j][4] = 0.9; rot[j][8] = 0.9; 79 | //initialize translation vectors 80 | for(int i=0; i<3; i++) trans[j][i] = 0; 81 | } 82 | } 83 | 84 | 85 | DeformationGraph::~DeformationGraph(){ 86 | delete[] nodes; nodes = NULL; 87 | delete[] rot; rot = NULL; 88 | delete[] trans; trans = NULL; 89 | for(int j=0; ji; j--) if(d[j]i; j--) if(d[j]