Optimization of the tool path preview generation algorithm:
1) Replaced linear search with logarithmic search. 2) Templated the travel path generation, replaced 3 functions with one.
This commit is contained in:
parent
66535b41d5
commit
80490550b5
4 changed files with 161 additions and 309 deletions
|
@ -13,22 +13,6 @@ namespace Slic3r {
|
|||
|
||||
const GCodePreviewData::Color GCodePreviewData::Color::Dummy(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
GCodePreviewData::Color::Color()
|
||||
{
|
||||
rgba[0] = 1.0f;
|
||||
rgba[1] = 1.0f;
|
||||
rgba[2] = 1.0f;
|
||||
rgba[3] = 1.0f;
|
||||
}
|
||||
|
||||
GCodePreviewData::Color::Color(float r, float g, float b, float a)
|
||||
{
|
||||
rgba[0] = r;
|
||||
rgba[1] = g;
|
||||
rgba[2] = b;
|
||||
rgba[3] = a;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> GCodePreviewData::Color::as_bytes() const
|
||||
{
|
||||
std::vector<unsigned char> ret;
|
||||
|
|
|
@ -14,14 +14,14 @@ public:
|
|||
{
|
||||
float rgba[4];
|
||||
|
||||
Color();
|
||||
Color(float r, float g, float b, float a);
|
||||
Color(const float *argba) { memcpy(this->rgba, argba, sizeof(float) * 4); }
|
||||
Color(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) { rgba[0] = r; rgba[1] = g; rgba[2] = b; rgba[3] = a; }
|
||||
|
||||
std::vector<unsigned char> as_bytes() const;
|
||||
|
||||
static const Color Dummy;
|
||||
};
|
||||
|
||||
|
||||
// Color mapping from a <min, max> range into a smooth rainbow of 10 colors.
|
||||
struct Range
|
||||
{
|
||||
|
|
|
@ -5027,10 +5027,10 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
|||
ExtrusionRole role;
|
||||
GLVolume* volume;
|
||||
|
||||
Filter(float value, ExtrusionRole role)
|
||||
Filter(float value, ExtrusionRole role, GLVolume *volume = nullptr)
|
||||
: value(value)
|
||||
, role(role)
|
||||
, volume(nullptr)
|
||||
, volume(volume)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -5046,310 +5046,181 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
|||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Filter> FiltersList;
|
||||
size_t initial_volumes_count = m_volumes.volumes.size();
|
||||
size_t initial_volume_index_count = m_gcode_preview_volume_index.first_volumes.size();
|
||||
|
||||
// detects filters
|
||||
FiltersList filters;
|
||||
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||
try
|
||||
{
|
||||
for (const ExtrusionPath& path : layer.paths)
|
||||
{
|
||||
ExtrusionRole role = path.role();
|
||||
float path_filter = Helper::path_filter(preview_data.extrusion.view_type, path);
|
||||
if (std::find(filters.begin(), filters.end(), Filter(path_filter, role)) == filters.end())
|
||||
filters.emplace_back(path_filter, role);
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - create volumes" << m_volumes.log_memory_info() << log_memory_info();
|
||||
|
||||
// nothing to render, return
|
||||
if (filters.empty())
|
||||
return;
|
||||
// detects filters
|
||||
typedef std::vector<Filter> FiltersList;
|
||||
FiltersList filters;
|
||||
{
|
||||
size_t num_paths = 0;
|
||||
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||
num_paths += layer.paths.size();
|
||||
std::vector<std::pair<float, unsigned int>> values;
|
||||
values.reserve(num_paths);
|
||||
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||
for (const ExtrusionPath& path : layer.paths)
|
||||
values.emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path), (unsigned int)path.role());
|
||||
sort_remove_duplicates(values);
|
||||
filters.reserve(values.size());
|
||||
for (const std::pair<float, unsigned int> &value : values) {
|
||||
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, value.second /* role */, (unsigned int)m_volumes.volumes.size());
|
||||
filters.emplace_back(value.first, (ExtrusionRole)value.second,
|
||||
m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value.first).rgba, VERTEX_BUFFER_RESERVE_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - create volumes" << m_volumes.log_memory_info() << log_memory_info();
|
||||
// nothing to render, return
|
||||
if (filters.empty())
|
||||
return;
|
||||
|
||||
// creates a new volume for each filter
|
||||
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());
|
||||
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())
|
||||
{
|
||||
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)
|
||||
delete *it;
|
||||
m_volumes.volumes.erase(begin, end);
|
||||
//FIXME rethrow bad_alloc?
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - populate volumes" << m_volumes.log_memory_info() << log_memory_info();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - populate volumes" << m_volumes.log_memory_info() << log_memory_info();
|
||||
// populates volumes
|
||||
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||
{
|
||||
for (const ExtrusionPath& path : layer.paths)
|
||||
{
|
||||
Filter key(Helper::path_filter(preview_data.extrusion.view_type, path), path.role());
|
||||
FiltersList::iterator filter = std::lower_bound(filters.begin(), filters.end(), key,
|
||||
[](const Filter& l, const Filter& r) { return (l.value < r.value) || (l.value == r.value && l.role < r.role); });
|
||||
assert(filter != filters.end() && key.value == filter->value && key.role == filter->role);
|
||||
|
||||
// populates volumes
|
||||
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||
{
|
||||
for (const ExtrusionPath& path : layer.paths)
|
||||
{
|
||||
float path_filter = Helper::path_filter(preview_data.extrusion.view_type, path);
|
||||
FiltersList::iterator filter = std::find(filters.begin(), filters.end(), Filter(path_filter, path.role()));
|
||||
if (filter != filters.end())
|
||||
{
|
||||
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());
|
||||
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, vol);
|
||||
_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.
|
||||
for (Filter &filter : filters)
|
||||
if (filter.volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
||||
GLVolume& vol = *filter.volume;
|
||||
filter.volume = m_volumes.new_toolpath_volume(vol.color);
|
||||
reserve_new_volume_finalize_old_volume(*filter.volume, vol, m_initialized);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (Filter &filter : filters)
|
||||
filter.volume->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();
|
||||
}
|
||||
catch (const std::bad_alloc & /* err */)
|
||||
{
|
||||
// an error occourred - restore to previous state and return
|
||||
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)
|
||||
delete *it;
|
||||
m_volumes.volumes.erase(begin, end);
|
||||
m_gcode_preview_volume_index.first_volumes.erase(m_gcode_preview_volume_index.first_volumes.begin() + initial_volume_index_count, m_gcode_preview_volume_index.first_volumes.end());
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - failed on low memory" << m_volumes.log_memory_info() << log_memory_info();
|
||||
//FIXME rethrow bad_alloc?
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - end" << m_volumes.log_memory_info() << log_memory_info();
|
||||
template<typename TYPE, typename FUNC_VALUE, typename FUNC_COLOR>
|
||||
inline void travel_paths_internal(
|
||||
// input
|
||||
const GCodePreviewData &preview_data,
|
||||
// accessors
|
||||
FUNC_VALUE func_value, FUNC_COLOR func_color,
|
||||
// output
|
||||
GLVolumeCollection &volumes, bool gl_initialized)
|
||||
|
||||
{
|
||||
// colors travels by type
|
||||
std::vector<std::pair<TYPE, GLVolume*>> by_type;
|
||||
{
|
||||
std::vector<TYPE> values;
|
||||
values.reserve(preview_data.travel.polylines.size());
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
values.emplace_back(func_value(polyline));
|
||||
sort_remove_duplicates(values);
|
||||
by_type.reserve(values.size());
|
||||
// creates a new volume for each feedrate
|
||||
for (TYPE type : values)
|
||||
by_type.emplace_back(type, volumes.new_nontoolpath_volume(func_color(type).rgba, VERTEX_BUFFER_RESERVE_SIZE));
|
||||
}
|
||||
|
||||
// populates volumes
|
||||
std::pair<TYPE, GLVolume*> key(0.f, nullptr);
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
{
|
||||
key.first = func_value(polyline);
|
||||
auto it = std::lower_bound(by_type.begin(), by_type.end(), key, [](const std::pair<TYPE, GLVolume*>& l, const std::pair<TYPE, GLVolume*>& r) { return l.first < r.first; });
|
||||
assert(it != by_type.end() && it->first == func_value(polyline));
|
||||
|
||||
GLVolume& vol = *it->second;
|
||||
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, 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) {
|
||||
it->second = volumes.new_nontoolpath_volume(vol.color);
|
||||
reserve_new_volume_finalize_old_volume(*it->second, vol, gl_initialized);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &feedrate : by_type)
|
||||
feedrate.second->finalize_geometry(gl_initialized);
|
||||
}
|
||||
|
||||
void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||
{
|
||||
size_t initial_volumes_count = m_volumes.volumes.size();
|
||||
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Travel, 0, (unsigned int)initial_volumes_count);
|
||||
|
||||
bool res = true;
|
||||
switch (preview_data.extrusion.view_type)
|
||||
{
|
||||
case GCodePreviewData::Extrusion::Feedrate:
|
||||
{
|
||||
res = _travel_paths_by_feedrate(preview_data);
|
||||
break;
|
||||
}
|
||||
case GCodePreviewData::Extrusion::Tool:
|
||||
{
|
||||
res = _travel_paths_by_tool(preview_data, tool_colors);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
res = _travel_paths_by_type(preview_data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!res)
|
||||
{
|
||||
// an error occourred - restore to previous state and return
|
||||
if (initial_volumes_count != m_volumes.volumes.size())
|
||||
{
|
||||
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)
|
||||
delete *it;
|
||||
m_volumes.volumes.erase(begin, end);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
|
||||
{
|
||||
// Helper structure for types
|
||||
struct Type
|
||||
{
|
||||
GCodePreviewData::Travel::EType value;
|
||||
GLVolume* volume;
|
||||
|
||||
explicit Type(GCodePreviewData::Travel::EType value)
|
||||
: value(value)
|
||||
, volume(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const Type& other) const
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Type> TypesList;
|
||||
|
||||
// colors travels by travel type
|
||||
|
||||
// detects types
|
||||
TypesList types;
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
{
|
||||
if (std::find(types.begin(), types.end(), Type(polyline.type)) == types.end())
|
||||
types.emplace_back(polyline.type);
|
||||
}
|
||||
|
||||
// nothing to render, return
|
||||
if (types.empty())
|
||||
return true;
|
||||
|
||||
// creates a new volume for each type
|
||||
for (Type& type : types)
|
||||
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)
|
||||
{
|
||||
TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type));
|
||||
if (type != types.end())
|
||||
{
|
||||
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, 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;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_travel_paths_by_feedrate(const GCodePreviewData& preview_data)
|
||||
{
|
||||
// nothing to render, return
|
||||
// nothing to render, return
|
||||
if (preview_data.travel.polylines.empty())
|
||||
return true;
|
||||
return;
|
||||
|
||||
// colors travels by feedrate
|
||||
// detects feedrates
|
||||
std::vector<std::pair<float, GLVolume*>> feedrates;
|
||||
{
|
||||
std::vector<float> values;
|
||||
values.reserve(preview_data.travel.polylines.size());
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
values.emplace_back(polyline.feedrate);
|
||||
sort_remove_duplicates(values);
|
||||
feedrates.reserve(values.size());
|
||||
// creates a new volume for each feedrate
|
||||
for (float feedrate : values)
|
||||
feedrates.emplace_back(feedrate, m_volumes.new_nontoolpath_volume(preview_data.get_feedrate_color(feedrate).rgba, VERTEX_BUFFER_RESERVE_SIZE));
|
||||
size_t initial_volumes_count = m_volumes.volumes.size();
|
||||
size_t volume_index_allocated = false;
|
||||
|
||||
try {
|
||||
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Travel, 0, (unsigned int)initial_volumes_count);
|
||||
volume_index_allocated = true;
|
||||
|
||||
switch (preview_data.extrusion.view_type)
|
||||
{
|
||||
case GCodePreviewData::Extrusion::Feedrate:
|
||||
travel_paths_internal<float>(preview_data,
|
||||
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.feedrate; },
|
||||
[&preview_data](const float feedrate) -> const GCodePreviewData::Color { return preview_data.get_feedrate_color(feedrate); },
|
||||
m_volumes, m_initialized);
|
||||
break;
|
||||
case GCodePreviewData::Extrusion::Tool:
|
||||
travel_paths_internal<unsigned int>(preview_data,
|
||||
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.extruder_id; },
|
||||
[&tool_colors](const unsigned int extruder_id) -> const GCodePreviewData::Color { assert((extruder_id + 1) * 4 <= tool_colors.size()); return GCodePreviewData::Color(tool_colors.data() + extruder_id * 4); },
|
||||
m_volumes, m_initialized);
|
||||
break;
|
||||
default:
|
||||
travel_paths_internal<unsigned int>(preview_data,
|
||||
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.type; },
|
||||
[&preview_data](const unsigned int type) -> const GCodePreviewData::Color& { return preview_data.travel.type_colors[type]; },
|
||||
m_volumes, m_initialized);
|
||||
break;
|
||||
}
|
||||
} catch (const std::bad_alloc & /* ex */) {
|
||||
// an error occourred - restore to previous state and return
|
||||
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)
|
||||
delete *it;
|
||||
m_volumes.volumes.erase(begin, end);
|
||||
if (volume_index_allocated)
|
||||
m_gcode_preview_volume_index.first_volumes.pop_back();
|
||||
//FIXME report the memory issue?
|
||||
}
|
||||
|
||||
// populates volumes
|
||||
std::pair<float, GLVolume*> key(0.f, nullptr);
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
{
|
||||
key.first = polyline.feedrate;
|
||||
auto it_feedrate = std::lower_bound(feedrates.begin(), feedrates.end(), key, [](const std::pair<float, GLVolume*> &l, const std::pair<float, GLVolume*> &r) { return l.first < r.first; });
|
||||
assert(it_feedrate != feedrates.end() && it_feedrate->first == polyline.feedrate);
|
||||
|
||||
GLVolume &vol = *it_feedrate->second;
|
||||
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, 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) {
|
||||
it_feedrate->second = m_volumes.new_nontoolpath_volume(vol.color);
|
||||
reserve_new_volume_finalize_old_volume(*it_feedrate->second, vol, m_initialized);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &feedrate : feedrates)
|
||||
feedrate.second->finalize_geometry(m_initialized);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||
{
|
||||
// Helper structure for tool
|
||||
struct Tool
|
||||
{
|
||||
unsigned int value;
|
||||
GLVolume* volume;
|
||||
|
||||
explicit Tool(unsigned int value)
|
||||
: value(value)
|
||||
, volume(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const Tool& other) const
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Tool> ToolsList;
|
||||
|
||||
// colors travels by tool
|
||||
|
||||
// detects tools
|
||||
ToolsList tools;
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
{
|
||||
if (std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id)) == tools.end())
|
||||
tools.emplace_back(polyline.extruder_id);
|
||||
}
|
||||
|
||||
// nothing to render, return
|
||||
if (tools.empty())
|
||||
return true;
|
||||
|
||||
// creates a new volume for each tool
|
||||
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())
|
||||
tool.volume = m_volumes.new_nontoolpath_volume(tool_colors.data() + tool.value * 4, VERTEX_BUFFER_RESERVE_SIZE);
|
||||
}
|
||||
|
||||
// populates volumes
|
||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||
{
|
||||
ToolsList::iterator tool = std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id));
|
||||
if (tool != tools.end() && tool->volume != nullptr)
|
||||
{
|
||||
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_fff_shells()
|
||||
|
|
|
@ -719,9 +719,6 @@ private:
|
|||
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
// generates gcode travel paths geometry
|
||||
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
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 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.
|
||||
|
|
Loading…
Reference in a new issue