mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-23 00:31:11 -06:00
Handling of left hand oriented coordinate systems:
is_left_handed() method on transformations and volumes rendering of GLVolumes in left handed coordinate systems by glFrontFace(GL_CW); SLA slicing on left hand oriented instances by flipping the mesh for SLAPrintObject in X. rendering of the SLA cutting plane in left handed systems resetting the SLA clipping planes on 3D preview invalidation
This commit is contained in:
parent
9594bf43b5
commit
086f11df98
11 changed files with 80 additions and 62 deletions
|
@ -333,6 +333,13 @@ Transform3d GLVolume::world_matrix() const
|
|||
return m;
|
||||
}
|
||||
|
||||
bool GLVolume::is_left_handed() const
|
||||
{
|
||||
const Vec3d &m1 = m_instance_transformation.get_mirror();
|
||||
const Vec3d &m2 = m_volume_transformation.get_mirror();
|
||||
return m1.x() * m1.y() * m1.z() * m2.x() * m2.y() * m2.z() < 0.;
|
||||
}
|
||||
|
||||
const BoundingBoxf3& GLVolume::transformed_bounding_box() const
|
||||
{
|
||||
assert(bounding_box.defined || bounding_box.min(0) >= bounding_box.max(0) || bounding_box.min(1) >= bounding_box.max(1) || bounding_box.min(2) >= bounding_box.max(2));
|
||||
|
@ -401,6 +408,8 @@ void GLVolume::render() const
|
|||
if (!is_active)
|
||||
return;
|
||||
|
||||
if (this->is_left_handed())
|
||||
glFrontFace(GL_CW);
|
||||
glsafe(::glCullFace(GL_BACK));
|
||||
glsafe(::glPushMatrix());
|
||||
|
||||
|
@ -410,6 +419,8 @@ void GLVolume::render() const
|
|||
else
|
||||
this->indexed_vertex_array.render();
|
||||
glsafe(::glPopMatrix());
|
||||
if (this->is_left_handed())
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
|
||||
void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) const
|
||||
|
@ -420,6 +431,9 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
|
|||
if (!indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)
|
||||
return;
|
||||
|
||||
if (this->is_left_handed())
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
GLsizei n_triangles = GLsizei(std::min(indexed_vertex_array.triangle_indices_size, tverts_range.second - tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
|
@ -481,6 +495,9 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
|
|||
}
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
if (this->is_left_handed())
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
|
||||
void GLVolume::render_legacy() const
|
||||
|
@ -489,6 +506,9 @@ void GLVolume::render_legacy() const
|
|||
if (!is_active)
|
||||
return;
|
||||
|
||||
if (this->is_left_handed())
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
GLsizei n_triangles = GLsizei(std::min(indexed_vertex_array.triangle_indices_size, tverts_range.second - tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
|
@ -520,6 +540,9 @@ void GLVolume::render_legacy() const
|
|||
glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first));
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
if (this->is_left_handed())
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
|
||||
std::vector<int> GLVolumeCollection::load_object(
|
||||
|
|
|
@ -388,6 +388,7 @@ public:
|
|||
int instance_idx() const { return this->composite_id.instance_id; }
|
||||
|
||||
Transform3d world_matrix() const;
|
||||
bool is_left_handed() const;
|
||||
|
||||
const BoundingBoxf3& transformed_bounding_box() const;
|
||||
const BoundingBoxf3& transformed_convex_hull_bounding_box() const;
|
||||
|
|
|
@ -5010,24 +5010,12 @@ void GLCanvas3D::_render_sla_slices() const
|
|||
Pointf3s &top_obj_triangles = it_caps_top->second.object;
|
||||
Pointf3s &top_sup_triangles = it_caps_top->second.supports;
|
||||
|
||||
const std::vector<SLAPrintObject::Instance>& instances = obj->instances();
|
||||
struct InstanceTransform
|
||||
{
|
||||
Vec3d offset;
|
||||
float rotation;
|
||||
};
|
||||
|
||||
std::vector<InstanceTransform> instance_transforms;
|
||||
for (const SLAPrintObject::Instance& inst : instances)
|
||||
{
|
||||
instance_transforms.push_back({ to_3d(unscale(inst.shift), 0.), Geometry::rad2deg(inst.rotation) });
|
||||
}
|
||||
|
||||
if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) &&
|
||||
obj->is_step_done(slaposSliceSupports) && !obj->get_slice_index().empty())
|
||||
{
|
||||
double layer_height = print->default_object_config().layer_height.value;
|
||||
double initial_layer_height = print->material_config().initial_layer_height.value;
|
||||
bool left_handed = obj->is_left_handed();
|
||||
|
||||
coord_t key_zero = obj->get_slice_index().front().print_level();
|
||||
// Slice at the center of the slab starting at clip_min_z will be rendered for the lower plane.
|
||||
|
@ -5046,10 +5034,10 @@ void GLCanvas3D::_render_sla_slices() const
|
|||
const ExPolygons& sup_bottom = slice_low.get_slice(soSupport);
|
||||
// calculate model bottom cap
|
||||
if (bottom_obj_triangles.empty() && !obj_bottom.empty())
|
||||
bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, true);
|
||||
bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, ! left_handed);
|
||||
// calculate support bottom cap
|
||||
if (bottom_sup_triangles.empty() && !sup_bottom.empty())
|
||||
bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, true);
|
||||
bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, ! left_handed);
|
||||
}
|
||||
|
||||
if (slice_high.is_valid()) {
|
||||
|
@ -5057,49 +5045,35 @@ void GLCanvas3D::_render_sla_slices() const
|
|||
const ExPolygons& sup_top = slice_high.get_slice(soSupport);
|
||||
// calculate model top cap
|
||||
if (top_obj_triangles.empty() && !obj_top.empty())
|
||||
top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, false);
|
||||
top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, left_handed);
|
||||
// calculate support top cap
|
||||
if (top_sup_triangles.empty() && !sup_top.empty())
|
||||
top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, false);
|
||||
top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, left_handed);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty())
|
||||
{
|
||||
for (const InstanceTransform& inst : instance_transforms)
|
||||
for (const SLAPrintObject::Instance& inst : obj->instances())
|
||||
{
|
||||
::glPushMatrix();
|
||||
::glTranslated(inst.offset(0), inst.offset(1), inst.offset(2));
|
||||
::glRotatef(inst.rotation, 0.0, 0.0, 1.0);
|
||||
|
||||
::glBegin(GL_TRIANGLES);
|
||||
|
||||
::glTranslated(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0);
|
||||
::glRotatef(Geometry::rad2deg(inst.rotation), 0.0, 0.0, 1.0);
|
||||
if (obj->is_left_handed())
|
||||
// The polygons are mirrored by X.
|
||||
::glScalef(-1.0, 1.0, 1.0);
|
||||
::glColor3f(1.0f, 0.37f, 0.0f);
|
||||
|
||||
for (const Vec3d& v : bottom_obj_triangles)
|
||||
{
|
||||
::glVertex3dv((GLdouble*)v.data());
|
||||
}
|
||||
|
||||
for (const Vec3d& v : top_obj_triangles)
|
||||
{
|
||||
::glVertex3dv((GLdouble*)v.data());
|
||||
}
|
||||
|
||||
::glColor3f(1.0f, 0.0f, 0.37f);
|
||||
|
||||
for (const Vec3d& v : bottom_sup_triangles)
|
||||
{
|
||||
::glVertex3dv((GLdouble*)v.data());
|
||||
}
|
||||
|
||||
for (const Vec3d& v : top_sup_triangles)
|
||||
{
|
||||
::glVertex3dv((GLdouble*)v.data());
|
||||
}
|
||||
|
||||
::glEnd();
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)bottom_obj_triangles.front().data());
|
||||
::glDrawArrays(GL_TRIANGLES, 0, bottom_obj_triangles.size());
|
||||
::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)top_obj_triangles.front().data());
|
||||
::glDrawArrays(GL_TRIANGLES, 0, top_obj_triangles.size());
|
||||
::glColor3f(1.0f, 0.0f, 0.37f);
|
||||
::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)bottom_sup_triangles.front().data());
|
||||
::glDrawArrays(GL_TRIANGLES, 0, bottom_sup_triangles.size());
|
||||
::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)top_sup_triangles.front().data());
|
||||
::glDrawArrays(GL_TRIANGLES, 0, top_sup_triangles.size());
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -6217,6 +6191,8 @@ void GLCanvas3D::_load_shells_fff()
|
|||
|
||||
void GLCanvas3D::_load_shells_sla()
|
||||
{
|
||||
//FIXME use reload_scene
|
||||
#if 1
|
||||
const SLAPrint* print = this->sla_print();
|
||||
if (print->objects().empty())
|
||||
// nothing to render, return
|
||||
|
@ -6240,9 +6216,7 @@ void GLCanvas3D::_load_shells_sla()
|
|||
|
||||
m_volumes.load_object(model_obj, obj_idx, instance_idxs, "object", m_use_VBOs && m_initialized);
|
||||
|
||||
const std::vector<SLAPrintObject::Instance>& instances = obj->instances();
|
||||
|
||||
for (const SLAPrintObject::Instance& instance : instances)
|
||||
for (const SLAPrintObject::Instance& instance : obj->instances())
|
||||
{
|
||||
Vec3d offset = unscale(instance.shift(0), instance.shift(1), 0);
|
||||
Vec3d rotation(0.0, 0.0, (double)instance.rotation);
|
||||
|
@ -6265,6 +6239,7 @@ void GLCanvas3D::_load_shells_sla()
|
|||
v.composite_id.volume_id = -1;
|
||||
v.set_instance_offset(offset);
|
||||
v.set_instance_rotation(rotation);
|
||||
v.set_instance_mirror(X, obj->is_left_handed() ? -1. : 1.);
|
||||
}
|
||||
|
||||
// add pad
|
||||
|
@ -6283,6 +6258,7 @@ void GLCanvas3D::_load_shells_sla()
|
|||
v.composite_id.volume_id = -1;
|
||||
v.set_instance_offset(offset);
|
||||
v.set_instance_rotation(rotation);
|
||||
v.set_instance_mirror(X, obj->is_left_handed() ? -1. : 1.);
|
||||
}
|
||||
|
||||
// finalize volumes and sends geometry to gpu
|
||||
|
@ -6305,6 +6281,9 @@ void GLCanvas3D::_load_shells_sla()
|
|||
}
|
||||
|
||||
update_volumes_colors_by_extruder();
|
||||
#else
|
||||
this->reload_scene(true, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data)
|
||||
|
|
|
@ -634,6 +634,7 @@ public:
|
|||
m_sla_caps[id].reset();
|
||||
}
|
||||
}
|
||||
void reset_clipping_planes_cache() { m_sla_caps[0].triangles.clear(); m_sla_caps[1].triangles.clear(); }
|
||||
void set_use_clipping_planes(bool use) { m_use_clipping_planes = use; }
|
||||
|
||||
void set_color_by(const std::string& value);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
View3D::View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
|
||||
View3D::View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
|
||||
: m_canvas_widget(nullptr)
|
||||
, m_canvas(nullptr)
|
||||
{
|
||||
|
@ -155,7 +155,9 @@ void View3D::render()
|
|||
m_canvas->set_as_dirty();
|
||||
}
|
||||
|
||||
Preview::Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
|
||||
Preview::Preview(
|
||||
wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
|
||||
: m_canvas_widget(nullptr)
|
||||
, m_canvas(nullptr)
|
||||
, m_double_slider_sizer(nullptr)
|
||||
|
@ -179,14 +181,14 @@ Preview::Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_t
|
|||
, m_volumes_cleanup_required(false)
|
||||
#endif // __linux__
|
||||
{
|
||||
if (init(parent, bed, camera, view_toolbar))
|
||||
if (init(parent, bed, camera, view_toolbar, model))
|
||||
{
|
||||
show_hide_ui_elements("none");
|
||||
load_print();
|
||||
}
|
||||
}
|
||||
|
||||
bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
|
||||
bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model)
|
||||
{
|
||||
if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */))
|
||||
return false;
|
||||
|
@ -196,6 +198,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view
|
|||
m_canvas = _3DScene::get_canvas(this->m_canvas_widget);
|
||||
m_canvas->allow_multisample(GLCanvas3DManager::can_multisample());
|
||||
m_canvas->set_config(m_config);
|
||||
m_canvas->set_model(model);
|
||||
m_canvas->set_process(m_process);
|
||||
m_canvas->enable_legend_texture(true);
|
||||
m_canvas->enable_dynamic_background(true);
|
||||
|
@ -781,6 +784,8 @@ void Preview::load_print_as_sla()
|
|||
}
|
||||
sort_remove_duplicates(zs);
|
||||
|
||||
m_canvas->reset_clipping_planes_cache();
|
||||
|
||||
n_layers = (unsigned int)zs.size();
|
||||
if (n_layers == 0)
|
||||
{
|
||||
|
|
|
@ -102,7 +102,8 @@ class Preview : public wxPanel
|
|||
PrusaDoubleSlider* m_slider {nullptr};
|
||||
|
||||
public:
|
||||
Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = [](){});
|
||||
Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = [](){});
|
||||
virtual ~Preview();
|
||||
|
||||
wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; }
|
||||
|
@ -120,7 +121,7 @@ public:
|
|||
void refresh_print();
|
||||
|
||||
private:
|
||||
bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar);
|
||||
bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model);
|
||||
|
||||
void bind_event_handlers();
|
||||
void unbind_event_handlers();
|
||||
|
|
|
@ -1350,7 +1350,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
this->q->Bind(EVT_SLICING_UPDATE, &priv::on_slicing_update, this);
|
||||
|
||||
view3D = new View3D(q, bed, camera, view_toolbar, &model, config, &background_process);
|
||||
preview = new Preview(q, bed, camera, view_toolbar, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); });
|
||||
preview = new Preview(q, bed, camera, view_toolbar, &model, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); });
|
||||
|
||||
panels.push_back(view3D);
|
||||
panels.push_back(preview);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue