mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 03:09:11 +08:00
SPE-2702: Seq arrange data for HT90, printhead model, extended delta visualization
This commit is contained in:
parent
606d3f1ef4
commit
302a662a50
@ -281,6 +281,55 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"printer_notes_regex": ".*PRINTER_MODEL_HT90.*",
|
||||||
|
"gantry_model_filename": "prusa3d_ht90_actuator.stl",
|
||||||
|
"slices": [
|
||||||
|
{
|
||||||
|
"height": "0",
|
||||||
|
"type": "convex",
|
||||||
|
"polygons": [
|
||||||
|
"-5,-5; 5,-5; 5,5; -5,5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": "1",
|
||||||
|
"type": "convex",
|
||||||
|
"polygons": [
|
||||||
|
"-33,-2; 33,-2; 33,48; -33,48",
|
||||||
|
"-46,-37; 46,-37; 46,2; -46,2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": "20",
|
||||||
|
"type": "convex",
|
||||||
|
"polygons": [
|
||||||
|
"-55,-55; 55,-55; 55,55; -55,55"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": "28",
|
||||||
|
"type": "convex",
|
||||||
|
"polygons": [
|
||||||
|
"-76,-68; 76,-68; 76,65; -76,65"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": "40",
|
||||||
|
"type": "convex",
|
||||||
|
"polygons": [
|
||||||
|
"-120,-118; 120,-118; 120,94; -120,94"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": "60",
|
||||||
|
"type": "box",
|
||||||
|
"polygons": [
|
||||||
|
"-200,-200; 200,-200; 200,200; -200,200"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
BIN
resources/data/printer_gantries/prusa3d_ht90_actuator.stl
Normal file
BIN
resources/data/printer_gantries/prusa3d_ht90_actuator.stl
Normal file
Binary file not shown.
@ -71,7 +71,7 @@ static Sequential::PrinterGeometry get_printer_geometry(const ConfigBase& config
|
|||||||
{
|
{
|
||||||
if (! printer_notes.empty()) {
|
if (! printer_notes.empty()) {
|
||||||
try {
|
try {
|
||||||
boost::nowide::ifstream in(resources_dir() + "/data/printer_gantries/geometries.txt");
|
boost::nowide::ifstream in(resources_dir() + "/data/printer_gantries/geometries.json");
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree pt;
|
||||||
boost::property_tree::read_json(in, pt);
|
boost::property_tree::read_json(in, pt);
|
||||||
for (const auto& printer : pt.get_child("printers")) {
|
for (const auto& printer : pt.get_child("printers")) {
|
||||||
|
@ -217,12 +217,13 @@ int GCodeViewer::SequentialView::ActualSpeedImguiWidget::plot(const char* label,
|
|||||||
}
|
}
|
||||||
#endif // ENABLE_ACTUAL_SPEED_DEBUG
|
#endif // ENABLE_ACTUAL_SPEED_DEBUG
|
||||||
|
|
||||||
void GCodeViewer::SequentialView::Marker::init(std::optional<std::unique_ptr<GLModel>>& model_opt)
|
void GCodeViewer::SequentialView::Marker::init(std::optional<std::unique_ptr<GLModel>>& model_opt, bool is_ht90)
|
||||||
{
|
{
|
||||||
if (! model_opt.has_value())
|
if (! model_opt.has_value())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_model.reset();
|
m_model.reset();
|
||||||
|
m_is_ht90 = is_ht90;
|
||||||
|
|
||||||
m_generic_marker = (model_opt->get() == nullptr);
|
m_generic_marker = (model_opt->get() == nullptr);
|
||||||
if (m_generic_marker)
|
if (m_generic_marker)
|
||||||
@ -233,6 +234,85 @@ void GCodeViewer::SequentialView::Marker::init(std::optional<std::unique_ptr<GLM
|
|||||||
m_model.set_color({ 1.0f, 1.0f, 1.0f, 0.5f });
|
m_model.set_color({ 1.0f, 1.0f, 1.0f, 0.5f });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This does not do any scaling!
|
||||||
|
static Transform3d align_cylinder(const Vec3d& p1, const Vec3d& p2, double r) {
|
||||||
|
Vec3d direction = p2 - p1;
|
||||||
|
Vec3d axis = direction.normalized();
|
||||||
|
Vec3d z0(0, 0, 1);
|
||||||
|
Matrix3d rotation;
|
||||||
|
if (axis.isApprox(z0))
|
||||||
|
rotation = Eigen::Matrix3d::Identity(); // Already aligned, use identity rotation
|
||||||
|
else if (axis.isApprox(-z0)) {
|
||||||
|
// 180-degree rotation around x or y (choose any perpendicular axis)
|
||||||
|
rotation = Eigen::AngleAxisd(M_PI, Vec3d(1, 0, 0)).toRotationMatrix();
|
||||||
|
} else {
|
||||||
|
Vec3d rotationAxis = z0.cross(axis);
|
||||||
|
double angle = acos(z0.dot(axis));
|
||||||
|
rotation = Eigen::AngleAxisd(angle, rotationAxis.normalized()).toRotationMatrix();
|
||||||
|
}
|
||||||
|
Transform3d transform = Transform3d::Identity();
|
||||||
|
transform.linear() = rotation;// * Geometry::scale_transform(Vec3d(2*r,2*r,length)).matrix().block<3,3>(0,0);
|
||||||
|
transform.translation() = p1;
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void render_ht90_rods(const Vec3d& pos, GLShaderProgram* shader, const Transform3d& view_matrix, const Vec3d& bed_offset, GLModel& model)
|
||||||
|
{
|
||||||
|
Vec3d start(30.06, 27.70, 35); // Position of the back-right ball bearing, on the extruder head.
|
||||||
|
Vec3d end(32.33, 212.92, 338.8); // The other ball bearing, on the printer.
|
||||||
|
double r=4.725; // Diameter of the rod.
|
||||||
|
double rods_spacing = 60.;
|
||||||
|
double height = (end-start).norm();
|
||||||
|
|
||||||
|
|
||||||
|
if (!model.is_initialized()) {
|
||||||
|
auto t0 = its_make_sphere(r, 0.5);
|
||||||
|
auto t1 = its_make_sphere(r, 0.5);
|
||||||
|
auto t2 = its_make_cylinder(r, height);
|
||||||
|
its_translate(t1, Vec3f(0., 0., height));
|
||||||
|
its_merge(t2, t0);
|
||||||
|
its_merge(t2, t1);
|
||||||
|
model.init_from(t2);
|
||||||
|
model.set_color({ 1.0f, 1.0f, 1.0f, 0.5f });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// trans transforms extruder to world coord system of the first bed
|
||||||
|
Transform3d trans = Geometry::translation_transform(pos);
|
||||||
|
|
||||||
|
Vec3d p1 = trans * start;
|
||||||
|
Vec3d p2 = end; // already in world coords
|
||||||
|
|
||||||
|
for (int j=0; j<6; ++j) {
|
||||||
|
if (j == 3) {
|
||||||
|
p1.x() = p1.x() - rods_spacing;
|
||||||
|
p2.x() = p2.x() - rods_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
p1 = trans * Geometry::rotation_transform(Vec3d(0,0,2*M_PI/3)) * trans.inverse() * p1;
|
||||||
|
p2 = Geometry::rotation_transform(Vec3d(0,0,2*M_PI/3)) * p2;
|
||||||
|
|
||||||
|
double dx = p2.x() - p1.x();
|
||||||
|
double dy = p2.y() - p1.y();
|
||||||
|
double dz = std::sqrt(height * height - dx * dx - dy * dy);
|
||||||
|
p2.z() = p1.z() + dz;
|
||||||
|
|
||||||
|
Transform3d wm = align_cylinder(p1, p2, r);
|
||||||
|
shader->set_uniform("view_model_matrix", view_matrix * wm);
|
||||||
|
shader->set_uniform("volume_world_matrix", Geometry::translation_transform(bed_offset) * wm);
|
||||||
|
model.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GCodeViewer::SequentialView::Marker::render()
|
void GCodeViewer::SequentialView::Marker::render()
|
||||||
{
|
{
|
||||||
if (!m_visible)
|
if (!m_visible)
|
||||||
@ -263,7 +343,7 @@ void GCodeViewer::SequentialView::Marker::render()
|
|||||||
BoundingBoxf box = s_multiple_beds.get_build_volume_box();
|
BoundingBoxf box = s_multiple_beds.get_build_volume_box();
|
||||||
box.translate(to_2d(bed_inst_offset));
|
box.translate(to_2d(bed_inst_offset));
|
||||||
// add a bit on both sides
|
// add a bit on both sides
|
||||||
box = box.inflated(40.0f);
|
box = box.inflated(m_is_ht90 ? 60.f : 40.f);
|
||||||
clip_planes = {{ { 1.0f, 0.0f, 0.0f, -box.min.cast<float>().x() } , { -1.0f, 0.0f, 0.0f, box.max.cast<float>().x() }}};
|
clip_planes = {{ { 1.0f, 0.0f, 0.0f, -box.min.cast<float>().x() } , { -1.0f, 0.0f, 0.0f, box.max.cast<float>().x() }}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,8 +367,12 @@ void GCodeViewer::SequentialView::Marker::render()
|
|||||||
shader->set_uniform("clipping_planes[0]", clip_planes[0]);
|
shader->set_uniform("clipping_planes[0]", clip_planes[0]);
|
||||||
shader->set_uniform("clipping_planes[1]", clip_planes[1]);
|
shader->set_uniform("clipping_planes[1]", clip_planes[1]);
|
||||||
|
|
||||||
|
shader->set_uniform("volume_world_matrix", volume_world_matrix);
|
||||||
m_model.render();
|
m_model.render();
|
||||||
|
|
||||||
|
if (m_is_ht90)
|
||||||
|
render_ht90_rods(m_world_position.cast<double>(), shader, view_matrix, bed_inst_offset, m_model_ht90_rod);
|
||||||
|
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
|
||||||
if (curr_cull_face)
|
if (curr_cull_face)
|
||||||
@ -1204,8 +1288,8 @@ void GCodeViewer::render()
|
|||||||
m_sequential_view.marker.set_z_offset(m_z_offset);
|
m_sequential_view.marker.set_z_offset(m_z_offset);
|
||||||
|
|
||||||
// Following just makes sure that the shown marker is correct.
|
// Following just makes sure that the shown marker is correct.
|
||||||
auto marker_model_opt = wxGetApp().plater()->get_current_canvas3D()->get_current_marker_model();
|
auto [marker_model_opt, is_ht90] = wxGetApp().plater()->get_current_canvas3D()->get_current_marker_model();
|
||||||
m_sequential_view.marker.init(marker_model_opt);
|
m_sequential_view.marker.init(marker_model_opt, is_ht90);
|
||||||
if (marker_model_opt.has_value())
|
if (marker_model_opt.has_value())
|
||||||
m_max_bounding_box.reset();
|
m_max_bounding_box.reset();
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ public:
|
|||||||
class Marker
|
class Marker
|
||||||
{
|
{
|
||||||
GLModel m_model;
|
GLModel m_model;
|
||||||
|
GLModel m_model_ht90_rod;
|
||||||
Vec3f m_world_position;
|
Vec3f m_world_position;
|
||||||
// For seams, the position of the marker is on the last endpoint of the toolpath containing it.
|
// For seams, the position of the marker is on the last endpoint of the toolpath containing it.
|
||||||
// This offset is used to show the correct value of tool position in the "ToolPosition" window.
|
// This offset is used to show the correct value of tool position in the "ToolPosition" window.
|
||||||
@ -128,14 +129,20 @@ public:
|
|||||||
bool m_fixed_screen_size{ false };
|
bool m_fixed_screen_size{ false };
|
||||||
float m_scale_factor{ 1.0f };
|
float m_scale_factor{ 1.0f };
|
||||||
bool m_generic_marker{ true };
|
bool m_generic_marker{ true };
|
||||||
|
bool m_is_ht90{false};
|
||||||
#if ENABLE_ACTUAL_SPEED_DEBUG
|
#if ENABLE_ACTUAL_SPEED_DEBUG
|
||||||
ActualSpeedImguiWidget m_actual_speed_imgui_widget;
|
ActualSpeedImguiWidget m_actual_speed_imgui_widget;
|
||||||
#endif // ENABLE_ACTUAL_SPEED_DEBUG
|
#endif // ENABLE_ACTUAL_SPEED_DEBUG
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init(std::optional<std::unique_ptr<GLModel>>& model_opt);
|
void init(std::optional<std::unique_ptr<GLModel>>& model_opt, bool is_ht90);
|
||||||
|
|
||||||
const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); }
|
BoundingBoxf3 get_bounding_box() const {
|
||||||
|
auto bb = m_model.get_bounding_box();
|
||||||
|
if (m_is_ht90)
|
||||||
|
bb.max.z() += scale_(400);
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
void set_world_position(const Vec3f& position) { m_world_position = position; }
|
void set_world_position(const Vec3f& position) { m_world_position = position; }
|
||||||
void set_world_offset(const Vec3f& offset) { m_world_offset = offset; }
|
void set_world_offset(const Vec3f& offset) { m_world_offset = offset; }
|
||||||
|
@ -162,9 +162,10 @@ void GLCanvas3D::select_bed(int i, bool triggered_by_user)
|
|||||||
// - nullopt = same as before
|
// - nullopt = same as before
|
||||||
// - nullptr = none available, use generic
|
// - nullptr = none available, use generic
|
||||||
// - GLModel = the model to use
|
// - GLModel = the model to use
|
||||||
std::optional<std::unique_ptr<GLModel>> GLCanvas3D::get_current_marker_model() const
|
// The other field is whether the printer is HT90.
|
||||||
|
std::pair<std::optional<std::unique_ptr<GLModel>>, bool> GLCanvas3D::get_current_marker_model() const
|
||||||
{
|
{
|
||||||
std::optional<std::unique_ptr<GLModel>> out;
|
auto out = std::make_pair<std::optional<std::unique_ptr<GLModel>>, bool>(std::nullopt, false);
|
||||||
|
|
||||||
static std::string last_printer_notes;
|
static std::string last_printer_notes;
|
||||||
static double old_r = 0.;
|
static double old_r = 0.;
|
||||||
@ -182,11 +183,13 @@ std::optional<std::unique_ptr<GLModel>> GLCanvas3D::get_current_marker_model() c
|
|||||||
old_h = h;
|
old_h = h;
|
||||||
old_seq = seq;
|
old_seq = seq;
|
||||||
|
|
||||||
out = std::make_optional(nullptr);
|
out.second = (printer_notes.find("PRINTER_MODEL_HT90") != std::string::npos);
|
||||||
|
|
||||||
|
out.first = std::make_optional(nullptr);
|
||||||
if (! seq)
|
if (! seq)
|
||||||
return out;
|
return out;
|
||||||
try {
|
try {
|
||||||
boost::nowide::ifstream in(resources_dir() + "/data/printer_gantries/geometries.txt");
|
boost::nowide::ifstream in(resources_dir() + "/data/printer_gantries/geometries.json");
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree pt;
|
||||||
boost::property_tree::read_json(in, pt);
|
boost::property_tree::read_json(in, pt);
|
||||||
for (const auto& printer : pt.get_child("printers")) {
|
for (const auto& printer : pt.get_child("printers")) {
|
||||||
@ -197,7 +200,7 @@ std::optional<std::unique_ptr<GLModel>> GLCanvas3D::get_current_marker_model() c
|
|||||||
if (boost::filesystem::exists(filename)) {
|
if (boost::filesystem::exists(filename)) {
|
||||||
std::unique_ptr<GLModel> m = std::make_unique<GLModel>();
|
std::unique_ptr<GLModel> m = std::make_unique<GLModel>();
|
||||||
if (m->init_from_file(filename))
|
if (m->init_from_file(filename))
|
||||||
out = std::make_optional(std::move(m));
|
out.first = std::make_optional(std::move(m));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -205,7 +208,7 @@ std::optional<std::unique_ptr<GLModel>> GLCanvas3D::get_current_marker_model() c
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Whatever happened, ignore it. We will return nullptr.
|
// Whatever happened, ignore it. We will return nullptr.
|
||||||
}
|
}
|
||||||
if (*out == nullptr && seq) {
|
if (*(out.first) == nullptr && seq) {
|
||||||
// Generic sequential extruder model.
|
// Generic sequential extruder model.
|
||||||
double gantry_height = 10;
|
double gantry_height = 10;
|
||||||
auto mesh = its_make_cylinder(r, h + gantry_height - 0.001);
|
auto mesh = its_make_cylinder(r, h + gantry_height - 0.001);
|
||||||
@ -215,7 +218,7 @@ std::optional<std::unique_ptr<GLModel>> GLCanvas3D::get_current_marker_model() c
|
|||||||
its_merge(mesh, mesh2);
|
its_merge(mesh, mesh2);
|
||||||
std::unique_ptr<GLModel> m = std::make_unique<GLModel>();
|
std::unique_ptr<GLModel> m = std::make_unique<GLModel>();
|
||||||
m->init_from(mesh);
|
m->init_from(mesh);
|
||||||
out = std::make_optional(std::move(m));
|
out.first = std::make_optional(std::move(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
@ -729,7 +729,7 @@ public:
|
|||||||
const libvgcode::Interval& get_gcode_view_visible_range() const { return m_gcode_viewer.get_gcode_view_visible_range(); }
|
const libvgcode::Interval& get_gcode_view_visible_range() const { return m_gcode_viewer.get_gcode_view_visible_range(); }
|
||||||
const libvgcode::PathVertex& get_gcode_vertex_at(size_t id) const { return m_gcode_viewer.get_gcode_vertex_at(id); }
|
const libvgcode::PathVertex& get_gcode_vertex_at(size_t id) const { return m_gcode_viewer.get_gcode_vertex_at(id); }
|
||||||
|
|
||||||
std::optional<std::unique_ptr<GLModel>> get_current_marker_model() const;
|
std::pair<std::optional<std::unique_ptr<GLModel>>, bool> get_current_marker_model() const;
|
||||||
|
|
||||||
void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
|
void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
|
||||||
void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1, const ModelVolume* mv = nullptr);
|
void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1, const ModelVolume* mv = nullptr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user