diff --git a/src/libslic3r/Color.hpp b/src/libslic3r/Color.hpp index fce0c67e000..183705c4af3 100644 --- a/src/libslic3r/Color.hpp +++ b/src/libslic3r/Color.hpp @@ -48,12 +48,14 @@ class ColorRGB static const ColorRGB BLACK() { return { 0.0f, 0.0f, 0.0f }; } static const ColorRGB BLUE() { return { 0.0f, 0.0f, 1.0f }; } static const ColorRGB BLUEISH() { return { 0.5f, 0.5f, 1.0f }; } + static const ColorRGB CYAN() { return { 0.0f, 1.0f, 1.0f }; } static const ColorRGB DARK_GRAY() { return { 0.25f, 0.25f, 0.25f }; } static const ColorRGB DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f }; } static const ColorRGB GRAY() { return { 0.5f, 0.5f, 0.5f }; } static const ColorRGB GREEN() { return { 0.0f, 1.0f, 0.0f }; } static const ColorRGB GREENISH() { return { 0.5f, 1.0f, 0.5f }; } static const ColorRGB LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f }; } + static const ColorRGB MAGENTA() { return { 1.0f, 0.0f, 1.0f }; } static const ColorRGB ORANGE() { return { 0.92f, 0.50f, 0.26f }; } static const ColorRGB RED() { return { 1.0f, 0.0f, 0.0f }; } static const ColorRGB REDISH() { return { 1.0f, 0.5f, 0.5f }; } @@ -112,12 +114,14 @@ class ColorRGBA static const ColorRGBA BLACK() { return { 0.0f, 0.0f, 0.0f, 1.0f }; } static const ColorRGBA BLUE() { return { 0.0f, 0.0f, 1.0f, 1.0f }; } static const ColorRGBA BLUEISH() { return { 0.5f, 0.5f, 1.0f, 1.0f }; } + static const ColorRGBA CYAN() { return { 0.0f, 1.0f, 1.0f, 1.0f }; } static const ColorRGBA DARK_GRAY() { return { 0.25f, 0.25f, 0.25f, 1.0f }; } static const ColorRGBA DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f, 1.0f }; } static const ColorRGBA GRAY() { return { 0.5f, 0.5f, 0.5f, 1.0f }; } static const ColorRGBA GREEN() { return { 0.0f, 1.0f, 0.0f, 1.0f }; } static const ColorRGBA GREENISH() { return { 0.5f, 1.0f, 0.5f, 1.0f }; } static const ColorRGBA LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f, 1.0f }; } + static const ColorRGBA MAGENTA() { return { 1.0f, 0.0f, 1.0f, 1.0f }; } static const ColorRGBA ORANGE() { return { 0.923f, 0.504f, 0.264f, 1.0f }; } static const ColorRGBA RED() { return { 1.0f, 0.0f, 0.0f, 1.0f }; } static const ColorRGBA REDISH() { return { 1.0f, 0.5f, 0.5f, 1.0f }; } diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 21e23d402ea..c4f1a4407ce 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -101,7 +101,7 @@ const float Bed3D::Axes::DefaultStemLength = 25.0f; const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius; const float Bed3D::Axes::DefaultTipLength = 5.0f; -void Bed3D::Axes::render() const +void Bed3D::Axes::render() { auto render_axis = [this](const Transform3f& transform) { glsafe(::glPushMatrix()); @@ -111,7 +111,7 @@ void Bed3D::Axes::render() const }; if (!m_arrow.is_initialized()) - const_cast(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length)); + m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length)); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) @@ -123,15 +123,27 @@ void Bed3D::Axes::render() const shader->set_uniform("emission_factor", 0.0f); // x axis - const_cast(&m_arrow)->set_color(-1, ColorRGBA::X()); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_arrow.set_color(ColorRGBA::X()); +#else + m_arrow.set_color(-1, ColorRGBA::X()); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast()); // y axis - const_cast(&m_arrow)->set_color(-1, ColorRGBA::Y()); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_arrow.set_color(ColorRGBA::Y()); +#else + m_arrow.set_color(-1, ColorRGBA::Y()); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast()); // z axis - const_cast(&m_arrow)->set_color(-1, ColorRGBA::Z()); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_arrow.set_color(ColorRGBA::Z()); +#else + m_arrow.set_color(-1, ColorRGBA::Z()); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL render_axis(Geometry::assemble_transform(m_origin).cast()); shader->stop_using(); @@ -230,15 +242,18 @@ void Bed3D::render_for_picking(GLCanvas3D& canvas, bool bottom, float scale_fact void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes, bool show_texture, bool picking) { - float* factor = const_cast(&m_scale_factor); - *factor = scale_factor; + m_scale_factor = scale_factor; if (show_axes) render_axes(); glsafe(::glEnable(GL_DEPTH_TEST)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_model.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); +#else m_model.set_color(-1, picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL switch (m_type) { @@ -330,13 +345,13 @@ std::tuple Bed3D::detect_type(const Point return { Type::Custom, {}, {} }; } -void Bed3D::render_axes() const +void Bed3D::render_axes() { if (m_build_volume.valid()) m_axes.render(); } -void Bed3D::render_system(GLCanvas3D& canvas, bool bottom, bool show_texture) const +void Bed3D::render_system(GLCanvas3D& canvas, bool bottom, bool show_texture) { if (!bottom) render_model(); @@ -345,26 +360,23 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom, bool show_texture) co render_texture(bottom, canvas); } -void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const +void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) { - GLTexture* texture = const_cast(&m_texture); - GLTexture* temp_texture = const_cast(&m_temp_texture); - if (m_texture_filename.empty()) { - texture->reset(); + m_texture.reset(); render_default(bottom, false); return; } - if (texture->get_id() == 0 || texture->get_source() != m_texture_filename) { - texture->reset(); + if (m_texture.get_id() == 0 || m_texture.get_source() != m_texture_filename) { + m_texture.reset(); if (boost::algorithm::iends_with(m_texture_filename, ".svg")) { // use higher resolution images if graphic card and opengl version allow GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size(); - if (temp_texture->get_id() == 0 || temp_texture->get_source() != m_texture_filename) { + if (m_temp_texture.get_id() == 0 || m_temp_texture.get_source() != m_texture_filename) { // generate a temporary lower resolution texture to show while no main texture levels have been compressed - if (!temp_texture->load_from_svg_file(m_texture_filename, false, false, false, max_tex_size / 8)) { + if (!m_temp_texture.load_from_svg_file(m_texture_filename, false, false, false, max_tex_size / 8)) { render_default(bottom, false); return; } @@ -372,15 +384,15 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const } // starts generating the main texture, compression will run asynchronously - if (!texture->load_from_svg_file(m_texture_filename, true, true, true, max_tex_size)) { + if (!m_texture.load_from_svg_file(m_texture_filename, true, true, true, max_tex_size)) { render_default(bottom, false); return; } } else if (boost::algorithm::iends_with(m_texture_filename, ".png")) { // generate a temporary lower resolution texture to show while no main texture levels have been compressed - if (temp_texture->get_id() == 0 || temp_texture->get_source() != m_texture_filename) { - if (!temp_texture->load_from_file(m_texture_filename, false, GLTexture::None, false)) { + if (m_temp_texture.get_id() == 0 || m_temp_texture.get_source() != m_texture_filename) { + if (!m_temp_texture.load_from_file(m_texture_filename, false, GLTexture::None, false)) { render_default(bottom, false); return; } @@ -388,7 +400,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const } // starts generating the main texture, compression will run asynchronously - if (!texture->load_from_file(m_texture_filename, true, GLTexture::MultiThreaded, true)) { + if (!m_texture.load_from_file(m_texture_filename, true, GLTexture::MultiThreaded, true)) { render_default(bottom, false); return; } @@ -398,13 +410,13 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const return; } } - else if (texture->unsent_compressed_data_available()) { + else if (m_texture.unsent_compressed_data_available()) { // sends to gpu the already available compressed levels of the main texture - texture->send_compressed_data_to_gpu(); + m_texture.send_compressed_data_to_gpu(); // the temporary texture is not needed anymore, reset it - if (temp_texture->get_id() != 0) - temp_texture->reset(); + if (m_temp_texture.get_id() != 0) + m_temp_texture.reset(); canvas.request_extra_frame(); } @@ -416,11 +428,9 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const shader->set_uniform("transparent_background", bottom); shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg")); - unsigned int* vbo_id = const_cast(&m_vbo_id); - - if (*vbo_id == 0) { - glsafe(::glGenBuffers(1, vbo_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, *vbo_id)); + if (m_vbo_id == 0) { + glsafe(::glGenBuffers(1, &m_vbo_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id)); glsafe(::glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)m_triangles.get_vertices_data_size(), (const GLvoid*)m_triangles.get_vertices_data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } @@ -441,12 +451,12 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const GLint tex_coords_id = shader->get_attrib_location("v_tex_coords"); // show the temporary texture while no compressed data is available - GLuint tex_id = (GLuint)temp_texture->get_id(); + GLuint tex_id = (GLuint)m_temp_texture.get_id(); if (tex_id == 0) - tex_id = (GLuint)texture->get_id(); + tex_id = (GLuint)m_texture.get_id(); glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, *vbo_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id)); if (position_id != -1) { glsafe(::glEnableVertexAttribArray(position_id)); @@ -480,38 +490,40 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const } } -void Bed3D::render_model() const +void Bed3D::render_model() { if (m_model_filename.empty()) return; - GLModel* model = const_cast(&m_model); - - if (model->get_filename() != m_model_filename && model->init_from_file(m_model_filename)) { - model->set_color(-1, DEFAULT_MODEL_COLOR); + if (m_model.get_filename() != m_model_filename && m_model.init_from_file(m_model_filename)) { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_model.set_color(DEFAULT_MODEL_COLOR); +#else + m_model.set_color(-1, DEFAULT_MODEL_COLOR); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL // move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad - *const_cast(&m_model_offset) = to_3d(m_build_volume.bounding_volume2d().center(), -0.03); + m_model_offset = to_3d(m_build_volume.bounding_volume2d().center(), -0.03); // update extended bounding box - const_cast(m_extended_bounding_box) = this->calc_extended_bounding_box(); + m_extended_bounding_box = this->calc_extended_bounding_box(); } - if (!model->get_filename().empty()) { + if (!m_model.get_filename().empty()) { GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); shader->set_uniform("emission_factor", 0.0f); glsafe(::glPushMatrix()); glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z())); - model->render(); + m_model.render(); glsafe(::glPopMatrix()); shader->stop_using(); } } } -void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bool picking) const +void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bool picking) { if (m_texture_filename.empty() && m_model_filename.empty()) { render_default(bottom, picking); @@ -525,13 +537,13 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bo render_texture(bottom, canvas); } -void Bed3D::render_default(bool bottom, bool picking) const +void Bed3D::render_default(bool bottom, bool picking) { - const_cast(&m_texture)->reset(); + m_texture.reset(); - unsigned int triangles_vcount = m_triangles.get_vertices_count(); + const unsigned int triangles_vcount = m_triangles.get_vertices_count(); if (triangles_vcount > 0) { - bool has_model = !m_model.get_filename().empty(); + const bool has_model = !m_model.get_filename().empty(); glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_BLEND)); diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 639dc6c1633..82c6b817be1 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -60,7 +60,7 @@ class Bed3D m_arrow.reset(); } float get_total_length() const { return m_stem_length + DefaultTipLength; } - void render() const; + void render(); }; public: @@ -130,12 +130,12 @@ class Bed3D static std::tuple detect_type(const Pointfs& shape); void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes, bool show_texture, bool picking); - void render_axes() const; - void render_system(GLCanvas3D& canvas, bool bottom, bool show_texture) const; - void render_texture(bool bottom, GLCanvas3D& canvas) const; - void render_model() const; - void render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bool picking) const; - void render_default(bool bottom, bool picking) const; + void render_axes(); + void render_system(GLCanvas3D& canvas, bool bottom, bool show_texture); + void render_texture(bool bottom, GLCanvas3D& canvas); + void render_model(); + void render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bool picking); + void render_default(bool bottom, bool picking); void release_VBOs(); }; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index bd02bf8f26e..4e929d060c4 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -314,13 +314,31 @@ void GLVolume::SinkingContours::update() const TriangleMesh& mesh = model.objects[object_idx]->volumes[m_parent.volume_idx()]->mesh(); m_model.reset(); - GUI::GLModel::InitializationData init_data; + GUI::GLModel::Geometry init_data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3, GUI::GLModel::Geometry::EIndexType::UINT }; + init_data.color = ColorRGBA::WHITE(); + unsigned int vertices_counter = 0; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL MeshSlicingParams slicing_params; slicing_params.trafo = m_parent.world_matrix(); const Polygons polygons = union_(slice_mesh(mesh.its, 0.0f, slicing_params)); - for (const ExPolygon &expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) { - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::GLModel::PrimitiveType::Triangles; + for (const ExPolygon& expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + const std::vector triangulation = triangulate_expolygon_3d(expoly); + init_data.vertices.reserve(init_data.vertices.size() + triangulation.size() * GUI::GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(init_data.indices.size() + triangulation.size() * GUI::GLModel::Geometry::index_stride_bytes(init_data.format)); + for (const Vec3d& v : triangulation) { + init_data.add_vertex((Vec3f)(v.cast() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting + ++vertices_counter; + if (vertices_counter % 3 == 0) + init_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); + } + } + m_model.init_from(std::move(init_data)); +#else + GUI::GLModel::Geometry::Entity entity; + entity.type = GUI::GLModel::EPrimitiveType::Triangles; const std::vector triangulation = triangulate_expolygon_3d(expoly); entity.positions.reserve(entity.positions.size() + triangulation.size()); entity.normals.reserve(entity.normals.size() + triangulation.size()); @@ -337,8 +355,8 @@ void GLVolume::SinkingContours::update() } init_data.entities.emplace_back(entity); } - m_model.init_from(init_data); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } else m_shift = box.center() - m_old_box.center(); @@ -355,7 +373,11 @@ void GLVolume::NonManifoldEdges::render() glsafe(::glLineWidth(2.0f)); glsafe(::glPushMatrix()); glsafe(::glMultMatrixd(m_parent.world_matrix().data())); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_model.set_color(complementary(m_parent.render_color)); +#else m_model.set_color(-1, complementary(m_parent.render_color)); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_model.render(); glsafe(::glPopMatrix()); } @@ -376,9 +398,24 @@ void GLVolume::NonManifoldEdges::update() const TriangleMesh& mesh = model_volume->mesh(); const std::vector> edges = its_get_open_edges(mesh.its); if (!edges.empty()) { - GUI::GLModel::InitializationData init_data; - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::GLModel::PrimitiveType::Lines; + GUI::GLModel::Geometry init_data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Lines, GUI::GLModel::Geometry::EVertexLayout::P3, GUI::GLModel::Geometry::EIndexType::UINT }; + init_data.vertices.reserve(2 * edges.size() * GUI::GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * edges.size() * GUI::GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + unsigned int vertices_count = 0; + for (const std::pair& edge : edges) { + init_data.add_vertex((Vec3f)mesh.its.vertices[edge.first].cast()); + init_data.add_vertex((Vec3f)mesh.its.vertices[edge.second].cast()); + vertices_count += 2; + init_data.add_uint_line(vertices_count - 2, vertices_count - 1); + } + m_model.init_from(std::move(init_data)); +#else + GUI::GLModel::Geometry::Entity entity; + entity.type = GUI::GLModel::EPrimitiveType::Lines; entity.positions.reserve(2 * edges.size()); entity.normals.reserve(2 * edges.size()); @@ -394,6 +431,7 @@ void GLVolume::NonManifoldEdges::update() init_data.entities.emplace_back(entity); m_model.init_from(init_data); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } } } @@ -879,6 +917,11 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab if (shader == nullptr) return; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); + GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat"); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + if (type == ERenderType::Transparent) { glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); @@ -892,13 +935,28 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab volume.first->set_render_color(true); // render sinking contours of non-hovered volumes - if (m_show_sinking_contours) - if (volume.first->is_sinking() && !volume.first->is_below_printbed() && - volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { - shader->stop_using(); - volume.first->render_sinking_contours(); - shader->start_using(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); + if (sink_shader != nullptr) { + sink_shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + if (m_show_sinking_contours) { + if (volume.first->is_sinking() && !volume.first->is_below_printbed() && + volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + volume.first->render_sinking_contours(); +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + shader->start_using(); +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + } } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + sink_shader->stop_using(); + } + shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); @@ -938,25 +996,49 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab } if (m_show_sinking_contours) { - for (GLVolumeWithIdAndZ& volume : to_render) { - // render sinking contours of hovered/displaced volumes - if (volume.first->is_sinking() && !volume.first->is_below_printbed() && - (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { - shader->stop_using(); - glsafe(::glDepthFunc(GL_ALWAYS)); - volume.first->render_sinking_contours(); - glsafe(::glDepthFunc(GL_LESS)); - shader->start_using(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); + if (sink_shader != nullptr) { + sink_shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + for (GLVolumeWithIdAndZ& volume : to_render) { + // render sinking contours of hovered/displaced volumes + if (volume.first->is_sinking() && !volume.first->is_below_printbed() && + (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + glsafe(::glDepthFunc(GL_ALWAYS)); + volume.first->render_sinking_contours(); + glsafe(::glDepthFunc(GL_LESS)); +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + shader->start_using(); +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + } } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + sink_shader->start_using(); } + shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } #if ENABLE_SHOW_NON_MANIFOLD_EDGES - if (m_show_non_manifold_edges && GUI::wxGetApp().app_config->get("non_manifold_edges") == "1") { - for (GLVolumeWithIdAndZ& volume : to_render) { - volume.first->render_non_manifold_edges(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); + if (edges_shader != nullptr) { + edges_shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + if (m_show_non_manifold_edges && GUI::wxGetApp().app_config->get("non_manifold_edges") == "1") { + for (GLVolumeWithIdAndZ& volume : to_render) { + volume.first->render_non_manifold_edges(); + } } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + edges_shader->stop_using(); } + shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL #endif // ENABLE_SHOW_NON_MANIFOLD_EDGES if (disable_cullface) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 28fe65d8143..53d19a6fc77 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -221,7 +221,11 @@ void GCodeViewer::SequentialRangeCap::reset() { void GCodeViewer::SequentialView::Marker::init() { m_model.init_from(stilized_arrow(16, 2.0f, 4.0f, 1.0f, 8.0f)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_model.set_color({ 1.0f, 1.0f, 1.0f, 0.5f }); +#else m_model.set_color(-1, { 1.0f, 1.0f, 1.0f, 0.5f }); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } void GCodeViewer::SequentialView::Marker::set_world_position(const Vec3f& position) @@ -230,7 +234,7 @@ void GCodeViewer::SequentialView::Marker::set_world_position(const Vec3f& positi m_world_transform = (Geometry::assemble_transform((position + m_z_offset * Vec3f::UnitZ()).cast()) * Geometry::assemble_transform(m_model.get_bounding_box().size().z() * Vec3d::UnitZ(), { M_PI, 0.0, 0.0 })).cast(); } -void GCodeViewer::SequentialView::Marker::render() const +void GCodeViewer::SequentialView::Marker::render() { if (!m_visible) return; @@ -260,7 +264,7 @@ void GCodeViewer::SequentialView::Marker::render() const static size_t last_text_length = 0; ImGuiWrapper& imgui = *wxGetApp().imgui(); - Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); + const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); imgui.set_next_window_pos(0.5f * static_cast(cnv_size.get_width()), static_cast(cnv_size.get_height()), ImGuiCond_Always, 0.5f, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::SetNextWindowBgAlpha(0.25f); @@ -273,8 +277,8 @@ void GCodeViewer::SequentialView::Marker::render() const imgui.text(std::string(buf)); // force extra frame to automatically update window size - float width = ImGui::GetWindowWidth(); - size_t length = strlen(buf); + const float width = ImGui::GetWindowWidth(); + const size_t length = strlen(buf); if (width != last_window_width || length != last_text_length) { last_window_width = width; last_text_length = length; @@ -465,7 +469,7 @@ void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file() m_file.close(); } -void GCodeViewer::SequentialView::render(float legend_height) const +void GCodeViewer::SequentialView::render(float legend_height) { marker.render(); float bottom = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_height(); @@ -1426,13 +1430,30 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) }; // format data into the buffers to be rendered as batched model - auto add_vertices_as_model_batch = [](const GCodeProcessorResult::MoveVertex& curr, const GLModel::InitializationData& data, VertexBuffer& vertices, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { + auto add_vertices_as_model_batch = [](const GCodeProcessorResult::MoveVertex& curr, const GLModel::Geometry& data, VertexBuffer& vertices, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { const double width = static_cast(1.5f * curr.width); const double height = static_cast(1.5f * curr.height); const Transform3d trafo = Geometry::assemble_transform((curr.position - 0.5f * curr.height * Vec3f::UnitZ()).cast(), Vec3d::Zero(), { width, width, height }); const Eigen::Matrix normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + // append vertices + const size_t vertices_count = data.vertices_count(); + for (size_t i = 0; i < vertices_count; ++i) { + // append position + const Vec3d position = trafo * data.extract_position_3(i).cast(); + vertices.push_back(float(position.x())); + vertices.push_back(float(position.y())); + vertices.push_back(float(position.z())); + + // append normal + const Vec3d normal = normal_matrix * data.extract_normal_3(i).cast(); + vertices.push_back(float(normal.x())); + vertices.push_back(float(normal.y())); + vertices.push_back(float(normal.z())); + } +#else for (const auto& entity : data.entities) { // append vertices for (size_t i = 0; i < entity.positions.size(); ++i) { @@ -1449,6 +1470,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) vertices.push_back(static_cast(normal.z())); } } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL // append instance position instances.push_back(curr.position.x()); @@ -1458,12 +1480,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) instances_ids.push_back(move_id); }; - auto add_indices_as_model_batch = [](const GLModel::InitializationData& data, IndexBuffer& indices, IBufferType base_index) { + auto add_indices_as_model_batch = [](const GLModel::Geometry& data, IndexBuffer& indices, IBufferType base_index) { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + const size_t indices_count = data.indices_count(); + for (size_t i = 0; i < indices_count; ++i) { + indices.push_back(static_cast(data.extract_ushort_index(i) + base_index)); + } +#else for (const auto& entity : data.entities) { for (size_t i = 0; i < entity.indices.size(); ++i) { indices.push_back(static_cast(entity.indices[i] + base_index)); } } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL }; #if ENABLE_GCODE_VIEWER_STATISTICS @@ -2802,7 +2831,11 @@ void GCodeViewer::render_toolpaths() } if (range.vbo > 0) { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + buffer.model.model.set_color(range.color); +#else buffer.model.model.set_color(-1, range.color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL buffer.model.model.render_instanced(range.vbo, range.count); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_instanced_models_calls_count; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index f7adcc9eb3c..ecebb26414e 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -298,7 +298,7 @@ class GCodeViewer GLModel model; ColorRGBA color; InstanceVBuffer instances; - GLModel::InitializationData data; + GLModel::Geometry data; void reset(); }; @@ -361,7 +361,11 @@ class GCodeViewer } case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } case ERenderPrimitiveType::BatchedModel: { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + return !model.data.vertices.empty() && !model.data.indices.empty() && +#else return model.data.vertices_count() > 0 && model.data.indices_count() && +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } default: { return false; } @@ -632,7 +636,7 @@ class GCodeViewer bool is_visible() const { return m_visible; } void set_visible(bool visible) { m_visible = visible; } - void render() const; + void render(); }; class GCodeWindow @@ -688,7 +692,7 @@ class GCodeViewer GCodeWindow gcode_window; std::vector gcode_ids; - void render(float legend_height) const; + void render(float legend_height); }; enum class EViewType : unsigned char diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f33377880cf..ce889d408b7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -210,11 +210,7 @@ void GLCanvas3D::LayersEditing::set_enabled(bool enabled) float GLCanvas3D::LayersEditing::s_overlay_window_width; -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) -#else -void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { if (!m_enabled) return; @@ -412,11 +408,7 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3 shader->stop_using(); } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) -#else -void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { //FIXME show some kind of legend. @@ -429,53 +421,48 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) const const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x; #if ENABLE_GLBEGIN_GLEND_REMOVAL - bool bar_rect_changed = m_profile.old_bar_rect != bar_rect; + const bool bar_rect_changed = m_profile.old_bar_rect != bar_rect; m_profile.old_bar_rect = bar_rect; // Baseline if (!m_profile.baseline.is_initialized() || bar_rect_changed) { m_profile.old_bar_rect = bar_rect; - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2); - entity.positions.emplace_back(x, bar_rect.get_bottom(), 0.0f); - entity.positions.emplace_back(x, bar_rect.get_top(), 0.0f); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.color = ColorRGBA::BLACK(); + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); - entity.normals.reserve(2); - for (size_t j = 0; j < 2; ++j) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + // vertices + init_data.add_vertex(Vec3f(x, bar_rect.get_bottom(), 0.0f)); + init_data.add_vertex(Vec3f(x, bar_rect.get_top(), 0.0f)); - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); + // indices + init_data.add_ushort_line(0, 1); - init_data.entities.emplace_back(entity); - m_profile.baseline.init_from(init_data); - m_profile.baseline.set_color(-1, ColorRGBA::BLACK()); + m_profile.baseline.init_from(std::move(init_data)); } if (!m_profile.profile.is_initialized() || bar_rect_changed || m_profile.old_layer_height_profile != m_layer_height_profile) { m_profile.old_layer_height_profile = m_layer_height_profile; m_profile.profile.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::LineStrip; - entity.positions.reserve(m_layer_height_profile.size()); - entity.normals.reserve(m_layer_height_profile.size()); - entity.indices.reserve(m_layer_height_profile.size()); - for (unsigned int i = 0; i < unsigned int(m_layer_height_profile.size()); i += 2) { - entity.positions.emplace_back(bar_rect.get_left() + float(m_layer_height_profile[i + 1]) * scale_x, bar_rect.get_bottom() + float(m_layer_height_profile[i]) * scale_y, 0.0f); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.emplace_back(i / 2); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT }; + init_data.color = ColorRGBA::BLUE(); + init_data.vertices.reserve(m_layer_height_profile.size() * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(m_layer_height_profile.size() * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + for (unsigned int i = 0; i < (unsigned int)m_layer_height_profile.size(); i += 2) { + init_data.add_vertex(Vec3f(bar_rect.get_left() + float(m_layer_height_profile[i + 1]) * scale_x, + bar_rect.get_bottom() + float(m_layer_height_profile[i]) * scale_y, + 0.0f)); + init_data.add_uint_index(i / 2); } - init_data.entities.emplace_back(entity); - m_profile.profile.init_from(init_data); - m_profile.profile.set_color(-1, ColorRGBA::BLUE()); + m_profile.profile.init_from(std::move(init_data)); } GLShaderProgram* shader = wxGetApp().get_shader("flat"); @@ -893,16 +880,37 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons if (polygons.empty()) return; +#if !ENABLE_GLBEGIN_GLEND_REMOVAL size_t triangles_count = 0; for (const Polygon& poly : polygons) { triangles_count += poly.points.size() - 2; } const size_t vertices_count = 3 * triangles_count; +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL if (m_render_fill) { - GLModel::InitializationData fill_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; + GLModel::Geometry fill_data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT }; + fill_data.color = { 0.3333f, 0.0f, 0.0f, 0.5f }; + + // vertices + indices + const ExPolygons polygons_union = union_ex(polygons); + unsigned int vertices_counter = 0; + for (const ExPolygon& poly : polygons_union) { + const std::vector triangulation = triangulate_expolygon_3d(poly); + for (const Vec3d& v : triangulation) { + fill_data.add_vertex((Vec3f)(v.cast() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting + ++vertices_counter; + if (vertices_counter % 3 == 0) + fill_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); + } + } + + m_fill.init_from(std::move(fill_data)); +#else + GLModel::Geometry::Entity entity; + entity.type = GLModel::EPrimitiveType::Triangles; entity.color = { 0.3333f, 0.0f, 0.0f, 0.5f }; entity.positions.reserve(vertices_count); entity.normals.reserve(vertices_count); @@ -925,12 +933,16 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons fill_data.entities.emplace_back(entity); m_fill.init_from(fill_data); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } - GLModel::InitializationData perimeter_data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_perimeter.init_from(polygons, 0.025f); // add a small positive z to avoid z-fighting +#else + GLModel::Geometry perimeter_data; for (const Polygon& poly : polygons) { - GLModel::InitializationData::Entity ent; - ent.type = GLModel::PrimitiveType::LineLoop; + GLModel::Geometry::Entity ent; + ent.type = GLModel::EPrimitiveType::LineLoop; ent.positions.reserve(poly.points.size()); ent.indices.reserve(poly.points.size()); unsigned int id_count = 0; @@ -944,6 +956,7 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons } m_perimeter.init_from(perimeter_data); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } void GLCanvas3D::SequentialPrintClearance::render() @@ -951,7 +964,11 @@ void GLCanvas3D::SequentialPrintClearance::render() const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f }; const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader("flat"); +#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL if (shader == nullptr) return; @@ -962,7 +979,11 @@ void GLCanvas3D::SequentialPrintClearance::render() glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_perimeter.set_color(m_render_fill ? FILL_COLOR : NO_FILL_COLOR); +#else m_perimeter.set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_perimeter.render(); m_fill.render(); @@ -1553,13 +1574,13 @@ void GLCanvas3D::render() wxGetApp().imgui()->new_frame(); if (m_picking_enabled) { - if (m_rectangle_selection.is_dragging()) - // picking pass using rectangle selection - _rectangular_selection_picking_pass(); - else if (!m_volumes.empty()) - // regular picking pass - _picking_pass(); - } + if (m_rectangle_selection.is_dragging()) + // picking pass using rectangle selection + _rectangular_selection_picking_pass(); + else if (!m_volumes.empty()) + // regular picking pass + _picking_pass(); + } #if ENABLE_RENDER_PICKING_PASS if (!m_picking_enabled || !m_show_picking_texture) { @@ -5331,11 +5352,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type) // before transparent objects are rendered. Otherwise they would not be // visible when inside modifier meshes etc. { -#if ENABLE_GLBEGIN_GLEND_REMOVAL GLGizmosManager& gm = get_gizmos_manager(); -#else - const GLGizmosManager& gm = get_gizmos_manager(); -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL // GLGizmosManager::EType type = gm.get_current_type(); if (dynamic_cast(gm.get_current())) { shader->stop_using(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index e0304fd00cd..0006b2406b7 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -264,11 +264,7 @@ class GLCanvas3D bool is_enabled() const; void set_enabled(bool enabled); -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_overlay(const GLCanvas3D& canvas); -#else - void render_overlay(const GLCanvas3D& canvas) const; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void render_volumes(const GLCanvas3D& canvas, const GLVolumeCollection& volumes); void adjust_layer_height_profile(); @@ -291,11 +287,7 @@ class GLCanvas3D bool is_initialized() const; void generate_layer_height_texture(); void render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const; -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_profile(const Rect& bar_rect); -#else - void render_profile(const Rect& bar_rect) const; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void update_slicing_parameters(); static float thickness_bar_width(const GLCanvas3D &canvas); diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 257f0f291b3..2da64f662e1 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -17,7 +17,320 @@ namespace Slic3r { namespace GUI { -size_t GLModel::InitializationData::vertices_count() const +#if ENABLE_GLBEGIN_GLEND_REMOVAL +void GLModel::Geometry::add_vertex(const Vec2f& position) +{ + assert(format.vertex_layout == EVertexLayout::P2); + vertices.emplace_back(position.x()); + vertices.emplace_back(position.y()); +} + +void GLModel::Geometry::add_vertex(const Vec3f& position) +{ + assert(format.vertex_layout == EVertexLayout::P3); + vertices.emplace_back(position.x()); + vertices.emplace_back(position.y()); + vertices.emplace_back(position.z()); +} + +void GLModel::Geometry::add_vertex(const Vec3f& position, const Vec3f& normal) +{ + assert(format.vertex_layout == EVertexLayout::P3N3); + vertices.emplace_back(position.x()); + vertices.emplace_back(position.y()); + vertices.emplace_back(position.z()); + vertices.emplace_back(normal.x()); + vertices.emplace_back(normal.y()); + vertices.emplace_back(normal.z()); +} + +void GLModel::Geometry::add_ushort_index(unsigned short id) +{ + if (format.index_type != EIndexType::USHORT) { + assert(false); + return; + } + indices.resize(indices.size() + sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id, sizeof(unsigned short)); +} + +void GLModel::Geometry::add_uint_index(unsigned int id) +{ + if (format.index_type != EIndexType::UINT) { + assert(false); + return; + } + indices.resize(indices.size() + sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id, sizeof(unsigned int)); +} + +void GLModel::Geometry::add_ushort_line(unsigned short id1, unsigned short id2) +{ + if (format.index_type != EIndexType::USHORT) { + assert(false); + return; + } + indices.resize(indices.size() + 2 * sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned short), &id1, sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id2, sizeof(unsigned short)); +} + +void GLModel::Geometry::add_uint_line(unsigned int id1, unsigned int id2) +{ + if (format.index_type != EIndexType::UINT) { + assert(false); + return; + } + indices.resize(indices.size() + 2 * sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned int), &id1, sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id2, sizeof(unsigned int)); +} + +void GLModel::Geometry::add_ushort_triangle(unsigned short id1, unsigned short id2, unsigned short id3) +{ + if (format.index_type != EIndexType::USHORT) { + assert(false); + return; + } + indices.resize(indices.size() + 3 * sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - 3 * sizeof(unsigned short), &id1, sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned short), &id2, sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id3, sizeof(unsigned short)); +} + +void GLModel::Geometry::add_uint_triangle(unsigned int id1, unsigned int id2, unsigned int id3) +{ + if (format.index_type != EIndexType::UINT) { + assert(false); + return; + } + indices.resize(indices.size() + 3 * sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - 3 * sizeof(unsigned int), &id1, sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned int), &id2, sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id3, sizeof(unsigned int)); +} + +Vec2f GLModel::Geometry::extract_position_2(size_t id) const +{ + const size_t p_stride = position_stride_floats(format); + if (p_stride != 2) { + assert(false); + return { FLT_MAX, FLT_MAX }; + } + + if (vertices_count() <= id) { + assert(false); + return { FLT_MAX, FLT_MAX }; + } + + const float* start = &vertices[id * vertex_stride_floats(format) + position_offset_floats(format)]; + return { *(start + 0), *(start + 1) }; +} + +Vec3f GLModel::Geometry::extract_position_3(size_t id) const +{ + const size_t p_stride = position_stride_floats(format); + if (p_stride != 3) { + assert(false); + return { FLT_MAX, FLT_MAX, FLT_MAX }; + } + + if (vertices_count() <= id) { + assert(false); + return { FLT_MAX, FLT_MAX, FLT_MAX }; + } + + const float* start = &vertices[id * vertex_stride_floats(format) + position_offset_floats(format)]; + return { *(start + 0), *(start + 1), *(start + 2) }; +} + +Vec3f GLModel::Geometry::extract_normal_3(size_t id) const +{ + const size_t n_stride = normal_stride_floats(format); + if (n_stride != 3) { + assert(false); + return { FLT_MAX, FLT_MAX, FLT_MAX }; + } + + if (vertices_count() <= id) { + assert(false); + return { FLT_MAX, FLT_MAX, FLT_MAX }; + } + + const float* start = &vertices[id * vertex_stride_floats(format) + normal_offset_floats(format)]; + return { *(start + 0), *(start + 1), *(start + 2) }; +} + +Vec2f GLModel::Geometry::extract_tex_coord_2(size_t id) const +{ + const size_t t_stride = tex_coord_stride_floats(format); + if (t_stride != 2) { + assert(false); + return { FLT_MAX, FLT_MAX }; + } + + if (vertices_count() <= id) { + assert(false); + return { FLT_MAX, FLT_MAX }; + } + + const float* start = &vertices[id * vertex_stride_floats(format) + tex_coord_offset_floats(format)]; + return { *(start + 0), *(start + 1) }; +} + +unsigned int GLModel::Geometry::extract_uint_index(size_t id) const +{ + if (format.index_type != EIndexType::UINT) { + assert(false); + return -1; + } + + if (indices_count() <= id) { + assert(false); + return -1; + } + + unsigned int ret = -1; + ::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned int)); + return ret; +} + +unsigned short GLModel::Geometry::extract_ushort_index(size_t id) const +{ + if (format.index_type != EIndexType::USHORT) { + assert(false); + return -1; + } + + if (indices_count() <= id) { + assert(false); + return -1; + } + + unsigned short ret = -1; + ::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned short)); + return ret; +} + +size_t GLModel::Geometry::vertex_stride_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2: { return 2; } + case EVertexLayout::P2T2: { return 4; } + case EVertexLayout::P3: { return 3; } + case EVertexLayout::P3N3: { return 6; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::position_stride_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2: + case EVertexLayout::P2T2: { return 2; } + case EVertexLayout::P3: + case EVertexLayout::P3N3: { return 3; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::position_offset_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2: + case EVertexLayout::P2T2: + case EVertexLayout::P3: + case EVertexLayout::P3N3: { return 0; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::normal_stride_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P3N3: { return 3; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::normal_offset_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P3N3: { return 3; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::tex_coord_stride_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2T2: { return 2; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::tex_coord_offset_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2T2: { return 2; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::index_stride_bytes(const Format& format) +{ + switch (format.index_type) + { + case EIndexType::UINT: { return sizeof(unsigned int); } + case EIndexType::USHORT: { return sizeof(unsigned short); } + default: { assert(false); return 0; } + }; +} + +bool GLModel::Geometry::has_position(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2: + case EVertexLayout::P2T2: + case EVertexLayout::P3: + case EVertexLayout::P3N3: { return true; } + default: { assert(false); return false; } + }; +} + +bool GLModel::Geometry::has_normal(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2: + case EVertexLayout::P2T2: + case EVertexLayout::P3: { return false; } + case EVertexLayout::P3N3: { return true; } + default: { assert(false); return false; } + }; +} + +bool GLModel::Geometry::has_tex_coord(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P2T2: { return true; } + case EVertexLayout::P2: + case EVertexLayout::P3: + case EVertexLayout::P3N3: { return false; } + default: { assert(false); return false; } + }; +} +#else +size_t GLModel::Geometry::vertices_count() const { size_t ret = 0; for (const Entity& entity : entities) { @@ -26,7 +339,7 @@ size_t GLModel::InitializationData::vertices_count() const return ret; } -size_t GLModel::InitializationData::indices_count() const +size_t GLModel::Geometry::indices_count() const { size_t ret = 0; for (const Entity& entity : entities) { @@ -34,13 +347,40 @@ size_t GLModel::InitializationData::indices_count() const } return ret; } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL -void GLModel::init_from(const InitializationData& data) +#if ENABLE_GLBEGIN_GLEND_REMOVAL +void GLModel::init_from(Geometry&& data) +#else +void GLModel::init_from(const Geometry& data) +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + if (is_initialized()) // call reset() if you want to reuse this model + return; + + if (data.vertices.empty() || data.indices.empty()) { + assert(false); + return; + } + + m_render_data.geometry = std::move(data); + + // update bounding box + for (size_t i = 0; i < vertices_count(); ++i) { + const size_t position_stride = Geometry::position_stride_floats(data.format); + if (position_stride == 3) + m_bounding_box.merge(m_render_data.geometry.extract_position_3(i).cast()); + else if (position_stride == 2) { + const Vec2f position = m_render_data.geometry.extract_position_2(i); + m_bounding_box.merge(Vec3f(position.x(), position.y(), 0.0f).cast()); + } + } +#else if (!m_render_data.empty()) // call reset() if you want to reuse this model return; - for (const InitializationData::Entity& entity : data.entities) { + for (const Geometry::Entity& entity : data.entities) { if (entity.positions.empty() || entity.indices.empty()) continue; @@ -72,15 +412,52 @@ void GLModel::init_from(const InitializationData& data) send_to_gpu(rdata, vertices, indices); m_render_data.emplace_back(rdata); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } +#if ENABLE_GLBEGIN_GLEND_REMOVAL +void GLModel::init_from(const indexed_triangle_set& its) +#else void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bbox) +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + if (is_initialized()) // call reset() if you want to reuse this model + return; + + if (its.vertices.empty() || its.indices.empty()){ + assert(false); + return; + } + + Geometry& data = m_render_data.geometry; + data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, Geometry::EIndexType::UINT }; + data.vertices.reserve(3 * its.indices.size() * Geometry::vertex_stride_floats(data.format)); + data.indices.reserve(3 * its.indices.size() * Geometry::index_stride_bytes(data.format)); + + // vertices + indices + unsigned int vertices_counter = 0; + for (uint32_t i = 0; i < its.indices.size(); ++i) { + stl_triangle_vertex_indices face = its.indices[i]; + stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] }; + stl_vertex n = face_normal_normalized(vertex); + for (size_t j = 0; j < 3; ++j) { + data.add_vertex(vertex[j], n); + } + vertices_counter += 3; + data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); + } + + // update bounding box + for (size_t i = 0; i < vertices_count(); ++i) { + m_bounding_box.merge(m_render_data.geometry.extract_position_3(i).cast()); + } +#else if (!m_render_data.empty()) // call reset() if you want to reuse this model return; RenderData data; - data.type = PrimitiveType::Triangles; + data.type = EPrimitiveType::Triangles; std::vector vertices = std::vector(18 * its.indices.size()); std::vector indices = std::vector(3 * its.indices.size()); @@ -105,19 +482,60 @@ void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bb send_to_gpu(data, vertices, indices); m_render_data.emplace_back(data); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } +#if !ENABLE_GLBEGIN_GLEND_REMOVAL void GLModel::init_from(const indexed_triangle_set& its) { this->init_from(its, bounding_box(its)); } +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL void GLModel::init_from(const Polygons& polygons, float z) { - auto append_polygon = [](const Polygon& polygon, float z, GUI::GLModel::InitializationData& data) { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + if (is_initialized()) // call reset() if you want to reuse this model + return; + + if (polygons.empty()) { + assert(false); + return; + } + + Geometry& data = m_render_data.geometry; + data.format = { Geometry::EPrimitiveType::Lines, Geometry::EVertexLayout::P3, Geometry::EIndexType::UINT }; + + size_t segments_count = 0; + for (const Polygon& polygon : polygons) { + segments_count += polygon.points.size(); + } + + data.vertices.reserve(2 * segments_count * Geometry::vertex_stride_floats(data.format)); + data.indices.reserve(2 * segments_count * Geometry::index_stride_bytes(data.format)); + + // vertices + indices + unsigned int vertices_counter = 0; + for (const Polygon& poly : polygons) { + for (size_t i = 0; i < poly.points.size(); ++i) { + const Point& p0 = poly.points[i]; + const Point& p1 = (i == poly.points.size() - 1) ? poly.points.front() : poly.points[i + 1]; + data.add_vertex(Vec3f(unscale(p0.x()), unscale(p0.y()), z)); + data.add_vertex(Vec3f(unscale(p1.x()), unscale(p1.y()), z)); + vertices_counter += 2; + data.add_uint_line(vertices_counter - 2, vertices_counter - 1); + } + } + + // update bounding box + for (size_t i = 0; i < vertices_count(); ++i) { + m_bounding_box.merge(m_render_data.geometry.extract_position_3(i).cast()); + } +#else + auto append_polygon = [](const Polygon& polygon, float z, GUI::GLModel::Geometry& data) { if (!polygon.empty()) { - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::GLModel::PrimitiveType::LineLoop; + GUI::GLModel::Geometry::Entity entity; + entity.type = GUI::GLModel::EPrimitiveType::LineLoop; // contour entity.positions.reserve(polygon.size() + 1); entity.indices.reserve(polygon.size() + 1); @@ -132,11 +550,12 @@ void GLModel::init_from(const Polygons& polygons, float z) } }; - InitializationData init_data; + Geometry init_data; for (const Polygon& polygon : polygons) { append_polygon(polygon, z, init_data); } init_from(init_data); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } bool GLModel::init_from_file(const std::string& filename) @@ -148,23 +567,26 @@ bool GLModel::init_from_file(const std::string& filename) return false; Model model; - try - { + try { model = Model::read_from_file(filename); } - catch (std::exception&) - { + catch (std::exception&) { return false; } - TriangleMesh mesh = model.mesh(); + const TriangleMesh mesh = model.mesh(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + init_from(mesh.its); +#else init_from(mesh.its, mesh.bounding_box()); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_filename = filename; return true; } +#if !ENABLE_GLBEGIN_GLEND_REMOVAL void GLModel::set_color(int entity_id, const ColorRGBA& color) { for (size_t i = 0; i < m_render_data.size(); ++i) { @@ -178,9 +600,26 @@ ColorRGBA GLModel::get_color(size_t entity_id) const if (entity_id < 0 || entity_id >= m_render_data.size()) return ColorRGBA{}; return m_render_data[entity_id].color; } +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL void GLModel::reset() { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + // release gpu memory + if (m_render_data.ibo_id > 0) { + glsafe(::glDeleteBuffers(1, &m_render_data.ibo_id)); + m_render_data.ibo_id = 0; + } + if (m_render_data.vbo_id > 0) { + glsafe(::glDeleteBuffers(1, &m_render_data.vbo_id)); + m_render_data.vbo_id = 0; + } + + m_render_data.vertices_count = 0; + m_render_data.indices_count = 0; + m_render_data.geometry.vertices = std::vector(); + m_render_data.geometry.indices = std::vector(); +#else for (RenderData& data : m_render_data) { // release gpu memory if (data.ibo_id > 0) @@ -190,14 +629,94 @@ void GLModel::reset() } m_render_data.clear(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_bounding_box = BoundingBoxf3(); m_filename = std::string(); } +#if ENABLE_GLBEGIN_GLEND_REMOVAL +static GLenum get_primitive_mode(const GLModel::Geometry::Format& format) +{ + switch (format.type) + { + case GLModel::Geometry::EPrimitiveType::Points: { return GL_POINTS; } + default: + case GLModel::Geometry::EPrimitiveType::Triangles: { return GL_TRIANGLES; } + case GLModel::Geometry::EPrimitiveType::TriangleStrip: { return GL_TRIANGLE_STRIP; } + case GLModel::Geometry::EPrimitiveType::TriangleFan: { return GL_TRIANGLE_FAN; } + case GLModel::Geometry::EPrimitiveType::Lines: { return GL_LINES; } + case GLModel::Geometry::EPrimitiveType::LineStrip: { return GL_LINE_STRIP; } + case GLModel::Geometry::EPrimitiveType::LineLoop: { return GL_LINE_LOOP; } + } +} + +static GLenum get_index_type(const GLModel::Geometry::Format& format) +{ + switch (format.index_type) + { + default: + case GLModel::Geometry::EIndexType::UINT: { return GL_UNSIGNED_INT; } + case GLModel::Geometry::EIndexType::USHORT: { return GL_UNSIGNED_SHORT; } + } +} + +void GLModel::render() +#else void GLModel::render() const +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { GLShaderProgram* shader = wxGetApp().get_current_shader(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + if (shader == nullptr) + return; + + // sends data to gpu if not done yet + if (m_render_data.vbo_id == 0 || m_render_data.ibo_id == 0) { + if (m_render_data.geometry.vertices_count() > 0 && m_render_data.geometry.indices_count() > 0 && !send_to_gpu()) + return; + } + + const Geometry& data = m_render_data.geometry; + + GLenum mode = get_primitive_mode(data.format); + GLenum index_type = get_index_type(data.format); + + const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format); + const bool position = Geometry::has_position(data.format); + const bool normal = Geometry::has_normal(data.format); + const bool tex_coord = Geometry::has_tex_coord(data.format); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); + + if (position) { + glsafe(::glVertexPointer(Geometry::position_stride_floats(data.format), GL_FLOAT, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format))); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + } + if (normal) { + glsafe(::glNormalPointer(GL_FLOAT, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format))); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + } + if (tex_coord) { + glsafe(::glTexCoordPointer(Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, vertex_stride_bytes, (const void*)Geometry::tex_coord_offset_bytes(data.format))); + glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + } + + shader->set_uniform("uniform_color", data.color); + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); + glsafe(::glDrawElements(mode, indices_count(), index_type, nullptr)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (tex_coord) + glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY)); + if (normal) + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (position) + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); +#else for (const RenderData& data : m_render_data) { if (data.vbo_id == 0 || data.ibo_id == 0) continue; @@ -206,10 +725,10 @@ void GLModel::render() const switch (data.type) { default: - case PrimitiveType::Triangles: { mode = GL_TRIANGLES; break; } - case PrimitiveType::Lines: { mode = GL_LINES; break; } - case PrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; } - case PrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; } + case EPrimitiveType::Triangles: { mode = GL_TRIANGLES; break; } + case EPrimitiveType::Lines: { mode = GL_LINES; break; } + case EPrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; } + case EPrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; } } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); @@ -233,14 +752,40 @@ void GLModel::render() const glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } +#if ENABLE_GLBEGIN_GLEND_REMOVAL +void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) +#else void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { if (instances_vbo == 0) return; GLShaderProgram* shader = wxGetApp().get_current_shader(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced")) + return; + + // vertex attributes + GLint position_id = shader->get_attrib_location("v_position"); + GLint normal_id = shader->get_attrib_location("v_normal"); + if (position_id == -1 || normal_id == -1) + return; + + // instance attributes + GLint offset_id = shader->get_attrib_location("i_offset"); + GLint scales_id = shader->get_attrib_location("i_scales"); + if (offset_id == -1 || scales_id == -1) + return; + + if (m_render_data.vbo_id == 0 || m_render_data.ibo_id == 0) { + if (!send_to_gpu()) + return; + } +#else assert(shader == nullptr || boost::algorithm::iends_with(shader->get_name(), "_instanced")); // vertex attributes @@ -252,8 +797,18 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance GLint offset_id = (shader != nullptr) ? shader->get_attrib_location("i_offset") : -1; GLint scales_id = (shader != nullptr) ? shader->get_attrib_location("i_scales") : -1; assert(offset_id != -1 && scales_id != -1); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instances_vbo)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0)); + glsafe(::glEnableVertexAttribArray(offset_id)); + glsafe(::glVertexAttribDivisor(offset_id, 1)); + + glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(scales_id)); + glsafe(::glVertexAttribDivisor(scales_id, 1)); +#else if (offset_id != -1) { glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0)); glsafe(::glEnableVertexAttribArray(offset_id)); @@ -264,7 +819,44 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glEnableVertexAttribArray(scales_id)); glsafe(::glVertexAttribDivisor(scales_id, 1)); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_GLBEGIN_GLEND_REMOVAL + const Geometry& data = m_render_data.geometry; + + GLenum mode = get_primitive_mode(data.format); + GLenum index_type = get_index_type(data.format); + + shader->set_uniform("uniform_color", data.color); + + const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format); + const bool position = Geometry::has_position(data.format); + const bool normal = Geometry::has_normal(data.format); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); + + if (position) { + glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format))); + glsafe(::glEnableVertexAttribArray(position_id)); + } + + if (normal) { + glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format))); + glsafe(::glEnableVertexAttribArray(normal_id)); + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); + glsafe(::glDrawElementsInstanced(mode, indices_count(), index_type, (const void*)0, instances_count)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (normal) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position) + glsafe(::glDisableVertexAttribArray(position_id)); + + glsafe(::glDisableVertexAttribArray(scales_id)); + glsafe(::glDisableVertexAttribArray(offset_id)); +#else for (const RenderData& data : m_render_data) { if (data.vbo_id == 0 || data.ibo_id == 0) continue; @@ -273,10 +865,10 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance switch (data.type) { default: - case PrimitiveType::Triangles: { mode = GL_TRIANGLES; break; } - case PrimitiveType::Lines: { mode = GL_LINES; break; } - case PrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; } - case PrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; } + case EPrimitiveType::Triangles: { mode = GL_TRIANGLES; break; } + case EPrimitiveType::Lines: { mode = GL_LINES; break; } + case EPrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; } + case EPrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; } } if (shader != nullptr) @@ -308,10 +900,44 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glDisableVertexAttribArray(scales_id)); if (offset_id != -1) glsafe(::glDisableVertexAttribArray(offset_id)); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } +#if ENABLE_GLBEGIN_GLEND_REMOVAL +bool GLModel::send_to_gpu() +{ + if (m_render_data.vbo_id > 0 || m_render_data.ibo_id > 0) { + assert(false); + return false; + } + + Geometry& data = m_render_data.geometry; + if (data.vertices.empty() || data.indices.empty()) { + assert(false); + return false; + } + + // vertices + glsafe(::glGenBuffers(1, &m_render_data.vbo_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, data.vertices_size_bytes(), data.vertices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + m_render_data.vertices_count = vertices_count(); + data.vertices = std::vector(); + + // indices + glsafe(::glGenBuffers(1, &m_render_data.ibo_id)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); + glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + m_render_data.indices_count = indices_count(); + data.indices = std::vector(); + + return true; +} +#else void GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices) { assert(data.vbo_id == 0); @@ -329,31 +955,57 @@ void GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + +#if ENABLE_GLBEGIN_GLEND_REMOVAL +static void append_vertex(GLModel::Geometry& data, const Vec3f& position, const Vec3f& normal) +{ + data.add_vertex(position, normal); +} -GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height) +static void append_triangle(GLModel::Geometry& data, unsigned short v1, unsigned short v2, unsigned short v3) { - auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) { + data.add_ushort_index(v1); + data.add_ushort_index(v2); + data.add_ushort_index(v3); +} +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + +GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height) +{ +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + auto append_vertex = [](GLModel::Geometry::Entity& entity, const Vec3f& position, const Vec3f& normal) { entity.positions.emplace_back(position); entity.normals.emplace_back(normal); }; - auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) { + auto append_indices = [](GLModel::Geometry::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) { entity.indices.emplace_back(v1); entity.indices.emplace_back(v2); entity.indices.emplace_back(v3); }; - - resolution = std::max(4, resolution); - - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - - const float angle_step = 2.0f * M_PI / static_cast(resolution); +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + + resolution = std::max(4, resolution); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + resolution = std::min(10922, resolution); // ensure no unsigned short overflow of indices +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + + GLModel::Geometry data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; + data.vertices.reserve((6 * resolution + 2) * GLModel::Geometry::vertex_stride_floats(data.format)); + data.indices.reserve((6 * resolution * 3) * GLModel::Geometry::index_stride_bytes(data.format)); +#else + GLModel::Geometry::Entity entity; + entity.type = GLModel::EPrimitiveType::Triangles; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + + const float angle_step = 2.0f * float(PI) / float(resolution); std::vector cosines(resolution); std::vector sines(resolution); - for (int i = 0; i < resolution; ++i) { - const float angle = angle_step * static_cast(i); + for (unsigned short i = 0; i < resolution; ++i) { + const float angle = angle_step * float(i); cosines[i] = ::cos(angle); sines[i] = -::sin(angle); } @@ -361,6 +1013,66 @@ GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, flo const float total_height = tip_height + stem_height; // tip vertices/normals +#if ENABLE_GLBEGIN_GLEND_REMOVAL + append_vertex(data, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ()); + for (unsigned short i = 0; i < resolution; ++i) { + append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f }); + } + + // tip triangles + for (unsigned short i = 0; i < resolution; ++i) { + const unsigned short v3 = (i < resolution - 1) ? i + 2 : 1; + append_triangle(data, 0, i + 1, v3); + } + + // tip cap outer perimeter vertices + for (unsigned short i = 0; i < resolution; ++i) { + append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ()); + } + + // tip cap inner perimeter vertices + for (unsigned short i = 0; i < resolution; ++i) { + append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ()); + } + + // tip cap triangles + for (unsigned short i = 0; i < resolution; ++i) { + const unsigned short v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1; + const unsigned short v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1; + append_triangle(data, i + resolution + 1, v3, v2); + append_triangle(data, i + resolution + 1, i + 2 * resolution + 1, v3); + } + + // stem bottom vertices + for (unsigned short i = 0; i < resolution; ++i) { + append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f }); + } + + // stem top vertices + for (unsigned short i = 0; i < resolution; ++i) { + append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f }); + } + + // stem triangles + for (unsigned short i = 0; i < resolution; ++i) { + const unsigned short v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1; + const unsigned short v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1; + append_triangle(data, i + 3 * resolution + 1, v3, v2); + append_triangle(data, i + 3 * resolution + 1, i + 4 * resolution + 1, v3); + } + + // stem cap vertices + append_vertex(data, Vec3f::Zero(), -Vec3f::UnitZ()); + for (unsigned short i = 0; i < resolution; ++i) { + append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ()); + } + + // stem cap triangles + for (unsigned short i = 0; i < resolution; ++i) { + const unsigned short v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2; + append_triangle(data, 5 * resolution + 1, v3, i + 5 * resolution + 2); + } +#else append_vertex(entity, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ()); for (int i = 0; i < resolution; ++i) { append_vertex(entity, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f }); @@ -421,26 +1133,38 @@ GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, flo } data.entities.emplace_back(entity); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL return data; } -GLModel::InitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness) +GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness) { - auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) { +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + auto append_vertex = [](GLModel::Geometry::Entity& entity, const Vec3f& position, const Vec3f& normal) { entity.positions.emplace_back(position); entity.normals.emplace_back(normal); }; - auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) { + auto append_indices = [](GLModel::Geometry::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) { entity.indices.emplace_back(v1); entity.indices.emplace_back(v2); entity.indices.emplace_back(v3); }; - - resolution = std::max(2, resolution); - - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + + resolution = std::max(2, resolution); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + resolution = std::min(8188, resolution); // ensure no unsigned short overflow of indices +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + + GLModel::Geometry data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; + data.vertices.reserve((8 * (resolution + 1) + 30) * GLModel::Geometry::vertex_stride_floats(data.format)); + data.indices.reserve(((8 * resolution + 16) * 3) * GLModel::Geometry::index_stride_bytes(data.format)); +#else + GLModel::Geometry::Entity entity; + entity.type = GLModel::EPrimitiveType::Triangles; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL const float half_thickness = 0.5f * thickness; const float half_stem_width = 0.5f * stem_width; @@ -448,8 +1172,153 @@ GLModel::InitializationData circular_arrow(int resolution, float radius, float t const float outer_radius = radius + half_stem_width; const float inner_radius = radius - half_stem_width; - const float step_angle = 0.5f * PI / static_cast(resolution); + const float step_angle = 0.5f * float(PI) / float(resolution); + +#if ENABLE_GLBEGIN_GLEND_REMOVAL + // tip + // top face vertices + append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { -tip_height, radius, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitZ()); + + // top face triangles + append_triangle(data, 0, 1, 2); + append_triangle(data, 0, 2, 4); + append_triangle(data, 4, 2, 3); + + // bottom face vertices + append_vertex(data, { 0.0f, outer_radius, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { -tip_height, radius, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { 0.0f, inner_radius, -half_thickness }, -Vec3f::UnitZ()); + + // bottom face triangles + append_triangle(data, 5, 7, 6); + append_triangle(data, 5, 9, 7); + append_triangle(data, 9, 8, 7); + + // side faces vertices + append_vertex(data, { 0.0f, outer_radius, -half_thickness }, Vec3f::UnitX()); + append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, Vec3f::UnitX()); + append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitX()); + append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitX()); + + Vec3f normal(-half_tip_width, tip_height, 0.0f); + normal.normalize(); + append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, normal); + append_vertex(data, { -tip_height, radius, -half_thickness }, normal); + append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, normal); + append_vertex(data, { -tip_height, radius, half_thickness }, normal); + + normal = { -half_tip_width, -tip_height, 0.0f }; + normal.normalize(); + append_vertex(data, { -tip_height, radius, -half_thickness }, normal); + append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, normal); + append_vertex(data, { -tip_height, radius, half_thickness }, normal); + append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, normal); + + append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, Vec3f::UnitX()); + append_vertex(data, { 0.0f, inner_radius, -half_thickness }, Vec3f::UnitX()); + append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitX()); + append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX()); + + // side face triangles + for (unsigned short i = 0; i < 4; ++i) { + const unsigned short ii = i * 4; + append_triangle(data, 10 + ii, 11 + ii, 13 + ii); + append_triangle(data, 10 + ii, 13 + ii, 12 + ii); + } + + // stem + // top face vertices + for (unsigned short i = 0; i <= resolution; ++i) { + const float angle = float(i) * step_angle; + append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ()); + } + + for (unsigned short i = 0; i <= resolution; ++i) { + const float angle = float(i) * step_angle; + append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ()); + } + + // top face triangles + for (unsigned short i = 0; i < resolution; ++i) { + append_triangle(data, 26 + i, 27 + i, 27 + resolution + i); + append_triangle(data, 27 + i, 28 + resolution + i, 27 + resolution + i); + } + + // bottom face vertices + for (unsigned short i = 0; i <= resolution; ++i) { + const float angle = float(i) * step_angle; + append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ()); + } + + for (unsigned short i = 0; i <= resolution; ++i) { + const float angle = float(i) * step_angle; + append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ()); + } + + // bottom face triangles + for (unsigned short i = 0; i < resolution; ++i) { + append_triangle(data, 28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i); + append_triangle(data, 29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i); + } + + // side faces vertices and triangles + for (unsigned short i = 0; i <= resolution; ++i) { + const float angle = float(i) * step_angle; + const float c = ::cos(angle); + const float s = ::sin(angle); + append_vertex(data, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f }); + } + + for (unsigned short i = 0; i <= resolution; ++i) { + const float angle = float(i) * step_angle; + const float c = ::cos(angle); + const float s = ::sin(angle); + append_vertex(data, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f }); + } + + unsigned short first_id = 26 + 4 * (resolution + 1); + for (unsigned short i = 0; i < resolution; ++i) { + const unsigned short ii = first_id + i; + append_triangle(data, ii, ii + 1, ii + resolution + 2); + append_triangle(data, ii, ii + resolution + 2, ii + resolution + 1); + } + + append_vertex(data, { inner_radius, 0.0f, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { outer_radius, 0.0f, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { inner_radius, 0.0f, half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { outer_radius, 0.0f, half_thickness }, -Vec3f::UnitY()); + + first_id = 26 + 6 * (resolution + 1); + append_triangle(data, first_id, first_id + 1, first_id + 3); + append_triangle(data, first_id, first_id + 3, first_id + 2); + + for (short i = resolution; i >= 0; --i) { + const float angle = float(i) * step_angle; + const float c = ::cos(angle); + const float s = ::sin(angle); + append_vertex(data, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f }); + } + for (short i = resolution; i >= 0; --i) { + const float angle = float(i) * step_angle; + const float c = ::cos(angle); + const float s = ::sin(angle); + append_vertex(data, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f }); + } + + first_id = 30 + 6 * (resolution + 1); + for (unsigned short i = 0; i < resolution; ++i) { + const unsigned short ii = first_id + i; + append_triangle(data, ii, ii + 1, ii + resolution + 2); + append_triangle(data, ii, ii + resolution + 2, ii + resolution + 1); + } +#else // tip // top face vertices append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ()); @@ -595,30 +1464,119 @@ GLModel::InitializationData circular_arrow(int resolution, float radius, float t } data.entities.emplace_back(entity); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL return data; } -GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness) +GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness) { - auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) { +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + auto append_vertex = [](GLModel::Geometry::Entity& entity, const Vec3f& position, const Vec3f& normal) { entity.positions.emplace_back(position); entity.normals.emplace_back(normal); }; - auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) { + auto append_indices = [](GLModel::Geometry::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) { entity.indices.emplace_back(v1); entity.indices.emplace_back(v2); entity.indices.emplace_back(v3); }; - - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL + + GLModel::Geometry data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; + data.vertices.reserve(42 * GLModel::Geometry::vertex_stride_floats(data.format)); + data.indices.reserve((24 * 3) * GLModel::Geometry::index_stride_bytes(data.format)); +#else + GLModel::Geometry::Entity entity; + entity.type = GLModel::EPrimitiveType::Triangles; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL const float half_thickness = 0.5f * thickness; const float half_stem_width = 0.5f * stem_width; const float half_tip_width = 0.5f * tip_width; const float total_height = tip_height + stem_height; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + // top face vertices + append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { 0.0, total_height, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { -half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { -half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ()); + append_vertex(data, { -half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ()); + + // top face triangles + append_triangle(data, 0, 1, 6); + append_triangle(data, 6, 1, 5); + append_triangle(data, 4, 5, 3); + append_triangle(data, 5, 1, 3); + append_triangle(data, 1, 2, 3); + + // bottom face vertices + append_vertex(data, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { 0.0, total_height, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); + append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ()); + + // bottom face triangles + append_triangle(data, 7, 13, 8); + append_triangle(data, 13, 12, 8); + append_triangle(data, 12, 11, 10); + append_triangle(data, 8, 12, 10); + append_triangle(data, 9, 8, 10); + + // side faces vertices + append_vertex(data, { half_stem_width, 0.0, -half_thickness }, Vec3f::UnitX()); + append_vertex(data, { half_stem_width, stem_height, -half_thickness }, Vec3f::UnitX()); + append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitX()); + append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitX()); + + append_vertex(data, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY()); + + Vec3f normal(tip_height, half_tip_width, 0.0f); + normal.normalize(); + append_vertex(data, { half_tip_width, stem_height, -half_thickness }, normal); + append_vertex(data, { 0.0, total_height, -half_thickness }, normal); + append_vertex(data, { half_tip_width, stem_height, half_thickness }, normal); + append_vertex(data, { 0.0, total_height, half_thickness }, normal); + + normal = { -tip_height, half_tip_width, 0.0f }; + normal.normalize(); + append_vertex(data, { 0.0, total_height, -half_thickness }, normal); + append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, normal); + append_vertex(data, { 0.0, total_height, half_thickness }, normal); + append_vertex(data, { -half_tip_width, stem_height, half_thickness }, normal); + + append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { -half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY()); + + append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitX()); + append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitX()); + append_vertex(data, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitX()); + append_vertex(data, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitX()); + + append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY()); + append_vertex(data, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY()); + + // side face triangles + for (unsigned short i = 0; i < 7; ++i) { + const unsigned short ii = i * 4; + append_triangle(data, 14 + ii, 15 + ii, 17 + ii); + append_triangle(data, 14 + ii, 17 + ii, 16 + ii); + } +#else // top face vertices append_vertex(entity, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ()); append_vertex(entity, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ()); @@ -699,19 +1657,54 @@ GLModel::InitializationData straight_arrow(float tip_width, float tip_height, fl } data.entities.emplace_back(entity); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL return data; } -GLModel::InitializationData diamond(int resolution) +GLModel::Geometry diamond(unsigned short resolution) { - resolution = std::max(4, resolution); - - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; + resolution = std::max(4, resolution); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + resolution = std::min(65534, resolution); // ensure no unsigned short overflow of indices +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + + GLModel::Geometry data; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; + data.vertices.reserve((resolution + 2) * GLModel::Geometry::vertex_stride_floats(data.format)); + data.indices.reserve(((2 * (resolution + 1)) * 3) * GLModel::Geometry::index_stride_bytes(data.format)); +#else + GLModel::Geometry::Entity entity; + entity.type = GLModel::EPrimitiveType::Triangles; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL const float step = 2.0f * float(PI) / float(resolution); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + // vertices + for (unsigned short i = 0; i < resolution; ++i) { + float ii = float(i) * step; + const Vec3f p = { 0.5f * ::cos(ii), 0.5f * ::sin(ii), 0.0f }; + append_vertex(data, p, p.normalized()); + } + Vec3f p = { 0.0f, 0.0f, 0.5f }; + append_vertex(data, p, p.normalized()); + p = { 0.0f, 0.0f, -0.5f }; + append_vertex(data, p, p.normalized()); + + // triangles + // top + for (unsigned short i = 0; i < resolution; ++i) { + append_triangle(data, i + 0, i + 1, resolution); + } + append_triangle(data, resolution - 1, 0, resolution); + + // bottom + for (unsigned short i = 0; i < resolution; ++i) { + append_triangle(data, i + 0, resolution + 1, i + 1); + } + append_triangle(data, resolution - 1, resolution + 1, 0); +#else // positions for (int i = 0; i < resolution; ++i) { float ii = float(i) * step; @@ -747,6 +1740,7 @@ GLModel::InitializationData diamond(int resolution) entity.indices.push_back(0); data.entities.emplace_back(entity); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL return data; } diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 14269637ea5..e81231aea52 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -20,7 +20,8 @@ namespace GUI { class GLModel { public: - enum class PrimitiveType : unsigned char +#if !ENABLE_GLBEGIN_GLEND_REMOVAL + enum class EPrimitiveType : unsigned char { Triangles, Lines, @@ -30,18 +31,109 @@ namespace GUI { struct RenderData { - PrimitiveType type; + EPrimitiveType type; unsigned int vbo_id{ 0 }; unsigned int ibo_id{ 0 }; size_t indices_count{ 0 }; ColorRGBA color; }; +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL - struct InitializationData + struct Geometry { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + enum class EPrimitiveType : unsigned char + { + Points, + Triangles, + TriangleStrip, + TriangleFan, + Lines, + LineStrip, + LineLoop + }; + + enum class EVertexLayout : unsigned char + { + P2, // position 2 floats + P2T2, // position 2 floats + texture coords 2 floats + P3, // position 3 floats + P3N3, // position 3 floats + normal 3 floats + }; + + enum class EIndexType : unsigned char + { + UINT, // unsigned int + USHORT // unsigned short + }; + + struct Format + { + EPrimitiveType type{ EPrimitiveType::Triangles }; + EVertexLayout vertex_layout{ EVertexLayout::P3N3 }; + EIndexType index_type{ EIndexType::UINT }; + }; + + Format format; + std::vector vertices; + std::vector indices; + ColorRGBA color{ ColorRGBA::BLACK() }; + + void add_vertex(const Vec2f& position); + void add_vertex(const Vec3f& position); + void add_vertex(const Vec3f& position, const Vec3f& normal); + + void add_ushort_index(unsigned short id); + void add_uint_index(unsigned int id); + + void add_ushort_line(unsigned short id1, unsigned short id2); + void add_uint_line(unsigned int id1, unsigned int id2); + + void add_ushort_triangle(unsigned short id1, unsigned short id2, unsigned short id3); + void add_uint_triangle(unsigned int id1, unsigned int id2, unsigned int id3); + + Vec2f extract_position_2(size_t id) const; + Vec3f extract_position_3(size_t id) const; + Vec3f extract_normal_3(size_t id) const; + Vec2f extract_tex_coord_2(size_t id) const; + + unsigned int extract_uint_index(size_t id) const; + unsigned short extract_ushort_index(size_t id) const; + + size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); } + size_t indices_count() const { return indices.size() / index_stride_bytes(format); } + + size_t vertices_size_floats() const { return vertices.size(); } + size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } + size_t indices_size_bytes() const { return indices.size(); } + + static size_t vertex_stride_floats(const Format& format); + static size_t vertex_stride_bytes(const Format& format) { return vertex_stride_floats(format) * sizeof(float); } + + static size_t position_stride_floats(const Format& format); + static size_t position_stride_bytes(const Format& format) { return position_stride_floats(format) * sizeof(float); } + static size_t position_offset_floats(const Format& format); + static size_t position_offset_bytes(const Format& format) { return position_offset_floats(format) * sizeof(float); } + + static size_t normal_stride_floats(const Format& format); + static size_t normal_stride_bytes(const Format& format) { return normal_stride_floats(format) * sizeof(float); } + static size_t normal_offset_floats(const Format& format); + static size_t normal_offset_bytes(const Format& format) { return normal_offset_floats(format) * sizeof(float); } + + static size_t tex_coord_stride_floats(const Format& format); + static size_t tex_coord_stride_bytes(const Format& format) { return tex_coord_stride_floats(format) * sizeof(float); } + static size_t tex_coord_offset_floats(const Format& format); + static size_t tex_coord_offset_bytes(const Format& format) { return tex_coord_offset_floats(format) * sizeof(float); } + + static size_t index_stride_bytes(const Format& format); + + static bool has_position(const Format& format); + static bool has_normal(const Format& format); + static bool has_tex_coord(const Format& format); +#else struct Entity { - PrimitiveType type; + EPrimitiveType type; std::vector positions; std::vector normals; std::vector indices; @@ -56,10 +148,26 @@ namespace GUI { size_t indices_count() const; size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + }; + +#if ENABLE_GLBEGIN_GLEND_REMOVAL + struct RenderData + { + Geometry geometry; + unsigned int vbo_id{ 0 }; + unsigned int ibo_id{ 0 }; + size_t vertices_count{ 0 }; + size_t indices_count{ 0 }; }; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL private: +#if ENABLE_GLBEGIN_GLEND_REMOVAL + RenderData m_render_data; +#else std::vector m_render_data; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL BoundingBoxf3 m_bounding_box; std::string m_filename; @@ -68,51 +176,81 @@ namespace GUI { GLModel() = default; virtual ~GLModel() { reset(); } - void init_from(const InitializationData& data); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + size_t vertices_count() const { return m_render_data.vertices_count > 0 ? + m_render_data.vertices_count : m_render_data.geometry.vertices_count(); } + size_t indices_count() const { return m_render_data.indices_count > 0 ? + m_render_data.indices_count : m_render_data.geometry.indices_count(); } + + size_t vertices_size_floats() const { return vertices_count() * Geometry::vertex_stride_floats(m_render_data.geometry.format); } + size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } + + size_t indices_size_bytes() const { return indices_count() * Geometry::index_stride_bytes(m_render_data.geometry.format); } + + void init_from(Geometry&& data); +#else + void init_from(const Geometry& data); void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void init_from(const indexed_triangle_set& its); void init_from(const Polygons& polygons, float z); bool init_from_file(const std::string& filename); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + void set_color(const ColorRGBA& color) { m_render_data.geometry.color = color; } + const ColorRGBA& get_color() const { return m_render_data.geometry.color; } +#else // if entity_id == -1 set the color of all entities void set_color(int entity_id, const ColorRGBA& color); ColorRGBA get_color(size_t entity_id = 0U) const; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void reset(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + void render(); + void render_instanced(unsigned int instances_vbo, unsigned int instances_count); + + bool is_initialized() const { return vertices_count() > 0 && indices_count() > 0; } +#else void render() const; void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; bool is_initialized() const { return !m_render_data.empty(); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; } const std::string& get_filename() const { return m_filename; } private: +#if ENABLE_GLBEGIN_GLEND_REMOVAL + bool send_to_gpu(); +#else void send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL }; // create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution // the origin of the arrow is in the center of the stem cap // the arrow has its axis of symmetry along the Z axis and is pointing upward // used to render bed axes and sequential marker - GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height); + GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height); // create an arrow whose stem is a quarter of circle, with the given dimensions and resolution // the origin of the arrow is in the center of the circle // the arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise // used to render sidebar hints for rotations - GLModel::InitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness); + GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness); // create an arrow with the given dimensions // the origin of the arrow is in the center of the stem cap // the arrow is contained in XY plane and has its main axis along the Y axis // used to render sidebar hints for position and scale - GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness); + GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness); // create a diamond with the given resolution // the origin of the diamond is in its center // the diamond is contained into a box with size [1, 1, 1] - GLModel::InitializationData diamond(int resolution); + GLModel::Geometry diamond(unsigned short resolution); } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index f7dd320fe23..5331d517d8f 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -69,11 +69,7 @@ namespace GUI { m_state = Off; } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLSelectionRectangle::render(const GLCanvas3D& canvas) -#else - void GLSelectionRectangle::render(const GLCanvas3D& canvas) const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { if (!is_dragging()) return; @@ -84,16 +80,16 @@ namespace GUI { Size cnv_size = canvas.get_canvas_size(); float cnv_half_width = 0.5f * (float)cnv_size.get_width(); float cnv_half_height = 0.5f * (float)cnv_size.get_height(); - if ((cnv_half_width == 0.0f) || (cnv_half_height == 0.0f)) + if (cnv_half_width == 0.0f || cnv_half_height == 0.0f) return; Vec2d start(m_start_corner(0) - cnv_half_width, cnv_half_height - m_start_corner(1)); Vec2d end(m_end_corner(0) - cnv_half_width, cnv_half_height - m_end_corner(1)); - float left = (float)std::min(start(0), end(0)) * inv_zoom; - float top = (float)std::max(start(1), end(1)) * inv_zoom; - float right = (float)std::max(start(0), end(0)) * inv_zoom; - float bottom = (float)std::min(start(1), end(1)) * inv_zoom; + const float left = (float)std::min(start(0), end(0)) * inv_zoom; + const float top = (float)std::max(start(1), end(1)) * inv_zoom; + const float right = (float)std::max(start(0), end(0)) * inv_zoom; + const float bottom = (float)std::min(start(1), end(1)) * inv_zoom; glsafe(::glLineWidth(1.5f)); #if !ENABLE_GLBEGIN_GLEND_REMOVAL @@ -111,7 +107,7 @@ namespace GUI { // ensure that the rectangle is renderered inside the frustrum glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5))); // ensure that the overlay fits the frustrum near z plane - double gui_scale = camera.get_gui_scale(); + const double gui_scale = camera.get_gui_scale(); glsafe(::glScaled(gui_scale, gui_scale, 1.0)); glsafe(::glPushAttrib(GL_ENABLE_BIT)); @@ -128,37 +124,31 @@ namespace GUI { m_old_end_corner = m_end_corner; m_rectangle.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::LineLoop; - entity.positions.reserve(4); - entity.positions.emplace_back(left, bottom, 0.0f); - entity.positions.emplace_back(right, bottom, 0.0f); - entity.positions.emplace_back(right, top, 0.0f); - entity.positions.emplace_back(left, top, 0.0f); - - entity.normals.reserve(4); - for (size_t j = 0; j < 5; ++j) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } - - entity.indices.reserve(6); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); - entity.indices.emplace_back(2); - entity.indices.emplace_back(2); - entity.indices.emplace_back(3); - entity.indices.emplace_back(0); - - init_data.entities.emplace_back(entity); - m_rectangle.init_from(init_data); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(4 * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + init_data.add_vertex(Vec2f(left, bottom)); + init_data.add_vertex(Vec2f(right, bottom)); + init_data.add_vertex(Vec2f(right, top)); + init_data.add_vertex(Vec2f(left, top)); + + // indices + init_data.add_ushort_index(0); + init_data.add_ushort_index(1); + init_data.add_ushort_index(2); + init_data.add_ushort_index(3); + + m_rectangle.init_from(std::move(init_data)); } - ColorRGBA color( + const ColorRGBA color( (m_state == Select) ? 0.3f : 1.0f, (m_state == Select) ? 1.0f : 0.3f, 0.3f, 1.0f); - m_rectangle.set_color(-1, color); + m_rectangle.set_color(color); m_rectangle.render(); shader->stop_using(); } diff --git a/src/slic3r/GUI/GLSelectionRectangle.hpp b/src/slic3r/GUI/GLSelectionRectangle.hpp index 0ead6adfda7..ae0b7a097e0 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.hpp +++ b/src/slic3r/GUI/GLSelectionRectangle.hpp @@ -33,11 +33,7 @@ class GLSelectionRectangle { // Disables the rectangle. void stop_dragging(); -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render(const GLCanvas3D& canvas); -#else - void render(const GLCanvas3D& canvas) const; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL bool is_dragging() const { return m_state != Off; } EState get_state() const { return m_state; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 21b5c13e629..67c17cd015d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -14,22 +14,9 @@ const float GLGizmoBase::Grabber::SizeFactor = 0.05f; const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; -GLGizmoBase::Grabber::Grabber() - : center(Vec3d::Zero()) - , angles(Vec3d::Zero()) - , dragging(false) - , enabled(true) +void GLGizmoBase::Grabber::render(bool hover, float size) { - color = { 1.0f, 1.0f, 1.0f, 1.0f }; -} - -void GLGizmoBase::Grabber::render(bool hover, float size) const -{ - ColorRGBA render_color = color; - if (hover) - render_color = complementary(render_color); - - render(size, render_color, false); + render(size, hover ? complementary(color) : color, false); } float GLGizmoBase::Grabber::get_half_size(float size) const @@ -42,19 +29,27 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const return get_half_size(size) * DraggingScaleFactor; } -void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) const +void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) { - if (!cube.is_initialized()) { + if (!m_cube.is_initialized()) { // This cannot be done in constructor, OpenGL is not yet // initialized at that point (on Linux at least). - indexed_triangle_set mesh = its_make_cube(1., 1., 1.); - its_translate(mesh, Vec3f(-0.5, -0.5, -0.5)); - const_cast(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); + indexed_triangle_set its = its_make_cube(1., 1., 1.); + its_translate(its, Vec3f(-0.5, -0.5, -0.5)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cube.init_from(its); +#else + const_cast(m_cube).init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } - float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); + const float fullsize = 2.0f * (dragging ? get_dragging_half_size(size) : get_half_size(size)); - const_cast(&cube)->set_color(-1, render_color); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cube.set_color(render_color); +#else + const_cast(&m_cube)->set_color(-1, render_color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glPushMatrix()); glsafe(::glTranslated(center.x(), center.y(), center.z())); @@ -62,11 +57,10 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0)); glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); glsafe(::glScaled(fullsize, fullsize, fullsize)); - cube.render(); + m_cube.render(); glsafe(::glPopMatrix()); } - GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : m_parent(parent) , m_group_id(-1) @@ -176,14 +170,23 @@ void GLGizmoBase::render_grabbers(float size) const void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { - float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); - - for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { - if (m_grabbers[i].enabled) { - m_grabbers[i].color = picking_color_component(i); - m_grabbers[i].render_for_picking(mean_size); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); + + for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { + if (m_grabbers[i].enabled) { + m_grabbers[i].color = picking_color_component(i); + m_grabbers[i].render_for_picking(mean_size); + } } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } std::string GLGizmoBase::format(float value, unsigned int decimals) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index ca7e3f2f7d2..99050a25255 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -45,24 +45,24 @@ class GLGizmoBase static const float MinHalfSize; static const float DraggingScaleFactor; - Vec3d center; - Vec3d angles; - ColorRGBA color; - bool enabled; - bool dragging; + bool enabled{ true }; + bool dragging{ false }; + Vec3d center{ Vec3d::Zero() }; + Vec3d angles{ Vec3d::Zero() }; + ColorRGBA color{ ColorRGBA::WHITE() }; - Grabber(); + Grabber() = default; - void render(bool hover, float size) const; - void render_for_picking(float size) const { render(size, color, true); } + void render(bool hover, float size); + void render_for_picking(float size) { render(size, color, true); } float get_half_size(float size) const; float get_dragging_half_size(float size) const; private: - void render(float size, const ColorRGBA& render_color, bool picking) const; + void render(float size, const ColorRGBA& render_color, bool picking); - GLModel cube; + GLModel m_cube; }; public: diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 227cfcc8383..ab29e902623 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -24,7 +24,6 @@ namespace GUI { const double GLGizmoCut::Offset = 10.0; const double GLGizmoCut::Margin = 20.0; static const ColorRGBA GRABBER_COLOR = ColorRGBA::ORANGE(); -static const ColorRGBA PLANE_COLOR = { 0.8f, 0.8f, 0.8f, 0.5f }; GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) @@ -104,48 +103,39 @@ void GLGizmoCut::on_render() #if ENABLE_GLBEGIN_GLEND_REMOVAL GLShaderProgram* shader = wxGetApp().get_shader("flat"); - if (shader == nullptr) - return; - shader->start_using(); - - bool z_changed = std::abs(plane_center.z() - m_old_z) > EPSILON; - m_old_z = plane_center.z(); - - if (!m_plane.is_initialized() || z_changed) { - m_plane.reset(); - - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - entity.positions.reserve(4); - entity.positions.emplace_back(Vec3f(min_x, min_y, plane_center.z())); - entity.positions.emplace_back(Vec3f(max_x, min_y, plane_center.z())); - entity.positions.emplace_back(Vec3f(max_x, max_y, plane_center.z())); - entity.positions.emplace_back(Vec3f(min_x, max_y, plane_center.z())); - - entity.normals.reserve(4); - for (size_t i = 0; i < 4; ++i) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + if (shader != nullptr) { + shader->start_using(); - entity.indices.reserve(6); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); - entity.indices.emplace_back(2); - entity.indices.emplace_back(2); - entity.indices.emplace_back(3); - entity.indices.emplace_back(0); - - init_data.entities.emplace_back(entity); - m_plane.init_from(init_data); - m_plane.set_color(-1, PLANE_COLOR); - } + const bool z_changed = std::abs(plane_center.z() - m_old_z) > EPSILON; + m_old_z = plane_center.z(); + + if (!m_plane.is_initialized() || z_changed) { + m_plane.reset(); - m_plane.render(); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.color = { 0.8f, 0.8f, 0.8f, 0.5f }; + init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + init_data.add_vertex(Vec3f(min_x, min_y, plane_center.z())); + init_data.add_vertex(Vec3f(max_x, min_y, plane_center.z())); + init_data.add_vertex(Vec3f(max_x, max_y, plane_center.z())); + init_data.add_vertex(Vec3f(min_x, max_y, plane_center.z())); + + // indices + init_data.add_ushort_triangle(0, 1, 2); + init_data.add_ushort_triangle(2, 3, 0); + + m_plane.init_from(std::move(init_data)); + } + + m_plane.render(); #else // Draw the cutting plane ::glBegin(GL_QUADS); - ::glColor4fv(PLANE_COLOR.data()); + ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); ::glVertex3f(min_x, min_y, plane_center.z()); ::glVertex3f(max_x, min_y, plane_center.z()); ::glVertex3f(max_x, max_y, plane_center.z()); @@ -153,46 +143,40 @@ void GLGizmoCut::on_render() glsafe(::glEnd()); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL - glsafe(::glEnable(GL_CULL_FACE)); - glsafe(::glDisable(GL_BLEND)); - - // TODO: draw cut part contour? + glsafe(::glEnable(GL_CULL_FACE)); + glsafe(::glDisable(GL_BLEND)); - // Draw the grabber and the connecting line - m_grabbers[0].center = plane_center; - m_grabbers[0].center.z() = plane_center.z() + Offset; + // Draw the grabber and the connecting line + m_grabbers[0].center = plane_center; + m_grabbers[0].center.z() = plane_center.z() + Offset; - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); + glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); #if ENABLE_GLBEGIN_GLEND_REMOVAL - if (!m_grabber_connection.is_initialized() || z_changed) { - m_grabber_connection.reset(); - - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2); - entity.positions.emplace_back(plane_center.cast()); - entity.positions.emplace_back(m_grabbers[0].center.cast()); - - entity.normals.reserve(2); - for (size_t i = 0; i < 2; ++i) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + if (!m_grabber_connection.is_initialized() || z_changed) { + m_grabber_connection.reset(); - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.color = ColorRGBA::YELLOW(); + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); - init_data.entities.emplace_back(entity); - m_grabber_connection.init_from(init_data); - m_grabber_connection.set_color(-1, ColorRGBA::YELLOW()); - } + // vertices + init_data.add_vertex((Vec3f)plane_center.cast()); + init_data.add_vertex((Vec3f)m_grabbers[0].center.cast()); - m_grabber_connection.render(); + // indices + init_data.add_ushort_line(0, 1); - shader->stop_using(); + m_grabber_connection.init_from(std::move(init_data)); + } + + m_grabber_connection.render(); + + shader->stop_using(); + } shader = wxGetApp().get_shader("gouraud_light"); #else @@ -204,23 +188,31 @@ void GLGizmoCut::on_render() GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + if (shader != nullptr) { + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); - if (shader == nullptr) - return; - shader->start_using(); - shader->set_uniform("emission_factor", 0.1f); - - m_grabbers[0].color = GRABBER_COLOR; - m_grabbers[0].render(m_hover_id == 0, (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0)); + m_grabbers[0].color = GRABBER_COLOR; + m_grabbers[0].render(m_hover_id == 0, float((box.size().x() + box.size().y() + box.size().z()) / 3.0)); - shader->stop_using(); + shader->stop_using(); + } - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z())); - glsafe(::glLineWidth(2.0f)); - m_cut_contours.contours.render(); - glsafe(::glPopMatrix()); -} +#if ENABLE_GLBEGIN_GLEND_REMOVAL + shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + glsafe(::glPushMatrix()); + glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z())); + glsafe(::glLineWidth(2.0f)); + m_cut_contours.contours.render(); + glsafe(::glPopMatrix()); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + shader->stop_using(); + } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + } void GLGizmoCut::on_render_for_picking() { @@ -378,7 +370,11 @@ void GLGizmoCut::update_contours() const Polygons polys = slice_mesh(m_cut_contours.mesh.its, m_cut_z, slicing_params); if (!polys.empty()) { m_cut_contours.contours.init_from(polys, static_cast(m_cut_z)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cut_contours.contours.set_color(ColorRGBA::WHITE()); +#else m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f }); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } } else if (box.center() != m_cut_contours.position) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 1aaca437d9f..66b6dcf6096 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -69,11 +69,7 @@ bool GLGizmoFdmSupports::on_init() return true; } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLGizmoFdmSupports::render_painter_gizmo() -#else -void GLGizmoFdmSupports::render_painter_gizmo() const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { const Selection& selection = m_parent.get_selection(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index 6d0de09d492..df9cdce56fe 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -11,11 +11,7 @@ class GLGizmoFdmSupports : public GLGizmoPainterBase GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoPainterBase(parent, icon_filename, sprite_id) {} -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_painter_gizmo() override; -#else - void render_painter_gizmo() const override; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL protected: void on_render_input_window(float x, float y, float bottom_limit) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 16e3730b275..be52ebcb9ae 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -101,12 +101,21 @@ void GLGizmoHollow::on_render_for_picking() render_points(selection, true); } -void GLGizmoHollow::render_points(const Selection& selection, bool picking) const +void GLGizmoHollow::render_points(const Selection& selection, bool picking) { +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); + if (shader == nullptr) + return; + + shader->start_using(); + ScopeGuard guard([shader]() { shader->stop_using(); }); +#else GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light"); if (shader) shader->start_using(); ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); @@ -132,17 +141,21 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons render_color = picking_color_component(i); else { if (size_t(m_hover_id) == i) - render_color = {0.0f, 1.0f, 1.0f, 1.0f}; + render_color = ColorRGBA::CYAN(); else if (m_c->hollowed_mesh() && i < m_c->hollowed_mesh()->get_drainholes().size() && m_c->hollowed_mesh()->get_drainholes()[i].failed) { - render_color = {1.0f, 0.0f, 0.0f, 0.5f}; + render_color = { 1.0f, 0.0f, 0.0f, 0.5f }; } else // neither hover nor picking render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cylinder.set_color(render_color); +#else const_cast(&m_cylinder)->set_color(-1, render_color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. glsafe(::glPushMatrix()); @@ -154,9 +167,9 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons // Matrices set, we can render the point mark now. Eigen::Quaterniond q; - q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); + q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); + glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); glsafe(::glPushMatrix()); glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); @@ -171,8 +184,6 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons glsafe(::glPopMatrix()); } - - bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const { if (m_c->object_clipper()->get_position() == 0.) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index bc144c2973f..fa89e0febc2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -42,7 +42,7 @@ class GLGizmoHollow : public GLGizmoBase void on_render() override; void on_render_for_picking() override; - void render_points(const Selection& selection, bool picking = false) const; + void render_points(const Selection& selection, bool picking = false); void hollow_mesh(bool postpone_error_messages = false); bool unsaved_changes() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index adb4d35bf93..4c204d0d4c5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -130,11 +130,7 @@ bool GLGizmoMmuSegmentation::on_init() return true; } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLGizmoMmuSegmentation::render_painter_gizmo() -#else -void GLGizmoMmuSegmentation::render_painter_gizmo() const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { const Selection& selection = m_parent.get_selection(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 753a89c697e..c294fafcf2c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -85,11 +85,7 @@ class GLGizmoMmuSegmentation : public GLGizmoPainterBase : GLGizmoPainterBase(parent, icon_filename, sprite_id) {} ~GLGizmoMmuSegmentation() override = default; -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_painter_gizmo() override; -#else - void render_painter_gizmo() const override; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void set_painter_gizmo_data(const Selection& selection) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 11db61e0a9a..fe884b38bd6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -114,25 +114,20 @@ void GLGizmoMove3D::on_render() m_grabber_connections[id].old_center = center; m_grabber_connections[id].model.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2); - entity.positions.emplace_back(center.cast()); - entity.positions.emplace_back(m_grabbers[id].center.cast()); - - entity.normals.reserve(2); - for (size_t j = 0; j < 2; ++j) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.color = AXES_COLOR[id]; + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + init_data.add_vertex((Vec3f)center.cast()); + init_data.add_vertex((Vec3f)m_grabbers[id].center.cast()); - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); + // indices + init_data.add_ushort_line(0, 1); - init_data.entities.emplace_back(entity); - m_grabber_connections[id].model.init_from(init_data); - m_grabber_connections[id].model.set_color(-1, AXES_COLOR[id]); + m_grabber_connections[id].model.init_from(std::move(init_data)); } m_grabber_connections[id].model.render(); @@ -243,24 +238,30 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const return projection; } -void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const +void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) { - float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); - double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size); - - ColorRGBA color = m_grabbers[axis].color; - if (!picking && m_hover_id != -1) - color = complementary(color); + float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); + double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size)); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); +#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL if (shader == nullptr) return; - const_cast(&m_cone)->set_color(-1, color); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cone.set_color((!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color); + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); +#else + const_cast(&m_cone)->set_color(-1, (!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color); if (!picking) { shader->start_using(); shader->set_uniform("emission_factor", 0.1f); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glPushMatrix()); glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z())); @@ -274,11 +275,11 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box m_cone.render(); glsafe(::glPopMatrix()); +#if !ENABLE_GLBEGIN_GLEND_REMOVAL if (! picking) +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL shader->stop_using(); } - - } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index 8d83e0be382..2a75df86698 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -50,7 +50,7 @@ class GLGizmoMove3D : public GLGizmoBase private: double calc_projection(const UpdateData& data) const; - void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const; + void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking); }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index f1fe275fe2e..4c76767bd71 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -113,11 +113,7 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const } } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLGizmoPainterBase::render_cursor() -#else -void GLGizmoPainterBase::render_cursor() const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { // First check that the mouse pointer is on an object. const ModelObject* mo = m_c->selection_info()->model_object(); @@ -144,11 +140,7 @@ void GLGizmoPainterBase::render_cursor() const } } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLGizmoPainterBase::render_cursor_circle() -#else -void GLGizmoPainterBase::render_cursor_circle() const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { const Camera &camera = wxGetApp().plater()->get_camera(); const float zoom = float(camera.get_zoom()); @@ -188,27 +180,30 @@ void GLGizmoPainterBase::render_cursor_circle() const m_old_cursor_radius = m_cursor_radius; m_circle.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::LineLoop; + GLModel::Geometry init_data; static const unsigned int StepsCount = 32; static const float StepSize = 2.0f * float(PI) / float(StepsCount); - entity.positions.reserve(StepsCount); - entity.normals.reserve(StepsCount); - entity.indices.reserve(StepsCount); - for (unsigned int i = 0; i < StepsCount; ++i) { + init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f }; + init_data.vertices.reserve(StepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(StepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + for (unsigned short i = 0; i < StepsCount; ++i) { const float angle = float(i * StepSize); - entity.positions.emplace_back(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius, 0.0f); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.emplace_back(i); + init_data.add_vertex(Vec3f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius, 0.0f)); + init_data.add_ushort_index(i); } - init_data.entities.emplace_back(entity); - m_circle.init_from(init_data); + m_circle.init_from(std::move(init_data)); } - m_circle.set_color(-1, { 0.0f, 1.0f, 0.3f, 1.0f }); - m_circle.render(); + GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); + m_circle.render(); + shader->stop_using(); + } #else ::glBegin(GL_LINE_LOOP); for (double angle=0; angle<2*M_PI; angle+=M_PI/20.) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 93df15d8062..079f3f08edd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -121,11 +121,7 @@ class GLGizmoPainterBase : public GLGizmoBase // from usual on_render method allows to render them before transparent // objects, so they can be seen inside them. The usual on_render is called // after all volumes (including transparent ones) are rendered. -#if ENABLE_GLBEGIN_GLEND_REMOVAL virtual void render_painter_gizmo() = 0; -#else - virtual void render_painter_gizmo() const = 0; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL virtual const float get_cursor_radius_min() const { return CursorRadiusMin; } virtual const float get_cursor_radius_max() const { return CursorRadiusMax; } @@ -133,13 +129,8 @@ class GLGizmoPainterBase : public GLGizmoBase protected: virtual void render_triangles(const Selection& selection) const; -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_cursor(); void render_cursor_circle(); -#else - void render_cursor() const; - void render_cursor_circle() const; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void render_cursor_sphere(const Transform3d& trafo) const; virtual void update_model_object() const = 0; virtual void update_from_model_object() = 0; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index b7fbcec9151..9bedc86cc8d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -233,24 +233,22 @@ void GLGizmoRotate::render_circle() const if (!m_circle.is_initialized() || radius_changed) { m_circle.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::LineLoop; - entity.positions.reserve(ScaleStepsCount); - entity.normals.reserve(ScaleStepsCount); - entity.indices.reserve(ScaleStepsCount); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) { + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + for (unsigned short i = 0; i < ScaleStepsCount; ++i) { const float angle = float(i * ScaleStepRad); - entity.positions.emplace_back(::cos(angle) * m_radius, ::sin(angle) * m_radius, 0.0f); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.emplace_back(i); + init_data.add_vertex(Vec3f(::cos(angle) * m_radius, ::sin(angle) * m_radius, 0.0f)); + init_data.add_ushort_index(i); } - init_data.entities.emplace_back(entity); - m_circle.init_from(init_data); + m_circle.init_from(std::move(init_data)); } - m_circle.set_color(-1, color); + m_circle.set_color(color); m_circle.render(); #else ::glBegin(GL_LINE_LOOP); @@ -278,13 +276,13 @@ void GLGizmoRotate::render_scale() const if (!m_scale.is_initialized() || radius_changed) { m_scale.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2 * ScaleStepsCount); - entity.normals.reserve(2 * ScaleStepsCount); - entity.indices.reserve(2 * ScaleStepsCount); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) { + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + for (unsigned short i = 0; i < ScaleStepsCount; ++i) { const float angle = float(i * ScaleStepRad); const float cosa = ::cos(angle); const float sina = ::sin(angle); @@ -293,19 +291,16 @@ void GLGizmoRotate::render_scale() const const float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short; const float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short; - entity.positions.emplace_back(in_x, in_y, 0.0f); - entity.positions.emplace_back(out_x, out_y, 0.0f); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.emplace_back(i * 2 + 0); - entity.indices.emplace_back(i * 2 + 1); + init_data.add_vertex(Vec3f(in_x, in_y, 0.0f)); + init_data.add_vertex(Vec3f(out_x, out_y, 0.0f)); + init_data.add_ushort_index(i * 2); + init_data.add_ushort_index(i * 2 + 1); } - init_data.entities.emplace_back(entity); - m_scale.init_from(init_data); -} + m_scale.init_from(std::move(init_data)); + } - m_scale.set_color(-1, color); + m_scale.set_color(color); m_scale.render(); #else ::glBegin(GL_LINES); @@ -340,13 +335,13 @@ void GLGizmoRotate::render_snap_radii() const if (!m_snap_radii.is_initialized() || radius_changed) { m_snap_radii.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2 * ScaleStepsCount); - entity.normals.reserve(2 * ScaleStepsCount); - entity.indices.reserve(2 * ScaleStepsCount); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) { + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + for (unsigned short i = 0; i < ScaleStepsCount; ++i) { const float angle = float(i * step); const float cosa = ::cos(angle); const float sina = ::sin(angle); @@ -355,19 +350,16 @@ void GLGizmoRotate::render_snap_radii() const const float out_x = cosa * out_radius; const float out_y = sina * out_radius; - entity.positions.emplace_back(in_x, in_y, 0.0f); - entity.positions.emplace_back(out_x, out_y, 0.0f); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.emplace_back(i * 2 + 0); - entity.indices.emplace_back(i * 2 + 1); + init_data.add_vertex(Vec3f(in_x, in_y, 0.0f)); + init_data.add_vertex(Vec3f(out_x, out_y, 0.0f)); + init_data.add_ushort_index(i * 2); + init_data.add_ushort_index(i * 2 + 1); } - init_data.entities.emplace_back(entity); - m_snap_radii.init_from(init_data); + m_snap_radii.init_from(std::move(init_data)); } - m_snap_radii.set_color(-1, color); + m_snap_radii.set_color(color); m_snap_radii.render(); #else ::glBegin(GL_LINES); @@ -394,24 +386,22 @@ void GLGizmoRotate::render_reference_radius(const ColorRGBA& color, bool radius_ if (!m_reference_radius.is_initialized() || radius_changed) { m_reference_radius.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2); - entity.positions.emplace_back(0.0f, 0.0f, 0.0f); - entity.positions.emplace_back(m_radius * (1.0f + GrabberOffset), 0.0f, 0.0f); - entity.normals.reserve(2); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); - init_data.entities.emplace_back(entity); - m_reference_radius.init_from(init_data); + // vertices + init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); + init_data.add_vertex(Vec3f(m_radius * (1.0f + GrabberOffset), 0.0f, 0.0f)); + + // indices + init_data.add_ushort_line(0, 1); + + m_reference_radius.init_from(std::move(init_data)); } - m_reference_radius.set_color(-1, color); + m_reference_radius.set_color(color); m_reference_radius.render(); } #else @@ -437,24 +427,22 @@ void GLGizmoRotate::render_angle() const if (!m_angle_arc.is_initialized() || radius_changed) { m_angle_arc.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::LineStrip; - entity.positions.reserve(1 + AngleResolution); - entity.normals.reserve(1 + AngleResolution); - entity.indices.reserve(1 + AngleResolution); - for (unsigned int i = 0; i <= AngleResolution; ++i) { + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve((1 + AngleResolution) * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve((1 + AngleResolution) * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + indices + for (unsigned short i = 0; i <= AngleResolution; ++i) { const float angle = float(i) * step_angle; - entity.positions.emplace_back(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.emplace_back(i); + init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f)); + init_data.add_ushort_index(i); } - init_data.entities.emplace_back(entity); - m_angle_arc.init_from(init_data); + m_angle_arc.init_from(std::move(init_data)); } - m_angle_arc.set_color(-1, color); + m_angle_arc.set_color(color); m_angle_arc.render(); #else ::glBegin(GL_LINE_STRIP); @@ -476,32 +464,30 @@ void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color, bool radiu m_grabber_connection.model.reset(); m_grabber_connection.old_center = m_grabbers.front().center; - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2); - entity.positions.emplace_back(0.0f, 0.0f, 0.0f); - entity.positions.emplace_back(m_grabbers.front().center.cast()); - entity.normals.reserve(2); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.normals.emplace_back(Vec3f::UnitZ()); - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); + init_data.add_vertex((Vec3f)m_grabbers.front().center.cast()); + + // indices + init_data.add_ushort_line(0, 1); - init_data.entities.emplace_back(entity); - m_grabber_connection.model.init_from(init_data); + m_grabber_connection.model.init_from(std::move(init_data)); } - m_grabber_connection.model.set_color(-1, color); + m_grabber_connection.model.set_color(color); m_grabber_connection.model.render(); } #endif // ENABLE_GLBEGIN_GLEND_REMOVAL -void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const +void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) { #if !ENABLE_GLBEGIN_GLEND_REMOVAL - const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); + const double grabber_radius = double(m_radius) * (1.0 + double(GrabberOffset)); m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); m_grabbers[0].angles.z() = m_angle; @@ -522,19 +508,26 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); const double size = m_dragging ? double(m_grabbers.front().get_dragging_half_size(mean_size)) : double(m_grabbers.front().get_half_size(mean_size)); - ColorRGBA color = m_grabbers.front().color; - if (!picking && m_hover_id != -1) - color = complementary(color); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); + if (shader == nullptr) + return; + + m_cone.set_color((!picking && m_hover_id != -1) ? complementary(m_grabbers.front().color) : m_grabbers.front().color); + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); +#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; - m_cone.set_color(-1, color); + m_cone.set_color(-1, (!picking && m_hover_id != -1) ? complementary(m_grabbers.front().color) : m_grabbers.front().color); if (!picking) { shader->start_using(); shader->set_uniform("emission_factor", 0.1f); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL const Vec3d& center = m_grabbers.front().center; @@ -555,13 +548,15 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick m_cone.render(); glsafe(::glPopMatrix()); +#if !ENABLE_GLBEGIN_GLEND_REMOVAL if (! picking) +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL shader->stop_using(); } void GLGizmoRotate::transform_to_local(const Selection& selection) const { - glsafe(::glTranslated(m_center(0), m_center(1), m_center(2))); + glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z())); if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) { const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 5e80ca7de40..bb33e0f7313 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -84,7 +84,7 @@ class GLGizmoRotate : public GLGizmoBase void render_reference_radius() const; void render_angle() const; #endif // ENABLE_GLBEGIN_GLEND_REMOVAL - void render_grabber(const BoundingBoxf3& box) const; + void render_grabber(const BoundingBoxf3& box); void render_grabber_extension(const BoundingBoxf3& box, bool picking); void transform_to_local(const Selection& selection) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 953c7dd6c2b..7d0e3ec3470 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -390,7 +390,7 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int return -1; }; - int id = grabber_connection(id_1, id_2); + const int id = grabber_connection(id_1, id_2); if (id == -1) return; @@ -401,27 +401,22 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int m_grabber_connections[id].old_v2 = m_grabbers[id_2].center; m_grabber_connections[id].model.reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(2); - entity.positions.emplace_back(m_grabbers[id_1].center.cast()); - entity.positions.emplace_back(m_grabbers[id_2].center.cast()); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); - entity.normals.reserve(2); - for (size_t j = 0; j < 2; ++j) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + // vertices + init_data.add_vertex((Vec3f)m_grabbers[id_1].center.cast()); + init_data.add_vertex((Vec3f)m_grabbers[id_2].center.cast()); - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); + // indices + init_data.add_ushort_line(0, 1); - init_data.entities.emplace_back(entity); - m_grabber_connections[id].model.init_from(init_data); + m_grabber_connections[id].model.init_from(std::move(init_data)); } - m_grabber_connections[id].model.set_color(-1, color); + m_grabber_connections[id].model.set_color(color); m_grabber_connections[id].model.render(); } #else diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 1ac311ea1ee..5f6cd7a95fa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -52,11 +52,7 @@ std::string GLGizmoSeam::on_get_name() const return _u8L("Seam painting"); } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLGizmoSeam::render_painter_gizmo() -#else -void GLGizmoSeam::render_painter_gizmo() const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { const Selection& selection = m_parent.get_selection(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp index 77be092d7aa..533683237d8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp @@ -11,11 +11,7 @@ class GLGizmoSeam : public GLGizmoPainterBase GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoPainterBase(parent, icon_filename, sprite_id) {} -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_painter_gizmo() override; -#else - void render_painter_gizmo() const override; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL protected: void on_render_input_window(float x, float y, float bottom_limit) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 0d475401b95..2126e41a2da 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -659,7 +659,11 @@ void GLGizmoSimplify::init_model() assert(m_glmodels.find(id) == m_glmodels.end()); GLModel &glmodel = m_glmodels[id]; // create new glmodel glmodel.init_from(its); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + glmodel.set_color(selected_volume->color); +#else glmodel.set_color(-1,selected_volume->color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_parent.toggle_model_objects_visibility(false, info->model_object(), info->get_active_instance(), @@ -688,7 +692,11 @@ void GLGizmoSimplify::update_model(const State::Data &data) // when not reset it keeps old shape glmodel.reset(); glmodel.init_from(its); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + glmodel.set_color(color); +#else glmodel.set_color(-1, color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_triangle_count += its.indices.size(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 37a1073461d..3406c58a29c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -116,7 +116,7 @@ void GLGizmoSlaSupports::on_render_for_picking() render_points(selection, true); } -void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const +void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) { size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); @@ -174,8 +174,13 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) } } - const_cast(&m_cone)->set_color(-1, render_color); - const_cast(&m_sphere)->set_color(-1, render_color); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cone.set_color(render_color); + m_sphere.set_color(render_color); +#else + m_cone.set_color(-1, render_color); + m_sphere.set_color(-1, render_color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL if (shader && !picking) shader->set_uniform("emission_factor", 0.5f); @@ -227,7 +232,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) // Now render the drain holes: if (has_holes && ! picking) { render_color = { 0.7f, 0.7f, 0.7f, 0.7f }; - const_cast(&m_cylinder)->set_color(-1, render_color); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_cylinder.set_color(render_color); +#else + m_cylinder.set_color(-1, render_color); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL if (shader) shader->set_uniform("emission_factor", 0.5f); for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 92d085f378a..49df659f481 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -77,7 +77,7 @@ class GLGizmoSlaSupports : public GLGizmoBase void on_render() override; void on_render_for_picking() override; - void render_points(const Selection& selection, bool picking = false) const; + void render_points(const Selection& selection, bool picking = false); bool unsaved_changes() const; bool m_lock_unique_islands = false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 6b3e03076b4..62ca16de35a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -475,11 +475,7 @@ void GLGizmosManager::render_current_gizmo() const m_gizmos[m_current]->render(); } -#if ENABLE_GLBEGIN_GLEND_REMOVAL void GLGizmosManager::render_painter_gizmo() -#else -void GLGizmosManager::render_painter_gizmo() const -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL { // This function shall only be called when current gizmo is // derived from GLGizmoPainterBase. diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 15aeacd5af4..fe4f81bd784 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -232,11 +232,7 @@ class GLGizmosManager : public Slic3r::ObjectBase void render_current_gizmo() const; void render_current_gizmo_for_picking_pass() const; -#if ENABLE_GLBEGIN_GLEND_REMOVAL void render_painter_gizmo(); -#else - void render_painter_gizmo() const; -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL void render_overlay() const; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 0fef5ac643a..5bd20407cc7 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1315,6 +1315,13 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const if (sidebar_field.empty()) return; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light"); + if (shader == nullptr) + return; + + shader->start_using(); +#else GLShaderProgram* shader = nullptr; if (!boost::starts_with(sidebar_field, "layer")) { @@ -1325,6 +1332,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const shader->start_using(); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glEnable(GL_DEPTH_TEST)); @@ -1369,6 +1377,11 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const } } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + if (!boost::starts_with(sidebar_field, "layer")) + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + if (boost::starts_with(sidebar_field, "position")) render_sidebar_position_hints(sidebar_field); else if (boost::starts_with(sidebar_field, "rotation")) @@ -1380,7 +1393,9 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const glsafe(::glPopMatrix()); +#if !ENABLE_GLBEGIN_GLEND_REMOVAL if (!boost::starts_with(sidebar_field, "layer")) +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL shader->stop_using(); } @@ -1865,15 +1880,6 @@ void Selection::render_synchronized_volumes() const } #if ENABLE_GLBEGIN_GLEND_REMOVAL -static bool is_approx(const Vec3d& v1, const Vec3d& v2) -{ - for (int i = 0; i < 3; ++i) { - if (std::abs(v1[i] - v2[i]) > EPSILON) - return false; - } - return true; -} - void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& color) { #else @@ -1900,79 +1906,74 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con const Vec3f b_max = box.max.cast(); const Vec3f size = 0.2f * box.size().cast(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Lines; - entity.positions.reserve(48); - - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x() + size.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y() + size.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_min.z() + size.z())); - - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x() - size.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y() + size.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_min.z() + size.z())); - - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x() - size.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y() - size.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_min.z() + size.z())); - - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x() + size.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y() - size.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_min.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_min.z() + size.z())); - - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x() + size.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y() + size.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_max.z() - size.z())); - - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x() - size.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y() + size.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_max.z() - size.z())); - - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x() - size.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y() - size.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_max.x(), b_max.y(), b_max.z() - size.z())); - - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x() + size.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y() - size.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_max.z())); - entity.positions.emplace_back(Vec3f(b_min.x(), b_max.y(), b_max.z() - size.z())); - - entity.normals.reserve(48); - for (size_t i = 0; i < 48; ++i) { - entity.normals.emplace_back(Vec3f::UnitZ()); + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(48 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(48 * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y() + size.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z() + size.z())); + + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y() + size.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z() + size.z())); + + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y() - size.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z() + size.z())); + + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y() - size.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z() + size.z())); + + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y() + size.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z() - size.z())); + + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y() + size.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z() - size.z())); + + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y() - size.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z() - size.z())); + + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y() - size.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z())); + init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z() - size.z())); + + // indices + for (unsigned short i = 0; i < 48; ++i) { + init_data.add_ushort_index(i); } - entity.indices.reserve(48); - for (size_t i = 0; i < 48; ++i) { - entity.indices.emplace_back(i); - } - - init_data.entities.emplace_back(entity); - m_box.init_from(init_data); + m_box.init_from(std::move(init_data)); } glsafe(::glEnable(GL_DEPTH_TEST)); @@ -1984,7 +1985,7 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con return; shader->start_using(); - m_box.set_color(-1, to_rgba(color)); + m_box.set_color(to_rgba(color)); m_box.render(); shader->stop_using(); #else @@ -2036,16 +2037,16 @@ void Selection::render_sidebar_position_hints(const std::string& sidebar_field) { if (boost::ends_with(sidebar_field, "x")) { glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); - m_arrow.set_color(-1, get_color(X)); + m_arrow.set_color(get_color(X)); m_arrow.render(); } else if (boost::ends_with(sidebar_field, "y")) { - m_arrow.set_color(-1, get_color(Y)); + m_arrow.set_color(get_color(Y)); m_arrow.render(); } else if (boost::ends_with(sidebar_field, "z")) { glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); - m_arrow.set_color(-1, get_color(Z)); + m_arrow.set_color(get_color(Z)); m_arrow.render(); } } @@ -2080,16 +2081,16 @@ void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) if (boost::ends_with(sidebar_field, "x")) { glsafe(::glRotated(90.0, 0.0, 1.0, 0.0)); - m_curved_arrow.set_color(-1, get_color(X)); + m_curved_arrow.set_color(get_color(X)); render_sidebar_rotation_hint(); } else if (boost::ends_with(sidebar_field, "y")) { glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); - m_curved_arrow.set_color(-1, get_color(Y)); + m_curved_arrow.set_color(get_color(Y)); render_sidebar_rotation_hint(); } else if (boost::ends_with(sidebar_field, "z")) { - m_curved_arrow.set_color(-1, get_color(Z)); + m_curved_arrow.set_color(get_color(Z)); render_sidebar_rotation_hint(); } } @@ -2129,7 +2130,7 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) { #if ENABLE_GLBEGIN_GLEND_REMOVAL - m_arrow.set_color(-1, uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis)); + m_arrow.set_color(uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis)); #else const_cast(&m_arrow)->set_color(-1, uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis)); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL @@ -2216,11 +2217,6 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co #if ENABLE_GLBEGIN_GLEND_REMOVAL const Vec3f p1 = { float(box.min.x()) - Margin, float(box.min.y()) - Margin, z1 }; const Vec3f p2 = { float(box.max.x()) + Margin, float(box.max.y()) + Margin, z2 }; -#else - const float min_x = float(box.min.x()) - Margin; - const float max_x = float(box.max.x()) + Margin; - const float min_y = float(box.min.y()) - Margin; - const float max_y = float(box.max.y()) + Margin; #endif // ENABLE_GLBEGIN_GLEND_REMOVAL glsafe(::glEnable(GL_DEPTH_TEST)); @@ -2229,69 +2225,53 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); #if ENABLE_GLBEGIN_GLEND_REMOVAL - if (!m_planes.models[0].is_initialized() || !is_approx(m_planes.check_points[0].cast(), p1.cast())) { + if (!m_planes.models[0].is_initialized() || !is_approx(m_planes.check_points[0], p1)) { m_planes.check_points[0] = p1; m_planes.models[0].reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - entity.positions.reserve(4); - entity.positions.emplace_back(Vec3f(p1.x(), p1.y(), z1)); - entity.positions.emplace_back(Vec3f(p2.x(), p1.y(), z1)); - entity.positions.emplace_back(Vec3f(p2.x(), p2.y(), z1)); - entity.positions.emplace_back(Vec3f(p1.x(), p2.y(), z1)); - - entity.normals.reserve(4); - for (size_t i = 0; i < 4; ++i) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); - entity.indices.reserve(6); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); - entity.indices.emplace_back(2); - entity.indices.emplace_back(2); - entity.indices.emplace_back(3); - entity.indices.emplace_back(0); + // vertices + init_data.add_vertex(Vec3f(p1.x(), p1.y(), z1)); + init_data.add_vertex(Vec3f(p2.x(), p1.y(), z1)); + init_data.add_vertex(Vec3f(p2.x(), p2.y(), z1)); + init_data.add_vertex(Vec3f(p1.x(), p2.y(), z1)); - init_data.entities.emplace_back(entity); - m_planes.models[0].init_from(init_data); + // indices + init_data.add_ushort_triangle(0, 1, 2); + init_data.add_ushort_triangle(2, 3, 0); + + m_planes.models[0].init_from(std::move(init_data)); } - if (!m_planes.models[1].is_initialized() || !is_approx(m_planes.check_points[1].cast(), p2.cast())) { + if (!m_planes.models[1].is_initialized() || !is_approx(m_planes.check_points[1], p2)) { m_planes.check_points[1] = p2; m_planes.models[1].reset(); - GLModel::InitializationData init_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - entity.positions.reserve(4); - entity.positions.emplace_back(Vec3f(p1.x(), p1.y(), z2)); - entity.positions.emplace_back(Vec3f(p2.x(), p1.y(), z2)); - entity.positions.emplace_back(Vec3f(p2.x(), p2.y(), z2)); - entity.positions.emplace_back(Vec3f(p1.x(), p2.y(), z2)); - - entity.normals.reserve(4); - for (size_t i = 0; i < 4; ++i) { - entity.normals.emplace_back(Vec3f::UnitZ()); - } + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + + // vertices + init_data.add_vertex(Vec3f(p1.x(), p1.y(), z2)); + init_data.add_vertex(Vec3f(p2.x(), p1.y(), z2)); + init_data.add_vertex(Vec3f(p2.x(), p2.y(), z2)); + init_data.add_vertex(Vec3f(p1.x(), p2.y(), z2)); - entity.indices.reserve(6); - entity.indices.emplace_back(0); - entity.indices.emplace_back(1); - entity.indices.emplace_back(2); - entity.indices.emplace_back(2); - entity.indices.emplace_back(3); - entity.indices.emplace_back(0); + // indices + init_data.add_ushort_triangle(0, 1, 2); + init_data.add_ushort_triangle(2, 3, 0); - init_data.entities.emplace_back(entity); - m_planes.models[1].init_from(init_data); + m_planes.models[1].init_from(std::move(init_data)); } - m_planes.models[0].set_color(-1, (camera_on_top && type == 1) || (!camera_on_top && type == 2) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR); + m_planes.models[0].set_color((camera_on_top && type == 1) || (!camera_on_top && type == 2) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR); m_planes.models[0].render(); - m_planes.models[1].set_color(-1, (camera_on_top && type == 2) || (!camera_on_top && type == 1) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR); + m_planes.models[1].set_color((camera_on_top && type == 2) || (!camera_on_top && type == 1) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR); m_planes.models[1].render(); #else ::glBegin(GL_QUADS);