Example #1
0
// http://www.songho.ca/opengl/gl_vbo.html#create
IGL_INLINE void igl::opengl::create_index_vbo(
  const Eigen::MatrixXi & F,
  GLuint & F_vbo_id)
{
  // Generate Buffers
  glGenBuffers(1,&F_vbo_id);
  // Bind Buffers
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,F_vbo_id);
  // Copy data to buffers
  // We expect a matrix with each vertex position on a row, we then want to
  // pass this data to OpenGL reading across rows (row-major)
  if(F.Options & Eigen::RowMajor)
  {
    glBufferData(
      GL_ELEMENT_ARRAY_BUFFER,
      sizeof(int)*F.size(),
      F.data(),
      GL_STATIC_DRAW);
  }else
  {
    // Create temporary copy of transpose
    Eigen::MatrixXi FT = F.transpose();
    // If its column major then we need to temporarily store a transpose
    glBufferData(
      GL_ELEMENT_ARRAY_BUFFER,
      sizeof(int)*F.size(),
      FT.data(),
      GL_STATIC_DRAW);
  }
  // bind with 0, so, switch back to normal pointer operation
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
Example #2
0
void BuildNJTree::configure(Eigen::MatrixXi& IDs, int numOccupiedNodes) {
	numJoints = (IDs.size()+2)/2;
	graph = Graph(numJoints);
	name = get(vertex_name, graph);
	newNodesIndex = numJoints + numOccupiedNodes;
	int i = 0;
	VertexIterator vi, vend;
	for (tie(vi, vend) = vertices(graph); vi != vend; ++vi, ++i) {
		name[*vi] = IDs(i);
	}
}
Example #3
0
void parse_rhs(
  const int nrhs, 
  const mxArray *prhs[], 
  Eigen::MatrixXd & V,
  Eigen::MatrixXi & F,
  Eigen::MatrixXd & P,
  Eigen::MatrixXd & N,
  int & num_samples)
{
  using namespace std;
  if(nrhs < 5)
  {
    mexErrMsgTxt("nrhs < 5");
  }

  const int dim = mxGetN(prhs[0]);
  if(dim != 3)
  {
    mexErrMsgTxt("Mesh vertex list must be #V by 3 list of vertex positions");
  }
  if(dim != (int)mxGetN(prhs[1]))
  {
   mexErrMsgTxt("Mesh facet size must be 3");
  }
  if(mxGetN(prhs[2]) != dim)
  {
    mexErrMsgTxt("Point list must be #P by 3 list of origin locations");
  }
  if(mxGetN(prhs[3]) != dim)
  {
    mexErrMsgTxt("Normal list must be #P by 3 list of origin normals");
  }
  if(mxGetN(prhs[4]) != 1 || mxGetM(prhs[4]) != 1)
  {
    mexErrMsgTxt("Number of samples must be scalar.");
  }


  V.resize(mxGetM(prhs[0]),mxGetN(prhs[0]));
  copy(mxGetPr(prhs[0]),mxGetPr(prhs[0])+V.size(),V.data());
  F.resize(mxGetM(prhs[1]),mxGetN(prhs[1]));
  copy(mxGetPr(prhs[1]),mxGetPr(prhs[1])+F.size(),F.data());
  F.array() -= 1;
  P.resize(mxGetM(prhs[2]),mxGetN(prhs[2]));
  copy(mxGetPr(prhs[2]),mxGetPr(prhs[2])+P.size(),P.data());
  N.resize(mxGetM(prhs[3]),mxGetN(prhs[3]));
  copy(mxGetPr(prhs[3]),mxGetPr(prhs[3])+N.size(),N.data());
  if(*mxGetPr(prhs[4]) != (int)*mxGetPr(prhs[4]))
  {
    mexErrMsgTxt("Number of samples should be non negative integer.");
  }
  num_samples = (int) *mxGetPr(prhs[4]);
}
Example #4
0
IGL_INLINE void igl::adjacency_matrix(
  const Eigen::MatrixXi & F, 
  Eigen::SparseMatrix<T>& A)
{
  using namespace std;
  using namespace Eigen;

  typedef Triplet<T> IJV;
  vector<IJV > ijv;
  ijv.reserve(F.size()*2);
  // Loop over faces
  for(int i = 0;i<F.rows();i++)
  {
    // Loop over this face
    for(int j = 0;j<F.cols();j++)
    {
      // Get indices of edge: s --> d
      int s = F(i,j);
      int d = F(i,(j+1)%F.cols());
      ijv.push_back(IJV(s,d,1));
      ijv.push_back(IJV(d,s,1));
    }
  }

  const int n = F.maxCoeff()+1;
  A.resize(n,n);
  switch(F.cols())
  {
    case 3:
      A.reserve(6*(F.maxCoeff()+1));
      break;
    case 4:
      A.reserve(26*(F.maxCoeff()+1));
      break;
  }
  A.setFromTriplets(ijv.begin(),ijv.end());

  // Force all non-zeros to be one

  // Iterate over outside
  for(int k=0; k<A.outerSize(); ++k)
  {
    // Iterate over inside
    for(typename Eigen::SparseMatrix<T>::InnerIterator it (A,k); it; ++it)
    {
      assert(it.value() != 0);
      A.coeffRef(it.row(),it.col()) = 1;
    }
  }
}
Example #5
0
// Read a surface mesh from a {.obj|.off|.mesh} files
// Inputs:
//   mesh_filename  path to {.obj|.off|.mesh} file
// Outputs:
//   V  #V by 3 list of mesh vertex positions
//   F  #F by 3 list of triangle indices
// Returns true only if successfuly able to read file
bool load_mesh_from_file(
  const std::string mesh_filename,
  Eigen::MatrixXd & V,
  Eigen::MatrixXi & F)
{
  using namespace std;
  using namespace igl;
  using namespace Eigen;
  string dirname, basename, extension, filename;
  pathinfo(mesh_filename,dirname,basename,extension,filename);
  transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
  bool success = false;
  if(extension == "obj")
  {
    success = readOBJ(mesh_filename,V,F);
  }else if(extension == "off")
  {
    success = readOFF(mesh_filename,V,F);
  }else if(extension == "mesh")
  {
    // Unused Tets read from .mesh file
    MatrixXi Tets;
    success = readMESH(mesh_filename,V,Tets,F);
    // We're not going to use any input tets. Only the surface
    if(Tets.size() > 0 && F.size() == 0)
    {
      // If Tets read, but no faces then use surface of tet volume
    }else
    {
      // Rearrange vertices so that faces come first
      VectorXi IM;
      faces_first(V,F,IM);
      // Dont' bother reordering Tets, but this is how one would:
      //Tets = 
      //  Tets.unaryExpr(bind1st(mem_fun( static_cast<VectorXi::Scalar&
      //  (VectorXi::*)(VectorXi::Index)>(&VectorXi::operator())),
      //  &IM)).eval();
      // Don't throw away any interior vertices, since user may want weights
      // there
    }
  }else
  {
    cerr<<"Error: Unknown shape file format extension: ."<<extension<<endl;
    return false;
  }
  return success;
}
Example #6
0
IGL_INLINE void igl::triangle_fan(
  const Eigen::MatrixXi & E,
  Eigen::MatrixXi & cap)
{
  using namespace std;
  using namespace Eigen;

  // Handle lame base case
  if(E.size() == 0)
  {
    cap.resize(0,E.cols()+1);
    return;
  }
  // "Triangulate" aka "close" the E trivially with facets
  // Note: in 2D we need to know if E endpoints are incoming or
  // outgoing (left or right). Thus this will not work.
  assert(E.cols() == 2);
  // Arbitrary starting vertex
  //int s = E(int(((double)rand() / RAND_MAX)*E.rows()),0);
  int s = E(rand()%E.rows(),0);
  vector<vector<int> >  lcap;
  for(int i = 0;i<E.rows();i++)
  {
    // Skip edges incident on s (they would be zero-area)
    if(E(i,0) == s || E(i,1) == s)
    {
      continue;
    }
    vector<int> e(3);
    e[0] = s;
    e[1] = E(i,0);
    e[2] = E(i,1);
    lcap.push_back(e);
  }
  list_to_matrix(lcap,cap);
}
Example #7
0
IGL_INLINE void igl::draw_mesh(
  const Eigen::MatrixXd & V,
  const Eigen::MatrixXi & F,
  const Eigen::MatrixXd & N,
  const Eigen::MatrixXi & NF,
  const Eigen::MatrixXd & C,
  const Eigen::MatrixXd & TC,
  const Eigen::MatrixXi & TF,
  const Eigen::MatrixXd & W,
  const GLuint W_index,
  const Eigen::MatrixXi & WI,
  const GLuint WI_index)
{
  using namespace std;
  using namespace Eigen;
  const int rF = F.rows();
  const int cF = F.cols();
  const int cC = C.cols();
  const int rC = C.rows();
  const int cW = W.cols();
  const int rW = W.rows();
  const int rV = V.rows();
  const int rTC = TC.rows();
  const int rTF = TF.rows();
  const int rNF = NF.rows();
  const int rN = N.rows();

  if(F.size() > 0)
  {
    assert(F.maxCoeff() < V.rows());
    assert(V.cols() == 3);
    assert(rC == rV || rC == rF || rC == rF*3 || rC==1 || C.size() == 0);
    assert(C.cols() == 3 || C.size() == 0);
    assert(N.cols() == 3 || N.size() == 0);
    assert(TC.cols() == 2 || TC.size() == 0);
    assert(cF == 3 || cF == 4);
    assert(TF.size() == 0 || TF.cols() == F.cols());
    assert(NF.size() == 0 || NF.cols() == NF.cols());
  }
  if(W.size()>0)
  {
    assert(W.rows() == V.rows());
    assert(WI.rows() == V.rows());
    assert(W.cols() == WI.cols());
  }

  switch(F.cols())
  {
    default:
    case 3:
      glBegin(GL_TRIANGLES);
      break;
    case 4:
      glBegin(GL_QUADS);
      break;
  }
  // loop over faces
  for(int i = 0; i<rF;i++)
  {
    // loop over corners of triangle
    for(int j = 0;j<cF;j++)
    {

      int tc = -1;
      if(rTF != 0)
      {
        tc = TF(i,j);
      } else if(rTC == 1)
      {
        tc = 0;
      }else if(rTC == rV)
      {
        tc = F(i,j);
      }else if(rTC == rF*cF)
      {
        tc = i*cF + j;
      }else if(rTC == rF)
      {
        tc = i;
      }else
      {
        assert(TC.size() == 0);
      }

      // RGB(A)
      Matrix<MatrixXd::Scalar,1,Dynamic> color;
      if(rC == 1)
      {
        color = C.row(0);
      }else if(rC == rV)
      {
        color = C.row(F(i,j));
      }else if(rC == rF*cF)
      {
        color = C.row(i*cF+j);
      }else if(rC == rF)
      {
        color = C.row(i);
      }else
      {
        assert(C.size() == 0);
      }

      int n = -1;
      if(rNF != 0)
      {
        n = NF(i,j); // indexed normals
      } else if(rN == 1) 
      {
        n = 0; // uniform normals
      }else if(rN == rF)
      {
        n = i; // face normals
      }else if(rN == rV)
      {
        n = F(i,j); // vertex normals
      }else if(rN == rF*cF)
      {
        n = i*cF + j; // corner normals
      }else
      {
        assert(N.size() == 0);
      }

      {
        if(rW>0 && W_index !=0 && WI_index != 0)
        {
          int weights_left = cW;
          while(weights_left != 0)
          {
            int pass_size = std::min(4,weights_left);
            int weights_already_passed = cW-weights_left;
            // Get attribute location of next 4 weights
            int pass_W_index = W_index + weights_already_passed/4;
            int pass_WI_index = WI_index + weights_already_passed/4;
            switch(pass_size)
            {
              case 1:
                glVertexAttrib1d(
                  pass_W_index,
                  W(F(i,j),0+weights_already_passed));
                glVertexAttrib1d(
                  pass_WI_index,
                  WI(F(i,j),0+weights_already_passed));
                break;
              case 2:
                glVertexAttrib2d(
                  pass_W_index,
                  W(F(i,j),0+weights_already_passed),
                  W(F(i,j),1+weights_already_passed));
                glVertexAttrib2d(
                  pass_WI_index,
                  WI(F(i,j),0+weights_already_passed),
                  WI(F(i,j),1+weights_already_passed));
                break;
              case 3:
                glVertexAttrib3d(
                  pass_W_index,
                  W(F(i,j),0+weights_already_passed),
                  W(F(i,j),1+weights_already_passed),
                  W(F(i,j),2+weights_already_passed));
                glVertexAttrib3d(
                  pass_WI_index,
                  WI(F(i,j),0+weights_already_passed),
                  WI(F(i,j),1+weights_already_passed),
                  WI(F(i,j),2+weights_already_passed));
                break;
              default:
                glVertexAttrib4d(
                  pass_W_index,
                  W(F(i,j),0+weights_already_passed),
                  W(F(i,j),1+weights_already_passed),
                  W(F(i,j),2+weights_already_passed),
                  W(F(i,j),3+weights_already_passed));
                glVertexAttrib4d(
                  pass_WI_index,
                  WI(F(i,j),0+weights_already_passed),
                  WI(F(i,j),1+weights_already_passed),
                  WI(F(i,j),2+weights_already_passed),
                  WI(F(i,j),3+weights_already_passed));
                break;
            }
            weights_left -= pass_size;
          }
        }
        if(tc != -1)
        {
          glTexCoord2d(TC(tc,0),TC(tc,1));
        }
        if(rC>0)
        {
          switch(cC)
          {
            case 3:
              glColor3dv(color.data());
              break;
            case 4:
              glColor4dv(color.data());
              break;
            default:
              break;
          }
        }
        if(n != -1)
        {
          glNormal3d(N(n,0),N(n,1),N(n,2));
        }
        glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
      }
    }
  }
  glEnd();
}
Example #8
0
void display()
{
  if(sorted_F.size() != F.size())
  {
    mouse(0,1,-1,-1);
  }
  //using namespace Eigen;
  using namespace igl;
  using namespace std;
  glClearColor(BG[0],BG[1],BG[2],0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  // All smooth points
  glEnable( GL_POINT_SMOOTH );

  lights();
  push_scene();
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);
  glEnable(GL_NORMALIZE);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  //glEnable(GL_CULL_FACE);
  //glCullFace(GL_BACK);

  // Draw a nice floor
  push_object();
  glEnable(GL_LIGHTING);
  glTranslated(0,V.col(1).minCoeff(),0);
  glScaled(2*bbd,2*bbd,2*bbd);
  glTranslated(0,-1000*FLOAT_EPS,0);
  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);
  igl::opengl2::draw_floor();
  pop_object();

  glDisable(GL_CULL_FACE);
  if(trackball_on)
  {
    glEnable(GL_COLOR_MATERIAL);
    glDisable(GL_LIGHTING);
  }else
  {
    float front[4];
    copy(GOLD_DIFFUSE,GOLD_DIFFUSE+3,front);
    float back[4];
    //copy(FAST_GREEN_DIFFUSE,FAST_GREEN_DIFFUSE+3,back);
    copy(GOLD_DIFFUSE,GOLD_DIFFUSE+3,back);
    float amb[4];
    copy(SILVER_AMBIENT,SILVER_AMBIENT+3,amb);
    float spec[4];
    copy(SILVER_SPECULAR,SILVER_SPECULAR+3,spec);
    front[3] = back[3] = amb[3] = spec[3] = alpha;
    // Set material properties
    glDisable(GL_COLOR_MATERIAL);
    glMaterialfv(GL_FRONT, GL_AMBIENT,  amb);
    glMaterialfv(GL_FRONT, GL_DIFFUSE,  front);
    glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
    glMaterialf (GL_FRONT, GL_SHININESS, 128);
    glMaterialfv(GL_BACK, GL_AMBIENT,  amb);
    glMaterialfv(GL_BACK, GL_DIFFUSE,  back);
    glMaterialfv(GL_BACK, GL_SPECULAR, spec);
    glMaterialf (GL_BACK, GL_SHININESS, 128);
    glEnable(GL_LIGHTING);
  }

  push_object();
  // Draw the model
  igl::opengl2::draw_mesh(V,sorted_F,sorted_N,C);
  pop_object();

  pop_scene();

  igl::opengl::report_gl_error();
  glutSwapBuffers();
  glutPostRedisplay();
}