diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp
index 0e2fbe3be..2e17cac21 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1519,7 +1519,7 @@ void GLCanvas3D::Gizmos::set_flattening_data(const ModelObject* model_object)
         reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object);
 }
 
-void GLCanvas3D::Gizmos::set_model_object_ptr(const ModelObject* model_object)
+void GLCanvas3D::Gizmos::set_model_object_ptr(ModelObject* model_object)
 {
     if (!m_enabled)
         return;
diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp
index 537a0624f..7807532c1 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp
@@ -403,7 +403,7 @@ class GLCanvas3D
 #endif // ENABLE_MODELINSTANCE_3D_ROTATION
         void set_flattening_data(const ModelObject* model_object);
 
-        void set_model_object_ptr(const ModelObject* model_object);
+        void set_model_object_ptr(ModelObject* model_object);
         void clicked_on_object(const Vec2d& mouse_position);
         void delete_current_grabber(bool delete_all = false);
 
diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp
index 4bea9bf07..3178639e7 100644
--- a/xs/src/slic3r/GUI/GLGizmo.cpp
+++ b/xs/src/slic3r/GUI/GLGizmo.cpp
@@ -1648,7 +1648,7 @@ void GLGizmoSlaSupports::render_grabbers(bool picking) const
             ::glEnable(GL_LIGHTING);
         ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]);
         ::glPushMatrix();
-        const Vec3d& center = m_grabbers[i].center;
+        Vec3d center = m_model_object->instances.front()->world_matrix() * m_grabbers[i].center;
         ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2));
         GLUquadricObj *quadric;
         quadric = ::gluNewQuadric();
@@ -1661,33 +1661,87 @@ void GLGizmoSlaSupports::render_grabbers(bool picking) const
     }
 }
 
+bool GLGizmoSlaSupports::is_mesh_update_necessary() const
+{
+    if (m_state != On || !m_model_object || m_model_object->instances.empty())
+        return false;
+
+#if ENABLE_MODELINSTANCE_3D_ROTATION
+    if (m_model_object->volumes.size() != m_source_data.bounding_boxes.size()
+     || (m_model_object->instances.front()->world_matrix() * m_source_data.matrix.inverse() * Vec3d(1., 1., 1.) - Vec3d(1., 1., 1.)).norm() > 0.001 )
+#else
+    if (m_model_object->volumes.size() != m_source_data.bounding_boxes.size()
+     || m_model_object->instances.front()->scaling_factor != m_source_data.scaling_factor
+     || m_model_object->instances.front()->rotation != m_source_data.rotation)
+#endif // ENABLE_MODELINSTANCE_3D_ROTATION
+        return true;
+
+    // now compare the bounding boxes:
+    for (unsigned int i=0; i<m_model_object->volumes.size(); ++i)
+        if (m_model_object->volumes[i]->get_convex_hull().bounding_box() != m_source_data.bounding_boxes[i])
+            return true;
+
+    // following should detect direct mesh changes (can be removed after the mesh is made completely immutable):
+    const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex();
+    Vec3d first_point((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]);
+    if (first_point != m_source_data.mesh_first_point)
+        return true;
+
+    return false;
+}
+
+void GLGizmoSlaSupports::update_mesh()
+{
+    Eigen::MatrixXf& V = m_V;
+    Eigen::MatrixXi& F = m_F;
+
+    TriangleMesh combined_mesh;
+    for (const ModelVolume* vol : m_model_object->volumes)
+        combined_mesh.merge(vol->mesh);
+    //combined_mesh.scale(m_model_object->instances.front()->scaling_factor);
+    //combined_mesh.rotate_z(m_model_object->instances.front()->rotation);
+    //const stl_file& stl = combined_mesh.stl;
+    const stl_file& stl = m_model_object->mesh().stl;
+
+    V.resize(3*stl.stats.number_of_facets, 3);
+    F.resize(stl.stats.number_of_facets, 3);
+    for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
+        const stl_facet* facet = stl.facet_start+i;
+        V(3*i+0, 0) = facet->vertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2);
+        V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2);
+        V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2);
+        F(i, 0) = 3*i+0;
+        F(i, 1) = 3*i+1;
+        F(i, 2) = 3*i+2;
+    }
+
+    // now we must save what we calculated the mesh from, so we can tell when to recalculate:
+    m_source_data.bounding_boxes.clear();
+    for (const auto& vol : m_model_object->volumes)
+        m_source_data.bounding_boxes.push_back(vol->get_convex_hull().bounding_box());
+#if !ENABLE_MODELINSTANCE_3D_ROTATION
+    m_source_data.scaling_factor = m_model_object->instances.front()->scaling_factor;
+    m_source_data.rotation = m_model_object->instances.front()->rotation;
+#else
+    m_source_data.matrix = m_model_object->instances.front()->world_matrix();
+#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
+    const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex();
+    m_source_data.mesh_first_point = Vec3d((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]);
+
+
+    // we'll now reload Grabbers (selection might have changed):
+    m_grabbers.clear();
+    for (const Vec3f& point : m_model_object->sla_support_points) {
+        m_grabbers.push_back(Grabber());
+        m_grabbers.back().center = point.cast<double>();
+    }
+}
+
 Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
 {
     // if the gizmo doesn't have the V, F structures for igl, calculate them first:
-    if (m_V.size() == 0) {
-        Eigen::MatrixXf& V = m_V;
-        Eigen::MatrixXi& F = m_F;
-
-        TriangleMesh combined_mesh;
-        for (const ModelVolume* vol : m_model_object->volumes)
-            combined_mesh.merge(vol->mesh);
-        //combined_mesh.scale(m_model_object->instances.front()->scaling_factor);
-        //combined_mesh.rotate_z(m_model_object->instances.front()->rotation);
-        //const stl_file& stl = combined_mesh.stl;
-        const stl_file& stl = m_model_object->mesh().stl;
-
-        V.resize(3*stl.stats.number_of_facets, 3);
-        F.resize(stl.stats.number_of_facets, 3);
-        for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
-            const stl_facet* facet = stl.facet_start+i;
-            V(3*i+0, 0) = facet->vertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2);
-            V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2);
-            V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2);
-            F(i, 0) = 3*i+0;
-            F(i, 1) = 3*i+1;
-            F(i, 2) = 3*i+2;
-        }
-    }
+    if (m_V.size() == 0 || is_mesh_update_necessary())
+        update_mesh();
 
     Eigen::Matrix<GLint, 4, 1, Eigen::DontAlign> viewport;
     ::glGetIntegerv(GL_VIEWPORT, viewport.data());
@@ -1712,7 +1766,8 @@ Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
     const Vec3f& a = m_V.row(m_F(fid, 0));
     const Vec3f& b = m_V.row(m_F(fid, 1));
     const Vec3f& c = m_V.row(m_F(fid, 2));
-    return bc(0)*a + bc(1)*b + bc(2)*c;
+    Vec3f point = bc(0)*a + bc(1)*b + bc(2)*c;
+    return m_model_object->instances.front()->world_matrix().inverse().cast<float>() * point;
 }
 
 void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position)
@@ -1722,6 +1777,7 @@ void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position)
         new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new grabber in that case
         m_grabbers.push_back(Grabber());
         m_grabbers.back().center = new_pos.cast<double>();
+        m_model_object->sla_support_points.push_back(new_pos);
     }
     catch (...) {}
 }
@@ -1730,10 +1786,12 @@ void GLGizmoSlaSupports::delete_current_grabber(bool delete_all)
 {
     if (delete_all) {
         m_grabbers.clear();
+        m_model_object->sla_support_points.clear();
     }
     else
         if (m_hover_id != -1) {
             m_grabbers.erase(m_grabbers.begin() + m_hover_id);
+            m_model_object->sla_support_points.erase(m_model_object->sla_support_points.begin() + m_hover_id);
             m_hover_id = -1;
         }
 }
@@ -1745,6 +1803,7 @@ void GLGizmoSlaSupports::on_update(const Linef3& mouse_ray, const Point* mouse_p
         try {
             new_pos = unproject_on_mesh(Vec2d((*mouse_pos)(0), (*mouse_pos)(1)));
             m_grabbers[m_hover_id].center = new_pos.cast<double>();
+            m_model_object->sla_support_points[m_hover_id] = new_pos;
         }
         catch (...) {}
     }
diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp
index 4755c559b..216facafe 100644
--- a/xs/src/slic3r/GUI/GLGizmo.hpp
+++ b/xs/src/slic3r/GUI/GLGizmo.hpp
@@ -409,15 +409,28 @@ protected:
 class GLGizmoSlaSupports : public GLGizmoBase
 {
 private:
-    const ModelObject* m_model_object = nullptr;
+    ModelObject* m_model_object = nullptr;
     Vec3f unproject_on_mesh(const Vec2d& mouse_pos);
 
     Eigen::MatrixXf m_V; // vertices
     Eigen::MatrixXi m_F; // facets indices
+    struct SourceDataSummary {
+        std::vector<BoundingBoxf3> bounding_boxes; // bounding boxes of convex hulls of individual volumes
+#if !ENABLE_MODELINSTANCE_3D_ROTATION
+        float scaling_factor;
+        float rotation;
+#else
+        Transform3d matrix;
+#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
+        Vec3d mesh_first_point;
+    };
+
+    // This holds information to decide whether recalculation is necessary:
+    SourceDataSummary m_source_data;
 
 public:
     explicit GLGizmoSlaSupports(GLCanvas3D& parent);
-    void set_model_object_ptr(const ModelObject* model_object) { m_model_object = model_object; }
+    void set_model_object_ptr(ModelObject* model_object) { m_model_object = model_object; if (is_mesh_update_necessary()) update_mesh(); }
     void clicked_on_object(const Vec2d& mouse_position);
     void delete_current_grabber(bool delete_all);
 
@@ -428,9 +441,17 @@ private:
     void on_render_for_picking(const BoundingBoxf3& box) const;
     void render_grabbers(bool picking = false) const;
     void render_tooltip_texture() const;
+    bool is_mesh_update_necessary() const;
+    void update_mesh();
 
     mutable GLTexture m_tooltip_texture;
     mutable GLTexture m_reset_texture;
+
+protected:
+    void on_set_state() override {
+        if (m_state == On && is_mesh_update_necessary())
+            update_mesh();
+    }
 };
 
 } // namespace GUI