Browse Source

explicit templates for xml (not quite working yet, but compiling)

Former-commit-id: 7b027561a16249bdb1fad6d6a2f763fd0c730364
Alec Jacobson (jalec 12 years ago
parent
commit
6ef83ce82d

+ 1 - 0
Makefile.conf

@@ -27,6 +27,7 @@ ifeq ($(IGL_USERNAME),ajx)
 	IGL_WITH_MATLAB=1
 	IGL_WITH_MOSEK=1
 	IGL_WITH_PNG=1
+	IGL_WITH_XML=1
 	# I don't use llvm
 #AFLAGS = -m64 -march="corei7-avx"
 	# msse4.2 is necessary for me to get embree to compile correctly

+ 23 - 9
include/igl/embree/EmbreeIntersector.cpp

@@ -70,39 +70,53 @@ igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
 ::intersectRay(
   const RowVector3& origin, 
   const RowVector3& direction, 
-  std::vector<embree::Hit > &hits) const
+  std::vector<embree::Hit > &hits,
+  int & num_rays) const
 {
   using namespace std;
+  num_rays = 0;
   hits.clear();
   embree::Vec3f o = toVec3f(origin);
   embree::Vec3f d = toVec3f(direction);
   int last_id0 = -1;
   double self_hits = 0;
-  const double eps = FLOAT_EPS*2.0;
+  // This epsilon is directly correleated to the number of missed hits, smaller
+  // means more accurate and slower
+  //const double eps = DOUBLE_EPS;
+  const double eps = FLOAT_EPS;
   while(true)
   {
-    //cout<<
-    //  o[0]<<" "<<o[1]<<" "<<o[2]<<" + t*"<<
-    //  d[0]<<" "<<d[1]<<" "<<d[2]<<" ---> "<<
-    //  endl;
+#ifdef VERBOSE
+    cout<<
+      o[0]<<" "<<o[1]<<" "<<o[2]<<" + t*"<<
+      d[0]<<" "<<d[1]<<" "<<d[2]<<" ---> "<<
+      endl;
+#endif
     embree::Hit hit;
     embree::Ray ray(o,d,embree::zero);
+    num_rays++;
     _intersector->intersect(ray, hit);
     if(hit)
     {
-      // Hit self again
+      // Hit self again, progressively advance
       if(hit.id0 == last_id0)
       {
         // sanity check
         assert(hit.t<1);
         // move off origin
-        double t_push = pow(2.0,self_hits)*(hit.t<eps?eps:hit.t);
+        //double t_push = pow(2.0,self_hits-4)*(hit.t<eps?eps:hit.t);
+        double t_push = pow(2.0,self_hits)*eps;
+#ifdef VERBOSE
+        cout<<"  t_push: "<<t_push<<endl;
+#endif
         o = o+t_push*d;
         self_hits++;
       }else
       {
         hits.push_back(hit);
-        //cout<<"  t: "<<hit.t<<endl;
+#ifdef VERBOSE
+        cout<<"  t: "<<hit.t<<endl;
+#endif
         o = o+hit.t*d;
         // reset t_scale
         self_hits = 0;

+ 3 - 1
include/igl/embree/EmbreeIntersector.h

@@ -46,11 +46,13 @@ namespace igl
     //   direction  3d (not necessarily normalized) direction vector of ray
     // Output:
     //   hit  embree information about hit
+    //   num_rays  number of rays shot (at least one)
     // Returns true if and only if there was a hit
     bool intersectRay(
       const RowVector3& origin, 
       const RowVector3& direction, 
-      std::vector<embree::Hit > &hits) const;
+      std::vector<embree::Hit > &hits,
+      int & num_rays) const;
   
     // Given a ray find the first *front-facing* hit
     // 

+ 6 - 4
include/igl/embree/bone_visible.cpp

@@ -2,6 +2,7 @@
 #include "EmbreeIntersector.h"
 #include <igl/project_to_line.h>
 #include <igl/EPS.h>
+#include <igl/Timer.h>
 #include <iostream>
 
 template <
@@ -9,7 +10,7 @@ template <
   typename DerivedF, 
   typename DerivedSD,
   typename Derivedflag>
-void bone_visible(
+IGL_INLINE void igl::bone_visible(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedSD> & s,
@@ -28,8 +29,9 @@ void bone_visible(
   const EmbreeIntersector<MatrixXd,MatrixXi,Vector3d> ei = 
         EmbreeIntersector<MatrixXd,MatrixXi,Vector3d>(V,FF);
   const double sd_norm = (s-d).norm();
+  // Embree seems to be parallel when constructing but not when tracing rays
+#pragma omp parallel for
   // loop over mesh vertices
-  // TODO: openmp?
   for(int v = 0;v<V.rows();v++)
   {
     Vector3d Vv = V.row(v);
@@ -113,6 +115,6 @@ void bone_visible(
 
 #ifndef IGL_HEADER_ONLY
 // Explicit template instanciation
-template void bone_visible<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
-template void bone_visible<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
+template void igl::bone_visible<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
+template void igl::bone_visible<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 #endif

+ 15 - 11
include/igl/embree/bone_visible.h

@@ -1,5 +1,6 @@
 #ifndef IGL_BONE_VISIBLE_H
 #define IGL_BONE_VISIBLE_H
+#include <igl/igl_inline.h>
 #include <Eigen/Core>
 //
 // BONE_VISIBLE  test whether vertices of mesh are "visible" to a given bone,
@@ -22,17 +23,20 @@
 // Note: This checks for hits along the segment which are facing in *any*
 // direction from the ray.
 //
-template <
-  typename DerivedV, 
-  typename DerivedF, 
-  typename DerivedSD,
-  typename Derivedflag>
-void bone_visible(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  const Eigen::PlainObjectBase<DerivedSD> & s,
-  const Eigen::PlainObjectBase<DerivedSD> & d,
-  Eigen::PlainObjectBase<Derivedflag>  & flag);
+namespace igl
+{
+  template <
+    typename DerivedV, 
+    typename DerivedF, 
+    typename DerivedSD,
+    typename Derivedflag>
+  IGL_INLINE void bone_visible(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    const Eigen::PlainObjectBase<DerivedSD> & s,
+    const Eigen::PlainObjectBase<DerivedSD> & d,
+    Eigen::PlainObjectBase<Derivedflag>  & flag);
+}
 #ifdef IGL_HEADER_ONLY
 #  include "bone_visible.cpp"
 #endif

+ 1 - 0
include/igl/matlab_format.cpp

@@ -14,6 +14,7 @@ IGL_INLINE const Eigen::WithFormat< DerivedM > igl::matlab_format(
   {
     prefix = name + " = ";
   }
+
   return M.format(Eigen::IOFormat(
     Eigen::FullPrecision,
     0,

+ 45 - 281
include/igl/xml/XMLSerializer.cpp

@@ -1548,288 +1548,52 @@ igl::XMLSerializerTest::XMLSerializerTest()
   testVector.push_back(2.0001f);
   testVector.push_back(3.0001f);
 }
-/*
-Use the following lines to run the XMLSerializer tests:
-
-igl::XMLSerializerTest* test = new igl::XMLSerializerTest();
-bool success = test->Test();
-delete test;
-*/
-bool igl::XMLSerializerTest::Test()
-{
-  // test vars 0
-  char testChar0 = 'a';
-  char* testCharArray0 = "testCharArray0";
-  std::string testString0 = "testString0";
-  bool testBool0 = true;
-  unsigned int testUnsigned0 = 13;
-  int testInt0 = 1000;
-  float testFloat0 = 0.00001f;
-  double testDouble0 = 0.01000000005;
-
-  //std::array<float,2> testArray0 = {{0.001f,1.001f}};
-
-  std::pair<int,bool> testPair0;
-  testPair0.first = 5;
-  testPair0.second = true;
-
-  std::vector<int> testVector0;
-  testVector0.push_back(1);
-  testVector0.push_back(2);
-  testVector0.push_back(3);
-
-  Eigen::MatrixXi testDenseMatrix0;
-  testDenseMatrix0 = Eigen::Matrix3i::Identity();
-
-  Eigen::SparseMatrix<double> testSparseMatrix0(3,3);
-  std::vector<Eigen::Triplet<double> > triplets;
-  triplets.push_back(Eigen::Triplet<double>(0,0,1));
-  triplets.push_back(Eigen::Triplet<double>(1,1,2));
-  triplets.push_back(Eigen::Triplet<double>(2,2,3));
-  testSparseMatrix0.setFromTriplets(triplets.begin(),triplets.end());
-
-  igl::XMLSerializerTest* testObject0 = new igl::XMLSerializerTest();
-
-  std::vector<std::pair<int,bool>*> testComplex10;
-  testComplex10.push_back(&testPair0);
-  testComplex10.push_back(&testPair0);
-
-  std::vector<igl::XMLSerializerTest*> testComplex20;
-  testComplex20.push_back(testObject0);
-  testComplex20.push_back(testObject0);
-  
-  // test vars 1
-  char testChar1 = 'b';
-  char* testCharArray1 = "testCharArray1";
-  std::string testString1 = "testString1";
-  bool testBool1 = false;
-  unsigned int testUnsigned1 = 12;
-  int testInt1 = -1000;
-  float testFloat1 = -0.00001f;
-  double testDouble1 = -0.000000000001;
-
-  //std::array<float,2> testArray1 = {{-0.001f,-1.001f}};
-
-  std::pair<int,bool> testPair1;
-  testPair1.first = -5;
-  testPair1.second = false;
-
-  std::vector<int> testVector1;
-  testVector1.push_back(-1);
-  testVector1.push_back(-2);
-  testVector1.push_back(-3);
-
-  Eigen::MatrixXi testDenseMatrix1;
-  testDenseMatrix1 = Eigen::Matrix3i::Identity();
-  testDenseMatrix1 *= 2;
-
-  Eigen::SparseMatrix<double> testSparseMatrix1(3,3);
-  triplets.clear();
-  triplets.push_back(Eigen::Triplet<double>(0,0,-1));
-  triplets.push_back(Eigen::Triplet<double>(1,1,-2));
-  triplets.push_back(Eigen::Triplet<double>(2,2,-3));
-  testSparseMatrix1.setFromTriplets(triplets.begin(),triplets.end());
-
-  igl::XMLSerializerTest* testObject1 = new igl::XMLSerializerTest();
-  testObject1->testInt = 3;
-  testObject1->testVector.clear();
-
-  std::vector<std::pair<int,bool>*> testComplex11;
-  testComplex11.push_back(&testPair1);
-  testComplex11.push_back(&testPair1);
-
-  std::vector<igl::XMLSerializerTest*> testComplex21;
-  testComplex21.push_back(testObject1);
-  testComplex21.push_back(testObject1);
-  
-  // test Serializer
-  bool testResult = true;
-  
-  // test static functions
-  
-  // check static updating
-  int testInt = 5;
-  testResult &= igl::XMLSerializer::SaveObject(testInt0,"test.xml");
-  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test","test.xml",false);
-  testResult &= igl::XMLSerializer::LoadObject(testInt,"test.xml");
-  testResult &= testInt0 == testInt;
-
-  // check static overwriting
-  testInt = 3;
-  testResult &= igl::XMLSerializer::SaveObject(testInt0,"test.xml");
-  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test","test.xml",true);
-  testResult &= igl::XMLSerializer::LoadObject(testInt,"test.xml") == false;
-  testResult &= testInt0 != testInt;
-
-  // check static based type saving
-  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test0","test.xml",true);
-  testResult &= igl::XMLSerializer::SaveObject(testCharArray0,"testCharArray","test0","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testString0,"testString","test0","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testBool0,"testBool","test0","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testUnsigned0,"testUnsigned","test0","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testInt0,"testInt","test0","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testFloat0,"testFloat","test0","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testDouble0,"testDouble","test0","test.xml",false);
-  //testResult &= igl::XMLSerializer::SaveObject(testArray0,"testArray","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testPair0,"testPair","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testVector0,"testVector","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testDenseMatrix0,"testDense","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testSparseMatrix0,"testSparse","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testObject0,"testObject","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testComplex10,"testComplex1","test1","test.xml",false);
-  testResult &= igl::XMLSerializer::SaveObject(testComplex20,"testComplex2","test1","test.xml",false);
-
-  testResult &= igl::XMLSerializer::LoadObject(testChar1,"testChar","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testCharArray1,"testCharArray","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testString1,"testString","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testBool1,"testBool","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testUnsigned1,"testUnsigned","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testInt1,"testInt","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testFloat1,"testFloat","test0","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testDouble1,"testDouble","test0","test.xml");
-  //testResult &= igl::XMLSerializer::LoadObject(testArray1,"testArray","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testPair1,"testPair","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testVector1,"testVector","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testDenseMatrix1,"testDense","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testSparseMatrix1,"testSparse","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testObject1,"testObject","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testComplex11,"testComplex1","test1","test.xml");
-  testResult &= igl::XMLSerializer::LoadObject(testComplex21,"testComplex2","test1","test.xml");
-
-  testResult &= testChar0 == testChar1;
-  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
-  testResult &= testString0 == testString1;
-  testResult &= testBool0 == testBool1;
-  testResult &= testUnsigned0 == testUnsigned1;
-  testResult &= testInt0 == testInt1;
-  testResult &= testFloat0 == testFloat1;
-  testResult &= testDouble0 == testDouble1;
-  /*for(unsigned int i=0;i<testArray0.size();i++)
-    testResult &= testArray0[i] == testArray1[i];*/
-  testResult &= testPair0.first == testPair1.first;
-  testResult &= testPair0.second == testPair1.second;
-  testResult &= testVector0.size() == testVector1.size();
-  for(unsigned int i=0;i<testVector0.size();i++)
-    testResult &= testVector0[i] == testVector1[i];
-  testResult &= (testDenseMatrix0-testDenseMatrix1).sum() == 0;
-  testResult &= (testSparseMatrix0-testSparseMatrix1).norm() == 0;
-  testResult &= testObject0->testInt == testObject1->testInt;
-  testResult &= testObject0->testVector.size() == testObject1->testVector.size();
-  for(unsigned int i=0;i<testObject0->testVector.size();i++)
-    testResult &= testObject0->testVector[i] == testObject1->testVector[i];
-  testResult &= testComplex10.size() == testComplex11.size();
-  for(unsigned int i=0;i<testComplex10.size();i++)
-  {
-    testResult &= testComplex10[i]->first == testComplex11[0]->first;
-    testResult &= testComplex10[i]->second == testComplex11[0]->second;
-  }
-  testResult &= testComplex20.size() == testComplex21.size();
-  for(unsigned int i=0;i<testComplex20.size();i++)
-  {
-    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
-    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
-    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
-       testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
-  }
-
-  igl::XMLSerializer* s = new igl::XMLSerializer("test0");
-
-  // clear file
-  testResult &= s->Save("test.xml",true);
-
-  testResult &= s->Add(testChar0,"testChar");
-  testResult &= s->Add(testCharArray0,"testCharArray");
-  testResult &= s->Add(testString0,"testString");
-  testResult &= s->Add(testBool0,"testBool");
-  testResult &= s->Add(testUnsigned0,"testUnsigned");
-  testResult &= s->Add(testInt0,"testInt");
-  testResult &= s->Add(testFloat0,"testFloat");
-  testResult &= s->Add(testDouble0,"testDouble");
-
-  s->SetCurrentGroup("test1");
-
-  //testResult &= s->Add(testArray0,"testArray");
-  testResult &= s->Add(testPair0,"testPair");
-  testResult &= s->Add(testVector0,"testVector");
-  testResult &= s->Add(testDenseMatrix0,"testDenseMatrix");
-  testResult &= s->Add(testSparseMatrix0,"testSparseMatrix");
-  testResult &= s->Add(testObject0,"testObject");
-  testResult &= s->Add(testComplex10,"testComplex1");
-  testResult &= s->Add(testComplex20,"testComplex2");
-  
-  // Test single attribute save load
-  testResult &= s->Save("testComplex2","test1","test.xml",true);
-  testResult &= s->Load("testComplex2","test1","test.xml");
-  
-  testResult &= testComplex20.size() == testComplex21.size();
-  for(unsigned int i=0;i<testComplex20.size();i++)
-  {
-    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
-    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
-    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
-        testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
-  }
-
-  // Test group save load without overriding
-  testResult &= s->Save("test0","test.xml",false);
-  testResult &= s->Load("test0","test.xml");
-  testResult &= s->Load("testComplex2","test1","test.xml");
-
-  testResult &= testChar0 == testChar1;
-  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
-  testResult &= testString0 == testString1;
-  testResult &= testBool0 == testBool1;
-  testResult &= testUnsigned0 == testUnsigned1;
-  testResult &= testInt0 == testInt1;
-  testResult &= testFloat0 == testFloat1;
-  testResult &= testDouble0 == testDouble1;
-
-  // Test full serialization save load
-  testResult &= s->Save("test.xml",true);
-  testResult &= s->Load("test.xml");
-  
-  testResult &= testChar0 == testChar1;
-  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
-  testResult &= testString0 == testString1;
-  testResult &= testBool0 == testBool1;
-  testResult &= testUnsigned0 == testUnsigned1;
-  testResult &= testInt0 == testInt1;
-  testResult &= testFloat0 == testFloat1;
-  testResult &= testDouble0 == testDouble1;
-  /*for(unsigned int i=0;i<testArray0.size();i++)
-    testResult &= testArray0[i] == testArray1[i];*/
-  testResult &= testPair0.first == testPair1.first;
-  testResult &= testPair0.second == testPair1.second;
-  testResult &= testVector0.size() == testVector1.size();
-  for(unsigned int i=0;i<testVector0.size();i++)
-    testResult &= testVector0[i] == testVector1[i];
-  testResult &= (testDenseMatrix0-testDenseMatrix1).sum() == 0;
-  testResult &= (testSparseMatrix0-testSparseMatrix1).norm() == 0;
-  testResult &= testObject0->testInt == testObject1->testInt;
-  testResult &= testObject0->testVector.size() == testObject1->testVector.size();
-  for(unsigned int i=0;i<testObject0->testVector.size();i++)
-    testResult &= testObject0->testVector[i] == testObject1->testVector[i];
-  testResult &= testComplex10.size() == testComplex11.size();
-  for(unsigned int i=0;i<testComplex10.size();i++)
-  {
-    testResult &= testComplex10[i]->first == testComplex11[0]->first;
-    testResult &= testComplex10[i]->second == testComplex11[0]->second;
-  }
-  testResult &= testComplex20.size() == testComplex21.size();
-  for(unsigned int i=0;i<testComplex20.size();i++)
-  {
-    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
-    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
-    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
-        testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
-  }
-
-  delete s;
-
-  return testResult;
-}
 
 #ifndef IGL_HEADER_ONLY
 // Explicit template specialization
-
+//igl::XMLSerializerTest test;
+template bool igl::XMLSerializer::LoadObject<Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, -1, 0, -1, -1>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<igl::XMLSerializerTest*>(igl::XMLSerializerTest*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<char*>(char*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<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> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<std::pair<int, bool> >(std::pair<int, bool>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> > >(std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> > >(std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<std::vector<int, std::allocator<int> > >(std::vector<int, std::allocator<int> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<bool>(bool&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<char>(char&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<double>(double&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<float>(float&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<int>(int&, char const*);
+template bool igl::XMLSerializer::LoadObject<int>(int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::LoadObject<unsigned int>(unsigned int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*);
+template bool igl::XMLSerializer::SaveObject<Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, -1, 0, -1, -1>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<igl::XMLSerializerTest*>(igl::XMLSerializerTest*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<char*>(char*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<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> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<std::pair<int, bool> >(std::pair<int, bool>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> > >(std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> > >(std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<std::vector<int, std::allocator<int> > >(std::vector<int, std::allocator<int> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<bool>(bool&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<char>(char&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<double>(double&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<float>(float&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<int>(int&, char const*);
+template bool igl::XMLSerializer::SaveObject<int>(int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::SaveObject<unsigned int>(unsigned int&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, bool);
+template bool igl::XMLSerializer::Add<igl::XMLSerializerTest*>(std::vector<igl::XMLSerializerTest*, std::allocator<igl::XMLSerializerTest*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<igl::XMLSerializerTest*>(igl::XMLSerializerTest*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<std::pair<int, bool>*>(std::vector<std::pair<int, bool>*, std::allocator<std::pair<int, bool>*> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<double>(Eigen::SparseMatrix<double, 0, int>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<int>(std::vector<int, std::allocator<int> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<int, bool>(std::pair<int, bool>&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<int, -1, -1>
+(Eigen::Matrix<int, -1, -1>&, std::basic_string<char,
+    std::char_traits<char>, std::allocator<char> > const&);
+template bool igl::XMLSerializer::Add<int, 3, 3>
+(Eigen::Matrix<int, 3, 3>&, std::basic_string<char,
+    std::char_traits<char>, std::allocator<char> > const&);
 #endif

+ 3 - 2
include/igl/xml/XMLSerializer.h

@@ -26,7 +26,7 @@ You can find examples how to use it in the test case class XMLSerializerTest.
 #include <Eigen/Dense>
 #include <Eigen/Sparse>
 
-#include "tinyxml2.h"
+#include <tinyxml2.h>
 
 namespace igl
 {
@@ -415,9 +415,9 @@ namespace igl
     bool Add(std::pair<T0,T1>& obj, const std::string& name);
     template<typename T>
     bool Add(std::vector<T>& obj, const std::string& name);
-    template<typename T, int R, int C>
     
     // Eigen types
+    template<typename T, int R, int C>
     bool Add(Eigen::Matrix<T,R,C>& obj, const std::string& name);
     template<typename T>
     bool Add(Eigen::SparseMatrix<T>& obj, const std::string& name);
@@ -457,6 +457,7 @@ namespace igl
 
 #ifdef IGL_HEADER_ONLY
 #include "XMLSerializer.cpp"
+#else
 #endif
 
 #endif

+ 298 - 0
include/igl/xml/test.sccp

@@ -0,0 +1,298 @@
+#!/bin/bash
+/*/../bin/ls > /dev/null
+# BEGIN BASH SCRIPT
+printf "//" | cat - $0 | g++ -g -liglxml -ligl -ltinyxml2 -I/opt/local/include/eigen3 -L$LIBIGL/external/tinyxml2 -I$LIBIGL/external/tinyxml2 -I$LIBIGL/include -L$LIBIGL/lib -o .main -x c++ - && ./.main $@
+rm -f .main
+# END BASH SCRIPT
+exit
+*/
+
+#include <igl/xml/XMLSerializer.h>
+
+
+/*
+Use the following lines to run the XMLSerializer tests:
+igl::XMLSerializerTest* test = new igl::XMLSerializerTest();
+bool success = test->Test();
+delete test;
+*/
+bool igl::XMLSerializerTest::Test()
+{
+  // test vars 0
+  char testChar0 = 'a';
+  char* testCharArray0 = "testCharArray0";
+  std::string testString0 = "testString0";
+  bool testBool0 = true;
+  unsigned int testUnsigned0 = 13;
+  int testInt0 = 1000;
+  float testFloat0 = 0.00001f;
+  double testDouble0 = 0.01000000005;
+
+  //std::array<float,2> testArray0 = {{0.001f,1.001f}};
+
+  std::pair<int,bool> testPair0;
+  testPair0.first = 5;
+  testPair0.second = true;
+
+  std::vector<int> testVector0;
+  testVector0.push_back(1);
+  testVector0.push_back(2);
+  testVector0.push_back(3);
+
+  Eigen::Matrix3i testDenseMatrix0;
+  //testDenseMatrix0 = Eigen::Matrix3i::Identity();
+
+  Eigen::SparseMatrix<double> testSparseMatrix0(3,3);
+  std::vector<Eigen::Triplet<double> > triplets;
+  triplets.push_back(Eigen::Triplet<double>(0,0,1));
+  triplets.push_back(Eigen::Triplet<double>(1,1,2));
+  triplets.push_back(Eigen::Triplet<double>(2,2,3));
+  testSparseMatrix0.setFromTriplets(triplets.begin(),triplets.end());
+
+  igl::XMLSerializerTest* testObject0 = new igl::XMLSerializerTest();
+
+  std::vector<std::pair<int,bool>*> testComplex10;
+  testComplex10.push_back(&testPair0);
+  testComplex10.push_back(&testPair0);
+
+  std::vector<igl::XMLSerializerTest*> testComplex20;
+  testComplex20.push_back(testObject0);
+  testComplex20.push_back(testObject0);
+  
+  // test vars 1
+  char testChar1 = 'b';
+  char* testCharArray1 = "testCharArray1";
+  std::string testString1 = "testString1";
+  bool testBool1 = false;
+  unsigned int testUnsigned1 = 12;
+  int testInt1 = -1000;
+  float testFloat1 = -0.00001f;
+  double testDouble1 = -0.000000000001;
+
+  //std::array<float,2> testArray1 = {{-0.001f,-1.001f}};
+
+  std::pair<int,bool> testPair1;
+  testPair1.first = -5;
+  testPair1.second = false;
+
+  std::vector<int> testVector1;
+  testVector1.push_back(-1);
+  testVector1.push_back(-2);
+  testVector1.push_back(-3);
+
+  Eigen::Matrix3i testDenseMatrix1;
+  //testDenseMatrix1 = Eigen::Matrix3i::Identity();
+  //testDenseMatrix1 *= 2;
+
+  Eigen::SparseMatrix<double> testSparseMatrix1(3,3);
+  triplets.clear();
+  triplets.push_back(Eigen::Triplet<double>(0,0,-1));
+  triplets.push_back(Eigen::Triplet<double>(1,1,-2));
+  triplets.push_back(Eigen::Triplet<double>(2,2,-3));
+  testSparseMatrix1.setFromTriplets(triplets.begin(),triplets.end());
+
+  igl::XMLSerializerTest* testObject1 = new igl::XMLSerializerTest();
+  testObject1->testInt = 3;
+  testObject1->testVector.clear();
+
+  std::vector<std::pair<int,bool>*> testComplex11;
+  testComplex11.push_back(&testPair1);
+  testComplex11.push_back(&testPair1);
+
+  std::vector<igl::XMLSerializerTest*> testComplex21;
+  testComplex21.push_back(testObject1);
+  testComplex21.push_back(testObject1);
+  
+  // test Serializer
+  bool testResult = true;
+  
+  // test static functions
+  
+  // check static updating
+  int testInt = 5;
+  testResult &= igl::XMLSerializer::SaveObject(testInt0,"test.xml");
+  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test","test.xml",false);
+  testResult &= igl::XMLSerializer::LoadObject(testInt,"test.xml");
+  testResult &= testInt0 == testInt;
+
+  // check static overwriting
+  testInt = 3;
+  testResult &= igl::XMLSerializer::SaveObject(testInt0,"test.xml");
+  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test","test.xml",true);
+  testResult &= igl::XMLSerializer::LoadObject(testInt,"test.xml") == false;
+  testResult &= testInt0 != testInt;
+
+  // check static based type saving
+  testResult &= igl::XMLSerializer::SaveObject(testChar0,"testChar","test0","test.xml",true);
+  testResult &= igl::XMLSerializer::SaveObject(testCharArray0,"testCharArray","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testString0,"testString","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testBool0,"testBool","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testUnsigned0,"testUnsigned","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testInt0,"testInt","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testFloat0,"testFloat","test0","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testDouble0,"testDouble","test0","test.xml",false);
+  //testResult &= igl::XMLSerializer::SaveObject(testArray0,"testArray","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testPair0,"testPair","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testVector0,"testVector","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testDenseMatrix0,"testDense","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testSparseMatrix0,"testSparse","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testObject0,"testObject","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testComplex10,"testComplex1","test1","test.xml",false);
+  testResult &= igl::XMLSerializer::SaveObject(testComplex20,"testComplex2","test1","test.xml",false);
+
+  testResult &= igl::XMLSerializer::LoadObject(testChar1,"testChar","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testCharArray1,"testCharArray","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testString1,"testString","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testBool1,"testBool","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testUnsigned1,"testUnsigned","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testInt1,"testInt","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testFloat1,"testFloat","test0","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testDouble1,"testDouble","test0","test.xml");
+  //testResult &= igl::XMLSerializer::LoadObject(testArray1,"testArray","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testPair1,"testPair","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testVector1,"testVector","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testDenseMatrix1,"testDense","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testSparseMatrix1,"testSparse","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testObject1,"testObject","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testComplex11,"testComplex1","test1","test.xml");
+  testResult &= igl::XMLSerializer::LoadObject(testComplex21,"testComplex2","test1","test.xml");
+
+  testResult &= testChar0 == testChar1;
+  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
+  testResult &= testString0 == testString1;
+  testResult &= testBool0 == testBool1;
+  testResult &= testUnsigned0 == testUnsigned1;
+  testResult &= testInt0 == testInt1;
+  testResult &= testFloat0 == testFloat1;
+  testResult &= testDouble0 == testDouble1;
+  /*for(unsigned int i=0;i<testArray0.size();i++)
+    testResult &= testArray0[i] == testArray1[i];*/
+  testResult &= testPair0.first == testPair1.first;
+  testResult &= testPair0.second == testPair1.second;
+  testResult &= testVector0.size() == testVector1.size();
+  for(unsigned int i=0;i<testVector0.size();i++)
+    testResult &= testVector0[i] == testVector1[i];
+  testResult &= (testDenseMatrix0-testDenseMatrix1).sum() == 0;
+  testResult &= (testSparseMatrix0-testSparseMatrix1).norm() == 0;
+  testResult &= testObject0->testInt == testObject1->testInt;
+  testResult &= testObject0->testVector.size() == testObject1->testVector.size();
+  for(unsigned int i=0;i<testObject0->testVector.size();i++)
+    testResult &= testObject0->testVector[i] == testObject1->testVector[i];
+  testResult &= testComplex10.size() == testComplex11.size();
+  for(unsigned int i=0;i<testComplex10.size();i++)
+  {
+    testResult &= testComplex10[i]->first == testComplex11[0]->first;
+    testResult &= testComplex10[i]->second == testComplex11[0]->second;
+  }
+  testResult &= testComplex20.size() == testComplex21.size();
+  for(unsigned int i=0;i<testComplex20.size();i++)
+  {
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
+    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
+       testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
+  }
+
+  igl::XMLSerializer* s = new igl::XMLSerializer("test0");
+
+  // clear file
+  testResult &= s->Save("test.xml",true);
+
+  testResult &= s->Add(testChar0,"testChar");
+  testResult &= s->Add(testCharArray0,"testCharArray");
+  testResult &= s->Add(testString0,"testString");
+  testResult &= s->Add(testBool0,"testBool");
+  testResult &= s->Add(testUnsigned0,"testUnsigned");
+  testResult &= s->Add(testInt0,"testInt");
+  testResult &= s->Add(testFloat0,"testFloat");
+  testResult &= s->Add(testDouble0,"testDouble");
+
+  s->SetCurrentGroup("test1");
+
+  //testResult &= s->Add(testArray0,"testArray");
+  testResult &= s->Add(testPair0,"testPair");
+  testResult &= s->Add(testVector0,"testVector");
+  testResult &= s->Add(testDenseMatrix0,"testDenseMatrix");
+  testResult &= s->Add(testSparseMatrix0,"testSparseMatrix");
+  testResult &= s->Add(testObject0,"testObject");
+  testResult &= s->Add(testComplex10,"testComplex1");
+  testResult &= s->Add(testComplex20,"testComplex2");
+  
+  // Test single attribute save load
+  testResult &= s->Save("testComplex2","test1","test.xml",true);
+  testResult &= s->Load("testComplex2","test1","test.xml");
+  
+  testResult &= testComplex20.size() == testComplex21.size();
+  for(unsigned int i=0;i<testComplex20.size();i++)
+  {
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
+    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
+        testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
+  }
+
+  // Test group save load without overriding
+  testResult &= s->Save("test0","test.xml",false);
+  testResult &= s->Load("test0","test.xml");
+  testResult &= s->Load("testComplex2","test1","test.xml");
+
+  testResult &= testChar0 == testChar1;
+  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
+  testResult &= testString0 == testString1;
+  testResult &= testBool0 == testBool1;
+  testResult &= testUnsigned0 == testUnsigned1;
+  testResult &= testInt0 == testInt1;
+  testResult &= testFloat0 == testFloat1;
+  testResult &= testDouble0 == testDouble1;
+
+  // Test full serialization save load
+  testResult &= s->Save("test.xml",true);
+  testResult &= s->Load("test.xml");
+  
+  testResult &= testChar0 == testChar1;
+  testResult &= strcmp(testCharArray0,testCharArray1) == 0;
+  testResult &= testString0 == testString1;
+  testResult &= testBool0 == testBool1;
+  testResult &= testUnsigned0 == testUnsigned1;
+  testResult &= testInt0 == testInt1;
+  testResult &= testFloat0 == testFloat1;
+  testResult &= testDouble0 == testDouble1;
+  /*for(unsigned int i=0;i<testArray0.size();i++)
+    testResult &= testArray0[i] == testArray1[i];*/
+  testResult &= testPair0.first == testPair1.first;
+  testResult &= testPair0.second == testPair1.second;
+  testResult &= testVector0.size() == testVector1.size();
+  for(unsigned int i=0;i<testVector0.size();i++)
+    testResult &= testVector0[i] == testVector1[i];
+  testResult &= (testDenseMatrix0-testDenseMatrix1).sum() == 0;
+  testResult &= (testSparseMatrix0-testSparseMatrix1).norm() == 0;
+  testResult &= testObject0->testInt == testObject1->testInt;
+  testResult &= testObject0->testVector.size() == testObject1->testVector.size();
+  for(unsigned int i=0;i<testObject0->testVector.size();i++)
+    testResult &= testObject0->testVector[i] == testObject1->testVector[i];
+  testResult &= testComplex10.size() == testComplex11.size();
+  for(unsigned int i=0;i<testComplex10.size();i++)
+  {
+    testResult &= testComplex10[i]->first == testComplex11[0]->first;
+    testResult &= testComplex10[i]->second == testComplex11[0]->second;
+  }
+  testResult &= testComplex20.size() == testComplex21.size();
+  for(unsigned int i=0;i<testComplex20.size();i++)
+  {
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testInt == ((XMLSerializerTest*)testComplex21[i])->testInt;
+    testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector.size() == ((XMLSerializerTest*)testComplex21[i])->testVector.size();
+    for(unsigned int j=0;j<((XMLSerializerTest*)testComplex20[i])->testVector.size();j++)
+        testResult &= ((XMLSerializerTest*)testComplex20[i])->testVector[j] == ((XMLSerializerTest*)testComplex21[i])->testVector[j];
+  }
+
+  delete s;
+  printf("done with test.\n");
+
+  return testResult;
+}
+
+int main(int argc, char * argv[])
+{
+  igl::XMLSerializerTest test;
+  return !test.Test();
+}