From fc1a23f5b0447c9d43e7060b49e278fad81ee7f4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 16 May 2013 12:01:38 +0200 Subject: [PATCH] Quick and dirty OpenGL mockup --- MANIFEST | 1 + lib/Slic3r/GUI.pm | 1 + lib/Slic3r/GUI/Plater/ObjectDialog.pm | 19 +++ lib/Slic3r/GUI/PreviewCanvas.pm | 182 ++++++++++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 lib/Slic3r/GUI/PreviewCanvas.pm diff --git a/MANIFEST b/MANIFEST index bc338a5ce..24253e6bf 100644 --- a/MANIFEST +++ b/MANIFEST @@ -37,6 +37,7 @@ lib/Slic3r/GUI/OptionsGroup.pm lib/Slic3r/GUI/Plater.pm lib/Slic3r/GUI/Plater/ObjectDialog.pm lib/Slic3r/GUI/Preferences.pm +lib/Slic3r/GUI/PreviewCanvas.pm lib/Slic3r/GUI/SkeinPanel.pm lib/Slic3r/GUI/SimpleTab.pm lib/Slic3r/GUI/Tab.pm diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 1c60f8573..399b978b0 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -10,6 +10,7 @@ use Slic3r::GUI::Plater; use Slic3r::GUI::Plater::ObjectDialog; use Slic3r::GUI::Preferences; use Slic3r::GUI::OptionsGroup; +use Slic3r::GUI::PreviewCanvas; use Slic3r::GUI::SkeinPanel; use Slic3r::GUI::SimpleTab; use Slic3r::GUI::Tab; diff --git a/lib/Slic3r/GUI/Plater/ObjectDialog.pm b/lib/Slic3r/GUI/Plater/ObjectDialog.pm index 6543d50da..c1723632b 100644 --- a/lib/Slic3r/GUI/Plater/ObjectDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectDialog.pm @@ -14,6 +14,7 @@ sub new { $self->{object} = $params{object}; $self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); + $self->{tabpanel}->AddPage($self->{preview} = Slic3r::GUI::Plater::ObjectDialog::PreviewTab->new($self->{tabpanel}, object => $self->{object}), "Preview"); $self->{tabpanel}->AddPage($self->{info} = Slic3r::GUI::Plater::ObjectDialog::InfoTab->new($self->{tabpanel}, object => $self->{object}), "Info"); $self->{tabpanel}->AddPage($self->{layers} = Slic3r::GUI::Plater::ObjectDialog::LayersTab->new($self->{tabpanel}, object => $self->{object}), "Layers"); @@ -83,6 +84,24 @@ sub get_properties { ]; } +package Slic3r::GUI::Plater::ObjectDialog::PreviewTab; +use Wx qw(:dialog :id :misc :sizer :systemsettings); +use base 'Wx::Panel'; + +sub new { + my $class = shift; + my ($parent, %params) = @_; + my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize); + $self->{object} = $params{object}; + + my $sizer = Wx::BoxSizer->new(wxVERTICAL); + $sizer->Add(Slic3r::GUI::PreviewCanvas::Cube->new($self, $self->{object}->get_model_object->mesh), 1, wxEXPAND, 0); + $self->SetSizer($sizer); + $sizer->SetSizeHints($self); + + return $self; +} + package Slic3r::GUI::Plater::ObjectDialog::LayersTab; use Wx qw(:dialog :id :misc :sizer :systemsettings); use Wx::Grid; diff --git a/lib/Slic3r/GUI/PreviewCanvas.pm b/lib/Slic3r/GUI/PreviewCanvas.pm new file mode 100644 index 000000000..122df54b8 --- /dev/null +++ b/lib/Slic3r/GUI/PreviewCanvas.pm @@ -0,0 +1,182 @@ +package Slic3r::GUI::PreviewCanvas; + +use strict; + +use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_TIMER); +# must load OpenGL *before* Wx::GLCanvas +use OpenGL qw(:glconstants :glfunctions); +use base qw(Wx::GLCanvas Class::Accessor::Fast); +use Wx::GLCanvas qw(:all); + +__PACKAGE__->mk_accessors( qw(timer x_rot y_rot dirty init mesh) ); + +sub new { + my( $class, $parent, $mesh ) = @_; + my $self = $class->SUPER::new($parent); + $self->mesh($mesh); + + my $timer = $self->timer( Wx::Timer->new( $self ) ); + $timer->Start( 50 ); + + $self->x_rot( 0 ); + $self->y_rot( 0 ); + + EVT_PAINT( $self, + sub { + my $dc = Wx::PaintDC->new( $self ); + $self->Render( $dc ); + } ); + EVT_SIZE( $self, sub { $self->dirty( 1 ) } ); + EVT_IDLE( $self, sub { + return unless $self->dirty; + $self->Resize( $self->GetSizeWH ); + $self->Refresh; + } ); + EVT_TIMER( $self, -1, sub { + my( $self, $e ) = @_; + + $self->x_rot( $self->x_rot - 1 ); + $self->y_rot( $self->y_rot + 2 ); + + $self->dirty( 1 ); + Wx::WakeUpIdle; + } ); + + return $self; +} + +sub GetContext { + my( $self ) = @_; + + if( Wx::wxVERSION >= 2.009 ) { + return $self->{context} ||= Wx::GLContext->new( $self ); + } else { + return $self->SUPER::GetContext; + } +} + +sub SetCurrent { + my( $self, $context ) = @_; + + if( Wx::wxVERSION >= 2.009 ) { + return $self->SUPER::SetCurrent( $context ); + } else { + return $self->SUPER::SetCurrent; + } +} + +sub Resize { + my( $self, $x, $y ) = @_; + + return unless $self->GetContext; + $self->dirty( 0 ); + + $self->SetCurrent( $self->GetContext ); + glViewport( 0, 0, $x, $y ); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + my_gluPerspective( 45, $x/$y, .5, 100 ); + + glMatrixMode(GL_MODELVIEW); +} + +use Math::Trig; + +sub my_gluPerspective { + my( $fov, $ratio, $near, $far ) = @_; + + my $top = tan(deg2rad($fov)*0.5) * $near; + my $bottom = -$top; + my $left = $ratio * $bottom; + my $right = $ratio * $top; + + glFrustum( $left, $right, $bottom, $top, $near, $far ); +} + +sub DESTROY { + my( $self ) = @_; + + $self->timer->Stop; + $self->timer( undef ); +} + +package Slic3r::GUI::PreviewCanvas::Cube; + +# must load OpenGL *before* Wx::GLCanvas +use OpenGL qw(:glconstants :glfunctions); +use base qw(Slic3r::GUI::PreviewCanvas); +use Slic3r::Geometry qw(X Y Z MIN MAX); + +sub cube { + my( @v ) = ( [ 1, 1, 1 ], [ -1, 1, 1 ], + [ -1, -1, 1 ], [ 1, -1, 1 ], + [ 1, 1, -1 ], [ -1, 1, -1 ], + [ -1, -1, -1 ], [ 1, -1, -1 ] ); + my( @c ) = ( [ 1, 1, 0 ], [ 1, 0, 1 ], + [ 0, 1, 1 ], [ 1, 1, 1 ], + [ 0, 0, 1 ], [ 0, 1, 0 ], + [ 1, 0, 1 ], [ 1, 1, 0 ] ); + my( @s ) = ( [ 0, 1, 2, 3 ], [ 4, 5, 6, 7 ], + [ 0, 1, 5, 4 ], [ 2, 3, 7, 6 ], + [ 1, 2, 6, 5 ], [ 0, 3, 7, 4 ] ); + + for my $i ( 0 .. 5 ) { + my $s = $s[$i]; + glBegin(GL_QUADS); + foreach my $j ( @$s ) { + glColor3f( @{$c[$j]} ); + glVertex3f( @{$v[$j]} ); + } + glEnd(); + } +} + +sub draw_mesh { + my $self = shift; + + my $mesh = $self->mesh; + $mesh->align_to_origin; + glBegin(GL_TRIANGLES); + for my $facet (@{$mesh->facets}) { + glVertex3f( map 0.1 * $_, @{ $mesh->vertices->[$_] } ) for @$facet; + } + glEnd(); +} + +sub InitGL { + my $self = shift; + + return if $self->init; + return unless $self->GetContext; + $self->init( 1 ); + + glDisable( GL_LIGHTING ); + glDepthFunc( GL_LESS ); + glEnable( GL_DEPTH_TEST ); +} + +sub Render { + my( $self, $dc ) = @_; + + return unless $self->GetContext; + $self->SetCurrent( $self->GetContext ); + $self->InitGL; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glTranslatef( 0, 0, -5 ); + glRotatef( $self->x_rot, 1, 0, 0 ); + glRotatef( $self->y_rot, 0, 0, 1 ); + + #cube(); + $self->draw_mesh; + + glPopMatrix(); + glFlush(); + + $self->SwapBuffers(); +} + +1; \ No newline at end of file