Use of bounding box of rotated 3D convex hull for out of print volume detection

This commit is contained in:
Enrico Turri 2018-08-15 12:50:06 +02:00
parent 211790f8c3
commit 4d98d32199
12 changed files with 276 additions and 141 deletions

View file

@ -202,7 +202,8 @@ const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
GLVolume::GLVolume(float r, float g, float b, float a)
: m_angle_z(0.0f)
, m_scale_factor(1.0f)
, m_dirty(true)
, m_transformed_bounding_box_dirty(true)
, m_transformed_convex_hull_bounding_box_dirty(true)
, composite_id(-1)
, select_group_id(-1)
, drag_group_id(-1)
@ -219,8 +220,6 @@ GLVolume::GLVolume(float r, float g, float b, float a)
, tverts_range(0, size_t(-1))
, qverts_range(0, size_t(-1))
{
m_world_mat = std::vector<float>(UNIT_MATRIX, std::end(UNIT_MATRIX));
color[0] = r;
color[1] = g;
color[2] = b;
@ -264,45 +263,76 @@ const Pointf3& GLVolume::get_origin() const
void GLVolume::set_origin(const Pointf3& origin)
{
m_origin = origin;
m_dirty = true;
if (m_origin != origin)
{
m_origin = origin;
m_transformed_bounding_box_dirty = true;
m_transformed_convex_hull_bounding_box_dirty = true;
}
}
void GLVolume::set_angle_z(float angle_z)
{
m_angle_z = angle_z;
m_dirty = true;
if (m_angle_z != angle_z)
{
m_angle_z = angle_z;
m_transformed_bounding_box_dirty = true;
m_transformed_convex_hull_bounding_box_dirty = true;
}
}
void GLVolume::set_scale_factor(float scale_factor)
{
m_scale_factor = scale_factor;
m_dirty = true;
if (m_scale_factor != scale_factor)
{
m_scale_factor = scale_factor;
m_transformed_bounding_box_dirty = true;
m_transformed_convex_hull_bounding_box_dirty = true;
}
}
const std::vector<float>& GLVolume::world_matrix() const
void GLVolume::set_convex_hull(const TriangleMesh& convex_hull)
{
if (m_dirty)
{
Eigen::Transform<float, 3, Eigen::Affine> m = Eigen::Transform<float, 3, Eigen::Affine>::Identity();
m.translate(Eigen::Vector3f((float)m_origin.x, (float)m_origin.y, (float)m_origin.z));
m.rotate(Eigen::AngleAxisf(m_angle_z, Eigen::Vector3f::UnitZ()));
m.scale(m_scale_factor);
::memcpy((void*)m_world_mat.data(), (const void*)m.data(), 16 * sizeof(float));
m_dirty = false;
}
m_convex_hull = convex_hull;
}
return m_world_mat;
std::vector<float> GLVolume::world_matrix() const
{
std::vector<float> world_mat(UNIT_MATRIX, std::end(UNIT_MATRIX));
Eigen::Transform<float, 3, Eigen::Affine> m = Eigen::Transform<float, 3, Eigen::Affine>::Identity();
m.translate(Eigen::Vector3f((float)m_origin.x, (float)m_origin.y, (float)m_origin.z));
m.rotate(Eigen::AngleAxisf(m_angle_z, Eigen::Vector3f::UnitZ()));
m.scale(m_scale_factor);
::memcpy((void*)world_mat.data(), (const void*)m.data(), 16 * sizeof(float));
return world_mat;
}
BoundingBoxf3 GLVolume::transformed_bounding_box() const
{
if (m_dirty)
if (m_transformed_bounding_box_dirty)
{
m_transformed_bounding_box = bounding_box.transformed(world_matrix());
m_transformed_bounding_box_dirty = false;
}
return m_transformed_bounding_box;
}
BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box() const
{
if (m_transformed_convex_hull_bounding_box_dirty)
{
if (m_convex_hull.stl.stats.number_of_facets > 0)
m_transformed_convex_hull_bounding_box = m_convex_hull.transformed_bounding_box(world_matrix());
else
m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix());
m_transformed_convex_hull_bounding_box_dirty = false;
}
return m_transformed_convex_hull_bounding_box;
}
void GLVolume::set_range(double min_z, double max_z)
{
this->qverts_range.first = 0;
@ -629,6 +659,7 @@ std::vector<int> GLVolumeCollection::load_object(
if (!model_volume->modifier)
{
v.set_convex_hull(model_volume->get_convex_hull());
v.layer_height_texture = layer_height_texture;
if (extruder_id != -1)
v.extruder_id = extruder_id;
@ -716,6 +747,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
v.drag_group_id = obj_idx * 1000;
v.is_wipe_tower = true;
v.shader_outside_printer_detection_enabled = ! size_unknown;
v.set_convex_hull(mesh.convex_hull_3d());
return int(this->volumes.size() - 1);
}
@ -803,7 +835,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
{
if ((volume != nullptr) && !volume->is_modifier)
{
const BoundingBoxf3& bb = volume->transformed_bounding_box();
const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
bool contained = print_volume.contains(bb);
all_contained &= contained;

View file

@ -260,12 +260,16 @@ private:
float m_angle_z;
// Scale factor of the volume to be rendered.
float m_scale_factor;
// World matrix of the volume to be rendered.
std::vector<float> m_world_mat;
// Bounding box of this volume, in unscaled coordinates.
mutable BoundingBoxf3 m_transformed_bounding_box;
// Whether or not is needed to recalculate the world matrix.
mutable bool m_dirty;
// Whether or not is needed to recalculate the transformed bounding box.
mutable bool m_transformed_bounding_box_dirty;
// Convex hull of the original mesh, if any.
TriangleMesh m_convex_hull;
// Bounding box of this volume, in unscaled coordinates.
mutable BoundingBoxf3 m_transformed_convex_hull_bounding_box;
// Whether or not is needed to recalculate the transformed convex hull bounding box.
mutable bool m_transformed_convex_hull_bounding_box_dirty;
public:
@ -323,13 +327,15 @@ public:
void set_origin(const Pointf3& origin);
void set_angle_z(float angle_z);
void set_scale_factor(float scale_factor);
void set_convex_hull(const TriangleMesh& convex_hull);
int object_idx() const { return this->composite_id / 1000000; }
int volume_idx() const { return (this->composite_id / 1000) % 1000; }
int instance_idx() const { return this->composite_id % 1000; }
const std::vector<float>& world_matrix() const;
std::vector<float> world_matrix() const;
BoundingBoxf3 transformed_bounding_box() const;
BoundingBoxf3 transformed_convex_hull_bounding_box() const;
bool empty() const { return this->indexed_vertex_array.empty(); }
bool indexed() const { return this->indexed_vertex_array.indexed(); }

View file

@ -3243,7 +3243,7 @@ BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const
{
for (const GLVolume* volume : selected_volumes)
{
bb.merge(volume->transformed_bounding_box());
bb.merge(volume->transformed_convex_hull_bounding_box());
}
}

View file

@ -189,7 +189,7 @@ GLGizmoRotate::GLGizmoRotate()
, m_angle_z(0.0f)
, m_center(Pointf(0.0, 0.0))
, m_radius(0.0f)
, m_keep_radius(false)
, m_keep_initial_values(false)
{
}
@ -229,7 +229,7 @@ bool GLGizmoRotate::on_init()
void GLGizmoRotate::on_set_state()
{
m_keep_radius = (m_state == On) ? false : true;
m_keep_initial_values = (m_state == On) ? false : true;
}
void GLGizmoRotate::on_update(const Pointf& mouse_pos)
@ -255,19 +255,19 @@ void GLGizmoRotate::on_update(const Pointf& mouse_pos)
void GLGizmoRotate::on_refresh()
{
m_keep_radius = false;
m_keep_initial_values = false;
}
void GLGizmoRotate::on_render(const BoundingBoxf3& box) const
{
::glDisable(GL_DEPTH_TEST);
const Pointf3& size = box.size();
m_center = box.center();
if (!m_keep_radius)
if (!m_keep_initial_values)
{
const Pointf3& size = box.size();
m_center = box.center();
m_radius = Offset + ::sqrt(sqr(0.5f * size.x) + sqr(0.5f * size.y));
m_keep_radius = true;
m_keep_initial_values = true;
}
::glLineWidth(2.0f);

View file

@ -101,7 +101,7 @@ class GLGizmoRotate : public GLGizmoBase
mutable Pointf m_center;
mutable float m_radius;
mutable bool m_keep_radius;
mutable bool m_keep_initial_values;
public:
GLGizmoRotate();