Explorar el Código

OFF color-per-vertex

Former-commit-id: 92ef923397faabe23a6d6574e8ae6f154d449f06
jmespadero hace 8 años
padre
commit
33c27124bf

+ 36 - 6
include/igl/readOFF.cpp

@@ -14,7 +14,8 @@ IGL_INLINE bool igl::readOFF(
   const std::string off_file_name,
   std::vector<std::vector<Scalar > > & V,
   std::vector<std::vector<Index > > & F,
-  std::vector<std::vector<Scalar > > & N)
+  std::vector<std::vector<Scalar > > & N,
+  std::vector<std::vector<Scalar > > & C)
 {
   using namespace std;
   FILE * off_file = fopen(off_file_name.c_str(),"r");
@@ -26,20 +27,25 @@ IGL_INLINE bool igl::readOFF(
   V.clear();
   F.clear();
   N.clear();
+  C.clear();
+
   // First line is always OFF
   char header[1000];
   const std::string OFF("OFF");
   const std::string NOFF("NOFF");
+  const std::string COFF("COFF");
   if(fscanf(off_file,"%s\n",header)!=1
      || !(
        string(header).compare(0, OFF.length(), OFF)==0 ||
+       string(header).compare(0, COFF.length(), COFF)==0 ||
        string(header).compare(0,NOFF.length(),NOFF)==0))
   {
-    printf("Error: %s's first line should be OFF or NOFF not %s...",off_file_name.c_str(),header);
+    printf("Error: readOFF() %s's first line should be OFF or NOFF or COFF, not %s...",off_file_name.c_str(),header);
     fclose(off_file);
     return false;
   }
   bool has_normals = string(header).compare(0,NOFF.length(),NOFF)==0;
+  bool has_vertexColors = string(header).compare(0,COFF.length(),COFF)==0;
   // Second line is #vertices #faces #edges
   int number_of_vertices;
   int number_of_faces;
@@ -56,6 +62,8 @@ IGL_INLINE bool igl::readOFF(
   V.resize(number_of_vertices);
   if (has_normals)
     N.resize(number_of_vertices);
+  if (has_vertexColors)
+    C.resize(number_of_vertices);
   F.resize(number_of_faces);
   //printf("%s %d %d %d\n",(has_normals ? "NOFF" : "OFF"),number_of_vertices,number_of_faces,number_of_edges);
   // Read vertices
@@ -81,6 +89,14 @@ IGL_INLINE bool igl::readOFF(
         normal[2] = nz;
         N[i] = normal;
       }
+
+      if (has_vertexColors)
+      {
+        C[i].resize(3);
+        C[i][0] = nx / 255.0;
+        C[i][1] = ny / 255.0;
+        C[i][2] = nz / 255.0;
+      }
       i++;
     }else if(
         fscanf(off_file,"%[#]",&tic_tac_toe)==1)
@@ -146,10 +162,11 @@ IGL_INLINE bool igl::readOFF(
   std::vector<std::vector<double> > vV;
   std::vector<std::vector<double> > vN;
   std::vector<std::vector<int> > vF;
-  bool success = igl::readOFF(str,vV,vF,vN);
+  std::vector<std::vector<double> > vC;
+  bool success = igl::readOFF(str,vV,vF,vN,vC);
   if(!success)
   {
-    // readOFF(str,vV,vF) should have already printed an error
+    // readOFF(str,vV,vF,vN,vC) should have already printed an error
     // message to stderr
     return false;
   }
@@ -179,10 +196,11 @@ IGL_INLINE bool igl::readOFF(
   std::vector<std::vector<double> > vV;
   std::vector<std::vector<double> > vN;
   std::vector<std::vector<int> > vF;
-  bool success = igl::readOFF(str,vV,vF,vN);
+  std::vector<std::vector<double> > vC;
+  bool success = igl::readOFF(str,vV,vF,vN,vC);
   if(!success)
   {
-    // readOFF(str,vV,vF) should have already printed an error
+    // readOFF(str,vV,vF,vC) should have already printed an error
     // message to stderr
     return false;
   }
@@ -208,6 +226,18 @@ IGL_INLINE bool igl::readOFF(
       return false;
     }
   }
+
+  //Warning: RGB colors will be returned in the N matrix
+  if (vC.size())
+  {
+    bool C_rect = igl::list_to_matrix(vC,N);
+    if(!C_rect)
+    {
+      // igl::list_to_matrix(vC,N) already printed error message to std err
+      return false;
+    }
+  }
+
   return true;
 }
 #endif

+ 5 - 6
include/igl/readOFF.h

@@ -20,7 +20,7 @@
 namespace igl 
 {
   
-  // Read a mesh from an ascii obj file, filling in vertex positions, normals
+  // Read a mesh from an ascii OFF file, filling in vertex positions, normals
   // and texture coordinates. Mesh may have faces of any number of degree
   //
   // Templates:
@@ -32,17 +32,16 @@ namespace igl
   // Outputs:
   //   V  double matrix of vertex positions  #V by 3
   //   F  #F list of face indices into vertex positions
-  //   TC  double matrix of texture coordinats #TC by 2
-  //   FTC  #F list of face indices into vertex texture coordinates
-  //   N  double matrix of corner normals #N by 3
-  //   FN  #F list of face indices into vertex normals
+  //   N  list of vertex normals #V by 3
+  //   C  list of rgb color values per vertex #V by 3
   // Returns true on success, false on errors
   template <typename Scalar, typename Index>
   IGL_INLINE bool readOFF(
     const std::string off_file_name, 
     std::vector<std::vector<Scalar > > & V,
     std::vector<std::vector<Index > > & F,
-    std::vector<std::vector<Scalar > > & N);
+    std::vector<std::vector<Scalar > > & N,
+    std::vector<std::vector<Scalar > > & C);
   
   
 #ifndef IGL_NO_EIGEN

+ 4 - 5
include/igl/read_triangle_mesh.cpp

@@ -35,7 +35,7 @@ IGL_INLINE bool igl::read_triangle_mesh(
   pathinfo(str,d,b,e,f);
   // Convert extension to lower case
   std::transform(e.begin(), e.end(), e.begin(), ::tolower);
-  vector<vector<Scalar> > TC, N;
+  vector<vector<Scalar> > TC, N, C;
   vector<vector<Index> > FTC, FN;
   if(e == "obj")
   {
@@ -49,7 +49,7 @@ IGL_INLINE bool igl::read_triangle_mesh(
     return success;
   }else if(e == "off")
   {
-    return readOFF(str,V,F,N);
+    return readOFF(str,V,F,N,C);
   }
   cerr<<"Error: "<<__FUNCTION__<<": "<<
     str<<" is not a recognized mesh file format."<<endl;
@@ -85,7 +85,7 @@ IGL_INLINE bool igl::read_triangle_mesh(
   pathinfo(filename,dir,base,ext,name);
   // Convert extension to lower case
   transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
-  vector<vector<double > > vV,vN,vTC;
+  vector<vector<double > > vV,vN,vTC,vC;
   vector<vector<int > > vF,vFTC,vFN;
   if(ext == "mesh")
   {
@@ -113,7 +113,7 @@ IGL_INLINE bool igl::read_triangle_mesh(
     }
   }else if(ext == "off")
   {
-    if(!readOFF(filename,vV,vF,vN))
+    if(!readOFF(filename,vV,vF,vN,vC))
     {
       return false;
     }
@@ -163,5 +163,4 @@ template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Ei
 template bool igl::read_triangle_mesh<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&);
-template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 43 - 0
include/igl/writeOFF.cpp

@@ -33,6 +33,47 @@ IGL_INLINE bool igl::writeOFF(
   return true;
 }
 
+// write mesh and colors-by-vertex to an ascii off file
+template <typename DerivedV, typename DerivedF, typename DerivedC>
+IGL_INLINE bool igl::writeOFF(
+  const std::string fname,
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::PlainObjectBase<DerivedC>& C)
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(V.cols() == 3 && "V should have 3 columns");
+  assert(C.cols() == 3 && "C should have 3 columns");
+
+  if(V.rows() != C.rows())
+  {
+    fprintf(stderr,"IOError: writeOFF() Only color per vertex supported. V and C should have same size.\n");
+    return false;
+  }
+
+  ofstream s(fname);
+  if(!s.is_open())
+  {
+    fprintf(stderr,"IOError: writeOFF() could not open %s\n",fname.c_str());
+    return false;
+  }
+
+  //Check if RGB values are in the range [0..1] or [0..255]
+  int rgbScale = (C.maxCoeff() <= 1.0)?255:1;
+  Eigen::MatrixXd RGB = rgbScale * C;
+
+  s<< "COFF\n"<<V.rows()<<" "<<F.rows()<<" 0\n";
+  for (unsigned i=0; i< V.rows(); i++)
+  {
+    s <<V.row(i).format(IOFormat(FullPrecision,DontAlignCols," "," ","","",""," "));
+    s << unsigned(RGB(i,0)) << " " << unsigned(RGB(i,1)) << " " << unsigned(RGB(i,2)) << " 255\n";
+  }
+
+  s<<(F.array()).format(IOFormat(FullPrecision,DontAlignCols," ","\n","3 ","","","\n"));
+  return true;
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
@@ -44,4 +85,6 @@ template bool igl::writeOFF<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix
 template bool igl::writeOFF<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
 template bool igl::writeOFF<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
 template bool igl::writeOFF<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&);
+template bool igl::writeOFF<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&);
+template bool igl::writeOFF<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&);
 #endif

+ 22 - 0
include/igl/writeOFF.h

@@ -14,6 +14,28 @@
 
 namespace igl 
 {
+  //Export geometry and colors-by-vertex
+  // Export a mesh from an ascii OFF file, filling in vertex positions.
+  // Only triangle meshes are supported
+  //
+  // Templates:
+  //   Scalar  type for positions and vectors (will be read as double and cast
+  //     to Scalar)
+  //   Index  type for indices (will be read as int and cast to Index)
+  // Inputs:
+  //  str  path to .off output file
+  //   V  #V by 3 mesh vertex positions
+  //   F  #F by 3 mesh indices into V
+  //   C  double matrix of rgb values per vertex #V by 3
+  // Outputs:
+  // Returns true on success, false on errors
+  template <typename DerivedV, typename DerivedF, typename DerivedC>
+  IGL_INLINE bool writeOFF(
+    const std::string str,
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const Eigen::PlainObjectBase<DerivedC>& C);
+
   template <typename DerivedV, typename DerivedF>
   IGL_INLINE bool writeOFF(
     const std::string str,