diff --git a/IO/CMakeLists.txt b/IO/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..75392f8fe006488315d867a9a5db8efb7805ee73
--- /dev/null
+++ b/IO/CMakeLists.txt
@@ -0,0 +1,29 @@
+
+simmedtk_add_library(IO
+  SOURCES
+    IOMesh.cpp
+    IOMeshAssimpDelegate.cpp
+    IOMeshVegaDelegate.cpp
+    IOMeshVTKDelegate.cpp
+  PUBLIC_HEADERS
+    Mesh.h
+    SurfaceMesh.h
+    VolumeMesh.h
+    VegaSceneObject.h
+    VegaSceneObjectDeformable.h
+    VegaSceneObjectWithRestPosition.h
+)
+
+target_link_libraries(Mesh
+  PRIVATE
+    Core
+    Rendering
+  PUBLIC
+    Assimp::Assimp
+    VegaFEM::minivector
+    VegaFEM::volumetricMesh
+    )
+
+if(BUILD_TESTING)
+  add_subdirectory(UnitTests)
+endif()
diff --git a/InputOutput/IOMesh.cpp b/IO/IOMesh.cpp
similarity index 77%
rename from InputOutput/IOMesh.cpp
rename to IO/IOMesh.cpp
index 79d2f00c214da645ae4ab674749e3463214582d6..c7dd2dd043f8e096830d1a2752aff96133209d39 100644
--- a/InputOutput/IOMesh.cpp
+++ b/IO/IOMesh.cpp
@@ -23,11 +23,13 @@
 
 #include"IOMesh.h"
 
-IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : mesh(nullptr), fileName(""), fileType(MeshFileType::Unknown)
+IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : fileName(""), fileType(MeshFileType::Unknown), mesh(nullptr)
 {
+    //
+    // VTK io for some vtk files (use only vtk to read these files)
     delegatorList[MeshFileType::VTK] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createDefault("VTKMeshReaderDelegate");
+        auto delegate = Factory<IOMeshDelegate>::createDefault("VTKMeshReaderDelegate");
         if(delegate)
         {
             delegate->setSource(source);
@@ -36,7 +38,7 @@ IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : mesh(nullptr), fileName(""),
     };
     delegatorList[MeshFileType::VTU] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createDefault("VTKMeshReaderDelegate");
+        auto delegate = Factory<IOMeshDelegate>::createDefault("VTKMeshReaderDelegate");
         if(delegate)
         {
             delegate->setSource(source);
@@ -45,34 +47,29 @@ IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : mesh(nullptr), fileName(""),
     };
     delegatorList[MeshFileType::VTP] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createDefault("VTKMeshReaderDelegate");
-        if(delegate)
-        {
-            delegate->setSource(source);
-        }
-        return delegate;
-    };
-    delegatorList[MeshFileType::VTP] = [](std::shared_ptr<IOMesh> source)
-    {
-        auto delegate = Factory<IODelegate>::createDefault("VTKMeshReaderDelegate");
+        auto delegate = Factory<IOMeshDelegate>::createDefault("VTKMeshReaderDelegate");
         if(delegate)
         {
             delegate->setSource(source);
         }
         return delegate;
     };
+    //
+    // Set the vega io, only vega can read/write those files
     delegatorList[MeshFileType::VEG] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createDefault("VegaMeshDelegate");
+        auto delegate = Factory<IOMeshDelegate>::createDefault("VegaMeshDelegate");
         if(delegate)
         {
             delegate->setSource(source);
         }
         return delegate;
     };
+    //
+    // The readers for obj,stl and ply are based on a priority group (defaults to vtk io's)
     delegatorList[MeshFileType::OBJ] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createSubclassForGroup("IODelegate",priorityGroup);
+        auto delegate = Factory<IOMeshDelegate>::createSubclassForGroup("IOMeshDelegate",priorityGroup);
         if(delegate)
         {
             delegate->setSource(source);
@@ -81,7 +78,7 @@ IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : mesh(nullptr), fileName(""),
     };
     delegatorList[MeshFileType::STL] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createSubclassForGroup("IODelegate",priorityGroup);
+        auto delegate = Factory<IOMeshDelegate>::createSubclassForGroup("IOMeshDelegate",priorityGroup);
         if(delegate)
         {
             delegate->setSource(source);
@@ -90,7 +87,7 @@ IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : mesh(nullptr), fileName(""),
     };
     delegatorList[MeshFileType::PLY] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createSubclassForGroup("IODelegate",priorityGroup);
+        auto delegate = Factory<IOMeshDelegate>::createSubclassForGroup("IOMeshDelegate",priorityGroup);
         if(delegate)
         {
             delegate->setSource(source);
@@ -99,7 +96,7 @@ IOMesh::IOMesh(IOMesh::ReaderGroup priorityGroup) : mesh(nullptr), fileName(""),
     };
     delegatorList[MeshFileType::Unknown] = [](std::shared_ptr<IOMesh> source)
     {
-        auto delegate = Factory<IODelegate>::createSubclassForGroup("IODelegate",ReaderGroup::Assimp);
+        auto delegate = Factory<IOMeshDelegate>::createSubclassForGroup("IOMeshDelegate",ReaderGroup::Assimp);
         if(delegate)
         {
             delegate->setSource(source);
@@ -119,7 +116,7 @@ void IOMesh::read(const std::string& filePath)
     }
     else
     {
-        std::cerr << "Error: Invalid reader!" << std::endl;
+        std::cerr << "Error: No reader found for " << this->fileName << std::endl;
     }
 
 }
diff --git a/InputOutput/IOMesh.h b/IO/IOMesh.h
similarity index 73%
rename from InputOutput/IOMesh.h
rename to IO/IOMesh.h
index c90c82281a1db2f6a490a18f58b1683f988c80d4..95f76ead651d2b403a69da7d9d44fba8c1faa0ce 100644
--- a/InputOutput/IOMesh.h
+++ b/IO/IOMesh.h
@@ -28,14 +28,23 @@
 #include <memory>
 #include <unordered_map>
 
-#include "InputOutput/IODelegate.h"
+#include "InputOutput/IOMeshDelegate.h"
 #include "Core/Factory.h"
 #include "Core/BaseMesh.h"
 
-class IOMesh : public std::enable_shared_from_this<IOMesh>
+///
+/// \brief Mesh input/output class. This class is used to read meshes on several formats.
+///  Users can add more readers by implementing delegates for a particular reader
+///     \see \VTKMeshDelegate, \VegaMeshDelegarte and \AssimpMeshDelegate
+///
+class IOMesh
 {
-    typedef std::function<std::shared_ptr<IODelegate>(std::shared_ptr<IOMesh>)> DelegatorType;
+    typedef std::function<std::shared_ptr<IOMeshDelegate>(std::shared_ptr<IOMesh>)> DelegatorType;
 public:
+    ///
+    /// \brief Enum class for the type of files this mesh io expect,
+    ///         add more types here to extend the mesh io.
+    ///
     enum class MeshFileType
     {
         VTK,
@@ -48,6 +57,10 @@ public:
         Unknown
     };
 
+
+    ///
+    /// \brief Enum class for the readers group. Used to prioritize the io delegates in the factory.
+    ///
     enum class ReaderGroup : int
     {
         VTK,
@@ -55,6 +68,10 @@ public:
         Vega,
         Other
     };
+
+    ///
+    /// \brief Constructor/Destructors
+    ///
     IOMesh(ReaderGroup priorityGroup = ReaderGroup::VTK);
     ~IOMesh();
 
@@ -89,9 +106,16 @@ public:
     const MeshFileType &getFileType() const;
 
 private:
-    std::shared_ptr<Core::BaseMesh> mesh;
+    // Storage for the mesh file name, used by delegates.
     std::string fileName;
+
+    // Storage for the file type, used by delegates.
     MeshFileType fileType;
+
+    // Mesh pointer.
+    std::shared_ptr<Core::BaseMesh> mesh;
+
+    // Map file types with reader delegates.
     std::unordered_map<MeshFileType,DelegatorType> delegatorList;
 };
 
diff --git a/InputOutput/AssimpMeshDelegate.cpp b/IO/IOMeshAssimpDelegate.cpp
similarity index 90%
rename from InputOutput/AssimpMeshDelegate.cpp
rename to IO/IOMeshAssimpDelegate.cpp
index da09f9fd7e6fc68c2d32c7343b4b1d39c5debf63..aa8bdf8cdbbae0fedb6520dfe593c494fea887c7 100644
--- a/InputOutput/AssimpMeshDelegate.cpp
+++ b/IO/IOMeshAssimpDelegate.cpp
@@ -23,14 +23,15 @@
 
 
 #include "Core/Factory.h"
-#include "InputOutput/IODelegate.h"
+#include "InputOutput/IOMeshDelegate.h"
+#include "Mesh/SurfaceMesh.h"
 
 // Assimp includes
 #include <assimp/Importer.hpp>
 #include <assimp/scene.h>
 #include <assimp/postprocess.h>
 
-class AssimpMeshDelegate : IODelegate
+class AssimpMeshDelegate : IOMeshDelegate
 {
 public:
     void read()
@@ -61,7 +62,8 @@ public:
         // Extract the information from the aiScene's mesh objects
         aiMesh *mesh = scene->mMeshes[0]; //Guarenteed to have atleast one mesh
 
-        auto &vertices = this->meshIO->getMesh()->getVertices();
+        auto localMesh = std::make_shared<SurfaceMesh>();
+        auto &vertices = localMesh->getVertices();
 
         vertices.reserve(mesh->mNumVertices);
 
@@ -72,7 +74,7 @@ public:
                                   mesh->mVertices[i][1],
                                   mesh->mVertices[i][2]);
         }
-        this->meshIO->getMesh()->updateOriginalVertsWithCurrent();
+        localMesh->updateOriginalVertsWithCurrent();
 
         // Get indexed texture coordinate data
         if (mesh->HasTextureCoords(0))
@@ -93,7 +95,7 @@ public:
             }
         }
 
-        auto &triangles = this->meshIO->getMesh()->getTriangles();
+        auto &triangles = localMesh->getTriangles();
         triangles.reserve(mesh->mNumFaces);
 
         // Setup triangle/face data
@@ -111,13 +113,13 @@ public:
                                    mesh->mFaces[i].mIndices[2]);
         }
 
-        return true;
+        this->meshIO->setMesh(localMesh);
     }
     void write(){}
 };
 
 SIMMEDTK_BEGIN_DYNAMIC_LOADER()
   SIMMEDTK_BEGIN_ONLOAD(register_AssimpMeshReaderDelegate)
-    SIMMEDTK_REGISTER_CLASS(IODelegate,IODelegate,AssimpMeshDelegate,IOMesh::ReaderGroup::Assimp);
+    SIMMEDTK_REGISTER_CLASS(IOMeshDelegate,IOMeshDelegate,AssimpMeshDelegate,IOMesh::ReaderGroup::Assimp);
   SIMMEDTK_FINISH_ONLOAD()
 SIMMEDTK_FINISH_DYNAMIC_LOADER()
diff --git a/InputOutput/IODelegate.h b/IO/IOMeshDelegate.h
similarity index 94%
rename from InputOutput/IODelegate.h
rename to IO/IOMeshDelegate.h
index 9b3473bdeb194a4b744ace4aedf74de7890d028d..8b726707a129116af1ec5721a3c2bd72539a1794 100644
--- a/InputOutput/IODelegate.h
+++ b/IO/IOMeshDelegate.h
@@ -30,10 +30,10 @@
 #include "InputOutput/IOMesh.h"
 #include "Core/Config.h"
 
-class IODelegate
+class IOMeshDelegate
 {
 public:
-    typedef std::shared_ptr<IODelegate> Ptr;
+    typedef std::shared_ptr<IOMeshDelegate> Ptr;
 
 public:
     setSource(std::shared_ptr<IOMesh> src)
diff --git a/InputOutput/VTKMeshDelegate.cpp b/IO/IOMeshVTKDelegate.cpp
similarity index 97%
rename from InputOutput/VTKMeshDelegate.cpp
rename to IO/IOMeshVTKDelegate.cpp
index 0b91e6d012abb96780ce490df59d140d798a998a..2ae133052363db484b5f0e575391d7213cc201a5 100644
--- a/InputOutput/VTKMeshDelegate.cpp
+++ b/IO/IOMeshVTKDelegate.cpp
@@ -22,7 +22,7 @@
 // Contact:
 //---------------------------------------------------------------------------
 
-#include "InputOutput/IODelegate.h"
+#include "InputOutput/IOMeshDelegate.h"
 #include "Core/Factory.h"
 
 // VTK includes
@@ -36,7 +36,7 @@
 #include <vtkPLYReader.h>
 #include <vtkSTLReader.h>
 
-class VTKMeshDelegate : IODelegate
+class VTKMeshDelegate : IOMeshDelegate
 {
 public:
     void read()
@@ -203,6 +203,6 @@ public:
 
 SIMMEDTK_BEGIN_DYNAMIC_LOADER()
 SIMMEDTK_BEGIN_ONLOAD(register_VTKMeshReaderDelegate)
-SIMMEDTK_REGISTER_CLASS(IODelegate, IODelegate, VTKMeshDelegate, IOMesh::ReaderGroup::VTK);
+SIMMEDTK_REGISTER_CLASS(IOMeshDelegate, IOMeshDelegate, VTKMeshDelegate, IOMesh::ReaderGroup::VTK);
 SIMMEDTK_FINISH_ONLOAD()
 SIMMEDTK_FINISH_DYNAMIC_LOADER()
diff --git a/InputOutput/VegaMeshDelegate.cpp b/IO/IOMeshVegaDelegate.cpp
similarity index 92%
rename from InputOutput/VegaMeshDelegate.cpp
rename to IO/IOMeshVegaDelegate.cpp
index c75981785e560abc15701232c00dc9d09caa7955..225773ff775a058d946f09c79c3cb7e9f9b40be2 100644
--- a/InputOutput/VegaMeshDelegate.cpp
+++ b/IO/IOMeshVegaDelegate.cpp
@@ -25,7 +25,7 @@
 
 
 #include "Core/Factory.h"
-#include "InputOutput/IODelegate.h"
+#include "InputOutput/IOMeshDelegate.h"
 #include "Mesh//VegaVolumetricMesh.h"
 
 // Vega includes
@@ -33,7 +33,7 @@
 #include "cubicMesh.h"
 #include "tetMesh.h"
 
-class VegaMeshDelegate : IODelegate
+class VegaMeshDelegate : IOMeshDelegate
 {
 public:
     void read()
@@ -72,6 +72,6 @@ public:
 
 SIMMEDTK_BEGIN_DYNAMIC_LOADER()
 SIMMEDTK_BEGIN_ONLOAD(register_VegaMeshReaderDelegate)
-SIMMEDTK_REGISTER_CLASS(IODelegate, IODelegate, VegaMeshDelegate, IOMesh::ReaderGroup::Vega);
+SIMMEDTK_REGISTER_CLASS(IOMeshDelegate, IOMeshDelegate, VegaMeshDelegate, IOMesh::ReaderGroup::Vega);
 SIMMEDTK_FINISH_ONLOAD()
 SIMMEDTK_FINISH_DYNAMIC_LOADER()
diff --git a/InputOutput/CMakeLists.txt b/InputOutput/CMakeLists.txt
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000