Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/Print.cpp50
-rw-r--r--src/libslic3r/Print.hpp4
-rw-r--r--src/libslic3r/Technologies.hpp2
-rw-r--r--src/slic3r/GUI/3DBed.cpp45
-rw-r--r--src/slic3r/GUI/3DBed.hpp9
-rw-r--r--src/slic3r/GUI/GCodeViewer.cpp5
-rw-r--r--src/slic3r/GUI/GCodeViewer.hpp4
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp233
-rw-r--r--src/slic3r/GUI/GLCanvas3D.hpp35
-rw-r--r--src/slic3r/GUI/GLModel.cpp584
-rw-r--r--src/slic3r/GUI/GLModel.hpp78
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoBase.cpp12
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp4
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoMove.cpp28
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp4
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp6
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoScale.cpp70
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp9
-rw-r--r--src/slic3r/GUI/Plater.cpp47
-rw-r--r--src/slic3r/GUI/Selection.cpp54
20 files changed, 1141 insertions, 142 deletions
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 99119f566..baaa0497c 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -354,9 +354,19 @@ bool Print::has_brim() const
return std::any_of(m_objects.begin(), m_objects.end(), [](PrintObject *object) { return object->has_brim(); });
}
+#if ENABLE_SEQUENTIAL_LIMITS
+bool Print::sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons)
+#else
static inline bool sequential_print_horizontal_clearance_valid(const Print &print)
+#endif // ENABLE_SEQUENTIAL_LIMITS
{
Polygons convex_hulls_other;
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (polygons != nullptr)
+ polygons->clear();
+ std::vector<size_t> intersecting_idxs;
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
std::map<ObjectID, Polygon> map_model_object_to_convex_hull;
for (const PrintObject *print_object : print.objects()) {
assert(! print_object->model_object()->instances.empty());
@@ -378,7 +388,7 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)),
- jtRound, float(scale_(0.1))).front());
+ jtRound, scale_(0.1)).front());
#else
it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id,
offset(print_object->model_object()->convex_hull_2d(
@@ -391,21 +401,47 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin
}
// Make a copy, so it may be rotated for instances.
Polygon convex_hull0 = it_convex_hull->second;
- double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
+ const double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
if (std::abs(z_diff) > EPSILON)
convex_hull0.rotate(z_diff);
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
for (const PrintInstance &instance : print_object->instances()) {
Polygon convex_hull = convex_hull0;
// instance.shift is a position of a centered object, while model object may not be centered.
- // Conver the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
+ // Convert the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
convex_hull.translate(instance.shift - print_object->center_offset());
- if (! intersection(convex_hulls_other, (Polygons)convex_hull).empty())
- return false;
- convex_hulls_other.emplace_back(std::move(convex_hull));
+#if ENABLE_SEQUENTIAL_LIMITS
+ // if output needed, collect indices (inside convex_hulls_other) of intersecting hulls
+ for (size_t i = 0; i < convex_hulls_other.size(); ++i) {
+ if (!intersection((Polygons)convex_hulls_other[i], (Polygons)convex_hull).empty()) {
+ if (polygons == nullptr)
+ return false;
+ else {
+ intersecting_idxs.emplace_back(i);
+ intersecting_idxs.emplace_back(convex_hulls_other.size());
+ }
+ }
+ }
+#else
+ if (!intersection(convex_hulls_other, (Polygons)convex_hull).empty())
+ return false;
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ convex_hulls_other.emplace_back(std::move(convex_hull));
}
}
- return true;
+
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (!intersecting_idxs.empty()) {
+ // use collected indices (inside convex_hulls_other) to update output
+ std::sort(intersecting_idxs.begin(), intersecting_idxs.end());
+ intersecting_idxs.erase(std::unique(intersecting_idxs.begin(), intersecting_idxs.end()), intersecting_idxs.end());
+ for (size_t i : intersecting_idxs) {
+ polygons->emplace_back(std::move(convex_hulls_other[i]));
+ }
+ return false;
+ }
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ return true;
}
static inline bool sequential_print_vertical_clearance_valid(const Print &print)
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index edd8e19f1..ec48a607c 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -545,6 +545,10 @@ public:
const PrintRegion& get_print_region(size_t idx) const { return *m_print_regions[idx]; }
const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; }
+#if ENABLE_SEQUENTIAL_LIMITS
+ static bool sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons = nullptr);
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
protected:
// Invalidates the step, and its depending steps in Print.
bool invalidate_step(PrintStep step);
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index e00af1851..b35ccbc6d 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -66,6 +66,8 @@
// Enable to push object instances under the bed
#define ENABLE_ALLOW_NEGATIVE_Z (1 && ENABLE_2_4_0_ALPHA0)
#define DISABLE_ALLOW_NEGATIVE_Z_FOR_SLA (1 && ENABLE_ALLOW_NEGATIVE_Z)
+// Enable visualization of objects clearance for sequential prints
+#define ENABLE_SEQUENTIAL_LIMITS (1 && ENABLE_2_4_0_ALPHA0)
#endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index f3eec0080..77710c0de 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -98,12 +98,6 @@ const float Bed3D::Axes::DefaultStemLength = 25.0f;
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
const float Bed3D::Axes::DefaultTipLength = 5.0f;
-void Bed3D::Axes::set_stem_length(float length)
-{
- m_stem_length = length;
- m_arrow.reset();
-}
-
void Bed3D::Axes::render() const
{
auto render_axis = [this](const Transform3f& transform) {
@@ -113,7 +107,10 @@ void Bed3D::Axes::render() const
glsafe(::glPopMatrix());
};
- const_cast<GLModel*>(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (!m_arrow.is_initialized())
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr)
@@ -125,18 +122,30 @@ void Bed3D::Axes::render() const
shader->set_uniform("emission_factor", 0.0);
// x axis
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.75f, 0.0f, 0.0f, 1.0f });
+#else
std::array<float, 4> color = { 0.75f, 0.0f, 0.0f, 1.0f };
shader->set_uniform("uniform_color", color);
- render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0f }).cast<float>());
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
// y axis
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.0f, 0.75f, 0.0f, 1.0f });
+#else
color = { 0.0f, 0.75f, 0.0f, 1.0f };
shader->set_uniform("uniform_color", color);
- render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0f }).cast<float>());
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
// z axis
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.0f, 0.0f, 0.75f, 1.0f });
+#else
color = { 0.0f, 0.0f, 0.75f, 1.0f };
shader->set_uniform("uniform_color", color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
render_axis(Geometry::assemble_transform(m_origin).cast<float>());
shader->stop_using();
@@ -416,7 +425,10 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const
}
glsafe(::glEnable(GL_DEPTH_TEST));
- glsafe(::glDepthMask(GL_FALSE));
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (bottom)
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ glsafe(::glDepthMask(GL_FALSE));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
@@ -461,7 +473,10 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const
glsafe(::glFrontFace(GL_CCW));
glsafe(::glDisable(GL_BLEND));
- glsafe(::glDepthMask(GL_TRUE));
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (bottom)
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ glsafe(::glDepthMask(GL_TRUE));
shader->stop_using();
}
@@ -476,6 +491,10 @@ void Bed3D::render_model() const
GLModel* model = const_cast<GLModel*>(&m_model);
if (model->get_filename() != m_model_filename && model->init_from_file(m_model_filename)) {
+#if ENABLE_SEQUENTIAL_LIMITS
+ model->set_color(-1, m_model_color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
// move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad
Vec3d shift = m_bounding_box.center();
shift(2) = -0.03;
@@ -489,10 +508,12 @@ void Bed3D::render_model() const
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader != nullptr) {
shader->start_using();
+#if !ENABLE_SEQUENTIAL_LIMITS
shader->set_uniform("uniform_color", m_model_color);
+#endif // !ENABLE_SEQUENTIAL_LIMITS
shader->set_uniform("emission_factor", 0.0);
::glPushMatrix();
- ::glTranslated(m_model_offset(0), m_model_offset(1), m_model_offset(2));
+ ::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z());
model->render();
::glPopMatrix();
shader->stop_using();
diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp
index c2630b799..71382315d 100644
--- a/src/slic3r/GUI/3DBed.hpp
+++ b/src/slic3r/GUI/3DBed.hpp
@@ -17,8 +17,8 @@ class GeometryBuffer
{
struct Vertex
{
- Vec3f position = Vec3f::Zero();
- Vec2f tex_coords = Vec2f::Zero();
+ Vec3f position{ Vec3f::Zero() };
+ Vec2f tex_coords{ Vec2f::Zero() };
};
std::vector<Vertex> m_vertices;
@@ -53,7 +53,10 @@ class Bed3D
public:
const Vec3d& get_origin() const { return m_origin; }
void set_origin(const Vec3d& origin) { m_origin = origin; }
- void set_stem_length(float length);
+ void set_stem_length(float length) {
+ m_stem_length = length;
+ m_arrow.reset();
+ }
float get_total_length() const { return m_stem_length + DefaultTipLength; }
void render() const;
};
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 3949511f5..2ced8e601 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -205,6 +205,9 @@ void GCodeViewer::SequentialRangeCap::reset() {
void GCodeViewer::SequentialView::Marker::init()
{
m_model.init_from(stilized_arrow(16, 2.0f, 4.0f, 1.0f, 8.0f));
+#if ENABLE_SEQUENTIAL_LIMITS
+ m_model.set_color(-1, { 1.0f, 1.0f, 1.0f, 0.5f });
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
void GCodeViewer::SequentialView::Marker::set_world_position(const Vec3f& position)
@@ -226,7 +229,9 @@ void GCodeViewer::SequentialView::Marker::render() const
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
shader->start_using();
+#if !ENABLE_SEQUENTIAL_LIMITS
shader->set_uniform("uniform_color", m_color);
+#endif // !ENABLE_SEQUENTIAL_LIMITS
shader->set_uniform("emission_factor", 0.0);
glsafe(::glPushMatrix());
diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp
index 48cc53ba0..d5c793e62 100644
--- a/src/slic3r/GUI/GCodeViewer.hpp
+++ b/src/slic3r/GUI/GCodeViewer.hpp
@@ -505,7 +505,9 @@ public:
Vec3f m_world_position;
Transform3f m_world_transform;
float m_z_offset{ 0.5f };
+#if !ENABLE_SEQUENTIAL_LIMITS
std::array<float, 4> m_color{ 1.0f, 1.0f, 1.0f, 0.5f };
+#endif // !ENABLE_SEQUENTIAL_LIMITS
bool m_visible{ true };
public:
@@ -514,7 +516,9 @@ public:
const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); }
void set_world_position(const Vec3f& position);
+#if !ENABLE_SEQUENTIAL_LIMITS
void set_color(const std::array<float, 4>& color) { m_color = color; }
+#endif // !ENABLE_SEQUENTIAL_LIMITS
bool is_visible() const { return m_visible; }
void set_visible(bool visible) { m_visible = visible; }
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index baebbbf2d..8442194f2 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -789,6 +789,97 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas
ImGui::PopStyleVar(2);
}
+#if ENABLE_SEQUENTIAL_LIMITS
+void GLCanvas3D::SequentialPrintClearance::set(const Polygons& polygons, bool fill)
+{
+ m_render_fill = fill;
+
+ m_perimeter.reset();
+ m_fill.reset();
+ if (polygons.empty())
+ return;
+
+ size_t triangles_count = 0;
+ for (const Polygon& poly : polygons) {
+ triangles_count += poly.points.size() - 2;
+ }
+ size_t vertices_count = 3 * triangles_count;
+
+ if (fill) {
+ GLModel::InitializationData fill_data;
+ GLModel::InitializationData::Entity entity;
+ entity.type = GLModel::PrimitiveType::Triangles;
+ entity.color = { 0.3333f, 0.0f, 0.0f, 0.5f };
+ entity.positions.reserve(vertices_count);
+ entity.normals.reserve(vertices_count);
+ entity.indices.reserve(vertices_count);
+
+ ExPolygons polygons_union = union_ex(polygons);
+ for (const ExPolygon& poly : polygons_union) {
+ std::vector<Vec3d> triangulation = triangulate_expolygon_3d(poly, false);
+ for (const Vec3d& v : triangulation) {
+ entity.positions.emplace_back(v.cast<float>() + Vec3f(0.0f, 0.0f, 0.0125f)); // add a small positive z to avoid z-fighting
+ entity.normals.emplace_back(Vec3f::UnitZ());
+ size_t positions_count = entity.positions.size();
+ if (positions_count % 3 == 0) {
+ entity.indices.emplace_back(positions_count - 3);
+ entity.indices.emplace_back(positions_count - 2);
+ entity.indices.emplace_back(positions_count - 1);
+ }
+ }
+ }
+
+ fill_data.entities.emplace_back(entity);
+ m_fill.init_from(fill_data);
+ }
+
+ GLModel::InitializationData perimeter_data;
+ for (const Polygon& poly : polygons) {
+ GLModel::InitializationData::Entity ent;
+ ent.type = GLModel::PrimitiveType::LineLoop;
+ ent.positions.reserve(poly.points.size());
+ ent.indices.reserve(poly.points.size());
+ unsigned int id_count = 0;
+ for (const Point& p : poly.points) {
+ ent.positions.emplace_back(unscale<float>(p.x()), unscale<float>(p.y()), 0.025f); // add a small positive z to avoid z-fighting
+ ent.normals.emplace_back(Vec3f::UnitZ());
+ ent.indices.emplace_back(id_count++);
+ }
+
+ perimeter_data.entities.emplace_back(ent);
+ }
+
+ m_perimeter.init_from(perimeter_data);
+}
+
+void GLCanvas3D::SequentialPrintClearance::render() const
+{
+ std::array<float, 4> FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f };
+ std::array<float, 4> NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
+
+ GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
+ if (shader == nullptr)
+ return;
+
+ shader->start_using();
+
+ glsafe(::glEnable(GL_DEPTH_TEST));
+ glsafe(::glDisable(GL_CULL_FACE));
+ glsafe(::glEnable(GL_BLEND));
+ glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+
+ const_cast<GLModel*>(&m_perimeter)->set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR);
+ m_perimeter.render();
+ m_fill.render();
+
+ glsafe(::glDisable(GL_BLEND));
+ glsafe(::glEnable(GL_CULL_FACE));
+ glsafe(::glDisable(GL_DEPTH_TEST));
+
+ shader->stop_using();
+}
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
@@ -1376,7 +1467,11 @@ void GLCanvas3D::render()
_render_sla_slices();
_render_selection();
_render_bed(!camera.is_looking_downward(), true);
-
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined &&
+ !m_layers_editing.is_enabled())
+ _render_sequential_clearance();
+#endif // ENABLE_SEQUENTIAL_LIMITS
#if ENABLE_RENDER_SELECTION_CENTER
_render_selection_center();
#endif // ENABLE_RENDER_SELECTION_CENTER
@@ -1917,7 +2012,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
bool wt = dynamic_cast<const ConfigOptionBool*>(m_config->option("wipe_tower"))->value;
bool co = dynamic_cast<const ConfigOptionBool*>(m_config->option("complete_objects"))->value;
- if ((extruders_count > 1) && wt && !co) {
+ if (extruders_count > 1 && wt && !co) {
// Height of a print (Show at least a slab)
double height = std::max(m_model->bounding_box().max(2), 10.0);
@@ -2864,6 +2959,23 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.set_start_position_3D_as_invalid();
m_mouse.position = pos.cast<double>();
+
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (evt.Dragging() && current_printer_technology() == ptFFF && fff_print()->config().complete_objects) {
+ switch (m_gizmos.get_current_type())
+ {
+ case GLGizmosManager::EType::Move:
+ case GLGizmosManager::EType::Scale:
+ case GLGizmosManager::EType::Rotate:
+ {
+ update_sequential_clearance();
+ break;
+ }
+ default: { break; }
+ }
+ }
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
return;
}
@@ -2985,6 +3097,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.drag.move_volume_idx = volume_idx;
m_selection.start_dragging();
m_mouse.drag.start_position_3D = m_mouse.scene_position;
+#if ENABLE_SEQUENTIAL_LIMITS
+ m_sequential_print_clearance_first_displacement = true;
+#endif // ENABLE_SEQUENTIAL_LIMITS
m_moving = true;
}
}
@@ -3030,6 +3145,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects)
+ update_sequential_clearance();
+#endif // ENABLE_SEQUENTIAL_LIMITS
wxGetApp().obj_manipul()->set_dirty();
m_dirty = true;
}
@@ -3062,7 +3181,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// See GH issue #3816.
Camera& camera = wxGetApp().plater()->get_camera();
camera.recover_from_free_camera();
- camera.rotate_on_sphere(rot.x(), rot.y(), wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA);
+ camera.rotate_on_sphere(rot.x(), rot.y(), current_printer_technology() != ptSLA);
}
m_dirty = true;
@@ -3279,15 +3398,15 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
for (const std::pair<int, int>& i : done) {
ModelObject* m = m_model->objects[i.first];
#if ENABLE_ALLOW_NEGATIVE_Z
- double shift_z = m->get_instance_min_z(i.second);
+ const double shift_z = m->get_instance_min_z(i.second);
#if DISABLE_ALLOW_NEGATIVE_Z_FOR_SLA
if (current_printer_technology() == ptSLA || shift_z > 0.0) {
#else
if (shift_z > 0.0) {
#endif // DISABLE_ALLOW_NEGATIVE_Z_FOR_SLA
- Vec3d shift(0.0, 0.0, -shift_z);
+ const Vec3d shift(0.0, 0.0, -shift_z);
#else
- Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
+ const Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
#endif // ENABLE_ALLOW_NEGATIVE_Z
m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift);
@@ -3309,6 +3428,10 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
if (wipe_tower_origin != Vec3d::Zero())
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin)));
+#if ENABLE_SEQUENTIAL_LIMITS
+ set_sequential_print_clearance(Polygons(), false);
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
m_dirty = true;
}
@@ -3655,6 +3778,93 @@ void GLCanvas3D::mouse_up_cleanup()
m_canvas->ReleaseMouse();
}
+#if ENABLE_SEQUENTIAL_LIMITS
+void GLCanvas3D::update_sequential_clearance()
+{
+ if (current_printer_technology() != ptFFF || !fff_print()->config().complete_objects)
+ return;
+
+ // collects instance transformations from volumes
+ // first define temporary cache
+ unsigned int instances_count = 0;
+ std::vector<std::vector<std::optional<Geometry::Transformation>>> instance_transforms;
+ for (size_t obj = 0; obj < m_model->objects.size(); ++obj) {
+ instance_transforms.emplace_back(std::vector<std::optional<Geometry::Transformation>>());
+ const ModelObject* model_object = m_model->objects[obj];
+ for (size_t i = 0; i < model_object->instances.size(); ++i) {
+ instance_transforms[obj].emplace_back(std::optional<Geometry::Transformation>());
+ ++instances_count;
+ }
+ }
+
+ if (instances_count == 1)
+ return;
+
+ // second fill temporary cache with data from volumes
+ for (const GLVolume* v : m_volumes.volumes) {
+ if (v->is_modifier || v->is_wipe_tower)
+ continue;
+
+ auto& transform = instance_transforms[v->object_idx()][v->instance_idx()];
+ if (!transform.has_value())
+ transform = v->get_instance_transformation();
+ }
+
+ // calculates objects 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
+ // this is done only the first time this method is called while moving the mouse,
+ // the results are then cached for following displacements
+ if (m_sequential_print_clearance_first_displacement) {
+ m_sequential_print_clearance.m_hull_2d_cache.clear();
+ float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON));
+ double mitter_limit = scale_(0.1);
+ m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size());
+ for (size_t i = 0; i < m_model->objects.size(); ++i) {
+ ModelObject* model_object = m_model->objects[i];
+ ModelInstance* model_instance0 = model_object->instances.front();
+ Polygon hull_2d = offset(model_object->convex_hull_2d(Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(),
+ model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
+ // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
+ // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
+ shrink_factor,
+ jtRound, mitter_limit).front();
+
+ Pointf3s& cache_hull_2d = m_sequential_print_clearance.m_hull_2d_cache.emplace_back(Pointf3s());
+ cache_hull_2d.reserve(hull_2d.points.size());
+ for (const Point& p : hull_2d.points) {
+ cache_hull_2d.emplace_back(unscale<double>(p.x()), unscale<double>(p.y()), 0.0);
+ }
+ }
+ m_sequential_print_clearance_first_displacement = false;
+ }
+
+ // calculates instances 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
+ Polygons polygons;
+ polygons.reserve(instances_count);
+ for (size_t i = 0; i < instance_transforms.size(); ++i) {
+ const auto& instances = instance_transforms[i];
+ double rotation_z0 = instances.front()->get_rotation().z();
+ for (const auto& instance : instances) {
+ Geometry::Transformation transformation;
+ const Vec3d& offset = instance->get_offset();
+ transformation.set_offset({ offset.x(), offset.y(), 0.0 });
+ transformation.set_rotation(Z, instance->get_rotation().z() - rotation_z0);
+ const Transform3d& trafo = transformation.get_matrix();
+ const Pointf3s& hull_2d = m_sequential_print_clearance.m_hull_2d_cache[i];
+ Points inst_pts;
+ inst_pts.reserve(hull_2d.size());
+ for (size_t j = 0; j < hull_2d.size(); ++j) {
+ const Vec3d p = trafo * hull_2d[j];
+ inst_pts.emplace_back(scaled<double>(p.x()), scaled<double>(p.y()));
+ }
+ polygons.emplace_back(Geometry::convex_hull(std::move(inst_pts)));
+ }
+ }
+
+ // sends instances 2d hulls to be rendered
+ set_sequential_print_clearance(polygons, false);
+}
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
bool GLCanvas3D::_is_shown_on_screen() const
{
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
@@ -4756,7 +4966,7 @@ void GLCanvas3D::_render_background() const
bool use_error_color = false;
if (wxGetApp().is_editor()) {
use_error_color = m_dynamic_background_enabled &&
- (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA || !m_volumes.empty());
+ (current_printer_technology() != ptSLA || !m_volumes.empty());
if (!m_volumes.empty())
use_error_color &= _is_any_volume_outside();
@@ -4902,6 +5112,13 @@ void GLCanvas3D::_render_selection() const
m_selection.render(scale_factor);
}
+#if ENABLE_SEQUENTIAL_LIMITS
+void GLCanvas3D::_render_sequential_clearance() const
+{
+ m_sequential_print_clearance.render();
+}
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
#if ENABLE_RENDER_SELECTION_CENTER
void GLCanvas3D::_render_selection_center() const
{
@@ -5167,7 +5384,7 @@ void GLCanvas3D::_render_camera_target() const
void GLCanvas3D::_render_sla_slices() const
{
- if (!m_use_clipping_planes || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
+ if (!m_use_clipping_planes || current_printer_technology() != ptSLA)
return;
const SLAPrint* print = this->sla_print();
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index f7493f157..c0ef83b72 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -496,6 +496,26 @@ private:
void load_arrange_settings();
+#if ENABLE_SEQUENTIAL_LIMITS
+ class SequentialPrintClearance
+ {
+ GLModel m_fill;
+ GLModel m_perimeter;
+ bool m_render_fill{ true };
+
+ std::vector<Pointf3s> m_hull_2d_cache;
+
+ public:
+ void set(const Polygons& polygons, bool fill);
+ void render() const;
+
+ friend class GLCanvas3D;
+ };
+
+ SequentialPrintClearance m_sequential_print_clearance;
+ bool m_sequential_print_clearance_first_displacement{ true };
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
public:
explicit GLCanvas3D(wxGLCanvas* canvas);
~GLCanvas3D();
@@ -737,6 +757,14 @@ public:
#endif
}
+#if ENABLE_SEQUENTIAL_LIMITS
+ void set_sequential_print_clearance(const Polygons& polygons, bool fill) { m_sequential_print_clearance.set(polygons, fill); }
+ void update_sequential_clearance();
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
+ const Print* fff_print() const;
+ const SLAPrint* sla_print() const;
+
#if ENABLE_SCROLLABLE_LEGEND
void reset_old_size() { m_old_size = { 0, 0 }; }
#endif // ENABLE_SCROLLABLE_LEGEND
@@ -767,6 +795,9 @@ private:
void _render_objects() const;
void _render_gcode() const;
void _render_selection() const;
+#if ENABLE_SEQUENTIAL_LIMITS
+ void _render_sequential_clearance() const;
+#endif // ENABLE_SEQUENTIAL_LIMITS
#if ENABLE_RENDER_SELECTION_CENTER
void _render_selection_center() const;
#endif // ENABLE_RENDER_SELECTION_CENTER
@@ -843,10 +874,6 @@ private:
float get_overlay_window_width() { return LayersEditing::get_overlay_window_width(); }
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
-
-public:
- const Print* fff_print() const;
- const SLAPrint* sla_print() const;
};
} // namespace GUI
diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp
index e738aa3c4..5452a1865 100644
--- a/src/slic3r/GUI/GLModel.cpp
+++ b/src/slic3r/GUI/GLModel.cpp
@@ -2,6 +2,11 @@
#include "GLModel.hpp"
#include "3DScene.hpp"
+#if ENABLE_SEQUENTIAL_LIMITS
+#include "GUI_App.hpp"
+#include "GLShader.hpp"
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Model.hpp"
@@ -13,6 +18,45 @@
namespace Slic3r {
namespace GUI {
+#if ENABLE_SEQUENTIAL_LIMITS
+void GLModel::init_from(const InitializationData& data)
+{
+ if (!m_render_data.empty()) // call reset() if you want to reuse this model
+ return;
+
+ for (const InitializationData::Entity& entity : data.entities) {
+ if (entity.positions.empty() || entity.indices.empty())
+ continue;
+
+ assert(entity.normals.empty() || entity.normals.size() == entity.positions.size());
+
+ RenderData rdata;
+ rdata.type = entity.type;
+ rdata.color = entity.color;
+
+ // vertices/normals data
+ std::vector<float> vertices(6 * entity.positions.size());
+ for (size_t i = 0; i < entity.positions.size(); ++i) {
+ const size_t offset = i * 6;
+ ::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(entity.positions[i].data()), 3 * sizeof(float));
+ if (!entity.normals.empty())
+ ::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(entity.normals[i].data()), 3 * sizeof(float));
+ }
+
+ // indices data
+ std::vector<unsigned int> indices = entity.indices;
+
+ rdata.indices_count = static_cast<unsigned int>(indices.size());
+
+ // update bounding box
+ for (size_t i = 0; i < entity.positions.size(); ++i) {
+ m_bounding_box.merge(entity.positions[i].cast<double>());
+ }
+
+ send_to_gpu(rdata, vertices, indices);
+ m_render_data.emplace_back(rdata);
+ }
+#else
void GLModel::init_from(const GLModelInitializationData& data)
{
assert(!data.positions.empty() && !data.triangles.empty());
@@ -44,10 +88,41 @@ void GLModel::init_from(const GLModelInitializationData& data)
}
send_to_gpu(vertices, indices);
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
void GLModel::init_from(const TriangleMesh& mesh)
{
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (!m_render_data.empty()) // call reset() if you want to reuse this model
+ return;
+
+ RenderData data;
+ data.type = PrimitiveType::Triangles;
+
+ std::vector<float> vertices = std::vector<float>(18 * mesh.stl.stats.number_of_facets);
+ std::vector<unsigned int> indices = std::vector<unsigned int>(3 * mesh.stl.stats.number_of_facets);
+
+ unsigned int vertices_count = 0;
+ for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
+ const stl_facet& facet = mesh.stl.facet_start[i];
+ for (size_t j = 0; j < 3; ++j) {
+ size_t offset = i * 18 + j * 6;
+ ::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(facet.vertex[j].data()), 3 * sizeof(float));
+ ::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(facet.normal.data()), 3 * sizeof(float));
+ }
+ for (size_t j = 0; j < 3; ++j) {
+ indices[i * 3 + j] = vertices_count + j;
+ }
+ vertices_count += 3;
+ }
+
+ data.indices_count = static_cast<unsigned int>(indices.size());
+ m_bounding_box = mesh.bounding_box();
+
+ send_to_gpu(data, vertices, indices);
+ m_render_data.emplace_back(data);
+#else
if (m_vbo_id > 0) // call reset() if you want to reuse this model
return;
@@ -72,6 +147,7 @@ void GLModel::init_from(const TriangleMesh& mesh)
m_bounding_box = mesh.bounding_box();
send_to_gpu(vertices, indices);
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
bool GLModel::init_from_file(const std::string& filename)
@@ -99,8 +175,29 @@ bool GLModel::init_from_file(const std::string& filename)
return true;
}
+#if ENABLE_SEQUENTIAL_LIMITS
+void GLModel::set_color(int entity_id, const std::array<float, 4>& color)
+{
+ for (size_t i = 0; i < m_render_data.size(); ++i) {
+ if (entity_id == -1 || static_cast<int>(i) == entity_id)
+ m_render_data[i].color = color;
+ }
+}
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
void GLModel::reset()
{
+#if ENABLE_SEQUENTIAL_LIMITS
+ for (RenderData& data : m_render_data) {
+ // release gpu memory
+ if (data.ibo_id > 0)
+ glsafe(::glDeleteBuffers(1, &data.ibo_id));
+ if (data.vbo_id > 0)
+ glsafe(::glDeleteBuffers(1, &data.vbo_id));
+ }
+
+ m_render_data.clear();
+#else
// release gpu memory
if (m_ibo_id > 0) {
glsafe(::glDeleteBuffers(1, &m_ibo_id));
@@ -113,12 +210,49 @@ void GLModel::reset()
}
m_indices_count = 0;
+#endif // ENABLE_SEQUENTIAL_LIMITS
m_bounding_box = BoundingBoxf3();
m_filename = std::string();
}
void GLModel::render() const
{
+#if ENABLE_SEQUENTIAL_LIMITS
+ for (const RenderData& data : m_render_data) {
+ if (data.vbo_id == 0 || data.ibo_id == 0)
+ continue;
+
+ GLenum mode;
+ switch (data.type)
+ {
+ default:
+ case PrimitiveType::Triangles: { mode = GL_TRIANGLES; break; }
+ case PrimitiveType::Lines: { mode = GL_LINES; break; }
+ case PrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; }
+ case PrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; }
+ }
+
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id));
+ glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)0));
+ glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
+
+ glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
+ glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
+
+ GLShaderProgram* shader = wxGetApp().get_current_shader();
+ if (shader != nullptr)
+ shader->set_uniform("uniform_color", data.color);
+
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id));
+ glsafe(::glDrawElements(mode, static_cast<GLsizei>(data.indices_count), GL_UNSIGNED_INT, (const void*)0));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+
+ glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
+ glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
+
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
+ }
+#else
if (m_vbo_id == 0 || m_ibo_id == 0)
return;
@@ -137,8 +271,28 @@ void GLModel::render() const
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
+#if ENABLE_SEQUENTIAL_LIMITS
+void GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
+{
+ assert(data.vbo_id == 0);
+ assert(data.ibo_id == 0);
+
+ // vertex data -> send to gpu
+ glsafe(::glGenBuffers(1, &data.vbo_id));
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id));
+ glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW));
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
+
+ // indices data -> send to gpu
+ glsafe(::glGenBuffers(1, &data.ibo_id));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id));
+ glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+}
+#else
void GLModel::send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
{
// vertex data -> send to gpu
@@ -153,60 +307,138 @@ void GLModel::send_to_gpu(const std::vector<float>& vertices, const std::vector<
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
+#endif // ENABLE_SEQUENTIAL_LIMITS
+#if ENABLE_SEQUENTIAL_LIMITS
+GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
+{
+ auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) {
+ entity.positions.emplace_back(position);
+ entity.normals.emplace_back(normal);
+ };
+ auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) {
+ entity.indices.emplace_back(v1);
+ entity.indices.emplace_back(v2);
+ entity.indices.emplace_back(v3);
+ };
+#else
GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
{
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
data.positions.emplace_back(position);
data.normals.emplace_back(normal);
};
+#endif // ENABLE_SEQUENTIAL_LIMITS
resolution = std::max(4, resolution);
+#if ENABLE_SEQUENTIAL_LIMITS
+ GLModel::InitializationData data;
+ GLModel::InitializationData::Entity entity;
+ entity.type = GLModel::PrimitiveType::Triangles;
+#else
GLModelInitializationData data;
+#endif // ENABLE_SEQUENTIAL_LIMITS
const float angle_step = 2.0f * M_PI / static_cast<float>(resolution);
std::vector<float> cosines(resolution);
std::vector<float> sines(resolution);
- for (int i = 0; i < resolution; ++i)
- {
- float angle = angle_step * static_cast<float>(i);
+ for (int i = 0; i < resolution; ++i) {
+ const float angle = angle_step * static_cast<float>(i);
cosines[i] = ::cos(angle);
sines[i] = -::sin(angle);
}
const float total_height = tip_height + stem_height;
+#if ENABLE_SEQUENTIAL_LIMITS
+ // tip vertices/normals
+ append_vertex(entity, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ());
+ for (int i = 0; i < resolution; ++i) {
+ append_vertex(entity, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
+ }
+
+ // tip triangles
+ for (int i = 0; i < resolution; ++i) {
+ const int v3 = (i < resolution - 1) ? i + 2 : 1;
+ append_indices(entity, 0, i + 1, v3);
+ }
+
+ // tip cap outer perimeter vertices
+ for (int i = 0; i < resolution; ++i) {
+ append_vertex(entity, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
+ }
+
+ // tip cap inner perimeter vertices
+ for (int i = 0; i < resolution; ++i) {
+ append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
+ }
+
+ // tip cap triangles
+ for (int i = 0; i < resolution; ++i) {
+ const int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
+ const int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
+ append_indices(entity, i + resolution + 1, v3, v2);
+ append_indices(entity, i + resolution + 1, i + 2 * resolution + 1, v3);
+ }
+
+ // stem bottom vertices
+ for (int i = 0; i < resolution; ++i) {
+ append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
+ }
+
+ // stem top vertices
+ for (int i = 0; i < resolution; ++i) {
+ append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f });
+ }
+
+ // stem triangles
+ for (int i = 0; i < resolution; ++i) {
+ const int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
+ const int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
+ append_indices(entity, i + 3 * resolution + 1, v3, v2);
+ append_indices(entity, i + 3 * resolution + 1, i + 4 * resolution + 1, v3);
+ }
+
+ // stem cap vertices
+ append_vertex(entity, Vec3f::Zero(), -Vec3f::UnitZ());
+ for (int i = 0; i < resolution; ++i) {
+ append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ());
+ }
+
+ // stem cap triangles
+ for (int i = 0; i < resolution; ++i) {
+ const int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
+ append_indices(entity, 5 * resolution + 1, v3, i + 5 * resolution + 2);
+ }
+
+ data.entities.emplace_back(entity);
+#else
// tip vertices/normals
append_vertex(data, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ());
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
}
// tip triangles
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
int v3 = (i < resolution - 1) ? i + 2 : 1;
data.triangles.emplace_back(0, i + 1, v3);
}
// tip cap outer perimeter vertices
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
}
// tip cap inner perimeter vertices
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
}
// tip cap triangles
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
data.triangles.emplace_back(i + resolution + 1, v3, v2);
@@ -214,20 +446,17 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
}
// stem bottom vertices
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
}
// stem top vertices
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f });
}
// stem triangles
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
data.triangles.emplace_back(i + 3 * resolution + 1, v3, v2);
@@ -236,31 +465,50 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
// stem cap vertices
append_vertex(data, Vec3f::Zero(), -Vec3f::UnitZ());
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ());
}
// stem cap triangles
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
data.triangles.emplace_back(5 * resolution + 1, v3, i + 5 * resolution + 2);
}
+#endif // ENABLE_SEQUENTIAL_LIMITS
return data;
}
+#if ENABLE_SEQUENTIAL_LIMITS
+GLModel::InitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
+{
+ auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) {
+ entity.positions.emplace_back(position);
+ entity.normals.emplace_back(normal);
+ };
+ auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) {
+ entity.indices.emplace_back(v1);
+ entity.indices.emplace_back(v2);
+ entity.indices.emplace_back(v3);
+ };
+#else
GLModelInitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
{
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
data.positions.emplace_back(position);
data.normals.emplace_back(normal);
};
+#endif // ENABLE_SEQUENTIAL_LIMITS
resolution = std::max(2, resolution);
+#if ENABLE_SEQUENTIAL_LIMITS
+ GLModel::InitializationData data;
+ GLModel::InitializationData::Entity entity;
+ entity.type = GLModel::PrimitiveType::Triangles;
+#else
GLModelInitializationData data;
+#endif // ENABLE_SEQUENTIAL_LIMITS
const float half_thickness = 0.5f * thickness;
const float half_stem_width = 0.5f * stem_width;
@@ -270,6 +518,153 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
const float inner_radius = radius - half_stem_width;
const float step_angle = 0.5f * PI / static_cast<float>(resolution);
+#if ENABLE_SEQUENTIAL_LIMITS
+ // tip
+ // top face vertices
+ append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { -tip_height, radius, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitZ());
+
+ // top face triangles
+ append_indices(entity, 0, 1, 2);
+ append_indices(entity, 0, 2, 4);
+ append_indices(entity, 4, 2, 3);
+
+ // bottom face vertices
+ append_vertex(entity, { 0.0f, outer_radius, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { -tip_height, radius, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { 0.0f, inner_radius, -half_thickness }, -Vec3f::UnitZ());
+
+ // bottom face triangles
+ append_indices(entity, 5, 7, 6);
+ append_indices(entity, 5, 9, 7);
+ append_indices(entity, 9, 8, 7);
+
+ // side faces vertices
+ append_vertex(entity, { 0.0f, outer_radius, -half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitX());
+
+ Vec3f normal(-half_tip_width, tip_height, 0.0f);
+ normal.normalize();
+ append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, normal);
+ append_vertex(entity, { -tip_height, radius, -half_thickness }, normal);
+ append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, normal);
+ append_vertex(entity, { -tip_height, radius, half_thickness }, normal);
+
+ normal = Vec3f(-half_tip_width, -tip_height, 0.0f);
+ normal.normalize();
+ append_vertex(entity, { -tip_height, radius, -half_thickness }, normal);
+ append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, normal);
+ append_vertex(entity, { -tip_height, radius, half_thickness }, normal);
+ append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, normal);
+
+ append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { 0.0f, inner_radius, -half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX());
+
+ // side face triangles
+ for (int i = 0; i < 4; ++i) {
+ const int ii = i * 4;
+ append_indices(entity, 10 + ii, 11 + ii, 13 + ii);
+ append_indices(entity, 10 + ii, 13 + ii, 12 + ii);
+ }
+
+ // stem
+ // top face vertices
+ for (int i = 0; i <= resolution; ++i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ append_vertex(entity, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
+ }
+
+ for (int i = 0; i <= resolution; ++i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ append_vertex(entity, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
+ }
+
+ // top face triangles
+ for (int i = 0; i < resolution; ++i) {
+ append_indices(entity, 26 + i, 27 + i, 27 + resolution + i);
+ append_indices(entity, 27 + i, 28 + resolution + i, 27 + resolution + i);
+ }
+
+ // bottom face vertices
+ for (int i = 0; i <= resolution; ++i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ append_vertex(entity, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
+ }
+
+ for (int i = 0; i <= resolution; ++i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ append_vertex(entity, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
+ }
+
+ // bottom face triangles
+ for (int i = 0; i < resolution; ++i) {
+ append_indices(entity, 28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i);
+ append_indices(entity, 29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i);
+ }
+
+ // side faces vertices and triangles
+ for (int i = 0; i <= resolution; ++i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ const float c = ::cos(angle);
+ const float s = ::sin(angle);
+ append_vertex(entity, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f });
+ }
+
+ for (int i = 0; i <= resolution; ++i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ const float c = ::cos(angle);
+ const float s = ::sin(angle);
+ append_vertex(entity, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f });
+ }
+
+ int first_id = 26 + 4 * (resolution + 1);
+ for (int i = 0; i < resolution; ++i) {
+ const int ii = first_id + i;
+ append_indices(entity, ii, ii + 1, ii + resolution + 2);
+ append_indices(entity, ii, ii + resolution + 2, ii + resolution + 1);
+ }
+
+ append_vertex(entity, { inner_radius, 0.0f, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { outer_radius, 0.0f, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { inner_radius, 0.0f, half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { outer_radius, 0.0f, half_thickness }, -Vec3f::UnitY());
+
+ first_id = 26 + 6 * (resolution + 1);
+ append_indices(entity, first_id, first_id + 1, first_id + 3);
+ append_indices(entity, first_id, first_id + 3, first_id + 2);
+
+ for (int i = resolution; i >= 0; --i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ const float c = ::cos(angle);
+ const float s = ::sin(angle);
+ append_vertex(entity, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f });
+ }
+
+ for (int i = resolution; i >= 0; --i) {
+ const float angle = static_cast<float>(i) * step_angle;
+ const float c = ::cos(angle);
+ const float s = ::sin(angle);
+ append_vertex(entity, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f });
+ }
+
+ first_id = 30 + 6 * (resolution + 1);
+ for (int i = 0; i < resolution; ++i) {
+ const int ii = first_id + i;
+ append_indices(entity, ii, ii + 1, ii + resolution + 2);
+ append_indices(entity, ii, ii + resolution + 2, ii + resolution + 1);
+ }
+
+ data.entities.emplace_back(entity);
+#else
// tip
// top face vertices
append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ());
@@ -321,8 +716,7 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX());
// side face triangles
- for (int i = 0; i < 4; ++i)
- {
+ for (int i = 0; i < 4; ++i) {
int ii = i * 4;
data.triangles.emplace_back(10 + ii, 11 + ii, 13 + ii);
data.triangles.emplace_back(10 + ii, 13 + ii, 12 + ii);
@@ -330,56 +724,48 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
// stem
// top face vertices
- for (int i = 0; i <= resolution; ++i)
- {
+ for (int i = 0; i <= resolution; ++i) {
float angle = static_cast<float>(i) * step_angle;
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
}
- for (int i = 0; i <= resolution; ++i)
- {
+ for (int i = 0; i <= resolution; ++i) {
float angle = static_cast<float>(i) * step_angle;
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
}
// top face triangles
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
data.triangles.emplace_back(26 + i, 27 + i, 27 + resolution + i);
data.triangles.emplace_back(27 + i, 28 + resolution + i, 27 + resolution + i);
}
// bottom face vertices
- for (int i = 0; i <= resolution; ++i)
- {
+ for (int i = 0; i <= resolution; ++i) {
float angle = static_cast<float>(i) * step_angle;
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
}
- for (int i = 0; i <= resolution; ++i)
- {
+ for (int i = 0; i <= resolution; ++i) {
float angle = static_cast<float>(i) * step_angle;
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
}
// bottom face triangles
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
data.triangles.emplace_back(28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i);
data.triangles.emplace_back(29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i);
}
// side faces vertices and triangles
- for (int i = 0; i <= resolution; ++i)
- {
+ for (int i = 0; i <= resolution; ++i) {
float angle = static_cast<float>(i) * step_angle;
float c = ::cos(angle);
float s = ::sin(angle);
append_vertex(data, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f });
}
- for (int i = 0; i <= resolution; ++i)
- {
+ for (int i = 0; i <= resolution; ++i) {
float angle = static_cast<float>(i) * step_angle;
float c = ::cos(angle);
float s = ::sin(angle);
@@ -387,8 +773,7 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
}
int first_id = 26 + 4 * (resolution + 1);
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
int ii = first_id + i;
data.triangles.emplace_back(ii, ii + 1, ii + resolution + 2);
data.triangles.emplace_back(ii, ii + resolution + 2, ii + resolution + 1);
@@ -403,16 +788,14 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
data.triangles.emplace_back(first_id, first_id + 1, first_id + 3);
data.triangles.emplace_back(first_id, first_id + 3, first_id + 2);
- for (int i = resolution; i >= 0; --i)
- {
+ for (int i = resolution; i >= 0; --i) {
float angle = static_cast<float>(i) * step_angle;
float c = ::cos(angle);
float s = ::sin(angle);
append_vertex(data, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f });
}
- for (int i = resolution; i >= 0; --i)
- {
+ for (int i = resolution; i >= 0; --i) {
float angle = static_cast<float>(i) * step_angle;
float c = ::cos(angle);
float s = ::sin(angle);
@@ -420,16 +803,33 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
}
first_id = 30 + 6 * (resolution + 1);
- for (int i = 0; i < resolution; ++i)
- {
+ for (int i = 0; i < resolution; ++i) {
int ii = first_id + i;
data.triangles.emplace_back(ii, ii + 1, ii + resolution + 2);
data.triangles.emplace_back(ii, ii + resolution + 2, ii + resolution + 1);
}
+#endif // ENABLE_SEQUENTIAL_LIMITS
return data;
}
+#if ENABLE_SEQUENTIAL_LIMITS
+GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
+{
+ auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) {
+ entity.positions.emplace_back(position);
+ entity.normals.emplace_back(normal);
+ };
+ auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) {
+ entity.indices.emplace_back(v1);
+ entity.indices.emplace_back(v2);
+ entity.indices.emplace_back(v3);
+ };
+
+ GLModel::InitializationData data;
+ GLModel::InitializationData::Entity entity;
+ entity.type = GLModel::PrimitiveType::Triangles;
+#else
GLModelInitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
{
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
@@ -438,6 +838,7 @@ GLModelInitializationData straight_arrow(float tip_width, float tip_height, floa
};
GLModelInitializationData data;
+#endif // ENABLE_SEQUENTIAL_LIMITS
const float half_thickness = 0.5f * thickness;
const float half_stem_width = 0.5f * stem_width;
@@ -445,6 +846,87 @@ GLModelInitializationData straight_arrow(float tip_width, float tip_height, floa
const float total_height = tip_height + stem_height;
// top face vertices
+#if ENABLE_SEQUENTIAL_LIMITS
+ append_vertex(entity, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { 0.0, total_height, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
+ append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
+
+ // top face triangles
+ append_indices(entity, 0, 1, 6);
+ append_indices(entity, 6, 1, 5);
+ append_indices(entity, 4, 5, 3);
+ append_indices(entity, 5, 1, 3);
+ append_indices(entity, 1, 2, 3);
+
+ // bottom face vertices
+ append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { 0.0, total_height, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
+ append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ());
+
+ // bottom face triangles
+ append_indices(entity, 7, 13, 8);
+ append_indices(entity, 13, 12, 8);
+ append_indices(entity, 12, 11, 10);
+ append_indices(entity, 8, 12, 10);
+ append_indices(entity, 9, 8, 10);
+
+ // side faces vertices
+ append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitX());
+ append_vertex(entity, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitX());
+
+ append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY());
+
+ Vec3f normal(tip_height, half_tip_width, 0.0f);
+ normal.normalize();
+ append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, normal);
+ append_vertex(entity, { 0.0, total_height, -half_thickness }, normal);
+ append_vertex(entity, { half_tip_width, stem_height, half_thickness }, normal);
+ append_vertex(entity, { 0.0, total_height, half_thickness }, normal);
+
+ normal = Vec3f(-tip_height, half_tip_width, 0.0f);
+ normal.normalize();
+ append_vertex(entity, { 0.0, total_height, -half_thickness }, normal);
+ append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, normal);
+ append_vertex(entity, { 0.0, total_height, half_thickness }, normal);
+ append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, normal);
+
+ append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY());
+
+ append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitX());
+ append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitX());
+ append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitX());
+ append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitX());
+
+ append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
+ append_vertex(entity, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
+
+ // side face triangles
+ for (int i = 0; i < 7; ++i) {
+ const int ii = i * 4;
+ append_indices(entity, 14 + ii, 15 + ii, 17 + ii);
+ append_indices(entity, 14 + ii, 17 + ii, 16 + ii);
+ }
+
+ data.entities.emplace_back(entity);
+#else
append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
append_vertex(data, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
@@ -517,12 +999,12 @@ GLModelInitializationData straight_arrow(float tip_width, float tip_height, floa
append_vertex(data, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
// side face triangles
- for (int i = 0; i < 7; ++i)
- {
+ for (int i = 0; i < 7; ++i) {
int ii = i * 4;
data.triangles.emplace_back(14 + ii, 15 + ii, 17 + ii);
data.triangles.emplace_back(14 + ii, 17 + ii, 16 + ii);
}
+#endif // ENABLE_SEQUENTIAL_LIMITS
return data;
}
diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp
index 0b4a69bdb..8e1e3dfd5 100644
--- a/src/slic3r/GUI/GLModel.hpp
+++ b/src/slic3r/GUI/GLModel.hpp
@@ -12,40 +12,115 @@ class TriangleMesh;
namespace GUI {
+#if !ENABLE_SEQUENTIAL_LIMITS
struct GLModelInitializationData
{
std::vector<Vec3f> positions;
std::vector<Vec3f> normals;
std::vector<Vec3i> triangles;
};
+#endif // !ENABLE_SEQUENTIAL_LIMITS
class GLModel
{
+#if ENABLE_SEQUENTIAL_LIMITS
+ public:
+ enum class PrimitiveType : unsigned char
+ {
+ Triangles,
+ Lines,
+ LineStrip,
+ LineLoop
+ };
+
+ struct RenderData
+ {
+ PrimitiveType type;
+ unsigned int vbo_id{ 0 };
+ unsigned int ibo_id{ 0 };
+ size_t indices_count{ 0 };
+ std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
+ };
+
+ struct InitializationData
+ {
+ struct Entity
+ {
+ PrimitiveType type;
+ std::vector<Vec3f> positions;
+ std::vector<Vec3f> normals;
+ std::vector<unsigned int> indices;
+ std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
+ };
+
+ std::vector<Entity> entities;
+ };
+
+ private:
+ std::vector<RenderData> m_render_data;
+#else
unsigned int m_vbo_id{ 0 };
unsigned int m_ibo_id{ 0 };
size_t m_indices_count{ 0 };
+#endif // ENABLE_SEQUENTIAL_LIMITS
BoundingBoxf3 m_bounding_box;
std::string m_filename;
public:
+ GLModel() = default;
virtual ~GLModel() { reset(); }
+#if ENABLE_SEQUENTIAL_LIMITS
+ void init_from(const InitializationData& data);
+#else
void init_from(const GLModelInitializationData& data);
+#endif // ENABLE_SEQUENTIAL_LIMITS
void init_from(const TriangleMesh& mesh);
bool init_from_file(const std::string& filename);
+
+#if ENABLE_SEQUENTIAL_LIMITS
+ // if entity_id == -1 set the color of all entities
+ void set_color(int entity_id, const std::array<float, 4>& color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
void reset();
void render() const;
- const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
+#if ENABLE_SEQUENTIAL_LIMITS
+ bool is_initialized() const { return !m_render_data.empty(); }
+#endif // ENABLE_SEQUENTIAL_LIMITS
+ const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
const std::string& get_filename() const { return m_filename; }
private:
+#if ENABLE_SEQUENTIAL_LIMITS
+ void send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
+#else
void send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
+#endif // ENABLE_SEQUENTIAL_LIMITS
};
+#if ENABLE_SEQUENTIAL_LIMITS
+ // create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution
+ // the origin of the arrow is in the center of the stem cap
+ // the arrow has its axis of symmetry along the Z axis and is pointing upward
+ // used to render bed axes and sequential marker
+ GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height);
+
+ // create an arrow whose stem is a quarter of circle, with the given dimensions and resolution
+ // the origin of the arrow is in the center of the circle
+ // the arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise
+ // used to render sidebar hints for rotations
+ GLModel::InitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness);
+ // create an arrow with the given dimensions
+ // the origin of the arrow is in the center of the stem cap
+ // the arrow is contained in XY plane and has its main axis along the Y axis
+ // used to render sidebar hints for position and scale
+ GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness);
+#else
// create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution
// the origin of the arrow is in the center of the stem cap
// the arrow has its axis of symmetry along the Z axis and is pointing upward
@@ -60,6 +135,7 @@ namespace GUI {
// the origin of the arrow is in the center of the stem cap
// the arrow is contained in XY plane and has its main axis along the Y axis
GLModelInitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness);
+#endif // ENABLE_SEQUENTIAL_LIMITS
} // namespace GUI
} // namespace Slic3r
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
index 98729bd7f..07eb49379 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
@@ -63,15 +63,19 @@ void GLGizmoBase::Grabber::render(float size, const std::array<float, 4>& render
GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_current_shader();
if (shader != nullptr)
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&cube)->set_color(-1, render_color);
+#else
shader->set_uniform("uniform_color", render_color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
else
glsafe(::glColor4fv(render_color.data())); // picking
glsafe(::glPushMatrix());
- glsafe(::glTranslated(center(0), center(1), center(2)));
- glsafe(::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0));
- glsafe(::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0));
- glsafe(::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0));
+ glsafe(::glTranslated(center.x(), center.y(), center.z()));
+ glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0));
+ glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
+ glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
glsafe(::glScaled(fullsize, fullsize, fullsize));
cube.render();
glsafe(::glPopMatrix());
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
index 486d945ba..b4c0b7a52 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
@@ -150,7 +150,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
}
if (shader && ! picking)
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_vbo_cylinder)->set_color(-1 , render_color);
+#else
shader->set_uniform("uniform_color", render_color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
else // picking
glsafe(::glColor4fv(render_color.data()));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
index 84282f0a8..d92f339d7 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
@@ -80,11 +80,11 @@ void GLGizmoMove3D::on_stop_dragging()
void GLGizmoMove3D::on_update(const UpdateData& data)
{
if (m_hover_id == 0)
- m_displacement(0) = calc_projection(data);
+ m_displacement.x() = calc_projection(data);
else if (m_hover_id == 1)
- m_displacement(1) = calc_projection(data);
+ m_displacement.y() = calc_projection(data);
else if (m_hover_id == 2)
- m_displacement(2) = calc_projection(data);
+ m_displacement.z() = calc_projection(data);
}
void GLGizmoMove3D::on_render() const
@@ -98,15 +98,15 @@ void GLGizmoMove3D::on_render() const
const Vec3d& center = box.center();
// x axis
- m_grabbers[0].center = Vec3d(box.max.x() + Offset, center.y(), center.z());
+ m_grabbers[0].center = { box.max.x() + Offset, center.y(), center.z() };
m_grabbers[0].color = AXES_COLOR[0];
// y axis
- m_grabbers[1].center = Vec3d(center.x(), box.max.y() + Offset, center.z());
+ m_grabbers[1].center = { center.x(), box.max.y() + Offset, center.z() };
m_grabbers[1].color = AXES_COLOR[1];
// z axis
- m_grabbers[2].center = Vec3d(center.x(), center.y(), box.max.z() + Offset);
+ m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
m_grabbers[2].color = AXES_COLOR[2];
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
@@ -138,9 +138,15 @@ void GLGizmoMove3D::on_render() const
::glVertex3dv(m_grabbers[m_hover_id].center.data());
glsafe(::glEnd());
- // draw grabber
- float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
- m_grabbers[m_hover_id].render(true, mean_size);
+ GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
+ if (shader != nullptr) {
+ shader->start_using();
+ shader->set_uniform("emission_factor", 0.1);
+ // draw grabber
+ float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
+ m_grabbers[m_hover_id].render(true, mean_size);
+ shader->stop_using();
+ }
render_grabber_extension((Axis)m_hover_id, box, false);
}
}
@@ -202,7 +208,11 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
if (! picking) {
shader->start_using();
shader->set_uniform("emission_factor", 0.1);
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_vbo_cone)->set_color(-1, color);
+#else
shader->set_uniform("uniform_color", color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
} else
glsafe(::glColor4fv(color.data()));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
index f72ea014d..0f0c74652 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
@@ -339,7 +339,11 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
if (! picking) {
shader->start_using();
shader->set_uniform("emission_factor", 0.1);
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_cone)->set_color(-1, color);
+#else
shader->set_uniform("uniform_color", color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
} else
glsafe(::glColor4fv(color.data()));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index 88a5ba169..3fc347222 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -120,16 +120,14 @@ protected:
void on_stop_dragging() override;
void on_update(const UpdateData& data) override
{
- for (GLGizmoRotate& g : m_gizmos)
- {
+ for (GLGizmoRotate& g : m_gizmos) {
g.update(data);
}
}
void on_render() const override;
void on_render_for_picking() const override
{
- for (const GLGizmoRotate& g : m_gizmos)
- {
+ for (const GLGizmoRotate& g : m_gizmos) {
g.render_for_picking();
}
}
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
index d088b4ba3..fb1b148b4 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
@@ -1,6 +1,7 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoScale.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
+#include "slic3r/GUI/GUI_App.hpp"
#include <GL/glew.h>
@@ -75,7 +76,7 @@ bool GLGizmoScale3D::on_init()
std::string GLGizmoScale3D::on_get_name() const
{
- return (_(L("Scale")) + " [S]").ToUTF8().data();
+ return (_L("Scale") + " [S]").ToUTF8().data();
}
bool GLGizmoScale3D::on_is_activable() const
@@ -131,12 +132,10 @@ void GLGizmoScale3D::on_render() const
m_offsets_transform = Transform3d::Identity();
Vec3d angles = Vec3d::Zero();
- if (single_instance)
- {
+ if (single_instance) {
// calculate bounding box in instance local reference system
const Selection::IndicesList& idxs = selection.get_volume_idxs();
- for (unsigned int idx : idxs)
- {
+ for (unsigned int idx : idxs) {
const GLVolume* vol = selection.get_volume(idx);
m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix()));
}
@@ -150,8 +149,7 @@ void GLGizmoScale3D::on_render() const
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
m_offsets_transform = offsets_transform;
}
- else if (single_volume)
- {
+ else if (single_volume) {
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
m_box = v->bounding_box();
m_transform = v->world_matrix();
@@ -172,20 +170,20 @@ void GLGizmoScale3D::on_render() const
// x axis
m_grabbers[0].center = m_transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x;
- m_grabbers[1].center = m_transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x;
m_grabbers[0].color = (ctrl_down && (m_hover_id == 1)) ? CONSTRAINED_COLOR : AXES_COLOR[0];
+ m_grabbers[1].center = m_transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x;
m_grabbers[1].color = (ctrl_down && (m_hover_id == 0)) ? CONSTRAINED_COLOR : AXES_COLOR[0];
// y axis
m_grabbers[2].center = m_transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y;
- m_grabbers[3].center = m_transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y;
m_grabbers[2].color = (ctrl_down && (m_hover_id == 3)) ? CONSTRAINED_COLOR : AXES_COLOR[1];
+ m_grabbers[3].center = m_transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y;
m_grabbers[3].color = (ctrl_down && (m_hover_id == 2)) ? CONSTRAINED_COLOR : AXES_COLOR[1];
// z axis
m_grabbers[4].center = m_transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z;
- m_grabbers[5].center = m_transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z;
m_grabbers[4].color = (ctrl_down && (m_hover_id == 5)) ? CONSTRAINED_COLOR : AXES_COLOR[2];
+ m_grabbers[5].center = m_transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z;
m_grabbers[5].color = (ctrl_down && (m_hover_id == 4)) ? CONSTRAINED_COLOR : AXES_COLOR[2];
// uniform
@@ -234,25 +232,46 @@ void GLGizmoScale3D::on_render() const
// draw connection
glsafe(::glColor4fv(m_grabbers[0].color.data()));
render_grabbers_connection(0, 1);
- // draw grabbers
- m_grabbers[0].render(true, grabber_mean_size);
- m_grabbers[1].render(true, grabber_mean_size);
+
+ GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
+ if (shader != nullptr) {
+ shader->start_using();
+ shader->set_uniform("emission_factor", 0.1);
+ // draw grabbers
+ m_grabbers[0].render(true, grabber_mean_size);
+ m_grabbers[1].render(true, grabber_mean_size);
+ shader->stop_using();
+ }
}
else if (m_hover_id == 2 || m_hover_id == 3) {
// draw connection
glsafe(::glColor4fv(m_grabbers[2].color.data()));
render_grabbers_connection(2, 3);
- // draw grabbers
- m_grabbers[2].render(true, grabber_mean_size);
- m_grabbers[3].render(true, grabber_mean_size);
+
+ GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
+ if (shader != nullptr) {
+ shader->start_using();
+ shader->set_uniform("emission_factor", 0.1);
+ // draw grabbers
+ m_grabbers[2].render(true, grabber_mean_size);
+ m_grabbers[3].render(true, grabber_mean_size);
+ shader->stop_using();
+ }
}
else if (m_hover_id == 4 || m_hover_id == 5) {
// draw connection
glsafe(::glColor4fv(m_grabbers[4].color.data()));
render_grabbers_connection(4, 5);
- // draw grabbers
- m_grabbers[4].render(true, grabber_mean_size);
- m_grabbers[5].render(true, grabber_mean_size);
+
+ GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
+ if (shader != nullptr) {
+ shader->start_using();
+ shader->set_uniform("emission_factor", 0.1);
+ // draw grabbers
+ m_grabbers[4].render(true, grabber_mean_size);
+ m_grabbers[5].render(true, grabber_mean_size);
+ shader->stop_using();
+ }
}
else if (m_hover_id >= 6) {
// draw connection
@@ -261,9 +280,16 @@ void GLGizmoScale3D::on_render() const
render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9);
render_grabbers_connection(9, 6);
- // draw grabbers
- for (int i = 6; i < 10; ++i) {
- m_grabbers[i].render(true, grabber_mean_size);
+
+ GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
+ if (shader != nullptr) {
+ shader->start_using();
+ shader->set_uniform("emission_factor", 0.1);
+ // draw grabbers
+ for (int i = 6; i < 10; ++i) {
+ m_grabbers[i].render(true, grabber_mean_size);
+ }
+ shader->stop_using();
}
}
}
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index f0818a2d7..10da6b85c 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -166,7 +166,12 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
}
}
if (shader && ! picking) {
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_cone)->set_color(-1, render_color);
+ const_cast<GLModel*>(&m_sphere)->set_color(-1, render_color);
+#else
shader->set_uniform("uniform_color", render_color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
shader->set_uniform("emission_factor", 0.5);
}
else // picking
@@ -225,7 +230,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
render_color[2] = 0.7f;
render_color[3] = 0.7f;
if (shader) {
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_cylinder)->set_color(-1, render_color);
+#else
shader->set_uniform("uniform_color", render_color);
+#endif // ENABLE_SEQUENTIAL_LIMITS
shader->set_uniform("emission_factor", 0.5);
}
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 3aff82fb4..63aca0df2 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -2730,6 +2730,10 @@ void Plater::priv::reset()
reset_gcode_toolpaths();
gcode_result.reset();
+#if ENABLE_SEQUENTIAL_LIMITS
+ view3D->get_canvas3d()->set_sequential_print_clearance(Polygons(), false);
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
// Stop and reset the Print content.
this->background_process.reset();
model.clear_objects();
@@ -2894,12 +2898,12 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// If the update_background_process() was not called by the timer, kill the timer,
// so the update_restart_background_process() will not be called again in vain.
- this->background_process_timer.Stop();
+ background_process_timer.Stop();
// Update the "out of print bed" state of ModelInstances.
- this->update_print_volume_state();
+ update_print_volume_state();
// Apply new config to the possibly running background task.
- bool was_running = this->background_process.running();
- Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config());
+ bool was_running = background_process.running();
+ Print::ApplyStatus invalidated = background_process.apply(q->model(), wxGetApp().preset_bundle->full_config());
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
if (view3D->is_layers_editing_enabled())
@@ -2908,40 +2912,56 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
if (invalidated == Print::APPLY_STATUS_INVALIDATED) {
// Some previously calculated data on the Print was invalidated.
// Hide the slicing results, as the current slicing status is no more valid.
- this->sidebar->show_sliced_info_sizer(false);
+ sidebar->show_sliced_info_sizer(false);
// Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
// Otherwise they will be just refreshed.
- if (this->preview != nullptr) {
+ if (preview != nullptr) {
// If the preview is not visible, the following line just invalidates the preview,
// but the G-code paths or SLA preview are calculated first once the preview is made visible.
reset_gcode_toolpaths();
- this->preview->reload_print();
+ preview->reload_print();
}
// In FDM mode, we need to reload the 3D scene because of the wipe tower preview box.
// In SLA mode, we need to reload the 3D scene every time to show the support structures.
- if (this->printer_technology == ptSLA || (this->printer_technology == ptFFF && this->config->opt_bool("wipe_tower")))
+ if (printer_technology == ptSLA || (printer_technology == ptFFF && config->opt_bool("wipe_tower")))
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
}
- if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! this->background_process.empty()) {
+ if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! background_process.empty()) {
// The delayed error message is no more valid.
- this->delayed_error_message.clear();
+ delayed_error_message.clear();
// The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
std::string warning;
- std::string err = this->background_process.validate(&warning);
+ std::string err = background_process.validate(&warning);
if (err.empty()) {
notification_manager->set_all_slicing_errors_gray(true);
- if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled())
+ if (invalidated != Print::APPLY_STATUS_UNCHANGED && background_processing_enabled())
return_state |= UPDATE_BACKGROUND_PROCESS_RESTART;
// Pass a warning from validation and either show a notification,
// or hide the old one.
process_validation_warning(warning);
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (printer_technology == ptFFF) {
+ view3D->get_canvas3d()->set_sequential_print_clearance(Polygons(), false);
+ view3D->get_canvas3d()->set_as_dirty();
+ view3D->get_canvas3d()->request_extra_frame();
+ }
+#endif // ENABLE_SEQUENTIAL_LIMITS
} else {
// The print is not valid.
// Show error as notification.
notification_manager->push_slicing_error_notification(err);
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (printer_technology == ptFFF) {
+ const Print* print = background_process.fff_print();
+ Polygons polygons;
+ if (print->config().complete_objects)
+ Print::sequential_print_horizontal_clearance_valid(*print, &polygons);
+ view3D->get_canvas3d()->set_sequential_print_clearance(polygons, true);
+ }
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
} else if (! this->delayed_error_message.empty()) {
@@ -3077,8 +3097,7 @@ void Plater::priv::update_fff_scene()
if (this->preview != nullptr)
this->preview->reload_print();
// In case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth:
- view3D->reload_scene(true);
-
+ view3D->reload_scene(true);
}
void Plater::priv::update_sla_scene()
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index 479b0fa77..ca1530683 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -1818,8 +1818,31 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons
glsafe(::glEnd());
}
+#if ENABLE_SEQUENTIAL_LIMITS
+static std::array<float, 4> get_color(Axis axis)
+{
+ return { AXES_COLOR[axis][0], AXES_COLOR[axis][1], AXES_COLOR[axis][2], AXES_COLOR[axis][3] };
+};
+#endif // ENABLE_SEQUENTIAL_LIMITS
+
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const
{
+#if ENABLE_SEQUENTIAL_LIMITS
+ if (boost::ends_with(sidebar_field, "x")) {
+ glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, get_color(X));
+ m_arrow.render();
+ }
+ else if (boost::ends_with(sidebar_field, "y")) {
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, get_color(Y));
+ m_arrow.render();
+ }
+ else if (boost::ends_with(sidebar_field, "z")) {
+ glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, get_color(Z));
+ m_arrow.render();
+ }
+#else
auto set_color = [](Axis axis) {
GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader != nullptr) {
@@ -1840,10 +1863,33 @@ void Selection::render_sidebar_position_hints(const std::string& sidebar_field)
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
m_arrow.render();
}
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const
{
+#if ENABLE_SEQUENTIAL_LIMITS
+ auto render_sidebar_rotation_hint = [this]() {
+ m_curved_arrow.render();
+ glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
+ m_curved_arrow.render();
+ };
+
+ if (boost::ends_with(sidebar_field, "x")) {
+ glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
+ const_cast<GLModel*>(&m_curved_arrow)->set_color(-1, get_color(X));
+ render_sidebar_rotation_hint();
+ }
+ else if (boost::ends_with(sidebar_field, "y")) {
+ glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
+ const_cast<GLModel*>(&m_curved_arrow)->set_color(-1, get_color(Y));
+ render_sidebar_rotation_hint();
+ }
+ else if (boost::ends_with(sidebar_field, "z")) {
+ const_cast<GLModel*>(&m_curved_arrow)->set_color(-1, get_color(Z));
+ render_sidebar_rotation_hint();
+ }
+#else
auto set_color = [](Axis axis) {
GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader != nullptr) {
@@ -1870,6 +1916,7 @@ void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field)
set_color(Z);
render_sidebar_rotation_hint();
}
+#endif // ENABLE_SEQUENTIAL_LIMITS
}
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) const
@@ -1877,11 +1924,12 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con
bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) {
+#if ENABLE_SEQUENTIAL_LIMITS
+ const_cast<GLModel*>(&m_arrow)->set_color(-1, uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis));
+#endif // ENABLE_SEQUENTIAL_LIMITS
GLShaderProgram* shader = wxGetApp().get_current_shader();
- if (shader != nullptr) {
- shader->set_uniform("uniform_color", uniform_scale ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]);
+ if (shader != nullptr)
shader->set_uniform("emission_factor", 0.0);
- }
glsafe(::glTranslated(0.0, 5.0, 0.0));
m_arrow.render();