GLVolume and GLIndexedVertexArray refactored to send data to gpu at the first render call

This commit is contained in:
Enrico Turri 2019-07-02 12:55:55 +02:00
parent 2356fe5a13
commit d15698e21e
3 changed files with 128 additions and 232 deletions

View file

@ -74,13 +74,13 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh)
} }
} }
void GLIndexedVertexArray::finalize_geometry() void GLIndexedVertexArray::finalize_geometry() const
{ {
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->setup_sizes(); this->shrink_to_fit();
if (! empty()) { if (! empty()) {
glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id)); glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
@ -103,8 +103,6 @@ void GLIndexedVertexArray::finalize_geometry()
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
this->quad_indices.clear(); this->quad_indices.clear();
} }
this->shrink_to_fit();
} }
void GLIndexedVertexArray::release_geometry() void GLIndexedVertexArray::release_geometry()
@ -122,89 +120,78 @@ void GLIndexedVertexArray::release_geometry()
this->quad_indices_VBO_id = 0; this->quad_indices_VBO_id = 0;
} }
this->clear(); this->clear();
this->shrink_to_fit();
} }
void GLIndexedVertexArray::render() const void GLIndexedVertexArray::render() const
{ {
if (this->vertices_and_normals_interleaved_VBO_id) { if (this->vertices_and_normals_interleaved_VBO_id == 0)
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)))); // sends data to gpu, if not done yet
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); finalize_geometry();
} else { if (this->vertices_and_normals_interleaved_VBO_id == 0)
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3)); return;
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
} }
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(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (this->indexed()) { // Render using the Vertex Buffer Objects.
if (this->vertices_and_normals_interleaved_VBO_id) { if (this->triangle_indices_size > 0) {
// Render using the Vertex Buffer Objects. glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
if (this->triangle_indices_size > 0) { glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr)); }
} if (this->quad_indices_size > 0) {
if (this->quad_indices_size > 0) { glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); glsafe(::glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr));
glsafe(::glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr)); glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
// Render in an immediate mode.
if (! this->triangle_indices.empty())
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data()));
if (! this->quad_indices.empty())
glsafe(::glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data()));
}
} else
glsafe(::glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6)));
if (this->vertices_and_normals_interleaved_VBO_id)
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
}
void GLIndexedVertexArray::render(
const std::pair<size_t, size_t> &tverts_range,
const std::pair<size_t, size_t> &qverts_range) const
{
assert(this->indexed());
if (! this->indexed())
return;
if (this->vertices_and_normals_interleaved_VBO_id) {
// Render using the Vertex Buffer Objects.
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(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (this->triangle_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
}
if (this->quad_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(::glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
}
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
// Render in an immediate mode.
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (! this->triangle_indices.empty())
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first)));
if (! this->quad_indices.empty())
glsafe(::glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first)));
} }
glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
void GLIndexedVertexArray::render(
const std::pair<size_t, size_t>& tverts_range,
const std::pair<size_t, size_t>& qverts_range) const
{
if (this->vertices_and_normals_interleaved_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.
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(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (this->triangle_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
if (this->quad_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(::glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
} }
const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
@ -357,9 +344,9 @@ BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d &
void GLVolume::set_range(double min_z, double max_z) void GLVolume::set_range(double min_z, double max_z)
{ {
this->qverts_range.first = 0; this->qverts_range.first = 0;
this->qverts_range.second = this->indexed_vertex_array.quad_indices_size; this->qverts_range.second = this->indexed_vertex_array.quad_indices_size;
this->tverts_range.first = 0; this->tverts_range.first = 0;
this->tverts_range.second = this->indexed_vertex_array.triangle_indices_size; this->tverts_range.second = this->indexed_vertex_array.triangle_indices_size;
if (! this->print_zs.empty()) { if (! this->print_zs.empty()) {
// The Z layer range is specified. // The Z layer range is specified.
@ -399,12 +386,10 @@ void GLVolume::render() const
glFrontFace(GL_CW); glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK)); glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(world_matrix().data())); glsafe(::glMultMatrixd(world_matrix().data()));
if (this->indexed_vertex_array.indexed())
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range); this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
else
this->indexed_vertex_array.render();
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
if (this->is_left_handed()) if (this->is_left_handed())
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
@ -412,45 +397,6 @@ void GLVolume::render() const
void GLVolume::render(int color_id, int detection_id, int worldmatrix_id) const void GLVolume::render(int color_id, int detection_id, int worldmatrix_id) const
{ {
if (!is_active)
return;
if (!indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)
return;
GLsizei n_triangles = GLsizei(std::min(indexed_vertex_array.triangle_indices_size, tverts_range.second - tverts_range.first));
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
if (n_triangles + n_quads == 0)
{
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (color_id >= 0)
{
float color[4];
::memcpy((void*)color, (const void*)render_color, 4 * sizeof(float));
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color));
}
else
glsafe(::glColor4fv(render_color));
if (detection_id != -1)
glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0));
if (worldmatrix_id != -1)
glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data()));
render();
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
return;
}
if (this->is_left_handed())
glFrontFace(GL_CW);
if (color_id >= 0) if (color_id >= 0)
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)render_color)); glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)render_color));
else else
@ -462,29 +408,7 @@ void GLVolume::render(int color_id, int detection_id, int worldmatrix_id) const
if (worldmatrix_id != -1) if (worldmatrix_id != -1)
glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data())); glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data()));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)); render();
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(world_matrix().data()));
if (n_triangles > 0)
{
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id));
glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
}
if (n_quads > 0)
{
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id));
glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
}
glsafe(::glPopMatrix());
if (this->is_left_handed())
glFrontFace(GL_CCW);
} }
bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -int(slaposSupportTree); } bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -int(slaposSupportTree); }
@ -531,8 +455,6 @@ 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();
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())
{ {
@ -573,7 +495,6 @@ 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();
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.
@ -645,8 +566,6 @@ int GLVolumeCollection::load_wipe_tower_preview(
v.indexed_vertex_array.load_mesh(mesh); v.indexed_vertex_array.load_mesh(mesh);
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.indexed_vertex_array.finalize_geometry();
v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0); v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0);
v.geometry_id.first = 0; v.geometry_id.first = 0;
v.geometry_id.second = wipe_tower_instance_id().id; v.geometry_id.second = wipe_tower_instance_id().id;
@ -1576,7 +1495,9 @@ void GLModel::set_scale(const Vec3d& scale)
void GLModel::reset() void GLModel::reset()
{ {
m_volume.release_geometry(); //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// m_volume.release_geometry();
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
m_filename = ""; m_filename = "";
} }
@ -1659,7 +1580,6 @@ 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.finalize_geometry();
return true; return true;
} }
@ -1773,7 +1693,6 @@ 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.finalize_geometry();
return true; return true;
} }
@ -1810,8 +1729,6 @@ bool GLBed::on_init_from_file(const std::string& filename)
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);
m_volume.finalize_geometry();
return true; return true;
} }

View file

@ -56,7 +56,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)
{ this->setup_sizes(); } {}
GLIndexedVertexArray(const GLIndexedVertexArray &rhs) : GLIndexedVertexArray(const GLIndexedVertexArray &rhs) :
vertices_and_normals_interleaved(rhs.vertices_and_normals_interleaved), vertices_and_normals_interleaved(rhs.vertices_and_normals_interleaved),
triangle_indices(rhs.triangle_indices), triangle_indices(rhs.triangle_indices),
@ -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)
{ this->setup_sizes(); } {}
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,11 @@ 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)
{ this->setup_sizes(); } {}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
~GLIndexedVertexArray() { release_geometry(); }
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs) GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs)
{ {
@ -83,7 +87,9 @@ public:
this->triangle_indices = rhs.triangle_indices; this->triangle_indices = rhs.triangle_indices;
this->quad_indices = rhs.quad_indices; this->quad_indices = rhs.quad_indices;
this->m_bounding_box = rhs.m_bounding_box; this->m_bounding_box = rhs.m_bounding_box;
this->setup_sizes(); vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
triangle_indices_size = rhs.triangle_indices_size;
quad_indices_size = rhs.quad_indices_size;
return *this; return *this;
} }
@ -96,26 +102,28 @@ public:
this->triangle_indices = std::move(rhs.triangle_indices); this->triangle_indices = std::move(rhs.triangle_indices);
this->quad_indices = std::move(rhs.quad_indices); this->quad_indices = std::move(rhs.quad_indices);
this->m_bounding_box = std::move(rhs.m_bounding_box); this->m_bounding_box = std::move(rhs.m_bounding_box);
this->setup_sizes(); vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
triangle_indices_size = rhs.triangle_indices_size;
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)
std::vector<float> vertices_and_normals_interleaved; mutable std::vector<float> vertices_and_normals_interleaved;
std::vector<int> triangle_indices; mutable std::vector<int> triangle_indices;
std::vector<int> quad_indices; mutable 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.
size_t vertices_and_normals_interleaved_size; size_t vertices_and_normals_interleaved_size{ 0 };
size_t triangle_indices_size; size_t triangle_indices_size{ 0 };
size_t quad_indices_size; size_t quad_indices_size{ 0 };
// 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.
unsigned int vertices_and_normals_interleaved_VBO_id; mutable unsigned int vertices_and_normals_interleaved_VBO_id{ 0 };
unsigned int triangle_indices_VBO_id; mutable unsigned int triangle_indices_VBO_id{ 0 };
unsigned int quad_indices_VBO_id; mutable 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); }
@ -129,6 +137,10 @@ public:
} }
inline void push_geometry(float x, float y, float z, float nx, float ny, float nz) { inline void push_geometry(float x, float y, float z, float nx, float ny, float nz) {
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
if (this->vertices_and_normals_interleaved_VBO_id != 0)
return;
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.push_back(nx);
@ -138,6 +150,7 @@ public:
this->vertices_and_normals_interleaved.push_back(y); this->vertices_and_normals_interleaved.push_back(y);
this->vertices_and_normals_interleaved.push_back(z); this->vertices_and_normals_interleaved.push_back(z);
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>());
}; };
@ -150,50 +163,57 @@ public:
} }
inline void push_triangle(int idx1, int idx2, int idx3) { inline void push_triangle(int idx1, int idx2, int idx3) {
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
if (this->vertices_and_normals_interleaved_VBO_id != 0)
return;
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.push_back(idx1);
this->triangle_indices.push_back(idx2); this->triangle_indices.push_back(idx2);
this->triangle_indices.push_back(idx3); this->triangle_indices.push_back(idx3);
this->triangle_indices_size = this->triangle_indices.size();
}; };
inline void push_quad(int idx1, int idx2, int idx3, int idx4) { inline void push_quad(int idx1, int idx2, int idx3, int idx4) {
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
if (this->vertices_and_normals_interleaved_VBO_id != 0)
return;
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.push_back(idx1);
this->quad_indices.push_back(idx2); this->quad_indices.push_back(idx2);
this->quad_indices.push_back(idx3); this->quad_indices.push_back(idx3);
this->quad_indices.push_back(idx4); this->quad_indices.push_back(idx4);
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(); void finalize_geometry() const;
// Release the geometry data, release OpenGL VBOs. // Release the geometry data, release OpenGL VBOs.
void release_geometry(); void release_geometry();
void render() const; void render() const;
void render(const std::pair<size_t, size_t> &tverts_range, const std::pair<size_t, size_t> &qverts_range) const; void render(const std::pair<size_t, size_t>& tverts_range, const std::pair<size_t, size_t>& qverts_range) const;
// Is there any geometry data stored? // Is there any geometry data stored?
bool empty() const { return vertices_and_normals_interleaved_size == 0; } bool empty() const { return vertices_and_normals_interleaved_size == 0; }
// Is this object indexed, or is it just a set of triangles?
bool indexed() const { return ! this->empty() && this->triangle_indices_size + this->quad_indices_size > 0; }
void clear() { void clear() {
this->vertices_and_normals_interleaved.clear(); this->vertices_and_normals_interleaved.clear();
this->triangle_indices.clear(); this->triangle_indices.clear();
this->quad_indices.clear(); this->quad_indices.clear();
this->m_bounding_box.reset(); this->m_bounding_box.reset();
this->setup_sizes(); vertices_and_normals_interleaved_size = 0;
triangle_indices_size = 0;
quad_indices_size = 0;
} }
// Shrink the internal storage to tighly fit the data stored. // Shrink the internal storage to tighly fit the data stored.
void shrink_to_fit() { void shrink_to_fit() const {
if (! this->has_VBOs())
this->setup_sizes();
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();
@ -203,12 +223,6 @@ public:
private: private:
BoundingBoxf3 m_bounding_box; BoundingBoxf3 m_bounding_box;
inline void setup_sizes() {
vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
triangle_indices_size = this->triangle_indices.size();
quad_indices_size = this->quad_indices.size();
}
}; };
class GLVolume { class GLVolume {
@ -400,9 +414,9 @@ public:
const BoundingBoxf3& transformed_convex_hull_bounding_box() const; const BoundingBoxf3& transformed_convex_hull_bounding_box() const;
bool empty() const { return this->indexed_vertex_array.empty(); } bool empty() const { return this->indexed_vertex_array.empty(); }
bool indexed() const { return this->indexed_vertex_array.indexed(); }
void set_range(coordf_t low, coordf_t high); void set_range(coordf_t low, coordf_t high);
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;

View file

@ -524,7 +524,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
glsafe(::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data())); glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data()));
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4)); glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4));
for (const GLVolume *glvolume : volumes.volumes) { for (const GLVolume* glvolume : volumes.volumes) {
// Render the object using the layer editing shader and texture. // Render the object using the layer editing shader and texture.
if (! glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier) if (! glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
continue; continue;
@ -543,8 +543,8 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
{ {
// Something went wrong. Just render the object. // Something went wrong. Just render the object.
assert(false); assert(false);
for (const GLVolume *glvolume : volumes.volumes) { for (const GLVolume* glvolume : volumes.volumes) {
// Render the object using the layer editing shader and texture. // Render the object using the layer editing shader and texture.
if (!glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier) if (!glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
continue; continue;
glsafe(::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)glvolume->world_matrix().cast<float>().data())); glsafe(::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)glvolume->world_matrix().cast<float>().data()));
@ -1314,10 +1314,10 @@ 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()) // if (!m_volumes.empty())
m_volumes.finalize_geometry(); // m_volumes.finalize_geometry();
if (m_gizmos.is_enabled() && !m_gizmos.init(*this)) if (m_gizmos.is_enabled() && !m_gizmos.init(*this))
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;
@ -1355,7 +1355,9 @@ void GLCanvas3D::reset_volumes()
if (!m_volumes.empty()) if (!m_volumes.empty())
{ {
m_selection.clear(); m_selection.clear();
m_volumes.release_geometry(); //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// m_volumes.release_geometry();
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
m_volumes.clear(); m_volumes.clear();
m_dirty = true; m_dirty = true;
} }
@ -1917,7 +1919,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
assert(volume_idx_wipe_tower_old == -1); assert(volume_idx_wipe_tower_old == -1);
volume_idx_wipe_tower_old = (int)volume_id; volume_idx_wipe_tower_old = (int)volume_id;
} }
volume->release_geometry(); //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// volume->release_geometry();
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if (! m_reload_delayed) if (! m_reload_delayed)
delete volume; delete volume;
} else { } else {
@ -4474,7 +4478,6 @@ 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();
} }
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)
@ -4646,9 +4649,6 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
} }
} }
} }
for (GLVolume *vol : vols) {
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";
@ -4657,8 +4657,6 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
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();
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end"; BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
} }
@ -4814,9 +4812,6 @@ 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";
@ -4825,8 +4820,6 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
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();
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end"; BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
} }
@ -5003,16 +4996,6 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
} }
} }
} }
// finalize volumes and sends geometry to gpu
if (m_volumes.volumes.size() > initial_volumes_count)
{
for (size_t i = initial_volumes_count; i < m_volumes.volumes.size(); ++i)
{
GLVolume* volume = m_volumes.volumes[i];
volume->indexed_vertex_array.finalize_geometry();
}
}
} }
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)
@ -5057,16 +5040,6 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data,
return; return;
} }
// finalize volumes and sends geometry to gpu
if (m_volumes.volumes.size() > initial_volumes_count)
{
for (size_t i = initial_volumes_count; i < m_volumes.volumes.size(); ++i)
{
GLVolume* volume = m_volumes.volumes[i];
volume->indexed_vertex_array.finalize_geometry();
}
}
} }
bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data) bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
@ -5295,9 +5268,6 @@ 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);
} }
// finalize volumes and sends geometry to gpu
volume->indexed_vertex_array.finalize_geometry();
} }
} }
@ -5325,9 +5295,6 @@ 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);
} }
// finalize volumes and sends geometry to gpu
volume->indexed_vertex_array.finalize_geometry();
} }
} }
@ -5419,8 +5386,6 @@ void GLCanvas3D::_load_sla_shells()
double shift_z = obj->get_current_elevation(); double shift_z = obj->get_current_elevation();
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) { for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
GLVolume& v = *m_volumes.volumes[i]; GLVolume& v = *m_volumes.volumes[i];
// finalize volumes and sends geometry to gpu
v.indexed_vertex_array.finalize_geometry();
// apply shift z // apply shift z
v.set_sla_shift_z(shift_z); v.set_sla_shift_z(shift_z);
} }