Browse Source

selfintersection and intersection demo

Former-commit-id: bd4c12d7132695d360d5e635e5fa46a5932350a4
Alec Jacobson 11 years ago
parent
commit
5b438b9b2d
3 changed files with 165 additions and 55 deletions
  1. 0 0
      examples/intersections/Makefile
  2. 8 0
      examples/intersections/README.md
  3. 157 55
      examples/intersections/example.cpp

+ 0 - 0
examples/selfintersect/Makefile → examples/intersections/Makefile


+ 8 - 0
examples/intersections/README.md

@@ -0,0 +1,8 @@
+To compute and visualize all facets participating in self-intersections issue:
+
+    ./example input.obj
+
+To compute and visualize all facets participating in intersections between mesh
+A and mesh B (ignoring self-intersections in each) issue:
+
+    ./example A.obj B.obj

+ 157 - 55
examples/selfintersect/example.cpp → examples/intersections/example.cpp

@@ -25,6 +25,7 @@
 #include <igl/Camera.h>
 #include <igl/get_seconds.h>
 #include <igl/cgal/selfintersect.h>
+#include <igl/cgal/intersect_other.h>
 
 #ifdef __APPLE__
 #  include <GLUT/glut.h>
@@ -118,11 +119,17 @@ void TW_CALL get_rotation_type(void * value, void *clientData)
 int width,height;
 // Position of light
 float light_pos[4] = {0.1,0.1,-0.9,0};
-// Vertex positions, normals, colors and centroid
-Eigen::MatrixXd V,N,C,Z,mid;
+// V,U  Vertex positions
+// C,D  Colors
+// N,W  Normals
+// mid  combined "centroid"
+Eigen::MatrixXd V,N,C,Z,mid,U,W,D;
+// F,G  faces
+Eigen::MatrixXi F,G;
+bool has_other = false;
+bool show_A = true;
+bool show_B = true;
 int selected_col = 0;
-// Faces
-Eigen::MatrixXi F;
 // Bounding box diagonal length
 double bbd;
 // Running ambient occlusion
@@ -258,7 +265,40 @@ void display()
   // Draw the model
   // Set material properties
   glEnable(GL_COLOR_MATERIAL);
-  draw_mesh(V,F,N,C);
+
+  const auto draw = [](
+    const MatrixXd & V,
+    const MatrixXi & F,
+    const MatrixXd & N,
+    const MatrixXd & C)
+  {
+    glEnable(GL_POLYGON_OFFSET_FILL); // Avoid Stitching!
+    glPolygonOffset(1.0,1);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    draw_mesh(V,F,N,C);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glDisable(GL_COLOR_MATERIAL);
+    const float black[4] = {0,0,0,1};
+    glColor4fv(black);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,  black);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,  black);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+    glLightfv(GL_LIGHT0, GL_AMBIENT, black);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE, black);
+    glLineWidth(1.0);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+    draw_mesh(V,F,N,C);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    glEnable(GL_COLOR_MATERIAL);
+  };
+  if(show_A)
+  {
+    draw(V,F,N,C);
+  }
+  if(show_B)
+  {
+    draw(U,G,W,D);
+  }
 
   pop_object();
 
@@ -449,7 +489,34 @@ void color_selfintersections(
     C.row(IF(f,0)) = RowVector3d(1,0.4,0.4);
     C.row(IF(f,1)) = RowVector3d(1,0.4,0.4);
   }
+}
 
+void color_intersections(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & U,
+  const Eigen::MatrixXi & G,
+  Eigen::MatrixXd & C,
+  Eigen::MatrixXd & D)
+{
+  using namespace igl;
+  using namespace Eigen;
+  MatrixXi IF;
+  const bool first_only = false;
+  intersect_other(V,F,U,G,first_only,IF);
+  C.resize(F.rows(),3);
+  C.col(0).setConstant(0.4);
+  C.col(1).setConstant(0.8);
+  C.col(2).setConstant(0.3);
+  D.resize(G.rows(),3);
+  D.col(0).setConstant(0.4);
+  D.col(1).setConstant(0.3);
+  D.col(2).setConstant(0.8);
+  for(int f = 0;f<IF.rows();f++)
+  {
+    C.row(IF(f,0)) = RowVector3d(1,0.4,0.4);
+    D.row(IF(f,1)) = RowVector3d(0.8,0.7,0.3);
+  }
 }
 
 void key(unsigned char key, int mouse_x, int mouse_y)
@@ -481,73 +548,103 @@ int main(int argc, char * argv[])
 
   // init mesh
   string filename = "../shared/truck.obj";
-  if(argc < 3)
+  string filename_other = "";
+  switch(argc)
   {
-    cerr<<"Usage:"<<endl<<"    ./example input.obj color.dmat"<<endl;
+    case 3:
+      // Read and prepare mesh
+      filename_other = argv[2];
+      has_other=true;
+      // fall through
+    case 2:
+      // Read and prepare mesh
+      filename = argv[1];
+      break;
+    default:
+    cerr<<"Usage:"<<endl<<"    ./example input.obj [other.obj]"<<endl;
     cout<<endl<<"Opening default mesh..."<<endl;
-  }else
-  {
-    // Read and prepare mesh
-    filename = argv[1];
   }
 
-  // dirname, basename, extension and filename
-  string d,b,ext,f;
-  pathinfo(filename,d,b,ext,f);
-  // Convert extension to lower case
-  transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
-  vector<vector<double > > vV,vN,vTC;
-  vector<vector<int > > vF,vFTC,vFN;
-  if(ext == "obj")
+  const auto read = []
+    (const string & filename, MatrixXd & V, MatrixXi & F, MatrixXd & N) -> bool
   {
+    // dirname, basename, extension and filename
+    string d,b,ext,f;
+    pathinfo(filename,d,b,ext,f);
     // Convert extension to lower case
-    if(!igl::readOBJ(filename,vV,vTC,vN,vF,vFTC,vFN))
+    transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
+    vector<vector<double > > vV,vN,vTC;
+    vector<vector<int > > vF,vFTC,vFN;
+    if(ext == "obj")
     {
-      return 1;
-    }
-  }else if(ext == "off")
-  {
-    // Convert extension to lower case
-    if(!igl::readOFF(filename,vV,vF,vN))
+      // Convert extension to lower case
+      if(!igl::readOBJ(filename,vV,vTC,vN,vF,vFTC,vFN))
+      {
+        return false;
+      }
+    }else if(ext == "off")
     {
-      return 1;
+      // Convert extension to lower case
+      if(!igl::readOFF(filename,vV,vF,vN))
+      {
+        return false;
+      }
+    }else if(ext == "wrl")
+    {
+      // Convert extension to lower case
+      if(!igl::readWRL(filename,vV,vF))
+      {
+        return false;
+      }
+    //}else
+    //{
+    //  // Convert extension to lower case
+    //  MatrixXi T;
+    //  if(!igl::readMESH(filename,V,T,F))
+    //  {
+    //    return false;
+    //  }
+    //  //if(F.size() > T.size() || F.size() == 0)
+    //  {
+    //    boundary_faces(T,F);
+    //  }
     }
-  }else if(ext == "wrl")
-  {
-    // Convert extension to lower case
-    if(!igl::readWRL(filename,vV,vF))
+    if(vV.size() > 0)
     {
-      return 1;
+      if(!list_to_matrix(vV,V))
+      {
+        return false;
+      }
+      triangulate(vF,F);
     }
-  //}else
-  //{
-  //  // Convert extension to lower case
-  //  MatrixXi T;
-  //  if(!igl::readMESH(filename,V,T,F))
-  //  {
-  //    return 1;
-  //  }
-  //  //if(F.size() > T.size() || F.size() == 0)
-  //  {
-  //    boundary_faces(T,F);
-  //  }
+    // Compute normals, centroid, colors, bounding box diagonal
+    per_face_normals(V,F,N);
+    return true;
+  };
+
+  if(!read(filename,V,F,N))
+  {
+    return 1;
   }
-  if(vV.size() > 0)
+  if(has_other)
   {
-    if(!list_to_matrix(vV,V))
+    if(!read(argv[2],U,G,W))
     {
       return 1;
     }
-    triangulate(vF,F);
+    mid = 0.25*(V.colwise().maxCoeff() + V.colwise().minCoeff()) +
+      0.25*(U.colwise().maxCoeff() + U.colwise().minCoeff());
+    bbd = max(
+      (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff(),
+      (U.colwise().maxCoeff() - U.colwise().minCoeff()).maxCoeff());
+    color_intersections(V,F,U,G,C,D);
+  }else
+  {
+    mid = 0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff());
+    bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
+    color_selfintersections(V,F,C);
   }
 
-
-  // Compute normals, centroid, colors, bounding box diagonal
-  per_face_normals(V,F,N);
-  mid = 0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff());
-  bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
-  color_selfintersections(V,F,C);
-
   // Init glut
   glutInit(&argc,argv);
 
@@ -567,11 +664,16 @@ int main(int argc, char * argv[])
     "igl_trackball,two-a...-fixed-up");
   rebar.TwAddVarCB( "rotation_type", RotationTypeTW,
     set_rotation_type,get_rotation_type,NULL,"keyIncr=] keyDecr=[");
+  if(has_other)
+  {
+    rebar.TwAddVarRW("show_A",TW_TYPE_BOOLCPP,&show_A, "key=a",false);
+    rebar.TwAddVarRW("show_B",TW_TYPE_BOOLCPP,&show_B, "key=b",false);
+  }
   rebar.load(REBAR_NAME);
 
   glutInitDisplayString("rgba depth double samples>=8 ");
   glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT));
-  glutCreateWindow("selfintersect-mesh");
+  glutCreateWindow("mesh-intersections");
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(key);