Merge branch 'scene_manipulators' of https://github.com/prusa3d/Slic3r

This commit is contained in:
Enrico Turri 2018-07-24 10:03:45 +02:00
commit bbe5586c15
18 changed files with 82 additions and 67 deletions

View File

@ -127,6 +127,8 @@ sub new {
$range->[1] *= $variation; $range->[1] *= $variation;
} }
$_->set_scaling_factor($scale) for @{ $model_object->instances }; $_->set_scaling_factor($scale) for @{ $model_object->instances };
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
$object->transform_thumbnail($self->{model}, $obj_idx); $object->transform_thumbnail($self->{model}, $obj_idx);
#update print and start background processing #update print and start background processing
@ -2100,7 +2102,8 @@ sub object_list_changed {
my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file}; my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file};
my $model_fits = $self->{canvas3D} ? Slic3r::GUI::_3DScene::check_volumes_outside_state($self->{canvas3D}, $self->{config}) : 1; my $model_fits = $self->{canvas3D} ? Slic3r::GUI::_3DScene::check_volumes_outside_state($self->{canvas3D}, $self->{config}) : 1;
my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable'; # $model_fits == 1 -> ModelInstance::PVS_Partly_Outside
my $method = ($have_objects && ! $export_in_progress && ($model_fits != 1)) ? 'Enable' : 'Disable';
$self->{"btn_$_"}->$method $self->{"btn_$_"}->$method
for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode);
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 186 KiB

View File

@ -1989,7 +1989,7 @@ namespace Slic3r {
// stores object's name // stores object's name
if (!obj->name.empty()) if (!obj->name.empty())
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"name\" " << VALUE_ATTR << "=\"" << obj->name << "\"/>\n"; stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"name\" " << VALUE_ATTR << "=\"" << xml_escape(obj->name) << "\"/>\n";
// stores object's config data // stores object's config data
for (const std::string& key : obj->config.keys()) for (const std::string& key : obj->config.keys())
@ -2012,7 +2012,7 @@ namespace Slic3r {
// stores volume's name // stores volume's name
if (!volume->name.empty()) if (!volume->name.empty())
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << NAME_KEY << "\" " << VALUE_ATTR << "=\"" << volume->name << "\"/>\n"; stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << NAME_KEY << "\" " << VALUE_ATTR << "=\"" << xml_escape(volume->name) << "\"/>\n";
// stores volume's modifier field // stores volume's modifier field
if (volume->modifier) if (volume->modifier)

View File

@ -8,6 +8,7 @@
#include "../libslic3r.h" #include "../libslic3r.h"
#include "../Model.hpp" #include "../Model.hpp"
#include "../GCode.hpp" #include "../GCode.hpp"
#include "../Utils.hpp"
#include "../slic3r/GUI/PresetBundle.hpp" #include "../slic3r/GUI/PresetBundle.hpp"
#include "AMF.hpp" #include "AMF.hpp"
@ -686,33 +687,6 @@ bool load_amf(const char *path, PresetBundle* bundle, Model *model)
return false; return false;
} }
std::string xml_escape(std::string text)
{
std::string::size_type pos = 0;
for (;;)
{
pos = text.find_first_of("\"\'&<>", pos);
if (pos == std::string::npos)
break;
std::string replacement;
switch (text[pos])
{
case '\"': replacement = "&quot;"; break;
case '\'': replacement = "&apos;"; break;
case '&': replacement = "&amp;"; break;
case '<': replacement = "&lt;"; break;
case '>': replacement = "&gt;"; break;
default: break;
}
text.replace(pos, 1, replacement);
pos += replacement.size();
}
return text;
}
bool store_amf(const char *path, Model *model, Print* print, bool export_print_config) bool store_amf(const char *path, Model *model, Print* print, bool export_print_config)
{ {
if ((path == nullptr) || (model == nullptr) || (print == nullptr)) if ((path == nullptr) || (model == nullptr) || (print == nullptr))
@ -761,7 +735,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
for (const std::string &key : object->config.keys()) for (const std::string &key : object->config.keys())
stream << " <metadata type=\"slic3r." << key << "\">" << object->config.serialize(key) << "</metadata>\n"; stream << " <metadata type=\"slic3r." << key << "\">" << object->config.serialize(key) << "</metadata>\n";
if (!object->name.empty()) if (!object->name.empty())
stream << " <metadata type=\"name\">" << object->name << "</metadata>\n"; stream << " <metadata type=\"name\">" << xml_escape(object->name) << "</metadata>\n";
std::vector<double> layer_height_profile = object->layer_height_profile_valid ? object->layer_height_profile : std::vector<double>(); std::vector<double> layer_height_profile = object->layer_height_profile_valid ? object->layer_height_profile : std::vector<double>();
if (layer_height_profile.size() >= 4 && (layer_height_profile.size() % 2) == 0) { if (layer_height_profile.size() >= 4 && (layer_height_profile.size() % 2) == 0) {
// Store the layer height profile as a single semicolon separated list. // Store the layer height profile as a single semicolon separated list.
@ -805,7 +779,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
for (const std::string &key : volume->config.keys()) for (const std::string &key : volume->config.keys())
stream << " <metadata type=\"slic3r." << key << "\">" << volume->config.serialize(key) << "</metadata>\n"; stream << " <metadata type=\"slic3r." << key << "\">" << volume->config.serialize(key) << "</metadata>\n";
if (!volume->name.empty()) if (!volume->name.empty())
stream << " <metadata type=\"name\">" << volume->name << "</metadata>\n"; stream << " <metadata type=\"name\">" << xml_escape(volume->name) << "</metadata>\n";
if (volume->modifier) if (volume->modifier)
stream << " <metadata type=\"slic3r.modifier\">1</metadata>\n"; stream << " <metadata type=\"slic3r.modifier\">1</metadata>\n";
for (int i = 0; i < volume->mesh.stl.stats.number_of_facets; ++i) { for (int i = 0; i < volume->mesh.stl.stats.number_of_facets; ++i) {

View File

@ -309,10 +309,12 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
size_t object_idx; size_t object_idx;
size_t layer_idx; size_t layer_idx;
}; };
std::vector<std::vector<LayerToPrint>> per_object(print.objects.size(), std::vector<LayerToPrint>());
PrintObjectPtrs printable_objects = print.get_printable_objects();
std::vector<std::vector<LayerToPrint>> per_object(printable_objects.size(), std::vector<LayerToPrint>());
std::vector<OrderingItem> ordering; std::vector<OrderingItem> ordering;
for (size_t i = 0; i < print.objects.size(); ++ i) { for (size_t i = 0; i < printable_objects.size(); ++i) {
per_object[i] = collect_layers_to_print(*print.objects[i]); per_object[i] = collect_layers_to_print(*printable_objects[i]);
OrderingItem ordering_item; OrderingItem ordering_item;
ordering_item.object_idx = i; ordering_item.object_idx = i;
ordering.reserve(ordering.size() + per_object[i].size()); ordering.reserve(ordering.size() + per_object[i].size());
@ -337,8 +339,8 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
std::pair<coordf_t, std::vector<LayerToPrint>> merged; std::pair<coordf_t, std::vector<LayerToPrint>> merged;
// Assign an average print_z to the set of layers with nearly equal print_z. // Assign an average print_z to the set of layers with nearly equal print_z.
merged.first = 0.5 * (ordering[i].print_z + ordering[j-1].print_z); merged.first = 0.5 * (ordering[i].print_z + ordering[j-1].print_z);
merged.second.assign(print.objects.size(), LayerToPrint()); merged.second.assign(printable_objects.size(), LayerToPrint());
for (; i < j; ++ i) { for (; i < j; ++i) {
const OrderingItem &oi = ordering[i]; const OrderingItem &oi = ordering[i];
assert(merged.second[oi.object_idx].layer() == nullptr); assert(merged.second[oi.object_idx].layer() == nullptr);
merged.second[oi.object_idx] = std::move(per_object[oi.object_idx][oi.layer_idx]); merged.second[oi.object_idx] = std::move(per_object[oi.object_idx][oi.layer_idx]);
@ -472,9 +474,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
// How many times will be change_layer() called? // How many times will be change_layer() called?
// change_layer() in turn increments the progress bar status. // change_layer() in turn increments the progress bar status.
m_layer_count = 0; m_layer_count = 0;
PrintObjectPtrs printable_objects = print.get_printable_objects();
if (print.config.complete_objects.value) { if (print.config.complete_objects.value) {
// Add each of the object's layers separately. // Add each of the object's layers separately.
for (auto object : print.objects) { for (auto object : printable_objects) {
std::vector<coordf_t> zs; std::vector<coordf_t> zs;
zs.reserve(object->layers.size() + object->support_layers.size()); zs.reserve(object->layers.size() + object->support_layers.size());
for (auto layer : object->layers) for (auto layer : object->layers)
@ -487,7 +490,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
} else { } else {
// Print all objects with the same print_z together. // Print all objects with the same print_z together.
std::vector<coordf_t> zs; std::vector<coordf_t> zs;
for (auto object : print.objects) { for (auto object : printable_objects) {
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size()); zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
for (auto layer : object->layers) for (auto layer : object->layers)
zs.push_back(layer->print_z); zs.push_back(layer->print_z);
@ -506,8 +509,8 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
{ {
// get the minimum cross-section used in the print // get the minimum cross-section used in the print
std::vector<double> mm3_per_mm; std::vector<double> mm3_per_mm;
for (auto object : print.objects) { for (auto object : printable_objects) {
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) { for (size_t region_id = 0; region_id < print.regions.size(); ++region_id) {
auto region = print.regions[region_id]; auto region = print.regions[region_id];
for (auto layer : object->layers) { for (auto layer : object->layers) {
auto layerm = layer->regions[region_id]; auto layerm = layer->regions[region_id];
@ -567,7 +570,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
_write(file, "\n"); _write(file, "\n");
} }
// Write some terse information on the slicing parameters. // Write some terse information on the slicing parameters.
const PrintObject *first_object = print.objects.front(); const PrintObject *first_object = printable_objects.front();
const double layer_height = first_object->config.layer_height.value; const double layer_height = first_object->config.layer_height.value;
const double first_layer_height = first_object->config.first_layer_height.get_abs_value(layer_height); const double first_layer_height = first_object->config.first_layer_height.get_abs_value(layer_height);
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) { for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
@ -596,13 +599,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
size_t initial_print_object_id = 0; size_t initial_print_object_id = 0;
bool has_wipe_tower = false; bool has_wipe_tower = false;
if (print.config.complete_objects.value) { if (print.config.complete_objects.value) {
// Find the 1st printing object, find its tool ordering and the initial extruder ID. // Find the 1st printing object, find its tool ordering and the initial extruder ID.
for (; initial_print_object_id < print.objects.size(); ++initial_print_object_id) { for (; initial_print_object_id < printable_objects.size(); ++initial_print_object_id) {
tool_ordering = ToolOrdering(*print.objects[initial_print_object_id], initial_extruder_id); tool_ordering = ToolOrdering(*printable_objects[initial_print_object_id], initial_extruder_id);
if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1) if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1)
break; break;
} }
} else { }
else {
// Find tool ordering for all the objects at once, and the initial extruder ID. // Find tool ordering for all the objects at once, and the initial extruder ID.
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it. // If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
tool_ordering = print.m_tool_ordering.empty() ? tool_ordering = print.m_tool_ordering.empty() ?
@ -676,7 +680,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
// Collect outer contours of all objects over all layers. // Collect outer contours of all objects over all layers.
// Discard objects only containing thin walls (offset would fail on an empty polygon). // Discard objects only containing thin walls (offset would fail on an empty polygon).
Polygons islands; Polygons islands;
for (const PrintObject *object : print.objects) for (const PrintObject *object : printable_objects)
for (const Layer *layer : object->layers) for (const Layer *layer : object->layers)
for (const ExPolygon &expoly : layer->slices.expolygons) for (const ExPolygon &expoly : layer->slices.expolygons)
for (const Point &copy : object->_shifted_copies) { for (const Point &copy : object->_shifted_copies) {
@ -724,7 +728,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
if (print.config.complete_objects.value) { if (print.config.complete_objects.value) {
// Print objects from the smallest to the tallest to avoid collisions // Print objects from the smallest to the tallest to avoid collisions
// when moving onto next object starting point. // when moving onto next object starting point.
std::vector<PrintObject*> objects(print.objects); std::vector<PrintObject*> objects(printable_objects);
std::sort(objects.begin(), objects.end(), [](const PrintObject* po1, const PrintObject* po2) { return po1->size.z < po2->size.z; }); std::sort(objects.begin(), objects.end(), [](const PrintObject* po1, const PrintObject* po2) { return po1->size.z < po2->size.z; });
size_t finished_objects = 0; size_t finished_objects = 0;
for (size_t object_id = initial_print_object_id; object_id < objects.size(); ++ object_id) { for (size_t object_id = initial_print_object_id; object_id < objects.size(); ++ object_id) {
@ -788,7 +792,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
PrintObjectPtrs printable_objects = print.get_printable_objects(); PrintObjectPtrs printable_objects = print.get_printable_objects();
for (PrintObject *object : printable_objects) for (PrintObject *object : printable_objects)
object_reference_points.push_back(object->_shifted_copies.front()); object_reference_points.push_back(object->_shifted_copies.front());
Slic3r::Geometry::chained_path(object_reference_points, object_indices); Slic3r::Geometry::chained_path(object_reference_points, object_indices);
// Sort layers by Z. // Sort layers by Z.
// All extrusion moves with the same top layer height are extruded uninterrupted. // All extrusion moves with the same top layer height are extruded uninterrupted.
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print); std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);

View File

@ -451,10 +451,9 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
return volume_to_wipe; // Soluble filament cannot be wiped in a random infill, neither the filament after it return volume_to_wipe; // Soluble filament cannot be wiped in a random infill, neither the filament after it
// we will sort objects so that dedicated for wiping are at the beginning: // we will sort objects so that dedicated for wiping are at the beginning:
PrintObjectPtrs object_list = print.objects; PrintObjectPtrs object_list = print.get_printable_objects();
std::sort(object_list.begin(), object_list.end(), [](const PrintObject* a, const PrintObject* b) { return a->config.wipe_into_objects; }); std::sort(object_list.begin(), object_list.end(), [](const PrintObject* a, const PrintObject* b) { return a->config.wipe_into_objects; });
// We will now iterate through // We will now iterate through
// - first the dedicated objects to mark perimeters or infills (depending on infill_first) // - first the dedicated objects to mark perimeters or infills (depending on infill_first)
// - second through the dedicated ones again to mark infills or perimeters (depending on infill_first) // - second through the dedicated ones again to mark infills or perimeters (depending on infill_first)
@ -548,7 +547,8 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
unsigned int first_nonsoluble_extruder = first_nonsoluble_extruder_on_layer(print.config); unsigned int first_nonsoluble_extruder = first_nonsoluble_extruder_on_layer(print.config);
unsigned int last_nonsoluble_extruder = last_nonsoluble_extruder_on_layer(print.config); unsigned int last_nonsoluble_extruder = last_nonsoluble_extruder_on_layer(print.config);
for (const PrintObject* object : print.objects) { PrintObjectPtrs printable_objects = print.get_printable_objects();
for (const PrintObject* object : printable_objects) {
// Finds this layer: // Finds this layer:
auto this_layer_it = std::find_if(object->layers.begin(), object->layers.end(), [&lt](const Layer* lay) { return std::abs(lt.print_z - lay->print_z)<EPSILON; }); auto this_layer_it = std::find_if(object->layers.begin(), object->layers.end(), [&lt](const Layer* lay) { return std::abs(lt.print_z - lay->print_z)<EPSILON; });
if (this_layer_it == object->layers.end()) if (this_layer_it == object->layers.end())

View File

@ -84,6 +84,8 @@ inline T next_highest_power_of_2(T v)
return ++ v; return ++ v;
} }
extern std::string xml_escape(std::string text);
class PerlCallback { class PerlCallback {
public: public:
PerlCallback(void *sv) : m_callback(nullptr) { this->register_callback(sv); } PerlCallback(void *sv) : m_callback(nullptr) { this->register_callback(sv); }

View File

@ -387,4 +387,31 @@ unsigned get_current_pid()
#endif #endif
} }
std::string xml_escape(std::string text)
{
std::string::size_type pos = 0;
for (;;)
{
pos = text.find_first_of("\"\'&<>", pos);
if (pos == std::string::npos)
break;
std::string replacement;
switch (text[pos])
{
case '\"': replacement = "&quot;"; break;
case '\'': replacement = "&apos;"; break;
case '&': replacement = "&amp;"; break;
case '<': replacement = "&lt;"; break;
case '>': replacement = "&gt;"; break;
default: break;
}
text.replace(pos, 1, replacement);
pos += replacement.size();
}
return text;
}
}; // namespace Slic3r }; // namespace Slic3r

View File

@ -1651,7 +1651,7 @@ void _3DScene::update_volumes_selection(wxGLCanvas* canvas, const std::vector<in
s_canvas_mgr.update_volumes_selection(canvas, selections); s_canvas_mgr.update_volumes_selection(canvas, selections);
} }
bool _3DScene::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) int _3DScene::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config)
{ {
return s_canvas_mgr.check_volumes_outside_state(canvas, config); return s_canvas_mgr.check_volumes_outside_state(canvas, config);
} }

View File

@ -460,7 +460,7 @@ public:
static void deselect_volumes(wxGLCanvas* canvas); static void deselect_volumes(wxGLCanvas* canvas);
static void select_volume(wxGLCanvas* canvas, unsigned int id); static void select_volume(wxGLCanvas* canvas, unsigned int id);
static void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections); static void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
static bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config); static int check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config);
static bool move_volume_up(wxGLCanvas* canvas, unsigned int id); static bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
static bool move_volume_down(wxGLCanvas* canvas, unsigned int id); static bool move_volume_down(wxGLCanvas* canvas, unsigned int id);

View File

@ -1878,9 +1878,11 @@ void GLCanvas3D::update_volumes_selection(const std::vector<int>& selections)
} }
} }
bool GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const int GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const
{ {
return m_volumes.check_outside_state(config, nullptr); ModelInstance::EPrintVolumeState state;
m_volumes.check_outside_state(config, &state);
return (int)state;
} }
bool GLCanvas3D::move_volume_up(unsigned int id) bool GLCanvas3D::move_volume_up(unsigned int id)

View File

@ -495,7 +495,7 @@ public:
void deselect_volumes(); void deselect_volumes();
void select_volume(unsigned int id); void select_volume(unsigned int id);
void update_volumes_selection(const std::vector<int>& selections); void update_volumes_selection(const std::vector<int>& selections);
bool check_volumes_outside_state(const DynamicPrintConfig* config) const; int check_volumes_outside_state(const DynamicPrintConfig* config) const;
bool move_volume_up(unsigned int id); bool move_volume_up(unsigned int id);
bool move_volume_down(unsigned int id); bool move_volume_down(unsigned int id);

View File

@ -237,7 +237,7 @@ void GLCanvas3DManager::update_volumes_selection(wxGLCanvas* canvas, const std::
it->second->update_volumes_selection(selections); it->second->update_volumes_selection(selections);
} }
bool GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const int GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const
{ {
CanvasesMap::const_iterator it = _get_canvas(canvas); CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->check_volumes_outside_state(config) : false; return (it != m_canvases.end()) ? it->second->check_volumes_outside_state(config) : false;

View File

@ -75,7 +75,7 @@ public:
void deselect_volumes(wxGLCanvas* canvas); void deselect_volumes(wxGLCanvas* canvas);
void select_volume(wxGLCanvas* canvas, unsigned int id); void select_volume(wxGLCanvas* canvas, unsigned int id);
void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections); void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const; int check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const;
bool move_volume_up(wxGLCanvas* canvas, unsigned int id); bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
bool move_volume_down(wxGLCanvas* canvas, unsigned int id); bool move_volume_down(wxGLCanvas* canvas, unsigned int id);

View File

@ -79,7 +79,8 @@ bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmap
if (generate_mipmaps) if (generate_mipmaps)
{ {
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards // we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
_generate_mipmaps(image); unsigned int levels_count = _generate_mipmaps(image);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1 + levels_count);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} }
else else
@ -149,14 +150,14 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo
::glDisable(GL_BLEND); ::glDisable(GL_BLEND);
} }
void GLTexture::_generate_mipmaps(wxImage& image) unsigned int GLTexture::_generate_mipmaps(wxImage& image)
{ {
int w = image.GetWidth(); int w = image.GetWidth();
int h = image.GetHeight(); int h = image.GetHeight();
GLint level = 0; GLint level = 0;
std::vector<unsigned char> data(w * h * 4, 0); std::vector<unsigned char> data(w * h * 4, 0);
while ((w > 1) && (h > 1)) while ((w > 1) || (h > 1))
{ {
++level; ++level;
@ -183,6 +184,8 @@ void GLTexture::_generate_mipmaps(wxImage& image)
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()); ::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
} }
return (unsigned int)level;
} }
} // namespace GUI } // namespace GUI

View File

@ -32,7 +32,7 @@ namespace GUI {
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top); static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
protected: protected:
void _generate_mipmaps(wxImage& image); unsigned int _generate_mipmaps(wxImage& image);
}; };
} // namespace GUI } // namespace GUI

View File

@ -230,7 +230,7 @@ update_volumes_selection(canvas, selections)
CODE: CODE:
_3DScene::update_volumes_selection((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), selections); _3DScene::update_volumes_selection((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), selections);
bool int
check_volumes_outside_state(canvas, config) check_volumes_outside_state(canvas, config)
SV *canvas; SV *canvas;
DynamicPrintConfig *config; DynamicPrintConfig *config;