mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Merge branch 'tm_opencsg' into lm_tm_hollowing
This commit is contained in:
		
						commit
						39fbb31db2
					
				
					 5 changed files with 245 additions and 214 deletions
				
			
		|  | @ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) | ||||||
| 
 | 
 | ||||||
| project(OpenCSG-example) | project(OpenCSG-example) | ||||||
| 
 | 
 | ||||||
| add_executable(opencsg_example main.cpp  GLScene.hpp GLScene.cpp Canvas.hpp  | add_executable(opencsg_example main.cpp  GLScene.hpp GLScene.cpp  | ||||||
|     ${CMAKE_CURRENT_SOURCE_DIR}/../../src/slic3r/GUI/ProgressStatusBar.cpp |     ${CMAKE_CURRENT_SOURCE_DIR}/../../src/slic3r/GUI/ProgressStatusBar.cpp | ||||||
|     ${CMAKE_CURRENT_SOURCE_DIR}/../../src/slic3r/GUI/I18N.hpp |     ${CMAKE_CURRENT_SOURCE_DIR}/../../src/slic3r/GUI/I18N.hpp | ||||||
|     ${CMAKE_CURRENT_SOURCE_DIR}/../../src/slic3r/GUI/I18N.cpp) |     ${CMAKE_CURRENT_SOURCE_DIR}/../../src/slic3r/GUI/I18N.cpp) | ||||||
|  |  | ||||||
|  | @ -1,100 +0,0 @@ | ||||||
| #ifndef CANVAS_HPP |  | ||||||
| #define CANVAS_HPP |  | ||||||
| 
 |  | ||||||
| #include <memory> |  | ||||||
| 
 |  | ||||||
| // For compilers that support precompilation, includes "wx/wx.h".
 |  | ||||||
| #include <wx/wxprec.h> |  | ||||||
| #ifndef WX_PRECOMP |  | ||||||
| #include <wx/wx.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include <wx/glcanvas.h> |  | ||||||
| #include <wx/msgdlg.h> |  | ||||||
| 
 |  | ||||||
| #include "GLScene.hpp" |  | ||||||
| 
 |  | ||||||
| namespace Slic3r { namespace GL { |  | ||||||
| 
 |  | ||||||
| class Canvas: public wxGLCanvas, public Slic3r::GL::Display |  | ||||||
| { |  | ||||||
|     std::unique_ptr<wxGLContext> m_context; |  | ||||||
| public: |  | ||||||
|      |  | ||||||
|     void set_active(long w, long h) override |  | ||||||
|     { |  | ||||||
|         SetCurrent(*m_context); |  | ||||||
|         Slic3r::GL::Display::set_active(w, h); |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     void swap_buffers() override { SwapBuffers(); } |  | ||||||
|          |  | ||||||
|     template<class...Args> |  | ||||||
|     Canvas(Args &&...args): wxGLCanvas(std::forward<Args>(args)...) |  | ||||||
|     { |  | ||||||
|         auto ctx = new wxGLContext(this); |  | ||||||
|         if (!ctx || !ctx->IsOK()) { |  | ||||||
|             wxMessageBox("Could not create OpenGL context.", "Error", |  | ||||||
|                          wxOK | wxICON_ERROR); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         m_context.reset(ctx); |  | ||||||
|          |  | ||||||
|         Bind( |  | ||||||
|             wxEVT_MOUSEWHEEL, |  | ||||||
|             [this](wxMouseEvent &evt) { |  | ||||||
|                 on_scroll(evt.GetWheelRotation(), evt.GetWheelDelta(), |  | ||||||
|                           evt.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL ? |  | ||||||
|                               Slic3r::GL::MouseInput::waVertical : |  | ||||||
|                               Slic3r::GL::MouseInput::waHorizontal); |  | ||||||
|             }, |  | ||||||
|             GetId()); |  | ||||||
|          |  | ||||||
|         Bind( |  | ||||||
|             wxEVT_MOTION, |  | ||||||
|             [this](wxMouseEvent &evt) { |  | ||||||
|                 on_moved_to(evt.GetPosition().x, evt.GetPosition().y); |  | ||||||
|             }, |  | ||||||
|             GetId()); |  | ||||||
|          |  | ||||||
|         Bind( |  | ||||||
|             wxEVT_RIGHT_DOWN, |  | ||||||
|             [this](wxMouseEvent & /*evt*/) { on_right_click_down(); }, |  | ||||||
|             GetId()); |  | ||||||
|          |  | ||||||
|         Bind( |  | ||||||
|             wxEVT_RIGHT_UP, |  | ||||||
|             [this](wxMouseEvent & /*evt*/) { on_right_click_up(); }, |  | ||||||
|             GetId()); |  | ||||||
|          |  | ||||||
|         Bind( |  | ||||||
|             wxEVT_LEFT_DOWN, |  | ||||||
|             [this](wxMouseEvent & /*evt*/) { on_left_click_down(); }, |  | ||||||
|             GetId()); |  | ||||||
|          |  | ||||||
|         Bind( |  | ||||||
|             wxEVT_LEFT_UP, |  | ||||||
|             [this](wxMouseEvent & /*evt*/) { on_left_click_up(); }, |  | ||||||
|             GetId()); |  | ||||||
|          |  | ||||||
|         Bind(wxEVT_PAINT, [this](wxPaintEvent &) { |  | ||||||
|             // This is required even though dc is not used otherwise.
 |  | ||||||
|             wxPaintDC dc(this); |  | ||||||
|              |  | ||||||
|             // Set the OpenGL viewport according to the client size of this
 |  | ||||||
|             // canvas. This is done here rather than in a wxSizeEvent handler
 |  | ||||||
|             // because our OpenGL rendering context (and thus viewport setting) is
 |  | ||||||
|             // used with multiple canvases: If we updated the viewport in the
 |  | ||||||
|             // wxSizeEvent handler, changing the size of one canvas causes a
 |  | ||||||
|             // viewport setting that is wrong when next another canvas is
 |  | ||||||
|             // repainted.
 |  | ||||||
|             const wxSize ClientSize = GetClientSize(); |  | ||||||
|             repaint(ClientSize.x, ClientSize.y); |  | ||||||
|         }, GetId()); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| }} // namespace Slic3r::GL
 |  | ||||||
| 
 |  | ||||||
| #endif // CANVAS_HPP
 |  | ||||||
|  | @ -133,7 +133,7 @@ void Scene::set_print(uqptr<SLAPrint> &&print) | ||||||
|     m_print = std::move(print); |     m_print = std::move(print); | ||||||
|          |          | ||||||
|     // Notify displays
 |     // Notify displays
 | ||||||
|     call(&Display::on_scene_updated, m_displays); |     call(&Listener::on_scene_updated, m_listeners, *this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BoundingBoxf3 Scene::get_bounding_box() const | BoundingBoxf3 Scene::get_bounding_box() const | ||||||
|  | @ -383,13 +383,18 @@ void Display::set_active(long width, long height) | ||||||
|     m_camera->set_screen(width, height); |     m_camera->set_screen(width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::repaint(long width, long height) | void Display::set_screen_size(long width, long height) | ||||||
| { | { | ||||||
|     if (m_size.x() != width || m_size.y() != height) |     if (m_size.x() != width || m_size.y() != height) | ||||||
|         m_camera->set_screen(width, height); |         m_camera->set_screen(width, height); | ||||||
|      |      | ||||||
|     m_size = {width, height}; |     m_size = {width, height}; | ||||||
|      |      | ||||||
|  |     repaint(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Display::repaint() | ||||||
|  | { | ||||||
|     clear_screen(); |     clear_screen(); | ||||||
|      |      | ||||||
|     m_camera->view(); |     m_camera->view(); | ||||||
|  | @ -400,23 +405,34 @@ void Display::repaint(long width, long height) | ||||||
|     swap_buffers(); |     swap_buffers(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::on_scroll(long v, long d, MouseInput::WheelAxis wa) | void Controller::on_scene_updated(const Scene &scene) | ||||||
|  | { | ||||||
|  |     const SLAPrint *print = scene.get_print(); | ||||||
|  |     if (!print) return; | ||||||
|  |      | ||||||
|  |     auto bb = scene.get_bounding_box(); | ||||||
|  |     double d = std::max(std::max(bb.size().x(), bb.size().y()), bb.size().z()); | ||||||
|  |     m_wheel_pos = long(2 * d); | ||||||
|  |      | ||||||
|  |     call_cameras(&Camera::set_zoom, m_wheel_pos); | ||||||
|  |     call(&Display::on_scene_updated, m_displays, scene);     | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Controller::on_scroll(long v, long d, MouseInput::WheelAxis /*wa*/) | ||||||
| { | { | ||||||
|     m_wheel_pos += v / d; |     m_wheel_pos += v / d; | ||||||
|      |      | ||||||
|     m_camera->set_zoom(m_wheel_pos); |     call_cameras(&Camera::set_zoom, m_wheel_pos); | ||||||
|      |     call(&Display::repaint, m_displays); | ||||||
|     m_scene->on_scroll(v, d, wa); |  | ||||||
|      |  | ||||||
|     repaint(m_size.x(), m_size.y()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::on_moved_to(long x, long y) | void Controller::on_moved_to(long x, long y) | ||||||
| { | { | ||||||
|     if (m_left_btn) { |     if (m_left_btn) { | ||||||
|         m_camera->rotate((Vec2i{x, y} - m_mouse_pos).cast<float>()); |         call_cameras(&Camera::rotate, (Vec2i{x, y} - m_mouse_pos).cast<float>()); | ||||||
|         repaint(); |         call(&Display::repaint, m_displays); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     m_mouse_pos = {x, y}; |     m_mouse_pos = {x, y}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -424,30 +440,27 @@ void Display::apply_csgsettings(const CSGSettings &settings) | ||||||
| { | { | ||||||
|     using namespace OpenCSG; |     using namespace OpenCSG; | ||||||
|      |      | ||||||
|     bool update = m_csgsettings.get_convexity() != settings.get_convexity(); |     bool needupdate = m_csgsettings.get_convexity() != settings.get_convexity(); | ||||||
|      |      | ||||||
|     m_csgsettings = settings; |     m_csgsettings = settings; | ||||||
|     setOption(AlgorithmSetting, m_csgsettings.get_algo()); |     setOption(AlgorithmSetting, m_csgsettings.get_algo()); | ||||||
|     setOption(DepthComplexitySetting, m_csgsettings.get_depth_algo()); |     setOption(DepthComplexitySetting, m_csgsettings.get_depth_algo()); | ||||||
|     setOption(DepthBoundsOptimization, m_csgsettings.get_optimization()); |     setOption(DepthBoundsOptimization, m_csgsettings.get_optimization()); | ||||||
|      |      | ||||||
|     if (update) on_scene_updated(); |     if (needupdate) { | ||||||
|  |         for (OpenCSG::Primitive * p : m_scene_cache.primitives_csg) | ||||||
|  |             if (p->getConvexity() > 1) | ||||||
|  |                 p->setConvexity(m_csgsettings.get_convexity()); | ||||||
|  |     } | ||||||
|      |      | ||||||
|     repaint(); |     repaint(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::on_scene_updated() | void Display::on_scene_updated(const Scene &scene) | ||||||
| { | { | ||||||
|     const SLAPrint *print = m_scene->get_print(); |     const SLAPrint *print = scene.get_print(); | ||||||
|     if (!print) return; |     if (!print) return; | ||||||
|      |      | ||||||
|     { |  | ||||||
|     auto bb = m_scene->get_bounding_box(); |  | ||||||
|     double d = std::max(std::max(bb.size().x(), bb.size().y()), bb.size().z()); |  | ||||||
|     m_wheel_pos = long(2 * d); |  | ||||||
|     m_camera->set_zoom(m_wheel_pos); |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     m_scene_cache.clear(); |     m_scene_cache.clear(); | ||||||
|      |      | ||||||
|     for (const SLAPrintObject *po : print->objects()) { |     for (const SLAPrintObject *po : print->objects()) { | ||||||
|  | @ -499,12 +512,6 @@ void Display::on_scene_updated() | ||||||
|     repaint(); |     repaint(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::set_scene(shptr<Scene> scene) |  | ||||||
| { |  | ||||||
|     m_scene = scene; |  | ||||||
|     m_scene->add_display(shared_from_this()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Camera::view() | void Camera::view() | ||||||
| { | { | ||||||
|     glMatrixMode(GL_MODELVIEW); |     glMatrixMode(GL_MODELVIEW); | ||||||
|  |  | ||||||
|  | @ -21,16 +21,16 @@ template<class T> using uqptr = std::unique_ptr<T>; | ||||||
| template<class T> using wkptr = std::weak_ptr<T>; | template<class T> using wkptr = std::weak_ptr<T>; | ||||||
| 
 | 
 | ||||||
| template<class T, class A = std::allocator<T>> | template<class T, class A = std::allocator<T>> | ||||||
| using Collection = std::vector<T, A>; | using vector = std::vector<T, A>; | ||||||
| 
 | 
 | ||||||
| template<class L> void cleanup(Collection<std::weak_ptr<L>> &listeners) { | template<class L> void cleanup(vector<std::weak_ptr<L>> &listeners) { | ||||||
|     auto it = std::remove_if(listeners.begin(), listeners.end(), |     auto it = std::remove_if(listeners.begin(), listeners.end(), | ||||||
|                              [](auto &l) { return !l.lock(); }); |                              [](auto &l) { return !l.lock(); }); | ||||||
|     listeners.erase(it, listeners.end()); |     listeners.erase(it, listeners.end()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<class F, class L, class...Args> | template<class F, class L, class...Args> | ||||||
| void call(F &&f, Collection<std::weak_ptr<L>> &listeners, Args&&... args) { | void call(F &&f, vector<std::weak_ptr<L>> &listeners, Args&&... args) { | ||||||
|     for (auto &l : listeners) |     for (auto &l : listeners) | ||||||
|         if (auto p = l.lock()) ((p.get())->*f)(std::forward<Args>(args)...); |         if (auto p = l.lock()) ((p.get())->*f)(std::forward<Args>(args)...); | ||||||
| } | } | ||||||
|  | @ -57,7 +57,7 @@ public: | ||||||
|     }; |     }; | ||||||
|      |      | ||||||
| private: | private: | ||||||
|     Collection<wkptr<Listener>> m_listeners; |     vector<wkptr<Listener>> m_listeners; | ||||||
|          |          | ||||||
| public: | public: | ||||||
|     virtual ~MouseInput() = default; |     virtual ~MouseInput() = default; | ||||||
|  | @ -104,9 +104,9 @@ public: | ||||||
| 
 | 
 | ||||||
|     // Vertices and their normals, interleaved to be used by void
 |     // Vertices and their normals, interleaved to be used by void
 | ||||||
|     // glInterleavedArrays(GL_N3F_V3F, 0, x)
 |     // glInterleavedArrays(GL_N3F_V3F, 0, x)
 | ||||||
|     Collection<float> vertices_and_normals_interleaved; |     vector<float> vertices_and_normals_interleaved; | ||||||
|     Collection<int>   triangle_indices; |     vector<int>   triangle_indices; | ||||||
|     Collection<int>   quad_indices; |     vector<int>   quad_indices; | ||||||
| 
 | 
 | ||||||
|     // When the geometry data is loaded into the graphics card as Vertex
 |     // When the geometry data is loaded into the graphics card as Vertex
 | ||||||
|     // Buffer Objects, the above mentioned std::vectors are cleared and the
 |     // Buffer Objects, the above mentioned std::vectors are cleared and the
 | ||||||
|  | @ -223,8 +223,8 @@ public: | ||||||
|      |      | ||||||
| private: | private: | ||||||
|     OpenCSG::Algorithm m_csgalg = OpenCSG::Algorithm::Automatic; |     OpenCSG::Algorithm m_csgalg = OpenCSG::Algorithm::Automatic; | ||||||
|     OpenCSG::DepthComplexityAlgorithm m_depth_algo = OpenCSG::DepthComplexityAlgorithm::NoDepthComplexitySampling; |     OpenCSG::DepthComplexityAlgorithm m_depth_algo = OpenCSG::NoDepthComplexitySampling; | ||||||
|     OpenCSG::Optimization m_optim = OpenCSG::Optimization::OptimizationDefault; |     OpenCSG::Optimization m_optim = OpenCSG::OptimizationDefault; | ||||||
|     bool m_enable = true; |     bool m_enable = true; | ||||||
|     unsigned int m_convexity = DEFAULT_CONVEXITY; |     unsigned int m_convexity = DEFAULT_CONVEXITY; | ||||||
|      |      | ||||||
|  | @ -244,25 +244,48 @@ public: | ||||||
|     unsigned get_convexity() const { return m_convexity; } |     unsigned get_convexity() const { return m_convexity; } | ||||||
|     void set_convexity(unsigned c) { m_convexity = c; } |     void set_convexity(unsigned c) { m_convexity = c; } | ||||||
| }; | }; | ||||||
|         |        | ||||||
| class Display : public std::enable_shared_from_this<Display>, | class Scene | ||||||
|                 public MouseInput::Listener | { | ||||||
|  |     uqptr<SLAPrint> m_print; | ||||||
|  | public: | ||||||
|  |      | ||||||
|  |     class Listener { | ||||||
|  |     public: | ||||||
|  |         virtual ~Listener() = default; | ||||||
|  |         virtual void on_scene_updated(const Scene &scene) = 0; | ||||||
|  |     }; | ||||||
|  |      | ||||||
|  |     Scene(); | ||||||
|  |     ~Scene(); | ||||||
|  |      | ||||||
|  |     void set_print(uqptr<SLAPrint> &&print); | ||||||
|  |     const SLAPrint * get_print() const { return m_print.get(); } | ||||||
|  |      | ||||||
|  |     BoundingBoxf3 get_bounding_box() const; | ||||||
|  |      | ||||||
|  |     void add_listener(shptr<Listener> listener) | ||||||
|  |     { | ||||||
|  |         m_listeners.emplace_back(listener); | ||||||
|  |         cleanup(m_listeners); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | private: | ||||||
|  |     vector<wkptr<Listener>> m_listeners; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class Display : public Scene::Listener | ||||||
| { | { | ||||||
| protected: | protected: | ||||||
|     shptr<Scene> m_scene; |  | ||||||
|     long m_wheel_pos = 0; |  | ||||||
|     Vec2i m_mouse_pos, m_mouse_pos_rprev, m_mouse_pos_lprev; |  | ||||||
|     Vec2i m_size; |     Vec2i m_size; | ||||||
|     bool m_initialized = false, m_left_btn = false, m_right_btn = false; |     bool m_initialized = false; | ||||||
|      |      | ||||||
|     CSGSettings m_csgsettings; |     CSGSettings m_csgsettings; | ||||||
|      |      | ||||||
|     shptr<Camera> m_camera; |  | ||||||
|      |  | ||||||
|     struct SceneCache { |     struct SceneCache { | ||||||
|         Collection<shptr<Primitive>> primitives; |         vector<shptr<Primitive>> primitives; | ||||||
|         Collection<Primitive *> primitives_free; |         vector<Primitive *> primitives_free; | ||||||
|         Collection<OpenCSG::Primitive *> primitives_csg; |         vector<OpenCSG::Primitive *> primitives_csg; | ||||||
|          |          | ||||||
|         void clear(); |         void clear(); | ||||||
|          |          | ||||||
|  | @ -272,64 +295,80 @@ protected: | ||||||
|                                   unsigned            covexity); |                                   unsigned            covexity); | ||||||
|     } m_scene_cache; |     } m_scene_cache; | ||||||
|      |      | ||||||
|  |     shptr<Camera>  m_camera; | ||||||
|  |      | ||||||
| public: | public: | ||||||
|     Display(shptr<Scene> scene = nullptr, shptr<Camera> camera = nullptr) |      | ||||||
|         : m_scene(scene) |     explicit Display(shptr<Camera> camera = nullptr) | ||||||
|         , m_camera(camera ? camera : std::make_shared<PerspectiveCamera>()) |         : m_camera(camera ? camera : std::make_shared<PerspectiveCamera>()) | ||||||
|     {} |     {} | ||||||
| 
 |      | ||||||
|  |     Camera * camera() { return m_camera.get(); } | ||||||
|  |      | ||||||
|     virtual void swap_buffers() = 0; |     virtual void swap_buffers() = 0; | ||||||
|      |  | ||||||
|     virtual void set_active(long width, long height); |     virtual void set_active(long width, long height); | ||||||
|  |     virtual void set_screen_size(long width, long height); | ||||||
|  |     Vec2i get_screen_size() const { return m_size; } | ||||||
|      |      | ||||||
|     virtual void repaint(long width, long height);     |     virtual void repaint(); | ||||||
|     void repaint() { repaint(m_size.x(), m_size.y()); } |  | ||||||
|      |  | ||||||
|     void set_scene(shptr<Scene> scene); |  | ||||||
|     shptr<Scene> get_scene() { return m_scene; } |  | ||||||
|      |      | ||||||
|     bool is_initialized() const { return m_initialized; } |     bool is_initialized() const { return m_initialized; } | ||||||
|      |      | ||||||
|     void on_scroll(long v, long d, MouseInput::WheelAxis wa) override; |  | ||||||
|     void on_moved_to(long x, long y) override; |  | ||||||
|     void on_left_click_down() override { m_left_btn = true; } |  | ||||||
|     void on_left_click_up() override { m_left_btn = false;  } |  | ||||||
|     void on_right_click_down() override { m_right_btn = true;  } |  | ||||||
|     void on_right_click_up() override { m_right_btn = false; } |  | ||||||
|      |  | ||||||
|     void move_clip_plane(double z) { m_camera->set_clip_z(z); } |  | ||||||
|      |  | ||||||
|     const CSGSettings & get_csgsettings() const { return m_csgsettings; } |     const CSGSettings & get_csgsettings() const { return m_csgsettings; } | ||||||
|     void apply_csgsettings(const CSGSettings &settings); |     void apply_csgsettings(const CSGSettings &settings); | ||||||
|      |      | ||||||
|     virtual void on_scene_updated(); |     void on_scene_updated(const Scene &scene) override; | ||||||
|  |      | ||||||
|     virtual void clear_screen(); |     virtual void clear_screen(); | ||||||
|     virtual void render_scene(); |     virtual void render_scene(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Scene: public MouseInput::Listener | class Controller : public std::enable_shared_from_this<Controller>, | ||||||
|  |                    public MouseInput::Listener, | ||||||
|  |                    public Scene::Listener | ||||||
| { | { | ||||||
|     uqptr<SLAPrint> m_print; |     long m_wheel_pos = 0; | ||||||
|  |     Vec2i m_mouse_pos, m_mouse_pos_rprev, m_mouse_pos_lprev; | ||||||
|  |     bool m_left_btn = false, m_right_btn = false; | ||||||
|  | 
 | ||||||
|  |     shptr<Scene>               m_scene; | ||||||
|  |     vector<wkptr<Display>> m_displays; | ||||||
|  |      | ||||||
|  |     // Call a method of Camera on all the cameras of the attached displays
 | ||||||
|  |     template<class F, class...Args> | ||||||
|  |     void call_cameras(F &&f, Args&&... args) { | ||||||
|  |         for (wkptr<Display> &l : m_displays) | ||||||
|  |             if (auto disp = l.lock()) if (disp->camera()) | ||||||
|  |                 (disp->camera()->*f)(std::forward<Args>(args)...); | ||||||
|  |     } | ||||||
|  |      | ||||||
| public: | public: | ||||||
|      |      | ||||||
|     Scene(); |     void set_scene(shptr<Scene> scene) | ||||||
|     ~Scene(); |     { | ||||||
|  |         m_scene = scene; | ||||||
|  |         m_scene->add_listener(shared_from_this()); | ||||||
|  |     } | ||||||
|      |      | ||||||
|  |     const Scene * get_scene() const { return m_scene.get(); } | ||||||
|  | 
 | ||||||
|     void add_display(shptr<Display> disp) |     void add_display(shptr<Display> disp) | ||||||
|     { |     { | ||||||
|         m_displays.emplace_back(disp); |         m_displays.emplace_back(disp); | ||||||
|         cleanup(m_displays); |         cleanup(m_displays); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     void set_print(uqptr<SLAPrint> &&print); |     void on_scene_updated(const Scene &scene) override; | ||||||
|     const SLAPrint * get_print() const { return m_print.get(); } |  | ||||||
|      |      | ||||||
|     BoundingBoxf3 get_bounding_box() const; |     void on_left_click_down() override { m_left_btn = true; } | ||||||
|  |     void on_left_click_up() override { m_left_btn = false;  } | ||||||
|  |     void on_right_click_down() override { m_right_btn = true;  } | ||||||
|  |     void on_right_click_up() override { m_right_btn = false; } | ||||||
|  |      | ||||||
|  |     void on_scroll(long v, long d, MouseInput::WheelAxis wa) override; | ||||||
|  |     void on_moved_to(long x, long y) override; | ||||||
| 
 | 
 | ||||||
| private: |     void move_clip_plane(double z) { call_cameras(&Camera::set_clip_z, z); } | ||||||
|      |  | ||||||
|     Collection<wkptr<Display>> m_displays; |  | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| }}     // namespace Slic3r::GL
 | }}     // namespace Slic3r::GL
 | ||||||
| #endif // GLSCENE_HPP
 | #endif // GLSCENE_HPP
 | ||||||
|  |  | ||||||
|  | @ -15,9 +15,9 @@ | ||||||
| #include <wx/tglbtn.h> | #include <wx/tglbtn.h> | ||||||
| #include <wx/combobox.h> | #include <wx/combobox.h> | ||||||
| #include <wx/spinctrl.h> | #include <wx/spinctrl.h> | ||||||
|  | #include <wx/msgdlg.h> | ||||||
| #include <wx/glcanvas.h> | #include <wx/glcanvas.h> | ||||||
| 
 | 
 | ||||||
| #include "Canvas.hpp" |  | ||||||
| #include "GLScene.hpp" | #include "GLScene.hpp" | ||||||
| 
 | 
 | ||||||
| #include "libslic3r/Model.hpp" | #include "libslic3r/Model.hpp" | ||||||
|  | @ -29,51 +29,60 @@ | ||||||
| 
 | 
 | ||||||
| using namespace Slic3r::GL; | using namespace Slic3r::GL; | ||||||
| 
 | 
 | ||||||
|  | class Canvas: public wxGLCanvas, public Slic3r::GL::Display | ||||||
|  | { | ||||||
|  |     std::unique_ptr<wxGLContext> m_context; | ||||||
|  | public: | ||||||
|  |      | ||||||
|  |     void set_active(long w, long h) override | ||||||
|  |     { | ||||||
|  |         SetCurrent(*m_context); | ||||||
|  |         Slic3r::GL::Display::set_active(w, h); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     void swap_buffers() override { SwapBuffers(); } | ||||||
|  |      | ||||||
|  |     template<class...Args> | ||||||
|  |     Canvas(Args &&...args): wxGLCanvas(std::forward<Args>(args)...) | ||||||
|  |     { | ||||||
|  |         auto ctx = new wxGLContext(this); | ||||||
|  |         if (!ctx || !ctx->IsOK()) { | ||||||
|  |             wxMessageBox("Could not create OpenGL context.", "Error", | ||||||
|  |                          wxOK | wxICON_ERROR); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         m_context.reset(ctx); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class MyFrame: public wxFrame | class MyFrame: public wxFrame | ||||||
| { | { | ||||||
|     std::shared_ptr<Canvas> m_canvas; |     shptr<Scene>      m_scene;    // Model
 | ||||||
|     std::shared_ptr<Slic3r::GUI::ProgressStatusBar> m_stbar; |     shptr<Canvas>     m_canvas;   // View
 | ||||||
|     std::unique_ptr<Slic3r::GUI::Job> m_ui_job; |     shptr<Controller> m_ctl;      // Controller
 | ||||||
|  | 
 | ||||||
|  |     shptr<Slic3r::GUI::ProgressStatusBar> m_stbar; | ||||||
|  |     uqptr<Slic3r::GUI::Job> m_ui_job; | ||||||
|      |      | ||||||
|     class SLAJob: public Slic3r::GUI::Job { |     class SLAJob: public Slic3r::GUI::Job { | ||||||
|         MyFrame *m_parent; |         MyFrame *m_parent; | ||||||
|         std::unique_ptr<Slic3r::SLAPrint> m_print; |         std::unique_ptr<Slic3r::SLAPrint> m_print; | ||||||
|         std::string m_fname; |         std::string m_fname; | ||||||
|     public: |     public: | ||||||
|          |         SLAJob(MyFrame *frame, const std::string &fname) | ||||||
|         SLAJob(MyFrame *frame, const std::string &fname)  |  | ||||||
|             : Slic3r::GUI::Job{frame->m_stbar} |             : Slic3r::GUI::Job{frame->m_stbar} | ||||||
|             , m_parent{frame} |             , m_parent{frame} | ||||||
|             , m_fname{fname} |             , m_fname{fname} | ||||||
|         { |         {} | ||||||
|         } | 
 | ||||||
|          |         void process() override; | ||||||
|         void process() override  |  | ||||||
|         { |  | ||||||
|             using Status = Slic3r::PrintBase::SlicingStatus; |  | ||||||
|              |  | ||||||
|             Slic3r::DynamicPrintConfig cfg; |  | ||||||
|             auto model = Slic3r::Model::read_from_file(m_fname, &cfg); |  | ||||||
|              |  | ||||||
|             m_print = std::make_unique<Slic3r::SLAPrint>(); |  | ||||||
|             m_print->apply(model, cfg); |  | ||||||
|              |  | ||||||
|             Slic3r::PrintBase::TaskParams params; |  | ||||||
|             params.to_object_step = Slic3r::slaposHollowing; |  | ||||||
|             m_print->set_task(params); |  | ||||||
|              |  | ||||||
|             m_print->set_status_callback([this](const Status &status) { |  | ||||||
|                 update_status(status.percent, status.text); |  | ||||||
|             }); |  | ||||||
|              |  | ||||||
|             m_print->process(); |  | ||||||
|         } |  | ||||||
|          |          | ||||||
|     protected: |     protected: | ||||||
|          |          | ||||||
|         void finalize() override  |         void finalize() override  | ||||||
|         { |         { | ||||||
|             m_parent->m_canvas->get_scene()->set_print(std::move(m_print)); |             m_parent->m_scene->set_print(std::move(m_print)); | ||||||
|             m_parent->m_stbar->set_status_text( |             m_parent->m_stbar->set_status_text( | ||||||
|                         wxString::Format("Model %s loaded.", m_fname)); |                         wxString::Format("Model %s loaded.", m_fname)); | ||||||
|         } |         } | ||||||
|  | @ -84,6 +93,8 @@ public: | ||||||
|      |      | ||||||
| private: | private: | ||||||
|      |      | ||||||
|  |     void bind_canvas_events_to_controller(); | ||||||
|  |      | ||||||
|     void OnExit(wxCommandEvent& /*event*/)  |     void OnExit(wxCommandEvent& /*event*/)  | ||||||
|     { |     { | ||||||
|         RemoveChild(m_canvas.get()); |         RemoveChild(m_canvas.get()); | ||||||
|  | @ -108,7 +119,8 @@ private: | ||||||
|         const wxSize ClientSize = GetClientSize(); |         const wxSize ClientSize = GetClientSize(); | ||||||
|         m_canvas->set_active(ClientSize.x, ClientSize.y);  |         m_canvas->set_active(ClientSize.x, ClientSize.y);  | ||||||
|          |          | ||||||
|         m_canvas->repaint(ClientSize.x, ClientSize.y); |         m_canvas->set_screen_size(ClientSize.x, ClientSize.y); | ||||||
|  |         m_canvas->repaint(); | ||||||
|          |          | ||||||
|         // Do the repaint continuously
 |         // Do the repaint continuously
 | ||||||
|         Bind(wxEVT_IDLE, [this](wxIdleEvent &evt) { |         Bind(wxEVT_IDLE, [this](wxIdleEvent &evt) { | ||||||
|  | @ -159,9 +171,14 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|      WX_GL_MIN_ALPHA, 8, WX_GL_DEPTH_SIZE, 8, WX_GL_STENCIL_SIZE, 8, |      WX_GL_MIN_ALPHA, 8, WX_GL_DEPTH_SIZE, 8, WX_GL_STENCIL_SIZE, 8, | ||||||
|      WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0}; |      WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0}; | ||||||
|      |      | ||||||
|  |     m_scene = std::make_shared<Scene>(); | ||||||
|  |     m_ctl = std::make_shared<Controller>(); | ||||||
|  |     m_ctl->set_scene(m_scene); | ||||||
|  |      | ||||||
|     m_canvas = std::make_shared<Canvas>(this, wxID_ANY, attribList, |     m_canvas = std::make_shared<Canvas>(this, wxID_ANY, attribList, | ||||||
|                                         wxDefaultPosition, wxDefaultSize, |                                         wxDefaultPosition, wxDefaultSize, | ||||||
|                                         wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE); |                                         wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE); | ||||||
|  |     m_ctl->add_display(m_canvas); | ||||||
|      |      | ||||||
|     wxPanel *control_panel = new wxPanel(this); |     wxPanel *control_panel = new wxPanel(this); | ||||||
|     auto controlsizer = new wxBoxSizer(wxHORIZONTAL); |     auto controlsizer = new wxBoxSizer(wxHORIZONTAL); | ||||||
|  | @ -234,7 +251,7 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|     Bind(wxEVT_SHOW, &MyFrame::OnShown, this, GetId()); |     Bind(wxEVT_SHOW, &MyFrame::OnShown, this, GetId()); | ||||||
|      |      | ||||||
|     Bind(wxEVT_SLIDER, [this, slider](wxCommandEvent &) { |     Bind(wxEVT_SLIDER, [this, slider](wxCommandEvent &) { | ||||||
|         m_canvas->move_clip_plane(double(slider->GetValue())); |         m_ctl->move_clip_plane(double(slider->GetValue())); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     ms_toggle->Bind(wxEVT_TOGGLEBUTTON, [this, ms_toggle](wxCommandEvent &){ |     ms_toggle->Bind(wxEVT_TOGGLEBUTTON, [this, ms_toggle](wxCommandEvent &){ | ||||||
|  | @ -283,5 +300,73 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     m_canvas->set_scene(std::make_shared<Slic3r::GL::Scene>()); |     bind_canvas_events_to_controller(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MyFrame::bind_canvas_events_to_controller() | ||||||
|  | { | ||||||
|  |     m_canvas->Bind(wxEVT_MOUSEWHEEL, [this](wxMouseEvent &evt) { | ||||||
|  |         m_ctl->on_scroll(evt.GetWheelRotation(), evt.GetWheelDelta(), | ||||||
|  |                          evt.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL ? | ||||||
|  |                              Slic3r::GL::MouseInput::waVertical : | ||||||
|  |                              Slic3r::GL::MouseInput::waHorizontal); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     m_canvas->Bind(wxEVT_MOTION, [this](wxMouseEvent &evt) { | ||||||
|  |         m_ctl->on_moved_to(evt.GetPosition().x, evt.GetPosition().y); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     m_canvas->Bind(wxEVT_RIGHT_DOWN, [this](wxMouseEvent & /*evt*/) { | ||||||
|  |         m_ctl->on_right_click_down(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     m_canvas->Bind(wxEVT_RIGHT_UP, [this](wxMouseEvent & /*evt*/) { | ||||||
|  |         m_ctl->on_right_click_up(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     m_canvas->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent & /*evt*/) { | ||||||
|  |         m_ctl->on_left_click_down(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     m_canvas->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent & /*evt*/) { | ||||||
|  |         m_ctl->on_left_click_up(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     m_canvas->Bind(wxEVT_PAINT, [this](wxPaintEvent &) { | ||||||
|  |         // This is required even though dc is not used otherwise.
 | ||||||
|  |         wxPaintDC dc(this); | ||||||
|  |          | ||||||
|  |         // Set the OpenGL viewport according to the client size of this
 | ||||||
|  |         // canvas. This is done here rather than in a wxSizeEvent handler
 | ||||||
|  |         // because our OpenGL rendering context (and thus viewport setting) is
 | ||||||
|  |         // used with multiple canvases: If we updated the viewport in the
 | ||||||
|  |         // wxSizeEvent handler, changing the size of one canvas causes a
 | ||||||
|  |         // viewport setting that is wrong when next another canvas is
 | ||||||
|  |         // repainted.
 | ||||||
|  |         const wxSize ClientSize = m_canvas->GetClientSize(); | ||||||
|  |          | ||||||
|  |         m_canvas->set_screen_size(ClientSize.x, ClientSize.y); | ||||||
|  |         m_canvas->repaint(); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MyFrame::SLAJob::process()  | ||||||
|  | { | ||||||
|  |     using Status = Slic3r::PrintBase::SlicingStatus; | ||||||
|  |      | ||||||
|  |     Slic3r::DynamicPrintConfig cfg; | ||||||
|  |     auto model = Slic3r::Model::read_from_file(m_fname, &cfg); | ||||||
|  |      | ||||||
|  |     m_print = std::make_unique<Slic3r::SLAPrint>(); | ||||||
|  |     m_print->apply(model, cfg); | ||||||
|  |      | ||||||
|  |     Slic3r::PrintBase::TaskParams params; | ||||||
|  |     params.to_object_step = Slic3r::slaposHollowing; | ||||||
|  |     m_print->set_task(params); | ||||||
|  |      | ||||||
|  |     m_print->set_status_callback([this](const Status &status) { | ||||||
|  |         update_status(status.percent, status.text); | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     m_print->process(); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tamasmeszaros
						tamasmeszaros