Use Vertex Buffer Objects for rendering of 3D volumes if possible.
This commit is contained in:
parent
c32c7fa1dc
commit
7f7d2da5fe
@ -540,6 +540,10 @@ sub mouse_wheel_event {
|
|||||||
# Reset selection.
|
# Reset selection.
|
||||||
sub reset_objects {
|
sub reset_objects {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
if ($self->{use_VBOs}) {
|
||||||
|
$self->GetContext;
|
||||||
|
$self->volumes->release_geometry;
|
||||||
|
}
|
||||||
$self->volumes->erase;
|
$self->volumes->erase;
|
||||||
$self->_dirty(1);
|
$self->_dirty(1);
|
||||||
}
|
}
|
||||||
@ -944,6 +948,10 @@ sub InitGL {
|
|||||||
return unless $self->GetContext;
|
return unless $self->GetContext;
|
||||||
$self->init(1);
|
$self->init(1);
|
||||||
|
|
||||||
|
my @gl_version = split(/\./, glGetString(GL_VERSION));
|
||||||
|
$self->{use_VBOs} = int($gl_version[0]) >= 2;
|
||||||
|
# print "OpenGL major: $gl_version[0], minor: $gl_version[1]. Use VBOs: ", $self->{use_VBOs}, "\n";
|
||||||
|
|
||||||
glClearColor(0, 0, 0, 1);
|
glClearColor(0, 0, 0, 1);
|
||||||
glColor3f(1, 0, 0);
|
glColor3f(1, 0, 0);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
@ -983,12 +991,15 @@ sub InitGL {
|
|||||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||||
glEnable(GL_COLOR_MATERIAL);
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
|
Slic3r::GUI::_3DScene::_glew_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub DestroyGL {
|
sub DestroyGL {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
if ($self->init && $self->GetContext) {
|
if ($self->init && $self->GetContext) {
|
||||||
delete $self->{shader};
|
delete $self->{shader};
|
||||||
|
$self->volumes->release_geometry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,58 +1262,7 @@ sub draw_volumes {
|
|||||||
glColor4f(@{ $volume->color });
|
glColor4f(@{ $volume->color });
|
||||||
}
|
}
|
||||||
|
|
||||||
glPushMatrix();
|
$volume->render;
|
||||||
glTranslatef(@{$volume->origin});
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
if (1) {
|
|
||||||
if ($volume->indexed) {
|
|
||||||
my $quads_cnt = $volume->indexed_quads_to_render_cnt;
|
|
||||||
my $triangles_cnt = $volume->indexed_triangles_to_render_cnt;
|
|
||||||
if ($quads_cnt + $triangles_cnt > 0) {
|
|
||||||
if ($self->{use_VBOs}) {
|
|
||||||
my ($name_geometry, $name_triangle_indices, $name_quad_indices) = glGenBuffersARB_p(3);
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, $name_geometry);
|
|
||||||
glBufferDataARB_c(GL_ARRAY_BUFFER_ARB, $volume->geometry_size, $volume->triangles_to_render_ptr, GL_STATIC_DRAW_ARB);
|
|
||||||
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
|
|
||||||
if ($quads_cnt) {
|
|
||||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, $name_quad_indices);
|
|
||||||
glBufferDataARB_c(GL_ELEMENT_ARRAY_BUFFER_ARB, $volume->indexed_quads_cnt * 4, $volume->quad_indices_ptr, GL_STATIC_DRAW_ARB);
|
|
||||||
glDrawElements_c(GL_QUADS, $quads_cnt, GL_UNSIGNED_INT, $volume->quad_indices_to_render_offset * 4);
|
|
||||||
}
|
|
||||||
if ($triangles_cnt) {
|
|
||||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, $name_triangle_indices);
|
|
||||||
glBufferDataARB_c(GL_ELEMENT_ARRAY_BUFFER_ARB, $volume->indexed_triangles_cnt * 4, $volume->triangle_indices_ptr, GL_STATIC_DRAW_ARB);
|
|
||||||
glDrawElements_c(GL_TRIANGLES, $triangles_cnt, GL_UNSIGNED_INT, $volume->triangle_indices_to_render_offset * 4);
|
|
||||||
}
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
|
||||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
|
||||||
glDeleteBuffersARB_p(($name_geometry, $name_triangle_indices, $name_quad_indices));
|
|
||||||
} else {
|
|
||||||
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr);
|
|
||||||
glDrawElements_c(GL_QUADS, $quads_cnt, GL_UNSIGNED_INT, $volume->quad_indices_ptr + $volume->quad_indices_to_render_offset * 4)
|
|
||||||
if ($quads_cnt);
|
|
||||||
glDrawElements_c(GL_TRIANGLES, $triangles_cnt, GL_UNSIGNED_INT, $volume->triangle_indices_ptr + $volume->triangle_indices_to_render_offset * 4)
|
|
||||||
if ($triangles_cnt);
|
|
||||||
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elsif (! $volume->empty) {
|
|
||||||
if ($self->{use_VBOs}) {
|
|
||||||
my ($name_geometry) = glGenBuffersARB_p(1);
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, $name_geometry);
|
|
||||||
glBufferDataARB_c(GL_ARRAY_BUFFER_ARB, $volume->triangles_to_render_cnt * 6 * 4, $volume->triangles_to_render_ptr, GL_STATIC_DRAW_ARB);
|
|
||||||
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, $volume->triangles_to_render_cnt);
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
|
||||||
glDeleteBuffersARB_p(($name_geometry));
|
|
||||||
} else {
|
|
||||||
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr);
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, $volume->triangles_to_render_cnt);
|
|
||||||
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
if ($shader_active) {
|
if ($shader_active) {
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
@ -174,7 +174,7 @@ void* NSGLGetProcAddress (const GLubyte *name)
|
|||||||
#if defined(GLEW_REGAL)
|
#if defined(GLEW_REGAL)
|
||||||
# define glewGetProcAddress(name) regalGetProcAddress((const GLchar *) name)
|
# define glewGetProcAddress(name) regalGetProcAddress((const GLchar *) name)
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
# define glewGetProcAddress(name) ((LPCSTR)name)
|
# define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name)
|
||||||
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
|
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
|
||||||
# define glewGetProcAddress(name) NSGLGetProcAddress(name)
|
# define glewGetProcAddress(name) NSGLGetProcAddress(name)
|
||||||
#elif defined(__sgi) || defined(__sun) || defined(__HAIKU__)
|
#elif defined(__sgi) || defined(__sun) || defined(__HAIKU__)
|
||||||
@ -12105,8 +12105,10 @@ GLenum GLEWAPIENTRY wglewInit (WGLEW_CONTEXT_ARG_DEF_LIST)
|
|||||||
extStart = (const GLubyte*)"";
|
extStart = (const GLubyte*)"";
|
||||||
else
|
else
|
||||||
extStart = (const GLubyte*)_wglewGetExtensionsStringEXT();
|
extStart = (const GLubyte*)_wglewGetExtensionsStringEXT();
|
||||||
else
|
else {
|
||||||
extStart = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
|
HDC dc = wglGetCurrentDC();
|
||||||
|
extStart = (const GLubyte*)_wglewGetExtensionsStringARB(dc);
|
||||||
|
}
|
||||||
extEnd = extStart + _glewStrLen(extStart);
|
extEnd = extStart + _glewStrLen(extStart);
|
||||||
/* initialize extensions */
|
/* initialize extensions */
|
||||||
crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL;
|
crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL;
|
||||||
|
@ -1353,7 +1353,7 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#if 0
|
||||||
void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coord_t resolution, const char *path)
|
void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coord_t resolution, const char *path)
|
||||||
{
|
{
|
||||||
unsigned int w = (bbox.max.x - bbox.min.x + resolution - 1) / resolution;
|
unsigned int w = (bbox.max.x - bbox.min.x + resolution - 1) / resolution;
|
||||||
|
@ -107,7 +107,7 @@ protected:
|
|||||||
std::vector<float> m_signed_distance_field;
|
std::vector<float> m_signed_distance_field;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#if 0
|
||||||
// Debugging utility. Save the signed distance field.
|
// Debugging utility. Save the signed distance field.
|
||||||
extern void save_png(const Grid &grid, const BoundingBox &bbox, coord_t resolution, const char *path);
|
extern void save_png(const Grid &grid, const BoundingBox &bbox, coord_t resolution, const char *path);
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
@ -940,7 +940,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||||||
::Slic3r::SVG svg(debug_out_path("support-bottom-contacts-simplified-%d-%d.svg", iRun, layer_id), bbox);
|
::Slic3r::SVG svg(debug_out_path("support-bottom-contacts-simplified-%d-%d.svg", iRun, layer_id), bbox);
|
||||||
svg.draw(union_ex(projection, false), "blue", 0.5);
|
svg.draw(union_ex(projection, false), "blue", 0.5);
|
||||||
svg.draw(union_ex(projection_simplified, false), "red", 0.5);
|
svg.draw(union_ex(projection_simplified, false), "red", 0.5);
|
||||||
#ifdef SLIC3R_GUI
|
#if 0
|
||||||
bbox.min.x -= scale_(5.f);
|
bbox.min.x -= scale_(5.f);
|
||||||
bbox.min.y -= scale_(5.f);
|
bbox.min.y -= scale_(5.f);
|
||||||
bbox.max.x += scale_(5.f);
|
bbox.max.x += scale_(5.f);
|
||||||
@ -1593,12 +1593,12 @@ struct MyLayerExtruded
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The source layer. It carries the height and extrusion type (bridging / non bridging, extrusion height).
|
// The source layer. It carries the height and extrusion type (bridging / non bridging, extrusion height).
|
||||||
PrintObjectSupportMaterial::MyLayer *layer;
|
PrintObjectSupportMaterial::MyLayer *layer;
|
||||||
// Collect extrusions. They will be exported sorted by the bottom height.
|
// Collect extrusions. They will be exported sorted by the bottom height.
|
||||||
ExtrusionEntitiesPtr extrusions;
|
ExtrusionEntitiesPtr extrusions;
|
||||||
// In case the extrusions are non-empty, m_polygons_to_extrude may contain the rest areas yet to be filled by additional support.
|
// In case the extrusions are non-empty, m_polygons_to_extrude may contain the rest areas yet to be filled by additional support.
|
||||||
// This is useful mainly for the loop interfaces, which are generated before the zig-zag infills.
|
// This is useful mainly for the loop interfaces, which are generated before the zig-zag infills.
|
||||||
Polygons *m_polygons_to_extrude;
|
Polygons *m_polygons_to_extrude;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<MyLayerExtruded*> MyLayerExtrudedPtrs;
|
typedef std::vector<MyLayerExtruded*> MyLayerExtrudedPtrs;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
|
|
||||||
#include "../../libslic3r/libslic3r.h"
|
#include "../../libslic3r/libslic3r.h"
|
||||||
@ -21,6 +23,10 @@ namespace Slic3r {
|
|||||||
|
|
||||||
void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
|
void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
|
||||||
{
|
{
|
||||||
|
assert(triangle_indices.empty() && vertices_and_normals_interleaved_size == 0);
|
||||||
|
assert(quad_indices.empty() && triangle_indices_size == 0);
|
||||||
|
assert(vertices_and_normals_interleaved.size() % 6 == 0 && quad_indices_size == vertices_and_normals_interleaved.size());
|
||||||
|
|
||||||
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
|
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
|
||||||
|
|
||||||
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) {
|
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) {
|
||||||
@ -28,6 +34,130 @@ void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
|
|||||||
for (int j = 0; j < 3; ++ j)
|
for (int j = 0; j < 3; ++ j)
|
||||||
this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z);
|
this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLIndexedVertexArray::finalize_geometry(bool use_VBOs)
|
||||||
|
{
|
||||||
|
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
||||||
|
assert(this->triangle_indices_VBO_id == 0);
|
||||||
|
assert(this->quad_indices_VBO_id == 0);
|
||||||
|
|
||||||
|
this->setup_sizes();
|
||||||
|
|
||||||
|
if (use_VBOs) {
|
||||||
|
if (! empty()) {
|
||||||
|
glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
this->vertices_and_normals_interleaved.clear();
|
||||||
|
}
|
||||||
|
if (! this->triangle_indices.empty()) {
|
||||||
|
glGenBuffers(1, &this->triangle_indices_VBO_id);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW);
|
||||||
|
this->triangle_indices.clear();
|
||||||
|
}
|
||||||
|
if (! this->quad_indices.empty()) {
|
||||||
|
glGenBuffers(1, &this->quad_indices_VBO_id);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW);
|
||||||
|
this->quad_indices.clear();
|
||||||
|
}
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
this->shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLIndexedVertexArray::release_geometry()
|
||||||
|
{
|
||||||
|
if (this->vertices_and_normals_interleaved_VBO_id)
|
||||||
|
glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id);
|
||||||
|
if (this->triangle_indices_VBO_id)
|
||||||
|
glDeleteBuffers(1, &this->triangle_indices_VBO_id);
|
||||||
|
if (this->quad_indices_VBO_id)
|
||||||
|
glDeleteBuffers(1, &this->quad_indices_VBO_id);
|
||||||
|
this->clear();
|
||||||
|
this->shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLIndexedVertexArray::render() const
|
||||||
|
{
|
||||||
|
if (this->indexed()) {
|
||||||
|
if (this->vertices_and_normals_interleaved_VBO_id) {
|
||||||
|
// Render using the Vertex Buffer Objects.
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||||
|
if (this->triangle_indices_size > 0) {
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
|
||||||
|
glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr);
|
||||||
|
}
|
||||||
|
if (this->quad_indices_size > 0) {
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
|
||||||
|
glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr);
|
||||||
|
}
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
} else {
|
||||||
|
// Render in an immediate mode.
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, this->vertices_and_normals_interleaved.data());
|
||||||
|
// Due to issues with the Intel drivers, rather limit the amount of vertices processed per draw command.
|
||||||
|
if (! this->triangle_indices.empty())
|
||||||
|
glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data());
|
||||||
|
if (! this->quad_indices.empty())
|
||||||
|
glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this->vertices_and_normals_interleaved_VBO_id) {
|
||||||
|
// Render using the Vertex Buffer Objects.
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6));
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
} else {
|
||||||
|
// Render in an immediate mode.
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, this->vertices_and_normals_interleaved.data());
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||||
|
if (this->triangle_indices_size > 0) {
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
|
||||||
|
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) {
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
} else {
|
||||||
|
// Render in an immediate mode.
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, this->vertices_and_normals_interleaved.data());
|
||||||
|
if (! this->triangle_indices.empty())
|
||||||
|
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())
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLVolume::set_range(double min_z, double max_z)
|
void GLVolume::set_range(double min_z, double max_z)
|
||||||
@ -65,6 +195,18 @@ void GLVolume::set_range(double min_z, double max_z)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLVolume::render() const
|
||||||
|
{
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated(this->origin.x, this->origin.y, this->origin.z);
|
||||||
|
if (this->indexed_vertex_array.indexed())
|
||||||
|
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
|
||||||
|
else
|
||||||
|
this->indexed_vertex_array.render();
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force)
|
void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force)
|
||||||
{
|
{
|
||||||
GLTexture *tex = this->layer_height_texture.get();
|
GLTexture *tex = this->layer_height_texture.get();
|
||||||
@ -235,7 +377,6 @@ static void thick_lines_to_indexed_vertex_array(
|
|||||||
idx_a[BOTTOM] = idx_prev[BOTTOM];
|
idx_a[BOTTOM] = idx_prev[BOTTOM];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sharp = true;
|
|
||||||
if (ii == 0) {
|
if (ii == 0) {
|
||||||
// Start of the 1st line segment.
|
// Start of the 1st line segment.
|
||||||
idx_a[LEFT ] = idx_last ++;
|
idx_a[LEFT ] = idx_last ++;
|
||||||
@ -490,6 +631,11 @@ static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, fl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _3DScene::_glew_init()
|
||||||
|
{
|
||||||
|
glewInit();
|
||||||
|
}
|
||||||
|
|
||||||
// Create 3D thick extrusion lines for a skirt and brim.
|
// Create 3D thick extrusion lines for a skirt and brim.
|
||||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||||
void _3DScene::_load_print_toolpaths(
|
void _3DScene::_load_print_toolpaths(
|
||||||
@ -539,6 +685,7 @@ void _3DScene::_load_print_toolpaths(
|
|||||||
auto bb = print->bounding_box();
|
auto bb = print->bounding_box();
|
||||||
volume.bounding_box.merge(Pointf3(unscale(bb.min.x), unscale(bb.min.y), 0.f));
|
volume.bounding_box.merge(Pointf3(unscale(bb.min.x), unscale(bb.min.y), 0.f));
|
||||||
volume.bounding_box.merge(Pointf3(unscale(bb.max.x), unscale(bb.max.y), 0.f));
|
volume.bounding_box.merge(Pointf3(unscale(bb.max.x), unscale(bb.max.y), 0.f));
|
||||||
|
volume.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 3D thick extrusion lines for object forming extrusions.
|
// Create 3D thick extrusion lines for object forming extrusions.
|
||||||
@ -559,8 +706,10 @@ void _3DScene::_load_print_object_toolpaths(
|
|||||||
bool has_infill;
|
bool has_infill;
|
||||||
bool has_support;
|
bool has_support;
|
||||||
|
|
||||||
// static const size_t alloc_size_max () { return 32 * 1048576 / 4; }
|
// Number of vertices (each vertex is 6x4=24 bytes long)
|
||||||
static const size_t alloc_size_max () { return 4 * 1048576 / 4; }
|
static const size_t alloc_size_max () { return 131072; } // 3.15MB
|
||||||
|
// static const size_t alloc_size_max () { return 65536; } // 1.57MB
|
||||||
|
// static const size_t alloc_size_max () { return 32768; } // 786kB
|
||||||
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
||||||
|
|
||||||
static const float* color_perimeters () { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
static const float* color_perimeters () { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
||||||
@ -672,6 +821,8 @@ void _3DScene::_load_print_object_toolpaths(
|
|||||||
volume_ptr += v.volumes.size();
|
volume_ptr += v.volumes.size();
|
||||||
v.volumes.clear();
|
v.volumes.clear();
|
||||||
}
|
}
|
||||||
|
for (GLVolume *v : volumes->volumes)
|
||||||
|
v->indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
||||||
}
|
}
|
||||||
|
@ -17,31 +17,49 @@ class ModelObject;
|
|||||||
// possibly indexed by triangles and / or quads.
|
// possibly indexed by triangles and / or quads.
|
||||||
class GLIndexedVertexArray {
|
class GLIndexedVertexArray {
|
||||||
public:
|
public:
|
||||||
GLIndexedVertexArray() {}
|
GLIndexedVertexArray() :
|
||||||
|
vertices_and_normals_interleaved_VBO_id(0),
|
||||||
|
triangle_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),
|
||||||
quad_indices(rhs.quad_indices)
|
quad_indices(rhs.quad_indices),
|
||||||
{}
|
vertices_and_normals_interleaved_VBO_id(0),
|
||||||
|
triangle_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)),
|
||||||
quad_indices(std::move(rhs.quad_indices))
|
quad_indices(std::move(rhs.quad_indices)),
|
||||||
{}
|
vertices_and_normals_interleaved_VBO_id(0),
|
||||||
|
triangle_indices_VBO_id(0),
|
||||||
|
quad_indices_VBO_id(0)
|
||||||
|
{ this->setup_sizes(); }
|
||||||
|
|
||||||
GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs)
|
GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs)
|
||||||
{
|
{
|
||||||
|
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
||||||
|
assert(triangle_indices_VBO_id == 0);
|
||||||
|
assert(triangle_indices_VBO_id == 0);
|
||||||
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
||||||
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->setup_sizes();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLIndexedVertexArray& operator=(GLIndexedVertexArray &&rhs)
|
GLIndexedVertexArray& operator=(GLIndexedVertexArray &&rhs)
|
||||||
{
|
{
|
||||||
|
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
||||||
|
assert(triangle_indices_VBO_id == 0);
|
||||||
|
assert(triangle_indices_VBO_id == 0);
|
||||||
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
||||||
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->setup_sizes();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +68,22 @@ public:
|
|||||||
std::vector<int> triangle_indices;
|
std::vector<int> triangle_indices;
|
||||||
std::vector<int> quad_indices;
|
std::vector<int> quad_indices;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
size_t vertices_and_normals_interleaved_size;
|
||||||
|
size_t triangle_indices_size;
|
||||||
|
size_t quad_indices_size;
|
||||||
|
|
||||||
|
// IDs of the Vertex Array Objects, into which the geometry has been loaded.
|
||||||
|
// Zero if the VBOs are not used.
|
||||||
|
unsigned int vertices_and_normals_interleaved_VBO_id;
|
||||||
|
unsigned int triangle_indices_VBO_id;
|
||||||
|
unsigned int quad_indices_VBO_id;
|
||||||
|
|
||||||
void load_mesh_flat_shading(const TriangleMesh &mesh);
|
void load_mesh_flat_shading(const TriangleMesh &mesh);
|
||||||
|
|
||||||
|
inline bool has_VBOs() const { return vertices_and_normals_interleaved_VBO_id != 0; }
|
||||||
|
|
||||||
inline void reserve(size_t sz) {
|
inline void reserve(size_t sz) {
|
||||||
this->vertices_and_normals_interleaved.reserve(sz * 6);
|
this->vertices_and_normals_interleaved.reserve(sz * 6);
|
||||||
this->triangle_indices.reserve(sz * 3);
|
this->triangle_indices.reserve(sz * 3);
|
||||||
@ -72,23 +104,36 @@ public:
|
|||||||
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finalize the initialization of the geometry & indices,
|
||||||
|
// 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.
|
||||||
|
void finalize_geometry(bool use_VBOs);
|
||||||
|
// Release the geometry data, release OpenGL VBOs.
|
||||||
|
void release_geometry();
|
||||||
|
// Render either using an immediate mode, or the VBOs.
|
||||||
|
void render() 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.empty(); }
|
bool empty() const { return vertices_and_normals_interleaved_size == 0; }
|
||||||
|
|
||||||
// Is this object indexed, or is it just a set of triangles?
|
// Is this object indexed, or is it just a set of triangles?
|
||||||
bool indexed() const { return ! this->empty() && (! this->triangle_indices.empty() || ! this->quad_indices.empty()); }
|
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->setup_sizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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() {
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBoxf3 bounding_box() const {
|
BoundingBoxf3 bounding_box() const {
|
||||||
@ -109,6 +154,13 @@ public:
|
|||||||
}
|
}
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
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 GLTexture
|
class GLTexture
|
||||||
@ -201,23 +253,8 @@ public:
|
|||||||
bool indexed() const { return this->indexed_vertex_array.indexed(); }
|
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;
|
||||||
// Non-indexed interleaved vertices & normals, likely forming triangles.
|
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
||||||
void* triangles_to_render_ptr() { return indexed_vertex_array.vertices_and_normals_interleaved.data(); }
|
|
||||||
size_t triangles_to_render_cnt() { return indexed_vertex_array.vertices_and_normals_interleaved.size() / (3 * 2); }
|
|
||||||
// Indexed triangles & quads, complete set for storing into a vertex buffer.
|
|
||||||
size_t geometry_size() const { return indexed_vertex_array.vertices_and_normals_interleaved.size() * 4; }
|
|
||||||
void* triangle_indices_ptr() { return indexed_vertex_array.triangle_indices.data(); }
|
|
||||||
void* quad_indices_ptr() { return indexed_vertex_array.quad_indices.data(); }
|
|
||||||
size_t indexed_triangles_cnt() { return indexed_vertex_array.triangle_indices.size(); }
|
|
||||||
size_t indexed_quads_cnt() { return indexed_vertex_array.quad_indices.size(); }
|
|
||||||
// Indexed triangles & quads, to be painted in an immediate mode.
|
|
||||||
size_t triangle_indices_to_render_offset() const { return tverts_range.first; }
|
|
||||||
size_t quad_indices_to_render_offset() const { return qverts_range.first; }
|
|
||||||
size_t indexed_triangles_to_render_cnt() const { return std::min(indexed_vertex_array.triangle_indices.size(), tverts_range.second - tverts_range.first); }
|
|
||||||
size_t indexed_quads_to_render_cnt() const { return std::min(indexed_vertex_array.quad_indices.size(), qverts_range.second - qverts_range.first); }
|
|
||||||
|
|
||||||
void render_VBOs() const;
|
|
||||||
|
|
||||||
/************************************************ Layer height texture ****************************************************/
|
/************************************************ Layer height texture ****************************************************/
|
||||||
std::shared_ptr<GLTexture> layer_height_texture;
|
std::shared_ptr<GLTexture> layer_height_texture;
|
||||||
@ -261,10 +298,14 @@ public:
|
|||||||
const std::string &select_by,
|
const std::string &select_by,
|
||||||
const std::string &drag_by);
|
const std::string &drag_by);
|
||||||
|
|
||||||
|
// Release the geometry data assigned to the volumes.
|
||||||
|
// 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(); }
|
||||||
|
// Clear the geometry
|
||||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||||
|
|
||||||
bool empty() const { return volumes.empty(); }
|
bool empty() const { return volumes.empty(); }
|
||||||
void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); }
|
void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); }
|
||||||
void render_VBOs() const { for (GLVolume *vol : this->volumes) vol->render_VBOs(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLVolumeCollection(const GLVolumeCollection &other);
|
GLVolumeCollection(const GLVolumeCollection &other);
|
||||||
@ -274,6 +315,8 @@ private:
|
|||||||
class _3DScene
|
class _3DScene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static void _glew_init();
|
||||||
|
|
||||||
static void _load_print_toolpaths(
|
static void _load_print_toolpaths(
|
||||||
const Print *print,
|
const Print *print,
|
||||||
GLVolumeCollection *volumes,
|
GLVolumeCollection *volumes,
|
||||||
|
@ -38,17 +38,7 @@
|
|||||||
bool empty() const;
|
bool empty() const;
|
||||||
bool indexed() const;
|
bool indexed() const;
|
||||||
|
|
||||||
void* triangles_to_render_ptr();
|
void render() const;
|
||||||
size_t triangles_to_render_cnt();
|
|
||||||
size_t geometry_size() const;
|
|
||||||
void* triangle_indices_ptr();
|
|
||||||
void* quad_indices_ptr();
|
|
||||||
size_t indexed_triangles_cnt();
|
|
||||||
size_t indexed_quads_cnt();
|
|
||||||
size_t triangle_indices_to_render_offset() const;
|
|
||||||
size_t quad_indices_to_render_offset() const;
|
|
||||||
size_t indexed_triangles_to_render_cnt() const;
|
|
||||||
size_t indexed_quads_to_render_cnt() const;
|
|
||||||
|
|
||||||
bool has_layer_height_texture();
|
bool has_layer_height_texture();
|
||||||
int layer_height_texture_width();
|
int layer_height_texture_width();
|
||||||
@ -72,8 +62,10 @@
|
|||||||
|
|
||||||
int count()
|
int count()
|
||||||
%code{% RETVAL = THIS->volumes.size(); %};
|
%code{% RETVAL = THIS->volumes.size(); %};
|
||||||
|
|
||||||
void set_range(double low, double high);
|
void set_range(double low, double high);
|
||||||
|
|
||||||
|
void release_geometry();
|
||||||
%{
|
%{
|
||||||
|
|
||||||
SV*
|
SV*
|
||||||
@ -95,6 +87,12 @@ GLVolumeCollection::arrayref()
|
|||||||
%package{Slic3r::GUI::_3DScene};
|
%package{Slic3r::GUI::_3DScene};
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_glew_init()
|
||||||
|
CODE:
|
||||||
|
_3DScene::_glew_init();
|
||||||
|
|
||||||
void
|
void
|
||||||
_load_print_toolpaths(print, volumes, use_VBOs)
|
_load_print_toolpaths(print, volumes, use_VBOs)
|
||||||
Print *print;
|
Print *print;
|
||||||
|
Loading…
Reference in New Issue
Block a user