Răsfoiți Sursa

VBO (Vertex buffer object) handlers for eigen style V and F, normalize vector lists, compute normals

Former-commit-id: 2f788a9fe6901035ddc419d3c6cf6199d3f91dfd
jalec 13 ani în urmă
părinte
comite
843d26c2be
8 a modificat fișierele cu 358 adăugiri și 2 ștergeri
  1. 65 0
      create_index_vbo.h
  2. 85 0
      create_mesh_vbo.h
  3. 65 0
      create_vector_vbo.h
  4. 2 0
      examples/pathinfo/input.txt
  5. 36 0
      normalize_rows.h
  6. 49 0
      per_face_normals.h
  7. 54 0
      per_vertex_normals.h
  8. 2 2
      readOFF.h

+ 65 - 0
create_index_vbo.h

@@ -0,0 +1,65 @@
+#ifndef IGL_CREATE_INDEX_VBO
+#define IGL_CREATE_INDEX_VBO
+// NOTE: It wouldn't be so hard to template this using Eigen's templates
+
+#include <Eigen/Core>
+
+#if __APPLE__
+#  include <OpenGL/gl.h>
+#else
+#  include <GL/gl.h>
+#endif
+
+// Create a VBO (Vertex Buffer Object) for a list of indices:
+// GL_ELEMENT_ARRAY_BUFFER_ARB for the triangle indices (F)
+namespace igl
+{
+
+  // Inputs:
+  //   F  #F by 3 eigen Matrix of face (triangle) indices
+  // Outputs:
+  //   F_vbo_id  buffer id for face indices
+  //
+  void create_index_vbo(
+    const Eigen::MatrixXi & F,
+    GLuint & F_vbo_id);
+}
+
+// Implementation
+
+// http://www.songho.ca/opengl/gl_vbo.html#create
+void igl::create_index_vbo(
+  const Eigen::MatrixXi & F,
+  GLuint & F_vbo_id)
+{
+  // Generate Buffers
+  glGenBuffersARB(1,&F_vbo_id);
+  // Bind Buffers
+  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,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)
+  {
+    glBufferDataARB(
+      GL_ELEMENT_ARRAY_BUFFER_ARB,
+      sizeof(double)*F.size(),
+      F.data(),
+      GL_STATIC_DRAW_ARB);
+  }else
+  {
+    // Create temporary copy of transpose
+    Eigen::MatrixXi FT = F.transpose();
+    // If its column major then we need to temporarily store a transpose
+    glBufferDataARB(
+      GL_ELEMENT_ARRAY_BUFFER_ARB,
+      sizeof(double)*F.size(),
+      FT.data(),
+      GL_STATIC_DRAW_ARB);
+  }
+  // bind with 0, so, switch back to normal pointer operation
+  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+}
+
+#endif
+

+ 85 - 0
create_mesh_vbo.h

@@ -0,0 +1,85 @@
+#ifndef IGL_CREATE_MESH_VBO
+#define IGL_CREATE_MESH_VBO
+// NOTE: It wouldn't be so hard to template this using Eigen's templates
+
+#include <Eigen/Core>
+
+#if __APPLE__
+#  include <OpenGL/gl.h>
+#else
+#  include <GL/gl.h>
+#endif
+
+// Create a VBO (Vertex Buffer Object) for a mesh. Actually two VBOs: one 
+// GL_ARRAY_BUFFER_ARB for the vertex positions (V) and one
+// GL_ELEMENT_ARRAY_BUFFER_ARB for the triangle indices (F)
+namespace igl
+{
+
+  // Inputs:
+  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
+  //   F  #F by 3 eigne Matrix of face (triangle) indices
+  // Outputs:
+  //   V_vbo_id  buffer id for vertex positions
+  //   F_vbo_id  buffer id for face indices
+  //
+  // NOTE: when using glDrawElements VBOs for V and F using MatrixXd and
+  // MatrixXi will have types GL_DOUBLE and GL_UNSIGNED_INT respectively
+  //
+  void create_mesh_vbo(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    GLuint & V_vbo_id,
+    GLuint & F_vbo_id);
+
+  // Inputs:
+  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
+  //   F  #F by 3 eigne Matrix of face (triangle) indices
+  //   N  #V by 3 eigen Matrix of mesh vertex 3D normals
+  // Outputs:
+  //   V_vbo_id  buffer id for vertex positions
+  //   F_vbo_id  buffer id for face indices
+  //   N_vbo_id  buffer id for vertex positions
+  void create_mesh_vbo(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const Eigen::MatrixXd & N,
+    GLuint & V_vbo_id,
+    GLuint & F_vbo_id,
+    GLuint & N_vbo_id);
+
+}
+
+// Implementation
+#include "create_vector_vbo.h"
+#include "create_index_vbo.h"
+
+// http://www.songho.ca/opengl/gl_vbo.html#create
+void igl::create_mesh_vbo(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  GLuint & V_vbo_id,
+  GLuint & F_vbo_id)
+{
+  // Create VBO for vertex position vectors
+  create_vector_vbo(V,V_vbo_id);
+  // Create VBO for face index lists
+  create_index_vbo(F,F_vbo_id);
+}
+
+// http://www.songho.ca/opengl/gl_vbo.html#create
+void igl::create_mesh_vbo(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & N,
+  GLuint & V_vbo_id,
+  GLuint & F_vbo_id,
+  GLuint & N_vbo_id)
+{
+  // Create VBOs for faces and vertices
+  create_mesh_vbo(V,F,V_vbo_id,F_vbo_id);
+  // Create VBO for normal vectors
+  create_vector_vbo(N,N_vbo_id);
+}
+
+#endif

+ 65 - 0
create_vector_vbo.h

@@ -0,0 +1,65 @@
+#ifndef IGL_CREATE_VECTOR_VBO
+#define IGL_CREATE_VECTOR_VBO
+// NOTE: It wouldn't be so hard to template this using Eigen's templates
+
+#include <Eigen/Core>
+
+#if __APPLE__
+#  include <OpenGL/gl.h>
+#else
+#  include <GL/gl.h>
+#endif
+
+// Create a VBO (Vertex Buffer Object) for a list of vectors:
+// GL_ARRAY_BUFFER_ARB for the vectors (V)
+namespace igl
+{
+
+  // Inputs:
+  //   V  #V by 3 eigen Matrix of vertex 3D positions
+  // Outputs:
+  //   V_vbo_id  buffer id for vectors
+  //
+  void create_vector_vbo(
+    const Eigen::MatrixXd & V,
+    GLuint & V_vbo_id);
+}
+
+// Implementation
+
+// http://www.songho.ca/opengl/gl_vbo.html#create
+void igl::create_vector_vbo(
+  const Eigen::MatrixXd & V,
+  GLuint & V_vbo_id)
+{
+  // Generate Buffers
+  glGenBuffersARB(1,&V_vbo_id);
+  // Bind Buffers
+  glBindBufferARB(GL_ARRAY_BUFFER_ARB,V_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(V.Options & Eigen::RowMajor)
+  {
+    glBufferDataARB(
+      GL_ARRAY_BUFFER_ARB,
+      sizeof(double)*V.size(),
+      V.data(),
+      GL_STATIC_DRAW_ARB);
+  }else
+  {
+    // Create temporary copy of transpose
+    Eigen::MatrixXd VT = V.transpose();
+    // If its column major then we need to temporarily store a transpose
+    glBufferDataARB(
+      GL_ARRAY_BUFFER_ARB,
+      sizeof(double)*V.size(),
+      VT.data(),
+      GL_STATIC_DRAW_ARB);
+  }
+  // bind with 0, so, switch back to normal pointer operation
+  glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+}
+
+#endif
+

+ 2 - 0
examples/pathinfo/input.txt

@@ -2,6 +2,8 @@
 //
 /foo
 /foo/
+/foo//
+/foo/./
 /foo/bar
 /foo/bar.
 /foo/bar.txt

+ 36 - 0
normalize_rows.h

@@ -0,0 +1,36 @@
+#ifndef IGL_NORMALIZE_ROWS_H
+#define IGL_NORMALIZE_ROWS_H
+#include <Eigen/Core>
+
+namespace igl
+{
+  // Normalize the rows in A so that their lengths are each 1 and place the new
+  // entries in B
+  // Inputs:
+  //   A  #rows by k input matrix
+  // Outputs:
+  //   B  #rows by k input matrix, can be the same as A
+  void normalize_rows(const Eigen::MatrixXd & A, Eigen::MatrixXd & B);
+}
+
+void igl::normalize_rows(const Eigen::MatrixXd & A, Eigen::MatrixXd & B)
+{
+  // loop over rows
+  for(int i = 0; i < A.rows();i++)
+  {
+    double length = 0;
+    // loop over cols
+    for(int j = 0; j < A.cols();j++)
+    {
+      length += A(i,j)*A(i,j);
+    }
+    length = sqrt(length);
+    // loop over cols
+    for(int j = 0; j < A.cols();j++)
+    {
+      B(i,j) = A(i,j) / length;
+    }
+  }
+}
+
+#endif

+ 49 - 0
per_face_normals.h

@@ -0,0 +1,49 @@
+#ifndef IGL_PER_FACE_NORMALS_H
+#define IGL_PER_FACE_NORMALS_H
+#include <Eigen/Core>
+namespace igl
+{
+  // Compute face normals via vertex position list, face list
+  // Inputs:
+  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
+  //   F  #F by 3 eigne Matrix of face (triangle) indices
+  // Output:
+  //   N  #F by 3 eigen Matrix of mesh face (triangle) 3D normals
+  void per_face_normals(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    Eigen::MatrixXd & N);
+}
+// Implementation
+
+void igl::per_face_normals(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  Eigen::MatrixXd & N)
+{
+  N = Eigen::MatrixXd(F.rows(),3);
+  // loop over faces
+  for(int i = 0; i < F.rows();i++)
+  {
+    float v1[3];
+    v1[0] = V(F(i,1),0) - V(F(i,0),0);
+    v1[1] = V(F(i,1),1) - V(F(i,0),1);
+    v1[2] = V(F(i,1),2) - V(F(i,0),2);
+    float v2[3];
+    v2[0] = V(F(i,2),0) - V(F(i,0),0);
+    v2[1] = V(F(i,2),1) - V(F(i,0),1);
+    v2[2] = V(F(i,2),2) - V(F(i,0),2);
+    N(i,0) = v1[1]*v2[2] - v1[2]*v2[1];
+    N(i,1) = -(v1[0]*v2[2] - v1[2]*v2[0]);
+    N(i,2) = v1[0]*v2[1] - v1[1]*v2[0];
+    float length = sqrt(
+      N(i,0)*N(i,0) +
+      N(i,1)*N(i,1) +
+      N(i,2)*N(i,2));
+    N(i,0) /= length;
+    N(i,1) /=  length;
+    N(i,2) /=  length;
+  }
+}
+
+#endif

+ 54 - 0
per_vertex_normals.h

@@ -0,0 +1,54 @@
+#ifndef IGL_PER_VERTEX_NORMALS_H
+#define IGL_PER_VERTEX_NORMALS_H
+#include <Eigen/Core>
+namespace igl
+{
+  // Compute vertex normals via vertex position list, face list
+  // Inputs:
+  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
+  //   F  #F by 3 eigne Matrix of face (triangle) indices
+  // Output:
+  //   N  #V by 3 eigen Matrix of mesh vertex 3D normals
+  void per_vertex_normals(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    Eigen::MatrixXd & N);
+}
+
+// Implementation
+#include "per_face_normals.h"
+#include "normalize_rows.h"
+
+void igl::per_vertex_normals(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  Eigen::MatrixXd & N)
+{
+  Eigen::MatrixXd PFN;
+  igl::per_face_normals(V,F,PFN);
+
+  N = Eigen::MatrixXd(V.rows(),3);
+  // loop over vertices, setting normalize to 0
+  for(int i = 0; i < N.rows();i++)
+  {
+    N(i,0) = 0;
+    N(i,1) = 0;
+    N(i,2) = 0;
+  }
+
+  // loop over faces
+  for(int i = 0; i < F.rows();i++)
+  {
+    // throw normal at each corner
+    for(int j = 0; j < 3;j++)
+    {
+      N(F(i,j),0) += PFN(i,0);
+      N(F(i,j),1) += PFN(i,1);
+      N(F(i,j),2) += PFN(i,2);
+    }
+  }
+  // normalize each row
+  igl::normalize_rows(N,N);
+}
+
+#endif

+ 2 - 2
readOFF.h

@@ -6,8 +6,8 @@
 // History:
 //  return type changed from void to bool  Alec 18 Sept 2011
 
-#ifndef READOFF_H
-#define READOFF_H
+#ifndef IGL_READOFF_H
+#define IGL_READOFF_H
 
 #include <Eigen/Core>
 #include <string>