mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
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);
|
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> GCodePreviewData::Color::as_bytes() const
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> ret;
|
std::vector<unsigned char> ret;
|
||||||
|
|
|
@ -14,8 +14,8 @@ public:
|
||||||
{
|
{
|
||||||
float rgba[4];
|
float rgba[4];
|
||||||
|
|
||||||
Color();
|
Color(const float *argba) { memcpy(this->rgba, argba, sizeof(float) * 4); }
|
||||||
Color(float r, float g, float b, float a);
|
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;
|
std::vector<unsigned char> as_bytes() const;
|
||||||
|
|
||||||
|
|
|
@ -5027,10 +5027,10 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
||||||
ExtrusionRole role;
|
ExtrusionRole role;
|
||||||
GLVolume* volume;
|
GLVolume* volume;
|
||||||
|
|
||||||
Filter(float value, ExtrusionRole role)
|
Filter(float value, ExtrusionRole role, GLVolume *volume = nullptr)
|
||||||
: value(value)
|
: value(value)
|
||||||
, role(role)
|
, role(role)
|
||||||
, volume(nullptr)
|
, volume(volume)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5046,19 +5046,31 @@ 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_volumes_count = m_volumes.volumes.size();
|
||||||
|
size_t initial_volume_index_count = m_gcode_preview_volume_index.first_volumes.size();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - create volumes" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
|
||||||
// detects filters
|
// detects filters
|
||||||
|
typedef std::vector<Filter> FiltersList;
|
||||||
FiltersList filters;
|
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 GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||||
{
|
|
||||||
for (const ExtrusionPath& path : layer.paths)
|
for (const ExtrusionPath& path : layer.paths)
|
||||||
{
|
values.emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path), (unsigned int)path.role());
|
||||||
ExtrusionRole role = path.role();
|
sort_remove_duplicates(values);
|
||||||
float path_filter = Helper::path_filter(preview_data.extrusion.view_type, path);
|
filters.reserve(values.size());
|
||||||
if (std::find(filters.begin(), filters.end(), Filter(path_filter, role)) == filters.end())
|
for (const std::pair<float, unsigned int> &value : values) {
|
||||||
filters.emplace_back(path_filter, role);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5066,30 +5078,6 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
||||||
if (filters.empty())
|
if (filters.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - create volumes" << m_volumes.log_memory_info() << log_memory_info();
|
|
||||||
|
|
||||||
// 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
|
// populates volumes
|
||||||
|
@ -5097,23 +5085,24 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
||||||
{
|
{
|
||||||
for (const ExtrusionPath& path : layer.paths)
|
for (const ExtrusionPath& path : layer.paths)
|
||||||
{
|
{
|
||||||
float path_filter = Helper::path_filter(preview_data.extrusion.view_type, path);
|
Filter key(Helper::path_filter(preview_data.extrusion.view_type, path), path.role());
|
||||||
FiltersList::iterator filter = std::find(filters.begin(), filters.end(), Filter(path_filter, path.role()));
|
FiltersList::iterator filter = std::lower_bound(filters.begin(), filters.end(), key,
|
||||||
if (filter != filters.end())
|
[](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);
|
||||||
GLVolume &vol = *filter->volume;
|
|
||||||
|
GLVolume& vol = *filter->volume;
|
||||||
vol.print_zs.push_back(layer.z);
|
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.quad_indices.size());
|
||||||
vol.offsets.push_back(vol.indexed_vertex_array.triangle_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.
|
// 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) {
|
for (Filter &filter : filters)
|
||||||
filter->volume = m_volumes.new_toolpath_volume(vol.color);
|
if (filter.volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
||||||
reserve_new_volume_finalize_old_volume(*filter->volume, vol, m_initialized);
|
GLVolume& vol = *filter.volume;
|
||||||
}
|
filter.volume = m_volumes.new_toolpath_volume(vol.color);
|
||||||
}
|
reserve_new_volume_finalize_old_volume(*filter.volume, vol, m_initialized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5122,96 +5111,54 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
||||||
filter.volume->indexed_vertex_array.finalize_geometry(m_initialized);
|
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();
|
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - end" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
catch (const std::bad_alloc & /* err */)
|
||||||
{
|
|
||||||
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
|
// 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 begin = m_volumes.volumes.begin() + initial_volumes_count;
|
||||||
GLVolumePtrs::iterator end = m_volumes.volumes.end();
|
GLVolumePtrs::iterator end = m_volumes.volumes.end();
|
||||||
for (GLVolumePtrs::iterator it = begin; it < end; ++it)
|
for (GLVolumePtrs::iterator it = begin; it < end; ++it)
|
||||||
delete *it;
|
delete *it;
|
||||||
m_volumes.volumes.erase(begin, end);
|
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();
|
||||||
return;
|
//FIXME rethrow bad_alloc?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
|
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)
|
||||||
|
|
||||||
{
|
{
|
||||||
// Helper structure for types
|
// colors travels by type
|
||||||
struct Type
|
std::vector<std::pair<TYPE, GLVolume*>> by_type;
|
||||||
{
|
{
|
||||||
GCodePreviewData::Travel::EType value;
|
std::vector<TYPE> values;
|
||||||
GLVolume* volume;
|
values.reserve(preview_data.travel.polylines.size());
|
||||||
|
|
||||||
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)
|
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||||
{
|
values.emplace_back(func_value(polyline));
|
||||||
if (std::find(types.begin(), types.end(), Type(polyline.type)) == types.end())
|
sort_remove_duplicates(values);
|
||||||
types.emplace_back(polyline.type);
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// populates volumes
|
||||||
|
std::pair<TYPE, GLVolume*> key(0.f, nullptr);
|
||||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
||||||
{
|
{
|
||||||
TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type));
|
key.first = func_value(polyline);
|
||||||
if (type != types.end())
|
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 = *type->volume;
|
|
||||||
|
GLVolume& vol = *it->second;
|
||||||
vol.print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
|
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.quad_indices.size());
|
||||||
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
||||||
|
@ -5220,136 +5167,60 @@ bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
|
||||||
|
|
||||||
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
|
// 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) {
|
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
||||||
type->volume = m_volumes.new_nontoolpath_volume(vol.color);
|
it->second = volumes.new_nontoolpath_volume(vol.color);
|
||||||
reserve_new_volume_finalize_old_volume(*type->volume, vol, m_initialized);
|
reserve_new_volume_finalize_old_volume(*it->second, vol, gl_initialized);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Type &type : types)
|
for (auto &feedrate : by_type)
|
||||||
type.volume->finalize_geometry(m_initialized);
|
feedrate.second->finalize_geometry(gl_initialized);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::_travel_paths_by_feedrate(const GCodePreviewData& preview_data)
|
void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
{
|
{
|
||||||
// nothing to render, return
|
// nothing to render, return
|
||||||
if (preview_data.travel.polylines.empty())
|
if (preview_data.travel.polylines.empty())
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
// colors travels by feedrate
|
size_t initial_volumes_count = m_volumes.volumes.size();
|
||||||
// detects feedrates
|
size_t volume_index_allocated = false;
|
||||||
std::vector<std::pair<float, GLVolume*>> feedrates;
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
std::vector<float> values;
|
case GCodePreviewData::Extrusion::Feedrate:
|
||||||
values.reserve(preview_data.travel.polylines.size());
|
travel_paths_internal<float>(preview_data,
|
||||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.feedrate; },
|
||||||
values.emplace_back(polyline.feedrate);
|
[&preview_data](const float feedrate) -> const GCodePreviewData::Color { return preview_data.get_feedrate_color(feedrate); },
|
||||||
sort_remove_duplicates(values);
|
m_volumes, m_initialized);
|
||||||
feedrates.reserve(values.size());
|
break;
|
||||||
// creates a new volume for each feedrate
|
case GCodePreviewData::Extrusion::Tool:
|
||||||
for (float feedrate : values)
|
travel_paths_internal<unsigned int>(preview_data,
|
||||||
feedrates.emplace_back(feedrate, m_volumes.new_nontoolpath_volume(preview_data.get_feedrate_color(feedrate).rgba, VERTEX_BUFFER_RESERVE_SIZE));
|
[](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 */) {
|
||||||
// populates volumes
|
// an error occourred - restore to previous state and return
|
||||||
std::pair<float, GLVolume*> key(0.f, nullptr);
|
GLVolumePtrs::iterator begin = m_volumes.volumes.begin() + initial_volumes_count;
|
||||||
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
|
GLVolumePtrs::iterator end = m_volumes.volumes.end();
|
||||||
{
|
for (GLVolumePtrs::iterator it = begin; it < end; ++it)
|
||||||
key.first = polyline.feedrate;
|
delete *it;
|
||||||
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; });
|
m_volumes.volumes.erase(begin, end);
|
||||||
assert(it_feedrate != feedrates.end() && it_feedrate->first == polyline.feedrate);
|
if (volume_index_allocated)
|
||||||
|
m_gcode_preview_volume_index.first_volumes.pop_back();
|
||||||
GLVolume &vol = *it_feedrate->second;
|
//FIXME report the memory issue?
|
||||||
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()
|
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);
|
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||||
// generates gcode travel paths geometry
|
// generates gcode travel paths geometry
|
||||||
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
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
|
// generates objects and wipe tower geometry
|
||||||
void _load_fff_shells();
|
void _load_fff_shells();
|
||||||
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
|
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue