Browse Source

dmat matrix file format reader, writer and example
sort, reorder vectors and eigen (dynamic) matrices like matlabs sort (with example)
function to retrieve shader uniform names and locations,
function to report open gl errors to stderr
example that prints opengl version and glsl version,


Former-commit-id: 729936710fd24a26f7467622109c2c8c8110cd0a

jalec 13 years ago
parent
commit
fa03862cee

+ 23 - 0
examples/dmat/Makefile

@@ -0,0 +1,23 @@
+
+.PHONY: all
+
+all: example
+
+.PHONY: example
+
+igl_lib=../../
+eigen=/usr/local/include/eigen3
+
+CFLAGS=-g
+inc=-I$(igl_lib) -I$(eigen)
+lib=
+
+example: example.o
+	g++ $(CFLAGS) -o example example.o $(lib)
+	rm example.o
+
+example.o: example.cpp
+	g++ $(CFLAGS) -c example.cpp -o example.o $(inc)
+clean:
+	rm -f example.o
+	rm -f example

+ 22 - 0
examples/dmat/README

@@ -0,0 +1,22 @@
+This is a simple example program that shows how to use the readDMAT and
+writeDMAT functions of the igl library
+
+
+To Build:
+  make
+
+To Run:
+  ./example [input path] [output path]
+
+Example Run #1:
+  Issuing:
+    ./example example.dmat output.dmat
+    cat output.dmat
+  should produce:
+    3 2
+    1
+    4
+    2
+    5
+    3
+    6

+ 18 - 0
examples/dmat/example.cpp

@@ -0,0 +1,18 @@
+#include <Eigen/Core>
+#include "readDMAT.h"
+#include "writeDMAT.h"
+using namespace igl;
+#include <cstdio>
+
+int main(int argc, char * argv[])
+{
+  if(argc <= 2)
+  {
+    printf("USAGE:\n  ./example [input path] [output path]\n");
+    return 1;
+  }
+  Eigen::MatrixXd M;
+  readDMAT(argv[1],M);
+  writeDMAT(argv[2],M);
+  return 0;
+}

+ 7 - 0
examples/dmat/example.dmat

@@ -0,0 +1,7 @@
+3 2
+1
+4
+2
+5
+3
+6

+ 22 - 0
examples/glslversion/Makefile

@@ -0,0 +1,22 @@
+
+.PHONY: all
+
+all: example
+
+.PHONY: example
+
+igl_lib=../../
+
+CFLAGS=-g
+inc=-I$(igl_lib)
+lib=-framework OpenGL -framework GLUT
+
+example: example.o
+	g++ $(CFLAGS) -o example example.o $(lib)
+	rm example.o
+
+example.o: example.cpp
+	g++ $(CFLAGS) -c example.cpp -o example.o $(inc)
+clean:
+	rm -f example.o
+	rm -f example

+ 15 - 0
examples/glslversion/README

@@ -0,0 +1,15 @@
+This is a simple example program that creates a dummy GLUT window to get a
+valid opengl context then print the glsl version string
+
+
+To Build:
+  make
+
+To Run:
+  ./example
+
+Example Run #1:
+  Issuing:
+    ./example
+  should produce something like:
+    GL_SHADING_LANGUAGE_VERSION: 1.20

+ 18 - 0
examples/glslversion/example.cpp

@@ -0,0 +1,18 @@
+#include <GLUT/glut.h>
+#include <cstdio>
+
+int main(int argc,char * argv[])
+{
+  // Make GLUT window just to get a valid OpenGL context
+  glutInit(&argc,argv);
+  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+  glutInitWindowSize(640, 480);
+  glutCreateWindow("Dummy");
+  glutCreateMenu(NULL);
+
+  printf("GL_VERSION: %s\n", 
+    glGetString(GL_VERSION));
+  printf("GL_SHADING_LANGUAGE_VERSION: %s\n", 
+    glGetString(GL_SHADING_LANGUAGE_VERSION));
+  return 0;
+}

+ 23 - 0
examples/sort/Makefile

@@ -0,0 +1,23 @@
+
+.PHONY: all
+
+all: example
+
+.PHONY: example
+
+igl_lib=../../
+eigen=/usr/local/include/eigen3/
+
+CFLAGS=-g
+inc=-I$(igl_lib) -I$(eigen)
+lib=
+
+example: example.o
+	g++ $(CFLAGS) -o example example.o $(lib)
+	rm example.o
+
+example.o: example.cpp
+	g++ $(CFLAGS) -c example.cpp -o example.o $(inc)
+clean:
+	rm -f example.o
+	rm -f example

+ 9 - 0
examples/sort/README

@@ -0,0 +1,9 @@
+This is a simple example program that shows how to use the sort function on
+eigen matrices like matlab's sort function
+
+
+To Build:
+  make
+
+To Run:
+  ./example

+ 69 - 0
examples/sort/example.cpp

@@ -0,0 +1,69 @@
+// g++ -o main main.cpp -I. -I/usr/local/include/eigen3
+#include <Eigen/Core>
+#include <iostream>
+using namespace std;
+#include "sort.h"
+using namespace igl;
+
+
+template <typename T>
+void matlab_print(const string name, const T & X)
+{
+  cout<<name<<"=["<<endl<<X<<endl<<"];"<<endl;
+}
+
+int main(int argc, char * argv[])
+{
+  Eigen::MatrixXd X(2,3);
+  X << 3,5,2,1,3,8;
+  matlab_print("X",X);
+
+  // sort each row independently
+  int dim = 2;
+  // sort ascending order
+  int ascending = true;
+  // Sorted output matrix
+  Eigen::MatrixXd Y;
+  // sorted indices for sort dimension
+  Eigen::MatrixXi IX;
+  sort(X,dim,ascending,Y,IX);
+  matlab_print<Eigen::MatrixXd>("Y",Y);
+  matlab_print<Eigen::MatrixXi>("IX",IX);
+
+  // Verify that IX really does sort X into Y
+  int num_outer = (dim == 1 ? X.cols() : X.rows() );
+  // get number of rows (or columns)
+  int num_inner = (dim == 1 ? X.rows() : X.cols() );
+  bool verified = true;
+  for(int i = 0;i<num_outer;i++)
+  {
+    for(int j = 0;j<num_inner;j++)
+    {
+      if(dim == 1)
+      {
+        if( Y(j,i) != X(IX(j,i),i))
+        {
+          printf("Y(%d,%d) = %g != %g = X(%d,%d) = X(IX(%d,%d),%d)\n",
+            j,i,Y(j,i),X(IX(j,i),i),IX(j,i),i,j,i,i);
+          verified = false;
+        }
+      }else
+      {
+        if( Y(i,j) != X(i,IX(i,j)))
+        {
+          printf("Y(%d,%d) = %g != %g = X(%d,%d) = X(IX(%d,%d),%d)\n",
+            i,j,Y(i,j),X(i,IX(i,j)),IX(i,j),i,i,j,i);
+          verified = false;
+        }
+      }
+    }
+  }
+  if(verified)
+  {
+    printf("Sorting succeeded\n");
+  }else
+  {
+    printf("Sorting failed\n");
+  }
+  return (verified?0:1);
+}

+ 91 - 0
readDMAT.h

@@ -0,0 +1,91 @@
+#ifndef IGL_READDMAT_H
+#define IGL_READDMAT_H
+// .dmat is a simple ascii matrix file type, defined as follows. The first line
+// is always:
+// <#columns> <#rows>
+// Then the coefficients of the matrix are given separated by whitespace with
+// columns running fastest.
+//
+// Example:
+//   The matrix m = [1 2 3; 4 5 6];
+//   corresponds to a .dmat file containing:
+//   3 2
+//   1 4 2 5 3 6
+#include <Eigen/Core>
+#include <string>
+namespace igl
+{
+  // Read a matrix from an ascii dmat file
+  //
+  // Inputs:
+  //   file_name  path to .dmat file
+  // Outputs:
+  //   W  eigen matrix containing read-in coefficients
+  // Returns true on success, false on error
+  //
+  inline bool readDMAT(const std::string file_name, Eigen::MatrixXd & W);
+}
+
+// Implementation
+#include "verbose.h"
+#include <cstdio>
+
+inline bool igl::readDMAT(const std::string file_name, Eigen::MatrixXd & W)
+{
+  FILE * fp = fopen(file_name.c_str(),"r");
+  if(fp == NULL)
+  {
+    fclose(fp);
+    fprintf(stderr,"IOError: readDMAT() could not open %s...\n",file_name.c_str());
+    return false; 
+  }
+  // first line contains number of rows and number of columns
+  int num_cols, num_rows;
+  int res = fscanf(fp,"%d %d\n",&num_cols,&num_rows);
+  if(res != 2)
+  {
+    fclose(fp);
+    fprintf(stderr,"IOError: readDMAT() first row should be [num cols] [num rows]...\n");
+    return false;
+  }
+  verbose("Number of rows: %d\n",num_rows);
+  verbose("Number of cols: %d\n",num_cols);
+
+  // check that number of columns and rows are sane
+  if(num_cols < 0)
+  {
+    fclose(fp);
+    fprintf(stderr,"IOError: readDMAT() number of columns %d < 0\n",num_cols);
+    return false;
+  }
+  if(num_rows < 0)
+  {
+    fclose(fp);
+    fprintf(stderr,"IOError: readDMAT() number of rows %d < 0\n",num_rows);
+    return false;
+  }
+
+  // Resize output to fit matrix
+  W.resize(num_rows,num_cols);
+
+  // Loop over columns slowly
+  for(int j = 0;j < num_cols;j++)
+  {
+    // loop over rows (down columns) quickly
+    for(int i = 0;i < num_rows;i++)
+    {
+      if(fscanf(fp," %lg",&W(i,j)) != 1)
+      {
+        fclose(fp);
+        fprintf(
+          stderr,
+          "IOError: readDMAT() bad format after reading %d entries\n",
+          j*num_rows + i);
+        return false;
+      }
+    }
+  }
+  fclose(fp);
+  return true;
+}
+#endif

+ 37 - 0
reorder.h

@@ -0,0 +1,37 @@
+#ifndef IGL_REORDER_H
+#define IGL_REORDER_H
+
+namespace igl
+{
+  // Act like matlab's Y = X[I] for std vectors
+  // where I contains a vector of indices so that after,
+  // Y[j] = X[I[j]] for index j
+  // this implies that Y.size() == I.size()
+  // X and Y are allowed to be the same reference
+  template< class T >
+  inline void reorder(
+    const std::vector<T> & unordered,
+    std::vector<size_t> const & index_map,
+    std::vector<T> & ordered);
+}
+
+// Implementation
+
+// This implementation is O(n), but also uses O(n) extra memory
+template< class T >
+inline void igl::reorder(
+  const std::vector<T> & unordered,
+  std::vector<size_t> const & index_map,
+  std::vector<T> & ordered)
+{
+  // copy for the reorder according to index_map, because unsorted may also be
+  // sorted
+  std::vector<T> copy = unordered;
+  ordered.resize(index_map.size());
+  for(int i = 0; i<index_map.size();i++)
+  {
+    ordered[i] = copy[index_map[i]];
+  }
+}
+#endif
+

+ 35 - 0
report_gl_error.h

@@ -0,0 +1,35 @@
+#ifndef IGL_REPORT_GL_ERROR
+#define IGL_REPORT_GL_ERROR
+
+#ifdef __APPLE__
+#   include <OpenGL/gl.h>
+#   include <OpenGL/glu.h>
+#else
+#   include <GL/gl.h>
+#   include <GL/glu.h>
+#endif
+
+#include <cstdio>
+
+namespace igl
+{
+  // Print last OpenGL error to stderr
+  // Returns result of glGetError()
+  inline GLenum report_gl_error();
+}
+
+// Implementation
+#include "verbose.h"
+
+inline GLenum igl::report_gl_error()
+{
+  GLenum err = glGetError();
+  if(GL_NO_ERROR != err)
+  {
+    verbose("GL_ERROR: ");
+    fprintf(stderr,"%s\n",gluErrorString(err));
+  }
+  return err;
+}
+
+#endif

+ 65 - 0
shader_program_uniforms_map.h

@@ -0,0 +1,65 @@
+#ifndef IGL_SHADER_PROGRAM_UNIFORMS_MAP_H
+#define IGL_SHADER_PROGRAM_UNIFORMS_MAP_H
+#include <string>
+#include <map>
+
+#ifdef __APPLE__
+#   include <OpenGL/gl.h>
+#else
+#   include <GL/gl.h>
+#endif
+
+namespace igl
+{
+  // Builds a map of *active* uniform names as strings to their respective
+  // locations as GLuint.
+  // Input:
+  //   id  index id of the program to query 
+  // Output:
+  //   uniforms  map of names to locations
+  // Returns true on success, false on errors
+  void shader_program_uniforms_map(
+    const GLuint id, 
+    std::map<std::string,GLint> & uniforms);
+}
+
+// Implementation
+#include "verbose.h"
+#include "report_gl_error.h"
+
+void igl::shader_program_uniforms_map(
+  const GLuint id, 
+  std::map<std::string,GLint> & uniforms)
+{
+  // empty the map of previous contents
+  uniforms.clear();
+
+  // get number of active uniforms
+  GLint n = 200;
+  glGetProgramiv(id,GL_ACTIVE_UNIFORMS,&n);
+
+  // get max uniform name length
+  GLint max_name_length;
+  glGetProgramiv(id,GL_ACTIVE_UNIFORM_MAX_LENGTH,&max_name_length);
+
+  // buffer for name
+  GLchar * name = new GLchar[max_name_length];
+  // buffer for length
+  GLsizei length = 100;
+  GLenum type;
+  GLint size;
+
+  // loop over active uniforms getting each's name
+  for(GLuint u = 0;u < n;u++)
+  {
+    // I have no idea why glGetActiveUniformName doesn't work but
+    // glGetActiveUniform does...
+    //glGetActiveUniformName(id,u,max_name_length,&length,name);
+    glGetActiveUniform(id,u,max_name_length,&length,&size,&type,name);
+    // insert into map
+    uniforms[string(name)] = u;
+  }
+
+  delete[] name;
+}
+#endif

+ 151 - 0
sort.h

@@ -0,0 +1,151 @@
+#ifndef IGL_SORT_H
+#define IGL_SORT_H
+
+#include <vector>
+namespace igl
+{
+
+  // Sort the elements of a matrix X along a given dimension like matlabs sort
+  // function
+  //
+  // Templates:
+  //   T  should be a eigen matrix primitive type like int or double
+  // Inputs:
+  //   X  m by n matrix whose entries are to be sorted
+  //   dim  dimensional along which to sort:
+  //     1  sort each column (matlab default)
+  //     2  sort each row
+  //   ascending  sort ascending (true, matlab default) or descending (false)
+  // Outputs:
+  //   Y  m by n matrix whose entries are sorted
+  //   IX  m by n matrix of indices so that if dim = 1, then in matlab notation
+  //     for j = 1:n, Y(:,j) = X(I(:,j),j); end
+  template <typename T>
+  inline void sort(
+    const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & X,
+    const int dim,
+    const bool ascending,
+    Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & Y,
+    Eigen::MatrixXi & IX);
+
+  // Act like matlab's [Y,I] = SORT(X) for std library vectors
+  // Templates:
+  //   T  should be a class that implements the '<' comparator operator
+  // Input:
+  //   unsorted  unsorted vector
+  //   ascending  sort ascending (true, matlab default) or descending (false)
+  // Output:
+  //   sorted     sorted vector, allowed to be same as unsorted
+  //   index_map  an index map such that sorted[i] = unsorted[index_map[i]]
+  template <class T>
+  inline void sort(
+      const std::vector<T> &unsorted,
+      const bool ascending,
+      std::vector<T> &sorted,
+      std::vector<size_t> &index_map);
+
+}
+
+// Implementation
+#include <algorithm>
+#include "reorder.h"
+
+template <typename T>
+inline void igl::sort(
+  const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & X,
+  const int dim,
+  const bool ascending,
+  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & Y,
+  Eigen::MatrixXi & IX)
+{
+  // dim must be 2 or 1
+  assert(dim == 1 || dim == 2);
+  // Resize output
+  Y.resize(X.rows(),X.cols());
+  IX.resize(X.rows(),X.cols());
+  // idea is to process each column (or row) as a std vector
+  // get number of columns (or rows)
+  int num_outer = (dim == 1 ? X.cols() : X.rows() );
+  // get number of rows (or columns)
+  int num_inner = (dim == 1 ? X.rows() : X.cols() );
+  // loop over columns (or rows)
+  for(int i = 0; i<num_outer;i++)
+  {
+    // Unsorted index map for this column (or row)
+    std::vector<size_t> index_map(num_inner);
+    std::vector<T> data(num_inner);
+    for(int j = 0;j<num_inner;j++)
+    {
+      if(dim == 1)
+      {
+        data[j] = X(j,i);
+      }else
+      {
+        data[j] = X(i,j);
+      }
+    }
+    // sort this column (or row)
+    sort<T>(
+      data,
+      ascending,
+      data,
+      index_map);
+    // Copy into Y and IX
+    for(int j = 0;j<num_inner;j++)
+    {
+      if(dim == 1)
+      {
+        Y(j,i) = data[j];
+        IX(j,i) = index_map[j];
+      }else
+      {
+        Y(i,j) = data[j];
+        IX(i,j) = index_map[j];
+      }
+    }
+  }
+}
+
+// Comparison struct used by sort
+// http://bytes.com/topic/c/answers/132045-sort-get-index
+template<class T> struct index_cmp
+{
+  index_cmp(const T arr) : arr(arr) {}
+  bool operator()(const size_t a, const size_t b) const
+  {
+    return arr[a] < arr[b];
+  }
+  const T arr;
+};
+
+template <class T>
+inline void igl::sort(
+  const std::vector<T> & unsorted,
+  const bool ascending,
+  std::vector<T> & sorted,
+  std::vector<size_t> & index_map)
+{
+  // Original unsorted index map
+  index_map.resize(unsorted.size());
+  for(size_t i=0;i<unsorted.size();i++)
+  {
+    index_map[i] = i;
+  }
+  // Sort the index map, using unsorted for comparison
+  sort(
+    index_map.begin(),
+    index_map.end(),
+    index_cmp<const std::vector<T>& >(unsorted));
+
+  // if not ascending then reverse
+  if(!ascending)
+  {
+    std::reverse(index_map.begin(),index_map.end());
+  }
+  // make space for output without clobbering
+  sorted.resize(unsorted.size());
+  // reorder unsorted into sorted using index map
+  igl::reorder(unsorted,index_map,sorted);
+}
+
+#endif

+ 44 - 0
writeDMAT.h

@@ -0,0 +1,44 @@
+#ifndef IGL_WRITEDMAT_H
+#define IGL_WRITEDMAT_H
+// See writeDMAT.h for a description of the .dmat file type
+#include <Eigen/Core>
+#include <string>
+namespace igl
+{
+  // Write a matrix using ascii dmat file type
+  //
+  // Inputs:
+  //   file_name  path to .dmat file
+  //   W  eigen matrix containing to-be-written coefficients
+  // Returns true on success, false on error
+  //
+  inline bool writeDMAT(const std::string file_name, const Eigen::MatrixXd & W);
+}
+
+// Implementation
+#include <cstdio>
+
+inline bool igl::writeDMAT(const std::string file_name, const Eigen::MatrixXd & W)
+{
+  FILE * fp = fopen(file_name.c_str(),"w");
+  if(fp == NULL)
+  {
+    fclose(fp);
+    fprintf(stderr,"IOError: writeDMAT() could not open %s...",file_name.c_str());
+    return false; 
+  }
+  // first line contains number of rows and number of columns
+  fprintf(fp,"%d %d\n",(int)W.cols(),(int)W.rows());
+  // Loop over columns slowly
+  for(int j = 0;j < W.cols();j++)
+  {
+    // loop over rows (down columns) quickly
+    for(int i = 0;i < W.rows();i++)
+    {
+      fprintf(fp,"%lg\n",W(i,j));
+    }
+  }
+  fclose(fp);
+  return true;
+}
+#endif