diff --git a/xs/src/admesh/util.c b/xs/src/admesh/util.c
index f29ba1614..4ecb76e79 100644
--- a/xs/src/admesh/util.c
+++ b/xs/src/admesh/util.c
@@ -27,7 +27,7 @@
 
 #include "stl.h"
 
-static void stl_rotate(float *x, float *y, float angle);
+static void stl_rotate(float *x, float *y, const double c, const double s);
 static float get_area(stl_facet *facet);
 static float get_volume(stl_file *stl);
 
@@ -189,13 +189,16 @@ void
 stl_rotate_x(stl_file *stl, float angle) {
   int i;
   int j;
+  double radian_angle = (angle / 180.0) * M_PI;
+  double c = cos(radian_angle);
+  double s = sin(radian_angle);
 
   if (stl->error) return;
 
   for(i = 0; i < stl->stats.number_of_facets; i++) {
     for(j = 0; j < 3; j++) {
       stl_rotate(&stl->facet_start[i].vertex[j].y,
-                 &stl->facet_start[i].vertex[j].z, angle);
+                 &stl->facet_start[i].vertex[j].z, c, s);
     }
   }
   stl_get_size(stl);
@@ -206,13 +209,16 @@ void
 stl_rotate_y(stl_file *stl, float angle) {
   int i;
   int j;
+  double radian_angle = (angle / 180.0) * M_PI;
+  double c = cos(radian_angle);
+  double s = sin(radian_angle);
 
   if (stl->error) return;
 
   for(i = 0; i < stl->stats.number_of_facets; i++) {
     for(j = 0; j < 3; j++) {
       stl_rotate(&stl->facet_start[i].vertex[j].z,
-                 &stl->facet_start[i].vertex[j].x, angle);
+                 &stl->facet_start[i].vertex[j].x, c, s);
     }
   }
   stl_get_size(stl);
@@ -223,13 +229,16 @@ void
 stl_rotate_z(stl_file *stl, float angle) {
   int i;
   int j;
+  double radian_angle = (angle / 180.0) * M_PI;
+  double c = cos(radian_angle);
+  double s = sin(radian_angle);
 
   if (stl->error) return;
 
   for(i = 0; i < stl->stats.number_of_facets; i++) {
     for(j = 0; j < 3; j++) {
       stl_rotate(&stl->facet_start[i].vertex[j].x,
-                 &stl->facet_start[i].vertex[j].y, angle);
+                 &stl->facet_start[i].vertex[j].y, c, s);
     }
   }
   stl_get_size(stl);
@@ -239,17 +248,11 @@ stl_rotate_z(stl_file *stl, float angle) {
 
 
 static void
-stl_rotate(float *x, float *y, float angle) {
-  double r;
-  double theta;
-  double radian_angle;
-
-  radian_angle = (angle / 180.0) * M_PI;
-
-  r = sqrt((*x **x) + (*y **y));
-  theta = atan2(*y, *x);
-  *x = r * cos(theta + radian_angle);
-  *y = r * sin(theta + radian_angle);
+stl_rotate(float *x, float *y, const double c, const double s) {
+  double xold = *x;
+  double yold = *y;
+  *x = float(c * xold - s * yold);
+  *y = float(s * xold + c * yold);
 }
 
 extern void
diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp
index 5db9066a6..e4a4c48a8 100644
--- a/xs/src/libslic3r/Model.cpp
+++ b/xs/src/libslic3r/Model.cpp
@@ -473,7 +473,16 @@ ModelObject::invalidate_bounding_box()
 void
 ModelObject::update_bounding_box()
 {
-    this->_bounding_box = this->mesh().bounding_box();
+//    this->_bounding_box = this->mesh().bounding_box();
+    BoundingBoxf3 raw_bbox;
+    for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
+        if ((*v)->modifier) continue;
+        raw_bbox.merge((*v)->mesh.bounding_box());
+    }
+    BoundingBoxf3 bb;
+    for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i)
+        bb.merge((*i)->transform_bounding_box(raw_bbox));
+    this->_bounding_box = bb;
     this->_bounding_box_valid = true;
 }
 
@@ -509,12 +518,8 @@ ModelObject::raw_bounding_box() const
     BoundingBoxf3 bb;
     for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
         if ((*v)->modifier) continue;
-        TriangleMesh mesh = (*v)->mesh;
-        
         if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
-        this->instances.front()->transform_mesh(&mesh, true);
-        
-        bb.merge(mesh.bounding_box());
+        bb.merge(this->instances.front()->transform_mesh_bounding_box(&(*v)->mesh, true));
     }
     return bb;
 }
@@ -523,9 +528,12 @@ ModelObject::raw_bounding_box() const
 BoundingBoxf3
 ModelObject::instance_bounding_box(size_t instance_idx) const
 {
-    TriangleMesh mesh = this->raw_mesh();
-    this->instances[instance_idx]->transform_mesh(&mesh);
-    return mesh.bounding_box();
+    BoundingBoxf3 bb;
+    for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
+        if ((*v)->modifier) continue;
+        bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(&(*v)->mesh, true));
+    }
+    return bb;
 }
 
 void
@@ -533,7 +541,10 @@ ModelObject::center_around_origin()
 {
     // calculate the displacements needed to 
     // center this object around the origin
-    BoundingBoxf3 bb = this->raw_mesh().bounding_box();
+	BoundingBoxf3 bb;
+	for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v)
+		if (! (*v)->modifier)
+			bb.merge((*v)->mesh.bounding_box());
     
     // first align to origin on XYZ
     Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z);
@@ -775,6 +786,63 @@ ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
         mesh->translate(this->offset.x, this->offset.y, 0);
 }
 
+BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const
+{
+    // rotate around mesh origin
+    double c = cos(this->rotation);
+    double s = sin(this->rotation);
+    BoundingBoxf3 bbox;
+    for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) {
+        const stl_facet &facet = mesh->stl.facet_start[i];
+        for (int j = 0; j < 3; ++ j) {
+            stl_vertex v = facet.vertex[j];
+            double xold = v.x;
+            double yold = v.y;
+            v.x = float(c * xold - s * yold);
+            v.y = float(s * xold + c * yold);
+            v.x *= float(this->scaling_factor);
+            v.y *= float(this->scaling_factor);
+            v.z *= float(this->scaling_factor);
+            if (!dont_translate) {
+                v.x += this->offset.x;
+                v.y += this->offset.y;
+            }
+            bbox.merge(Pointf3(v.x, v.y, v.z));
+        }
+    }
+    return bbox;
+}
+
+BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
+{
+    // rotate around mesh origin
+    double c = cos(this->rotation);
+    double s = sin(this->rotation);
+    Pointf3 pts[4] = {
+        bbox.min,
+        bbox.max,
+        Pointf3(bbox.min.x, bbox.max.y, bbox.min.z),
+        Pointf3(bbox.max.x, bbox.min.y, bbox.max.z)
+    };
+    BoundingBoxf3 out;
+    for (int i = 0; i < 4; ++ i) {
+        Pointf3 &v = pts[i];
+        double xold = v.x;
+        double yold = v.y;
+        v.x = float(c * xold - s * yold);
+        v.y = float(s * xold + c * yold);
+        v.x *= this->scaling_factor;
+        v.y *= this->scaling_factor;
+        v.z *= this->scaling_factor;
+        if (!dont_translate) {
+            v.x += this->offset.x;
+            v.y += this->offset.y;
+        }
+        out.merge(v);
+    }
+    return out;
+}
+
 void
 ModelInstance::transform_polygon(Polygon* polygon) const
 {
diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp
index 60405f6f6..b2a9d0b53 100644
--- a/xs/src/libslic3r/Model.hpp
+++ b/xs/src/libslic3r/Model.hpp
@@ -215,6 +215,10 @@ public:
 
     // To be called on an external mesh
     void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
+    // Calculate a bounding box of a transformed mesh. To be called on an external mesh.
+    BoundingBoxf3 transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate = false) const;
+    // Transform an external bounding box.
+    BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const;
     // To be called on an external polygon. It does not translate the polygon, only rotates and scales.
     void transform_polygon(Polygon* polygon) const;