mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-14 19:31:14 +00:00
The slicing frame of a belt object started at its lowest vertex, but the belt under the leading end of an overhang lies below that, by the overhang's length times the tilt's shear. Every support generator works in layers at z >= 0, so none of them could reach it: normal supports stopped at the object's own lowest layer, and the two tree generators each carried a stack of hacks to extend themselves below it (a post-hoc copy of the lowest base area in TreeSupport, "virtual belt raft layers" in TreeSupport3D/TreeModelVolumes), sized from the pre-rotation bbox and capped at global z = 0, which is only right for the trailing half of the belt. Start the frame at the lowest belt-floor point under the footprint instead, less a 10 mm margin along the belt for the base of a support column (BeltSliceStrategy::apply_preslice_transforms and BeltTransformPipeline::compute_belt_height_and_floor agree on it). The layers between it and the first vertex come out empty, which belt slicing already tolerates, and the generators need no extension at all: - normal supports: the generator anchors its layer grid at the frame origin, so run it in the object frame and shift the global belt Z offset onto the result afterwards, as organic supports already did. With the offset on the object layers a top contact at negative z turned the intermediate-layer count negative and the generator allocated layers until the kernel killed it (any overhang in the leading half of the belt). Drop the first-layer flange expansion on a belt: the first support layer is the leading tip of the support, not a flange, and inflating it put lines in the air ahead of the belt. - classic tree: a node now keeps dropping until its whole circle is in the belt, so the branch tapers to a tip on the belt instead of stopping, a radius above it, when its centre crosses. - organic: the belt is no longer a support blocker. A blocker is a collision, and a branch descending onto one slides off it, down the tilted belt and ahead of the part; the belt is where branches end, which the per-layer m_belt_floor clipping already does. The belt brim is generated after the parallel support step instead of inside it: belt_brim_obstacles() reads every object's layers and support layers, which another object's support step rebuilds (and, now, shifts) at the same time. This is the race behind the Windows arm64 segfault in "Belt brim of each object precedes its perimeters on its own filament". Also: the belt tilt axis moves to Developer mode as its own row (a shared line is shown by its first option's mode), first_layer_plane band thickness, belt_support_floor_mode, belt_preslice_global and gcode_back_transform are retired and presumed on, the gravity arrow is a plain line along the up direction, and the "Show raw G-code (belt only)" preview toggle is gone. Regression test: "Belt supports reach the belt under a leading overhang" slices a cube with a fin whose underside is parallel to the layers, 20 mm ahead of the cube and up to 41 mm of slicing Z above the belt, for normal, organic and classic tree supports, and checks that the lowest support layer sits on the belt beneath its own lines. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
199 lines
7.2 KiB
C++
199 lines
7.2 KiB
C++
#ifndef slic3r_3DBed_hpp_
|
|
#define slic3r_3DBed_hpp_
|
|
|
|
#include "GLTexture.hpp"
|
|
#include "3DScene.hpp"
|
|
#include "GLModel.hpp"
|
|
|
|
#include "libslic3r/BuildVolume.hpp"
|
|
#include "libslic3r/ExPolygon.hpp"
|
|
|
|
#include "libslic3r/Color.hpp"
|
|
#include "libslic3r/Point.hpp"
|
|
#include <string>
|
|
#include "libslic3r/BoundingBox.hpp"
|
|
#include <tuple>
|
|
#include <array>
|
|
#include <vector>
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
class GLCanvas3D;
|
|
|
|
/*
|
|
class GeometryBuffer
|
|
{
|
|
struct Vertex
|
|
{
|
|
Vec3f position{ Vec3f::Zero() };
|
|
Vec2f tex_coords{ Vec2f::Zero() };
|
|
};
|
|
|
|
std::vector<Vertex> m_vertices;
|
|
|
|
public:
|
|
bool set_from_triangles(const std::vector<Vec2f> &triangles, float z);
|
|
bool set_from_lines(const Lines& lines, float z);
|
|
//BBS: add APi to set from 3d lines
|
|
bool set_from_3d_Lines(const Lines3& lines);
|
|
|
|
const float* get_vertices_data() const;
|
|
unsigned int get_vertices_data_size() const { return (unsigned int)m_vertices.size() * get_vertex_data_size(); }
|
|
unsigned int get_vertex_data_size() const { return (unsigned int)(5 * sizeof(float)); }
|
|
size_t get_position_offset() const { return 0; }
|
|
size_t get_tex_coords_offset() const { return (size_t)(3 * sizeof(float)); }
|
|
unsigned int get_vertices_count() const { return (unsigned int)m_vertices.size(); }
|
|
};
|
|
*/
|
|
|
|
bool init_model_from_poly(GLModel &model, const ExPolygon &poly, float z);
|
|
|
|
class Bed3D
|
|
{
|
|
public:
|
|
// ORCA make bed colors accessable for 2D bed
|
|
static ColorRGBA DEFAULT_MODEL_COLOR;
|
|
static ColorRGBA DEFAULT_MODEL_COLOR_DARK;
|
|
static ColorRGBA DEFAULT_SOLID_GRID_COLOR;
|
|
static ColorRGBA DEFAULT_TRANSPARENT_GRID_COLOR;
|
|
|
|
static ColorRGBA AXIS_X_COLOR;
|
|
static ColorRGBA AXIS_Y_COLOR;
|
|
static ColorRGBA AXIS_Z_COLOR;
|
|
|
|
static void update_render_colors();
|
|
static void load_render_colors();
|
|
|
|
class Axes
|
|
{
|
|
public:
|
|
static const float DefaultStemRadius;
|
|
static const float DefaultStemLength;
|
|
static const float DefaultTipRadius;
|
|
static const float DefaultTipLength;
|
|
|
|
private:
|
|
Vec3d m_origin{ Vec3d::Zero() };
|
|
float m_stem_length{ DefaultStemLength };
|
|
GLModel m_arrow;
|
|
|
|
public:
|
|
const Vec3d& get_origin() const { return m_origin; }
|
|
void set_origin(const Vec3d& origin) { m_origin = origin; }
|
|
void set_stem_length(float length) {
|
|
m_stem_length = length;
|
|
m_arrow.reset();
|
|
}
|
|
float get_total_length() const { return m_stem_length; } // + DefaultTipLength; } // ORCA axis without arrow
|
|
void render();
|
|
};
|
|
|
|
public:
|
|
enum class Type : unsigned char
|
|
{
|
|
// The print bed model and texture are available from some printer preset.
|
|
System,
|
|
// The print bed model is unknown, thus it is rendered procedurally.
|
|
Custom
|
|
};
|
|
|
|
private:
|
|
BuildVolume m_build_volume;
|
|
Type m_type{ Type::System };
|
|
//std::string m_texture_filename;
|
|
std::string m_model_filename;
|
|
// Print volume bounding box exteded with axes and model.
|
|
BoundingBoxf3 m_extended_bounding_box;
|
|
BoundingBoxf3 m_printable_bounding_box;
|
|
// Slightly expanded print bed polygon, for collision detection.
|
|
//Polygon m_polygon;
|
|
GLModel m_triangles;
|
|
//GLModel m_gridlines;
|
|
// GLTexture m_texture;
|
|
// temporary texture shown until the main texture has still no levels compressed
|
|
//GLTexture m_temp_texture;
|
|
GLModel m_model;
|
|
Vec3d m_model_offset{ Vec3d::Zero() };
|
|
GLModel m_gravity_arrow;
|
|
float m_gravity_arrow_length{ 0.f };
|
|
Axes m_axes;
|
|
|
|
float m_scale_factor{ 1.0f };
|
|
//BBS: add part plate related logic
|
|
Vec2d m_position{ Vec2d::Zero() };
|
|
std::vector<Vec2d> m_bed_shape;
|
|
std::vector<std::vector<Vec2d>> m_extruder_shapes;
|
|
std::vector<double> m_extruder_heights;
|
|
bool m_is_dark = false;
|
|
|
|
public:
|
|
Bed3D() = default;
|
|
~Bed3D() = default;
|
|
|
|
// Update print bed model from configuration.
|
|
// Return true if the bed shape changed, so the calee will update the UI.
|
|
//FIXME if the build volume max print height is updated, this function still returns zero
|
|
// as this class does not use it, thus there is no need to update the UI.
|
|
// BBS
|
|
bool set_shape(const Pointfs& printable_area, const double printable_height, std::vector<Pointfs> extruder_areas, std::vector<double> extruder_heights, const std::string& custom_model, bool force_as_custom = false,
|
|
const Vec2d position = Vec2d::Zero(), bool with_reset = true);
|
|
|
|
void set_position(Vec2d& position);
|
|
void set_axes_mode(bool origin);
|
|
void set_axes_origin(const Vec3d& origin) { m_axes.set_origin(origin); } // Design tab: triad at bed centre
|
|
const Vec2d& get_position() const { return m_position; }
|
|
|
|
// Build volume geometry for various collision detection tasks.
|
|
const BuildVolume& build_volume() const { return m_build_volume; }
|
|
BuildVolume& build_volume() { return m_build_volume; }
|
|
|
|
// Was the model provided, or was it generated procedurally?
|
|
Type get_type() const { return m_type; }
|
|
// Was the model generated procedurally?
|
|
bool is_custom() const { return m_type == Type::Custom; }
|
|
|
|
// get the bed shape type
|
|
BuildVolume_Type get_build_volume_type() const { return m_build_volume.type(); }
|
|
|
|
// Bounding box around the print bed, axes and model, for rendering.
|
|
const BoundingBoxf3& extended_bounding_box() const { return m_extended_bounding_box; }
|
|
const BoundingBoxf3 &printable_bounding_box() const { return m_printable_bounding_box; }
|
|
|
|
// Check against an expanded 2d bounding box.
|
|
//FIXME shall one check against the real build volume?
|
|
bool contains(const Point& point) const;
|
|
Point point_projection(const Point& point) const;
|
|
|
|
void render(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor, bool show_axes);
|
|
|
|
void on_change_color_mode(bool is_dark);
|
|
|
|
private:
|
|
//BBS: add partplate related logic
|
|
// Calculate an extended bounding box from axes and current model for visualization purposes.
|
|
BoundingBoxf3 calc_printable_bounding_box() const;
|
|
BoundingBoxf3 calc_extended_bounding_box() const;
|
|
void update_model_offset();
|
|
//BBS: with offset
|
|
void update_bed_triangles();
|
|
static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape);
|
|
void render_internal(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor,
|
|
bool show_axes);
|
|
void render_axes();
|
|
void render_system(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom);
|
|
//void render_texture(bool bottom, GLCanvas3D& canvas);
|
|
void render_model(const Transform3d& view_matrix, const Transform3d& projection_matrix);
|
|
void render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom);
|
|
void render_default(bool bottom, const Transform3d& view_matrix, const Transform3d& projection_matrix);
|
|
void render_gravity_arrow(const Transform3d& view_matrix, const Transform3d& projection_matrix);
|
|
|
|
// BBS: remove the bed picking logic
|
|
// void register_raycasters_for_picking(const GLModel::Geometry& geometry, const Transform3d& trafo);
|
|
};
|
|
|
|
} // GUI
|
|
} // Slic3r
|
|
|
|
#endif // slic3r_3DBed_hpp_
|