how to produce .mesh .tgf file for 403_BoundedBiharmonicWeights_bin

来源:互联网 发布:欧姬丝洗发水 知乎 编辑:程序博客网 时间:2024/05/16 06:45

1. First, assume you have an .obj file, you can download or make one from maya

2. then convert it into .off file in meshlab.

3. after that using Tetgen to generate tetrahetras by typing: tetgen -pqYV cube.off

 the files named cube.1.node, cube.1.face, cube.1.smesh are gonna be used.

the cube.1.node file looks like:

26  3  0  0   0    -1.84531  3.7843800000000001  2.4587400000000001   1    0  3.7843800000000001  2.4587400000000001   2    1.84531  3.7843800000000001  2.4587400000000001   3    -1.84531  5.9363999999999999  2.4587400000000001   4    0  5.9363999999999999  2.4587400000000001   5    1.84531  5.9363999999999999  2.4587400000000001   6    -1.84531  8.0884300000000007  2.4587400000000001   7    0  8.0884300000000007  2.4587400000000001   8    1.84531  8.0884300000000007  2.4587400000000001   9    -1.84531  8.0884300000000007  0  10    0  8.0884300000000007  0  11    1.84531  8.0884300000000007  0  12    -1.84531  8.0884300000000007  -2.4587400000000001  13    0  8.0884300000000007  -2.4587400000000001  14    1.84531  8.0884300000000007  -2.4587400000000001  15    -1.84531  5.9363999999999999  -2.4587400000000001  16    0  5.9363999999999999  -2.4587400000000001  17    1.84531  5.9363999999999999  -2.4587400000000001  18    -1.84531  3.7843800000000001  -2.4587400000000001  19    0  3.7843800000000001  -2.4587400000000001  20    1.84531  3.7843800000000001  -2.4587400000000001  21    -1.84531  3.7843800000000001  0  22    0  3.7843800000000001  0  23    1.84531  3.7843800000000001  0  24    1.84531  5.9363999999999999  0  25    -1.84531  5.9363999999999999  0# Generated by tetgen -pqYV cube.off 

the cube.1.face file is like:

48  1    0      4     0     3    1    1      5     1     4    1    2      0     4     1    1    3      7     3     6    1    4      1     5     2    1    5      8     4     7    1    6      3     7     4    1    7     10     6     9    1    8      4     8     5    1    9     11     7    10    1   10      6    10     7    1   11     13     9    12    1   12      7    11     8    1   13     14    10    13    1   14      9    13    10    1   15     16    12    15    1   16     10    14    11    1   17     17    13    16    1   18     12    16    13    1   19     19    15    18    1   20     13    17    14    1   21     20    16    19    1   22     15    19    16    1   23     22    18    21    1   24     16    20    17    1   25     23    19    22    1   26     18    22    19    1   27      0    22    21    1   28     19    23    20    1   29      1    23    22    1   30     22     0     1    1   31     17    23    24    1   32     23     1     2    1   33     24     2     5    1   34     23    17    20    1   35     11    17    24    1   36      2    24    23    1   37     11     5     8    1   38     17    11    14    1   39     15    21    18    1   40      5    11    24    1   41     25     0    21    1   42     21    15    25    1   43      9    15    12    1   44      0    25     3    1   45      9     3    25    1   46     15     9    25    1   47      3     9     6    1# Generated by tetgen -pqYV cube.off 

the cube.1.smesh file seems to be:

# cube.1.smesh.  TetGen's input file.# part 1: node list.0  3  0  0  # nodes are found in cube.1.node.# part 2: facet list.48  03       0     4     33       1     5     43       4     0     13       3     7     63       5     1     23       4     8     73       7     3     43       6    10     93       8     4     53       7    11    103      10     6     73       9    13    123      11     7     83      10    14    133      13     9    103      12    16    153      14    10    113      13    17    163      16    12    133      15    19    183      17    13    143      16    20    193      19    15    163      18    22    213      20    16    173      19    23    223      22    18    193      22     0    213      23    19    203      23     1    223       0    22     13      23    17    243       1    23     23       2    24     53      17    23    203      17    11    243      24     2    233       5    11     83      11    17    143      21    15    183      11     5    243       0    25    213      15    21    253      15     9    123      25     0     33       3     9    253       9    15    253       9     3     6# part 3: hole list.0# part 4: region list.0# Generated by tetgen -pqYV cube.off 

4. then we create a file named "cube.mesh"

MeshVersionFormatted 1Dimension 3Vertices26-1.84531  3.7843800000000001  2.4587400000000001 00  3.7843800000000001  2.4587400000000001 01.84531  3.7843800000000001  2.4587400000000001 0-1.84531  5.9363999999999999  2.4587400000000001 00  5.9363999999999999  2.4587400000000001 01.84531  5.9363999999999999  2.4587400000000001 0-1.84531  8.0884300000000007  2.4587400000000001 00  8.0884300000000007  2.4587400000000001 01.84531  8.0884300000000007  2.4587400000000001 0-1.84531  8.0884300000000007  0 00  8.0884300000000007  0 01.84531  8.0884300000000007  0 0-1.84531  8.0884300000000007  -2.4587400000000001 00  8.0884300000000007  -2.4587400000000001 01.84531  8.0884300000000007  -2.4587400000000001 0-1.84531  5.9363999999999999  -2.4587400000000001 00  5.9363999999999999  -2.4587400000000001 01.84531  5.9363999999999999  -2.4587400000000001 0-1.84531  3.7843800000000001  -2.4587400000000001 00  3.7843800000000001  -2.4587400000000001 01.84531  3.7843800000000001  -2.4587400000000001 0-1.84531  3.7843800000000001  0 00  3.7843800000000001  0 0 1.84531  3.7843800000000001  0 01.84531  5.9363999999999999  0 0-1.84531  5.9363999999999999  0 0Triangles480  4   3 0                1  5   4 0                4  0   1 0                3  7   6 0                5  1   2 0                4  8   7 0                7  3   4 0                6  10  9 0                8  4   5 0                7  11 10 0                10 6    7 0               9  13 12 0                11 7    8 0               10 14  13 0               13 9   10 0               12 16  15 0               14 10  11 0               13 17  16 0               16 12  13 0               15 19  18 0               17 13  14 0               16 20  19 0               19 15  16 0               18 22  21 0               20 16  17 0               19 23  22 0               22 18  19 0               22 0   21 0               23 19  20 023 1   22 00  22  1 023 17  24 01  23  2 02  24  5 017 23  20 017 11  24 024 2   23 05  11  8 011 17  14 021 15  18 011 5   24 00  25 21 015 21  25 015 9   12 025 0    3 03  9  25 09  15 25 09  3   6 0Tetrahedra4325    10    24    16 05     4    11    24 0 16    24    23    17 0 25     0     4     3 05     4     8    11 018    15    22    19 024    25    16    22 011    17    10    14 05     2     1    24 04     3     7    10 023    16    20    19 015     9    25    16 09     3    10     6 0 22    16    23    19 015    16    22    19 025    15    16    22 025     9    10    16 09     3    25    10 016    24    22    23 021    15    25    22 021    15    22    18 023     1     2    24 025     3     4    10 023     1    24    22 03     6     7    10 08     4     7    11 07     4    10    11 023    16    17    20 09    15    12    16 010     9    13    16 09    12    13    16 00    22     4     1 04     5     1    24 04    25    10    24 04    10    11    24 04    25    24    22 01     4    24    22 00    25    22    21 00    25     4    22 014    10    13    17 013    10    16    17 010    24    16    17 011    17    24    10 0Edges 0End 


note: the rotational direction of triangles in .mesh file is opposite to the ones in .face file


5. create a file named "cube.tgf"

1-1.84531  3.7843800000000001  2.458740000000000120  3.7843800000000001  2.458740000000000131.84531  3.7843800000000001  2.45874000000000014-1.84531  5.9363999999999999  2.458740000000000150  5.9363999999999999  2.458740000000000161.84531  5.9363999999999999  2.45874000000000017-1.84531  8.0884300000000007  2.458740000000000180  8.0884300000000007  2.458740000000000191.84531  8.0884300000000007  2.458740000000000110-1.84531  8.0884300000000007  0110  8.0884300000000007  0121.84531  8.0884300000000007  013-1.84531  8.0884300000000007  -2.4587400000000001140  8.0884300000000007  -2.4587400000000001151.84531  8.0884300000000007  -2.458740000000000116-1.84531  5.9363999999999999  -2.4587400000000001170  5.9363999999999999  -2.4587400000000001181.84531  5.9363999999999999  -2.458740000000000119-1.84531  3.7843800000000001  -2.4587400000000001200  3.7843800000000001  -2.4587400000000001211.84531  3.7843800000000001  -2.458740000000000122-1.84531  3.7843800000000001  0230  3.7843800000000001  0241.84531  3.7843800000000001  0251.84531  5.9363999999999999  026-1.84531  5.9363999999999999  0

those are control points which point handle, the points of bone edges and the points and cage edges could be.

注意这里对于点handle和骨骼handle, 要求点为四面体中的点的子集.



6. As the indices generated by tetgen are based on 0 not 1 which the project adopt, we need to amend several places in the project.

find igl::readMESH function, go to the definition of it,  there are two places we need to change.

    for(int j = 0;j<3;j++)    {     // F(i,j) = tri[j]-1;        F(i, j) = tri[j]; // tetgen is based on 0, don't need to minus one.    }


  for(int i = 0;i<number_of_tetrahedra;i++)  {    if(5 != fscanf(mesh_file," %d %d %d %d %d",&a,&b,&c,&d,&extra))    {      fprintf(stderr,"Error: expecting tetrahedra indices...\n");      fclose(mesh_file);      return false;    }    //T(i,0) = a-1;    //T(i,1) = b-1;    //T(i,2) = c-1;    //T(i,3) = d-1;T(i,0) = a;//tetgen based on 0, don't need to minus oneT(i,1) = b;T(i,2) = c;T(i,3) = d;  }

7. after removing not necessary lines, the main.cpp looks like:

// If you don't have mosek installed and don't want to install it. Then// uncomment the following six lines.  Don't use static library for this// example because of Mosek complications////#define IGL_NO_MOSEK//#ifdef IGL_NO_MOSEK//#ifdef IGL_STATIC_LIBRARY//#undef IGL_STATIC_LIBRARY//#endif//#endif#include <igl/boundary_conditions.h>#include <igl/colon.h>#include <igl/column_to_quats.h>#include <igl/directed_edge_parents.h>#include <igl/forward_kinematics.h>#include <igl/jet.h>#include <igl/lbs_matrix.h>#include <igl/deform_skeleton.h>#include <igl/normalize_row_sums.h>#include <igl/readDMAT.h>#include <igl/readMESH.h>#include <igl/readTGF.h>#include <igl/viewer/Viewer.h>#include <igl/bbw/bbw.h>//#include <igl/embree/bone_heat.h>#include <Eigen/Geometry>#include <Eigen/StdVector>#include <vector>#include <algorithm>#include <iostream>#include "tutorial_shared_path.h"typedef   std::vector<Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> >  RotationList;const Eigen::RowVector3d sea_green(70./255.,252./255.,167./255.);int selected = 0;Eigen::MatrixXd V,W,U,C,M;Eigen::MatrixXi T,F,BE;Eigen::VectorXi P;RotationList pose;double anim_t = 1.0;double anim_t_dir = -0.03;void set_color(igl::viewer::Viewer &viewer){  Eigen::MatrixXd C;  igl::jet(W.col(selected).eval(),true,C);  viewer.data.set_colors(C);}bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods){  switch(key)  {    //case ' ':      //viewer.core.is_animating = !viewer.core.is_animating;      //break;    case '.':      selected++;      selected = std::min(std::max(selected,0),(int)W.cols()-1);      set_color(viewer);      break;    case ',':      selected--;      selected = std::min(std::max(selected,0),(int)W.cols()-1);      set_color(viewer);      break;  }  return true;}int main(int argc, char *argv[]){  using namespace Eigen;  using namespace std;  igl::readMESH(TUTORIAL_SHARED_PATH "/cube.mesh",V,T,F);//V为顶点,T为tetrahedra,F为Face  U=V;  igl::readTGF(TUTORIAL_SHARED_PATH "/cube.tgf",C,BE);  // retrieve parents for forward kinematics  //igl::directed_edge_parents(BE,P);  // Read pose as matrix of quaternions per row // MatrixXd Q;  //igl::readDMAT(TUTORIAL_SHARED_PATH "/hand-pose.dmat",Q);  //igl::column_to_quats(Q,pose);  //assert(pose.size() == BE.rows());  // List of boundary indices (aka fixed value indices into VV)  VectorXi b;  // List of boundary conditions of each weight function  MatrixXd bc;   // Added by seamanj  // Initialize P which is point handles    P.resize(3);  P << 1, 2, 3;  igl::boundary_conditions(V,T,C,P,BE,MatrixXi(),b,bc);  // compute BBW weights matrix  igl::bbw::BBWData bbw_data;  // only a few iterations for sake of demo  bbw_data.active_set_params.max_iter = 8;  bbw_data.verbosity = 2;  if(!igl::bbw::bbw(V,T,b,bc,bbw_data,W))  {    return false;  }  //MatrixXd Vsurf = V.topLeftCorner(F.maxCoeff()+1,V.cols());  //MatrixXd Wsurf;  //if(!igl::bone_heat(Vsurf,F,C,VectorXi(),BE,MatrixXi(),Wsurf))  //{  //  return false;  //}  //W.setConstant(V.rows(),Wsurf.cols(),1);  //W.topLeftCorner(Wsurf.rows(),Wsurf.cols()) = Wsurf = Wsurf = Wsurf = Wsurf;  // Normalize weights to sum to one  igl::normalize_row_sums(W,W);  // precompute linear blend skinning matrix  igl::lbs_matrix(V,W,M);  // Plot the mesh with pseudocolors  igl::viewer::Viewer viewer;  viewer.data.set_mesh(U, F);  set_color(viewer);  viewer.data.set_edges(C,BE,sea_green);  viewer.core.show_lines = false;  viewer.core.show_overlay_depth = false;  viewer.core.line_width = 1;  //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 '.' to show next weight function."<<endl<<    "Press ',' to show previous weight function."<<endl<<    "Press [space] to toggle animation."<<endl;  viewer.launch();}

the weights distribution looks like:



another subtler example is as follows:






Instead of generating .mesh file by ourselves manually, recently I found Tetgen can offer us these kind of files.


just use the -g switch in the command.

-g Outputs mesh to .mesh le for viewing by Medit.

the complete command is like:

tetgen -pqgYV cube.off

then Tetgen will generate the cube.1.mesh file which can be used directly in project 403.


with these files used, there are some matters needing attention.


a)  we don't need to change the indices as step 6 says, just keeping the indices minus one.

b) As step 4 says, we still need to change the winding orientation of triangles in cube.1.mesh. I think this may be caused by the fact that the normal of triangles generated by Tetgen pointing inside the tetrahedrons.


After .mesh file generating, we do the same things to the .tgf as step 5 says. Just copying the node data from file cube.1.node to file cube.1.tgf like:

0    -1.84531  3.7843800000000001  2.45874000000000011    0  3.7843800000000001  2.45874000000000012    1.84531  3.7843800000000001  2.45874000000000013    -1.84531  5.9363999999999999  2.45874000000000014    0  5.9363999999999999  2.45874000000000015    1.84531  5.9363999999999999  2.45874000000000016    -1.84531  8.0884300000000007  2.45874000000000017    0  8.0884300000000007  2.45874000000000018    1.84531  8.0884300000000007  2.45874000000000019    -1.84531  8.0884300000000007  010    0  8.0884300000000007  011    1.84531  8.0884300000000007  012    -1.84531  8.0884300000000007  -2.458740000000000113    0  8.0884300000000007  -2.458740000000000114    1.84531  8.0884300000000007  -2.458740000000000115    -1.84531  5.9363999999999999  -2.458740000000000116    0  5.9363999999999999  -2.458740000000000117    1.84531  5.9363999999999999  -2.458740000000000118    -1.84531  3.7843800000000001  -2.458740000000000119    0  3.7843800000000001  -2.458740000000000120    1.84531  3.7843800000000001  -2.458740000000000121    -1.84531  3.7843800000000001  022    0  3.7843800000000001  023    1.84531  3.7843800000000001  024    1.84531  5.9363999999999999  025    -1.84531  5.9363999999999999  0

By the way, I am not sure whether the based index should be 0 or 1. You figure it out.


In addition, the .mesh file generated by tetgen is different from our manual one in terms of triangle part. when generating triangle indices, tetgen will iterate all the triangles including the ones consisting in tetrahedrons. However, we just include the triangle from .face file which only contain boundary triangles. Both have their own advantages and disadvantages.

The one generated by tetgen will enable us to see the internal of the mesh, but the result of applying it in our example is not so appealing.







the one done by ourselves will give us pleasing result, but we can not see the internal structure of the mesh.






If you want the code product the pleasing result with .mesh file generated by tetgen, there is little change can be done in readMESH.cpp


  ////////////////original///////////////////// // // allocate space for triangles //  F.resize(number_of_triangles,3); // // triangle indices // int tri[3]; // for (int i = 0; i<number_of_triangles; i++) // {//  if (4 != fscanf(mesh_file, " %d %d %d %d", &tri[0], &tri[1], &tri[2], &extra))//  {//  printf("Error: expecting triangle indices...\n");//  return false;//  }//for (int j = 0; j<3; j++)//{//F(i, j) = tri[j] - 1;//} // }  /////////////////fixed by seamanj////////////////////  int tri[3];  for (int i = 0, k = F.rows(); i<number_of_triangles; i++)  {  if (4 != fscanf(mesh_file, " %d %d %d %d", &tri[0], &tri[1], &tri[2], &extra))  {  printf("Error: expecting triangle indices...\n");  return false;  }  if (extra == 1)//第四位指示是否为边界面  {  F.conservativeResize(k + 1, 3);  for (int j = 0; j<3; j++)  {  F(k, j) = tri[j] - 1;  }  k++;  }  }  //////////////////    end    /////////////////////



As for the details of .mesh, please refer to page 33 of http://www.ann.jussieu.fr/frey/publications/RT-0253.pdf, Here I just give part of it:


Then I would like to talk about the ref term, which means the group the element belong to.

Using tetview to open sphere.1.mesh we would see the result below:


see, there are two groups dividing the triangles, the boundary triangles are in green group, the internal triangles are in red group.







0 0