mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-20 07:11:12 -06:00 
			
		
		
		
	OpenGL to c++ 1st installment - WIP
This commit is contained in:
		
							parent
							
								
									8eb9ddc2eb
								
							
						
					
					
						commit
						5024fc4be7
					
				
					 14 changed files with 1015 additions and 56 deletions
				
			
		|  | @ -16,7 +16,10 @@ use strict; | ||||||
| use warnings; | use warnings; | ||||||
| 
 | 
 | ||||||
| use Wx qw(wxTheApp :timer :bitmap :icon :dialog); | use Wx qw(wxTheApp :timer :bitmap :icon :dialog); | ||||||
| use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER); | #============================================================================================================================== | ||||||
|  | use Wx::Event qw(EVT_PAINT EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER); | ||||||
|  | #use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER); | ||||||
|  | #============================================================================================================================== | ||||||
| # must load OpenGL *before* Wx::GLCanvas | # must load OpenGL *before* Wx::GLCanvas | ||||||
| use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants); | use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants); | ||||||
| use base qw(Wx::GLCanvas Class::Accessor); | use base qw(Wx::GLCanvas Class::Accessor); | ||||||
|  | @ -30,7 +33,8 @@ use Slic3r::Geometry qw(PI); | ||||||
| # _dirty: boolean flag indicating, that the screen has to be redrawn on EVT_IDLE. | # _dirty: boolean flag indicating, that the screen has to be redrawn on EVT_IDLE. | ||||||
| # volumes: reference to vector of Slic3r::GUI::3DScene::Volume. | # volumes: reference to vector of Slic3r::GUI::3DScene::Volume. | ||||||
| # _camera_type: 'perspective' or 'ortho' | # _camera_type: 'perspective' or 'ortho' | ||||||
| __PACKAGE__->mk_accessors( qw(_quat _dirty init | #============================================================================================================================== | ||||||
|  | __PACKAGE__->mk_accessors( qw(_quat init | ||||||
|                               enable_picking |                               enable_picking | ||||||
|                               enable_moving |                               enable_moving | ||||||
|                               use_plain_shader |                               use_plain_shader | ||||||
|  | @ -73,6 +77,50 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init | ||||||
|                               _mouse_dragging |                               _mouse_dragging | ||||||
|                                                              |                                                              | ||||||
|                               ) ); |                               ) ); | ||||||
|  | #__PACKAGE__->mk_accessors( qw(_quat _dirty init | ||||||
|  | #                              enable_picking | ||||||
|  | #                              enable_moving | ||||||
|  | #                              use_plain_shader | ||||||
|  | #                              on_viewport_changed | ||||||
|  | #                              on_hover | ||||||
|  | #                              on_select | ||||||
|  | #                              on_double_click | ||||||
|  | #                              on_right_click | ||||||
|  | #                              on_move | ||||||
|  | #                              on_model_update | ||||||
|  | #                              volumes | ||||||
|  | #                              _sphi _stheta | ||||||
|  | #                              cutting_plane_z | ||||||
|  | #                              cut_lines_vertices | ||||||
|  | #                              bed_shape | ||||||
|  | #                              bed_triangles | ||||||
|  | #                              bed_grid_lines | ||||||
|  | #                              bed_polygon | ||||||
|  | #                              background | ||||||
|  | #                              origin | ||||||
|  | #                              _mouse_pos | ||||||
|  | #                              _hover_volume_idx | ||||||
|  | # | ||||||
|  | #                              _drag_volume_idx | ||||||
|  | #                              _drag_start_pos | ||||||
|  | #                              _drag_volume_center_offset | ||||||
|  | #                              _drag_start_xy | ||||||
|  | #                              _dragged | ||||||
|  | # | ||||||
|  | #                              _layer_height_edited | ||||||
|  | # | ||||||
|  | #                              _camera_type | ||||||
|  | #                              _camera_target | ||||||
|  | #                              _camera_distance | ||||||
|  | #                              _zoom | ||||||
|  | #                               | ||||||
|  | #                              _legend_enabled | ||||||
|  | #                              _warning_enabled | ||||||
|  | #                              _apply_zoom_to_volumes_filter | ||||||
|  | #                              _mouse_dragging | ||||||
|  | #                                                             | ||||||
|  | #                              ) ); | ||||||
|  | #============================================================================================================================== | ||||||
|                                |                                | ||||||
| use constant TRACKBALLSIZE  => 0.8; | use constant TRACKBALLSIZE  => 0.8; | ||||||
| use constant TURNTABLE_MODE => 1; | use constant TURNTABLE_MODE => 1; | ||||||
|  | @ -130,12 +178,21 @@ sub new { | ||||||
|     # we request a depth buffer explicitely because it looks like it's not created by  |     # we request a depth buffer explicitely because it looks like it's not created by  | ||||||
|     # default on Linux, causing transparency issues |     # default on Linux, causing transparency issues | ||||||
|     my $self = $class->SUPER::new($parent, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, 0, "", $attrib); |     my $self = $class->SUPER::new($parent, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, 0, "", $attrib); | ||||||
|     if (Wx::wxVERSION >= 3.000003) { | #============================================================================================================================== | ||||||
|         # Wx 3.0.3 contains an ugly hack to support some advanced OpenGL attributes through the attribute list. | #    if (Wx::wxVERSION >= 3.000003) { | ||||||
|         # The attribute list is transferred between the wxGLCanvas and wxGLContext constructors using a single static array s_wglContextAttribs. | #        # Wx 3.0.3 contains an ugly hack to support some advanced OpenGL attributes through the attribute list. | ||||||
|         # Immediatelly force creation of the OpenGL context to consume the static variable s_wglContextAttribs. | #        # The attribute list is transferred between the wxGLCanvas and wxGLContext constructors using a single static array s_wglContextAttribs. | ||||||
|         $self->GetContext(); | #        # Immediatelly force creation of the OpenGL context to consume the static variable s_wglContextAttribs. | ||||||
|     } | #        $self->GetContext(); | ||||||
|  | #    } | ||||||
|  | #============================================================================================================================== | ||||||
|  | 
 | ||||||
|  | #============================================================================================================================== | ||||||
|  |     Slic3r::GUI::_3DScene::add_canvas($self, $self->GetContext); | ||||||
|  | #    my $context = $self->GetContext; | ||||||
|  | #    $self->SetCurrent($context); | ||||||
|  | #    Slic3r::GUI::_3DScene::add_canvas($self, $context); | ||||||
|  | #==============================================================================================================================     | ||||||
|      |      | ||||||
|     $self->{can_multisample} = $can_multisample; |     $self->{can_multisample} = $can_multisample; | ||||||
|     $self->background(1); |     $self->background(1); | ||||||
|  | @ -171,10 +228,16 @@ sub new { | ||||||
|         my $dc = Wx::PaintDC->new($self); |         my $dc = Wx::PaintDC->new($self); | ||||||
|         $self->Render($dc); |         $self->Render($dc); | ||||||
|     }); |     }); | ||||||
|     EVT_SIZE($self, sub { $self->_dirty(1) }); | #=======================================================================================================================     | ||||||
|  | #    EVT_SIZE($self, sub { $self->_dirty(1) }); | ||||||
|  | #=======================================================================================================================     | ||||||
|     EVT_IDLE($self, sub { |     EVT_IDLE($self, sub { | ||||||
|         return unless $self->_dirty; | #============================================================================================================================== | ||||||
|         return if !$self->IsShownOnScreen; |         return unless Slic3r::GUI::_3DScene::is_dirty($self); | ||||||
|  |         return unless Slic3r::GUI::_3DScene::is_shown_on_screen($self); | ||||||
|  | #        return unless $self->_dirty; | ||||||
|  | #        return if !$self->IsShownOnScreen; | ||||||
|  | #============================================================================================================================== | ||||||
|         $self->Resize( $self->GetSizeWH ); |         $self->Resize( $self->GetSizeWH ); | ||||||
|         $self->Refresh; |         $self->Refresh; | ||||||
|     }); |     }); | ||||||
|  | @ -237,6 +300,9 @@ sub Destroy { | ||||||
|     my ($self) = @_; |     my ($self) = @_; | ||||||
|     $self->{layer_height_edit_timer}->Stop; |     $self->{layer_height_edit_timer}->Stop; | ||||||
|     $self->DestroyGL; |     $self->DestroyGL; | ||||||
|  | #============================================================================================================================== | ||||||
|  |     Slic3r::GUI::_3DScene::remove_canvas($self);     | ||||||
|  | #============================================================================================================================== | ||||||
|     return $self->SUPER::Destroy; |     return $self->SUPER::Destroy; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -621,7 +687,10 @@ sub mouse_wheel_event { | ||||||
| #    ) if 0; | #    ) if 0; | ||||||
| 
 | 
 | ||||||
|     $self->on_viewport_changed->() if $self->on_viewport_changed; |     $self->on_viewport_changed->() if $self->on_viewport_changed; | ||||||
|     $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; | #============================================================================================================================== | ||||||
|  |     $self->Resize($self->GetSizeWH) if Slic3r::GUI::_3DScene::is_shown_on_screen($self); | ||||||
|  | #    $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; | ||||||
|  | #============================================================================================================================== | ||||||
|     $self->Refresh; |     $self->Refresh; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -633,7 +702,10 @@ sub reset_objects { | ||||||
|         $self->volumes->release_geometry; |         $self->volumes->release_geometry; | ||||||
|     } |     } | ||||||
|     $self->volumes->erase; |     $self->volumes->erase; | ||||||
|     $self->_dirty(1); | #============================================================================================================================== | ||||||
|  |     Slic3r::GUI::_3DScene::set_dirty($self, 1); | ||||||
|  | #    $self->_dirty(1); | ||||||
|  | #============================================================================================================================== | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| # Setup camera to view all objects. | # Setup camera to view all objects. | ||||||
|  | @ -645,7 +717,10 @@ sub set_viewport_from_scene { | ||||||
|     $self->_camera_target($scene->_camera_target); |     $self->_camera_target($scene->_camera_target); | ||||||
|     $self->_zoom($scene->_zoom); |     $self->_zoom($scene->_zoom); | ||||||
|     $self->_quat($scene->_quat); |     $self->_quat($scene->_quat); | ||||||
|     $self->_dirty(1); | #============================================================================================================================== | ||||||
|  |     Slic3r::GUI::_3DScene::set_dirty($self, 1); | ||||||
|  | #    $self->_dirty(1); | ||||||
|  | #============================================================================================================================== | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| # Set the camera to a default orientation, | # Set the camera to a default orientation, | ||||||
|  | @ -777,7 +852,10 @@ sub zoom_to_bounding_box { | ||||||
|         # center view around bounding box center |         # center view around bounding box center | ||||||
|         $self->_camera_target($bb->center); |         $self->_camera_target($bb->center); | ||||||
|         $self->on_viewport_changed->() if $self->on_viewport_changed; |         $self->on_viewport_changed->() if $self->on_viewport_changed; | ||||||
|         $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; | #============================================================================================================================== | ||||||
|  |         $self->Resize($self->GetSizeWH) if Slic3r::GUI::_3DScene::is_shown_on_screen($self); | ||||||
|  | #        $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; | ||||||
|  | #============================================================================================================================== | ||||||
|         $self->Refresh; |         $self->Refresh; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1071,38 +1149,46 @@ sub SetCurrent { | ||||||
| sub UseVBOs { | sub UseVBOs { | ||||||
|     my ($self) = @_; |     my ($self) = @_; | ||||||
| 
 | 
 | ||||||
|     if (! defined ($self->{use_VBOs})) { | #============================================================================================================================== | ||||||
|         my $use_legacy = wxTheApp->{app_config}->get('use_legacy_opengl'); |  | ||||||
|         if ($use_legacy eq '1') { |  | ||||||
|             # Disable OpenGL 2.0 rendering. |  | ||||||
|             $self->{use_VBOs} = 0; |  | ||||||
|             # Don't enable the layer editing tool. |  | ||||||
|             $self->{layer_editing_enabled} = 0; |  | ||||||
|             # 2 means failed |  | ||||||
|             $self->{layer_editing_initialized} = 2; |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|         # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized |  | ||||||
|         # first when an OpenGL widget is shown for the first time. How ugly. |  | ||||||
|     return 0 if (! $self->init && $^O eq 'linux'); |     return 0 if (! $self->init && $^O eq 'linux'); | ||||||
|         # Don't use VBOs if anything fails. |     return Slic3r::GUI::_3DScene::use_VBOs(); | ||||||
|         $self->{use_VBOs} = 0; |          | ||||||
|         if ($self->GetContext) { | #    if (! defined ($self->{use_VBOs})) { | ||||||
|             $self->SetCurrent($self->GetContext); | #        my $use_legacy = wxTheApp->{app_config}->get('use_legacy_opengl'); | ||||||
|             Slic3r::GUI::_3DScene::_glew_init; | #        if ($use_legacy eq '1') { | ||||||
|             my @gl_version = split(/\./, glGetString(GL_VERSION)); | #            # Disable OpenGL 2.0 rendering. | ||||||
|             $self->{use_VBOs} = int($gl_version[0]) >= 2; | #            $self->{use_VBOs} = 0; | ||||||
|             # print "UseVBOs $self OpenGL major: $gl_version[0], minor: $gl_version[1]. Use VBOs: ", $self->{use_VBOs}, "\n"; | #            # Don't enable the layer editing tool. | ||||||
|         } | #            $self->{layer_editing_enabled} = 0; | ||||||
|     } | #            # 2 means failed | ||||||
|     return $self->{use_VBOs}; | #            $self->{layer_editing_initialized} = 2; | ||||||
|  | #            return 0; | ||||||
|  | #        } | ||||||
|  | #        # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized | ||||||
|  | #        # first when an OpenGL widget is shown for the first time. How ugly. | ||||||
|  | #        return 0 if (! $self->init && $^O eq 'linux'); | ||||||
|  | #        # Don't use VBOs if anything fails. | ||||||
|  | #        $self->{use_VBOs} = 0; | ||||||
|  | #        if ($self->GetContext) { | ||||||
|  | #            $self->SetCurrent($self->GetContext); | ||||||
|  | #            Slic3r::GUI::_3DScene::_glew_init; | ||||||
|  | #            my @gl_version = split(/\./, glGetString(GL_VERSION)); | ||||||
|  | #            $self->{use_VBOs} = int($gl_version[0]) >= 2; | ||||||
|  | #            # print "UseVBOs $self OpenGL major: $gl_version[0], minor: $gl_version[1]. Use VBOs: ", $self->{use_VBOs}, "\n"; | ||||||
|  | #        } | ||||||
|  | #    } | ||||||
|  | #    return $self->{use_VBOs}; | ||||||
|  | #============================================================================================================================== | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub Resize { | sub Resize { | ||||||
|     my ($self, $x, $y) = @_; |     my ($self, $x, $y) = @_; | ||||||
|   |   | ||||||
|     return unless $self->GetContext; |     return unless $self->GetContext; | ||||||
|     $self->_dirty(0); | #============================================================================================================================== | ||||||
|  |     Slic3r::GUI::_3DScene::set_dirty($self, 0); | ||||||
|  | #    $self->_dirty(0); | ||||||
|  | #============================================================================================================================== | ||||||
|      |      | ||||||
|     $self->SetCurrent($self->GetContext); |     $self->SetCurrent($self->GetContext); | ||||||
|     glViewport(0, 0, $x, $y); |     glViewport(0, 0, $x, $y); | ||||||
|  | @ -1148,6 +1234,10 @@ sub InitGL { | ||||||
|     return unless $self->GetContext; |     return unless $self->GetContext; | ||||||
|     $self->init(1); |     $self->init(1); | ||||||
| 
 | 
 | ||||||
|  | #============================================================================================================================== | ||||||
|  |     Slic3r::GUI::_3DScene::init_gl; | ||||||
|  | #============================================================================================================================== | ||||||
|  |      | ||||||
|     # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized |     # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized | ||||||
|     # first when an OpenGL widget is shown for the first time. How ugly. |     # first when an OpenGL widget is shown for the first time. How ugly. | ||||||
|     # In that case the volumes are wainting to be moved to Vertex Buffer Objects |     # In that case the volumes are wainting to be moved to Vertex Buffer Objects | ||||||
|  | @ -1236,7 +1326,10 @@ sub Render { | ||||||
|     my ($self, $dc) = @_; |     my ($self, $dc) = @_; | ||||||
|      |      | ||||||
|     # prevent calling SetCurrent() when window is not shown yet |     # prevent calling SetCurrent() when window is not shown yet | ||||||
|     return unless $self->IsShownOnScreen; | #============================================================================================================================== | ||||||
|  |     return unless Slic3r::GUI::_3DScene::is_shown_on_screen($self); | ||||||
|  | #    return unless $self->IsShownOnScreen; | ||||||
|  | #============================================================================================================================== | ||||||
|     return unless my $context = $self->GetContext; |     return unless my $context = $self->GetContext; | ||||||
|     $self->SetCurrent($context); |     $self->SetCurrent($context); | ||||||
|     $self->InitGL; |     $self->InitGL; | ||||||
|  |  | ||||||
|  | @ -90,6 +90,9 @@ sub new { | ||||||
|         # Save the slic3r.ini. Usually the ini file is saved from "on idle" callback, |         # Save the slic3r.ini. Usually the ini file is saved from "on idle" callback, | ||||||
|         # but in rare cases it may not have been called yet. |         # but in rare cases it may not have been called yet. | ||||||
|         wxTheApp->{app_config}->save; |         wxTheApp->{app_config}->save; | ||||||
|  | #============================================================================================================================== | ||||||
|  |         Slic3r::GUI::_3DScene::remove_all_canvases(); | ||||||
|  | #============================================================================================================================== | ||||||
|         # propagate event |         # propagate event | ||||||
|         $event->Skip; |         $event->Skip; | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  | @ -144,6 +144,9 @@ sub new { | ||||||
|         # Note that the window was already closed, so a pending update will not be executed. |         # Note that the window was already closed, so a pending update will not be executed. | ||||||
|         $self->{already_closed} = 1; |         $self->{already_closed} = 1; | ||||||
|         $self->EndModal(wxID_OK); |         $self->EndModal(wxID_OK); | ||||||
|  | #=============================================================================================================================         | ||||||
|  |         $self->{canvas}->Destroy; | ||||||
|  | #=============================================================================================================================         | ||||||
|         $self->Destroy(); |         $self->Destroy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -151,6 +154,9 @@ sub new { | ||||||
|         # Note that the window was already closed, so a pending update will not be executed. |         # Note that the window was already closed, so a pending update will not be executed. | ||||||
|         $self->{already_closed} = 1; |         $self->{already_closed} = 1; | ||||||
|         $self->EndModal(wxID_CANCEL); |         $self->EndModal(wxID_CANCEL); | ||||||
|  | #=============================================================================================================================         | ||||||
|  |         $self->{canvas}->Destroy; | ||||||
|  | #=============================================================================================================================         | ||||||
|         $self->Destroy(); |         $self->Destroy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -511,6 +511,13 @@ sub CanClose { | ||||||
|     return ! Slic3r::GUI::catch_error($self); |     return ! Slic3r::GUI::catch_error($self); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #=============================================================================================================================         | ||||||
|  | sub Destroy { | ||||||
|  |     my ($self) = @_; | ||||||
|  |     $self->{canvas}->Destroy if ($self->{canvas}); | ||||||
|  | } | ||||||
|  | #=============================================================================================================================         | ||||||
|  | 
 | ||||||
| sub PartsChanged { | sub PartsChanged { | ||||||
|     my ($self) = @_; |     my ($self) = @_; | ||||||
|     return $self->{parts_changed}; |     return $self->{parts_changed}; | ||||||
|  |  | ||||||
|  | @ -36,6 +36,9 @@ sub new { | ||||||
|         wxTheApp->save_window_pos($self, "object_settings"); |         wxTheApp->save_window_pos($self, "object_settings"); | ||||||
|          |          | ||||||
|         $self->EndModal(wxID_OK); |         $self->EndModal(wxID_OK); | ||||||
|  | #=============================================================================================================================         | ||||||
|  |         $self->{parts}->Destroy; | ||||||
|  | #=============================================================================================================================         | ||||||
|         $self->Destroy; |         $self->Destroy; | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -182,6 +182,12 @@ add_library(libslic3r_gui STATIC | ||||||
|     ${LIBDIR}/slic3r/GUI/3DScene.hpp |     ${LIBDIR}/slic3r/GUI/3DScene.hpp | ||||||
|     ${LIBDIR}/slic3r/GUI/GLShader.cpp |     ${LIBDIR}/slic3r/GUI/GLShader.cpp | ||||||
|     ${LIBDIR}/slic3r/GUI/GLShader.hpp |     ${LIBDIR}/slic3r/GUI/GLShader.hpp | ||||||
|  |      | ||||||
|  |     ${LIBDIR}/slic3r/GUI/GLCanvas3D.hpp | ||||||
|  |     ${LIBDIR}/slic3r/GUI/GLCanvas3D.cpp | ||||||
|  |     ${LIBDIR}/slic3r/GUI/GLCanvas3DManager.hpp | ||||||
|  |     ${LIBDIR}/slic3r/GUI/GLCanvas3DManager.cpp | ||||||
|  |      | ||||||
|     ${LIBDIR}/slic3r/GUI/Preferences.cpp |     ${LIBDIR}/slic3r/GUI/Preferences.cpp | ||||||
|     ${LIBDIR}/slic3r/GUI/Preferences.hpp |     ${LIBDIR}/slic3r/GUI/Preferences.hpp | ||||||
|     ${LIBDIR}/slic3r/GUI/Preset.cpp |     ${LIBDIR}/slic3r/GUI/Preset.cpp | ||||||
|  | @ -550,13 +556,13 @@ if (SLIC3R_PRUSACONTROL) | ||||||
|     set(wxWidgets_UseAlienWx 1) |     set(wxWidgets_UseAlienWx 1) | ||||||
|     if (wxWidgets_UseAlienWx) |     if (wxWidgets_UseAlienWx) | ||||||
|         set(AlienWx_DEBUG 1) |         set(AlienWx_DEBUG 1) | ||||||
|         find_package(AlienWx REQUIRED COMPONENTS base core adv html) |         find_package(AlienWx REQUIRED COMPONENTS base core adv html gl) | ||||||
|         include_directories(${AlienWx_INCLUDE_DIRS}) |         include_directories(${AlienWx_INCLUDE_DIRS}) | ||||||
|         #add_compile_options(${AlienWx_CXX_FLAGS}) |         #add_compile_options(${AlienWx_CXX_FLAGS}) | ||||||
|         add_definitions(${AlienWx_DEFINITIONS}) |         add_definitions(${AlienWx_DEFINITIONS}) | ||||||
|         set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES}) |         set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES}) | ||||||
|     else () |     else () | ||||||
|         find_package(wxWidgets REQUIRED COMPONENTS base core adv html) |         find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) | ||||||
|         include(${wxWidgets_USE_FILE}) |         include(${wxWidgets_USE_FILE}) | ||||||
|     endif () |     endif () | ||||||
|     add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS) |     add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS) | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ our $VERSION = '0.01'; | ||||||
| BEGIN { | BEGIN { | ||||||
|     if ($^O eq 'MSWin32') { |     if ($^O eq 'MSWin32') { | ||||||
|         eval "use Wx"; |         eval "use Wx"; | ||||||
|  |         eval "use Wx::GLCanvas"; | ||||||
|  |         eval "use Wx::GLContext"; | ||||||
|         eval "use Wx::Html"; |         eval "use Wx::Html"; | ||||||
|         eval "use Wx::Print";  # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code) |         eval "use Wx::Print";  # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1473,6 +1473,9 @@ static void point3_to_verts(const Point3& point, double width, double height, GL | ||||||
| _3DScene::GCodePreviewVolumeIndex _3DScene::s_gcode_preview_volume_index; | _3DScene::GCodePreviewVolumeIndex _3DScene::s_gcode_preview_volume_index; | ||||||
| _3DScene::LegendTexture _3DScene::s_legend_texture; | _3DScene::LegendTexture _3DScene::s_legend_texture; | ||||||
| _3DScene::WarningTexture _3DScene::s_warning_texture; | _3DScene::WarningTexture _3DScene::s_warning_texture; | ||||||
|  | //##################################################################################################################
 | ||||||
|  | GUI::GLCanvas3DManager _3DScene::s_canvas_mgr; | ||||||
|  | //##################################################################################################################
 | ||||||
| 
 | 
 | ||||||
| unsigned int _3DScene::TextureBase::finalize() | unsigned int _3DScene::TextureBase::finalize() | ||||||
| { | { | ||||||
|  | @ -1709,11 +1712,117 @@ bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, con | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void _3DScene::_glew_init() | //##################################################################################################################
 | ||||||
|  | void _3DScene::init_gl() | ||||||
| { | { | ||||||
|     glewInit(); |     s_canvas_mgr.init_gl(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool _3DScene::use_VBOs() | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.use_VBOs(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool _3DScene::add_canvas(wxGLCanvas* canvas, wxGLContext* context) | ||||||
|  | { | ||||||
|  |     std::cout << "_3DScene::add_canvas()" << std::endl; | ||||||
|  |     return s_canvas_mgr.add(canvas, context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool _3DScene::remove_canvas(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     std::cout << "_3DScene::remove_canvas()" << std::endl; | ||||||
|  |     return s_canvas_mgr.remove(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::remove_all_canvases() | ||||||
|  | { | ||||||
|  |     std::cout << "_3DScene::remove_all_canvases()" << std::endl; | ||||||
|  |     std::cout << "# canvases not yet released: " << s_canvas_mgr.count() << std::endl; | ||||||
|  |     s_canvas_mgr.remove_all(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool _3DScene::is_dirty(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.is_dirty(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_dirty(wxGLCanvas* canvas, bool dirty) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_dirty(canvas, dirty); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool _3DScene::is_shown_on_screen(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.is_shown_on_screen(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | unsigned int _3DScene::get_camera_type(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.get_camera_type(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_camera_type(wxGLCanvas* canvas, unsigned int type) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_camera_type(canvas, type); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float _3DScene::get_camera_zoom(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.get_camera_zoom(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_camera_zoom(wxGLCanvas* canvas, float zoom) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_camera_zoom(canvas, zoom); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float _3DScene::get_camera_phi(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.get_camera_phi(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_camera_phi(wxGLCanvas* canvas, float phi) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_camera_phi(canvas, phi); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float _3DScene::get_camera_theta(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.get_camera_theta(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_camera_theta(wxGLCanvas* canvas, float theta) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_camera_theta(canvas, theta); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float _3DScene::get_camera_distance(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.get_camera_distance(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_camera_distance(wxGLCanvas* canvas, float distance) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_camera_distance(canvas, distance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Pointf3 _3DScene::get_camera_target(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return s_canvas_mgr.get_camera_target(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void _3DScene::set_camera_target(wxGLCanvas* canvas, const Pointf3* target) | ||||||
|  | { | ||||||
|  |     s_canvas_mgr.set_camera_target(canvas, target); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //void _3DScene::_glew_init()
 | ||||||
|  | //{ 
 | ||||||
|  | //    glewInit();
 | ||||||
|  | //}
 | ||||||
|  | //##################################################################################################################
 | ||||||
|  | 
 | ||||||
| static inline int hex_digit_to_int(const char c) | static inline int hex_digit_to_int(const char c) | ||||||
| { | { | ||||||
|     return  |     return  | ||||||
|  |  | ||||||
|  | @ -6,8 +6,14 @@ | ||||||
| #include "../../libslic3r/Line.hpp" | #include "../../libslic3r/Line.hpp" | ||||||
| #include "../../libslic3r/TriangleMesh.hpp" | #include "../../libslic3r/TriangleMesh.hpp" | ||||||
| #include "../../libslic3r/Utils.hpp" | #include "../../libslic3r/Utils.hpp" | ||||||
|  | //##################################################################################################################
 | ||||||
|  | #include "../../slic3r/GUI/GLCanvas3DManager.hpp" | ||||||
|  | //##################################################################################################################
 | ||||||
| 
 | 
 | ||||||
| class wxBitmap; | class wxBitmap; | ||||||
|  | //##################################################################################################################
 | ||||||
|  | class wxWindow; | ||||||
|  | //##################################################################################################################
 | ||||||
| 
 | 
 | ||||||
| namespace Slic3r { | namespace Slic3r { | ||||||
| 
 | 
 | ||||||
|  | @ -523,9 +529,44 @@ class _3DScene | ||||||
| 
 | 
 | ||||||
|     static LegendTexture s_legend_texture; |     static LegendTexture s_legend_texture; | ||||||
|     static WarningTexture s_warning_texture; |     static WarningTexture s_warning_texture; | ||||||
|  | //##################################################################################################################
 | ||||||
|  |     static GUI::GLCanvas3DManager s_canvas_mgr; | ||||||
|  | //##################################################################################################################
 | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     static void _glew_init(); | //##################################################################################################################
 | ||||||
|  |     static void init_gl(); | ||||||
|  |     static bool use_VBOs(); | ||||||
|  | 
 | ||||||
|  |     static bool add_canvas(wxGLCanvas* canvas, wxGLContext* context); | ||||||
|  |     static bool remove_canvas(wxGLCanvas* canvas); | ||||||
|  |     static void remove_all_canvases(); | ||||||
|  | 
 | ||||||
|  |     static bool is_dirty(wxGLCanvas* canvas); | ||||||
|  |     static void set_dirty(wxGLCanvas* canvas, bool dirty); | ||||||
|  | 
 | ||||||
|  |     static bool is_shown_on_screen(wxGLCanvas* canvas); | ||||||
|  | 
 | ||||||
|  |     static unsigned int get_camera_type(wxGLCanvas* canvas); | ||||||
|  |     static void set_camera_type(wxGLCanvas* canvas, unsigned int type); | ||||||
|  | 
 | ||||||
|  |     static float get_camera_zoom(wxGLCanvas* canvas); | ||||||
|  |     static void set_camera_zoom(wxGLCanvas* canvas, float zoom); | ||||||
|  | 
 | ||||||
|  |     static float get_camera_phi(wxGLCanvas* canvas); | ||||||
|  |     static void set_camera_phi(wxGLCanvas* canvas, float phi); | ||||||
|  | 
 | ||||||
|  |     static float get_camera_theta(wxGLCanvas* canvas); | ||||||
|  |     static void set_camera_theta(wxGLCanvas* canvas, float theta); | ||||||
|  | 
 | ||||||
|  |     static float get_camera_distance(wxGLCanvas* canvas); | ||||||
|  |     static void set_camera_distance(wxGLCanvas* canvas, float distance); | ||||||
|  | 
 | ||||||
|  |     static Pointf3 get_camera_target(wxGLCanvas* canvas); | ||||||
|  |     static void set_camera_target(wxGLCanvas* canvas, const Pointf3* target); | ||||||
|  | 
 | ||||||
|  | //    static void _glew_init();
 | ||||||
|  | //##################################################################################################################
 | ||||||
| 
 | 
 | ||||||
|     static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs); |     static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										117
									
								
								xs/src/slic3r/GUI/GLCanvas3D.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								xs/src/slic3r/GUI/GLCanvas3D.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | ||||||
|  | #include "GLCanvas3D.hpp" | ||||||
|  | 
 | ||||||
|  | #include <wx/glcanvas.h> | ||||||
|  | 
 | ||||||
|  | #include <iostream> | ||||||
|  | 
 | ||||||
|  | namespace Slic3r { | ||||||
|  | namespace GUI { | ||||||
|  | 
 | ||||||
|  | GLCanvas3D::Camera::Camera() | ||||||
|  |     : type(CT_Ortho) | ||||||
|  |     , zoom(1.0f) | ||||||
|  |     , phi(45.0f) | ||||||
|  |     , theta(45.0f) | ||||||
|  |     , distance(0.0f) | ||||||
|  |     , target(0.0, 0.0, 0.0) | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context) | ||||||
|  |     : m_canvas(canvas) | ||||||
|  |     , m_context(context) | ||||||
|  |     , m_dirty(true) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_current() | ||||||
|  | { | ||||||
|  |     if ((m_canvas != nullptr) && (m_context != nullptr)) | ||||||
|  |         m_canvas->SetCurrent(*m_context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3D::is_dirty() const | ||||||
|  | { | ||||||
|  |     return m_dirty; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_dirty(bool dirty) | ||||||
|  | { | ||||||
|  |     m_dirty = dirty; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3D::is_shown_on_screen() const | ||||||
|  | { | ||||||
|  |     return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GLCanvas3D::Camera::EType GLCanvas3D::get_camera_type() const | ||||||
|  | { | ||||||
|  |     return m_camera.type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_camera_type(GLCanvas3D::Camera::EType type) | ||||||
|  | { | ||||||
|  |     m_camera.type = type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3D::get_camera_zoom() const | ||||||
|  | { | ||||||
|  |     return m_camera.zoom; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_camera_zoom(float zoom) | ||||||
|  | { | ||||||
|  |     m_camera.zoom = zoom; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3D::get_camera_phi() const | ||||||
|  | { | ||||||
|  |     return m_camera.phi; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_camera_phi(float phi) | ||||||
|  | { | ||||||
|  |     m_camera.phi = phi; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3D::get_camera_theta() const | ||||||
|  | { | ||||||
|  |     return m_camera.theta; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_camera_theta(float theta) | ||||||
|  | { | ||||||
|  |     m_camera.theta = theta; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3D::get_camera_distance() const | ||||||
|  | { | ||||||
|  |     return m_camera.distance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_camera_distance(float distance) | ||||||
|  | { | ||||||
|  |     m_camera.distance = distance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const Pointf3& GLCanvas3D::get_camera_target() const | ||||||
|  | { | ||||||
|  |     return m_camera.target; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::set_camera_target(const Pointf3& target) | ||||||
|  | { | ||||||
|  |     m_camera.target = target; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3D::on_size(wxSizeEvent& evt) | ||||||
|  | { | ||||||
|  |     std::cout << "GLCanvas3D::on_size: " << (void*)this << std::endl; | ||||||
|  | 
 | ||||||
|  |     set_dirty(true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace GUI
 | ||||||
|  | } // namespace Slic3r
 | ||||||
							
								
								
									
										77
									
								
								xs/src/slic3r/GUI/GLCanvas3D.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								xs/src/slic3r/GUI/GLCanvas3D.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | ||||||
|  | #ifndef slic3r_GLCanvas3D_hpp_ | ||||||
|  | #define slic3r_GLCanvas3D_hpp_ | ||||||
|  | 
 | ||||||
|  | #include "../../libslic3r/Point.hpp" | ||||||
|  | 
 | ||||||
|  | class wxGLCanvas; | ||||||
|  | class wxGLContext; | ||||||
|  | class wxSizeEvent; | ||||||
|  | 
 | ||||||
|  | namespace Slic3r { | ||||||
|  | namespace GUI { | ||||||
|  | 
 | ||||||
|  | class GLCanvas3D | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     struct Camera | ||||||
|  |     { | ||||||
|  |         enum EType : unsigned char | ||||||
|  |         { | ||||||
|  |             CT_Unknown, | ||||||
|  |             CT_Perspective, | ||||||
|  |             CT_Ortho, | ||||||
|  |             CT_Count | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         EType type; | ||||||
|  |         float zoom; | ||||||
|  |         float phi; | ||||||
|  |         float theta; | ||||||
|  |         float distance; | ||||||
|  |         Pointf3 target; | ||||||
|  | 
 | ||||||
|  |         Camera(); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     wxGLCanvas* m_canvas; | ||||||
|  |     wxGLContext* m_context; | ||||||
|  |     Camera m_camera; | ||||||
|  | 
 | ||||||
|  |     bool m_dirty; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context); | ||||||
|  | 
 | ||||||
|  |     void set_current(); | ||||||
|  | 
 | ||||||
|  |     bool is_dirty() const; | ||||||
|  |     void set_dirty(bool dirty); | ||||||
|  | 
 | ||||||
|  |     bool is_shown_on_screen() const; | ||||||
|  | 
 | ||||||
|  |     Camera::EType get_camera_type() const; | ||||||
|  |     void set_camera_type(Camera::EType type); | ||||||
|  | 
 | ||||||
|  |     float get_camera_zoom() const; | ||||||
|  |     void set_camera_zoom(float zoom); | ||||||
|  | 
 | ||||||
|  |     float get_camera_phi() const; | ||||||
|  |     void set_camera_phi(float phi); | ||||||
|  | 
 | ||||||
|  |     float get_camera_theta() const; | ||||||
|  |     void set_camera_theta(float theta); | ||||||
|  | 
 | ||||||
|  |     float get_camera_distance() const; | ||||||
|  |     void set_camera_distance(float distance); | ||||||
|  | 
 | ||||||
|  |     const Pointf3& get_camera_target() const; | ||||||
|  |     void set_camera_target(const Pointf3& target); | ||||||
|  | 
 | ||||||
|  |     void on_size(wxSizeEvent& evt); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace GUI
 | ||||||
|  | } // namespace Slic3r
 | ||||||
|  | 
 | ||||||
|  | #endif // slic3r_GLCanvas3D_hpp_
 | ||||||
							
								
								
									
										263
									
								
								xs/src/slic3r/GUI/GLCanvas3DManager.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								xs/src/slic3r/GUI/GLCanvas3DManager.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,263 @@ | ||||||
|  | #include "GLCanvas3DManager.hpp" | ||||||
|  | #include "../../slic3r/GUI/GUI.hpp" | ||||||
|  | #include "../../slic3r/GUI/AppConfig.hpp" | ||||||
|  | 
 | ||||||
|  | #include <GL/glew.h> | ||||||
|  | 
 | ||||||
|  | #include <boost/algorithm/string/split.hpp> | ||||||
|  | #include <boost/algorithm/string/classification.hpp> | ||||||
|  | 
 | ||||||
|  | #include <wx/glcanvas.h> | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | #include <string> | ||||||
|  | #include <iostream> | ||||||
|  | 
 | ||||||
|  | namespace Slic3r { | ||||||
|  | namespace GUI { | ||||||
|  | 
 | ||||||
|  | GLCanvas3DManager::GLVersion::GLVersion() | ||||||
|  |     : vn_major(0) | ||||||
|  |     , vn_minor(0) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::GLVersion::detect() | ||||||
|  | { | ||||||
|  |     const char* gl_version = (const char*)::glGetString(GL_VERSION); | ||||||
|  |     if (gl_version == nullptr) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     std::vector<std::string> tokens; | ||||||
|  |     boost::split(tokens, gl_version, boost::is_any_of(" "), boost::token_compress_on); | ||||||
|  | 
 | ||||||
|  |     if (tokens.empty()) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     std::vector<std::string> numbers; | ||||||
|  |     boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); | ||||||
|  | 
 | ||||||
|  |     if (numbers.size() > 0) | ||||||
|  |         vn_major = ::atoi(numbers[0].c_str()); | ||||||
|  | 
 | ||||||
|  |     if (numbers.size() > 1) | ||||||
|  |         vn_minor = ::atoi(numbers[1].c_str()); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::GLVersion::is_greater_or_equal_to(unsigned int major, unsigned int minor) const | ||||||
|  | { | ||||||
|  |     if (vn_major < major) | ||||||
|  |         return false; | ||||||
|  |     else if (vn_major > major) | ||||||
|  |         return true; | ||||||
|  |     else | ||||||
|  |         return vn_minor >= minor; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GLCanvas3DManager::LayerEditing::LayerEditing() | ||||||
|  |     : allowed(false) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GLCanvas3DManager::GLCanvas3DManager() | ||||||
|  |     : m_gl_initialized(false) | ||||||
|  |     , m_use_legacy_opengl(false) | ||||||
|  |     , m_use_VBOs(false) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::add(wxGLCanvas* canvas, wxGLContext* context) | ||||||
|  | { | ||||||
|  |     if (_get_canvas(canvas) != m_canvases.end()) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     GLCanvas3D* canvas3D = new GLCanvas3D(canvas, context); | ||||||
|  |     if (canvas3D == nullptr) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     canvas->Bind(wxEVT_SIZE, [canvas3D](wxSizeEvent& evt) { canvas3D->on_size(evt); }); | ||||||
|  | 
 | ||||||
|  |     m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D)); | ||||||
|  | 
 | ||||||
|  |     std::cout << "canvas added: " << (void*)canvas << " (" << (void*)canvas3D << ")" << std::endl; | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::remove(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it == m_canvases.end()) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     delete it->second; | ||||||
|  |     m_canvases.erase(it); | ||||||
|  | 
 | ||||||
|  |     std::cout << "canvas removed: " << (void*)canvas << std::endl; | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::remove_all() | ||||||
|  | { | ||||||
|  |     for (CanvasesMap::value_type& item : m_canvases) | ||||||
|  |     { | ||||||
|  |         std::cout << "canvas removed: " << (void*)item.second << std::endl; | ||||||
|  |         delete item.second; | ||||||
|  |     } | ||||||
|  |     m_canvases.clear(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | unsigned int GLCanvas3DManager::count() const | ||||||
|  | { | ||||||
|  |     return (unsigned int)m_canvases.size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::init_gl() | ||||||
|  | { | ||||||
|  |     if (!m_gl_initialized) | ||||||
|  |     { | ||||||
|  |         std::cout << "GLCanvas3DManager::init_gl()" << std::endl; | ||||||
|  | 
 | ||||||
|  |         glewInit(); | ||||||
|  |         m_gl_version.detect(); | ||||||
|  | 
 | ||||||
|  |         const AppConfig* config = GUI::get_app_config(); | ||||||
|  |         m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1"); | ||||||
|  |         m_use_VBOs = !m_use_legacy_opengl && m_gl_version.is_greater_or_equal_to(2, 0); | ||||||
|  |         m_layer_editing.allowed = !m_use_legacy_opengl; | ||||||
|  |         m_gl_initialized = true; | ||||||
|  | 
 | ||||||
|  |         std::cout << "DETECTED OPENGL: " << m_gl_version.vn_major << "." << m_gl_version.vn_minor << std::endl; | ||||||
|  |         std::cout << "USE VBOS = " << (m_use_VBOs ? "YES" : "NO") << std::endl; | ||||||
|  |         std::cout << "LAYER EDITING ALLOWED = " << (m_layer_editing.allowed ? "YES" : "NO") << std::endl; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::use_VBOs() const | ||||||
|  | { | ||||||
|  |     return m_use_VBOs; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::layer_editing_allowed() const | ||||||
|  | { | ||||||
|  |     return m_layer_editing.allowed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::is_dirty(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->is_dirty() : false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_dirty(wxGLCanvas* canvas, bool dirty) | ||||||
|  | { | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_dirty(dirty); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GLCanvas3DManager::is_shown_on_screen(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->is_shown_on_screen() : false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | unsigned int GLCanvas3DManager::get_camera_type(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? (unsigned int)it->second->get_camera_type() : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_camera_type(wxGLCanvas* canvas, unsigned int type) | ||||||
|  | { | ||||||
|  |     if ((type <= (unsigned int)GLCanvas3D::Camera::CT_Unknown) || ((unsigned int)GLCanvas3D::Camera::CT_Count <= type)) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_camera_type((GLCanvas3D::Camera::EType)type); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3DManager::get_camera_zoom(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->get_camera_zoom() : 1.0f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_camera_zoom(wxGLCanvas* canvas, float zoom) | ||||||
|  | { | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_camera_zoom(zoom); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3DManager::get_camera_phi(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->get_camera_phi() : 0.0f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_camera_phi(wxGLCanvas* canvas, float phi) | ||||||
|  | { | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_camera_phi(phi); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3DManager::get_camera_theta(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->get_camera_theta() : 0.0f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_camera_theta(wxGLCanvas* canvas, float theta) | ||||||
|  | { | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_camera_theta(theta); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float GLCanvas3DManager::get_camera_distance(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->get_camera_distance() : 0.0f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_camera_distance(wxGLCanvas* canvas, float distance) | ||||||
|  | { | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_camera_distance(distance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Pointf3 GLCanvas3DManager::get_camera_target(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||||
|  |     return (it != m_canvases.end()) ? it->second->get_camera_target() : Pointf3(0.0, 0.0, 0.0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GLCanvas3DManager::set_camera_target(wxGLCanvas* canvas, const Pointf3* target) | ||||||
|  | { | ||||||
|  |     if (target == nullptr) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     CanvasesMap::iterator it = _get_canvas(canvas); | ||||||
|  |     if (it != m_canvases.end()) | ||||||
|  |         it->second->set_camera_target(*target); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) | ||||||
|  | { | ||||||
|  |     return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GLCanvas3DManager::CanvasesMap::const_iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) const | ||||||
|  | { | ||||||
|  |     return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace GUI
 | ||||||
|  | } // namespace Slic3r
 | ||||||
							
								
								
									
										86
									
								
								xs/src/slic3r/GUI/GLCanvas3DManager.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								xs/src/slic3r/GUI/GLCanvas3DManager.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | ||||||
|  | #ifndef slic3r_GLCanvas3DManager_hpp_ | ||||||
|  | #define slic3r_GLCanvas3DManager_hpp_ | ||||||
|  | 
 | ||||||
|  | #include "GLCanvas3D.hpp" | ||||||
|  | 
 | ||||||
|  | #include <map> | ||||||
|  | 
 | ||||||
|  | namespace Slic3r { | ||||||
|  | namespace GUI { | ||||||
|  | 
 | ||||||
|  | class GLCanvas3DManager | ||||||
|  | { | ||||||
|  |     struct GLVersion | ||||||
|  |     { | ||||||
|  |         unsigned int vn_major; | ||||||
|  |         unsigned int vn_minor; | ||||||
|  | 
 | ||||||
|  |         GLVersion(); | ||||||
|  |         bool detect(); | ||||||
|  | 
 | ||||||
|  |         bool is_greater_or_equal_to(unsigned int major, unsigned int minor) const; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     struct LayerEditing | ||||||
|  |     { | ||||||
|  |         bool allowed; | ||||||
|  | 
 | ||||||
|  |         LayerEditing(); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     typedef std::map<wxGLCanvas*, GLCanvas3D*> CanvasesMap; | ||||||
|  | 
 | ||||||
|  |     CanvasesMap m_canvases; | ||||||
|  |     GLVersion m_gl_version; | ||||||
|  |     LayerEditing m_layer_editing; | ||||||
|  |     bool m_gl_initialized; | ||||||
|  |     bool m_use_legacy_opengl; | ||||||
|  |     bool m_use_VBOs; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     GLCanvas3DManager(); | ||||||
|  | 
 | ||||||
|  |     bool add(wxGLCanvas* canvas, wxGLContext* context); | ||||||
|  |     bool remove(wxGLCanvas* canvas); | ||||||
|  | 
 | ||||||
|  |     void remove_all(); | ||||||
|  | 
 | ||||||
|  |     unsigned int count() const; | ||||||
|  | 
 | ||||||
|  |     void init_gl(); | ||||||
|  | 
 | ||||||
|  |     bool use_VBOs() const; | ||||||
|  |     bool layer_editing_allowed() const; | ||||||
|  | 
 | ||||||
|  |     bool is_dirty(wxGLCanvas* canvas) const; | ||||||
|  |     void set_dirty(wxGLCanvas* canvas, bool dirty); | ||||||
|  | 
 | ||||||
|  |     bool is_shown_on_screen(wxGLCanvas* canvas) const; | ||||||
|  | 
 | ||||||
|  |     unsigned int get_camera_type(wxGLCanvas* canvas) const; | ||||||
|  |     void set_camera_type(wxGLCanvas* canvas, unsigned int type); | ||||||
|  | 
 | ||||||
|  |     float get_camera_zoom(wxGLCanvas* canvas) const; | ||||||
|  |     void set_camera_zoom(wxGLCanvas* canvas, float zoom); | ||||||
|  | 
 | ||||||
|  |     float get_camera_phi(wxGLCanvas* canvas) const; | ||||||
|  |     void set_camera_phi(wxGLCanvas* canvas, float phi); | ||||||
|  | 
 | ||||||
|  |     float get_camera_theta(wxGLCanvas* canvas) const; | ||||||
|  |     void set_camera_theta(wxGLCanvas* canvas, float theta); | ||||||
|  | 
 | ||||||
|  |     float get_camera_distance(wxGLCanvas* canvas) const; | ||||||
|  |     void set_camera_distance(wxGLCanvas* canvas, float distance); | ||||||
|  | 
 | ||||||
|  |     Pointf3 get_camera_target(wxGLCanvas* canvas) const; | ||||||
|  |     void set_camera_target(wxGLCanvas* canvas, const Pointf3* target); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); | ||||||
|  |     CanvasesMap::const_iterator _get_canvas(wxGLCanvas* canvas) const; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace GUI
 | ||||||
|  | } // namespace Slic3r
 | ||||||
|  | 
 | ||||||
|  | #endif // slic3r_GLCanvas3DManager_hpp_
 | ||||||
|  | @ -151,11 +151,157 @@ GLVolumeCollection::arrayref() | ||||||
| %package{Slic3r::GUI::_3DScene}; | %package{Slic3r::GUI::_3DScene}; | ||||||
| %{ | %{ | ||||||
| 
 | 
 | ||||||
|  | void | ||||||
|  | init_gl() | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::init_gl(); | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | use_VBOs() | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::use_VBOs(); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  |          | ||||||
|  | bool | ||||||
|  | add_canvas(canvas, context) | ||||||
|  |         SV *canvas; | ||||||
|  |         SV *context; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::add_canvas((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (wxGLContext*)wxPli_sv_2_object(aTHX_ context, "Wx::GLContext")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | remove_canvas(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::remove_canvas((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| _glew_init() | remove_all_canvases() | ||||||
|     CODE: |     CODE: | ||||||
|         _3DScene::_glew_init(); |         _3DScene::remove_all_canvases(); | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | is_dirty(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::is_dirty((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_dirty(canvas, dirty) | ||||||
|  |         SV   *canvas; | ||||||
|  |         bool dirty; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_dirty((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), dirty); | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | is_shown_on_screen(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::is_shown_on_screen((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | unsigned int | ||||||
|  | get_camera_type(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::get_camera_type((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_camera_type(canvas, type) | ||||||
|  |         SV *canvas; | ||||||
|  |         unsigned int type; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_camera_type((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), type); | ||||||
|  |          | ||||||
|  | float | ||||||
|  | get_camera_zoom(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::get_camera_zoom((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_camera_zoom(canvas, zoom) | ||||||
|  |         SV    *canvas; | ||||||
|  |         float zoom; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_camera_zoom((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), zoom); | ||||||
|  | 
 | ||||||
|  | float | ||||||
|  | get_camera_phi(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::get_camera_phi((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_camera_phi(canvas, phi) | ||||||
|  |         SV    *canvas; | ||||||
|  |         float phi; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_camera_phi((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), phi); | ||||||
|  | 
 | ||||||
|  | float | ||||||
|  | get_camera_theta(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::get_camera_theta((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_camera_theta(canvas, theta) | ||||||
|  |         SV    *canvas; | ||||||
|  |         float theta; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_camera_theta((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), theta); | ||||||
|  | 
 | ||||||
|  | float | ||||||
|  | get_camera_distance(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::get_camera_distance((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_camera_distance(canvas, distance) | ||||||
|  |         SV    *canvas; | ||||||
|  |         float distance; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_camera_distance((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), distance); | ||||||
|  | 
 | ||||||
|  | Clone<Pointf3> | ||||||
|  | get_camera_target(canvas) | ||||||
|  |         SV *canvas; | ||||||
|  |     CODE: | ||||||
|  |         RETVAL = _3DScene::get_camera_target((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); | ||||||
|  |     OUTPUT: | ||||||
|  |         RETVAL | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | set_camera_target(canvas, target) | ||||||
|  |         SV      *canvas; | ||||||
|  |         Pointf3 *target; | ||||||
|  |     CODE: | ||||||
|  |         _3DScene::set_camera_target((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), target); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|      |      | ||||||
| unsigned int | unsigned int | ||||||
| finalize_legend_texture() | finalize_legend_texture() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri