Fixed a bug, where the GL context was not being activated with _set_current()

as _set_current() tested for visibility of the window on the screen.

Improved memory management by:
1) Allocating small (around 3MB) vertex buffers to be sent to the GPU.
2) Passing the small vertex buffers to the GPU as quickly as possible.

A bit of copy / paste refactoring into common functions.
This commit is contained in:
bubnikv 2019-08-26 11:12:48 +02:00
parent 9cbfe8f5ef
commit 85d9a16563
4 changed files with 182 additions and 202 deletions

View File

@ -585,6 +585,23 @@ int GLVolumeCollection::load_wipe_tower_preview(
return int(this->volumes.size() - 1);
}
GLVolume* GLVolumeCollection::new_toolpath_volume(const float *rgba, size_t reserve_vbo_floats)
{
GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats);
out->is_extrusion_path = true;
return out;
}
GLVolume* GLVolumeCollection::new_nontoolpath_volume(const float *rgba, size_t reserve_vbo_floats)
{
GLVolume *out = new GLVolume(rgba);
out->is_extrusion_path = false;
// Reserving number of vertices (3x position + 3x color)
out->indexed_vertex_array.reserve(reserve_vbo_floats / 6);
this->volumes.emplace_back(out);
return out;
}
GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func)
{
GLVolumeWithIdAndZList list;

View File

@ -522,6 +522,9 @@ public:
int load_wipe_tower_preview(
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized);
GLVolume* new_toolpath_volume(const float *rgba, size_t reserve_vbo_floats = 0);
GLVolume* new_nontoolpath_volume(const float *rgba, size_t reserve_vbo_floats = 0);
// Render the volumes by OpenGL.
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;

View File

@ -70,6 +70,11 @@ static const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f };
static const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f };
//static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
// Number of floats
static const float MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB
// Reserve size in number of floats.
static const float VERTEX_BUFFER_RESERVE_SIZE = 131072 * 2; // 1.05MB
namespace Slic3r {
namespace GUI {
@ -1518,14 +1523,8 @@ void GLCanvas3D::render()
if (m_canvas == nullptr)
return;
#ifndef __WXMAC__
// on Mac this check causes flickering when changing view
if (!_is_shown_on_screen())
return;
#endif // __WXMAC__
// ensures this canvas is current and initialized
if (!_set_current() || !_3DScene::init(m_canvas))
if (! _is_shown_on_screen() || !_set_current() || !_3DScene::init(m_canvas))
return;
#if ENABLE_RENDER_STATISTICS
@ -2084,6 +2083,52 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_dirty = true;
}
static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume& vol_old, bool gl_initialized)
{
// Assign the large pre-allocated buffers to the new GLVolume.
vol_new.indexed_vertex_array = std::move(vol_old.indexed_vertex_array);
// Copy the content back to the old GLVolume.
vol_old.indexed_vertex_array = vol_new.indexed_vertex_array;
// Clear the buffers, but keep them pre-allocated.
vol_new.indexed_vertex_array.clear();
// Just make sure that clear did not clear the reserved memory.
// Reserving number of vertices (3x position + 3x color)
vol_new.indexed_vertex_array.reserve(VERTEX_BUFFER_RESERVE_SIZE / 6);
// Finalize the old geometry, possibly move data to the graphics card.
vol_old.finalize_geometry(gl_initialized);
}
static void load_gcode_retractions(const GCodePreviewData::Retraction& retractions, GLCanvas3D::GCodePreviewVolumeIndex::EType extrusion_type, GLVolumeCollection &volumes, GLCanvas3D::GCodePreviewVolumeIndex &volume_index, bool gl_initialized)
{
volume_index.first_volumes.emplace_back(extrusion_type, 0, (unsigned int)volumes.volumes.size());
// nothing to render, return
if (retractions.positions.empty())
return;
GLVolume *volume = volumes.new_nontoolpath_volume(retractions.color.rgba, VERTEX_BUFFER_RESERVE_SIZE);
GCodePreviewData::Retraction::PositionsList copy(retractions.positions);
std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2) { return p1.position(2) < p2.position(2); });
for (const GCodePreviewData::Retraction::Position& position : copy)
{
volume->print_zs.push_back(unscale<double>(position.position(2)));
volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
GLVolume &vol = *volume;
volume = volumes.new_nontoolpath_volume(vol.color);
reserve_new_volume_finalize_old_volume(*volume, vol, gl_initialized);
}
}
volume->indexed_vertex_array.finalize_geometry(gl_initialized);
}
void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
{
const Print *print = this->fff_print();
@ -2099,8 +2144,8 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
_load_gcode_extrusion_paths(preview_data, tool_colors);
_load_gcode_travel_paths(preview_data, tool_colors);
_load_gcode_retractions(preview_data);
_load_gcode_unretractions(preview_data);
load_gcode_retractions(preview_data.retraction, GCodePreviewVolumeIndex::Retraction, m_volumes, m_gcode_preview_volume_index, m_initialized);
load_gcode_retractions(preview_data.unretraction, GCodePreviewVolumeIndex::Unretraction, m_volumes, m_gcode_preview_volume_index, m_initialized);
if (!m_volumes.empty())
{
@ -2129,6 +2174,8 @@ void GLCanvas3D::load_sla_preview()
if ((m_canvas != nullptr) && (print != nullptr))
{
_set_current();
// Release OpenGL data before generating new data.
this->reset_volumes();
_load_sla_shells();
_update_sla_shells_outside_state();
_show_warning_texture_if_needed(WarningTexture::SlaSupportsOutside);
@ -2143,18 +2190,13 @@ void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors, c
_set_current();
// Release OpenGL data before generating new data.
this->reset_volumes();
_load_print_toolpaths();
_load_wipe_tower_toolpaths(str_tool_colors);
for (const PrintObject* object : print->objects())
{
if (object != nullptr)
_load_print_object_toolpaths(*object, str_tool_colors, color_print_values);
}
for (GLVolume* volume : m_volumes.volumes)
{
volume->is_extrusion_path = true;
}
_load_print_object_toolpaths(*object, str_tool_colors, color_print_values);
_update_toolpath_volumes_outside_state();
_show_warning_texture_if_needed(WarningTexture::ToolpathOutside);
@ -3716,11 +3758,7 @@ bool GLCanvas3D::_init_undoredo_toolbar()
bool GLCanvas3D::_set_current()
{
if (_is_shown_on_screen() && (m_context != nullptr)) {
return m_canvas->SetCurrent(*m_context);
}
return false;
return m_context != nullptr && m_canvas->SetCurrent(*m_context);
}
void GLCanvas3D::_resize(unsigned int w, unsigned int h)
@ -4547,18 +4585,23 @@ void GLCanvas3D::_load_print_toolpaths()
if (print_zs.size() > skirt_height)
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
m_volumes.volumes.emplace_back(new GLVolume(color));
GLVolume& volume = *m_volumes.volumes.back();
for (size_t i = 0; i < skirt_height; ++i) {
volume.print_zs.push_back(print_zs[i]);
volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
if (i == 0)
_3DScene::extrusionentity_to_verts(print->brim(), print_zs[i], Point(0, 0), volume);
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), volume);
GLVolume *volume = m_volumes.new_toolpath_volume(color, VERTEX_BUFFER_RESERVE_SIZE);
for (size_t i = 0; i < skirt_height; ++i) {
volume->print_zs.push_back(print_zs[i]);
volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
if (i == 0)
_3DScene::extrusionentity_to_verts(print->brim(), print_zs[i], Point(0, 0), *volume);
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), *volume);
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
GLVolume &vol = *volume;
volume = m_volumes.new_toolpath_volume(vol.color);
reserve_new_volume_finalize_old_volume(*volume, vol, m_initialized);
}
}
volume.indexed_vertex_array.finalize_geometry(m_initialized);
volume->indexed_vertex_array.finalize_geometry(m_initialized);
}
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors, const std::vector<double>& color_print_values)
@ -4575,12 +4618,6 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
const std::vector<float>* tool_colors;
const std::vector<double>* color_print_values;
// Number of vertices (each vertex is 6x4=24 bytes long)
static const size_t alloc_size_max() { return 131072; } // 3.15MB
// static const size_t alloc_size_max () { return 65536; } // 1.57MB
// static const size_t alloc_size_max () { return 32768; } // 786kB
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
static const float* color_perimeters() { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
static const float* color_infill() { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
static const float* color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
@ -4630,10 +4667,14 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
tbb::spin_mutex new_volume_mutex;
auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
auto *volume = new GLVolume(color);
new_volume_mutex.lock();
// Allocate the volume before locking.
GLVolume *volume = new GLVolume(color);
volume->is_extrusion_path = true;
tbb::spin_mutex::scoped_lock lock;
// Lock by ROII, so if the emplace_back() fails, the lock will be released.
lock.acquire(new_volume_mutex);
m_volumes.volumes.emplace_back(volume);
new_volume_mutex.unlock();
lock.release();
return volume;
};
const size_t volumes_cnt_initial = m_volumes.volumes.size();
@ -4671,7 +4712,8 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
else
vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
for (GLVolume *vol : vols)
vol->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
// Reserving number of vertices (3x position + 3x color)
vol->indexed_vertex_array.reserve(VERTEX_BUFFER_RESERVE_SIZE / 6);
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
const Layer *layer = ctxt.layers[idx_layer];
for (GLVolume *vol : vols)
@ -4715,18 +4757,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
for (size_t i = 0; i < vols.size(); ++i) {
GLVolume &vol = *vols[i];
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
// Store the vertex arrays and restart their containers,
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
vols[i] = new_volume(vol.color);
GLVolume &vol_new = *vols[i];
// Assign the large pre-allocated buffers to the new GLVolume.
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
// Copy the content back to the old GLVolume.
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
// Clear the buffers, but keep them pre-allocated.
vol_new.indexed_vertex_array.clear();
// Just make sure that clear did not clear the reserved memory.
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
reserve_new_volume_finalize_old_volume(*vols[i], vol, false);
}
}
}
@ -4766,10 +4799,6 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
Vec2f wipe_tower_pos;
float wipe_tower_angle;
// Number of vertices (each vertex is 6x4=24 bytes long)
static const size_t alloc_size_max() { return 131072; } // 3.15MB
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
static const float* color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
// For cloring by a tool, return a parsed color.
@ -4810,9 +4839,11 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
tbb::spin_mutex new_volume_mutex;
auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
auto *volume = new GLVolume(color);
new_volume_mutex.lock();
volume->is_extrusion_path = true;
tbb::spin_mutex::scoped_lock lock;
lock.acquire(new_volume_mutex);
m_volumes.volumes.emplace_back(volume);
new_volume_mutex.unlock();
lock.release();
return volume;
};
const size_t volumes_cnt_initial = m_volumes.volumes.size();
@ -4829,7 +4860,8 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
else
vols = { new_volume(ctxt.color_support()) };
for (GLVolume *volume : vols)
volume->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
// Reserving number of vertices (3x position + 3x color)
volume->indexed_vertex_array.reserve(VERTEX_BUFFER_RESERVE_SIZE / 6);
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
for (size_t i = 0; i < vols.size(); ++i) {
@ -4886,18 +4918,9 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
}
for (size_t i = 0; i < vols.size(); ++i) {
GLVolume &vol = *vols[i];
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
// Store the vertex arrays and restart their containers,
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
vols[i] = new_volume(vol.color);
GLVolume &vol_new = *vols[i];
// Assign the large pre-allocated buffers to the new GLVolume.
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
// Copy the content back to the old GLVolume.
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
// Clear the buffers, but keep them pre-allocated.
vol_new.indexed_vertex_array.clear();
// Just make sure that clear did not clear the reserved memory.
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
reserve_new_volume_finalize_old_volume(*vols[i], vol, false);
}
}
for (GLVolume *vol : vols)
@ -5049,15 +5072,9 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
for (Filter& filter : filters)
{
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, (unsigned int)filter.role, (unsigned int)m_volumes.volumes.size());
GLVolume* volume = new GLVolume(Helper::path_color(preview_data, tool_colors, filter.value).rgba);
if (volume != nullptr)
{
filter.volume = volume;
volume->is_extrusion_path = true;
m_volumes.volumes.emplace_back(volume);
}
else
{
try {
filter.volume = m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, filter.value).rgba, VERTEX_BUFFER_RESERVE_SIZE);
} catch (std::bad_alloc& /* err */) {
// an error occourred - restore to previous state and return
m_gcode_preview_volume_index.first_volumes.pop_back();
if (initial_volumes_count != m_volumes.volumes.size())
@ -5065,11 +5082,9 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
GLVolumePtrs::iterator begin = m_volumes.volumes.begin() + initial_volumes_count;
GLVolumePtrs::iterator end = m_volumes.volumes.end();
for (GLVolumePtrs::iterator it = begin; it < end; ++it)
{
GLVolume* volume = *it;
delete volume;
}
delete *it;
m_volumes.volumes.erase(begin, end);
//FIXME rethrow bad_alloc?
return;
}
}
@ -5086,18 +5101,25 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
FiltersList::iterator filter = std::find(filters.begin(), filters.end(), Filter(path_filter, path.role()));
if (filter != filters.end())
{
filter->volume->print_zs.push_back(layer.z);
filter->volume->offsets.push_back(filter->volume->indexed_vertex_array.quad_indices.size());
filter->volume->offsets.push_back(filter->volume->indexed_vertex_array.triangle_indices.size());
GLVolume &vol = *filter->volume;
vol.print_zs.push_back(layer.z);
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
_3DScene::extrusionentity_to_verts(path, layer.z, *filter->volume);
_3DScene::extrusionentity_to_verts(path, layer.z, vol);
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
filter->volume = m_volumes.new_toolpath_volume(vol.color);
reserve_new_volume_finalize_old_volume(*filter->volume, vol, m_initialized);
}
}
}
}
// finalize volumes and sends geometry to gpu
for (size_t i = initial_volumes_count; i < m_volumes.volumes.size(); ++i)
m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized);
// Finalize volumes and sends geometry to gpu
for (Filter &filter : filters)
filter.volume->indexed_vertex_array.finalize_geometry(m_initialized);
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - end" << m_volumes.log_memory_info() << log_memory_info();
}
@ -5135,19 +5157,12 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data,
GLVolumePtrs::iterator begin = m_volumes.volumes.begin() + initial_volumes_count;
GLVolumePtrs::iterator end = m_volumes.volumes.end();
for (GLVolumePtrs::iterator it = begin; it < end; ++it)
{
GLVolume* volume = *it;
delete volume;
}
delete *it;
m_volumes.volumes.erase(begin, end);
}
return;
}
// finalize volumes and sends geometry to gpu
for (size_t i = initial_volumes_count; i < m_volumes.volumes.size(); ++i)
m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized);
}
bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
@ -5188,16 +5203,7 @@ bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
// creates a new volume for each type
for (Type& type : types)
{
GLVolume* volume = new GLVolume(preview_data.travel.type_colors[type.value].rgba);
if (volume == nullptr)
return false;
else
{
type.volume = volume;
m_volumes.volumes.emplace_back(volume);
}
}
type.volume = m_volumes.new_nontoolpath_volume(preview_data.travel.type_colors[type.value].rgba, VERTEX_BUFFER_RESERVE_SIZE);
// populates volumes
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
@ -5205,14 +5211,24 @@ bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type));
if (type != types.end())
{
type->volume->print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
type->volume->offsets.push_back(type->volume->indexed_vertex_array.quad_indices.size());
type->volume->offsets.push_back(type->volume->indexed_vertex_array.triangle_indices.size());
GLVolume &vol = *type->volume;
vol.print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *type->volume);
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, vol);
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
type->volume = m_volumes.new_nontoolpath_volume(vol.color);
reserve_new_volume_finalize_old_volume(*type->volume, vol, m_initialized);
}
}
}
for (Type &type : types)
type.volume->finalize_geometry(m_initialized);
return true;
}
@ -5254,31 +5270,32 @@ bool GLCanvas3D::_travel_paths_by_feedrate(const GCodePreviewData& preview_data)
// creates a new volume for each feedrate
for (Feedrate& feedrate : feedrates)
{
GLVolume* volume = new GLVolume(preview_data.get_feedrate_color(feedrate.value).rgba);
if (volume == nullptr)
return false;
else
{
feedrate.volume = volume;
m_volumes.volumes.emplace_back(volume);
}
}
feedrate.volume = m_volumes.new_nontoolpath_volume(preview_data.get_feedrate_color(feedrate.value).rgba, VERTEX_BUFFER_RESERVE_SIZE);
// populates volumes
// populates volumes
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
FeedratesList::iterator feedrate = std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate));
if (feedrate != feedrates.end())
{
feedrate->volume->print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.quad_indices.size());
feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.triangle_indices.size());
GLVolume &vol = *feedrate->volume;
vol.print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *feedrate->volume);
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
feedrate->volume = m_volumes.new_nontoolpath_volume(vol.color);
reserve_new_volume_finalize_old_volume(*feedrate->volume, vol, m_initialized);
}
}
}
for (Feedrate &feedrate : feedrates)
feedrate.volume->finalize_geometry(m_initialized);
return true;
}
@ -5322,17 +5339,8 @@ bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, con
for (Tool& tool : tools)
{
// tool.value could be invalid (as it was with https://github.com/prusa3d/PrusaSlicer/issues/2179), we better check
if (tool.value >= tool_colors.size())
continue;
GLVolume* volume = new GLVolume(tool_colors.data() + tool.value * 4);
if (volume == nullptr)
return false;
else
{
tool.volume = volume;
m_volumes.volumes.emplace_back(volume);
}
if (tool.value < tool_colors.size())
tool.volume = m_volumes.new_nontoolpath_volume(tool_colors.data() + tool.value * 4, VERTEX_BUFFER_RESERVE_SIZE);
}
// populates volumes
@ -5341,73 +5349,27 @@ bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, con
ToolsList::iterator tool = std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id));
if (tool != tools.end() && tool->volume != nullptr)
{
tool->volume->print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.quad_indices.size());
tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.triangle_indices.size());
GLVolume &vol = *tool->volume;
vol.print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *tool->volume);
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
tool->volume = m_volumes.new_nontoolpath_volume(vol.color);
reserve_new_volume_finalize_old_volume(*tool->volume, vol, m_initialized);
}
}
}
for (Tool& tool : tools)
tool.volume->finalize_geometry(m_initialized);
return true;
}
void GLCanvas3D::_load_gcode_retractions(const GCodePreviewData& preview_data)
{
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Retraction, 0, (unsigned int)m_volumes.volumes.size());
// nothing to render, return
if (preview_data.retraction.positions.empty())
return;
GLVolume* volume = new GLVolume(preview_data.retraction.color.rgba);
if (volume != nullptr)
{
m_volumes.volumes.emplace_back(volume);
GCodePreviewData::Retraction::PositionsList copy(preview_data.retraction.positions);
std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position(2) < p2.position(2); });
for (const GCodePreviewData::Retraction::Position& position : copy)
{
volume->print_zs.push_back(unscale<double>(position.position(2)));
volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
}
volume->indexed_vertex_array.finalize_geometry(m_initialized);
}
}
void GLCanvas3D::_load_gcode_unretractions(const GCodePreviewData& preview_data)
{
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Unretraction, 0, (unsigned int)m_volumes.volumes.size());
// nothing to render, return
if (preview_data.unretraction.positions.empty())
return;
GLVolume* volume = new GLVolume(preview_data.unretraction.color.rgba);
if (volume != nullptr)
{
m_volumes.volumes.emplace_back(volume);
GCodePreviewData::Retraction::PositionsList copy(preview_data.unretraction.positions);
std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position(2) < p2.position(2); });
for (const GCodePreviewData::Retraction::Position& position : copy)
{
volume->print_zs.push_back(unscale<double>(position.position(2)));
volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
}
volume->indexed_vertex_array.finalize_geometry(m_initialized);
}
}
void GLCanvas3D::_load_fff_shells()
{
size_t initial_volumes_count = m_volumes.volumes.size();

View File

@ -131,6 +131,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
class GLCanvas3D
{
public:
struct GCodePreviewVolumeIndex
{
enum EType
@ -158,6 +159,7 @@ class GLCanvas3D
void reset() { first_volumes.clear(); }
};
private:
class LayersEditing
{
public:
@ -720,10 +722,6 @@ private:
bool _travel_paths_by_type(const GCodePreviewData& preview_data);
bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data);
bool _travel_paths_by_tool(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates gcode retractions geometry
void _load_gcode_retractions(const GCodePreviewData& preview_data);
// generates gcode unretractions geometry
void _load_gcode_unretractions(const GCodePreviewData& preview_data);
// generates objects and wipe tower geometry
void _load_fff_shells();
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.