mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Merge branch 'tm_opencsg' into lm_tm_hollowing
This commit is contained in:
		
						commit
						9363344a6f
					
				
					 7 changed files with 549 additions and 225 deletions
				
			
		|  | @ -409,8 +409,7 @@ if(SLIC3R_STATIC) | ||||||
|     set(USE_BLOSC TRUE) |     set(USE_BLOSC TRUE) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| 
 | find_package(OpenVDB 5.0 REQUIRED COMPONENTS openvdb) | ||||||
| find_package(OpenVDB 5.0 COMPONENTS openvdb) |  | ||||||
| if(OpenVDB_FOUND) | if(OpenVDB_FOUND) | ||||||
|     slic3r_remap_configs(IlmBase::Half RelWithDebInfo Release) |     slic3r_remap_configs(IlmBase::Half RelWithDebInfo Release) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -215,20 +215,50 @@ if(UNIX AND OPENVDB_USE_STATIC_LIBS) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| set(OpenVDB_LIB_COMPONENTS "") | set(OpenVDB_LIB_COMPONENTS "") | ||||||
|  | set(OpenVDB_DEBUG_SUFFIX "d" CACHE STRING "Suffix for the debug libraries") | ||||||
|  | 
 | ||||||
|  | get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||||||
| 
 | 
 | ||||||
| foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS}) | foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS}) | ||||||
|   set(LIB_NAME ${COMPONENT}) |   set(LIB_NAME ${COMPONENT}) | ||||||
|   find_library(OpenVDB_${COMPONENT}_LIBRARY ${LIB_NAME} lib${LIB_NAME} | 
 | ||||||
|  |   find_library(OpenVDB_${COMPONENT}_LIBRARY_RELEASE ${LIB_NAME} lib${LIB_NAME} | ||||||
|     PATHS ${_OPENVDB_LIBRARYDIR_SEARCH_DIRS} |     PATHS ${_OPENVDB_LIBRARYDIR_SEARCH_DIRS} | ||||||
|     PATH_SUFFIXES ${OPENVDB_PATH_SUFFIXES} |     PATH_SUFFIXES ${OPENVDB_PATH_SUFFIXES} | ||||||
|   ) |   ) | ||||||
|   list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY}) |  | ||||||
| 
 | 
 | ||||||
|   if(OpenVDB_${COMPONENT}_LIBRARY) |   find_library(OpenVDB_${COMPONENT}_LIBRARY_DEBUG ${LIB_NAME}${OpenVDB_DEBUG_SUFFIX} lib${LIB_NAME}${OpenVDB_DEBUG_SUFFIX} | ||||||
|     set(OpenVDB_${COMPONENT}_FOUND TRUE) |     PATHS ${_OPENVDB_LIBRARYDIR_SEARCH_DIRS} | ||||||
|   else() |     PATH_SUFFIXES ${OPENVDB_PATH_SUFFIXES} | ||||||
|     set(OpenVDB_${COMPONENT}_FOUND FALSE) |   ) | ||||||
|   endif() | 
 | ||||||
|  |   if (_is_multi) | ||||||
|  |     list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY_RELEASE} ${OpenVDB_${COMPONENT}_LIBRARY_DEBUG}) | ||||||
|  | 
 | ||||||
|  |     list(FIND CMAKE_CONFIGURATION_TYPES "Debug" _has_debug) | ||||||
|  |      | ||||||
|  |     if(OpenVDB_${COMPONENT}_LIBRARY_RELEASE AND (_has_debug LESS 0 OR OpenVDB_${COMPONENT}_LIBRARY_DEBUG)) | ||||||
|  |       set(OpenVDB_${COMPONENT}_FOUND TRUE) | ||||||
|  |     else() | ||||||
|  |       set(OpenVDB_${COMPONENT}_FOUND FALSE) | ||||||
|  |     endif() | ||||||
|  |   else () | ||||||
|  |     string(TOUPPER "${CMAKE_BUILD_TYPE}" _BUILD_TYPE) | ||||||
|  | 
 | ||||||
|  |     set(OpenVDB_${COMPONENT}_LIBRARY ${OpenVDB_${COMPONENT}_LIBRARY_${_BUILD_TYPE}}) | ||||||
|  | 
 | ||||||
|  |     if (NOT MSVC AND NOT OpenVDB_${COMPONENT}_LIBRARY) | ||||||
|  |       set(OpenVDB_${COMPONENT}_LIBRARY ${OpenVDB_${COMPONENT}_LIBRARY_RELEASE}) | ||||||
|  |     endif () | ||||||
|  | 
 | ||||||
|  |     list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY}) | ||||||
|  | 
 | ||||||
|  |     if(OpenVDB_${COMPONENT}_LIBRARY) | ||||||
|  |       set(OpenVDB_${COMPONENT}_FOUND TRUE) | ||||||
|  |     else() | ||||||
|  |       set(OpenVDB_${COMPONENT}_FOUND FALSE) | ||||||
|  |     endif() | ||||||
|  |   endif () | ||||||
| endforeach() | endforeach() | ||||||
| 
 | 
 | ||||||
| if(UNIX AND OPENVDB_USE_STATIC_LIBS) | if(UNIX AND OPENVDB_USE_STATIC_LIBS) | ||||||
|  | @ -487,7 +517,6 @@ foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS}) | ||||||
|   if(NOT TARGET OpenVDB::${COMPONENT}) |   if(NOT TARGET OpenVDB::${COMPONENT}) | ||||||
|     add_library(OpenVDB::${COMPONENT} UNKNOWN IMPORTED) |     add_library(OpenVDB::${COMPONENT} UNKNOWN IMPORTED) | ||||||
|     set_target_properties(OpenVDB::${COMPONENT} PROPERTIES |     set_target_properties(OpenVDB::${COMPONENT} PROPERTIES | ||||||
|       IMPORTED_LOCATION "${OpenVDB_${COMPONENT}_LIBRARY}" |  | ||||||
|       INTERFACE_COMPILE_OPTIONS "${OpenVDB_DEFINITIONS}" |       INTERFACE_COMPILE_OPTIONS "${OpenVDB_DEFINITIONS}" | ||||||
|       INTERFACE_INCLUDE_DIRECTORIES "${OpenVDB_INCLUDE_DIR}" |       INTERFACE_INCLUDE_DIRECTORIES "${OpenVDB_INCLUDE_DIR}" | ||||||
|       IMPORTED_LINK_DEPENDENT_LIBRARIES "${_OPENVDB_HIDDEN_DEPENDENCIES}" # non visible deps |       IMPORTED_LINK_DEPENDENT_LIBRARIES "${_OPENVDB_HIDDEN_DEPENDENCIES}" # non visible deps | ||||||
|  | @ -495,6 +524,17 @@ foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS}) | ||||||
|       INTERFACE_COMPILE_FEATURES cxx_std_11 |       INTERFACE_COMPILE_FEATURES cxx_std_11 | ||||||
|    ) |    ) | ||||||
| 
 | 
 | ||||||
|  |   if (_is_multi) | ||||||
|  |     set_target_properties(OpenVDB::${COMPONENT} PROPERTIES  | ||||||
|  |       IMPORTED_LOCATION_RELEASE "${OpenVDB_${COMPONENT}_LIBRARY_RELEASE}" | ||||||
|  |       IMPORTED_LOCATION_DEBUG "${OpenVDB_${COMPONENT}_LIBRARY_DEBUG}" | ||||||
|  |     ) | ||||||
|  |   else () | ||||||
|  |     set_target_properties(OpenVDB::${COMPONENT} PROPERTIES  | ||||||
|  |       IMPORTED_LOCATION "${OpenVDB_${COMPONENT}_LIBRARY}" | ||||||
|  |     ) | ||||||
|  |   endif () | ||||||
|  | 
 | ||||||
|    if (OPENVDB_USE_STATIC_LIBS) |    if (OPENVDB_USE_STATIC_LIBS) | ||||||
|     set_target_properties(OpenVDB::${COMPONENT} PROPERTIES |     set_target_properties(OpenVDB::${COMPONENT} PROPERTIES | ||||||
|       INTERFACE_COMPILE_DEFINITIONS "OPENVDB_STATICLIB;OPENVDB_OPENEXR_STATICLIB" |       INTERFACE_COMPILE_DEFINITIONS "OPENVDB_STATICLIB;OPENVDB_OPENEXR_STATICLIB" | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								deps/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								deps/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							|  | @ -47,6 +47,7 @@ message(STATUS "PrusaSlicer deps debug build: ${DEP_DEBUG}") | ||||||
| 
 | 
 | ||||||
| find_package(Git REQUIRED) | find_package(Git REQUIRED) | ||||||
| 
 | 
 | ||||||
|  | get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||||||
| 
 | 
 | ||||||
| function(prusaslicer_add_cmake_project projectname) | function(prusaslicer_add_cmake_project projectname) | ||||||
|     cmake_parse_arguments(P_ARGS "" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN}) |     cmake_parse_arguments(P_ARGS "" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN}) | ||||||
|  |  | ||||||
|  | @ -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  | add_executable(opencsg_example WIN32 main.cpp  Engine.hpp Engine.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) | ||||||
|  | @ -11,11 +11,15 @@ find_package(wxWidgets 3.1 REQUIRED COMPONENTS core base gl html) | ||||||
| find_package(OpenGL REQUIRED) | find_package(OpenGL REQUIRED) | ||||||
| find_package(GLEW REQUIRED) | find_package(GLEW REQUIRED) | ||||||
| find_package(OpenCSG REQUIRED) | find_package(OpenCSG REQUIRED) | ||||||
| find_package(GLUT REQUIRED) |  | ||||||
| include(${wxWidgets_USE_FILE}) | include(${wxWidgets_USE_FILE}) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| target_link_libraries(opencsg_example libslic3r) | target_link_libraries(opencsg_example libslic3r) | ||||||
| target_include_directories(opencsg_example PRIVATE ${wxWidgets_INCLUDE_DIRS}) | target_include_directories(opencsg_example PRIVATE ${wxWidgets_INCLUDE_DIRS}) | ||||||
| target_compile_definitions(opencsg_example PRIVATE ${wxWidgets_DEFINITIONS}) | target_compile_definitions(opencsg_example PRIVATE ${wxWidgets_DEFINITIONS}) | ||||||
| target_link_libraries(opencsg_example ${wxWidgets_LIBRARIES} GLEW::GLEW OpenCSG::opencsg GLUT::GLUT OpenGL::OpenGL -lXrandr -lXext -lX11) | 
 | ||||||
|  | target_link_libraries(opencsg_example ${wxWidgets_LIBRARIES}  | ||||||
|  |     OpenCSG::opencsg  | ||||||
|  |     GLEW::GLEW | ||||||
|  |     OpenGL::GL  | ||||||
|  |     #-lXrandr -lXext -lX11 | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  | @ -1,16 +1,10 @@ | ||||||
| #include "GLScene.hpp" | #include "Engine.hpp" | ||||||
| #include <libslic3r/Utils.hpp> | #include <libslic3r/Utils.hpp> | ||||||
| #include <libslic3r/SLAPrint.hpp> | #include <libslic3r/SLAPrint.hpp> | ||||||
| #include <libslic3r/MTUtils.hpp> | #include <libslic3r/MTUtils.hpp> | ||||||
| 
 | 
 | ||||||
| #include <GL/glew.h> | #include <GL/glew.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __APPLE__ |  | ||||||
| #include <GLUT/glut.h> |  | ||||||
| #else |  | ||||||
| #include <GL/glut.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include <boost/log/trivial.hpp> | #include <boost/log/trivial.hpp> | ||||||
| 
 | 
 | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
|  | @ -52,49 +46,9 @@ inline void glAssertRecentCall() { } | ||||||
| namespace Slic3r { namespace GL { | namespace Slic3r { namespace GL { | ||||||
| 
 | 
 | ||||||
| Scene::Scene() = default; | Scene::Scene() = default; | ||||||
| 
 |  | ||||||
| Scene::~Scene() = default; | Scene::~Scene() = default; | ||||||
| 
 | 
 | ||||||
| void renderfps () { | void CSGDisplay::render_scene() | ||||||
|     static std::ostringstream fpsStream; |  | ||||||
|     static int fps = 0; |  | ||||||
|     static int ancient = 0; |  | ||||||
|     static int last = 0; |  | ||||||
|     static int msec = 0; |  | ||||||
|      |  | ||||||
|     last = msec; |  | ||||||
|     msec = glutGet(GLUT_ELAPSED_TIME); |  | ||||||
|     if (last / 1000 != msec / 1000) { |  | ||||||
|          |  | ||||||
|         float correctedFps = fps * 1000.0f / float(msec - ancient); |  | ||||||
|         fpsStream.str(""); |  | ||||||
|         fpsStream << "fps: " << correctedFps << std::ends; |  | ||||||
|          |  | ||||||
|         ancient = msec; |  | ||||||
|         fps = 0; |  | ||||||
|     } |  | ||||||
|     glDisable(GL_DEPTH_TEST); |  | ||||||
|     glLoadIdentity(); |  | ||||||
|     glMatrixMode(GL_PROJECTION); |  | ||||||
|     glPushMatrix(); |  | ||||||
|     glLoadIdentity(); |  | ||||||
|     glColor3f(0.0f, 0.0f, 0.0f); |  | ||||||
|     glRasterPos2f(-1.0f, -1.0f); |  | ||||||
|     glDisable(GL_LIGHTING); |  | ||||||
|     std::string s = fpsStream.str(); |  | ||||||
|     for (unsigned int i=0; i<s.size(); ++i) { |  | ||||||
|         glutBitmapCharacter(GLUT_BITMAP_8_BY_13, s[i]); |  | ||||||
|     } |  | ||||||
|     glEnable(GL_LIGHTING); |  | ||||||
|     glPopMatrix(); |  | ||||||
|     glMatrixMode(GL_MODELVIEW); |  | ||||||
|     glEnable(GL_DEPTH_TEST); |  | ||||||
|      |  | ||||||
|     ++fps; |  | ||||||
|     glFlush(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Display::render_scene() |  | ||||||
| { | { | ||||||
|     GLfloat color[] = {1.f, 1.f, 0.f, 0.f}; |     GLfloat color[] = {1.f, 1.f, 0.f, 0.f}; | ||||||
|     glsafe(::glColor4fv(color)); |     glsafe(::glColor4fv(color)); | ||||||
|  | @ -141,14 +95,14 @@ BoundingBoxf3 Scene::get_bounding_box() const | ||||||
|     return m_print->model().bounding_box(); |     return m_print->model().bounding_box(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::SceneCache::clear() | void CSGDisplay::SceneCache::clear() | ||||||
| { | { | ||||||
|     primitives_csg.clear(); |     primitives_csg.clear(); | ||||||
|     primitives_free.clear(); |     primitives_free.clear(); | ||||||
|     primitives.clear(); |     primitives.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| shptr<Primitive> Display::SceneCache::add_mesh(const TriangleMesh &mesh) | shptr<Primitive> CSGDisplay::SceneCache::add_mesh(const TriangleMesh &mesh) | ||||||
| { | { | ||||||
|     auto p = std::make_shared<Primitive>(); |     auto p = std::make_shared<Primitive>(); | ||||||
|     p->load_mesh(mesh); |     p->load_mesh(mesh); | ||||||
|  | @ -157,9 +111,9 @@ shptr<Primitive> Display::SceneCache::add_mesh(const TriangleMesh &mesh) | ||||||
|     return p; |     return p; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| shptr<Primitive> Display::SceneCache::add_mesh(const TriangleMesh &mesh, | shptr<Primitive> CSGDisplay::SceneCache::add_mesh(const TriangleMesh &mesh, | ||||||
|                                                OpenCSG::Operation  o, |                                                    OpenCSG::Operation  o, | ||||||
|                                                unsigned            c) |                                                    unsigned            c) | ||||||
| { | { | ||||||
|     auto p = std::make_shared<Primitive>(o, c); |     auto p = std::make_shared<Primitive>(o, c); | ||||||
|     p->load_mesh(mesh); |     p->load_mesh(mesh); | ||||||
|  | @ -347,18 +301,18 @@ void Display::clear_screen() | ||||||
|     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Display::~Display() | ||||||
|  | { | ||||||
|  |     OpenCSG::freeResources(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Display::set_active(long width, long height) | void Display::set_active(long width, long height) | ||||||
| {    | {    | ||||||
|     static int argc = 0; |  | ||||||
|      |  | ||||||
|     if (!m_initialized) { |     if (!m_initialized) { | ||||||
|         glewInit(); |         glewInit(); | ||||||
|         glutInit(&argc, nullptr); |  | ||||||
|         m_initialized = true; |         m_initialized = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     m_size = {width, height}; |  | ||||||
|      |  | ||||||
|     // gray background
 |     // gray background
 | ||||||
|     glClearColor(0.9f, 0.9f, 0.9f, 1.0f); |     glClearColor(0.9f, 0.9f, 0.9f, 1.0f); | ||||||
| 
 | 
 | ||||||
|  | @ -380,7 +334,7 @@ void Display::set_active(long width, long height) | ||||||
|     glEnable(GL_DEPTH_TEST); |     glEnable(GL_DEPTH_TEST); | ||||||
|     glEnable(GL_STENCIL_TEST); |     glEnable(GL_STENCIL_TEST); | ||||||
|      |      | ||||||
|     m_camera->set_screen(width, height); |     set_screen_size(width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::set_screen_size(long width, long height) | void Display::set_screen_size(long width, long height) | ||||||
|  | @ -389,8 +343,6 @@ void Display::set_screen_size(long width, long 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() | void Display::repaint() | ||||||
|  | @ -400,7 +352,7 @@ void Display::repaint() | ||||||
|     m_camera->view(); |     m_camera->view(); | ||||||
|     render_scene(); |     render_scene(); | ||||||
|      |      | ||||||
|     renderfps();  |     m_fps_counter.update(); | ||||||
|      |      | ||||||
|     swap_buffers(); |     swap_buffers(); | ||||||
| } | } | ||||||
|  | @ -436,7 +388,7 @@ void Controller::on_moved_to(long x, long y) | ||||||
|     m_mouse_pos = {x, y}; |     m_mouse_pos = {x, y}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::apply_csgsettings(const CSGSettings &settings) | void CSGDisplay::apply_csgsettings(const CSGSettings &settings) | ||||||
| { | { | ||||||
|     using namespace OpenCSG; |     using namespace OpenCSG; | ||||||
|      |      | ||||||
|  | @ -452,11 +404,9 @@ void Display::apply_csgsettings(const CSGSettings &settings) | ||||||
|             if (p->getConvexity() > 1) |             if (p->getConvexity() > 1) | ||||||
|                 p->setConvexity(m_csgsettings.get_convexity()); |                 p->setConvexity(m_csgsettings.get_convexity()); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     repaint(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Display::on_scene_updated(const Scene &scene) | void CSGDisplay::on_scene_updated(const Scene &scene) | ||||||
| { | { | ||||||
|     const SLAPrint *print = scene.get_print(); |     const SLAPrint *print = scene.get_print(); | ||||||
|     if (!print) return; |     if (!print) return; | ||||||
|  | @ -555,4 +505,24 @@ bool enable_multisampling(bool e) | ||||||
| 
 | 
 | ||||||
| MouseInput::Listener::~Listener() = default; | MouseInput::Listener::~Listener() = default; | ||||||
| 
 | 
 | ||||||
|  | void FpsCounter::update() | ||||||
|  | { | ||||||
|  |     ++m_frames; | ||||||
|  |      | ||||||
|  |     TimePoint msec = Clock::now(); | ||||||
|  |      | ||||||
|  |     double seconds_window = to_sec(msec - m_window); | ||||||
|  |     m_fps = 0.5 * m_fps + 0.5 * (m_frames / seconds_window); | ||||||
|  |      | ||||||
|  |     if (to_sec(msec - m_last) >= m_resolution) { | ||||||
|  |         m_last = msec; | ||||||
|  |         for (auto &l : m_listeners) l(m_fps); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (seconds_window >= m_window_size) { | ||||||
|  |         m_frames = 0; | ||||||
|  |         m_window = msec; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }} // namespace Slic3r::GL
 | }} // namespace Slic3r::GL
 | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| #ifndef GLSCENE_HPP | #ifndef SLIC3R_OCSG_EXMP_ENGINE_HPP | ||||||
| #define GLSCENE_HPP | #define SLIC3R_OCSG_EXMP_ENGINE_HPP_HPP | ||||||
| 
 | 
 | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <chrono> | ||||||
| 
 | 
 | ||||||
| #include <libslic3r/Geometry.hpp> | #include <libslic3r/Geometry.hpp> | ||||||
| #include <libslic3r/Model.hpp> | #include <libslic3r/Model.hpp> | ||||||
|  | @ -164,7 +165,6 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool enable_multisampling(bool e = true); | bool enable_multisampling(bool e = true); | ||||||
| void renderfps(); |  | ||||||
| 
 | 
 | ||||||
| class Primitive : public OpenCSG::Primitive | class Primitive : public OpenCSG::Primitive | ||||||
| { | { | ||||||
|  | @ -189,8 +189,6 @@ public: | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Scene; |  | ||||||
| 
 |  | ||||||
| class Camera { | class Camera { | ||||||
| protected: | protected: | ||||||
|     Vec2f m_rot = {0., 0.}; |     Vec2f m_rot = {0., 0.}; | ||||||
|  | @ -211,12 +209,56 @@ public: | ||||||
|     void set_clip_z(double z) { m_clip_z = z; } |     void set_clip_z(double z) { m_clip_z = z; } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | inline void reset(Camera &cam) | ||||||
|  | { | ||||||
|  |     cam.set_rotation({0., 0.}); | ||||||
|  |     cam.set_zoom(0.); | ||||||
|  |     cam.set_reference_point({0., 0., 0.}); | ||||||
|  |     cam.set_clip_z(0.); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class PerspectiveCamera: public Camera { | class PerspectiveCamera: public Camera { | ||||||
| public: | public: | ||||||
|      |      | ||||||
|     void set_screen(long width, long height) override; |     void set_screen(long width, long height) override; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | class FpsCounter { | ||||||
|  |     vector<std::function<void(double)>> m_listeners; | ||||||
|  |      | ||||||
|  |     using Clock = std::chrono::high_resolution_clock; | ||||||
|  |     using Duration = Clock::duration; | ||||||
|  |     using TimePoint = Clock::time_point; | ||||||
|  |      | ||||||
|  |     int m_frames = 0; | ||||||
|  |     TimePoint m_last = Clock::now(), m_window = m_last; | ||||||
|  |      | ||||||
|  |     double m_resolution = 0.1, m_window_size = 1.0; | ||||||
|  |     double m_fps = 0.; | ||||||
|  |      | ||||||
|  |     static double to_sec(Duration d) | ||||||
|  |     { | ||||||
|  |         return d.count() * double(Duration::period::num) / Duration::period::den; | ||||||
|  |     }     | ||||||
|  |      | ||||||
|  | public: | ||||||
|  |      | ||||||
|  |     void update(); | ||||||
|  | 
 | ||||||
|  |     void add_listener(std::function<void(double)> lst) | ||||||
|  |     { | ||||||
|  |         m_listeners.emplace_back(lst); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     void clear_listeners() { m_listeners = {}; } | ||||||
|  | 
 | ||||||
|  |     void set_notification_interval(double seconds); | ||||||
|  |     void set_measure_window_size(double seconds); | ||||||
|  |      | ||||||
|  |     double get_notification_interval() const { return m_resolution; } | ||||||
|  |     double get_mesure_window_size() const { return m_window_size; } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class CSGSettings { | class CSGSettings { | ||||||
| public: | public: | ||||||
|     static const constexpr unsigned DEFAULT_CONVEXITY = 10; |     static const constexpr unsigned DEFAULT_CONVEXITY = 10; | ||||||
|  | @ -280,6 +322,42 @@ protected: | ||||||
|     Vec2i m_size; |     Vec2i m_size; | ||||||
|     bool m_initialized = false; |     bool m_initialized = false; | ||||||
|      |      | ||||||
|  |     shptr<Camera>  m_camera; | ||||||
|  |     FpsCounter m_fps_counter; | ||||||
|  |      | ||||||
|  | public: | ||||||
|  |      | ||||||
|  |     explicit Display(shptr<Camera> camera = nullptr) | ||||||
|  |         : m_camera(camera ? camera : std::make_shared<PerspectiveCamera>()) | ||||||
|  |     {} | ||||||
|  |      | ||||||
|  |     ~Display() override; | ||||||
|  |      | ||||||
|  |     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(); | ||||||
|  |      | ||||||
|  |     bool is_initialized() const { return m_initialized; } | ||||||
|  |      | ||||||
|  |     virtual void clear_screen(); | ||||||
|  |     virtual void render_scene() {} | ||||||
|  |      | ||||||
|  |     template<class _FpsCounter> void set_fps_counter(_FpsCounter &&fpsc) | ||||||
|  |     { | ||||||
|  |         m_fps_counter = std::forward<_FpsCounter>(fpsc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const FpsCounter &get_fps_counter() const { return m_fps_counter; } | ||||||
|  |     FpsCounter &get_fps_counter() { return m_fps_counter; } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class CSGDisplay : public Display { | ||||||
|  | protected: | ||||||
|     CSGSettings m_csgsettings; |     CSGSettings m_csgsettings; | ||||||
|      |      | ||||||
|     struct SceneCache { |     struct SceneCache { | ||||||
|  | @ -295,32 +373,14 @@ protected: | ||||||
|                                   unsigned            covexity); |                                   unsigned            covexity); | ||||||
|     } m_scene_cache; |     } m_scene_cache; | ||||||
|      |      | ||||||
|     shptr<Camera>  m_camera; |  | ||||||
|      |  | ||||||
| public: | public: | ||||||
|      |      | ||||||
|     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(); |  | ||||||
|      |  | ||||||
|     bool is_initialized() const { return m_initialized; } |  | ||||||
|      |  | ||||||
|     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); | ||||||
|      |      | ||||||
|     void on_scene_updated(const Scene &scene) override; |     void render_scene() override; | ||||||
|      |      | ||||||
|     virtual void clear_screen(); |     void on_scene_updated(const Scene &scene) override; | ||||||
|     virtual void render_scene(); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Controller : public std::enable_shared_from_this<Controller>, | class Controller : public std::enable_shared_from_this<Controller>, | ||||||
|  | @ -331,7 +391,7 @@ class Controller : public std::enable_shared_from_this<Controller>, | ||||||
|     Vec2i m_mouse_pos, m_mouse_pos_rprev, m_mouse_pos_lprev; |     Vec2i m_mouse_pos, m_mouse_pos_rprev, m_mouse_pos_lprev; | ||||||
|     bool m_left_btn = false, m_right_btn = false; |     bool m_left_btn = false, m_right_btn = false; | ||||||
| 
 | 
 | ||||||
|     shptr<Scene>               m_scene; |     shptr<Scene>           m_scene; | ||||||
|     vector<wkptr<Display>> m_displays; |     vector<wkptr<Display>> m_displays; | ||||||
|      |      | ||||||
|     // Call a method of Camera on all the cameras of the attached displays
 |     // Call a method of Camera on all the cameras of the attached displays
 | ||||||
|  | @ -370,5 +430,6 @@ public: | ||||||
| 
 | 
 | ||||||
|     void move_clip_plane(double z) { call_cameras(&Camera::set_clip_z, z); } |     void move_clip_plane(double z) { call_cameras(&Camera::set_clip_z, z); } | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
| }}     // namespace Slic3r::GL
 | }}     // namespace Slic3r::GL
 | ||||||
| #endif // GLSCENE_HPP
 | #endif // SLIC3R_OCSG_EXMP_ENGINE_HPP
 | ||||||
|  | @ -2,13 +2,15 @@ | ||||||
| #include <utility> | #include <utility> | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
|  | #include "Engine.hpp" | ||||||
|  | 
 | ||||||
| #include <GL/glew.h> | #include <GL/glew.h> | ||||||
| 
 | 
 | ||||||
| #include <opencsg/opencsg.h> | #include <opencsg/opencsg.h> | ||||||
| // For compilers that support precompilation, includes "wx/wx.h".
 | // For compilers that support precompilation, includes "wx/wx.h".
 | ||||||
| #include <wx/wxprec.h> | #include <wx/wxprec.h> | ||||||
| #ifndef WX_PRECOMP | #ifndef WX_PRECOMP | ||||||
|     #include <wx/wx.h> | #include <wx/wx.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #include <wx/slider.h> | #include <wx/slider.h> | ||||||
|  | @ -17,8 +19,7 @@ | ||||||
| #include <wx/spinctrl.h> | #include <wx/spinctrl.h> | ||||||
| #include <wx/msgdlg.h> | #include <wx/msgdlg.h> | ||||||
| #include <wx/glcanvas.h> | #include <wx/glcanvas.h> | ||||||
| 
 | #include <wx/cmdline.h> | ||||||
| #include "GLScene.hpp" |  | ||||||
| 
 | 
 | ||||||
| #include "libslic3r/Model.hpp" | #include "libslic3r/Model.hpp" | ||||||
| #include "libslic3r/Format/3mf.hpp" | #include "libslic3r/Format/3mf.hpp" | ||||||
|  | @ -29,30 +30,154 @@ | ||||||
| 
 | 
 | ||||||
| using namespace Slic3r::GL; | using namespace Slic3r::GL; | ||||||
| 
 | 
 | ||||||
| class Canvas: public wxGLCanvas, public Slic3r::GL::Display | class Canvas: public wxGLCanvas | ||||||
| { | { | ||||||
|     std::unique_ptr<wxGLContext> m_context; |     class OCSGRenderer: public Slic3r::GL::CSGDisplay { | ||||||
|  |         Canvas *m_canvas; | ||||||
|  |         shptr<wxGLContext> m_context; | ||||||
|  |     public: | ||||||
|  |          | ||||||
|  |         OCSGRenderer(Canvas *c): m_canvas{c} { | ||||||
|  |             auto ctx = new wxGLContext(m_canvas); | ||||||
|  |             if (!ctx || !ctx->IsOK()) { | ||||||
|  |                 wxMessageBox("Could not create OpenGL context.", "Error", | ||||||
|  |                              wxOK | wxICON_ERROR); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             m_context.reset(ctx); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         void set_active(long w, long h) override | ||||||
|  |         { | ||||||
|  |             m_canvas->SetCurrent(*m_context); | ||||||
|  |             Slic3r::GL::Display::set_active(w, h); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         wxGLContext * context() { return m_context.get(); } | ||||||
|  |         const wxGLContext * context() const { return m_context.get(); } | ||||||
|  |          | ||||||
|  |         void swap_buffers() override { m_canvas->SwapBuffers(); } | ||||||
|  |          | ||||||
|  |         ~OCSGRenderer() override { m_scene_cache.clear(); } | ||||||
|  |     }; | ||||||
|  |      | ||||||
|  |     shptr<OCSGRenderer> m_ocsgdisplay = std::make_shared<OCSGRenderer>(this); | ||||||
|  |      | ||||||
|  |     shptr<Slic3r::GL::Display> m_display = m_ocsgdisplay; | ||||||
|  |      | ||||||
| public: | 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> |     template<class...Args> | ||||||
|     Canvas(Args &&...args): wxGLCanvas(std::forward<Args>(args)...) |     Canvas(Args &&...args): wxGLCanvas(std::forward<Args>(args)...) | ||||||
|     { |     { | ||||||
|         auto ctx = new wxGLContext(this); |         Bind(wxEVT_PAINT, [this](wxPaintEvent &) { | ||||||
|         if (!ctx || !ctx->IsOK()) { |             // This is required even though dc is not used otherwise.
 | ||||||
|             wxMessageBox("Could not create OpenGL context.", "Error", |             wxPaintDC dc(this); | ||||||
|                          wxOK | wxICON_ERROR); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         m_context.reset(ctx); |             // 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(); | ||||||
|  |              | ||||||
|  |             m_display->set_screen_size(ClientSize.x, ClientSize.y); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     shptr<Slic3r::GL::Display> get_display() const { return m_display; } | ||||||
|  |     void set_display(shptr<Slic3r::GL::Display> d) { m_display = d; } | ||||||
|  |      | ||||||
|  |     shptr<Slic3r::GL::CSGDisplay> get_ocsg_display() const { return m_ocsgdisplay; } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum EEvents { LCLK_U, RCLK_U, LCLK_D, RCLK_D, DDCLK, SCRL, MV }; | ||||||
|  | struct Event | ||||||
|  | { | ||||||
|  |     EEvents type; | ||||||
|  |     long    a, b; | ||||||
|  |     Event(EEvents t, long x = 0, long y = 0) : type{t}, a{x}, b{y} {} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class RecorderMouseInput: public MouseInput { | ||||||
|  |     std::vector<Event> m_events; | ||||||
|  |     bool m_recording = false, m_playing = false; | ||||||
|  |      | ||||||
|  | public: | ||||||
|  |     void left_click_down() override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(LCLK_D); | ||||||
|  |         if (!m_playing) MouseInput::left_click_down(); | ||||||
|  |     } | ||||||
|  |     void left_click_up() override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(LCLK_U); | ||||||
|  |         if (!m_playing) MouseInput::left_click_up(); | ||||||
|  |     } | ||||||
|  |     void right_click_down() override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(RCLK_D); | ||||||
|  |         if (!m_playing) MouseInput::right_click_down(); | ||||||
|  |     } | ||||||
|  |     void right_click_up() override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(RCLK_U); | ||||||
|  |         if (!m_playing) MouseInput::right_click_up(); | ||||||
|  |     } | ||||||
|  |     void double_click() override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(DDCLK); | ||||||
|  |         if (!m_playing) MouseInput::double_click(); | ||||||
|  |     } | ||||||
|  |     void scroll(long v, long d, WheelAxis wa) override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(SCRL, v, d); | ||||||
|  |         if (!m_playing) MouseInput::scroll(v, d, wa); | ||||||
|  |     } | ||||||
|  |     void move_to(long x, long y) override | ||||||
|  |     { | ||||||
|  |         if (m_recording) m_events.emplace_back(MV, x, y); | ||||||
|  |         if (!m_playing) MouseInput::move_to(x, y); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     void save(std::ostream &stream) | ||||||
|  |     { | ||||||
|  |         for (const Event &evt : m_events) | ||||||
|  |             stream << evt.type << " " << evt.a << " " << evt.b << std::endl; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     void load(std::istream &stream) | ||||||
|  |     { | ||||||
|  |         m_events.clear(); | ||||||
|  |         while (stream.good()) { | ||||||
|  |             int type; long a, b; | ||||||
|  |             stream >> type >> a >> b; | ||||||
|  |             m_events.emplace_back(EEvents(type), a, b); | ||||||
|  |         } | ||||||
|  |     }     | ||||||
|  |      | ||||||
|  |     void record(bool r) { m_recording = r; if (r) m_events.clear(); } | ||||||
|  |      | ||||||
|  |     void play() | ||||||
|  |     { | ||||||
|  |         m_playing = true; | ||||||
|  |         for (const Event &evt : m_events) { | ||||||
|  |             switch (evt.type) { | ||||||
|  |             case LCLK_U: MouseInput::left_click_up(); break; | ||||||
|  |             case LCLK_D: MouseInput::left_click_down(); break; | ||||||
|  |             case RCLK_U: MouseInput::right_click_up(); break; | ||||||
|  |             case RCLK_D: MouseInput::right_click_down(); break; | ||||||
|  |             case DDCLK:  MouseInput::double_click(); break; | ||||||
|  |             case SCRL:   MouseInput::scroll(evt.a, evt.b, WheelAxis::waVertical); break; | ||||||
|  |             case MV:     MouseInput::move_to(evt.a, evt.b); break; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             wxSafeYield(); | ||||||
|  |         } | ||||||
|  |         m_playing = false; | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -63,12 +188,14 @@ class MyFrame: public wxFrame | ||||||
|     shptr<Controller> m_ctl;      // Controller
 |     shptr<Controller> m_ctl;      // Controller
 | ||||||
| 
 | 
 | ||||||
|     shptr<Slic3r::GUI::ProgressStatusBar> m_stbar; |     shptr<Slic3r::GUI::ProgressStatusBar> m_stbar; | ||||||
|     uqptr<Slic3r::GUI::Job> m_ui_job; |      | ||||||
|  |     RecorderMouseInput m_mouse; | ||||||
|      |      | ||||||
|     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} | ||||||
|  | @ -78,8 +205,9 @@ class MyFrame: public wxFrame | ||||||
| 
 | 
 | ||||||
|         void process() override; |         void process() override; | ||||||
|          |          | ||||||
|     protected: |         const std::string & get_project_fname() const { return m_fname; } | ||||||
|          |          | ||||||
|  |     protected: | ||||||
|         void finalize() override  |         void finalize() override  | ||||||
|         { |         { | ||||||
|             m_parent->m_scene->set_print(std::move(m_print)); |             m_parent->m_scene->set_print(std::move(m_print)); | ||||||
|  | @ -88,55 +216,110 @@ class MyFrame: public wxFrame | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|      |      | ||||||
|  |     uqptr<SLAJob> m_ui_job; | ||||||
|  |      | ||||||
|  |     double m_fps_avg = 0.; | ||||||
|  |      | ||||||
| public: | public: | ||||||
|     MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); |     MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, const Slic3r::GL::CSGSettings &settings); | ||||||
|      |      | ||||||
| private: |     void load_model(const std::string &fname) { | ||||||
|      |         m_ui_job = std::make_unique<SLAJob>(this, fname); | ||||||
|     void bind_canvas_events_to_controller(); |         m_ui_job->start(); | ||||||
|      |  | ||||||
|     void OnExit(wxCommandEvent& /*event*/)  |  | ||||||
|     { |  | ||||||
|         RemoveChild(m_canvas.get()); |  | ||||||
|         m_canvas->Destroy(); |  | ||||||
|         Close( true ); |  | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     void OnOpen(wxCommandEvent &/*evt*/) |     void play_back_mouse(const std::string &events_fname) | ||||||
|     { |     { | ||||||
|         wxFileDialog dlg(this, "Select project file",  |         std::fstream stream(events_fname, std::fstream::in); | ||||||
|                          wxEmptyString, wxEmptyString, "*.3mf"); |  | ||||||
| 
 | 
 | ||||||
|         if (dlg.ShowModal() == wxID_OK) |         if (stream.good()) { | ||||||
|         { |             std::string model_name; | ||||||
|             m_ui_job = std::make_unique<SLAJob>(this, dlg.GetPath().ToStdString()); |             std::getline(stream, model_name); | ||||||
|             m_ui_job->start(); |             load_model(model_name); | ||||||
|  |              | ||||||
|  |             int w, h; | ||||||
|  |             stream >> w >> h; | ||||||
|  |             SetSize(w, h); | ||||||
|  |              | ||||||
|  |             m_mouse.load(stream); | ||||||
|  |             m_mouse.play(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     void OnShown(wxShowEvent&) |     Canvas * canvas() { return m_canvas.get(); } | ||||||
|     { |     const Canvas * canvas() const { return m_canvas.get(); } | ||||||
|         const wxSize ClientSize = GetClientSize(); |  | ||||||
|         m_canvas->set_active(ClientSize.x, ClientSize.y);  |  | ||||||
|      |      | ||||||
|         m_canvas->set_screen_size(ClientSize.x, ClientSize.y); |     void bind_canvas_events(MouseInput &msinput); | ||||||
|         m_canvas->repaint(); |  | ||||||
|      |      | ||||||
|         // Do the repaint continuously
 |     double get_fps_average() const { return m_fps_avg; } | ||||||
|         Bind(wxEVT_IDLE, [this](wxIdleEvent &evt) { |  | ||||||
|             m_canvas->repaint(); |  | ||||||
|             evt.RequestMore(); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const std::vector<wxString> CSG_ALGS  = {"Auto", "Goldfeather", "SCS"}; | ||||||
|  | static const std::vector<wxString> CSG_DEPTH = {"Off", "OcclusionQuery", "On"}; | ||||||
|  | static const std::vector<wxString> CSG_OPT   = { "Default", "ForceOn", "On", "Off" }; | ||||||
|  | 
 | ||||||
| class App : public wxApp { | class App : public wxApp { | ||||||
|     MyFrame *m_frame; |     MyFrame *m_frame = nullptr; | ||||||
|  |      | ||||||
| public: | public: | ||||||
|     bool OnInit() override { |     bool OnInit() override { | ||||||
|         m_frame = new MyFrame("PrusaSlicer OpenCSG Demo", wxDefaultPosition, wxSize(1024, 768)); |  | ||||||
|          |          | ||||||
|         m_frame->Show( true ); |         wxCmdLineParser parser(argc, argv); | ||||||
|  |          | ||||||
|  |         parser.AddOption("p", "play", "play back file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); | ||||||
|  |         parser.AddOption("a", "algorithm", "OpenCSG algorithm [Auto|Goldfeather|SCS]", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); | ||||||
|  |         parser.AddOption("d", "depth", "OpenCSG depth strategy [Off|OcclusionQuery|On]", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); | ||||||
|  |         parser.AddOption("o", "optimization", "OpenCSG optimization strategy [Default|ForceOn|On|Off]", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); | ||||||
|  |         parser.AddOption("c", "convexity", "OpenCSG convexity parameter for generic meshes", wxCMD_LINE_VAL_NUMBER, wxCMD_LINE_PARAM_OPTIONAL); | ||||||
|  |         parser.AddSwitch("", "disable-csg", "Disable csg rendering", wxCMD_LINE_PARAM_OPTIONAL); | ||||||
|  |          | ||||||
|  |         parser.Parse(); | ||||||
|  |          | ||||||
|  |         wxString fname; | ||||||
|  |         bool is_play = parser.Found("play", &fname); | ||||||
|  |          | ||||||
|  |         wxString alg; | ||||||
|  |         parser.Found("algorithm", &alg); | ||||||
|  |          | ||||||
|  |         wxString depth; | ||||||
|  |         parser.Found("depth", &depth); | ||||||
|  |          | ||||||
|  |         wxString opt; | ||||||
|  |         parser.Found("optimization", &opt); | ||||||
|  |          | ||||||
|  |         long convexity = 1; | ||||||
|  |         parser.Found("convexity", &convexity); | ||||||
|  |          | ||||||
|  |         bool csg_off = parser.Found("disable-csg"); | ||||||
|  |          | ||||||
|  |         auto get_idx = [](const wxString &a, const std::vector<wxString> &v) { | ||||||
|  |             auto it = std::find(v.begin(), v.end(), a.ToStdString()); | ||||||
|  |             return it - v.begin(); | ||||||
|  |         }; | ||||||
|  |          | ||||||
|  |         Slic3r::GL::CSGSettings settings; | ||||||
|  |          | ||||||
|  |         if (auto a = get_idx(alg, CSG_ALGS) < OpenCSG::AlgorithmUnused)  | ||||||
|  |             settings.set_algo(OpenCSG::Algorithm(a)); | ||||||
|  |          | ||||||
|  |         if (auto a = get_idx(depth, CSG_DEPTH) < OpenCSG::DepthComplexityAlgorithmUnused)  | ||||||
|  |             settings.set_depth_algo(OpenCSG::DepthComplexityAlgorithm(a)); | ||||||
|  |          | ||||||
|  |         if (auto a = get_idx(opt, CSG_OPT) < OpenCSG::OptimizationUnused)  | ||||||
|  |             settings.set_optimization(OpenCSG::Optimization(a)); | ||||||
|  |          | ||||||
|  |         settings.set_convexity(unsigned(convexity)); | ||||||
|  |         settings.enable_csg(!csg_off); | ||||||
|  |          | ||||||
|  |         m_frame = new MyFrame("PrusaSlicer OpenCSG Demo", wxDefaultPosition, wxSize(1024, 768), settings); | ||||||
|  |          | ||||||
|  |         if (is_play) { | ||||||
|  |             m_frame->Show( true ); | ||||||
|  |             m_frame->play_back_mouse(fname.ToStdString()); | ||||||
|  |             m_frame->Close( true ); | ||||||
|  |             std::cout << m_frame->get_fps_average() << std::endl; | ||||||
|  |              | ||||||
|  |         } else m_frame->Show( true ); | ||||||
|          |          | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  | @ -144,7 +327,8 @@ public: | ||||||
| 
 | 
 | ||||||
| wxIMPLEMENT_APP(App); | wxIMPLEMENT_APP(App); | ||||||
| 
 | 
 | ||||||
| MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size,  | ||||||
|  |                  const Slic3r::GL::CSGSettings &settings): | ||||||
|     wxFrame(nullptr, wxID_ANY, title, pos, size) |     wxFrame(nullptr, wxID_ANY, title, pos, size) | ||||||
| { | { | ||||||
|     wxMenu *menuFile = new wxMenu; |     wxMenu *menuFile = new wxMenu; | ||||||
|  | @ -169,7 +353,7 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|      // glReadPixels would not return the alpha channel on NVIDIA if
 |      // glReadPixels would not return the alpha channel on NVIDIA if
 | ||||||
|      // not requested when the GL context is created.
 |      // not requested when the GL context is created.
 | ||||||
|      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_scene = std::make_shared<Scene>(); | ||||||
|     m_ctl = std::make_shared<Controller>(); |     m_ctl = std::make_shared<Controller>(); | ||||||
|  | @ -178,9 +362,13 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|     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); |      | ||||||
|  |     m_canvas->get_ocsg_display()->apply_csgsettings(settings); | ||||||
|  |      | ||||||
|  |     m_ctl->add_display(m_canvas->get_display()); | ||||||
| 
 | 
 | ||||||
|     wxPanel *control_panel = new wxPanel(this); |     wxPanel *control_panel = new wxPanel(this); | ||||||
|  | 
 | ||||||
|     auto controlsizer = new wxBoxSizer(wxHORIZONTAL); |     auto controlsizer = new wxBoxSizer(wxHORIZONTAL); | ||||||
|     auto slider_sizer = new wxBoxSizer(wxVERTICAL); |     auto slider_sizer = new wxBoxSizer(wxVERTICAL); | ||||||
|     auto console_sizer = new wxBoxSizer(wxVERTICAL); |     auto console_sizer = new wxBoxSizer(wxVERTICAL); | ||||||
|  | @ -198,7 +386,7 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|     console_sizer->Add(csg_toggle, 0, wxALL | wxEXPAND, 5); |     console_sizer->Add(csg_toggle, 0, wxALL | wxEXPAND, 5); | ||||||
|      |      | ||||||
|     auto add_combobox = [control_panel, console_sizer] |     auto add_combobox = [control_panel, console_sizer] | ||||||
|             (const wxString &label, std::vector<wxString> &&list) |             (const wxString &label, const std::vector<wxString> &list) | ||||||
|     { |     { | ||||||
|         auto widget = new wxComboBox(control_panel, wxID_ANY, list[0], |         auto widget = new wxComboBox(control_panel, wxID_ANY, list[0], | ||||||
|                 wxDefaultPosition, wxDefaultSize, |                 wxDefaultPosition, wxDefaultSize, | ||||||
|  | @ -231,11 +419,21 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|      |      | ||||||
|     auto convexity_spin = add_spinctl("Convexity", CSGSettings::DEFAULT_CONVEXITY, 0, 100); |     auto convexity_spin = add_spinctl("Convexity", CSGSettings::DEFAULT_CONVEXITY, 0, 100); | ||||||
|      |      | ||||||
|     auto alg_select = add_combobox("Algorithm", {"Auto", "Goldfeather", "SCS"}); |     auto alg_select = add_combobox("Algorithm", CSG_ALGS); | ||||||
|     auto depth_select = add_combobox("Depth Complexity", {"Off", "OcclusionQuery", "On"}); |     auto depth_select = add_combobox("Depth Complexity", CSG_DEPTH); | ||||||
|     auto optimization_select = add_combobox("Optimization", { "Default", "ForceOn", "On", "Off" }); |     auto optimization_select = add_combobox("Optimization", CSG_OPT); | ||||||
|     depth_select->Disable(); |     depth_select->Disable(); | ||||||
|      |      | ||||||
|  |     auto fpstext = new wxStaticText(control_panel, wxID_ANY, ""); | ||||||
|  |     console_sizer->Add(fpstext, 0, wxALL, 5); | ||||||
|  |     m_canvas->get_ocsg_display()->get_fps_counter().add_listener([this, fpstext](double fps) { | ||||||
|  |         fpstext->SetLabel(wxString::Format("fps: %.2f", fps) ); | ||||||
|  |         m_fps_avg = 0.9 * m_fps_avg + 0.1 * fps; | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     auto record_btn = new wxToggleButton(control_panel, wxID_ANY, "Record"); | ||||||
|  |     console_sizer->Add(record_btn, 0, wxALL | wxEXPAND, 5); | ||||||
|  |      | ||||||
|     controlsizer->Add(slider_sizer, 0, wxEXPAND); |     controlsizer->Add(slider_sizer, 0, wxEXPAND); | ||||||
|     controlsizer->Add(console_sizer, 1, wxEXPAND); |     controlsizer->Add(console_sizer, 1, wxEXPAND); | ||||||
|      |      | ||||||
|  | @ -246,9 +444,33 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|     sizer->Add(control_panel, 0, wxEXPAND); |     sizer->Add(control_panel, 0, wxEXPAND); | ||||||
|     SetSizer(sizer); |     SetSizer(sizer); | ||||||
|      |      | ||||||
|     Bind(wxEVT_MENU, &MyFrame::OnOpen, this, wxID_OPEN); |     if (settings.get_algo() > 0) depth_select->Enable(true); | ||||||
|     Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT); |     alg_select->SetSelection(settings.get_algo()); | ||||||
|     Bind(wxEVT_SHOW, &MyFrame::OnShown, this, GetId()); |     depth_select->SetSelection(settings.get_depth_algo()); | ||||||
|  |     optimization_select->SetSelection(settings.get_optimization()); | ||||||
|  |     convexity_spin->SetValue(int(settings.get_convexity())); | ||||||
|  |     csg_toggle->SetValue(settings.is_enabled()); | ||||||
|  |      | ||||||
|  |     Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent &){ | ||||||
|  |         RemoveChild(m_canvas.get()); | ||||||
|  |         m_canvas.reset(); | ||||||
|  |         Destroy(); | ||||||
|  |     });     | ||||||
|  |      | ||||||
|  |     Bind(wxEVT_MENU, [this](wxCommandEvent &) { | ||||||
|  |         wxFileDialog dlg(this, "Select project file",  wxEmptyString, | ||||||
|  |                          wxEmptyString, "*.3mf", wxFD_OPEN|wxFD_FILE_MUST_EXIST); | ||||||
|  | 
 | ||||||
|  |         if (dlg.ShowModal() == wxID_OK) load_model(dlg.GetPath().ToStdString()); | ||||||
|  |     }, wxID_OPEN); | ||||||
|  |      | ||||||
|  |     Bind(wxEVT_MENU, [this](wxCommandEvent &) { Close(true); }, wxID_EXIT); | ||||||
|  |      | ||||||
|  |     Bind(wxEVT_SHOW, [this, ms_toggle](wxShowEvent &) { | ||||||
|  |         const wxSize ClientSize = GetClientSize(); | ||||||
|  |         m_canvas->get_display()->set_active(ClientSize.x, ClientSize.y); | ||||||
|  |         enable_multisampling(ms_toggle->GetValue()); | ||||||
|  |     }); | ||||||
|      |      | ||||||
|     Bind(wxEVT_SLIDER, [this, slider](wxCommandEvent &) { |     Bind(wxEVT_SLIDER, [this, slider](wxCommandEvent &) { | ||||||
|         m_ctl->move_clip_plane(double(slider->GetValue())); |         m_ctl->move_clip_plane(double(slider->GetValue())); | ||||||
|  | @ -256,13 +478,13 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|      |      | ||||||
|     ms_toggle->Bind(wxEVT_TOGGLEBUTTON, [this, ms_toggle](wxCommandEvent &){ |     ms_toggle->Bind(wxEVT_TOGGLEBUTTON, [this, ms_toggle](wxCommandEvent &){ | ||||||
|         enable_multisampling(ms_toggle->GetValue()); |         enable_multisampling(ms_toggle->GetValue()); | ||||||
|         m_canvas->repaint(); |         m_canvas->get_display()->repaint(); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     csg_toggle->Bind(wxEVT_TOGGLEBUTTON, [this, csg_toggle](wxCommandEvent &){ |     csg_toggle->Bind(wxEVT_TOGGLEBUTTON, [this, csg_toggle](wxCommandEvent &){ | ||||||
|         CSGSettings settings = m_canvas->get_csgsettings(); |         CSGSettings settings = m_canvas->get_ocsg_display()->get_csgsettings(); | ||||||
|         settings.enable_csg(csg_toggle->GetValue()); |         settings.enable_csg(csg_toggle->GetValue()); | ||||||
|         m_canvas->apply_csgsettings(settings); |         m_canvas->get_ocsg_display()->apply_csgsettings(settings); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     alg_select->Bind(wxEVT_COMBOBOX, |     alg_select->Bind(wxEVT_COMBOBOX, | ||||||
|  | @ -270,89 +492,110 @@ MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): | ||||||
|     { |     { | ||||||
|         int sel = alg_select->GetSelection(); |         int sel = alg_select->GetSelection(); | ||||||
|         depth_select->Enable(sel > 0); |         depth_select->Enable(sel > 0); | ||||||
|         CSGSettings settings = m_canvas->get_csgsettings(); |         CSGSettings settings = m_canvas->get_ocsg_display()->get_csgsettings(); | ||||||
|         settings.set_algo(OpenCSG::Algorithm(sel)); |         settings.set_algo(OpenCSG::Algorithm(sel)); | ||||||
|         m_canvas->apply_csgsettings(settings); |         m_canvas->get_ocsg_display()->apply_csgsettings(settings); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     depth_select->Bind(wxEVT_COMBOBOX, [this, depth_select](wxCommandEvent &) { |     depth_select->Bind(wxEVT_COMBOBOX, [this, depth_select](wxCommandEvent &) { | ||||||
|         int sel = depth_select->GetSelection(); |         int sel = depth_select->GetSelection(); | ||||||
|         CSGSettings settings = m_canvas->get_csgsettings(); |         CSGSettings settings = m_canvas->get_ocsg_display()->get_csgsettings(); | ||||||
|         settings.set_depth_algo(OpenCSG::DepthComplexityAlgorithm(sel)); |         settings.set_depth_algo(OpenCSG::DepthComplexityAlgorithm(sel)); | ||||||
|         m_canvas->apply_csgsettings(settings); |         m_canvas->get_ocsg_display()->apply_csgsettings(settings); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     optimization_select->Bind(wxEVT_COMBOBOX, |     optimization_select->Bind(wxEVT_COMBOBOX, | ||||||
|                               [this, optimization_select](wxCommandEvent &) { |                               [this, optimization_select](wxCommandEvent &) { | ||||||
|         int sel = optimization_select->GetSelection(); |         int sel = optimization_select->GetSelection(); | ||||||
|         CSGSettings settings = m_canvas->get_csgsettings(); |         CSGSettings settings = m_canvas->get_ocsg_display()->get_csgsettings(); | ||||||
|         settings.set_optimization(OpenCSG::Optimization(sel)); |         settings.set_optimization(OpenCSG::Optimization(sel)); | ||||||
|         m_canvas->apply_csgsettings(settings); |         m_canvas->get_ocsg_display()->apply_csgsettings(settings); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     convexity_spin->Bind(wxEVT_SPINCTRL, [this, convexity_spin](wxSpinEvent &) { |     convexity_spin->Bind(wxEVT_SPINCTRL, [this, convexity_spin](wxSpinEvent &) { | ||||||
|         CSGSettings settings = m_canvas->get_csgsettings(); |         CSGSettings settings = m_canvas->get_ocsg_display()->get_csgsettings(); | ||||||
|         int c = convexity_spin->GetValue(); |         int c = convexity_spin->GetValue(); | ||||||
|          |          | ||||||
|         if (c > 0) { |         if (c > 0) { | ||||||
|             settings.set_convexity(unsigned(c)); |             settings.set_convexity(unsigned(c)); | ||||||
|             m_canvas->apply_csgsettings(settings); |             m_canvas->get_ocsg_display()->apply_csgsettings(settings); | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     bind_canvas_events_to_controller(); |     record_btn->Bind(wxEVT_TOGGLEBUTTON, [this, record_btn](wxCommandEvent &) { | ||||||
|  |         if (!m_ui_job) { | ||||||
|  |             m_stbar->set_status_text("No project loaded!"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         if (record_btn->GetValue()) { | ||||||
|  |             if (auto c = m_canvas->get_display()->camera()) reset(*c); | ||||||
|  |             m_ctl->on_scene_updated(*m_scene); | ||||||
|  |             m_mouse.record(true); | ||||||
|  |         } else { | ||||||
|  |             m_mouse.record(false); | ||||||
|  |             wxFileDialog dlg(this, "Select output file", | ||||||
|  |                              wxEmptyString, wxEmptyString, "*.events", | ||||||
|  |                              wxFD_SAVE|wxFD_OVERWRITE_PROMPT); | ||||||
|  |              | ||||||
|  |             if (dlg.ShowModal() == wxID_OK) { | ||||||
|  |                 std::fstream stream(dlg.GetPath().ToStdString(), | ||||||
|  |                                     std::fstream::out); | ||||||
|  |                  | ||||||
|  |                 if (stream.good()) { | ||||||
|  |                     stream << m_ui_job->get_project_fname() << "\n"; | ||||||
|  |                     wxSize winsize = GetSize(); | ||||||
|  |                     stream << winsize.x << " " << winsize.y << "\n"; | ||||||
|  |                     m_mouse.save(stream); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     // Do the repaint continuously
 | ||||||
|  |     m_canvas->Bind(wxEVT_IDLE, [this](wxIdleEvent &evt) { | ||||||
|  |         if (m_canvas->IsShown()) m_canvas->get_display()->repaint(); | ||||||
|  |         evt.RequestMore(); | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     bind_canvas_events(m_mouse); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MyFrame::bind_canvas_events_to_controller() | void MyFrame::bind_canvas_events(MouseInput &ms) | ||||||
| { | { | ||||||
|     m_canvas->Bind(wxEVT_MOUSEWHEEL, [this](wxMouseEvent &evt) { |     m_canvas->Bind(wxEVT_MOUSEWHEEL, [&ms](wxMouseEvent &evt) { | ||||||
|         m_ctl->on_scroll(evt.GetWheelRotation(), evt.GetWheelDelta(), |         ms.scroll(evt.GetWheelRotation(), evt.GetWheelDelta(), | ||||||
|                          evt.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL ? |                   evt.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL ? | ||||||
|                              Slic3r::GL::MouseInput::waVertical : |                       Slic3r::GL::MouseInput::waVertical : | ||||||
|                              Slic3r::GL::MouseInput::waHorizontal); |                       Slic3r::GL::MouseInput::waHorizontal); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     m_canvas->Bind(wxEVT_MOTION, [this](wxMouseEvent &evt) { |     m_canvas->Bind(wxEVT_MOTION, [&ms](wxMouseEvent &evt) { | ||||||
|         m_ctl->on_moved_to(evt.GetPosition().x, evt.GetPosition().y); |         ms.move_to(evt.GetPosition().x, evt.GetPosition().y); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     m_canvas->Bind(wxEVT_RIGHT_DOWN, [this](wxMouseEvent & /*evt*/) { |     m_canvas->Bind(wxEVT_RIGHT_DOWN, [&ms](wxMouseEvent & /*evt*/) { | ||||||
|         m_ctl->on_right_click_down(); |         ms.right_click_down(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     m_canvas->Bind(wxEVT_RIGHT_UP, [this](wxMouseEvent & /*evt*/) { |     m_canvas->Bind(wxEVT_RIGHT_UP, [&ms](wxMouseEvent & /*evt*/) { | ||||||
|         m_ctl->on_right_click_up(); |         ms.right_click_up(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     m_canvas->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent & /*evt*/) { |     m_canvas->Bind(wxEVT_LEFT_DOWN, [&ms](wxMouseEvent & /*evt*/) { | ||||||
|         m_ctl->on_left_click_down(); |         ms.left_click_down(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     m_canvas->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent & /*evt*/) { |     m_canvas->Bind(wxEVT_LEFT_UP, [&ms](wxMouseEvent & /*evt*/) { | ||||||
|         m_ctl->on_left_click_up(); |         ms.left_click_up(); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     m_canvas->Bind(wxEVT_PAINT, [this](wxPaintEvent &) { |     ms.add_listener(m_ctl); | ||||||
|         // 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()  | void MyFrame::SLAJob::process()  | ||||||
| { | { | ||||||
|     using Status = Slic3r::PrintBase::SlicingStatus; |     using SlStatus = Slic3r::PrintBase::SlicingStatus; | ||||||
|      |      | ||||||
|     Slic3r::DynamicPrintConfig cfg; |     Slic3r::DynamicPrintConfig cfg; | ||||||
|     auto model = Slic3r::Model::read_from_file(m_fname, &cfg); |     auto model = Slic3r::Model::read_from_file(m_fname, &cfg); | ||||||
|  | @ -364,9 +607,15 @@ void MyFrame::SLAJob::process() | ||||||
|     params.to_object_step = Slic3r::slaposHollowing; |     params.to_object_step = Slic3r::slaposHollowing; | ||||||
|     m_print->set_task(params); |     m_print->set_task(params); | ||||||
|      |      | ||||||
|     m_print->set_status_callback([this](const Status &status) { |     m_print->set_status_callback([this](const SlStatus &status) { | ||||||
|         update_status(status.percent, status.text); |         update_status(status.percent, status.text); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     m_print->process(); |     try { | ||||||
|  |         m_print->process(); | ||||||
|  |     } catch(std::exception &e) { | ||||||
|  |         update_status(0, wxString("Exception during processing: ") + e.what()); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | //int main() {}
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tamasmeszaros
						tamasmeszaros