Merge branch 'master' into wipe_tower_improvements
This commit is contained in:
commit
3d6f6530c0
59 changed files with 4062 additions and 12410 deletions
|
@ -15,7 +15,6 @@ use Slic3r::GUI::Controller;
|
|||
use Slic3r::GUI::Controller::ManualControlDialog;
|
||||
use Slic3r::GUI::Controller::PrinterPanel;
|
||||
use Slic3r::GUI::MainFrame;
|
||||
use Slic3r::GUI::Notifier;
|
||||
use Slic3r::GUI::Plater;
|
||||
use Slic3r::GUI::Plater::2D;
|
||||
use Slic3r::GUI::Plater::2DToolpaths;
|
||||
|
@ -34,7 +33,6 @@ use Slic3r::GUI::SystemInfo;
|
|||
use Wx::Locale gettext => 'L';
|
||||
|
||||
our $have_OpenGL = eval "use Slic3r::GUI::3DScene; 1";
|
||||
our $have_LWP = eval "use LWP::UserAgent; 1";
|
||||
|
||||
use Wx 0.9901 qw(:bitmap :dialog :icon :id :misc :systemsettings :toplevelwindow :filedialog :font);
|
||||
use Wx::Event qw(EVT_IDLE EVT_COMMAND EVT_MENU);
|
||||
|
@ -88,7 +86,6 @@ sub OnInit {
|
|||
Slic3r::set_data_dir($datadir || Wx::StandardPaths::Get->GetUserDataDir);
|
||||
Slic3r::GUI::set_wxapp($self);
|
||||
|
||||
$self->{notifier} = Slic3r::GUI::Notifier->new;
|
||||
$self->{app_config} = Slic3r::GUI::AppConfig->new;
|
||||
$self->{preset_bundle} = Slic3r::GUI::PresetBundle->new;
|
||||
|
||||
|
@ -117,6 +114,8 @@ sub OnInit {
|
|||
}
|
||||
eval { $self->{preset_bundle}->load_selections($self->{app_config}) };
|
||||
$run_wizard = 1 if $self->{preset_bundle}->has_defauls_only;
|
||||
|
||||
Slic3r::GUI::set_preset_bundle($self->{preset_bundle});
|
||||
|
||||
# application frame
|
||||
Wx::Image::FindHandlerType(wxBITMAP_TYPE_PNG) || Wx::Image::AddHandler(Wx::PNGHandler->new);
|
||||
|
@ -270,7 +269,9 @@ sub notify {
|
|||
$frame->RequestUserAttention(&Wx::wxMAC ? wxUSER_ATTENTION_ERROR : wxUSER_ATTENTION_INFO)
|
||||
unless ($frame->IsActive);
|
||||
|
||||
$self->{notifier}->notify($message);
|
||||
# There used to be notifier using a Growl application for OSX, but Growl is dead.
|
||||
# The notifier also supported the Linux X D-bus notifications, but that support was broken.
|
||||
#TODO use wxNotificationMessage?
|
||||
}
|
||||
|
||||
# Called after the Preferences dialog is closed and the program settings are saved.
|
||||
|
|
|
@ -68,6 +68,7 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init
|
|||
_zoom
|
||||
|
||||
_legend_enabled
|
||||
_warning_enabled
|
||||
_apply_zoom_to_volumes_filter
|
||||
|
||||
) );
|
||||
|
@ -142,6 +143,7 @@ sub new {
|
|||
$self->_sphi(45);
|
||||
$self->_zoom(1);
|
||||
$self->_legend_enabled(0);
|
||||
$self->_warning_enabled(0);
|
||||
$self->use_plain_shader(0);
|
||||
$self->_apply_zoom_to_volumes_filter(0);
|
||||
|
||||
|
@ -217,7 +219,12 @@ sub new {
|
|||
|
||||
sub set_legend_enabled {
|
||||
my ($self, $value) = @_;
|
||||
$self->_legend_enabled($value);
|
||||
$self->_legend_enabled($value);
|
||||
}
|
||||
|
||||
sub set_warning_enabled {
|
||||
my ($self, $value) = @_;
|
||||
$self->_warning_enabled($value);
|
||||
}
|
||||
|
||||
sub Destroy {
|
||||
|
@ -400,6 +407,10 @@ sub mouse_event {
|
|||
$self->Refresh;
|
||||
$self->Update;
|
||||
} else {
|
||||
# The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate $pos->x,y,
|
||||
# an converts the screen space coordinate to unscaled object space.
|
||||
my $pos3d = ($volume_idx == -1) ? undef : $self->mouse_to_3d(@$pos);
|
||||
|
||||
# Select volume in this 3D canvas.
|
||||
# Don't deselect a volume if layer editing is enabled. We want the object to stay selected
|
||||
# during the scene manipulation.
|
||||
|
@ -427,9 +438,6 @@ sub mouse_event {
|
|||
|
||||
if ($volume_idx != -1) {
|
||||
if ($e->LeftDown && $self->enable_moving) {
|
||||
# The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate $pos->x,y,
|
||||
# an converts the screen space coordinate to unscaled object space.
|
||||
my $pos3d = $self->mouse_to_3d(@$pos);
|
||||
# Only accept the initial position, if it is inside the volume bounding box.
|
||||
my $volume_bbox = $self->volumes->[$volume_idx]->transformed_bounding_box;
|
||||
$volume_bbox->offset(1.);
|
||||
|
@ -948,6 +956,9 @@ sub mulquats {
|
|||
sub mouse_to_3d {
|
||||
my ($self, $x, $y, $z) = @_;
|
||||
|
||||
return unless $self->GetContext;
|
||||
$self->SetCurrent($self->GetContext);
|
||||
|
||||
my @viewport = glGetIntegerv_p(GL_VIEWPORT); # 4 items
|
||||
my @mview = glGetDoublev_p(GL_MODELVIEW_MATRIX); # 16 items
|
||||
my @proj = glGetDoublev_p(GL_PROJECTION_MATRIX); # 16 items
|
||||
|
@ -1296,11 +1307,16 @@ sub Render {
|
|||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
|
||||
# draw objects
|
||||
if (! $self->use_plain_shader) {
|
||||
$self->draw_volumes;
|
||||
} elsif ($self->UseVBOs) {
|
||||
if ($self->enable_picking) {
|
||||
$self->mark_volumes_for_layer_height;
|
||||
$self->volumes->set_print_box($self->bed_bounding_box->x_min, $self->bed_bounding_box->y_min, 0.0, $self->bed_bounding_box->x_max, $self->bed_bounding_box->y_max, $self->{config}->get('max_print_height'));
|
||||
$self->volumes->update_outside_state($self->{config}, 0);
|
||||
}
|
||||
$self->{plain_shader}->enable if $self->{plain_shader};
|
||||
$self->volumes->render_VBOs;
|
||||
$self->{plain_shader}->disable;
|
||||
|
@ -1327,6 +1343,9 @@ sub Render {
|
|||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
# draw warning message
|
||||
$self->draw_warning;
|
||||
|
||||
# draw gcode preview legend
|
||||
$self->draw_legend;
|
||||
|
||||
|
@ -1345,36 +1364,10 @@ sub draw_volumes {
|
|||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
my $z_cursor_relative = $self->_variable_layer_thickness_bar_mouse_cursor_z_relative;
|
||||
foreach my $volume_idx (0..$#{$self->volumes}) {
|
||||
my $volume = $self->volumes->[$volume_idx];
|
||||
|
||||
my $shader_active = 0;
|
||||
my $object_id = int($volume->select_group_id / 1000000);
|
||||
if ($self->layer_editing_enabled && ! $fakecolor && $volume->selected && $self->{layer_height_edit_shader} &&
|
||||
$volume->has_layer_height_texture && $object_id < $self->{print}->object_count) {
|
||||
# Update the height texture if the ModelObject::layer_height_texture is invalid.
|
||||
$volume->generate_layer_height_texture($self->{print}->get_object($object_id), 0);
|
||||
$self->{layer_height_edit_shader}->enable;
|
||||
$self->{layer_height_edit_shader}->set_uniform('z_to_texture_row', $volume->layer_height_texture_z_to_row_id);
|
||||
$self->{layer_height_edit_shader}->set_uniform('z_texture_row_to_normalized', 1. / $volume->layer_height_texture_height);
|
||||
$self->{layer_height_edit_shader}->set_uniform('z_cursor', $volume->bounding_box->z_max * $z_cursor_relative);
|
||||
$self->{layer_height_edit_shader}->set_uniform('z_cursor_band_width', $self->{layer_height_edit_band_width});
|
||||
glBindTexture(GL_TEXTURE_2D, $self->{layer_preview_z_texture_id});
|
||||
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LEVEL, 0);
|
||||
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $volume->layer_height_texture_width, $volume->layer_height_texture_height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D_c(GL_TEXTURE_2D, 1, GL_RGBA8, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
# glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
# glPixelStorei(GL_UNPACK_ROW_LENGTH, $self->{layer_preview_z_texture_width});
|
||||
glTexSubImage2D_c(GL_TEXTURE_2D, 0, 0, 0, $volume->layer_height_texture_width, $volume->layer_height_texture_height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level0);
|
||||
glTexSubImage2D_c(GL_TEXTURE_2D, 1, 0, 0, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level1);
|
||||
$shader_active = 1;
|
||||
} elsif ($fakecolor) {
|
||||
if ($fakecolor) {
|
||||
# Object picking mode. Render the object with a color encoding the object index.
|
||||
my $r = ($volume_idx & 0x000000FF) >> 0;
|
||||
my $g = ($volume_idx & 0x0000FF00) >> 8;
|
||||
|
@ -1389,11 +1382,6 @@ sub draw_volumes {
|
|||
}
|
||||
|
||||
$volume->render;
|
||||
|
||||
if ($shader_active) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
$self->{layer_height_edit_shader}->disable;
|
||||
}
|
||||
}
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_BLEND);
|
||||
|
@ -1408,6 +1396,22 @@ sub draw_volumes {
|
|||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
sub mark_volumes_for_layer_height {
|
||||
my ($self) = @_;
|
||||
|
||||
foreach my $volume_idx (0..$#{$self->volumes}) {
|
||||
my $volume = $self->volumes->[$volume_idx];
|
||||
my $object_id = int($volume->select_group_id / 1000000);
|
||||
if ($self->layer_editing_enabled && $volume->selected && $self->{layer_height_edit_shader} &&
|
||||
$volume->has_layer_height_texture && $object_id < $self->{print}->object_count) {
|
||||
$volume->set_layer_height_texture_data($self->{layer_preview_z_texture_id}, $self->{layer_height_edit_shader}->shader_program_id,
|
||||
$self->{print}->get_object($object_id), $self->_variable_layer_thickness_bar_mouse_cursor_z_relative, $self->{layer_height_edit_band_width});
|
||||
} else {
|
||||
$volume->reset_layer_height_texture_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _load_image_set_texture {
|
||||
my ($self, $file_name) = @_;
|
||||
# Load a PNG with an alpha channel.
|
||||
|
@ -1599,31 +1603,65 @@ sub draw_active_object_annotations {
|
|||
sub draw_legend {
|
||||
my ($self) = @_;
|
||||
|
||||
if ($self->_legend_enabled)
|
||||
{
|
||||
# If the legend texture has not been loaded into the GPU, do it now.
|
||||
my $tex_id = Slic3r::GUI::_3DScene::finalize_legend_texture;
|
||||
if ($tex_id > 0)
|
||||
{
|
||||
my $tex_w = Slic3r::GUI::_3DScene::get_legend_texture_width;
|
||||
my $tex_h = Slic3r::GUI::_3DScene::get_legend_texture_height;
|
||||
if (($tex_w > 0) && ($tex_h > 0))
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
my ($cw, $ch) = $self->GetSizeWH;
|
||||
|
||||
my $l = (-0.5 * $cw) / $self->_zoom;
|
||||
my $t = (0.5 * $ch) / $self->_zoom;
|
||||
my $r = $l + $tex_w / $self->_zoom;
|
||||
my $b = $t - $tex_h / $self->_zoom;
|
||||
$self->_render_texture($tex_id, $l, $r, $b, $t);
|
||||
if (!$self->_legend_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
# If the legend texture has not been loaded into the GPU, do it now.
|
||||
my $tex_id = Slic3r::GUI::_3DScene::finalize_legend_texture;
|
||||
if ($tex_id > 0)
|
||||
{
|
||||
my $tex_w = Slic3r::GUI::_3DScene::get_legend_texture_width;
|
||||
my $tex_h = Slic3r::GUI::_3DScene::get_legend_texture_height;
|
||||
if (($tex_w > 0) && ($tex_h > 0))
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
my ($cw, $ch) = $self->GetSizeWH;
|
||||
|
||||
my $l = (-0.5 * $cw) / $self->_zoom;
|
||||
my $t = (0.5 * $ch) / $self->_zoom;
|
||||
my $r = $l + $tex_w / $self->_zoom;
|
||||
my $b = $t - $tex_h / $self->_zoom;
|
||||
$self->_render_texture($tex_id, $l, $r, $b, $t);
|
||||
|
||||
glPopMatrix();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub draw_warning {
|
||||
my ($self) = @_;
|
||||
|
||||
if (!$self->_warning_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
# If the warning texture has not been loaded into the GPU, do it now.
|
||||
my $tex_id = Slic3r::GUI::_3DScene::finalize_warning_texture;
|
||||
if ($tex_id > 0)
|
||||
{
|
||||
my $tex_w = Slic3r::GUI::_3DScene::get_warning_texture_width;
|
||||
my $tex_h = Slic3r::GUI::_3DScene::get_warning_texture_height;
|
||||
if (($tex_w > 0) && ($tex_h > 0))
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
my ($cw, $ch) = $self->GetSizeWH;
|
||||
|
||||
my $l = (-0.5 * $tex_w) / $self->_zoom;
|
||||
my $t = (-0.5 * $ch + $tex_h) / $self->_zoom;
|
||||
my $r = $l + $tex_w / $self->_zoom;
|
||||
my $b = $t - $tex_h / $self->_zoom;
|
||||
$self->_render_texture($tex_id, $l, $r, $b, $t);
|
||||
|
||||
glPopMatrix();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1692,57 +1730,77 @@ sub _vertex_shader_Gouraud {
|
|||
return <<'VERTEX';
|
||||
#version 110
|
||||
|
||||
#define INTENSITY_CORRECTION 0.7
|
||||
#define INTENSITY_CORRECTION 0.6
|
||||
|
||||
#define LIGHT_TOP_DIR -0.6/1.31, 0.6/1.31, 1./1.31
|
||||
// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
|
||||
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.5 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 50.
|
||||
#define LIGHT_TOP_SPECULAR (0.25 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 200.0
|
||||
|
||||
#define LIGHT_FRONT_DIR 1./1.43, 0.2/1.43, 1./1.43
|
||||
// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
|
||||
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_FRONT_SHININESS 50.
|
||||
//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
|
||||
//#define LIGHT_FRONT_SHININESS 5.0
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
varying float intensity_specular;
|
||||
varying float intensity_tainted;
|
||||
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
|
||||
|
||||
struct PrintBoxDetection
|
||||
{
|
||||
vec3 min;
|
||||
vec3 max;
|
||||
// xyz contains the offset, if w == 1.0 detection needs to be performed
|
||||
vec4 volume_origin;
|
||||
};
|
||||
|
||||
uniform PrintBoxDetection print_box;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying vec3 delta_box_min;
|
||||
varying vec3 delta_box_max;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 eye, normal, lightDir, viewVector, halfVector;
|
||||
float NdotL, NdotHV;
|
||||
vec3 eye = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz);
|
||||
|
||||
eye = vec3(0., 0., 1.);
|
||||
|
||||
// First transform the normal into eye space and normalize the result.
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space.
|
||||
// Also since we're talking about a directional light, the position field is actually direction.
|
||||
lightDir = vec3(LIGHT_TOP_DIR);
|
||||
halfVector = normalize(lightDir + eye);
|
||||
vec3 halfVector = normalize(LIGHT_TOP_DIR + eye);
|
||||
|
||||
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
|
||||
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
|
||||
NdotL = max(dot(normal, lightDir), 0.0);
|
||||
float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity_tainted = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
intensity_specular = 0.;
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
intensity.y = 0.0;
|
||||
|
||||
if (NdotL > 0.0)
|
||||
intensity_specular = LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS);
|
||||
intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source.
|
||||
lightDir = vec3(LIGHT_FRONT_DIR);
|
||||
// halfVector = normalize(lightDir + eye);
|
||||
NdotL = max(dot(normal, lightDir), 0.0);
|
||||
intensity_tainted += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
// compute the specular term if NdotL is larger than zero
|
||||
// if (NdotL > 0.0)
|
||||
// intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_FRONT_SHININESS);
|
||||
// compute deltas for out of print volume detection (world coordinates)
|
||||
if (print_box.volume_origin.w == 1.0)
|
||||
{
|
||||
vec3 v = gl_Vertex.xyz + print_box.volume_origin.xyz;
|
||||
delta_box_min = v - print_box.min;
|
||||
delta_box_max = v - print_box.max;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta_box_min = ZERO;
|
||||
delta_box_max = ZERO;
|
||||
}
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
@ -1754,16 +1812,25 @@ sub _fragment_shader_Gouraud {
|
|||
return <<'FRAGMENT';
|
||||
#version 110
|
||||
|
||||
varying float intensity_specular;
|
||||
varying float intensity_tainted;
|
||||
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying vec3 delta_box_min;
|
||||
varying vec3 delta_box_max;
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor =
|
||||
vec4(intensity_specular, intensity_specular, intensity_specular, 0.) + uniform_color * intensity_tainted;
|
||||
gl_FragColor.a = uniform_color.a;
|
||||
gl_FragColor = vec4(intensity.y, intensity.y, intensity.y, 0.0) + uniform_color * intensity.x;
|
||||
|
||||
// if the fragment is outside the print volume darken it and set it as transparent
|
||||
if (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO)))
|
||||
gl_FragColor = vec4(mix(gl_FragColor.xyz, ZERO, 0.5), 0.5 * uniform_color.a);
|
||||
else
|
||||
gl_FragColor.a = uniform_color.a;
|
||||
}
|
||||
|
||||
FRAGMENT
|
||||
|
@ -1828,6 +1895,7 @@ void main() {
|
|||
// compute the specular term into spec
|
||||
// intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(h,normal), 0.0), LIGHT_FRONT_SHININESS);
|
||||
}
|
||||
|
||||
gl_FragColor = max(
|
||||
vec4(intensity_specular, intensity_specular, intensity_specular, 0.) + uniform_color * intensity_tainted,
|
||||
INTENSITY_AMBIENT * uniform_color);
|
||||
|
@ -1840,61 +1908,55 @@ sub _vertex_shader_variable_layer_height {
|
|||
return <<'VERTEX';
|
||||
#version 110
|
||||
|
||||
#define LIGHT_TOP_DIR 0., 1., 0.
|
||||
#define LIGHT_TOP_DIFFUSE 0.2
|
||||
#define LIGHT_TOP_SPECULAR 0.3
|
||||
#define LIGHT_TOP_SHININESS 50.
|
||||
#define INTENSITY_CORRECTION 0.6
|
||||
|
||||
#define LIGHT_FRONT_DIR 0., 0., 1.
|
||||
#define LIGHT_FRONT_DIFFUSE 0.5
|
||||
#define LIGHT_FRONT_SPECULAR 0.3
|
||||
#define LIGHT_FRONT_SHININESS 50.
|
||||
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.25 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 200.0
|
||||
|
||||
#define INTENSITY_AMBIENT 0.1
|
||||
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
|
||||
//#define LIGHT_FRONT_SHININESS 5.0
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
uniform float z_to_texture_row;
|
||||
varying float intensity_specular;
|
||||
varying float intensity_tainted;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying float object_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 eye, normal, lightDir, viewVector, halfVector;
|
||||
float NdotL, NdotHV;
|
||||
vec3 eye = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz);
|
||||
|
||||
// eye = gl_ModelViewMatrixInverse[3].xyz;
|
||||
eye = vec3(0., 0., 1.);
|
||||
|
||||
// First transform the normal into eye space and normalize the result.
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space.
|
||||
// Also since we're talking about a directional light, the position field is actually direction.
|
||||
lightDir = vec3(LIGHT_TOP_DIR);
|
||||
halfVector = normalize(lightDir + eye);
|
||||
vec3 halfVector = normalize(LIGHT_TOP_DIR + eye);
|
||||
|
||||
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
|
||||
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
|
||||
NdotL = max(dot(normal, lightDir), 0.0);
|
||||
float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity_tainted = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
intensity_specular = 0.;
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
intensity.y = 0.0;
|
||||
|
||||
// if (NdotL > 0.0)
|
||||
// intensity_specular = LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source.
|
||||
lightDir = vec3(LIGHT_FRONT_DIR);
|
||||
halfVector = normalize(lightDir + eye);
|
||||
NdotL = max(dot(normal, lightDir), 0.0);
|
||||
intensity_tainted += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
// compute the specular term if NdotL is larger than zero
|
||||
if (NdotL > 0.0)
|
||||
intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_FRONT_SHININESS);
|
||||
intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular)
|
||||
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
|
||||
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
// Scaled to widths of the Z texture.
|
||||
object_z = gl_Vertex.z / gl_Vertex.w;
|
||||
object_z = gl_Vertex.z;
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
@ -1913,13 +1975,14 @@ uniform sampler2D z_texture;
|
|||
// Scaling from the Z texture rows coordinate to the normalized texture row coordinate.
|
||||
uniform float z_to_texture_row;
|
||||
uniform float z_texture_row_to_normalized;
|
||||
|
||||
varying float intensity_specular;
|
||||
varying float intensity_tainted;
|
||||
varying float object_z;
|
||||
uniform float z_cursor;
|
||||
uniform float z_cursor_band_width;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying float object_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
float object_z_row = z_to_texture_row * object_z;
|
||||
|
@ -1938,15 +2001,12 @@ void main()
|
|||
float lod = clamp(0.5 * log2(max(dx_vtc*dx_vtc, dy_vtc*dy_vtc)), 0., 1.);
|
||||
// Sample the Z texture. Texture coordinates are normalized to <0, 1>.
|
||||
vec4 color =
|
||||
(1. - lod) * texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.) +
|
||||
lod * texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.);
|
||||
mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.),
|
||||
texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod);
|
||||
|
||||
// Mix the final color.
|
||||
gl_FragColor =
|
||||
vec4(intensity_specular, intensity_specular, intensity_specular, 1.) +
|
||||
(1. - z_blend) * intensity_tainted * color +
|
||||
z_blend * vec4(1., 1., 0., 0.);
|
||||
// and reset the transparency.
|
||||
gl_FragColor.a = 1.;
|
||||
vec4(intensity.y, intensity.y, intensity.y, 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
|
||||
}
|
||||
|
||||
FRAGMENT
|
||||
|
|
|
@ -25,10 +25,6 @@ our $last_config;
|
|||
our $VALUE_CHANGE_EVENT = Wx::NewEventType;
|
||||
# 2) To inform about a preset selection change or a "modified" status change.
|
||||
our $PRESETS_CHANGED_EVENT = Wx::NewEventType;
|
||||
# 3) To inform about a click on Browse button
|
||||
our $BUTTON_BROWSE_EVENT = Wx::NewEventType;
|
||||
# 4) To inform about a click on Test button
|
||||
our $BUTTON_TEST_EVENT = Wx::NewEventType;
|
||||
|
||||
sub new {
|
||||
my ($class, %params) = @_;
|
||||
|
@ -169,59 +165,7 @@ sub _init_tabpanel {
|
|||
}
|
||||
}
|
||||
});
|
||||
# The following event is emited by the C++ Tab implementation ,
|
||||
# when the Browse button was clicked
|
||||
EVT_COMMAND($self, -1, $BUTTON_BROWSE_EVENT, sub {
|
||||
my ($self, $event) = @_;
|
||||
my $msg = $event->GetString;
|
||||
|
||||
# look for devices
|
||||
my $entries;
|
||||
{
|
||||
my $res = Net::Bonjour->new('http');
|
||||
$res->discover;
|
||||
$entries = [ $res->entries ];
|
||||
}
|
||||
if (@{$entries}) {
|
||||
my $dlg = Slic3r::GUI::BonjourBrowser->new($self, $entries);
|
||||
my $tab = Slic3r::GUI::get_preset_tab("printer");
|
||||
$tab->load_key_value('octoprint_host', $dlg->GetValue . ":" . $dlg->GetPort)
|
||||
if $dlg->ShowModal == wxID_OK;
|
||||
} else {
|
||||
Wx::MessageDialog->new($self, L('No Bonjour device found'), L('Device Browser'), wxOK | wxICON_INFORMATION)->ShowModal;
|
||||
}
|
||||
});
|
||||
# The following event is emited by the C++ Tab implementation ,
|
||||
# when the Test button was clicked
|
||||
EVT_COMMAND($self, -1, $BUTTON_TEST_EVENT, sub {
|
||||
my ($self, $event) = @_;
|
||||
my $msg = $event->GetString;
|
||||
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->timeout(10);
|
||||
|
||||
my $config = Slic3r::GUI::get_preset_tab("printer")->get_config;
|
||||
my $res = $ua->get(
|
||||
"http://" . $config->octoprint_host . "/api/version",
|
||||
'X-Api-Key' => $config->octoprint_apikey,
|
||||
);
|
||||
if ($res->is_success) {
|
||||
Slic3r::GUI::show_info($self, L("Connection to OctoPrint works correctly."), _L("Success!"));
|
||||
} else {
|
||||
Slic3r::GUI::show_error($self,
|
||||
L("I wasn't able to connect to OctoPrint (") . $res->status_line .
|
||||
L("). Check hostname and OctoPrint version (at least 1.1.0 is required)."));
|
||||
}
|
||||
});
|
||||
# A variable to inform C++ Tab implementation about disabling of Browse button
|
||||
$self->{is_disabled_button_browse} = (!eval "use Net::Bonjour; 1") ? 1 : 0 ;
|
||||
# A variable to inform C++ Tab implementation about user_agent
|
||||
$self->{is_user_agent} = (eval "use LWP::UserAgent; 1") ? 1 : 0 ;
|
||||
Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, $self->{no_controller},
|
||||
$self->{is_disabled_button_browse},
|
||||
$self->{is_user_agent},
|
||||
$VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT,
|
||||
$BUTTON_BROWSE_EVENT, $BUTTON_TEST_EVENT);
|
||||
Slic3r::GUI::create_preset_tabs($self->{no_controller}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT);
|
||||
$self->{options_tabs} = {};
|
||||
for my $tab_name (qw(print filament printer)) {
|
||||
$self->{options_tabs}{$tab_name} = Slic3r::GUI::get_preset_tab("$tab_name");
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
# Notify about the end of slicing.
|
||||
# The notifications are sent out using the Growl protocol if installed, and using DBus XWindow protocol.
|
||||
|
||||
package Slic3r::GUI::Notifier;
|
||||
use Moo;
|
||||
|
||||
has 'growler' => (is => 'rw');
|
||||
|
||||
my $icon = Slic3r::var("Slic3r.png");
|
||||
|
||||
sub BUILD {
|
||||
my ($self) = @_;
|
||||
|
||||
if (eval 'use Growl::GNTP; 1') {
|
||||
# register with growl
|
||||
eval {
|
||||
$self->growler(Growl::GNTP->new(AppName => 'Slic3r', AppIcon => $icon));
|
||||
$self->growler->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]);
|
||||
};
|
||||
# if register() fails (for example because of a timeout), disable growler at all
|
||||
$self->growler(undef) if $@;
|
||||
}
|
||||
}
|
||||
|
||||
sub notify {
|
||||
my ($self, $message) = @_;
|
||||
my $title = 'Slicing Done!';
|
||||
|
||||
eval {
|
||||
$self->growler->notify(Event => 'SKEIN_DONE', Title => $title, Message => $message)
|
||||
if $self->growler;
|
||||
};
|
||||
# Net::DBus is broken in multithreaded environment
|
||||
if (0 && eval 'use Net::DBus; 1') {
|
||||
eval {
|
||||
my $session = Net::DBus->session;
|
||||
my $serv = $session->get_service('org.freedesktop.Notifications');
|
||||
my $notifier = $serv->get_object('/org/freedesktop/Notifications',
|
||||
'org.freedesktop.Notifications');
|
||||
$notifier->Notify('Slic3r', 0, $icon, $title, $message, [], {}, -1);
|
||||
undef $Net::DBus::bus_session;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -8,7 +8,6 @@ use utf8;
|
|||
use File::Basename qw(basename dirname);
|
||||
use List::Util qw(sum first max);
|
||||
use Slic3r::Geometry qw(X Y Z scale unscale deg2rad rad2deg);
|
||||
use LWP::UserAgent;
|
||||
use threads::shared qw(shared_clone);
|
||||
use Wx qw(:button :colour :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc
|
||||
:panel :sizer :toolbar :window wxTheApp :notebook :combobox wxNullBitmap);
|
||||
|
@ -53,8 +52,9 @@ sub new {
|
|||
$self->{config} = Slic3r::Config::new_from_defaults_keys([qw(
|
||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||
serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile
|
||||
nozzle_diameter single_extruder_multi_material
|
||||
wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe wipe_tower_rotation_angle extruder_colour filament_colour
|
||||
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width
|
||||
wipe_tower_per_color_wipe wipe_tower_rotation_angle extruder_colour filament_colour
|
||||
max_print_height
|
||||
)]);
|
||||
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
||||
$self->{model} = Slic3r::Model->new;
|
||||
|
@ -113,6 +113,7 @@ sub new {
|
|||
$self->{canvas3D}->set_on_decrease_objects(sub { $self->decrease() });
|
||||
$self->{canvas3D}->set_on_remove_object(sub { $self->remove() });
|
||||
$self->{canvas3D}->set_on_instances_moved($on_instances_moved);
|
||||
$self->{canvas3D}->use_plain_shader(1);
|
||||
$self->{canvas3D}->set_on_wipe_tower_moved(sub {
|
||||
my ($new_pos_3f) = @_;
|
||||
my $cfg = Slic3r::Config->new;
|
||||
|
@ -389,9 +390,12 @@ sub new {
|
|||
});
|
||||
});
|
||||
$presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4);
|
||||
$presets->Add($choice, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 0);
|
||||
$presets->Add($choice, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 1);
|
||||
}
|
||||
}
|
||||
|
||||
my $frequently_changed_parameters_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
Slic3r::GUI::add_frequently_changed_parameters($self, $frequently_changed_parameters_sizer, $presets);
|
||||
|
||||
my $object_info_sizer;
|
||||
{
|
||||
|
@ -473,14 +477,15 @@ sub new {
|
|||
|
||||
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
$right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets;
|
||||
$right_sizer->Add($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 10) if defined $frequently_changed_parameters_sizer;
|
||||
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
$right_sizer->Add($self->{list}, 1, wxEXPAND, 5);
|
||||
$right_sizer->Add($object_info_sizer, 0, wxEXPAND, 0);
|
||||
$right_sizer->Add($print_info_sizer, 0, wxEXPAND, 0);
|
||||
# Callback for showing / hiding the print info box.
|
||||
$self->{"print_info_box_show"} = sub {
|
||||
if ($right_sizer->IsShown(4) != $_[0]) {
|
||||
$right_sizer->Show(4, $_[0]);
|
||||
if ($right_sizer->IsShown(5) != $_[0]) {
|
||||
$right_sizer->Show(5, $_[0]);
|
||||
$self->Layout
|
||||
}
|
||||
};
|
||||
|
@ -1737,6 +1742,8 @@ sub on_config_change {
|
|||
$update_scheduled = 1;
|
||||
my $extruder_colors = $config->get('extruder_colour');
|
||||
$self->{preview3D}->set_number_extruders(scalar(@{$extruder_colors}));
|
||||
} elsif ($opt_key eq 'max_print_height') {
|
||||
$update_scheduled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1934,6 +1941,7 @@ sub selection_changed {
|
|||
$self->{object_info_manifold_warning_icon}->SetToolTipString($message);
|
||||
} else {
|
||||
$self->{object_info_manifold}->SetLabel(L("Yes"));
|
||||
$self->{object_info_manifold_warning_icon}->Hide;
|
||||
}
|
||||
} else {
|
||||
$self->{object_info_facets}->SetLabel($object->facets);
|
||||
|
|
|
@ -8,6 +8,8 @@ use Wx qw(:misc :pen :brush :sizer :font :cursor :keycode wxTAB_TRAVERSAL);
|
|||
use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR);
|
||||
use base qw(Slic3r::GUI::3DScene Class::Accessor);
|
||||
|
||||
use Wx::Locale gettext => 'L';
|
||||
|
||||
__PACKAGE__->mk_accessors(qw(
|
||||
on_arrange on_rotate_object_left on_rotate_object_right on_scale_object_uniformly
|
||||
on_remove_object on_increase_objects on_decrease_objects));
|
||||
|
@ -208,6 +210,19 @@ sub reload_scene {
|
|||
$self->{model}->bounding_box->z_max, $self->{config}->wipe_tower_rotation_angle, $self->UseVBOs);
|
||||
}
|
||||
}
|
||||
|
||||
# checks for geometry outside the print volume to render it accordingly
|
||||
if (scalar @{$self->volumes} > 0)
|
||||
{
|
||||
if (!$self->{model}->fits_print_volume($self->{config})) {
|
||||
$self->set_warning_enabled(1);
|
||||
Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
||||
} else {
|
||||
$self->set_warning_enabled(0);
|
||||
$self->volumes->update_outside_state($self->{config}, 1);
|
||||
Slic3r::GUI::_3DScene::reset_warning_texture();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub update_bed_size {
|
||||
|
|
|
@ -253,19 +253,19 @@ sub new {
|
|||
|
||||
# sets colors for gcode preview extrusion roles
|
||||
my @extrusion_roles_colors = (
|
||||
'Perimeter' => 'FFA500',
|
||||
'External perimeter' => 'FFFF66',
|
||||
'Perimeter' => 'FFFF66',
|
||||
'External perimeter' => 'FFA500',
|
||||
'Overhang perimeter' => '0000FF',
|
||||
'Internal infill' => 'FF0000',
|
||||
'Solid infill' => 'CD00CD',
|
||||
'Top solid infill' => 'FF3333',
|
||||
'Internal infill' => 'B1302A',
|
||||
'Solid infill' => 'D732D7',
|
||||
'Top solid infill' => 'FF1A1A',
|
||||
'Bridge infill' => '9999FF',
|
||||
'Gap fill' => 'FFFFFF',
|
||||
'Skirt' => '7F0000',
|
||||
'Skirt' => '845321',
|
||||
'Support material' => '00FF00',
|
||||
'Support material interface' => '008000',
|
||||
'Wipe tower' => 'B3E3AB',
|
||||
'Custom' => 'FFFF00',
|
||||
'Custom' => '28CC94',
|
||||
);
|
||||
$self->gcode_preview_data->set_extrusion_paths_colors(\@extrusion_roles_colors);
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ require Exporter;
|
|||
our @ISA = qw(Exporter);
|
||||
our @EXPORT_OK = qw(_eq);
|
||||
|
||||
use IO::Scalar;
|
||||
use List::Util qw(first);
|
||||
use Slic3r::Geometry qw(epsilon X Y Z);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue