Browse Source

updated serialization
small fixes


Former-commit-id: c3b5311a493b781cf7ce50e0f6eb9189e1e73afd

schuellc 10 years ago
parent
commit
07b9e984a2

+ 7 - 1
include/igl/angles.h

@@ -7,7 +7,13 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_ANGLES_H
 #define IGL_ANGLES_H
-#warning "Deprecated. Use igl/internal_angles.h instead"
+#ifdef _WIN32
+ #pragma message ( "Deprecated. Use igl/internal_angles.h instead" )
+#else
+ #warning "Deprecated. Use igl/internal_angles.h instead"
+#endif
+
+
 #include "igl_inline.h"
 #include <Eigen/Core>
 namespace igl

+ 1 - 1
include/igl/doublearea.cpp

@@ -132,7 +132,7 @@ IGL_INLINE void igl::doublearea(
   #  define IGL_OMP_MIN_VALUE 1000
   #endif
   #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(size_t i = 0;i<m;i++)
+  for(long int i = 0;i<m;i++)
   {
     //// Heron's formula for area
     //const typename Derivedl::Scalar arg =

+ 5 - 2
include/igl/file_dialog_open.cpp

@@ -9,9 +9,12 @@
 #include <cstdio>
 #include <cstring>
 
-
 #ifdef _WIN32
- #include <Commdlg.h>
+  #include <windows.h>
+  #undef max
+  #undef min
+  
+  #include <Commdlg.h>
 #endif
 
 IGL_INLINE std::string igl::file_dialog_open()

+ 1 - 1
include/igl/internal_angles.cpp

@@ -48,7 +48,7 @@ IGL_INLINE void igl::internal_angles(
   #  define IGL_OMP_MIN_VALUE 1000
   #endif
   #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(size_t f = 0;f<m;f++)
+  for(long int f = 0;f<m;f++)
   {
     for(size_t d = 0;d<3;d++)
     {

+ 213 - 24
include/igl/serialize.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2014 Christian Schller <schuellchr@gmail.com>
+// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
 //
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -12,20 +12,44 @@ namespace igl
   template <typename T>
   IGL_INLINE void serialize(const T& obj,const std::string& filename)
   {
-    std::ofstream fout(filename.c_str(),std::ios::out | std::ios::binary);
+    serialize(obj,"obj",filename);
+  }
+
+  template <typename T>
+  IGL_INLINE void serialize(const T& obj,const std::string& objectName,const std::string& filename,bool update)
+  {
+    std::vector<char> buffer;
 
-    if(fout.is_open())
+    if(update)
     {
-      std::vector<char> buffer;
-      serialize(obj,"obj",buffer);
+      std::ifstream file(filename.c_str(),std::ios::binary);
 
-      fout.write(&buffer[0],buffer.size());
+      if(file.is_open())
+      {
+        file.seekg(0,std::ios::end);
+        int size = file.tellg();
+        file.seekg(0,std::ios::beg);
+
+        buffer.resize(size);
+        file.read(&buffer[0],size);
+        
+        file.close();
+      }
+    }
 
-      fout.close();
+    std::ofstream file(filename.c_str(),std::ios::out | std::ios::binary);
+
+    if(file.is_open())
+    {
+      serialize(obj,objectName,buffer);
+
+      file.write(&buffer[0],buffer.size());
+
+      file.close();
     }
     else
     {
-      std::cerr << "Saving binary serialization failed!" << std::endl;
+      std::cerr << "saving binary serialization failed!" << std::endl;
     }
   }
 
@@ -40,26 +64,88 @@ namespace igl
     detail::serialize(obj,tmp,tmp.begin());
 
     std::string objectType(typeid(obj).name());
+    size_t newObjectSize = tmp.size();
+    size_t newHeaderSize = detail::getByteSize(objectName) + detail::getByteSize(objectType) + sizeof(size_t);
+    size_t oldObjectSize = 0;
+    size_t oldHeaderSize = 0;
+
+    // find object header
+    std::vector<char>::iterator iter = buffer.begin();
+    while(iter != buffer.end())
+    {
+      std::vector<char>::iterator iterTemp = iter;
+
+      std::string name;
+      std::string type;
+      detail::deserialize(name,iter);
+      detail::deserialize(type,iter);
+      detail::deserialize(oldObjectSize,iter);
+
+      if(name == objectName)
+      {
+        if(type != typeid(obj).name())
+          std::cout << "object " + objectName + " was overwriten with different data type!" << std::endl;
+
+        oldHeaderSize = iter - iterTemp;
+        iter = iterTemp;
+        break;
+      }
+      else
+        iter+=oldObjectSize;
+    }
 
-    size_t curSize = buffer.size();
-    size_t objSize = tmp.size();
-    size_t newSize = curSize + detail::getByteSize(objectName) + detail::getByteSize(objectType) + sizeof(size_t)+objSize;
+    if(iter != buffer.end())
+    {
+      std::vector<char>::iterator iterEndPart = iter+oldHeaderSize+oldObjectSize;
+      size_t startPartSize = iter - buffer.begin();
+      size_t endPartSize = buffer.end()-iterEndPart;
+      
+      // copy end part of buffer
+      std::vector<char> endPartBuffer(endPartSize);
+      std::copy(iterEndPart,buffer.end(),endPartBuffer.begin());
 
-    buffer.resize(newSize);
+      size_t newSize = startPartSize + newHeaderSize + newObjectSize + endPartSize;
+      buffer.resize(newSize);
+      iter = buffer.begin() + startPartSize;
 
-    std::vector<char>::iterator iter = buffer.begin()+curSize;
+      // serialize object header (name/type/size)
+      detail::serialize(objectName,buffer,iter);
+      detail::serialize(objectType,buffer,iter);
+      detail::serialize(newObjectSize,buffer,iter);
 
-    // serialize object header (name/type/size)
-    detail::serialize(objectName,buffer,iter);
-    detail::serialize(objectType,buffer,iter);
-    detail::serialize(objSize,buffer,iter);
+      // copy serialized data to buffer
+      iter = std::copy(tmp.begin(),tmp.end(),iter);
 
-    // copy serilized data to buffer
-    iter = std::copy(tmp.begin(),tmp.end(),iter);
+      // copy back end part of buffer
+      std::copy(endPartBuffer.begin(),endPartBuffer.end(),iter);
+    }
+    else
+    { 
+      size_t curSize = buffer.size();
+      size_t newSize = curSize + newHeaderSize + newObjectSize;
+
+      buffer.resize(newSize);
+
+      std::vector<char>::iterator iter = buffer.begin()+curSize;
+
+      // serialize object header (name/type/size)
+      detail::serialize(objectName,buffer,iter);
+      detail::serialize(objectType,buffer,iter);
+      detail::serialize(newObjectSize,buffer,iter);
+
+      // copy serialized data to buffer
+      iter = std::copy(tmp.begin(),tmp.end(),iter);
+    }
   }
 
   template <typename T>
   IGL_INLINE void deserialize(T& obj,const std::string& filename)
+  {
+    deserialize(obj,"obj",filename);
+  }
+
+  template <typename T>
+  IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::string& filename)
   {
     std::ifstream file(filename.c_str(),std::ios::binary);
 
@@ -72,7 +158,7 @@ namespace igl
       std::vector<char> buffer(size);
       file.read(&buffer[0],size);
 
-      deserialize(obj,"obj",buffer);
+      deserialize(obj,objectName,buffer);
       file.close();
     }
     else
@@ -109,6 +195,101 @@ namespace igl
       obj = T();
   }
 
+  IGL_INLINE bool Serializable::PreSerialization() const
+  {
+    return true;
+  }
+
+  IGL_INLINE void Serializable::PostSerialization() const
+  {
+  }
+
+  IGL_INLINE bool Serializable::PreDeserialization()
+  {
+    return true;
+  }
+
+  IGL_INLINE void Serializable::PostDeserialization()
+  {
+  }
+
+  IGL_INLINE void Serializable::Serialize(std::vector<char>& buffer) const
+  {
+    if(this->PreSerialization())
+    {
+      if(initialized == false)
+      {
+        objects.clear();
+        (const_cast<Serializable*>(this))->InitSerialization();
+        initialized = true;
+      }
+
+      for(unsigned int i=0;i<objects.size();i++)
+        objects[i]->Serialize(buffer);
+
+      this->PostSerialization();
+    }
+  }
+
+  IGL_INLINE void Serializable::Deserialize(const std::vector<char>& buffer)
+  {
+    if(this->PreDeserialization())
+    {
+      if(initialized == false)
+      {
+        objects.clear();
+        (const_cast<Serializable*>(this))->InitSerialization();
+        initialized = true;
+      }
+
+      for(unsigned int i=0;i<objects.size();i++)
+        objects[i]->Deserialize(buffer);
+
+      this->PostDeserialization();
+    }
+  }
+
+  IGL_INLINE Serializable::Serializable()
+  {
+    initialized = false;
+  }
+
+  IGL_INLINE Serializable::Serializable(const Serializable& obj)
+  {
+    initialized = false;
+    objects.clear();
+  }
+
+  IGL_INLINE Serializable::~Serializable()
+  {
+    initialized = false;
+    objects.clear();
+  }
+
+  IGL_INLINE Serializable& Serializable::operator=(const Serializable& obj)
+  {
+    if(this != &obj)
+    {
+      if(initialized)
+      {
+        initialized = false;
+        objects.clear();
+      }
+    }
+    return *this;
+  }
+
+  template <typename T>
+  IGL_INLINE void Serializable::Add(T& obj,std::string name,bool binary)
+  {
+    SerializationObject<T>* object = new SerializationObject<T>();
+    object->Binary = binary;
+    object->Name = name;
+    object->Object = &obj;
+
+    objects.push_back(object);
+  }
+
   namespace detail
   {
     // fundamental types
@@ -161,16 +342,16 @@ namespace igl
       obj = str;
     }
 
-    // Serializable
+    // SerializableBase
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<Serializable,T>::value,size_t>::type getByteSize(const T& obj)
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value,size_t>::type getByteSize(const T& obj)
     {
       return sizeof(std::vector<char>::size_type);
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<Serializable,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
     {
       // data
       std::vector<char> tmp;
@@ -187,7 +368,7 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<Serializable,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter)
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter)
     {
       std::vector<char>::size_type size;
       detail::deserialize(size,iter);
@@ -447,5 +628,13 @@ namespace igl
         detail::deserialize(*obj,iter);
       }
     }
+
+    template <typename T>
+    std::vector<char>::iterator findObject(const T& obj,const std::string objectName, std::vector<char>& buffer)
+    {
+      
+
+      return iter;
+    }
   }
 }

+ 86 - 24
include/igl/serialize.h

@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2014 Christian Schller <schuellchr@gmail.com>
+// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
 //
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -8,7 +8,7 @@
 // Functions to save and load a serialization of fundamental c++ data types to
 // and from a binary file. STL containers, Eigen matrix types and nested data
 // structures are also supported. To serialize a user defined class implement
-// the interface Serializable.
+// the interface Serializable or SerializableBase.
 //
 // See also: xml/serialize_xml.h
 // -----------------------------------------------------------------------------
@@ -19,25 +19,28 @@
 
 #ifndef IGL_SERIALIZE_H
 #define IGL_SERIALIZE_H
-#include "igl_inline.h"
+
 #include <type_traits>
 #include <iostream>
+#include <fstream>
+#include <cstdint>
 #include <numeric>
 #include <vector>
 #include <set>
 #include <map>
-#include <fstream>
 
 #include <Eigen/Dense>
 #include <Eigen/Sparse>
 
+#include "igl_inline.h"
+
 //#define SERIALIZE(x) igl::serialize(x,#x,buffer);
 //#define DESERIALIZE(x) igl::deserialize(x,#x,buffer);
 
 namespace igl
 {
 
-  // serializes the given object either to a file or to a provided buffer
+  // Serializes the given object either to a file or to a provided buffer
   // Templates:
   //   T  type of the object to serialize
   // Inputs:
@@ -50,9 +53,11 @@ namespace igl
   template <typename T>
   IGL_INLINE void serialize(const T& obj,const std::string& filename);
   template <typename T>
+  IGL_INLINE void serialize(const T& obj,const std::string& objectName,const std::string& filename,bool update = false);
+  template <typename T>
   IGL_INLINE void serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer);
 
-  // deserializes the given data from a file or buffer back to the provided object
+  // Deserializes the given data from a file or buffer back to the provided object
   //
   // Templates:
   //   T  type of the object to serialize
@@ -66,27 +71,80 @@ namespace igl
   template <typename T>
   IGL_INLINE void deserialize(T& obj,const std::string& filename);
   template <typename T>
+  IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::string& filename);
+  template <typename T>
   IGL_INLINE void deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer);
 
-  // interface for user defined types
-  struct Serializable
-  {
-    virtual void Serialize(std::vector<char>& buffer) const = 0;
-    virtual void Deserialize(const std::vector<char>& buffer) = 0;
-  };
-  // example:
+  // User defined types have to derive from the class Serializable
+  // and add their member variables in InitSerialization like the
+  // following:
   //
   // class Test : public igl::Serializable {
   //
   //   int var;
   //
-  //   void Serialize(std::vector<char>& buffer) {
-  //     serialize(var,"var1",buffer);
+  //   void InitSerialization() {
+  //     this->Add(var,"var");
   //   }
-  //   void Deserialize(const std::vector<char>& buffer) {
-  //     deserialize(var,"var1",buffer);
-  //   }
-  // }
+  // };
+
+  // Base interface for user defined types
+  struct SerializableBase 
+  {
+    virtual void Serialize(std::vector<char>& buffer) const = 0;
+    virtual void Deserialize(const std::vector<char>& buffer) = 0;
+  };
+
+  // Convenient interface for user defined types
+  class Serializable: public SerializableBase
+  {
+  private:
+
+    template <typename T>
+    struct SerializationObject : public SerializableBase
+    {
+      bool Binary;
+      std::string Name;
+      T* Object;
+
+      void Serialize(std::vector<char>& buffer) const {
+        igl::serialize(*Object,Name,buffer);
+      }
+
+      void Deserialize(const std::vector<char>& buffer) {
+        igl::deserialize(*Object,Name,buffer);
+      }
+    };
+
+    mutable bool initialized;
+    mutable std::vector<SerializableBase*> objects;
+  
+  public:
+
+    // Override this function to add your member variables which should be serialized
+    IGL_INLINE virtual void InitSerialization() = 0;
+
+    // Following functions can be overridden to handle the specific events.
+    // Return false to prevent the de-/serialization of an object.
+    IGL_INLINE virtual bool PreSerialization() const;
+    IGL_INLINE virtual void PostSerialization() const;
+    IGL_INLINE virtual bool PreDeserialization();
+    IGL_INLINE virtual void PostDeserialization();
+
+    // Default implementation of Serializable interface
+    IGL_INLINE void Serialize(std::vector<char>& buffer) const;
+    IGL_INLINE void Deserialize(const std::vector<char>& buffer);
+
+    // Default constructor, destructor, assignment and copy constructor
+    IGL_INLINE Serializable();
+    IGL_INLINE Serializable(const Serializable& obj);
+    IGL_INLINE ~Serializable();
+    IGL_INLINE Serializable& operator=(const Serializable& obj);
+
+    // Use this function to add your variables which should be serialized
+    template <typename T>
+    IGL_INLINE void Add(T& obj,std::string name,bool binary = false);
+  };
 
   // internal functions
   namespace detail
@@ -104,13 +162,13 @@ namespace igl
     IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
     IGL_INLINE void deserialize(std::string& obj,std::vector<char>::const_iterator& iter);
 
-    // Serializable
+    // SerializableBase
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<Serializable,T>::value,size_t>::type getByteSize(const T& obj);
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value,size_t>::type getByteSize(const T& obj);
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<Serializable,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<Serializable,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
 
     // stl containers
     // std::pair
@@ -168,6 +226,10 @@ namespace igl
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
 
+    // helper functions
+    template <typename T>
+    std::vector<char>::iterator findObject(const T& obj,const std::string objectName,std::vector<char>& buffer);
+
     // compile time type serializable check
     template <typename T>
     struct is_stl_container { static const bool value = false; };
@@ -190,7 +252,7 @@ namespace igl
     template <typename T>
     struct is_serializable {
       using T0 = typename  std::remove_pointer<T>::type;
-      static const bool value = std::is_fundamental<T0>::value || std::is_same<std::string,T0>::value || std::is_base_of<Serializable,T0>::value
+      static const bool value = std::is_fundamental<T0>::value || std::is_same<std::string,T0>::value || std::is_base_of<SerializableBase,T0>::value
         || is_stl_container<T0>::value || is_eigen_type<T0>::value;
     };
   }

+ 1 - 1
include/igl/svd3x3/arap_dof.cpp

@@ -739,7 +739,7 @@ IGL_INLINE bool igl::arap_dof_update(
 #ifdef __SSE__ // fit_rotations_SSE will convert to float if necessary
       fit_rotations_SSE(S,R);
 #else
-      fit_rotations(S,R);
+      fit_rotations(S,false,R);
 #endif
     }
 

+ 47 - 33
include/igl/viewer/Viewer.cpp

@@ -6,6 +6,8 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 
+// TODO: save_scene()/load_scene()
+
 #include "Viewer.h"
 #include <igl/get_seconds.h>
 
@@ -27,9 +29,6 @@
 #   include <OpenGL/gl3.h>
 #   define __gl_h_ /* Prevent inclusion of the old gl.h */
 #else
-#   ifdef _WIN32
-#       include <windows.h>
-#   endif
 #   include <GL/gl.h>
 #endif
 
@@ -51,10 +50,6 @@
 #include <limits>
 #include <cassert>
 
-#ifdef ENABLE_XML_SERIALIZATION
-  #include "igl/xml/XMLSerializer.h"
-#endif
-
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/adjacency_list.h>
@@ -334,10 +329,8 @@ namespace igl
 
     // ---------------------- LOADING ----------------------
 
-    #ifdef ENABLE_XML_SERIALIZATION
     TwAddButton(bar,"Load Scene", load_scene_cb,    this, "group='Workspace'");
     TwAddButton(bar,"Save Scene", save_scene_cb,    this, "group='Workspace'");
-    #endif
 
     #ifdef ENABLE_IO
     TwAddButton(bar,"Load Mesh",  open_dialog_mesh, this, "group='Mesh' key=o");
@@ -491,8 +484,11 @@ namespace igl
 
     if (extension == "off" || extension =="OFF")
     {
-      if (!igl::readOFF(mesh_file_name_string, data.V, data.F))
+      Eigen::MatrixXd V;
+      Eigen::MatrixXi F;
+      if (!igl::readOFF(mesh_file_name_string, V, F))
         return false;
+      data.set_mesh(V,F);
     }
     else if (extension == "obj" || extension =="OBJ")
     {
@@ -501,9 +497,15 @@ namespace igl
 
       Eigen::MatrixXd UV_V;
       Eigen::MatrixXi UV_F;
+      Eigen::MatrixXd V;
+      Eigen::MatrixXi F;
 
-      if (!(igl::readOBJ(mesh_file_name_string, data.V, data.F, corner_normals, fNormIndices, UV_V, UV_F)))
+      if (!(igl::readOBJ(mesh_file_name_string, V, F, corner_normals, fNormIndices, UV_V, UV_F)))
         return false;
+
+      data.set_mesh(V,F);
+      data.set_uv(UV_V,UV_F);
+
     }
     else
     {
@@ -796,43 +798,55 @@ namespace igl
 
   bool Viewer::save_scene()
   {
-    #ifdef ENABLE_XML_SERIALIZATION
-    string fname = igl::file_dialog_save();
+    std::string fname = igl::file_dialog_save();
     if (fname.length() == 0)
       return false;
 
-    ::igl::XMLSerializer serializer("Viewer");
-    serializer.Add(data,"Data");
-    serializer.Add(options,"Options");
+#ifdef ENABLE_XML_SERIALIZATION
+    
+    igl::serialize_xml(core,"Core",fname.c_str(),false,false);
+    igl::serialize_xml(data,"Data",fname.c_str(),false,true);
 
-    if (plugin_manager)
-      for (unsigned int i = 0; i <plugin_manager->plugin_list.size(); ++i)
-        serializer.Add(*(plugin_manager->plugin_list[i]),plugin_manager->plugin_list[i]->plugin_name);
+    for(unsigned int i = 0; i <plugins.size(); ++i)
+      igl::serialize_xml(*plugins[i],plugins[i]->plugin_name,fname.c_str(),false,true);
+#else
 
-    serializer.Save(fname.c_str(),true);
+    igl::serialize(core,"Core",fname.c_str(),false);
+    igl::serialize(data,"Data",fname.c_str(),true);
+
+    for(unsigned int i = 0; i <plugins.size(); ++i)
+      igl::serialize(*plugins[i],plugins[i]->plugin_name,fname.c_str(),true);
+
+#endif
 
-    #endif
     return true;
   }
 
   bool Viewer::load_scene()
   {
-    #ifdef ENABLE_XML_SERIALIZATION
-    string fname = igl::file_dialog_open();
+    std::string fname = igl::file_dialog_open();
     if (fname.length() == 0)
       return false;
 
-    ::igl::XMLSerializer serializer("Viewer");
-    serializer.Add(data,"Data");
-    serializer.Add(options,"Options");
+#ifdef ENABLE_XML_SERIALIZATION
+    
+    igl::deserialize_xml(core,"Core",fname.c_str());
+    igl::deserialize_xml(data,"Data",fname.c_str());
 
-    if (plugin_manager)
-      for (unsigned int i = 0; i <plugin_manager->plugin_list.size(); ++i)
-        serializer.Add(*(plugin_manager->plugin_list[i]),plugin_manager->plugin_list[i]->plugin_name);
+    for(unsigned int i = 0; i <plugins.size(); ++i)
+      igl::deserialize_xml(*plugins[i],plugins[i]->plugin_name,fname.c_str());
 
-    serializer.Load(fname.c_str());
 
-    #endif
+#else
+
+    igl::deserialize(core,"Core",fname.c_str());
+    igl::deserialize(data,"Data",fname.c_str());
+
+    for(unsigned int i = 0; i <plugins.size(); ++i)
+      igl::deserialize(*plugins[i],plugins[i]->plugin_name,fname.c_str());
+
+#endif
+
     return true;
   }
 
@@ -896,7 +910,7 @@ namespace igl
     static_cast<Viewer *>(clientData)->load_mesh_from_file(fname.c_str());
   }
 
-  int Viewer::launch(std::string filename)
+  int Viewer::launch(std::string filename)  
   {
     GLFWwindow* window;
 
@@ -904,7 +918,7 @@ namespace igl
     if (!glfwInit())
       return EXIT_FAILURE;
 
-    glfwWindowHint(GLFW_SAMPLES, 16);
+    glfwWindowHint(GLFW_SAMPLES, 4);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
     #ifdef __APPLE__

+ 2 - 7
include/igl/viewer/Viewer.h

@@ -23,18 +23,13 @@
 #define IGL_MOD_ALT             0x0004
 #define IGL_MOD_SUPER           0x0008
 
-#ifdef ENABLE_XML_SERIALIZATION
-  #include <igl/xml/XMLSerializer.h>
-  #include <igl/xml/XMLSerialization.h>
-#endif
-
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <igl/viewer/OpenGL_shader.h>
-#include <igl/viewer/ViewerData.h>
 #include <igl/viewer/OpenGL_state.h>
-#include <igl/viewer/ViewerPlugin.h>
 #include <igl/viewer/ViewerCore.h>
+#include <igl/viewer/ViewerData.h>
+#include <igl/viewer/ViewerPlugin.h>
 
 namespace igl
 {

+ 48 - 41
include/igl/viewer/ViewerCore.cpp

@@ -96,52 +96,62 @@ Eigen::Matrix4f translate(
 }
 
 
-
 void igl::ViewerCore::InitSerialization()
 {
-  #ifdef ENABLE_XML_SERIALIZATION
-  xmlSerializer->Add(shininess, "shininess");
-  xmlSerializer->Add(background_color, "background_color");
-  xmlSerializer->Add(line_color, "line_color");
-  xmlSerializer->Add(light_position, "light_position");
-  xmlSerializer->Add(lighting_factor, "lighting_factor");
-  xmlSerializer->Add(trackball_angle, "trackball_angle");
-  xmlSerializer->Add(model_zoom, "model_zoom");
-  xmlSerializer->Add(model_translation, "model_translation");
-  xmlSerializer->Add(model_zoom_uv, "model_zoom_uv");
-  xmlSerializer->Add(model_translation_uv, "model_translation_uv");
-  xmlSerializer->Add(camera_zoom, "camera_zoom");
-  xmlSerializer->Add(orthographic, "orthographic");
-  xmlSerializer->Add(camera_eye, "camera_eye");
-  xmlSerializer->Add(camera_up, "camera_up");
-  xmlSerializer->Add(camera_center, "camera_center");
-  xmlSerializer->Add(camera_view_angle, "camera_view_angle");
-  xmlSerializer->Add(camera_dnear, "camera_dnear");
-  xmlSerializer->Add(camera_dfar, "camera_dfar");
-  xmlSerializer->Add(show_overlay, "show_overlay");
-  xmlSerializer->Add(show_overlay_depth, "show_overlay_depth");
-  xmlSerializer->Add(show_texture, "show_texture");
-  xmlSerializer->Add(show_faces, "show_faces");
-  xmlSerializer->Add(show_lines, "show_lines");
-  xmlSerializer->Add(show_vertid, "show_vertid");
-  xmlSerializer->Add(show_faceid, "show_faceid");
-  xmlSerializer->Add(point_size, "point_size");
-  xmlSerializer->Add(line_width, "line_width");
-  xmlSerializer->Add(invert_normals, "invert_normals");
-  xmlSerializer->Add(face_based, "face_based");
-  xmlSerializer->Add(face_based, "object_scale");
-  xmlSerializer->Add(viewport, "viewport");
-  xmlSerializer->Add(view, "view");
-  xmlSerializer->Add(model, "model");
-  xmlSerializer->Add(proj, "proj");
-
-  #endif
+  Add(shininess, "shininess");
+  
+  Add(background_color, "background_color");
+  Add(line_color, "line_color");
+  
+  Add(light_position, "light_position");
+  Add(lighting_factor, "lighting_factor");
+  
+  Add(trackball_angle, "trackball_angle");
+  
+  Add(model_zoom, "model_zoom");
+  Add(model_translation, "model_translation");
+  
+  Add(model_zoom_uv, "model_zoom_uv");
+  Add(model_translation_uv, "model_translation_uv");
+  
+  Add(object_scale, "object_scale");
+  
+  Add(camera_zoom, "camera_zoom");
+  Add(orthographic, "orthographic");
+  Add(camera_view_angle, "camera_view_angle");
+  Add(camera_dnear, "camera_dnear");
+  Add(camera_dfar, "camera_dfar");
+  Add(camera_eye, "camera_eye");
+  Add(camera_center, "camera_center");
+  Add(camera_up, "camera_up");
+  
+  Add(show_faces, "show_faces");
+  Add(show_lines, "show_lines");
+  Add(invert_normals, "invert_normals");
+  Add(show_overlay, "show_overlay");
+  Add(show_overlay_depth, "show_overlay_depth");
+  Add(show_vertid, "show_vertid");
+  Add(show_faceid, "show_faceid");
+  Add(show_texture, "show_texture");
+  
+  Add(point_size, "point_size");
+  Add(line_width, "line_width");
+  Add(is_animating, "is_animating");
+  Add(animation_max_fps, "animation_max_fps");
+  
+  Add(viewport, "viewport");
+  Add(view, "view");
+  Add(model, "model");
+  Add(proj, "proj");
 }
 
 IGL_INLINE void igl::ViewerCore::align_camera_center(
   const Eigen::MatrixXd& V,
   const Eigen::MatrixXi& F)
 {
+  if(V.rows() == 0)
+    return;
+
   get_scale_and_shift_to_fit_mesh(V,F,model_zoom,model_translation);
   object_scale = (V.colwise().maxCoeff() - V.colwise().minCoeff()).norm();
 }
@@ -357,9 +367,6 @@ IGL_INLINE void igl::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl)
 }
 
 IGL_INLINE igl::ViewerCore::ViewerCore()
-#ifdef ENABLE_XML_SERIALIZATION
-: XMLSerialization("Core")
-#endif
 {
   // Default shininess
   shininess = 35.0f;

+ 9 - 1
include/igl/viewer/ViewerCore.h

@@ -14,6 +14,12 @@
 #include <igl/viewer/ViewerData.h>
 #include <igl/viewer/OpenGL_state.h>
 
+#ifdef ENABLE_XML_SERIALIZATION
+  #include <igl/xml/serialize_xml.h>
+#else
+  #include <igl/serialize.h>
+#endif
+
 namespace igl
 {
 
@@ -22,7 +28,9 @@ namespace igl
 
 class ViewerCore
 #ifdef ENABLE_XML_SERIALIZATION
-: public ::igl::XMLSerialization
+  : public igl::XMLSerializable
+#else
+  : public igl::Serializable
 #endif
 {
 public:

+ 35 - 31
include/igl/viewer/ViewerData.cpp

@@ -13,43 +13,47 @@
 #include <iostream>
 
 IGL_INLINE igl::ViewerData::ViewerData()
-#ifdef ENABLE_XML_SERIALIZATION
-: XMLSerialization("Data"), dirty(DIRTY_ALL)
-#endif
+: dirty(DIRTY_ALL)
 {
   clear();
 };
 
 IGL_INLINE void igl::ViewerData::InitSerialization()
+{  
+  Add(V,"V");
+  Add(F,"F");
+  
+  Add(F_normals,"F_normals");
+
+  Add(F_material_ambient,"F_material_ambient");
+  Add(F_material_diffuse,"F_material_diffuse");
+  Add(F_material_specular,"F_material_specular");
+
+  Add(V_normals,"V_normals");
+  
+  Add(V_material_ambient,"V_material_ambient");
+  Add(V_material_diffuse,"V_material_diffuse");
+  Add(V_material_specular,"V_material_specular");
+
+  Add(V_uv,"V_uv");
+  Add(F_uv,"F_uv");
+  
+  Add(texture_R,"texture_R");
+  Add(texture_G,"texture_G");
+  Add(texture_B,"texture_B");
+
+  Add(lines,"lines");
+  Add(points,"points");
+
+  Add(labels_positions,"labels_positions");
+  Add(labels_strings,"labels_strings");
+
+  Add(face_based,"face_based");
+}
+
+IGL_INLINE void igl::ViewerData::PostDeserialization()
 {
-  #ifdef ENABLE_XML_SERIALIZATION
-  xmlSerializer->Add(V,"V");
-  xmlSerializer->Add(F,"F");
-  xmlSerializer->Add(F_normals,"F_normals");
-
-  xmlSerializer->Add(F_material_ambient,"F_material_ambient");
-  xmlSerializer->Add(F_material_diffuse,"F_material_diffuse");
-  xmlSerializer->Add(F_material_specular,"F_material_specular");
-
-  xmlSerializer->Add(V_normals,"V_normals");
-  xmlSerializer->Add(V_material_ambient,"V_material_ambient");
-  xmlSerializer->Add(V_material_diffuse,"V_material_diffuse");
-  xmlSerializer->Add(V_material_specular,"V_material_specular");
-
-  xmlSerializer->Add(V_uv,"V_uv");
-  xmlSerializer->Add(F_uv,"F_uv");
-  xmlSerializer->Add(texture_R,"texture_R");
-  xmlSerializer->Add(texture_G,"texture_G");
-  xmlSerializer->Add(texture_B,"texture_B");
-  xmlSerializer->Add(lines,"lines");
-  xmlSerializer->Add(points,"points");
-
-  xmlSerializer->Add(labels_positions,"labels_positions");
-  xmlSerializer->Add(labels_strings,"labels_strings");
-
-  xmlSerializer->Add(face_based,"face_based");
-
-  #endif
+  dirty = DIRTY_ALL;
 }
 
 IGL_INLINE void igl::ViewerData::set_face_based(bool newvalue)

+ 10 - 2
include/igl/viewer/ViewerData.h

@@ -12,15 +12,22 @@
 #include <igl/igl_inline.h>
 #include <Eigen/Core>
 
+#ifdef ENABLE_XML_SERIALIZATION
+  #include <igl/xml/serialize_xml.h>
+#else
+  #include <igl/serialize.h>
+#endif
+
 namespace igl
 {
 
-// Store the data visualized by ViewerCore
 // TODO: write documentation
 
 class ViewerData
 #ifdef ENABLE_XML_SERIALIZATION
-: public ::igl::XMLSerialization
+  : public igl::XMLSerializable
+#else
+  : public igl::Serializable
 #endif
 {
 public:
@@ -98,6 +105,7 @@ public:
 
   // Serialization code
   IGL_INLINE void InitSerialization();
+  IGL_INLINE void PostDeserialization();
 
   Eigen::MatrixXd V; // Vertices of the current mesh (#V x 3)
   Eigen::MatrixXi F; // Faces of the mesh (#F x 3)

+ 17 - 7
include/igl/viewer/ViewerPlugin.h

@@ -6,14 +6,20 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 
+// TODO:
+// * create plugins/skeleton.h
+// * pass time in draw function
+// * remove Preview3D from comments
+
 #ifndef IGL_VIEWER_PLUGIN_H
 #define IGL_VIEWER_PLUGIN_H
 #include <string>
 #include <igl/igl_inline.h>
 
 #ifdef ENABLE_XML_SERIALIZATION
-  #include <igl/xml/XMLSerializer.h>
-  #include <igl/xml/XMLSerialization.h>
+  #include <igl/xml/serialize_xml.h>
+#else
+  #include <igl/serialize.h>
 #endif
 
 namespace igl
@@ -34,18 +40,22 @@ class Viewer;
 
 class ViewerPlugin
 #ifdef ENABLE_XML_SERIALIZATION
-: public ::igl::XMLSerialization
+  : public igl::XMLSerializable
+#else
+  : public igl::Serializable
 #endif
 {
 public:
   IGL_INLINE ViewerPlugin()
-  #ifdef ENABLE_XML_SERIALIZATION
-  : XMLSerialization("dummy")
-  #endif
   {plugin_name = "dummy";}
 
   virtual ~ViewerPlugin(){}
 
+  // This is a interface function for the serialization
+  IGL_INLINE virtual void InitSerialization()
+  {
+  }
+
   // This function is called when the viewer is initialized (no mesh will be loaded at this stage)
   IGL_INLINE virtual void init(igl::Viewer *_viewer)
   {
@@ -69,7 +79,7 @@ public:
     return false;
   }
 
-  // Runs immediately after a new mesh had been loaded.
+  // Runs immediately after a new mesh has been loaded.
   IGL_INLINE virtual bool post_load()
   {
     return false;

+ 0 - 194
include/igl/xml/XMLSerialization.h

@@ -1,194 +0,0 @@
-//
-// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_XML_SERIALIZATION_H
-#define IGL_XML_SERIALIZATION_H
-
-#include <igl/xml/serialize_xml.h>
-
-namespace igl
-{
-  class XMLSerialization: public XMLSerializable
-  {
-  private:
-
-    template <typename T>
-    struct XMLSerializationObject: public XMLSerializable
-    {
-      bool Binary;
-      std::string Name;
-      T* Object;
-
-      void Serialize(std::vector<char>& buffer) const {
-        igl::serialize(*Object,Name,buffer);
-      }
-
-      void Deserialize(const std::vector<char>& buffer) {
-        igl::deserialize(*Object,Name,buffer);
-      }
-
-      void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const {
-        igl::serialize_xml(*Object,Name,doc,element,Binary);
-      }
-
-      void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element) {
-        igl::deserialize_xml(*Object,Name,doc,element);
-      }
-    };
-
-    mutable bool initialized;
-    mutable std::vector<XMLSerializable*> objects;
-
-  public:
-
-    /**
-    * Override this function to add your member variables which should be
-    * serialized:
-    *
-    * this->Add(var1);
-    * this->Add(var2);
-    * ...
-    */
-    virtual void InitSerialization() = 0;
-
-    /**
-    * Following functions can be overridden to handle the specific events.
-    * Return false to prevent the de-/serialization of an object.
-    */
-    virtual bool BeforeSerialization() const { return true; }
-    virtual void AfterSerialization() const {}
-    virtual bool BeforeDeserialization() { return true; }
-    virtual void AfterDeserialization() {}
-
-    /**
-    * Default implementation of XMLSerializable interface
-    */
-    void Serialize(std::vector<char>& buffer) const
-    {
-      if(this->BeforeSerialization())
-      {
-        if(initialized == false)
-        {
-          objects.clear();
-          (const_cast<XMLSerialization*>(this))->InitSerialization();
-          initialized = true;
-        }
-
-        for(unsigned int i=0;i<objects.size();i++)
-          objects[i]->Serialize(buffer);
-
-        this->AfterSerialization();
-      }
-    }
-
-    void Deserialize(const std::vector<char>& buffer)
-    {
-      if(this->BeforeDeserialization())
-      {
-        if(initialized == false)
-        {
-          objects.clear();
-          (const_cast<XMLSerialization*>(this))->InitSerialization();
-          initialized = true;
-        }
-
-        for(unsigned int i=0;i<objects.size();i++)
-          objects[i]->Deserialize(buffer);
-
-        this->AfterDeserialization();
-      }
-    }
-
-    void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const
-    {
-      if(this->BeforeSerialization())
-      {
-        if(initialized == false)
-        {
-          objects.clear();
-          (const_cast<XMLSerialization*>(this))->InitSerialization();
-          initialized = true;
-        }
-
-        for(unsigned int i=0;i<objects.size();i++)
-          objects[i]->Serialize(doc,element);
-
-        this->AfterSerialization();
-      }
-    }
-
-    void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
-    {
-      if(this->BeforeDeserialization())
-      {
-        if(initialized == false)
-        {
-          objects.clear();
-          (const_cast<XMLSerialization*>(this))->InitSerialization();
-          initialized = true;
-        }
-
-        for(unsigned int i=0;i<objects.size();i++)
-          objects[i]->Deserialize(doc,element);
-
-        this->AfterDeserialization();
-      }
-    }
-
-    /**
-    * Default constructor, destructor, assignment and copy constructor
-    */
-
-    XMLSerialization()
-    {
-      initialized = false;
-    }
-
-    XMLSerialization(const XMLSerialization& obj)
-    {
-      initialized = false;
-      objects.clear();
-    }
-
-    ~XMLSerialization()
-    {
-      initialized = false;
-      objects.clear();
-    }
-
-
-    XMLSerialization& operator=(const XMLSerialization& obj)
-    {
-      if(this != &obj)
-      {
-        if(initialized)
-        {
-          initialized = false;
-          objects.clear();
-        }
-      }
-      return *this;
-    }
-
-    /**
-    * Use this function to add your variables which should be serialized.
-    */
-
-    template <typename T>
-    void Add(T& obj,std::string name, bool binary = false)
-    {
-      XMLSerializationObject<T>* object = new XMLSerializationObject<T>();
-      object->Binary = binary;
-      object->Name = name;
-      object->Object = &obj;
-
-      objects.push_back(object);
-    }
-  };
-
-}
-
-#endif

+ 1 - 1
include/igl/xml/old_version/XMLSerializable.h

@@ -4,7 +4,7 @@
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
- ------------------------------------------------------------------------------
+/* ------------------------------------------------------------------------------
  Inherit from this abstract class to have full control over the serialization
  of your user defined class.
  ----------------------------------------------------------------------------*/

+ 1 - 1
include/igl/xml/old_version/XMLSerializer.h.REMOVED.git-id

@@ -1 +1 @@
-681d2916ad693666eda6e41efaf85b0cc14f2dfd
+172f806cdef073e1613fe0def62c0521976222bd

+ 17 - 8
include/igl/xml/serialization_test.cpp

@@ -9,7 +9,6 @@
 
 //#include <igl/Timer.h>
 #include <igl/xml/serialize_xml.h>
-#include <igl/xml/XMLSerialization.h>
 
 namespace igl
 {
@@ -18,7 +17,7 @@ namespace igl
   {
   };
 
-  struct Test1 : public XMLSerialization
+  struct Test1 : public XMLSerializable
   {
     std::string ts;
     std::vector<Test1*> tvt;
@@ -37,7 +36,7 @@ namespace igl
     }
   };
 
-  struct Test2: public igl::XMLSerializable
+  struct Test2: public igl::XMLSerializableBase
   {
     char tc;
     int* ti;
@@ -201,6 +200,18 @@ namespace igl
     igl::deserialize(tstrOut,file);
     assert(tstrIn == tstrOut);
 
+    // updating
+    igl::serialize(tsIn,"tsIn",file);
+    igl::serialize(tVector1In,"tVector1In",file,true);
+    igl::serialize(tVector2In,"tsIn",file,true);
+    igl::deserialize(tVector2Out,"tsIn",file);
+    for(unsigned int i=0;i<tVector2In.size();i++)
+    {
+      assert(tVector2In[i].first == tVector2Out[i].first);
+      assert(tVector2In[i].second == tVector2Out[i].second);
+    }
+    tVector2Out.clear();
+
     igl::serialize(tObjIn,file);
     igl::deserialize(tObjOut,file);
     assert(tObjIn.tc == tObjOut.tc);
@@ -335,16 +346,14 @@ namespace igl
 
     // updating
     igl::serialize_xml(tsIn,"tsIn",file);
-    igl::serialize_xml(tVector2In,"tVector2In",file,false,true);
-    igl::deserialize_xml(tVector2Out,"tVector2In",file);
-    igl::deserialize_xml(tsOut,"tsIn",file);
-    assert(tsIn == tsOut);
+    igl::serialize_xml(tVector1In,"tVector1In",file,false,true);
+    igl::serialize_xml(tVector2In,"tsIn",file,false,true);
+    igl::deserialize_xml(tVector2Out,"tsIn",file);
     for(unsigned int i=0;i<tVector2In.size();i++)
     {
       assert(tVector2In[i].first == tVector2Out[i].first);
       assert(tVector2In[i].second == tVector2Out[i].second);
     }
-    tsOut = 0;
     tVector2Out.clear();
 
     // binarization

+ 151 - 12
include/igl/xml/serialize_xml.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2014 Christian Schller <schuellchr@gmail.com>
+// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
 //
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -16,11 +16,11 @@ namespace igl
   }
 
   template <typename T>
-  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename,bool binary,bool overwrite)
+  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename,bool binary,bool update)
   {
     tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
 
-    if(overwrite)
+    if(update)
     {
       // Check if file exists
       tinyxml2::XMLError error = doc->LoadFile(filename.c_str());
@@ -57,13 +57,20 @@ namespace igl
     std::string name(objectName);
     detail_xml::encodeXMLElementName(name);
 
+    tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
+    
+    if(child != NULL)
+      element->DeleteChild(child);
+
+    child = doc->NewElement(name.c_str());
+    element->InsertEndChild(child);
+
     if(binary)
     {
       std::vector<char> buffer;
       serialize(obj,name,buffer);
       std::string data = detail_xml::base64_encode(reinterpret_cast<const unsigned char*>(buffer.data()),buffer.size());
-
-      tinyxml2::XMLElement* child = detail_xml::getElement(doc,element,name);
+      
       child->SetAttribute("binary",true);
 
       detail_xml::serialize(data,doc,element,name);
@@ -140,6 +147,138 @@ namespace igl
     }
   }
 
+  IGL_INLINE bool XMLSerializable::PreSerialization() const
+  { 
+    return true;
+  }
+  
+  IGL_INLINE void XMLSerializable::PostSerialization() const
+  {
+  }
+  
+  IGL_INLINE bool XMLSerializable::PreDeserialization()
+  { 
+    return true;
+  }
+
+  IGL_INLINE void XMLSerializable::PostDeserialization() 
+  {
+  }
+
+  IGL_INLINE void XMLSerializable::Serialize(std::vector<char>& buffer) const
+  {
+    if(this->PreSerialization())
+    {
+      if(initialized == false)
+      {
+        objects.clear();
+        (const_cast<XMLSerializable*>(this))->InitSerialization();
+        initialized = true;
+      }
+
+      for(unsigned int i=0;i<objects.size();i++)
+        objects[i]->Serialize(buffer);
+
+      this->PostSerialization();
+    }
+  }
+
+  IGL_INLINE void XMLSerializable::Deserialize(const std::vector<char>& buffer)
+  {
+    if(this->PreDeserialization())
+    {
+      if(initialized == false)
+      {
+        objects.clear();
+        (const_cast<XMLSerializable*>(this))->InitSerialization();
+        initialized = true;
+      }
+
+      for(unsigned int i=0;i<objects.size();i++)
+        objects[i]->Deserialize(buffer);
+
+      this->PostDeserialization();
+    }
+  }
+
+  IGL_INLINE void XMLSerializable::Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const
+  {
+    if(this->PreSerialization())
+    {
+      if(initialized == false)
+      {
+        objects.clear();
+        (const_cast<XMLSerializable*>(this))->InitSerialization();
+        initialized = true;
+      }
+
+      for(unsigned int i=0;i<objects.size();i++)
+        objects[i]->Serialize(doc,element);
+
+      this->PostSerialization();
+    }
+  }
+
+  IGL_INLINE void XMLSerializable::Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
+  {
+    if(this->PreDeserialization())
+    {
+      if(initialized == false)
+      {
+        objects.clear();
+        (const_cast<XMLSerializable*>(this))->InitSerialization();
+        initialized = true;
+      }
+
+      for(unsigned int i=0;i<objects.size();i++)
+        objects[i]->Deserialize(doc,element);
+
+      this->PostDeserialization();
+    }
+  }
+
+  IGL_INLINE XMLSerializable::XMLSerializable()
+  {
+    initialized = false;
+  }
+
+  IGL_INLINE XMLSerializable::XMLSerializable(const XMLSerializable& obj)
+  {
+    initialized = false;
+    objects.clear();
+  }
+
+  IGL_INLINE XMLSerializable::~XMLSerializable()
+  {
+    initialized = false;
+    objects.clear();
+  }
+
+
+  IGL_INLINE XMLSerializable& XMLSerializable::operator=(const XMLSerializable& obj)
+  {
+    if(this != &obj)
+    {
+      if(initialized)
+      {
+        initialized = false;
+        objects.clear();
+      }
+    }
+    return *this;
+  }
+
+  template <typename T>
+  IGL_INLINE void XMLSerializable::Add(T& obj,std::string name,bool binary)
+  {
+    XMLSerializationObject<T>* object = new XMLSerializationObject<T>();
+    object->Binary = binary;
+    object->Name = name;
+    object->Object = &obj;
+
+    objects.push_back(object);
+  }
+
   namespace detail_xml
   {
     // fundamental types
@@ -189,17 +328,17 @@ namespace igl
     // Serializable
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializable,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
+    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
     {
       // Serialize object implementing Serializable interface
-      const XMLSerializable& object = dynamic_cast<const XMLSerializable&>(obj);
+      const XMLSerializableBase& object = dynamic_cast<const XMLSerializableBase&>(obj);
 
       tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
       object.Serialize(doc,child);
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializable,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
+    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
     {
       const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
 
@@ -634,16 +773,16 @@ namespace igl
       tinyxml2::XMLUtil::ToDouble(src,&dest);
     }
 
-    IGL_INLINE template<typename T>
-    typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
+    template<typename T>
+    IGL_INLINE typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
     {
       unsigned int val;
       tinyxml2::XMLUtil::ToUnsigned(src,&val);
       dest = (T)val;
     }
 
-    IGL_INLINE template<typename T>
-    typename std::enable_if<std::is_integral<T>::value && !std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
+    template<typename T>
+    IGL_INLINE typename std::enable_if<std::is_integral<T>::value && !std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
     {
       int val;
       tinyxml2::XMLUtil::ToInt(src,&val);

+ 68 - 26
include/igl/xml/serialize_xml.h

@@ -8,7 +8,7 @@
 // Functions to save and load a serialization of fundamental c++ data types to
 // and from a xml file. STL containers, Eigen matrix types and nested data
 // structures are also supported. To serialize a user defined class implement
-// the interface XMLSerializable.
+// the interface XMLSerializable or XMLSerializableBase.
 //
 // See also: serialize.h
 // -----------------------------------------------------------------------------
@@ -53,7 +53,7 @@ namespace igl
   template <typename T>
   IGL_INLINE void serialize_xml(const T& obj,const std::string& filename);
   template <typename T>
-  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename, bool binary = false,bool overwrite = false);
+  IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename, bool binary = false,bool update = false);
   template <typename T>
   IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,bool binary = false);
 
@@ -80,32 +80,74 @@ namespace igl
   IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element);
 
   // interface for user defined types
-  struct XMLSerializable : public Serializable
+  struct XMLSerializableBase : public SerializableBase
   {
     virtual void Serialize(std::vector<char>& buffer) const = 0;
     virtual void Deserialize(const std::vector<char>& buffer) = 0;
     virtual void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const = 0;
     virtual void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element) = 0;
   };
-  // example:
-  //
-  // class Test : public igl::Serializable {
-  //
-  //   int var;
-  //
-  //   void Serialize(std::vector<char>& buffer) {
-  //     serialize(var,"var1",buffer);
-  //   }
-  //   void Deserialize(const std::vector<char>& buffer) {
-  //     deserialize(var,"var1",buffer);
-  //   }
-  //   void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const {
-  //     serialize_xml(var,"var1",doc,element);
-  //   }
-  //   void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element) {
-  //     deserialize_xml(var,"var1",doc,element);
-  //   }
-  // }
+
+  // Convenient interface for user defined types
+  class XMLSerializable: public XMLSerializableBase
+  {
+  private:
+
+    template <typename T>
+    struct XMLSerializationObject: public XMLSerializableBase
+    {
+      bool Binary;
+      std::string Name;
+      T* Object;
+
+      void Serialize(std::vector<char>& buffer) const {
+        igl::serialize(*Object,Name,buffer);
+      }
+
+      void Deserialize(const std::vector<char>& buffer) {
+        igl::deserialize(*Object,Name,buffer);
+      }
+
+      void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const {
+        igl::serialize_xml(*Object,Name,doc,element,Binary);
+      }
+
+      void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element) {
+        igl::deserialize_xml(*Object,Name,doc,element);
+      }
+    };
+
+    mutable bool initialized;
+    mutable std::vector<XMLSerializableBase*> objects;
+
+  public:
+
+    // Override this function to add your member variables which should be serialized
+    IGL_INLINE virtual void InitSerialization() = 0;
+
+    // Following functions can be overridden to handle the specific events.
+    // Return false to prevent the de-/serialization of an object.
+    IGL_INLINE virtual bool PreSerialization() const;
+    IGL_INLINE virtual void PostSerialization() const;
+    IGL_INLINE virtual bool PreDeserialization();
+    IGL_INLINE virtual void PostDeserialization();
+
+    // Default implementation of XMLSerializable interface
+    IGL_INLINE void Serialize(std::vector<char>& buffer) const;
+    IGL_INLINE void Deserialize(const std::vector<char>& buffer);
+    IGL_INLINE void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const;
+    IGL_INLINE void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element);
+
+    // Default constructor, destructor, assignment and copy constructor
+    IGL_INLINE XMLSerializable();
+    IGL_INLINE XMLSerializable(const XMLSerializable& obj);
+    IGL_INLINE ~XMLSerializable();
+    IGL_INLINE XMLSerializable& operator=(const XMLSerializable& obj);
+
+    // Use this function to add your variables which should be serialized
+    template <typename T>
+    IGL_INLINE void Add(T& obj,std::string name,bool binary = false);
+  };
 
   // internal functions
   namespace detail_xml
@@ -120,11 +162,11 @@ namespace igl
     IGL_INLINE void serialize(const std::string& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
     IGL_INLINE void deserialize(std::string& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
 
-    // Serializable
+    // XMLSerializableBase
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializable,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
+    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializable,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
+    IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
 
     // STL containers
     template <typename T1, typename T2>
@@ -203,7 +245,7 @@ namespace igl
     template <typename T>
     struct is_serializable {
       using T0 = typename  std::remove_pointer<T>::type;
-      static const bool value = std::is_fundamental<T0>::value || std::is_same<std::string,T0>::value || std::is_base_of<Serializable,T0>::value
+      static const bool value = std::is_fundamental<T0>::value || std::is_same<std::string,T0>::value || std::is_base_of<XMLSerializableBase,T0>::value
         || is_stl_container<T0>::value || is_eigen_type<T0>::value;
     };
   }

+ 1 - 0
tutorial/402_PolyharmonicDeformation/main.cpp

@@ -52,6 +52,7 @@ bool key_down(igl::Viewer &viewer, unsigned char key, int mods)
       resolve = true;
       break;
   }
+  return true;
 }
 
 int main(int argc, char *argv[])

+ 1 - 0
tutorial/403_BoundedBiharmonicWeights/main.cpp

@@ -110,6 +110,7 @@ bool key_down(igl::Viewer &viewer, unsigned char key, int mods)
       set_color(viewer);
       break;
   }
+  return true;
 }
 
 int main(int argc, char *argv[])

+ 1 - 1
tutorial/501_HarmonicParam/main.cpp

@@ -31,7 +31,7 @@ bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
 int main(int argc, char *argv[])
 {
   // Load a mesh in OFF format
-  igl::readOFF("../shared/camelhead.off", V, F);
+  igl::readOFF("D:/libraries/libigl/tutorial/shared/camelhead.off", V, F);
 
   // Find the open boundary
   Eigen::VectorXi bnd;

+ 1 - 1
tutorial/CMakeLists.shared

@@ -67,7 +67,7 @@ link_directories(
 add_definitions(-DIGL_OPENGL_4)
 add_definitions(-DNDEBUG)
 add_definitions(-O3)
-add_definitions(-DENABLE_XML_SERIALIZATION)
+#add_definitions(-DENABLE_XML_SERIALIZATION)
 
 
 

+ 1 - 0
tutorial/cmake/FindEIGEN.cmake

@@ -66,6 +66,7 @@ else ()
       ${CMAKE_INSTALL_PREFIX}/include
       ${KDE4_INCLUDE_DIR}
 	  ${PROJECT_SOURCE_DIR}/../../../Eigen
+	  $ENV{DevLibraries}/Eigen
       PATH_SUFFIXES eigen3 eigen
     )