Add ctl and fix applying opencsg params on the fly.

This commit is contained in:
tamasmeszaros 2019-12-16 18:49:44 +01:00
parent d14ff000e0
commit bb3b39016f
4 changed files with 205 additions and 154 deletions

View file

@ -40,58 +40,6 @@ public:
}
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());
}
};

View file

@ -133,7 +133,7 @@ void Scene::set_print(uqptr<SLAPrint> &&print)
m_print = std::move(print);
// Notify displays
call(&Display::on_scene_updated, m_displays);
call(&Listener::on_scene_updated, m_listeners, *this);
}
BoundingBoxf3 Scene::get_bounding_box() const
@ -383,13 +383,18 @@ void Display::set_active(long width, long 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)
m_camera->set_screen(width, height);
m_size = {width, height};
repaint();
}
void Display::repaint()
{
clear_screen();
m_camera->view();
@ -400,23 +405,34 @@ void Display::repaint(long width, long height)
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_camera->set_zoom(m_wheel_pos);
m_scene->on_scroll(v, d, wa);
repaint(m_size.x(), m_size.y());
call_cameras(&Camera::set_zoom, m_wheel_pos);
call(&Display::repaint, m_displays);
}
void Display::on_moved_to(long x, long y)
void Controller::on_moved_to(long x, long y)
{
if (m_left_btn) {
m_camera->rotate((Vec2i{x, y} - m_mouse_pos).cast<float>());
repaint();
call_cameras(&Camera::rotate, (Vec2i{x, y} - m_mouse_pos).cast<float>());
call(&Display::repaint, m_displays);
}
m_mouse_pos = {x, y};
}
@ -424,30 +440,27 @@ void Display::apply_csgsettings(const CSGSettings &settings)
{
using namespace OpenCSG;
bool update = m_csgsettings.get_convexity() != settings.get_convexity();
bool needupdate = m_csgsettings.get_convexity() != settings.get_convexity();
m_csgsettings = settings;
setOption(AlgorithmSetting, m_csgsettings.get_algo());
setOption(DepthComplexitySetting, m_csgsettings.get_depth_algo());
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();
}
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;
{
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();
for (const SLAPrintObject *po : print->objects()) {
@ -499,12 +512,6 @@ void Display::on_scene_updated()
repaint();
}
void Display::set_scene(shptr<Scene> scene)
{
m_scene = scene;
m_scene->add_display(shared_from_this());
}
void Camera::view()
{
glMatrixMode(GL_MODELVIEW);

View file

@ -223,8 +223,8 @@ public:
private:
OpenCSG::Algorithm m_csgalg = OpenCSG::Algorithm::Automatic;
OpenCSG::DepthComplexityAlgorithm m_depth_algo = OpenCSG::DepthComplexityAlgorithm::NoDepthComplexitySampling;
OpenCSG::Optimization m_optim = OpenCSG::Optimization::OptimizationDefault;
OpenCSG::DepthComplexityAlgorithm m_depth_algo = OpenCSG::NoDepthComplexitySampling;
OpenCSG::Optimization m_optim = OpenCSG::OptimizationDefault;
bool m_enable = true;
unsigned int m_convexity = DEFAULT_CONVEXITY;
@ -244,21 +244,44 @@ public:
unsigned get_convexity() const { return m_convexity; }
void set_convexity(unsigned c) { m_convexity = c; }
};
class Display : public std::enable_shared_from_this<Display>,
public MouseInput::Listener
class Scene
{
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:
Collection<wkptr<Listener>> m_listeners;
};
class Display : public Scene::Listener
{
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;
bool m_initialized = false, m_left_btn = false, m_right_btn = false;
bool m_initialized = false;
CSGSettings m_csgsettings;
shptr<Camera> m_camera;
struct SceneCache {
Collection<shptr<Primitive>> primitives;
Collection<Primitive *> primitives_free;
@ -272,64 +295,79 @@ protected:
unsigned covexity);
} m_scene_cache;
shptr<Camera> m_camera;
public:
Display(shptr<Scene> scene = nullptr, shptr<Camera> camera = nullptr)
: m_scene(scene)
, m_camera(camera ? camera : std::make_shared<PerspectiveCamera>())
explicit Display(shptr<Camera> camera = nullptr)
: m_camera(camera ? camera : std::make_shared<PerspectiveCamera>())
{}
Camera * camera() { return m_camera.get(); }
virtual void swap_buffers() = 0;
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);
void repaint() { repaint(m_size.x(), m_size.y()); }
void set_scene(shptr<Scene> scene);
shptr<Scene> get_scene() { return m_scene; }
virtual void repaint();
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; }
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 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;
Collection<wkptr<Display>> m_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:
Scene();
~Scene();
void set_scene(shptr<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)
{
m_displays.emplace_back(disp);
cleanup(m_displays);
}
void set_print(uqptr<SLAPrint> &&print);
const SLAPrint * get_print() const { return m_print.get(); }
void on_scene_updated(const Scene &scene) override;
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:
Collection<wkptr<Display>> m_displays;
void move_clip_plane(double z) { call_cameras(&Camera::set_clip_z, z); }
};
}} // namespace Slic3r::GL
#endif // GLSCENE_HPP

View file

@ -31,49 +31,31 @@ using namespace Slic3r::GL;
class MyFrame: public wxFrame
{
std::shared_ptr<Canvas> m_canvas;
std::shared_ptr<Slic3r::GUI::ProgressStatusBar> m_stbar;
std::unique_ptr<Slic3r::GUI::Job> m_ui_job;
shptr<Scene> m_scene; // Model
shptr<Canvas> m_canvas; // View
shptr<Controller> m_ctl; // Controller
shptr<Slic3r::GUI::ProgressStatusBar> m_stbar;
uqptr<Slic3r::GUI::Job> m_ui_job;
class SLAJob: public Slic3r::GUI::Job {
MyFrame *m_parent;
std::unique_ptr<Slic3r::SLAPrint> m_print;
std::string m_fname;
public:
SLAJob(MyFrame *frame, const std::string &fname)
SLAJob(MyFrame *frame, const std::string &fname)
: Slic3r::GUI::Job{frame->m_stbar}
, m_parent{frame}
, m_fname{fname}
{
}
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();
}
{}
void process() override;
protected:
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(
wxString::Format("Model %s loaded.", m_fname));
}
@ -84,6 +66,8 @@ public:
private:
void bind_canvas_events_to_controller();
void OnExit(wxCommandEvent& /*event*/)
{
RemoveChild(m_canvas.get());
@ -108,7 +92,8 @@ private:
const wxSize ClientSize = GetClientSize();
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
Bind(wxEVT_IDLE, [this](wxIdleEvent &evt) {
@ -159,9 +144,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_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,
wxDefaultPosition, wxDefaultSize,
wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE);
m_ctl->add_display(m_canvas);
wxPanel *control_panel = new wxPanel(this);
auto controlsizer = new wxBoxSizer(wxHORIZONTAL);
@ -234,7 +224,7 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size):
Bind(wxEVT_SHOW, &MyFrame::OnShown, this, GetId());
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 &){
@ -283,5 +273,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();
}