diff --git a/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp
index 26302f702..b12ed5551 100644
--- a/src/libslic3r/BoundingBox.hpp
+++ b/src/libslic3r/BoundingBox.hpp
@@ -161,4 +161,15 @@ inline bool empty(const BoundingBox3Base<VT> &bb)
 
 } // namespace Slic3r
 
+#include <cereal/types/polymorphic.hpp>
+#include <cereal/archives/binary.hpp>
+
+// Serialization through the Cereal library
+namespace cereal {
+	template<class Archive> void serialize(Archive& archive, Slic3r::BoundingBox   &bb) { archive(bb.min, bb.max, bb.defined); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::BoundingBox3  &bb) { archive(bb.min, bb.max, bb.defined); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::BoundingBoxf  &bb) { archive(bb.min, bb.max, bb.defined); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::BoundingBoxf3 &bb) { archive(bb.min, bb.max, bb.defined); }
+}
+
 #endif
diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp
index 7b3c5c73a..d1fb9b7f4 100644
--- a/src/libslic3r/Config.hpp
+++ b/src/libslic3r/Config.hpp
@@ -744,7 +744,7 @@ public:
 
 private:
 	friend class cereal::access;
-	template<class Archive> void serialize(Archive &ar) { ar(this->value.x(), this->value.y()); }
+	template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<Vec2d>>(this)); }
 };
 
 class ConfigOptionPoints : public ConfigOptionVector<Vec2d>
@@ -853,7 +853,7 @@ public:
 
 private:
 	friend class cereal::access;
-	template<class Archive> void serialize(Archive &ar) { ar(this->value.x(), this->value.y(), this->value.z()); }
+	template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<Vec3d>>(this)); }
 };
 
 class ConfigOptionBool : public ConfigOptionSingle<bool>
diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp
index bcbe80a0d..f1987734f 100644
--- a/src/libslic3r/Geometry.hpp
+++ b/src/libslic3r/Geometry.hpp
@@ -7,6 +7,10 @@
 #include "Polygon.hpp"
 #include "Polyline.hpp"
 
+// Serialization through the Cereal library
+#include <cereal/types/polymorphic.hpp>
+#include <cereal/archives/binary.hpp>
+
 #include "boost/polygon/voronoi.hpp"
 using boost::polygon::voronoi_builder;
 using boost::polygon::voronoi_diagram;
@@ -263,6 +267,25 @@ public:
     // as possible in least squares norm in regard to the 8 corners of bbox.
     // Bounding box is expected to be centered around zero in all axes.
     static Transformation volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox);
+
+private:
+	template<class Archive> void load(Archive& archive, Slic3r::Geometry::Transformation &t) { 
+		archive.loadBinary((char*)m.data(), sizeof(float) * 4);
+	}
+	template<class Archive> void save(Archive& archive, const Slic3r::Geometry::Transformation &t) const {
+		archive.saveBinary((char*)m.data(), sizeof(float) * 4);
+	}
+
+private:
+	friend class cereal::access;
+	template<class Archive> void serialize(Archive & ar) { ar(m_offset, m_rotation, m_scaling_factor, m_mirror); }
+	explicit Transformation(int) : m_dirty(true) {}
+	template <class Archive> static void load_and_construct(Archive & ar, cereal::construct<Transformation> &construct)
+	{
+		// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
+		construct(1);
+		ar(construct.ptr()->m_offset, construct.ptr()->m_rotation, construct.ptr()->m_scaling_factor, m_mirror);
+	}
 };
 
 // Rotation when going from the first coordinate system with rotation rot_xyz_from applied
diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp
index 596f80671..da7d9e4d3 100644
--- a/src/libslic3r/Model.cpp
+++ b/src/libslic3r/Model.cpp
@@ -1910,3 +1910,16 @@ void check_model_ids_equal(const Model &model1, const Model &model2)
 #endif /* NDEBUG */
 
 }
+
+#if 0
+CEREAL_REGISTER_TYPE(Slic3r::ModelBase)
+CEREAL_REGISTER_TYPE(Slic3r::ModelObject)
+CEREAL_REGISTER_TYPE(Slic3r::ModelVolume)
+CEREAL_REGISTER_TYPE(Slic3r::ModelInstance)
+CEREAL_REGISTER_TYPE(Slic3r::Model)
+
+CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::ModelObject)
+CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::ModelVolume)
+CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::ModelInstance)
+CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::Model)
+#endif
\ No newline at end of file
diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp
index 0fd1140f0..3330f140d 100644
--- a/src/libslic3r/Model.hpp
+++ b/src/libslic3r/Model.hpp
@@ -40,8 +40,9 @@ typedef std::vector<ModelInstance*> ModelInstancePtrs;
 // Valid IDs are strictly positive (non zero).
 // It is declared as an object, as some compilers (notably msvcc) consider a typedef size_t equivalent to size_t
 // for parameter overload.
-struct ModelID 
+class ModelID 
 {
+public:
 	ModelID(size_t id) : id(id) {}
 
 	bool operator==(const ModelID &rhs) const { return this->id == rhs.id; }
@@ -54,6 +55,12 @@ struct ModelID
     bool valid() const { return id != 0; }
 
 	size_t	id;
+
+private:
+	ModelID() {}
+
+	friend class cereal::access;
+	template<class Archive> void serialize(Archive &ar) { ar(id); }
 };
 
 // Unique object / instance ID for the wipe tower.
@@ -76,6 +83,8 @@ protected:
     // Constructor with ignored int parameter to assign an invalid ID, to be replaced
     // by an existing ID copied from elsewhere.
     ModelBase(int) : m_id(ModelID(0)) {}
+	// The class tree will have virtual tables and type information.
+	virtual ~ModelBase() {}
 
     // Use with caution!
     void        set_new_unique_id() { m_id = generate_new_id(); }
@@ -94,6 +103,11 @@ private:
 	
 	friend ModelID wipe_tower_object_id();
 	friend ModelID wipe_tower_instance_id();
+
+	friend class cereal::access;
+	template<class Archive> void serialize(Archive &ar) { ar(m_id); }
+    ModelBase(const ModelID id) : m_id(id) {}
+  	template<class Archive> static void load_and_construct(Archive & ar, cereal::construct<ModelBase> &construct) { ModelID id; ar(id); construct(id); }
 };
 
 #define MODELBASE_DERIVED_COPY_MOVE_CLONE(TYPE) \
@@ -155,10 +169,13 @@ private:
     // Parent, owning this material.
     Model *m_model;
     
-	ModelMaterial() = delete;
 	ModelMaterial(ModelMaterial &&rhs) = delete;
 	ModelMaterial& operator=(const ModelMaterial &rhs) = delete;
     ModelMaterial& operator=(ModelMaterial &&rhs) = delete;
+
+	friend class cereal::access;
+	ModelMaterial() : m_model(nullptr) {}
+	template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ModelBase>(this)); ar(attributes, config); }
 };
 
 // A printable object, possibly having multiple print volumes (each with its own set of parameters and materials),
@@ -323,7 +340,15 @@ private:
     mutable BoundingBoxf3 m_raw_bounding_box;
     mutable bool          m_raw_bounding_box_valid;
     mutable BoundingBoxf3 m_raw_mesh_bounding_box;
-    mutable bool          m_raw_mesh_bounding_box_valid;    
+    mutable bool          m_raw_mesh_bounding_box_valid;
+
+	friend class cereal::access;
+	ModelObject() : m_model(nullptr), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {}
+	template<class Archive> void serialize(Archive &ar) { 
+		ar(cereal::base_class<ModelBase>(this));
+		ar(name, input_file, instances, volumes, config, layer_height_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
+			m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
+	}
 };
 
 // Declared outside of ModelVolume, so it could be forward declared.
@@ -459,7 +484,7 @@ private:
     //     -1   ->   is unknown value (before first cheking)
     //      0   ->   is not splittable
     //      1   ->   is splittable
-    mutable int               m_is_splittable{ -1 };
+    mutable int               		m_is_splittable{ -1 };
 
 	ModelVolume(ModelObject *object, const TriangleMesh &mesh) : m_mesh(new TriangleMesh(mesh)), m_type(ModelVolumeType::MODEL_PART), object(object)
     {
@@ -486,6 +511,13 @@ private:
     }
 
     ModelVolume& operator=(ModelVolume &rhs) = delete;
+
+	friend class cereal::access;
+	ModelVolume() : object(nullptr) {}
+	template<class Archive> void serialize(Archive &ar) {
+		ar(cereal::base_class<ModelBase>(this));
+		ar(name, config, m_mesh, m_type, m_material_id, m_convex_hull, m_transformation, m_is_splittable);
+	}
 };
 
 // A single instance of a ModelObject.
@@ -571,10 +603,16 @@ private:
     explicit ModelInstance(ModelObject *object, const ModelInstance &other) :
         m_transformation(other.m_transformation), object(object), print_volume_state(PVS_Inside) {}
 
-    ModelInstance() = delete;
     explicit ModelInstance(ModelInstance &&rhs) = delete;
     ModelInstance& operator=(const ModelInstance &rhs) = delete;
     ModelInstance& operator=(ModelInstance &&rhs) = delete;
+
+	friend class cereal::access;
+	ModelInstance() : object(nullptr) {}
+	template<class Archive> void serialize(Archive &ar) {
+		ar(cereal::base_class<ModelBase>(this));
+		ar(m_transformation, print_volume_state);
+	}
 };
 
 // The print bed content.
@@ -633,24 +671,24 @@ public:
     BoundingBoxf3 bounding_box() const;
     // Set the print_volume_state of PrintObject::instances, 
     // return total number of printable objects.
-    unsigned int update_print_volume_state(const BoundingBoxf3 &print_volume);
+    unsigned int  update_print_volume_state(const BoundingBoxf3 &print_volume);
 	// Returns true if any ModelObject was modified.
-    bool center_instances_around_point(const Vec2d &point);
-    void translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); }
-    TriangleMesh mesh() const;
-    bool arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL);
+    bool 		  center_instances_around_point(const Vec2d &point);
+    void 		  translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); }
+    TriangleMesh  mesh() const;
+    bool 		  arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL);
     // Croaks if the duplicated objects do not fit the print bed.
-    void duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL);
-    void duplicate_objects(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL);
-    void duplicate_objects_grid(size_t x, size_t y, coordf_t dist);
+    void 		  duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL);
+    void 	      duplicate_objects(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL);
+    void 		  duplicate_objects_grid(size_t x, size_t y, coordf_t dist);
 
-    bool looks_like_multipart_object() const;
-    void convert_multipart_object(unsigned int max_extruders);
+    bool 		  looks_like_multipart_object() const;
+    void 		  convert_multipart_object(unsigned int max_extruders);
 
     // Ensures that the min z of the model is not negative
-    void adjust_min_z();
+    void 		  adjust_min_z();
 
-    void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); }
+    void 		  print_info() const { for (const ModelObject *o : this->objects) o->print_info(); }
 
     static unsigned int get_auto_extruder_id(unsigned int max_extruders);
     static std::string get_auto_extruder_id_as_string(unsigned int max_extruders);
@@ -663,6 +701,11 @@ public:
 
 private:
     MODELBASE_DERIVED_PRIVATE_COPY_MOVE(Model)
+
+	friend class cereal::access;
+	template<class Archive> void serialize(Archive &ar) {
+		ar(cereal::base_class<ModelBase>(this), materials, objects);
+	}
 };
 
 #undef MODELBASE_DERIVED_COPY_MOVE_CLONE
diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp
index b02ead299..8979523b7 100644
--- a/src/libslic3r/Point.hpp
+++ b/src/libslic3r/Point.hpp
@@ -62,8 +62,8 @@ inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); }
 inline Vec2f   to_2d(const Vec3f   &pt3) { return Vec2f  (pt3(0), pt3(1)); }
 inline Vec2d   to_2d(const Vec3d   &pt3) { return Vec2d  (pt3(0), pt3(1)); }
 
-inline Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); }
-inline Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); }
+inline Vec3d   to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); }
+inline Vec3f   to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); }
 inline Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(int64_t(v(0)), int64_t(v(1)), int64_t(z)); }
 inline Vec3crd to_3d(const Vec3crd &p, coord_t z) { return Vec3crd(p(0), p(1), z); }
 
@@ -291,4 +291,24 @@ namespace boost { namespace polygon {
 } }
 // end Boost
 
+#include <cereal/types/polymorphic.hpp>
+#include <cereal/archives/binary.hpp>
+
+// Serialization through the Cereal library
+namespace cereal {
+//	template<class Archive> void serialize(Archive& archive, Slic3r::Vec2crd &v) { archive(v.x(), v.y()); }
+//	template<class Archive> void serialize(Archive& archive, Slic3r::Vec3crd &v) { archive(v.x(), v.y(), v.z()); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::Vec2i   &v) { archive(v.x(), v.y()); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::Vec3i   &v) { archive(v.x(), v.y(), v.z()); }
+//	template<class Archive> void serialize(Archive& archive, Slic3r::Vec2i64 &v) { archive(v.x(), v.y()); }
+//	template<class Archive> void serialize(Archive& archive, Slic3r::Vec3i64 &v) { archive(v.x(), v.y(), v.z()); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::Vec2f   &v) { archive(v.x(), v.y()); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::Vec3f   &v) { archive(v.x(), v.y(), v.z()); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::Vec2d   &v) { archive(v.x(), v.y()); }
+	template<class Archive> void serialize(Archive& archive, Slic3r::Vec3d   &v) { archive(v.x(), v.y(), v.z()); }
+
+	template<class Archive> void load(Archive& archive, Slic3r::Matrix2f &m) { archive.loadBinary((char*)m.data(), sizeof(float) * 4); }
+	template<class Archive> void save(Archive& archive, Slic3r::Matrix2f &m) { archive.saveBinary((char*)m.data(), sizeof(float) * 4); }
+}
+
 #endif
diff --git a/src/libslic3r/pchheader.hpp b/src/libslic3r/pchheader.hpp
index b27dfe6a2..54b563def 100644
--- a/src/libslic3r/pchheader.hpp
+++ b/src/libslic3r/pchheader.hpp
@@ -100,7 +100,14 @@
 #include <tbb/task_scheduler_init.h>
 
 #include <Eigen/Dense>
-#include <Eigen/Geometry> 
+#include <Eigen/Geometry>
+
+#include <cereal/types/polymorphic.hpp>
+#include <cereal/types/map.hpp>
+#include <cereal/types/memory.hpp>
+#include <cereal/types/string.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/archives/binary.hpp>
 
 #include "BoundingBox.hpp"
 #include "ClipperUtils.hpp"