From 0c1655b884496858971171cac863bae822896b3c Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 14 May 2018 14:14:19 +0200 Subject: [PATCH] 3DScene::Resize() method moved to c++ --- lib/Slic3r/GUI/3DScene.pm | 105 +++++++-------- xs/src/slic3r/GUI/3DScene.cpp | 35 ++++- xs/src/slic3r/GUI/3DScene.hpp | 13 +- xs/src/slic3r/GUI/GLCanvas3D.cpp | 165 +++++++++++++++++++++++- xs/src/slic3r/GUI/GLCanvas3D.hpp | 44 ++++++- xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 45 ++++++- xs/src/slic3r/GUI/GLCanvas3DManager.hpp | 13 +- xs/xsp/GUI_3DScene.xsp | 38 ++++++ 8 files changed, 377 insertions(+), 81 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index a7de71d4d..60f119980 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -194,10 +194,6 @@ sub new { $self->background(1); $self->_quat((0, 0, 0, 1)); #============================================================================================================================== - Slic3r::GUI::_3DScene::set_camera_theta($self, 45.0); - Slic3r::GUI::_3DScene::set_camera_phi($self, 45.0); - Slic3r::GUI::_3DScene::set_camera_zoom($self, 1.0); - # $self->_stheta(45); # $self->_sphi(45); # $self->_zoom(1); @@ -210,6 +206,9 @@ sub new { # Collection of GLVolume objects $self->volumes(Slic3r::GUI::_3DScene::GLVolume::Collection->new); +#============================================================================================================================== + Slic3r::GUI::_3DScene::set_volumes($self, $self->volumes); +#============================================================================================================================== # 3D point in model space #============================================================================================================================== @@ -217,8 +216,6 @@ sub new { ## $self->_camera_type('perspective'); #============================================================================================================================== #============================================================================================================================== - Slic3r::GUI::_3DScene::set_camera_target($self, Slic3r::Pointf3->new(0,0,0)); - Slic3r::GUI::_3DScene::set_camera_distance($self, 0.0); # $self->_camera_target(Slic3r::Pointf3->new(0,0,0)); # $self->_camera_distance(0.); #============================================================================================================================== @@ -969,9 +966,13 @@ sub bed_bounding_box { sub max_bounding_box { my ($self) = @_; - my $bb = $self->bed_bounding_box; - $bb->merge($self->volumes_bounding_box); - return $bb; +#============================================================================================================================== + return Slic3r::GUI::_3DScene::get_max_bounding_box($self); + +# my $bb = $self->bed_bounding_box; +# $bb->merge($self->volumes_bounding_box); +# return $bb; +#============================================================================================================================== } # Used by ObjectCutDialog and ObjectPartsPanel to generate a rectangular ground plane @@ -1000,6 +1001,9 @@ sub set_bed_shape { my ($self, $bed_shape) = @_; $self->bed_shape($bed_shape); +#============================================================================================================================== + Slic3r::GUI::_3DScene::set_bed_shape($self, $bed_shape); +#============================================================================================================================== # triangulate bed my $expolygon = Slic3r::ExPolygon->new([ map [map scale($_), @$_], @$bed_shape ]); @@ -1246,63 +1250,48 @@ sub UseVBOs { sub Resize { my ($self, $x, $y) = @_; - - return unless $self->GetContext; -#============================================================================================================================== - Slic3r::GUI::_3DScene::set_dirty($self, 0); -# $self->_dirty(0); + #============================================================================================================================== + Slic3r::GUI::_3DScene::resize($self, $x, $y); - $self->SetCurrent($self->GetContext); - glViewport(0, 0, $x, $y); - -#============================================================================================================================== - my $zoom = Slic3r::GUI::_3DScene::get_camera_zoom($self); - $x /= $zoom; - $y /= $zoom; +# return unless $self->GetContext; +# $self->_dirty(0); +# +# $self->SetCurrent($self->GetContext); +# glViewport(0, 0, $x, $y); +# # $x /= $self->_zoom; # $y /= $self->_zoom; -#============================================================================================================================== - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); -#============================================================================================================================== - my $camera_type = Slic3r::GUI::_3DScene::get_camera_type_as_string($self); - if ($camera_type eq 'ortho') { +# +# glMatrixMode(GL_PROJECTION); +# glLoadIdentity(); # if ($self->_camera_type eq 'ortho') { -#============================================================================================================================== - #FIXME setting the size of the box 10x larger than necessary - # is only a workaround for an incorrectly set camera. - # This workaround harms Z-buffer accuracy! -# my $depth = 1.05 * $self->max_bounding_box->radius(); - my $depth = 5.0 * max(@{ $self->max_bounding_box->size }); - glOrtho( - -$x/2, $x/2, -$y/2, $y/2, - -$depth, $depth, - ); - } else { -#============================================================================================================================== - die "Invalid camera type: ", $camera_type, "\n" if ($camera_type ne 'perspective'); +# #FIXME setting the size of the box 10x larger than necessary +# # is only a workaround for an incorrectly set camera. +# # This workaround harms Z-buffer accuracy! +## my $depth = 1.05 * $self->max_bounding_box->radius(); +# my $depth = 5.0 * max(@{ $self->max_bounding_box->size }); +# glOrtho( +# -$x/2, $x/2, -$y/2, $y/2, +# -$depth, $depth, +# ); +# } else { # die "Invalid camera type: ", $self->_camera_type, "\n" if ($self->_camera_type ne 'perspective'); -#============================================================================================================================== - my $bbox_r = $self->max_bounding_box->radius(); - my $fov = PI * 45. / 180.; - my $fov_tan = tan(0.5 * $fov); - my $cam_distance = 0.5 * $bbox_r / $fov_tan; -#============================================================================================================================== - Slic3r::GUI::_3DScene::set_camera_distance($self, $cam_distance); +# my $bbox_r = $self->max_bounding_box->radius(); +# my $fov = PI * 45. / 180.; +# my $fov_tan = tan(0.5 * $fov); +# my $cam_distance = 0.5 * $bbox_r / $fov_tan; # $self->_camera_distance($cam_distance); +# my $nr = $cam_distance - $bbox_r * 1.1; +# my $fr = $cam_distance + $bbox_r * 1.1; +# $nr = 1 if ($nr < 1); +# $fr = $nr + 1 if ($fr < $nr + 1); +# my $h2 = $fov_tan * $nr; +# my $w2 = $h2 * $x / $y; +# glFrustum(-$w2, $w2, -$h2, $h2, $nr, $fr); +# } +# glMatrixMode(GL_MODELVIEW); #============================================================================================================================== - my $nr = $cam_distance - $bbox_r * 1.1; - my $fr = $cam_distance + $bbox_r * 1.1; - $nr = 1 if ($nr < 1); - $fr = $nr + 1 if ($fr < $nr + 1); - my $h2 = $fov_tan * $nr; - my $w2 = $h2 * $x / $y; - glFrustum(-$w2, $w2, -$h2, $h2, $nr, $fr); - } - - glMatrixMode(GL_MODELVIEW); } sub InitGL { diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 7603c9b84..6f485d511 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -1742,6 +1742,36 @@ void _3DScene::remove_all_canvases() s_canvas_mgr.remove_all(); } +void _3DScene::resize(wxGLCanvas* canvas, unsigned int w, unsigned int h) +{ + s_canvas_mgr.resize(canvas, w, h); +} + +bool _3DScene::is_shown_on_screen(wxGLCanvas* canvas) +{ + return s_canvas_mgr.is_shown_on_screen(canvas); +} + +GLVolumeCollection* _3DScene::get_volumes(wxGLCanvas* canvas) +{ + return s_canvas_mgr.get_volumes(canvas); +} + +void _3DScene::set_volumes(wxGLCanvas* canvas, GLVolumeCollection* volumes) +{ + s_canvas_mgr.set_volumes(canvas, volumes); +} + +void _3DScene::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape) +{ + return s_canvas_mgr.set_bed_shape(canvas, shape); +} + +BoundingBoxf3 _3DScene::get_max_bounding_box(wxGLCanvas* canvas) +{ + return s_canvas_mgr.get_max_bounding_box(canvas); +} + bool _3DScene::is_dirty(wxGLCanvas* canvas) { return s_canvas_mgr.is_dirty(canvas); @@ -1752,11 +1782,6 @@ void _3DScene::set_dirty(wxGLCanvas* canvas, bool dirty) s_canvas_mgr.set_dirty(canvas, dirty); } -bool _3DScene::is_shown_on_screen(wxGLCanvas* canvas) -{ - return s_canvas_mgr.is_shown_on_screen(canvas); -} - unsigned int _3DScene::get_camera_type(wxGLCanvas* canvas) { return s_canvas_mgr.get_camera_type(canvas); diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 618b8ec34..0e8cd2bcc 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -542,11 +542,20 @@ public: static bool remove_canvas(wxGLCanvas* canvas); static void remove_all_canvases(); - static bool is_dirty(wxGLCanvas* canvas); - static void set_dirty(wxGLCanvas* canvas, bool dirty); + static void resize(wxGLCanvas* canvas, unsigned int w, unsigned int h); static bool is_shown_on_screen(wxGLCanvas* canvas); + static GLVolumeCollection* get_volumes(wxGLCanvas* canvas); + static void set_volumes(wxGLCanvas* canvas, GLVolumeCollection* volumes); + + static void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape); + + static BoundingBoxf3 get_max_bounding_box(wxGLCanvas* canvas); + + static bool is_dirty(wxGLCanvas* canvas); + static void set_dirty(wxGLCanvas* canvas, bool dirty); + static unsigned int get_camera_type(wxGLCanvas* canvas); static void set_camera_type(wxGLCanvas* canvas, unsigned int type); static std::string get_camera_type_as_string(wxGLCanvas* canvas); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 93186a8ab..0e539aaef 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1,5 +1,7 @@ #include "GLCanvas3D.hpp" +#include "../../slic3r/GUI/3DScene.hpp" + #include #include @@ -100,10 +102,37 @@ void GLCanvas3D::Camera::set_target(const Pointf3& target) m_target = target; } +const Pointfs& GLCanvas3D::Bed::get_shape() const +{ + return m_shape; +} + +void GLCanvas3D::Bed::set_shape(const Pointfs& shape) +{ + m_shape = shape; + _calc_bounding_box(); +} + +const BoundingBoxf3& GLCanvas3D::Bed::get_bounding_box() const +{ + return m_bounding_box; +} + +void GLCanvas3D::Bed::_calc_bounding_box() +{ + m_bounding_box = BoundingBoxf3(); + for (const Pointf& p : m_shape) + { + m_bounding_box.merge(Pointf3(p.x, p.y, 0.0)); + } +} + GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context) : m_canvas(canvas) , m_context(context) + , m_volumes(nullptr) , m_dirty(true) + , m_apply_zoom_to_volumes_filter(false) { } @@ -113,6 +142,94 @@ void GLCanvas3D::set_current() m_canvas->SetCurrent(*m_context); } +bool GLCanvas3D::is_shown_on_screen() const +{ + return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; +} + +void GLCanvas3D::resize(unsigned int w, unsigned int h) +{ + if (m_context == nullptr) + return; + + set_current(); + ::glViewport(0, 0, w, h); + + ::glMatrixMode(GL_PROJECTION); + ::glLoadIdentity(); + + BoundingBoxf3 bbox = max_bounding_box(); + + switch (get_camera_type()) + { + case Camera::CT_Ortho: + { + float w2 = w; + float h2 = h; + float two_zoom = 2.0f * get_camera_zoom(); + if (two_zoom != 0.0f) + { + float inv_two_zoom = 1.0f / two_zoom; + w2 *= inv_two_zoom; + h2 *= inv_two_zoom; + } + + // FIXME: calculate a tighter value for depth will improve z-fighting + Pointf3 bb_size = bbox.size(); + float depth = 5.0f * (float)std::max(bb_size.x, std::max(bb_size.y, bb_size.z)); + ::glOrtho(-w2, w2, -h2, h2, -depth, depth); + + break; + } + case Camera::CT_Perspective: + { + float bbox_r = (float)bbox.radius(); + float fov = PI * 45.0f / 180.0f; + float fov_tan = tan(0.5f * fov); + float cam_distance = 0.5f * bbox_r / fov_tan; + set_camera_distance(cam_distance); + + float nr = cam_distance - bbox_r * 1.1f; + float fr = cam_distance + bbox_r * 1.1f; + if (nr < 1.0f) + nr = 1.0f; + + if (fr < nr + 1.0f) + fr = nr + 1.0f; + + float h2 = fov_tan * nr; + float w2 = h2 * w / h; + ::glFrustum(-w2, w2, -h2, h2, nr, fr); + + break; + } + default: + { + throw std::runtime_error("Invalid camera type."); + break; + } + } + + ::glMatrixMode(GL_MODELVIEW); + + set_dirty(false); +} + +GLVolumeCollection* GLCanvas3D::get_volumes() +{ + return m_volumes; +} + +void GLCanvas3D::set_volumes(GLVolumeCollection* volumes) +{ + m_volumes = volumes; +} + +void GLCanvas3D::set_bed_shape(const Pointfs& shape) +{ + m_bed.set_shape(shape); +} + bool GLCanvas3D::is_dirty() const { return m_dirty; @@ -123,11 +240,6 @@ void GLCanvas3D::set_dirty(bool dirty) m_dirty = dirty; } -bool GLCanvas3D::is_shown_on_screen() const -{ - return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; -} - GLCanvas3D::Camera::EType GLCanvas3D::get_camera_type() const { return m_camera.get_type(); @@ -200,5 +312,48 @@ void GLCanvas3D::on_size(wxSizeEvent& evt) set_dirty(true); } +BoundingBoxf3 GLCanvas3D::bed_bounding_box() const +{ + return m_bed.get_bounding_box(); +} + +BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const +{ + BoundingBoxf3 bb; + if (m_volumes != nullptr) + { + for (const GLVolume* volume : m_volumes->volumes) + { + if (!m_apply_zoom_to_volumes_filter || ((volume != nullptr) && volume->zoom_to_volumes)) + bb.merge(volume->transformed_bounding_box()); + } + } + return bb; +} + +BoundingBoxf3 GLCanvas3D::max_bounding_box() const +{ + BoundingBoxf3 bb = bed_bounding_box(); + bb.merge(volumes_bounding_box()); + return bb; +} + +void GLCanvas3D::_zoom_to_bed() +{ + _zoom_to_bounding_box(bed_bounding_box()); +} + +void GLCanvas3D::_zoom_to_volumes() +{ + m_apply_zoom_to_volumes_filter = true; + _zoom_to_bounding_box(volumes_bounding_box()); + m_apply_zoom_to_volumes_filter = false; +} + +void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox) +{ + // >>>>>>>>>>>>>>>>>>>> TODO <<<<<<<<<<<<<<<<<<<<<<<< +} + } // namespace GUI } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 14c1031dd..26d0949f0 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -1,13 +1,16 @@ #ifndef slic3r_GLCanvas3D_hpp_ #define slic3r_GLCanvas3D_hpp_ -#include "../../libslic3r/Point.hpp" +#include "../../libslic3r/BoundingBox.hpp" class wxGLCanvas; class wxGLContext; class wxSizeEvent; namespace Slic3r { + +class GLVolumeCollection; + namespace GUI { class GLCanvas3D @@ -55,23 +58,49 @@ public: void set_target(const Pointf3& target); }; + class Bed + { + Pointfs m_shape; + BoundingBoxf3 m_bounding_box; + + public: + const Pointfs& get_shape() const; + void set_shape(const Pointfs& shape); + + const BoundingBoxf3& get_bounding_box() const; + + private: + void _calc_bounding_box(); + }; + private: wxGLCanvas* m_canvas; wxGLContext* m_context; Camera m_camera; + Bed m_bed; + + GLVolumeCollection* m_volumes; bool m_dirty; + bool m_apply_zoom_to_volumes_filter; public: GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context); void set_current(); + bool is_shown_on_screen() const; + + void resize(unsigned int w, unsigned int h); + + GLVolumeCollection* get_volumes(); + void set_volumes(GLVolumeCollection* volumes); + + void set_bed_shape(const Pointfs& shape); + bool is_dirty() const; void set_dirty(bool dirty); - bool is_shown_on_screen() const; - Camera::EType get_camera_type() const; void set_camera_type(Camera::EType type); std::string get_camera_type_as_string() const; @@ -92,6 +121,15 @@ public: void set_camera_target(const Pointf3& target); void on_size(wxSizeEvent& evt); + + BoundingBoxf3 bed_bounding_box() const; + BoundingBoxf3 volumes_bounding_box() const; + BoundingBoxf3 max_bounding_box() const; + +private: + void _zoom_to_bed(); + void _zoom_to_volumes(); + void _zoom_to_bounding_box(const BoundingBoxf3& bbox); }; } // namespace GUI diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index 5a565be28..b9bdde161 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -146,6 +146,45 @@ bool GLCanvas3DManager::layer_editing_allowed() const return m_layer_editing.allowed; } +bool GLCanvas3DManager::is_shown_on_screen(wxGLCanvas* canvas) const +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->is_shown_on_screen() : false; +} + +void GLCanvas3DManager::resize(wxGLCanvas* canvas, unsigned int w, unsigned int h) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->resize(w, h); +} + +GLVolumeCollection* GLCanvas3DManager::get_volumes(wxGLCanvas* canvas) +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->get_volumes() : nullptr; +} + +void GLCanvas3DManager::set_volumes(wxGLCanvas* canvas, GLVolumeCollection* volumes) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->set_volumes(volumes); +} + +void GLCanvas3DManager::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->set_bed_shape(shape); +} + +BoundingBoxf3 GLCanvas3DManager::get_max_bounding_box(wxGLCanvas* canvas) +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->max_bounding_box() : BoundingBoxf3(); +} + bool GLCanvas3DManager::is_dirty(wxGLCanvas* canvas) const { CanvasesMap::const_iterator it = _get_canvas(canvas); @@ -159,12 +198,6 @@ void GLCanvas3DManager::set_dirty(wxGLCanvas* canvas, bool dirty) it->second->set_dirty(dirty); } -bool GLCanvas3DManager::is_shown_on_screen(wxGLCanvas* canvas) const -{ - CanvasesMap::const_iterator it = _get_canvas(canvas); - return (it != m_canvases.end()) ? it->second->is_shown_on_screen() : false; -} - unsigned int GLCanvas3DManager::get_camera_type(wxGLCanvas* canvas) const { CanvasesMap::const_iterator it = _get_canvas(canvas); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp index 858c2d9e7..c53d6b5d3 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -52,11 +52,20 @@ public: bool use_VBOs() const; bool layer_editing_allowed() const; + bool is_shown_on_screen(wxGLCanvas* canvas) const; + + void resize(wxGLCanvas* canvas, unsigned int w, unsigned int h); + + GLVolumeCollection* get_volumes(wxGLCanvas* canvas); + void set_volumes(wxGLCanvas* canvas, GLVolumeCollection* volumes); + + void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape); + + BoundingBoxf3 get_max_bounding_box(wxGLCanvas* canvas); + bool is_dirty(wxGLCanvas* canvas) const; void set_dirty(wxGLCanvas* canvas, bool dirty); - bool is_shown_on_screen(wxGLCanvas* canvas) const; - unsigned int get_camera_type(wxGLCanvas* canvas) const; void set_camera_type(wxGLCanvas* canvas, unsigned int type); std::string get_camera_type_as_string(wxGLCanvas* canvas) const; diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index c7933f012..7e7fbc417 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -185,6 +185,44 @@ remove_all_canvases() CODE: _3DScene::remove_all_canvases(); +void +resize(canvas, w, h) + SV *canvas; + unsigned int w; + unsigned int h; + CODE: + _3DScene::resize((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), w, h); + +GLVolumeCollection* +get_volumes(canvas) + SV *canvas; + CODE: + RETVAL = _3DScene::get_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); + OUTPUT: + RETVAL + +void +set_volumes(canvas, volumes) + SV *canvas; + GLVolumeCollection *volumes; + CODE: + _3DScene::set_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), volumes); + +void +set_bed_shape(canvas, shape) + SV *canvas; + Pointfs shape; + CODE: + _3DScene::set_bed_shape((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), shape); + +Clone +get_max_bounding_box(canvas) + SV *canvas; + CODE: + RETVAL = _3DScene::get_max_bounding_box((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); + OUTPUT: + RETVAL + bool is_dirty(canvas) SV *canvas;