Use multiple colors for multimaterial models in 3D preview

xsdata-boost
Alessandro Ranellucci 2013-08-25 16:35:21 +02:00
parent 2fb725405f
commit fde6e371a9
3 changed files with 51 additions and 30 deletions

View File

@ -119,7 +119,7 @@ sub new {
$self->{object} = $params{object}; $self->{object} = $params{object};
my $sizer = Wx::BoxSizer->new(wxVERTICAL); my $sizer = Wx::BoxSizer->new(wxVERTICAL);
$sizer->Add(Slic3r::GUI::PreviewCanvas->new($self, $self->{object}->get_model_object->mesh), 1, wxEXPAND, 0); $sizer->Add(Slic3r::GUI::PreviewCanvas->new($self, $self->{object}->get_model_object), 1, wxEXPAND, 0);
$self->SetSizer($sizer); $self->SetSizer($sizer);
$sizer->SetSizeHints($self); $sizer->SetSizeHints($self);

View File

@ -7,37 +7,56 @@ use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL
use OpenGL qw(:glconstants :glfunctions :glufunctions); use OpenGL qw(:glconstants :glfunctions :glufunctions);
use base qw(Wx::GLCanvas Class::Accessor); use base qw(Wx::GLCanvas Class::Accessor);
use Math::Trig qw(asin); use Math::Trig qw(asin);
use List::Util qw(reduce min max); use List::Util qw(reduce min max first);
use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan); use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan);
use Wx::GLCanvas qw(:all); use Wx::GLCanvas qw(:all);
__PACKAGE__->mk_accessors( qw(quat dirty init mview_init __PACKAGE__->mk_accessors( qw(quat dirty init mview_init
mesh_center mesh_size object_center object_size
verts norms initpos volumes initpos
sphi stheta) ); sphi stheta) );
use constant TRACKBALLSIZE => 0.8; use constant TRACKBALLSIZE => 0.8;
use constant TURNTABLE_MODE => 1; use constant TURNTABLE_MODE => 1;
use constant COLORS => [ [1,1,1], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ];
sub new { sub new {
my ($class, $parent, $mesh) = @_; my ($class, $parent, $object) = @_;
my $self = $class->SUPER::new($parent); my $self = $class->SUPER::new($parent);
$self->quat((0, 0, 0, 1)); $self->quat((0, 0, 0, 1));
$self->sphi(45); $self->sphi(45);
$self->stheta(-45); $self->stheta(-45);
# prepare mesh $object->align_to_origin;
{ $self->object_center($object->center);
$mesh->align_to_origin; $self->object_size($object->size);
$self->mesh_center($mesh->center);
$self->mesh_size($mesh->size); # group mesh(es) by material
my @materials = ();
$self->volumes([]);
foreach my $volume (@{$object->volumes}) {
my $mesh = $volume->mesh;
my @verts = map @{ $mesh->vertices->[$_] }, map @$_, @{$mesh->facets}; my $material_id = $volume->material_id // '_';
$self->verts(OpenGL::Array->new_list(GL_FLOAT, @verts)); my $color_idx = first { $materials[$_] eq $material_id } 0..$#materials;
if (!defined $color_idx) {
push @materials, $material_id;
$color_idx = $#materials;
}
push @{$self->volumes}, my $v = {
color => COLORS->[ $color_idx % scalar(@{&COLORS}) ],
};
my @norms = map { @$_, @$_, @$_ } map normalize(triangle_normal(map $mesh->vertices->[$_], @$_)), @{$mesh->facets}; {
$self->norms(OpenGL::Array->new_list(GL_FLOAT, @norms)); my @verts = map @{ $mesh->vertices->[$_] }, map @$_, @{$mesh->facets};
$v->{verts} = OpenGL::Array->new_list(GL_FLOAT, @verts);
}
{
my @norms = map { @$_, @$_, @$_ } map normalize(triangle_normal(map $mesh->vertices->[$_], @$_)), @{$mesh->facets};
$v->{norms} = OpenGL::Array->new_list(GL_FLOAT, @norms);
}
} }
EVT_PAINT($self, sub { EVT_PAINT($self, sub {
@ -277,7 +296,7 @@ sub ResetModelView {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
my $win_size = $self->GetClientSize(); my $win_size = $self->GetClientSize();
my $ratio = $factor * min($win_size->width, $win_size->height) / max(@{ $self->mesh_size }); my $ratio = $factor * min($win_size->width, $win_size->height) / max(@{ $self->object_size });
glScalef($ratio, $ratio, 1); glScalef($ratio, $ratio, 1);
} }
@ -292,8 +311,8 @@ sub Resize {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
my $mesh_size = $self->mesh_size; my $object_size = $self->object_size;
glOrtho(-$x/2, $x/2, -$y/2, $y/2, 0.5, 2 * max(@$mesh_size)); glOrtho(-$x/2, $x/2, -$y/2, $y/2, 0.5, 2 * max(@$object_size));
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
unless ($self->mview_init) { unless ($self->mview_init) {
@ -350,19 +369,19 @@ sub Render {
glPushMatrix(); glPushMatrix();
my $mesh_size = $self->mesh_size; my $object_size = $self->object_size;
glTranslatef(0, 0, -max(@$mesh_size[0..1])); glTranslatef(0, 0, -max(@$object_size[0..1]));
my @rotmat = quat_to_rotmatrix($self->quat); my @rotmat = quat_to_rotmatrix($self->quat);
glMultMatrixd_p(@rotmat[0..15]); glMultMatrixd_p(@rotmat[0..15]);
glRotatef($self->stheta, 1, 0, 0); glRotatef($self->stheta, 1, 0, 0);
glRotatef($self->sphi, 0, 0, 1); glRotatef($self->sphi, 0, 0, 1);
glTranslatef(map -$_, @{ $self->mesh_center }); glTranslatef(map -$_, @{ $self->object_center });
$self->draw_mesh; $self->draw_mesh;
# draw axes # draw axes
{ {
my $axis_len = 2 * max(@{ $self->mesh_size }); my $axis_len = 2 * max(@{ $self->object_size });
glLineWidth(2); glLineWidth(2);
glBegin(GL_LINES); glBegin(GL_LINES);
# draw line for x axis # draw line for x axis
@ -421,12 +440,14 @@ sub draw_mesh {
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer_p(3, $self->verts); foreach my $volume (@{$self->volumes}) {
glVertexPointer_p(3, $volume->{verts});
glCullFace(GL_BACK);
glNormalPointer_p($self->norms); glCullFace(GL_BACK);
glColor3f(1, 1, 1); glNormalPointer_p($volume->{norms});
glDrawArrays(GL_TRIANGLES, 0, $self->verts->elements / 3); glColor3f(@{ $volume->{color} });
glDrawArrays(GL_TRIANGLES, 0, $volume->{verts}->elements / 3);
}
glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);

View File

@ -27,7 +27,7 @@ my %opt = ();
{ {
my $model = Slic3r::Model->read_from_file($ARGV[0]); my $model = Slic3r::Model->read_from_file($ARGV[0]);
$Slic3r::ViewMesh::mesh = $model->mesh; $Slic3r::ViewMesh::object = $model->objects->[0];
my $app = Slic3r::ViewMesh->new; my $app = Slic3r::ViewMesh->new;
$app->MainLoop; $app->MainLoop;
} }
@ -49,7 +49,7 @@ package Slic3r::ViewMesh;
use Wx qw(:sizer); use Wx qw(:sizer);
use base qw(Wx::App); use base qw(Wx::App);
our $mesh; our $object;
sub OnInit { sub OnInit {
my $self = shift; my $self = shift;
@ -58,7 +58,7 @@ sub OnInit {
my $panel = Wx::Panel->new($frame, -1); my $panel = Wx::Panel->new($frame, -1);
my $sizer = Wx::BoxSizer->new(wxVERTICAL); my $sizer = Wx::BoxSizer->new(wxVERTICAL);
$sizer->Add(Slic3r::GUI::PreviewCanvas->new($panel, $mesh), 1, wxEXPAND, 0); $sizer->Add(Slic3r::GUI::PreviewCanvas->new($panel, $object), 1, wxEXPAND, 0);
$panel->SetSizer($sizer); $panel->SetSizer($sizer);
$sizer->SetSizeHints($panel); $sizer->SetSizeHints($panel);