Fixed a regression issue where excessive memory was allocated
for the GLVolumes before sending to the GPU driver. The following commits were partially reverted:4269c8b23c
Removed GLVolume non-VBO renderingd15698e21e
GLVolume and GLIndexedVertexArray refactored to send data to gpu at the first render call Namely, the GLVolume buffers are "shrink to size"'d before sending their content to the OpenGL driver, and the vertex buffers are populated as quickly as possible from the GLVolume, so that the same buffer is not kept twice in RAM on systems, where the RAM is shared with the graphics card. Also the memory allocation reporting was improved for the GLVolumes.
This commit is contained in:
parent
28cc595350
commit
731e5abd88
5 changed files with 208 additions and 110 deletions
|
@ -561,11 +561,11 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print->config().remaining_times.value) {
|
if (print->config().remaining_times.value) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode";
|
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode" << log_memory_info();
|
||||||
m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||||
m_normal_time_estimator.reset();
|
m_normal_time_estimator.reset();
|
||||||
if (m_silent_time_estimator_enabled) {
|
if (m_silent_time_estimator_enabled) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode";
|
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode" << log_memory_info();
|
||||||
m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||||
m_silent_time_estimator.reset();
|
m_silent_time_estimator.reset();
|
||||||
}
|
}
|
||||||
|
@ -573,7 +573,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
|
|
||||||
// starts analyzer calculations
|
// starts analyzer calculations
|
||||||
if (m_enable_analyzer) {
|
if (m_enable_analyzer) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data";
|
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info();
|
||||||
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
||||||
m_analyzer.reset();
|
m_analyzer.reset();
|
||||||
}
|
}
|
||||||
|
@ -1820,7 +1820,8 @@ void GCode::process_layer(
|
||||||
", time estimator memory: " <<
|
", time estimator memory: " <<
|
||||||
format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) <<
|
format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) <<
|
||||||
", analyzer memory: " <<
|
", analyzer memory: " <<
|
||||||
format_memsize_MB(m_analyzer.memory_used());
|
format_memsize_MB(m_analyzer.memory_used()) <<
|
||||||
|
log_memory_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCode::apply_print_config(const PrintConfig &print_config)
|
void GCode::apply_print_config(const PrintConfig &print_config)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "libslic3r/GCode/Analyzer.hpp"
|
#include "libslic3r/GCode/Analyzer.hpp"
|
||||||
#include "slic3r/GUI/PresetBundle.hpp"
|
#include "slic3r/GUI/PresetBundle.hpp"
|
||||||
#include "libslic3r/Format/STL.hpp"
|
#include "libslic3r/Format/STL.hpp"
|
||||||
|
#include "libslic3r/Utils.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -74,15 +75,19 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLIndexedVertexArray::finalize_geometry() const
|
void GLIndexedVertexArray::finalize_geometry(bool opengl_initialized)
|
||||||
{
|
{
|
||||||
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
||||||
assert(this->triangle_indices_VBO_id == 0);
|
assert(this->triangle_indices_VBO_id == 0);
|
||||||
assert(this->quad_indices_VBO_id == 0);
|
assert(this->quad_indices_VBO_id == 0);
|
||||||
|
|
||||||
this->shrink_to_fit();
|
if (! opengl_initialized) {
|
||||||
|
// Shrink the data vectors to conserve memory in case the data cannot be transfered to the OpenGL driver yet.
|
||||||
|
this->shrink_to_fit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (! empty()) {
|
if (! this->vertices_and_normals_interleaved.empty()) {
|
||||||
glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
|
glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
|
||||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW));
|
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW));
|
||||||
|
@ -124,13 +129,8 @@ void GLIndexedVertexArray::release_geometry()
|
||||||
|
|
||||||
void GLIndexedVertexArray::render() const
|
void GLIndexedVertexArray::render() const
|
||||||
{
|
{
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
|
||||||
{
|
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
|
||||||
// sends data to gpu, if not done yet
|
|
||||||
finalize_geometry();
|
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||||
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
||||||
|
@ -161,13 +161,8 @@ void GLIndexedVertexArray::render(
|
||||||
const std::pair<size_t, size_t>& tverts_range,
|
const std::pair<size_t, size_t>& tverts_range,
|
||||||
const std::pair<size_t, size_t>& qverts_range) const
|
const std::pair<size_t, size_t>& qverts_range) const
|
||||||
{
|
{
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
|
||||||
{
|
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
|
||||||
// sends data to gpu, if not done yet
|
|
||||||
finalize_geometry();
|
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render using the Vertex Buffer Objects.
|
// Render using the Vertex Buffer Objects.
|
||||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||||
|
@ -415,30 +410,32 @@ bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -
|
||||||
bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposBasePool); }
|
bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposBasePool); }
|
||||||
|
|
||||||
std::vector<int> GLVolumeCollection::load_object(
|
std::vector<int> GLVolumeCollection::load_object(
|
||||||
const ModelObject* model_object,
|
const ModelObject *model_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
const std::vector<int>& instance_idxs,
|
const std::vector<int> &instance_idxs,
|
||||||
const std::string& color_by)
|
const std::string &color_by,
|
||||||
|
bool opengl_initialized)
|
||||||
{
|
{
|
||||||
std::vector<int> volumes_idx;
|
std::vector<int> volumes_idx;
|
||||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx)
|
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx)
|
||||||
for (int instance_idx : instance_idxs)
|
for (int instance_idx : instance_idxs)
|
||||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by));
|
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized));
|
||||||
return volumes_idx;
|
return volumes_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLVolumeCollection::load_object_volume(
|
int GLVolumeCollection::load_object_volume(
|
||||||
const ModelObject* model_object,
|
const ModelObject *model_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
int volume_idx,
|
int volume_idx,
|
||||||
int instance_idx,
|
int instance_idx,
|
||||||
const std::string& color_by)
|
const std::string &color_by,
|
||||||
|
bool opengl_initialized)
|
||||||
{
|
{
|
||||||
const ModelVolume* model_volume = model_object->volumes[volume_idx];
|
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||||
const int extruder_id = model_volume->extruder_id();
|
const int extruder_id = model_volume->extruder_id();
|
||||||
const ModelInstance* instance = model_object->instances[instance_idx];
|
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||||
const TriangleMesh& mesh = model_volume->mesh();
|
const TriangleMesh &mesh = model_volume->mesh();
|
||||||
float color[4];
|
float color[4];
|
||||||
memcpy(color, GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
memcpy(color, GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
||||||
/* if (model_volume->is_support_blocker()) {
|
/* if (model_volume->is_support_blocker()) {
|
||||||
color[0] = 1.0f;
|
color[0] = 1.0f;
|
||||||
|
@ -455,6 +452,7 @@ int GLVolumeCollection::load_object_volume(
|
||||||
GLVolume& v = *this->volumes.back();
|
GLVolume& v = *this->volumes.back();
|
||||||
v.set_color_from_model_volume(model_volume);
|
v.set_color_from_model_volume(model_volume);
|
||||||
v.indexed_vertex_array.load_mesh(mesh);
|
v.indexed_vertex_array.load_mesh(mesh);
|
||||||
|
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||||
v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx);
|
v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx);
|
||||||
if (model_volume->is_model_part())
|
if (model_volume->is_model_part())
|
||||||
{
|
{
|
||||||
|
@ -475,13 +473,14 @@ int GLVolumeCollection::load_object_volume(
|
||||||
// This function produces volumes for multiple instances in a single shot,
|
// This function produces volumes for multiple instances in a single shot,
|
||||||
// as some object specific mesh conversions may be expensive.
|
// as some object specific mesh conversions may be expensive.
|
||||||
void GLVolumeCollection::load_object_auxiliary(
|
void GLVolumeCollection::load_object_auxiliary(
|
||||||
const SLAPrintObject* print_object,
|
const SLAPrintObject *print_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
// pairs of <instance_idx, print_instance_idx>
|
// pairs of <instance_idx, print_instance_idx>
|
||||||
const std::vector<std::pair<size_t, size_t>>& instances,
|
const std::vector<std::pair<size_t, size_t>>& instances,
|
||||||
SLAPrintObjectStep milestone,
|
SLAPrintObjectStep milestone,
|
||||||
// Timestamp of the last change of the milestone
|
// Timestamp of the last change of the milestone
|
||||||
size_t timestamp)
|
size_t timestamp,
|
||||||
|
bool opengl_initialized)
|
||||||
{
|
{
|
||||||
assert(print_object->is_step_done(milestone));
|
assert(print_object->is_step_done(milestone));
|
||||||
Transform3d mesh_trafo_inv = print_object->trafo().inverse();
|
Transform3d mesh_trafo_inv = print_object->trafo().inverse();
|
||||||
|
@ -495,6 +494,7 @@ void GLVolumeCollection::load_object_auxiliary(
|
||||||
this->volumes.emplace_back(new GLVolume((milestone == slaposBasePool) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
|
this->volumes.emplace_back(new GLVolume((milestone == slaposBasePool) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
|
||||||
GLVolume& v = *this->volumes.back();
|
GLVolume& v = *this->volumes.back();
|
||||||
v.indexed_vertex_array.load_mesh(mesh);
|
v.indexed_vertex_array.load_mesh(mesh);
|
||||||
|
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||||
v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
|
v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
|
||||||
v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
|
v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
|
||||||
// Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.
|
// Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.
|
||||||
|
@ -511,7 +511,7 @@ void GLVolumeCollection::load_object_auxiliary(
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLVolumeCollection::load_wipe_tower_preview(
|
int GLVolumeCollection::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)
|
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)
|
||||||
{
|
{
|
||||||
if (depth < 0.01f)
|
if (depth < 0.01f)
|
||||||
return int(this->volumes.size() - 1);
|
return int(this->volumes.size() - 1);
|
||||||
|
@ -564,6 +564,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||||
this->volumes.emplace_back(new GLVolume(color));
|
this->volumes.emplace_back(new GLVolume(color));
|
||||||
GLVolume& v = *this->volumes.back();
|
GLVolume& v = *this->volumes.back();
|
||||||
v.indexed_vertex_array.load_mesh(mesh);
|
v.indexed_vertex_array.load_mesh(mesh);
|
||||||
|
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||||
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
||||||
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
|
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
|
||||||
v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0);
|
v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0);
|
||||||
|
@ -823,6 +824,27 @@ std::vector<double> GLVolumeCollection::get_current_print_zs(bool active_only) c
|
||||||
return print_zs;
|
return print_zs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GLVolumeCollection::cpu_memory_used() const
|
||||||
|
{
|
||||||
|
size_t memsize = sizeof(*this) + this->volumes.capacity() * sizeof(GLVolume);
|
||||||
|
for (const GLVolume *volume : this->volumes)
|
||||||
|
memsize += volume->cpu_memory_used();
|
||||||
|
return memsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GLVolumeCollection::gpu_memory_used() const
|
||||||
|
{
|
||||||
|
size_t memsize = 0;
|
||||||
|
for (const GLVolume *volume : this->volumes)
|
||||||
|
memsize += volume->gpu_memory_used();
|
||||||
|
return memsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GLVolumeCollection::log_memory_info() const
|
||||||
|
{
|
||||||
|
return " (GLVolumeCollection RAM: " + format_memsize_MB(this->cpu_memory_used()) + " GPU: " + format_memsize_MB(this->gpu_memory_used()) + " Both: " + format_memsize_MB(this->gpu_memory_used()) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
// caller is responsible for supplying NO lines with zero length
|
// caller is responsible for supplying NO lines with zero length
|
||||||
static void thick_lines_to_indexed_vertex_array(
|
static void thick_lines_to_indexed_vertex_array(
|
||||||
const Lines &lines,
|
const Lines &lines,
|
||||||
|
@ -1598,6 +1620,7 @@ bool GLArrow::on_init()
|
||||||
triangles.emplace_back(7, 13, 6);
|
triangles.emplace_back(7, 13, 6);
|
||||||
|
|
||||||
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
|
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
|
||||||
|
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1711,6 +1734,7 @@ bool GLCurvedArrow::on_init()
|
||||||
triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1);
|
triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1);
|
||||||
|
|
||||||
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
|
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
|
||||||
|
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1737,6 +1761,7 @@ bool GLBed::on_init_from_file(const std::string& filename)
|
||||||
m_filename = filename;
|
m_filename = filename;
|
||||||
|
|
||||||
m_volume.indexed_vertex_array.load_mesh(model.mesh());
|
m_volume.indexed_vertex_array.load_mesh(model.mesh());
|
||||||
|
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||||
|
|
||||||
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
|
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
|
||||||
set_color(color, 4);
|
set_color(color, 4);
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
vertices_and_normals_interleaved_VBO_id(0),
|
vertices_and_normals_interleaved_VBO_id(0),
|
||||||
triangle_indices_VBO_id(0),
|
triangle_indices_VBO_id(0),
|
||||||
quad_indices_VBO_id(0)
|
quad_indices_VBO_id(0)
|
||||||
{}
|
{ assert(! rhs.has_VBOs()); }
|
||||||
GLIndexedVertexArray(GLIndexedVertexArray &&rhs) :
|
GLIndexedVertexArray(GLIndexedVertexArray &&rhs) :
|
||||||
vertices_and_normals_interleaved(std::move(rhs.vertices_and_normals_interleaved)),
|
vertices_and_normals_interleaved(std::move(rhs.vertices_and_normals_interleaved)),
|
||||||
triangle_indices(std::move(rhs.triangle_indices)),
|
triangle_indices(std::move(rhs.triangle_indices)),
|
||||||
|
@ -72,7 +72,7 @@ public:
|
||||||
vertices_and_normals_interleaved_VBO_id(0),
|
vertices_and_normals_interleaved_VBO_id(0),
|
||||||
triangle_indices_VBO_id(0),
|
triangle_indices_VBO_id(0),
|
||||||
quad_indices_VBO_id(0)
|
quad_indices_VBO_id(0)
|
||||||
{}
|
{ assert(! rhs.has_VBOs()); }
|
||||||
|
|
||||||
~GLIndexedVertexArray() { release_geometry(); }
|
~GLIndexedVertexArray() { release_geometry(); }
|
||||||
|
|
||||||
|
@ -80,14 +80,17 @@ public:
|
||||||
{
|
{
|
||||||
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
||||||
assert(triangle_indices_VBO_id == 0);
|
assert(triangle_indices_VBO_id == 0);
|
||||||
assert(triangle_indices_VBO_id == 0);
|
assert(quad_indices_VBO_id == 0);
|
||||||
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
assert(rhs.vertices_and_normals_interleaved == 0);
|
||||||
this->triangle_indices = rhs.triangle_indices;
|
assert(rhs.triangle_indices_VBO_id == 0);
|
||||||
this->quad_indices = rhs.quad_indices;
|
assert(rhs.quad_indices_VBO_id == 0);
|
||||||
this->m_bounding_box = rhs.m_bounding_box;
|
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
||||||
vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
this->triangle_indices = rhs.triangle_indices;
|
||||||
triangle_indices_size = rhs.triangle_indices_size;
|
this->quad_indices = rhs.quad_indices;
|
||||||
quad_indices_size = rhs.quad_indices_size;
|
this->m_bounding_box = rhs.m_bounding_box;
|
||||||
|
this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
||||||
|
this->triangle_indices_size = rhs.triangle_indices_size;
|
||||||
|
this->quad_indices_size = rhs.quad_indices_size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,21 +98,24 @@ public:
|
||||||
{
|
{
|
||||||
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
||||||
assert(triangle_indices_VBO_id == 0);
|
assert(triangle_indices_VBO_id == 0);
|
||||||
assert(triangle_indices_VBO_id == 0);
|
assert(quad_indices_VBO_id == 0);
|
||||||
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
assert(rhs.vertices_and_normals_interleaved == 0);
|
||||||
this->triangle_indices = std::move(rhs.triangle_indices);
|
assert(rhs.triangle_indices_VBO_id == 0);
|
||||||
this->quad_indices = std::move(rhs.quad_indices);
|
assert(rhs.quad_indices_VBO_id == 0);
|
||||||
this->m_bounding_box = std::move(rhs.m_bounding_box);
|
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
||||||
vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
this->triangle_indices = std::move(rhs.triangle_indices);
|
||||||
triangle_indices_size = rhs.triangle_indices_size;
|
this->quad_indices = std::move(rhs.quad_indices);
|
||||||
quad_indices_size = rhs.quad_indices_size;
|
this->m_bounding_box = std::move(rhs.m_bounding_box);
|
||||||
|
this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
||||||
|
this->triangle_indices_size = rhs.triangle_indices_size;
|
||||||
|
this->quad_indices_size = rhs.quad_indices_size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x)
|
// Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x)
|
||||||
mutable std::vector<float> vertices_and_normals_interleaved;
|
std::vector<float> vertices_and_normals_interleaved;
|
||||||
mutable std::vector<int> triangle_indices;
|
std::vector<int> triangle_indices;
|
||||||
mutable std::vector<int> quad_indices;
|
std::vector<int> quad_indices;
|
||||||
|
|
||||||
// When the geometry data is loaded into the graphics card as Vertex Buffer Objects,
|
// When the geometry data is loaded into the graphics card as Vertex Buffer Objects,
|
||||||
// the above mentioned std::vectors are cleared and the following variables keep their original length.
|
// the above mentioned std::vectors are cleared and the following variables keep their original length.
|
||||||
|
@ -119,9 +125,9 @@ public:
|
||||||
|
|
||||||
// IDs of the Vertex Array Objects, into which the geometry has been loaded.
|
// IDs of the Vertex Array Objects, into which the geometry has been loaded.
|
||||||
// Zero if the VBOs are not sent to GPU yet.
|
// Zero if the VBOs are not sent to GPU yet.
|
||||||
mutable unsigned int vertices_and_normals_interleaved_VBO_id{ 0 };
|
unsigned int vertices_and_normals_interleaved_VBO_id{ 0 };
|
||||||
mutable unsigned int triangle_indices_VBO_id{ 0 };
|
unsigned int triangle_indices_VBO_id{ 0 };
|
||||||
mutable unsigned int quad_indices_VBO_id{ 0 };
|
unsigned int quad_indices_VBO_id{ 0 };
|
||||||
|
|
||||||
void load_mesh_full_shading(const TriangleMesh &mesh);
|
void load_mesh_full_shading(const TriangleMesh &mesh);
|
||||||
void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); }
|
void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); }
|
||||||
|
@ -141,12 +147,12 @@ public:
|
||||||
|
|
||||||
if (this->vertices_and_normals_interleaved.size() + 6 > this->vertices_and_normals_interleaved.capacity())
|
if (this->vertices_and_normals_interleaved.size() + 6 > this->vertices_and_normals_interleaved.capacity())
|
||||||
this->vertices_and_normals_interleaved.reserve(next_highest_power_of_2(this->vertices_and_normals_interleaved.size() + 6));
|
this->vertices_and_normals_interleaved.reserve(next_highest_power_of_2(this->vertices_and_normals_interleaved.size() + 6));
|
||||||
this->vertices_and_normals_interleaved.push_back(nx);
|
this->vertices_and_normals_interleaved.emplace_back(nx);
|
||||||
this->vertices_and_normals_interleaved.push_back(ny);
|
this->vertices_and_normals_interleaved.emplace_back(ny);
|
||||||
this->vertices_and_normals_interleaved.push_back(nz);
|
this->vertices_and_normals_interleaved.emplace_back(nz);
|
||||||
this->vertices_and_normals_interleaved.push_back(x);
|
this->vertices_and_normals_interleaved.emplace_back(x);
|
||||||
this->vertices_and_normals_interleaved.push_back(y);
|
this->vertices_and_normals_interleaved.emplace_back(y);
|
||||||
this->vertices_and_normals_interleaved.push_back(z);
|
this->vertices_and_normals_interleaved.emplace_back(z);
|
||||||
|
|
||||||
this->vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
|
this->vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
|
||||||
m_bounding_box.merge(Vec3f(x, y, z).cast<double>());
|
m_bounding_box.merge(Vec3f(x, y, z).cast<double>());
|
||||||
|
@ -167,9 +173,9 @@ public:
|
||||||
|
|
||||||
if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity())
|
if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity())
|
||||||
this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3));
|
this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3));
|
||||||
this->triangle_indices.push_back(idx1);
|
this->triangle_indices.emplace_back(idx1);
|
||||||
this->triangle_indices.push_back(idx2);
|
this->triangle_indices.emplace_back(idx2);
|
||||||
this->triangle_indices.push_back(idx3);
|
this->triangle_indices.emplace_back(idx3);
|
||||||
this->triangle_indices_size = this->triangle_indices.size();
|
this->triangle_indices_size = this->triangle_indices.size();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,17 +186,17 @@ public:
|
||||||
|
|
||||||
if (this->quad_indices.size() + 4 > this->vertices_and_normals_interleaved.capacity())
|
if (this->quad_indices.size() + 4 > this->vertices_and_normals_interleaved.capacity())
|
||||||
this->quad_indices.reserve(next_highest_power_of_2(this->quad_indices.size() + 4));
|
this->quad_indices.reserve(next_highest_power_of_2(this->quad_indices.size() + 4));
|
||||||
this->quad_indices.push_back(idx1);
|
this->quad_indices.emplace_back(idx1);
|
||||||
this->quad_indices.push_back(idx2);
|
this->quad_indices.emplace_back(idx2);
|
||||||
this->quad_indices.push_back(idx3);
|
this->quad_indices.emplace_back(idx3);
|
||||||
this->quad_indices.push_back(idx4);
|
this->quad_indices.emplace_back(idx4);
|
||||||
this->quad_indices_size = this->quad_indices.size();
|
this->quad_indices_size = this->quad_indices.size();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Finalize the initialization of the geometry & indices,
|
// Finalize the initialization of the geometry & indices,
|
||||||
// upload the geometry and indices to OpenGL VBO objects
|
// upload the geometry and indices to OpenGL VBO objects
|
||||||
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
||||||
void finalize_geometry() const;
|
void finalize_geometry(bool opengl_initialized);
|
||||||
// Release the geometry data, release OpenGL VBOs.
|
// Release the geometry data, release OpenGL VBOs.
|
||||||
void release_geometry();
|
void release_geometry();
|
||||||
|
|
||||||
|
@ -211,7 +217,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shrink the internal storage to tighly fit the data stored.
|
// Shrink the internal storage to tighly fit the data stored.
|
||||||
void shrink_to_fit() const {
|
void shrink_to_fit() {
|
||||||
this->vertices_and_normals_interleaved.shrink_to_fit();
|
this->vertices_and_normals_interleaved.shrink_to_fit();
|
||||||
this->triangle_indices.shrink_to_fit();
|
this->triangle_indices.shrink_to_fit();
|
||||||
this->quad_indices.shrink_to_fit();
|
this->quad_indices.shrink_to_fit();
|
||||||
|
@ -219,6 +225,22 @@ public:
|
||||||
|
|
||||||
const BoundingBoxf3& bounding_box() const { return m_bounding_box; }
|
const BoundingBoxf3& bounding_box() const { return m_bounding_box; }
|
||||||
|
|
||||||
|
// Return an estimate of the memory consumed by this class.
|
||||||
|
size_t cpu_memory_used() const { return sizeof(*this) + vertices_and_normals_interleaved.capacity() * sizeof(float) + triangle_indices.capacity() * sizeof(int) + quad_indices.capacity() * sizeof(int); }
|
||||||
|
// Return an estimate of the memory held by GPU vertex buffers.
|
||||||
|
size_t gpu_memory_used() const
|
||||||
|
{
|
||||||
|
size_t memsize = 0;
|
||||||
|
if (this->vertices_and_normals_interleaved_VBO_id != 0)
|
||||||
|
memsize += this->vertices_and_normals_interleaved_size * 4;
|
||||||
|
if (this->triangle_indices_VBO_id != 0)
|
||||||
|
memsize += this->triangle_indices_size * 4;
|
||||||
|
if (this->quad_indices_VBO_id != 0)
|
||||||
|
memsize += this->quad_indices_size * 4;
|
||||||
|
return memsize;
|
||||||
|
}
|
||||||
|
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BoundingBoxf3 m_bounding_box;
|
BoundingBoxf3 m_bounding_box;
|
||||||
};
|
};
|
||||||
|
@ -250,7 +272,7 @@ private:
|
||||||
Geometry::Transformation m_volume_transformation;
|
Geometry::Transformation m_volume_transformation;
|
||||||
|
|
||||||
// Shift in z required by sla supports+pad
|
// Shift in z required by sla supports+pad
|
||||||
double m_sla_shift_z;
|
double m_sla_shift_z;
|
||||||
// Bounding box of this volume, in unscaled coordinates.
|
// Bounding box of this volume, in unscaled coordinates.
|
||||||
mutable BoundingBoxf3 m_transformed_bounding_box;
|
mutable BoundingBoxf3 m_transformed_bounding_box;
|
||||||
// Whether or not is needed to recalculate the transformed bounding box.
|
// Whether or not is needed to recalculate the transformed bounding box.
|
||||||
|
@ -420,13 +442,22 @@ public:
|
||||||
void render() const;
|
void render() const;
|
||||||
void render(int color_id, int detection_id, int worldmatrix_id) const;
|
void render(int color_id, int detection_id, int worldmatrix_id) const;
|
||||||
|
|
||||||
void finalize_geometry() { this->indexed_vertex_array.finalize_geometry(); }
|
void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array.finalize_geometry(opengl_initialized); }
|
||||||
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
||||||
|
|
||||||
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
|
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
|
||||||
|
|
||||||
bool is_sla_support() const;
|
bool is_sla_support() const;
|
||||||
bool is_sla_pad() const;
|
bool is_sla_pad() const;
|
||||||
|
|
||||||
|
// Return an estimate of the memory consumed by this class.
|
||||||
|
size_t cpu_memory_used() const {
|
||||||
|
//FIXME what to do wih m_convex_hull?
|
||||||
|
return sizeof(*this) - sizeof(this->indexed_vertex_array) + this->indexed_vertex_array.cpu_memory_used() + this->print_zs.capacity() * sizeof(coordf_t) + this->offsets.capacity() * sizeof(size_t);
|
||||||
|
}
|
||||||
|
// Return an estimate of the memory held by GPU vertex buffers.
|
||||||
|
size_t gpu_memory_used() const { return this->indexed_vertex_array.gpu_memory_used(); }
|
||||||
|
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<GLVolume*> GLVolumePtrs;
|
typedef std::vector<GLVolume*> GLVolumePtrs;
|
||||||
|
@ -461,30 +492,33 @@ public:
|
||||||
~GLVolumeCollection() { clear(); };
|
~GLVolumeCollection() { clear(); };
|
||||||
|
|
||||||
std::vector<int> load_object(
|
std::vector<int> load_object(
|
||||||
const ModelObject* model_object,
|
const ModelObject *model_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
const std::vector<int>& instance_idxs,
|
const std::vector<int> &instance_idxs,
|
||||||
const std::string& color_by);
|
const std::string &color_by,
|
||||||
|
bool opengl_initialized);
|
||||||
|
|
||||||
int load_object_volume(
|
int load_object_volume(
|
||||||
const ModelObject* model_object,
|
const ModelObject *model_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
int volume_idx,
|
int volume_idx,
|
||||||
int instance_idx,
|
int instance_idx,
|
||||||
const std::string& color_by);
|
const std::string &color_by,
|
||||||
|
bool opengl_initialized);
|
||||||
|
|
||||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||||
void load_object_auxiliary(
|
void load_object_auxiliary(
|
||||||
const SLAPrintObject* print_object,
|
const SLAPrintObject *print_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
// pairs of <instance_idx, print_instance_idx>
|
// pairs of <instance_idx, print_instance_idx>
|
||||||
const std::vector<std::pair<size_t, size_t>>& instances,
|
const std::vector<std::pair<size_t, size_t>>& instances,
|
||||||
SLAPrintObjectStep milestone,
|
SLAPrintObjectStep milestone,
|
||||||
// Timestamp of the last change of the milestone
|
// Timestamp of the last change of the milestone
|
||||||
size_t timestamp);
|
size_t timestamp,
|
||||||
|
bool opengl_initialized);
|
||||||
|
|
||||||
int load_wipe_tower_preview(
|
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);
|
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);
|
||||||
|
|
||||||
// Render the volumes by OpenGL.
|
// 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;
|
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
|
||||||
|
@ -492,7 +526,7 @@ public:
|
||||||
// Finalize the initialization of the geometry & indices,
|
// Finalize the initialization of the geometry & indices,
|
||||||
// upload the geometry and indices to OpenGL VBO objects
|
// upload the geometry and indices to OpenGL VBO objects
|
||||||
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
||||||
void finalize_geometry() { for (auto* v : volumes) v->finalize_geometry(); }
|
void finalize_geometry(bool opengl_initialized) { for (auto* v : volumes) v->finalize_geometry(opengl_initialized); }
|
||||||
// Release the geometry data assigned to the volumes.
|
// Release the geometry data assigned to the volumes.
|
||||||
// If OpenGL VBOs were allocated, an OpenGL context has to be active to release them.
|
// If OpenGL VBOs were allocated, an OpenGL context has to be active to release them.
|
||||||
void release_geometry() { for (auto *v : volumes) v->release_geometry(); }
|
void release_geometry() { for (auto *v : volumes) v->release_geometry(); }
|
||||||
|
@ -520,6 +554,14 @@ public:
|
||||||
// Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection
|
// Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection
|
||||||
std::vector<double> get_current_print_zs(bool active_only) const;
|
std::vector<double> get_current_print_zs(bool active_only) const;
|
||||||
|
|
||||||
|
// Return an estimate of the memory consumed by this class.
|
||||||
|
size_t cpu_memory_used() const;
|
||||||
|
// Return an estimate of the memory held by GPU vertex buffers.
|
||||||
|
size_t gpu_memory_used() const;
|
||||||
|
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||||
|
// Return CPU, GPU and total memory log line.
|
||||||
|
std::string log_memory_info() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLVolumeCollection(const GLVolumeCollection &other);
|
GLVolumeCollection(const GLVolumeCollection &other);
|
||||||
GLVolumeCollection& operator=(const GLVolumeCollection &);
|
GLVolumeCollection& operator=(const GLVolumeCollection &);
|
||||||
|
@ -537,6 +579,7 @@ public:
|
||||||
GLModel();
|
GLModel();
|
||||||
virtual ~GLModel();
|
virtual ~GLModel();
|
||||||
|
|
||||||
|
// init() / init_from_file() shall be called with the OpenGL context active!
|
||||||
bool init() { return on_init(); }
|
bool init() { return on_init(); }
|
||||||
bool init_from_file(const std::string& filename) { return on_init_from_file(filename); }
|
bool init_from_file(const std::string& filename) { return on_init_from_file(filename); }
|
||||||
|
|
||||||
|
@ -566,7 +609,7 @@ protected:
|
||||||
class GLArrow : public GLModel
|
class GLArrow : public GLModel
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual bool on_init();
|
bool on_init() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GLCurvedArrow : public GLModel
|
class GLCurvedArrow : public GLModel
|
||||||
|
@ -577,13 +620,13 @@ public:
|
||||||
explicit GLCurvedArrow(unsigned int resolution);
|
explicit GLCurvedArrow(unsigned int resolution);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool on_init();
|
bool on_init() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GLBed : public GLModel
|
class GLBed : public GLModel
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual bool on_init_from_file(const std::string& filename);
|
bool on_init_from_file(const std::string& filename) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class _3DScene
|
class _3DScene
|
||||||
|
|
|
@ -1234,10 +1234,9 @@ bool GLCanvas3D::init()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // on linux the gl context is not valid until the canvas is not shown on screen
|
// on linux the gl context is not valid until the canvas is not shown on screen
|
||||||
// // we defer the geometry finalization of volumes until the first call to render()
|
// we defer the geometry finalization of volumes until the first call to render()
|
||||||
// if (!m_volumes.empty())
|
m_volumes.finalize_geometry(true);
|
||||||
// m_volumes.finalize_geometry();
|
|
||||||
|
|
||||||
if (m_gizmos.is_enabled() && !m_gizmos.init())
|
if (m_gizmos.is_enabled() && !m_gizmos.init())
|
||||||
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
||||||
|
@ -1691,7 +1690,7 @@ std::vector<int> GLCanvas3D::load_object(const ModelObject& model_object, int ob
|
||||||
instance_idxs.push_back(i);
|
instance_idxs.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by);
|
return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_initialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
||||||
|
@ -1879,7 +1878,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
|
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
|
||||||
if (it->new_geometry()) {
|
if (it->new_geometry()) {
|
||||||
// New volume.
|
// New volume.
|
||||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by);
|
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized);
|
||||||
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
||||||
update_object_list = true;
|
update_object_list = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1952,7 +1951,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
|
|
||||||
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
||||||
if (!instances[istep].empty())
|
if (!instances[istep].empty())
|
||||||
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
|
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
||||||
|
@ -1992,7 +1991,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
depth = (900.f/w) * (float)(extruders_count - 1);
|
depth = (900.f/w) * (float)(extruders_count - 1);
|
||||||
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
|
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
|
||||||
1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower),
|
1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower),
|
||||||
brim_spacing * 4.5f);
|
brim_spacing * 4.5f, m_initialized);
|
||||||
if (volume_idx_wipe_tower_old != -1)
|
if (volume_idx_wipe_tower_old != -1)
|
||||||
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
|
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
|
||||||
}
|
}
|
||||||
|
@ -4511,6 +4510,7 @@ void GLCanvas3D::_load_print_toolpaths()
|
||||||
|
|
||||||
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), volume);
|
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), volume);
|
||||||
}
|
}
|
||||||
|
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)
|
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)
|
||||||
|
@ -4576,7 +4576,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
||||||
|
|
||||||
// Maximum size of an allocation block: 32MB / sizeof(float)
|
// Maximum size of an allocation block: 32MB / sizeof(float)
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
|
||||||
//FIXME Improve the heuristics for a grain size.
|
//FIXME Improve the heuristics for a grain size.
|
||||||
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
||||||
|
@ -4682,16 +4682,22 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (GLVolume *vol : vols)
|
||||||
|
// Ideally one would call vol->indexed_vertex_array.finalize() here to move the buffers to the OpenGL driver,
|
||||||
|
// but this code runs in parallel and the OpenGL driver is not thread safe.
|
||||||
|
vol->indexed_vertex_array.shrink_to_fit();
|
||||||
});
|
});
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results";
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
// Remove empty volumes from the newly added volumes.
|
// Remove empty volumes from the newly added volumes.
|
||||||
m_volumes.volumes.erase(
|
m_volumes.volumes.erase(
|
||||||
std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
|
std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
|
||||||
[](const GLVolume *volume) { return volume->empty(); }),
|
[](const GLVolume *volume) { return volume->empty(); }),
|
||||||
m_volumes.volumes.end());
|
m_volumes.volumes.end());
|
||||||
|
for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i)
|
||||||
|
m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors)
|
void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors)
|
||||||
|
@ -4748,7 +4754,7 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
|
||||||
ctxt.wipe_tower_angle = ctxt.print->config().wipe_tower_rotation_angle.value/180.f * PI;
|
ctxt.wipe_tower_angle = ctxt.print->config().wipe_tower_rotation_angle.value/180.f * PI;
|
||||||
ctxt.wipe_tower_pos = Vec2f(ctxt.print->config().wipe_tower_x.value, ctxt.print->config().wipe_tower_y.value);
|
ctxt.wipe_tower_pos = Vec2f(ctxt.print->config().wipe_tower_x.value, ctxt.print->config().wipe_tower_y.value);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
|
||||||
//FIXME Improve the heuristics for a grain size.
|
//FIXME Improve the heuristics for a grain size.
|
||||||
size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||||
|
@ -4846,16 +4852,20 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
|
||||||
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (GLVolume *vol : vols)
|
||||||
|
vol->indexed_vertex_array.shrink_to_fit();
|
||||||
});
|
});
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results";
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
// Remove empty volumes from the newly added volumes.
|
// Remove empty volumes from the newly added volumes.
|
||||||
m_volumes.volumes.erase(
|
m_volumes.volumes.erase(
|
||||||
std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
|
std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
|
||||||
[](const GLVolume *volume) { return volume->empty(); }),
|
[](const GLVolume *volume) { return volume->empty(); }),
|
||||||
m_volumes.volumes.end());
|
m_volumes.volumes.end());
|
||||||
|
for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i)
|
||||||
|
m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int hex_digit_to_int(const char c)
|
static inline int hex_digit_to_int(const char c)
|
||||||
|
@ -4868,6 +4878,8 @@ static inline int hex_digit_to_int(const char c)
|
||||||
|
|
||||||
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
{
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - start" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
|
||||||
// helper functions to select data in dependence of the extrusion view type
|
// helper functions to select data in dependence of the extrusion view type
|
||||||
struct Helper
|
struct Helper
|
||||||
{
|
{
|
||||||
|
@ -4983,6 +4995,8 @@ 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
|
// creates a new volume for each filter
|
||||||
for (Filter& filter : filters)
|
for (Filter& filter : filters)
|
||||||
{
|
{
|
||||||
|
@ -5013,6 +5027,8 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - populate volumes" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
|
||||||
// populates volumes
|
// populates volumes
|
||||||
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
|
||||||
{
|
{
|
||||||
|
@ -5030,6 +5046,12 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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)
|
void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
|
@ -5074,6 +5096,10 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data,
|
||||||
|
|
||||||
return;
|
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)
|
bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
|
||||||
|
@ -5302,6 +5328,7 @@ void GLCanvas3D::_load_gcode_retractions(const GCodePreviewData& preview_data)
|
||||||
|
|
||||||
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
|
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
|
||||||
}
|
}
|
||||||
|
volume->indexed_vertex_array.finalize_geometry(m_initialized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5329,6 +5356,7 @@ void GLCanvas3D::_load_gcode_unretractions(const GCodePreviewData& preview_data)
|
||||||
|
|
||||||
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
|
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
|
||||||
}
|
}
|
||||||
|
volume->indexed_vertex_array.finalize_geometry(m_initialized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5354,7 +5382,7 @@ void GLCanvas3D::_load_fff_shells()
|
||||||
instance_ids[i] = i;
|
instance_ids[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_volumes.load_object(model_obj, object_id, instance_ids, "object");
|
m_volumes.load_object(model_obj, object_id, instance_ids, "object", m_initialized);
|
||||||
|
|
||||||
++object_id;
|
++object_id;
|
||||||
}
|
}
|
||||||
|
@ -5376,7 +5404,7 @@ void GLCanvas3D::_load_fff_shells()
|
||||||
if (!print->is_step_done(psWipeTower))
|
if (!print->is_step_done(psWipeTower))
|
||||||
depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1);
|
depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1);
|
||||||
m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
|
m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
|
||||||
!print->is_step_done(psWipeTower), brim_spacing * 4.5f);
|
!print->is_step_done(psWipeTower), brim_spacing * 4.5f, m_initialized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ void Selection::set_volumes(GLVolumePtrs* volumes)
|
||||||
update_valid();
|
update_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init shall be called from the OpenGL render function, so that the OpenGL context is initialized!
|
||||||
bool Selection::init()
|
bool Selection::init()
|
||||||
{
|
{
|
||||||
if (!m_arrow.init())
|
if (!m_arrow.init())
|
||||||
|
|
Loading…
Reference in a new issue