From fdf8b11d4cfa793d1e45d82560d4bd97d0466d40 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Sat, 21 Oct 2023 16:16:21 +0800 Subject: [PATCH] Tech ENABLE_GLBEGIN_GLEND_REMOVAL - Refactoring of GLModel to: 1) allow for custom vertex data layout 2) allow for custom index data format 3) allow for any OpenGL primitive type (cherry picked from commit prusa3d/PrusaSlicer@afcac6e2ea306fbbb12428e360c0fe70b2a3f12d) --- src/libslic3r/Color.hpp | 4 + src/slic3r/GUI/3DBed.cpp | 44 +- src/slic3r/GUI/3DBed.hpp | 14 +- src/slic3r/GUI/3DScene.cpp | 77 +- src/slic3r/GUI/GCodeViewer.cpp | 50 +- src/slic3r/GUI/GCodeViewer.hpp | 8 +- src/slic3r/GUI/GLCanvas3D.cpp | 149 +-- src/slic3r/GUI/GLModel.cpp | 1201 +++++++++++------- src/slic3r/GUI/GLModel.hpp | 153 ++- src/slic3r/GUI/GLSelectionRectangle.cpp | 60 +- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp | 184 +-- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp | 2 + src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 68 +- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 25 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 41 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 5 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 57 +- src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 35 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 187 ++- src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 29 +- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 23 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 10 +- src/slic3r/GUI/Gizmos/GLGizmoText.cpp | 20 +- src/slic3r/GUI/Selection.cpp | 260 ++-- 27 files changed, 1517 insertions(+), 1197 deletions(-) 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 0c29cdc195c..786cd401331 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -157,7 +157,7 @@ void Bed3D::load_render_colors() RenderColor::colors[RenderCol_Axis_Z] = ImGuiWrapper::to_ImVec4(Bed3D::AXIS_Z_COLOR); } -void Bed3D::Axes::render() const +void Bed3D::Axes::render() { auto render_axis = [this](const Transform3f& transform) { glsafe(::glPushMatrix()); @@ -167,7 +167,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) @@ -179,15 +179,15 @@ void Bed3D::Axes::render() const shader->set_uniform("emission_factor", 0.0f); // x axis - const_cast(&m_arrow)->set_color(-1, AXIS_X_COLOR); + m_arrow.set_color(AXIS_X_COLOR); 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, AXIS_Y_COLOR); + m_arrow.set_color(AXIS_Y_COLOR); 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, AXIS_Z_COLOR); + m_arrow.set_color(AXIS_Z_COLOR); render_axis(Geometry::assemble_transform(m_origin).cast()); shader->stop_using(); @@ -340,14 +340,14 @@ void Bed3D::render(GLCanvas3D& canvas, bool bottom, float scale_factor, bool sho void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes) { - 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)); - m_model.set_color(-1, m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR); + m_model.set_color(m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR); switch (m_type) { @@ -456,13 +456,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) const +void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) { if (!bottom) render_model(); @@ -471,7 +471,7 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const 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); @@ -656,34 +656,32 @@ GeometryBuffer Bed3D::update_bed_triangles() const return new_triangles; } -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, m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR); + if (m_model.get_filename() != m_model_filename && m_model.init_from_file(m_model_filename)) { + m_model.set_color(m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR); update_model_offset(); } - 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) const +void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) { if (m_model_filename.empty()) { render_default(bottom); @@ -697,15 +695,15 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) const render_texture(bottom, canvas);*/ } -void Bed3D::render_default(bool bottom) const +void Bed3D::render_default(bool bottom) { bool picking = false; - 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(); GeometryBuffer default_triangles = update_bed_triangles(); 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 d1af27f4255..7bb4ebfb74d 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -70,7 +70,7 @@ class Bed3D m_arrow.reset(); } float get_total_length() const { return m_stem_length + DefaultTipLength; } - void render() const; + void render(); }; public: @@ -159,12 +159,12 @@ class Bed3D static std::tuple detect_type(const Pointfs& shape); void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes); - void render_axes() const; - void render_system(GLCanvas3D& canvas, bool bottom) const; - //void render_texture(bool bottom, GLCanvas3D& canvas) const; - void render_model() const; - void render_custom(GLCanvas3D& canvas, bool bottom) const; - void render_default(bool bottom) const; + void render_axes(); + void render_system(GLCanvas3D& canvas, bool bottom); + //void render_texture(bool bottom, GLCanvas3D& canvas); + void render_model(); + void render_custom(GLCanvas3D& canvas, bool bottom); + void render_default(bool bottom); void release_VBOs(); }; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index f94bba6c4fa..209e77c01b2 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -332,10 +332,10 @@ void GLVolume::SinkingContours::render() void GLVolume::SinkingContours::update() { - int object_idx = m_parent.object_idx(); - Model& model = GUI::wxGetApp().plater()->model(); + const int object_idx = m_parent.object_idx(); + const Model& model = GUI::wxGetApp().plater()->model(); - if (0 <= object_idx && object_idx < (int)model.objects.size() && m_parent.is_sinking() && !m_parent.is_below_printbed()) { + if (0 <= object_idx && object_idx < int(model.objects.size()) && m_parent.is_sinking() && !m_parent.is_below_printbed()) { const BoundingBoxf3& box = m_parent.transformed_convex_hull_bounding_box(); if (!m_old_box.size().isApprox(box.size()) || m_old_box.min.z() != box.min.z()) { m_old_box = box; @@ -344,28 +344,25 @@ 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; + 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; MeshSlicingParams slicing_params; slicing_params.trafo = m_parent.world_matrix(); - Polygons polygons = union_(slice_mesh(mesh.its, 0.0f, slicing_params)); - for (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; + 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))))) { 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) { - entity.positions.emplace_back(v.cast() + Vec3f(0.0f, 0.0f, 0.015f)); // add a small positive z to avoid z-fighting - entity.normals.emplace_back(Vec3f::UnitZ()); - const size_t positions_count = entity.positions.size(); - if (positions_count % 3 == 0) { - entity.indices.emplace_back(positions_count - 3); - entity.indices.emplace_back(positions_count - 2); - entity.indices.emplace_back(positions_count - 1); - } + 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); } - init_data.entities.emplace_back(entity); } - - m_model.init_from(init_data); + m_model.init_from(std::move(init_data)); } else m_shift = box.center() - m_old_box.center(); @@ -1247,6 +1244,9 @@ void GLVolumeCollection::render( if (shader == nullptr) return; + GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); + GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat"); + if (type == ERenderType::Transparent) { glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); @@ -1272,13 +1272,18 @@ void GLVolumeCollection::render( #endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT // 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(); + shader->stop_using(); + if (sink_shader != nullptr) { + sink_shader->start_using(); + 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) { + volume.first->render_sinking_contours(); + } } + sink_shader->stop_using(); + } + shader->start_using(); glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); @@ -1341,17 +1346,21 @@ void GLVolumeCollection::render( } 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(); + shader->stop_using(); + if (sink_shader != nullptr) { + sink_shader->start_using(); + 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)) { + glsafe(::glDepthFunc(GL_ALWAYS)); + volume.first->render_sinking_contours(); + glsafe(::glDepthFunc(GL_LESS)); + } } + sink_shader->start_using(); } + shader->start_using(); } if (disable_cullface) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 082e7b84dfa..36e27b26359 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -288,7 +288,7 @@ void GCodeViewer::SequentialView::Marker::init(std::string filename) } else { m_model.init_from_file(filename); } - m_model.set_color(-1, {1.0f, 1.0f, 1.0f, 0.5f}); + m_model.set_color({ 1.0f, 1.0f, 1.0f, 0.5f }); } void GCodeViewer::SequentialView::Marker::set_world_position(const Vec3f& position) @@ -302,7 +302,7 @@ void GCodeViewer::SequentialView::Marker::update_curr_move(const GCodeProcessorR } //BBS: GUI refactor: add canvas size from parameters -void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_height, const EViewType& view_type) const +void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_height, const EViewType& view_type) { if (!m_visible) return; @@ -670,7 +670,7 @@ void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished mapping file " << m_filename; } } -void GCodeViewer::SequentialView::render(const bool has_render_path, float legend_height, int canvas_width, int canvas_height, int right_margin, const EViewType& view_type) const +void GCodeViewer::SequentialView::render(const bool has_render_path, float legend_height, int canvas_width, int canvas_height, int right_margin, const EViewType& view_type) { if (has_render_path) marker.render(canvas_width, canvas_height, view_type); @@ -1346,7 +1346,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai } if (range.vbo > 0) { - buffer.model.model.set_color(-1, range.color); + buffer.model.model.set_color(range.color); buffer.model.model.render_instanced(range.vbo, range.count); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_instanced_models_calls_count; @@ -2291,28 +2291,27 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const }; // 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(); - for (const auto& entity : data.entities) { - // append vertices - for (size_t i = 0; i < entity.positions.size(); ++i) { - // append position - const Vec3d position = trafo * entity.positions[i].cast(); - vertices.push_back(static_cast(position.x())); - vertices.push_back(static_cast(position.y())); - vertices.push_back(static_cast(position.z())); - - // append normal - const Vec3d normal = normal_matrix * entity.normals[i].cast(); - vertices.push_back(static_cast(normal.x())); - vertices.push_back(static_cast(normal.y())); - vertices.push_back(static_cast(normal.z())); - } + // 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())); } // append instance position @@ -2323,11 +2322,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const instances_ids.push_back(move_id); }; - auto add_indices_as_model_batch = [](const GLModel::InitializationData& data, IndexBuffer& indices, IBufferType base_index) { - 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)); - } + auto add_indices_as_model_batch = [](const GLModel::Geometry& data, IndexBuffer& indices, IBufferType base_index) { + 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)); } }; @@ -3868,7 +3866,7 @@ void GCodeViewer::render_toolpaths() } if (range.vbo > 0) { - buffer.model.model.set_color(-1, range.color); + buffer.model.model.set_color(range.color); 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 4c0f0809749..2bb2542f24f 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -311,7 +311,7 @@ class GCodeViewer GLModel model; ColorRGBA color; InstanceVBuffer instances; - GLModel::InitializationData data; + GLModel::Geometry data; void reset(); }; @@ -374,7 +374,7 @@ class GCodeViewer } case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } case ERenderPrimitiveType::BatchedModel: { - return model.data.vertices_count() > 0 && model.data.indices_count() && + return !model.data.vertices.empty() && !model.data.indices.empty() && !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } default: { return false; } @@ -642,7 +642,7 @@ Range layer_duration_log; bool is_visible() const { return m_visible; } void set_visible(bool visible) { m_visible = visible; } - void render(int canvas_width, int canvas_height, const EViewType& view_type) const; + void render(int canvas_width, int canvas_height, const EViewType& view_type); void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; } void update_curr_move(const GCodeProcessorResult::MoveVertex move); @@ -709,7 +709,7 @@ Range layer_duration_log; std::vector gcode_ids; float m_scale = 1.0; bool m_show_gcode_window = false; - void render(const bool has_render_path, float legend_height, int canvas_width, int canvas_height, int right_margin, const EViewType& view_type) const; + void render(const bool has_render_path, float legend_height, int canvas_width, int canvas_height, int right_margin, const EViewType& view_type); }; struct ETools diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 96414746f24..10d21155e05 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -462,53 +462,48 @@ void GLCanvas3D::LayersEditing::render_curve(const Rect & bar_rect) const float scale_y = bar_rect.get_height() / m_object_max_z; const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x; - 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"); @@ -924,89 +919,51 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons m_perimeter.reset(); m_fill.reset(); if (!polygons.empty()) { - size_t triangles_count = 0; - for (const Polygon &poly : polygons) { triangles_count += poly.points.size() - 2; } - const size_t vertices_count = 3 * triangles_count; - if (m_render_fill) { - GLModel::InitializationData fill_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - entity.color = {0.8f, 0.8f, 1.0f, 0.5f}; - entity.positions.reserve(vertices_count); - entity.normals.reserve(vertices_count); - entity.indices.reserve(vertices_count); + GLModel::Geometry fill_data; + fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT }; + fill_data.color = { 0.8f, 0.8f, 1.0f, 0.5f }; + // vertices + indices const ExPolygons polygons_union = union_ex(polygons); - for (const ExPolygon &poly : polygons_union) { - const std::vector triangulation = triangulate_expolygon_3d(poly); - for (const Vec3d &v : triangulation) { - entity.positions.emplace_back(v.cast() + Vec3f(0.0f, 0.0f, 0.0125f)); // add a small positive z to avoid z-fighting - entity.normals.emplace_back(Vec3f::UnitZ()); - const size_t positions_count = entity.positions.size(); - if (positions_count % 3 == 0) { - entity.indices.emplace_back(positions_count - 3); - entity.indices.emplace_back(positions_count - 2); - entity.indices.emplace_back(positions_count - 1); - } + 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); } } - fill_data.entities.emplace_back(entity); - m_fill.init_from(fill_data); - } - - GLModel::InitializationData perimeter_data; - for (const Polygon &poly : polygons) { - GLModel::InitializationData::Entity ent; - ent.type = GLModel::PrimitiveType::LineLoop; - ent.positions.reserve(poly.points.size()); - ent.indices.reserve(poly.points.size()); - unsigned int id_count = 0; - for (const Point &p : poly.points) { - ent.positions.emplace_back(unscale(p.x()), unscale(p.y()), 0.025f); // add a small positive z to avoid z-fighting - ent.normals.emplace_back(Vec3f::UnitZ()); - ent.indices.emplace_back(id_count++); - } - - perimeter_data.entities.emplace_back(ent); + m_fill.init_from(std::move(fill_data)); } - m_perimeter.init_from(perimeter_data); + m_perimeter.init_from(polygons, 0.025f); // add a small positive z to avoid z-fighting } //BBS: add the height limit compute logic if (!height_polygons.empty()) { - size_t height_triangles_count = 0; - for (const auto &poly : height_polygons) { height_triangles_count += poly.first.points.size() - 2; } - const size_t height_vertices_count = 3 * height_triangles_count; - - GLModel::InitializationData height_fill_data; - GLModel::InitializationData::Entity height_entity; - height_entity.type = GLModel::PrimitiveType::Triangles; - height_entity.color = {0.8f, 0.8f, 1.0f, 0.5f}; - height_entity.positions.reserve(height_vertices_count); - height_entity.normals.reserve(height_vertices_count); - height_entity.indices.reserve(height_vertices_count); + GLModel::Geometry height_fill_data; + height_fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT }; + height_fill_data.color = {0.8f, 0.8f, 1.0f, 0.5f}; + // vertices + indices + unsigned int vertices_counter = 0; for (const auto &poly : height_polygons) { ExPolygon ex_poly(poly.first); const std::vector height_triangulation = triangulate_expolygon_3d(ex_poly); for (const Vec3d &v : height_triangulation) { - Vec3d point{v.x(), v.y(), poly.second}; - height_entity.positions.emplace_back(point.cast()); - height_entity.normals.emplace_back(Vec3f::UnitZ()); - const size_t height_positions_count = height_entity.positions.size(); - if (height_positions_count % 3 == 0) { - height_entity.indices.emplace_back(height_positions_count - 3); - height_entity.indices.emplace_back(height_positions_count - 2); - height_entity.indices.emplace_back(height_positions_count - 1); - } + Vec3f point{(float) v.x(), (float) v.y(), poly.second}; + height_fill_data.add_vertex(point); + ++vertices_counter; + if (vertices_counter % 3 == 0) + height_fill_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); } } - height_fill_data.entities.emplace_back(height_entity); - m_height_limit.init_from(height_fill_data); + m_height_limit.init_from(std::move(height_fill_data)); } } @@ -1015,7 +972,7 @@ void GLCanvas3D::SequentialPrintClearance::render() const ColorRGBA FILL_COLOR = { 0.7f, 0.7f, 1.0f, 0.5f }; const ColorRGBA NO_FILL_COLOR = { 0.75f, 0.75f, 0.75f, 0.75f }; - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + GLShaderProgram* shader = wxGetApp().get_shader("flat"); if (shader == nullptr) return; @@ -1026,11 +983,11 @@ void GLCanvas3D::SequentialPrintClearance::render() glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - m_perimeter.set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR); + m_perimeter.set_color(m_render_fill ? FILL_COLOR : NO_FILL_COLOR); m_perimeter.render(); m_fill.render(); //BBS: add height limit - m_height_limit.set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR); + m_height_limit.set_color(m_render_fill ? FILL_COLOR : NO_FILL_COLOR); m_height_limit.render(); glsafe(::glDisable(GL_BLEND)); diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index fa804efc2f3..affd4cc8616 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -17,126 +17,414 @@ namespace Slic3r { namespace GUI { -size_t GLModel::InitializationData::vertices_count() const +void GLModel::Geometry::add_vertex(const Vec2f& position) { - size_t ret = 0; - for (const Entity& entity : entities) { - ret += entity.positions.size(); + 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; } - return ret; + indices.resize(indices.size() + sizeof(unsigned short)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id, sizeof(unsigned short)); } -size_t GLModel::InitializationData::indices_count() const +void GLModel::Geometry::add_uint_index(unsigned int id) { - size_t ret = 0; - for (const Entity& entity : entities) { - ret += entity.indices.size(); + if (format.index_type != EIndexType::UINT) { + assert(false); + return; } - return ret; + indices.resize(indices.size() + sizeof(unsigned int)); + ::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id, sizeof(unsigned int)); } -void GLModel::init_from(const InitializationData& data) +void GLModel::Geometry::add_ushort_line(unsigned short id1, unsigned short id2) { - if (!m_render_data.empty()) // call reset() if you want to reuse this model + 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)); +} - for (const InitializationData::Entity& entity : data.entities) { - if (entity.positions.empty() || entity.indices.empty()) - continue; +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)); +} - assert(entity.normals.empty() || entity.normals.size() == entity.positions.size()); +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)); +} - RenderData rdata; - rdata.type = entity.type; - rdata.color = entity.color; +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)); +} - // vertices/normals data - std::vector vertices(6 * entity.positions.size()); - for (size_t i = 0; i < entity.positions.size(); ++i) { - const size_t offset = i * 6; - ::memcpy(static_cast(&vertices[offset]), static_cast(entity.positions[i].data()), 3 * sizeof(float)); - if (!entity.normals.empty()) - ::memcpy(static_cast(&vertices[3 + offset]), static_cast(entity.normals[i].data()), 3 * sizeof(float)); - } +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 }; + } - // indices data - std::vector indices = entity.indices; + if (vertices_count() <= id) { + assert(false); + return { FLT_MAX, FLT_MAX }; + } - rdata.indices_count = static_cast(indices.size()); + const float* start = &vertices[id * vertex_stride_floats(format) + position_offset_floats(format)]; + return { *(start + 0), *(start + 1) }; +} - // update bounding box - for (size_t i = 0; i < entity.positions.size(); ++i) { - m_bounding_box.merge(entity.positions[i].cast()); - } +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 }; + } - send_to_gpu(rdata, vertices, indices); - m_render_data.emplace_back(rdata); + 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) }; } -void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bbox) +Vec3f GLModel::Geometry::extract_normal_3(size_t id) const { - if (!m_render_data.empty()) // call reset() if you want to reuse this model - return; + const size_t n_stride = normal_stride_floats(format); + if (n_stride != 3) { + assert(false); + return { FLT_MAX, FLT_MAX, FLT_MAX }; + } - RenderData data; - data.type = PrimitiveType::Triangles; + if (vertices_count() <= id) { + assert(false); + return { FLT_MAX, FLT_MAX, FLT_MAX }; + } - std::vector vertices = std::vector(18 * its.indices.size()); - std::vector indices = std::vector(3 * its.indices.size()); + const float* start = &vertices[id * vertex_stride_floats(format) + normal_offset_floats(format)]; + return { *(start + 0), *(start + 1), *(start + 2) }; +} - unsigned int vertices_count = 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) { - size_t offset = i * 18 + j * 6; - ::memcpy(static_cast(&vertices[offset]), static_cast(vertex[j].data()), 3 * sizeof(float)); - ::memcpy(static_cast(&vertices[3 + offset]), static_cast(n.data()), 3 * sizeof(float)); - } - for (size_t j = 0; j < 3; ++j) - indices[i * 3 + j] = vertices_count + j; - vertices_count += 3; +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; } + }; +} + +void GLModel::init_from(Geometry&& data) +{ + if (is_initialized()) // call reset() if you want to reuse this model + return; + + if (data.vertices.empty() || data.indices.empty()) { + assert(false); + return; } - data.indices_count = static_cast(indices.size()); - m_bounding_box = bbox; + m_render_data.geometry = std::move(data); - send_to_gpu(data, vertices, indices); - m_render_data.emplace_back(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()); + } + } } void GLModel::init_from(const indexed_triangle_set& its) { - this->init_from(its, bounding_box(its)); + 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()); + } } void GLModel::init_from(const Polygons& polygons, float z) { - auto append_polygon = [](const Polygon& polygon, float z, GUI::GLModel::InitializationData& data) { - if (!polygon.empty()) { - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::GLModel::PrimitiveType::LineLoop; - // contour - entity.positions.reserve(polygon.size() + 1); - entity.indices.reserve(polygon.size() + 1); - unsigned int id = 0; - for (const Point& p : polygon) { - Vec3f position = unscale(p.x(), p.y(), 0.0).cast(); - position.z() = z; - entity.positions.emplace_back(position); - entity.indices.emplace_back(id++); - } - data.entities.emplace_back(entity); - } - }; + if (is_initialized()) // call reset() if you want to reuse this model + return; + + if (polygons.empty()) { + assert(false); + return; + } - InitializationData init_data; + 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) { - append_polygon(polygon, z, init_data); + 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()); } - init_from(init_data); } bool GLModel::init_from_file(const std::string& filename) @@ -148,206 +436,252 @@ 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(); - init_from(mesh.its, mesh.bounding_box()); + const TriangleMesh mesh = model.mesh(); + init_from(mesh.its); m_filename = filename; return true; } -void GLModel::set_color(int entity_id, const ColorRGBA& color) +void GLModel::reset() { - for (size_t i = 0; i < m_render_data.size(); ++i) { - if (entity_id == -1 || static_cast(i) == entity_id) - m_render_data[i].color = color; + // 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(); + m_bounding_box = BoundingBoxf3(); + m_filename = std::string(); } -void GLModel::reset() +static GLenum get_primitive_mode(const GLModel::Geometry::Format& format) { - for (RenderData& data : m_render_data) { - // release gpu memory - if (data.ibo_id > 0) - glsafe(::glDeleteBuffers(1, &data.ibo_id)); - if (data.vbo_id > 0) - glsafe(::glDeleteBuffers(1, &data.vbo_id)); + 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; } } +} - m_render_data.clear(); - m_bounding_box = BoundingBoxf3(); - m_filename = std::string(); +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() const +void GLModel::render() { GLShaderProgram* shader = wxGetApp().get_current_shader(); - for (const RenderData& data : m_render_data) { - if (data.vbo_id == 0 || data.ibo_id == 0) - continue; - - GLenum mode; - 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; } - } + 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); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)0)); - glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + 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)); + } - if (shader != nullptr) - shader->set_uniform("uniform_color", data.color); - else - glsafe(::glColor4fv(data.color.data())); + shader->set_uniform("uniform_color", data.color); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id)); - glsafe(::glDrawElements(mode, static_cast(data.indices_count), GL_UNSIGNED_INT, (const void*)0)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + 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)); - } + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const +void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) { if (instances_vbo == 0) return; GLShaderProgram* shader = wxGetApp().get_current_shader(); - assert(shader == nullptr || boost::algorithm::iends_with(shader->get_name(), "_instanced")); + if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced")) + return; // vertex attributes - GLint position_id = (shader != nullptr) ? shader->get_attrib_location("v_position") : -1; - GLint normal_id = (shader != nullptr) ? shader->get_attrib_location("v_normal") : -1; - assert(position_id != -1 && normal_id != -1); + 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 != 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); + 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; + } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instances_vbo)); - if (offset_id != -1) { - glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0)); - glsafe(::glEnableVertexAttribArray(offset_id)); - glsafe(::glVertexAttribDivisor(offset_id, 1)); - } - if (scales_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)); - } - - for (const RenderData& data : m_render_data) { - if (data.vbo_id == 0 || data.ibo_id == 0) - continue; - - GLenum mode; - 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; } - } + glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0)); + glsafe(::glEnableVertexAttribArray(offset_id)); + glsafe(::glVertexAttribDivisor(offset_id, 1)); - if (shader != nullptr) - shader->set_uniform("uniform_color", data.color); - else - glsafe(::glColor4fv(data.color.data())); + 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)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); - if (position_id != -1) { - glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)0)); - glsafe(::glEnableVertexAttribArray(position_id)); - } - if (normal_id != -1) { - glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)(3 * sizeof(float)))); - glsafe(::glEnableVertexAttribArray(normal_id)); - } + 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_ELEMENT_ARRAY_BUFFER, data.ibo_id)); - glsafe(::glDrawElementsInstanced(mode, static_cast(data.indices_count), GL_UNSIGNED_INT, (const void*)0, instances_count)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); - if (normal_id != -1) - glsafe(::glDisableVertexAttribArray(normal_id)); - if (position_id != -1) - glsafe(::glDisableVertexAttribArray(position_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 (scales_id != -1) - glsafe(::glDisableVertexAttribArray(scales_id)); - if (offset_id != -1) - glsafe(::glDisableVertexAttribArray(offset_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)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -void GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices) +bool GLModel::send_to_gpu() { - assert(data.vbo_id == 0); - assert(data.ibo_id == 0); + 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; + } - // vertex data -> send to gpu - glsafe(::glGenBuffers(1, &data.vbo_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW)); + // 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 data -> send to gpu - glsafe(::glGenBuffers(1, &data.ibo_id)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id)); - glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW)); + // 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; } -GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height) +static void append_vertex(GLModel::Geometry& data, const Vec3f& position, const Vec3f& normal) { - auto append_vertex = [](GLModel::InitializationData::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) { - entity.indices.emplace_back(v1); - entity.indices.emplace_back(v2); - entity.indices.emplace_back(v3); - }; + data.add_vertex(position, normal); +} - resolution = std::max(4, resolution); +static void append_triangle(GLModel::Geometry& data, unsigned short v1, unsigned short v2, unsigned short v3) +{ + data.add_ushort_index(v1); + data.add_ushort_index(v2); + data.add_ushort_index(v3); +} +GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height) +{ + resolution = std::max(4, resolution); + resolution = std::min(10922, resolution); // ensure no unsigned short overflow of indices - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; + GLModel::Geometry data; + 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)); - const float angle_step = 2.0f * M_PI / static_cast(resolution); + 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); } @@ -355,86 +689,76 @@ GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, flo const float total_height = tip_height + stem_height; // tip vertices/normals - 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 }); + 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 (int i = 0; i < resolution; ++i) { - const int v3 = (i < resolution - 1) ? i + 2 : 1; - append_indices(entity, 0, i + 1, v3); + 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 (int i = 0; i < resolution; ++i) { - append_vertex(entity, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ()); + 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 (int i = 0; i < resolution; ++i) { - append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ()); + 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 (int i = 0; i < resolution; ++i) { - const int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1; - const int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1; - append_indices(entity, i + resolution + 1, v3, v2); - append_indices(entity, i + resolution + 1, i + 2 * resolution + 1, v3); + 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 (int i = 0; i < resolution; ++i) { - append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f }); + 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 (int i = 0; i < resolution; ++i) { - append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f }); + 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 (int i = 0; i < resolution; ++i) { - const int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1; - const int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1; - append_indices(entity, i + 3 * resolution + 1, v3, v2); - append_indices(entity, i + 3 * resolution + 1, i + 4 * resolution + 1, v3); + 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(entity, Vec3f::Zero(), -Vec3f::UnitZ()); - for (int i = 0; i < resolution; ++i) { - append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ()); + 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 (int i = 0; i < resolution; ++i) { - const int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2; - append_indices(entity, 5 * resolution + 1, v3, i + 5 * resolution + 2); + 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); } - - data.entities.emplace_back(entity); 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) { - 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) { - entity.indices.emplace_back(v1); - entity.indices.emplace_back(v2); - entity.indices.emplace_back(v3); - }; + resolution = std::max(2, resolution); + resolution = std::min(8188, resolution); // ensure no unsigned short overflow of indices - resolution = std::max(2, resolution); - - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; + GLModel::Geometry data; + 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)); const float half_thickness = 0.5f * thickness; const float half_stem_width = 0.5f * stem_width; @@ -442,171 +766,160 @@ 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); // tip // top face vertices - append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { -tip_height, radius, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitZ()); + 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_indices(entity, 0, 1, 2); - append_indices(entity, 0, 2, 4); - append_indices(entity, 4, 2, 3); + append_triangle(data, 0, 1, 2); + append_triangle(data, 0, 2, 4); + append_triangle(data, 4, 2, 3); // bottom face vertices - append_vertex(entity, { 0.0f, outer_radius, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { -tip_height, radius, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { 0.0f, inner_radius, -half_thickness }, -Vec3f::UnitZ()); + 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_indices(entity, 5, 7, 6); - append_indices(entity, 5, 9, 7); - append_indices(entity, 9, 8, 7); + append_triangle(data, 5, 7, 6); + append_triangle(data, 5, 9, 7); + append_triangle(data, 9, 8, 7); // side faces vertices - append_vertex(entity, { 0.0f, outer_radius, -half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 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()); + 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(entity, { 0.0f, radius + half_tip_width, -half_thickness }, normal); - append_vertex(entity, { -tip_height, radius, -half_thickness }, normal); - append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, normal); - append_vertex(entity, { -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, { -tip_height, radius, half_thickness }, normal); - normal = Vec3f(-half_tip_width, -tip_height, 0.0f); + normal = { -half_tip_width, -tip_height, 0.0f }; normal.normalize(); - append_vertex(entity, { -tip_height, radius, -half_thickness }, normal); - append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, normal); - append_vertex(entity, { -tip_height, radius, half_thickness }, normal); - append_vertex(entity, { 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); + append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, normal); - append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 0.0f, inner_radius, -half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 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()); + 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 (int i = 0; i < 4; ++i) { - const int ii = i * 4; - append_indices(entity, 10 + ii, 11 + ii, 13 + ii); - append_indices(entity, 10 + ii, 13 + ii, 12 + ii); + 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 (int i = 0; i <= resolution; ++i) { - const float angle = static_cast(i) * step_angle; - append_vertex(entity, { 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, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ()); } - for (int i = 0; i <= resolution; ++i) { - const float angle = static_cast(i) * step_angle; - append_vertex(entity, { outer_radius * ::sin(angle), outer_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 (int i = 0; i < resolution; ++i) { - append_indices(entity, 26 + i, 27 + i, 27 + resolution + i); - append_indices(entity, 27 + i, 28 + resolution + i, 27 + resolution + i); + 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 (int i = 0; i <= resolution; ++i) { - const float angle = static_cast(i) * step_angle; - append_vertex(entity, { 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, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ()); } - for (int i = 0; i <= resolution; ++i) { - const float angle = static_cast(i) * step_angle; - append_vertex(entity, { outer_radius * ::sin(angle), outer_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 (int i = 0; i < resolution; ++i) { - append_indices(entity, 28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i); - append_indices(entity, 29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i); + 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 (int i = 0; i <= resolution; ++i) { - const float angle = static_cast(i) * step_angle; + 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(entity, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f }); + append_vertex(data, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f }); } - for (int i = 0; i <= resolution; ++i) { - const float angle = static_cast(i) * step_angle; + 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(entity, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f }); + append_vertex(data, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f }); } - int first_id = 26 + 4 * (resolution + 1); - for (int i = 0; i < resolution; ++i) { - const int ii = first_id + i; - append_indices(entity, ii, ii + 1, ii + resolution + 2); - append_indices(entity, ii, ii + resolution + 2, ii + resolution + 1); + 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(entity, { inner_radius, 0.0f, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { outer_radius, 0.0f, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { inner_radius, 0.0f, half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { 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()); + 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_indices(entity, first_id, first_id + 1, first_id + 3); - append_indices(entity, first_id, first_id + 3, first_id + 2); + append_triangle(data, first_id, first_id + 1, first_id + 3); + append_triangle(data, first_id, first_id + 3, first_id + 2); - for (int i = resolution; i >= 0; --i) { - const float angle = static_cast(i) * step_angle; + 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(entity, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f }); + append_vertex(data, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f }); } - for (int i = resolution; i >= 0; --i) { - const float angle = static_cast(i) * step_angle; + 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(entity, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f }); + append_vertex(data, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f }); } first_id = 30 + 6 * (resolution + 1); - for (int i = 0; i < resolution; ++i) { - const int ii = first_id + i; - append_indices(entity, ii, ii + 1, ii + resolution + 2); - append_indices(entity, ii, ii + resolution + 2, ii + 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); } - - data.entities.emplace_back(entity); 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) { - 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) { - 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; + GLModel::Geometry data; + 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)); const float half_thickness = 0.5f * thickness; const float half_stem_width = 0.5f * stem_width; @@ -614,133 +927,121 @@ GLModel::InitializationData straight_arrow(float tip_width, float tip_height, fl const float total_height = tip_height + stem_height; // 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()); - append_vertex(entity, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { 0.0, total_height, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ()); - append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ()); + 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_indices(entity, 0, 1, 6); - append_indices(entity, 6, 1, 5); - append_indices(entity, 4, 5, 3); - append_indices(entity, 5, 1, 3); - append_indices(entity, 1, 2, 3); + 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(entity, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { 0.0, total_height, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); - append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ()); + 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_indices(entity, 7, 13, 8); - append_indices(entity, 13, 12, 8); - append_indices(entity, 12, 11, 10); - append_indices(entity, 8, 12, 10); - append_indices(entity, 9, 8, 10); + 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(entity, { half_stem_width, 0.0, -half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { 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, stem_height, half_thickness }, Vec3f::UnitX()); - append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { 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_tip_width, stem_height, half_thickness }, -Vec3f::UnitY()); Vec3f normal(tip_height, half_tip_width, 0.0f); normal.normalize(); - append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, normal); - append_vertex(entity, { 0.0, total_height, -half_thickness }, normal); - append_vertex(entity, { half_tip_width, stem_height, half_thickness }, normal); - append_vertex(entity, { 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, { 0.0, total_height, half_thickness }, normal); - normal = Vec3f(-tip_height, half_tip_width, 0.0f); + normal = { -tip_height, half_tip_width, 0.0f }; normal.normalize(); - append_vertex(entity, { 0.0, total_height, -half_thickness }, normal); - append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, normal); - append_vertex(entity, { 0.0, total_height, half_thickness }, normal); - append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, normal); - - append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY()); - - append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitX()); - append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitX()); - append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitX()); - append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitX()); - - append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY()); - append_vertex(entity, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY()); + 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 (int i = 0; i < 7; ++i) { - const int ii = i * 4; - append_indices(entity, 14 + ii, 15 + ii, 17 + ii); - append_indices(entity, 14 + ii, 17 + ii, 16 + ii); + 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); } - - data.entities.emplace_back(entity); return data; } -GLModel::InitializationData diamond(int resolution) +GLModel::Geometry diamond(unsigned short resolution) { - resolution = std::max(4, resolution); + resolution = std::max(4, resolution); + resolution = std::min(65534, resolution); // ensure no unsigned short overflow of indices - GLModel::InitializationData data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; + GLModel::Geometry data; + 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)); const float step = 2.0f * float(PI) / float(resolution); - // positions - for (int i = 0; i < resolution; ++i) { + // vertices + for (unsigned short i = 0; i < resolution; ++i) { float ii = float(i) * step; - entity.positions.emplace_back(0.5f * ::cos(ii), 0.5f * ::sin(ii), 0.0f); - } - entity.positions.emplace_back(0.0f, 0.0f, 0.5f); - entity.positions.emplace_back(0.0f, 0.0f, -0.5f); - - // normals - for (const Vec3f& v : entity.positions) { - entity.normals.emplace_back(v.normalized()); + 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 (int i = 0; i < resolution; ++i) { - entity.indices.push_back(i + 0); - entity.indices.push_back(i + 1); - entity.indices.push_back(resolution); + for (unsigned short i = 0; i < resolution; ++i) { + append_triangle(data, i + 0, i + 1, resolution); } - entity.indices.push_back(resolution - 1); - entity.indices.push_back(0); - entity.indices.push_back(resolution); + append_triangle(data, resolution - 1, 0, resolution); // bottom - for (int i = 0; i < resolution; ++i) { - entity.indices.push_back(i + 0); - entity.indices.push_back(resolution + 1); - entity.indices.push_back(i + 1); + for (unsigned short i = 0; i < resolution; ++i) { + append_triangle(data, i + 0, resolution + 1, i + 1); } - entity.indices.push_back(resolution - 1); - entity.indices.push_back(resolution + 1); - entity.indices.push_back(0); - - data.entities.emplace_back(entity); + append_triangle(data, resolution - 1, resolution + 1, 0); return data; } diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 62722b18cf2..3b1d20cea16 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -20,46 +20,108 @@ namespace GUI { class GLModel { public: - enum class PrimitiveType : unsigned char + struct Geometry { - Triangles, - Lines, - LineStrip, - LineLoop - }; + enum class EPrimitiveType : unsigned char + { + Points, + Triangles, + TriangleStrip, + TriangleFan, + Lines, + LineStrip, + LineLoop + }; - struct RenderData - { - PrimitiveType type; - unsigned int vbo_id{ 0 }; - unsigned int ibo_id{ 0 }; - size_t indices_count{ 0 }; - ColorRGBA color; - }; + 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 + }; - struct InitializationData - { - struct Entity + enum class EIndexType : unsigned char { - PrimitiveType type; - std::vector positions; - std::vector normals; - std::vector indices; - ColorRGBA color; + UINT, // unsigned int + USHORT // unsigned short }; - std::vector entities; + 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); - size_t vertices_count() const; - size_t vertices_size_floats() const { return vertices_count() * 6; } - size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } + 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); - size_t indices_count() const; - size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); } + 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); }; + struct RenderData + { + Geometry geometry; + unsigned int vbo_id{ 0 }; + unsigned int ibo_id{ 0 }; + size_t vertices_count{ 0 }; + size_t indices_count{ 0 }; + }; private: - std::vector m_render_data; + RenderData m_render_data; BoundingBoxf3 m_bounding_box; std::string m_filename; @@ -68,50 +130,59 @@ namespace GUI { GLModel() = default; virtual ~GLModel() { reset(); } - void init_from(const InitializationData& data); - void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox); + 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); 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 entity_id == -1 set the color of all entities - void set_color(int entity_id, const ColorRGBA& color); + void set_color(const ColorRGBA& color) { m_render_data.geometry.color = color; } + const ColorRGBA& get_color() const { return m_render_data.geometry.color; } void reset(); - void render() const; - void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; + void render(); + void render_instanced(unsigned int instances_vbo, unsigned int instances_count); - bool is_initialized() const { return !m_render_data.empty(); } + bool is_initialized() const { return vertices_count() > 0 && indices_count() > 0; } const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; } const std::string& get_filename() const { return m_filename; } private: - void send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices); + bool send_to_gpu(); }; // 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 30b7888c537..9ae15bbe8e1 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -80,17 +80,17 @@ 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)); glsafe(::glDisable(GL_DEPTH_TEST)); @@ -100,7 +100,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)); @@ -116,34 +116,28 @@ 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(0.0f, 1.0f, 0.38f, 1.0f); - m_rectangle.set_color(-1, color); + const ColorRGBA color(0.0f, 1.0f, 0.38f, 1.0f); + m_rectangle.set_color(color); m_rectangle.render(); shader->stop_using(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index bc1ff411a15..47b3a55ad38 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -27,30 +27,12 @@ const int c_connectors_group_id = 4; const float UndefFloat = -999.f; // connector colors - -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}; } -static const ColorRGBA YELLOW() { return {1.0f, 1.0f, 0.0f, 1.0f}; } -static const ColorRGBA WHITE() { return {1.0f, 1.0f, 1.0f, 1.0f}; } - -static const ColorRGBA PLAG_COLOR = YELLOW(); -static const ColorRGBA DOWEL_COLOR = DARK_YELLOW(); -static const ColorRGBA HOVERED_PLAG_COLOR = CYAN(); +static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW(); +static const ColorRGBA DOWEL_COLOR = ColorRGBA::DARK_YELLOW(); +static const ColorRGBA HOVERED_PLAG_COLOR = ColorRGBA::CYAN(); static const ColorRGBA HOVERED_DOWEL_COLOR = {0.0f, 0.5f, 0.5f, 1.0f}; -static const ColorRGBA SELECTED_PLAG_COLOR = GRAY(); -static const ColorRGBA SELECTED_DOWEL_COLOR = GRAY(); // DARK_GRAY(); +static const ColorRGBA SELECTED_PLAG_COLOR = ColorRGBA::GRAY(); +static const ColorRGBA SELECTED_DOWEL_COLOR = ColorRGBA::GRAY(); // DARK_GRAY(); static const ColorRGBA CONNECTOR_DEF_COLOR = {1.0f, 1.0f, 1.0f, 0.5f}; static const ColorRGBA CONNECTOR_ERR_COLOR = {1.0f, 0.3f, 0.3f, 0.5f}; static const ColorRGBA HOVERED_ERR_COLOR = {1.0f, 0.3f, 0.3f, 1.0f}; @@ -516,6 +498,8 @@ void GLGizmoAdvancedCut::on_render_for_picking() glsafe(::glDisable(GL_DEPTH_TEST)); + glsafe(::glPushMatrix()); + BoundingBoxf3 box = m_parent.get_selection().get_bounding_box(); #if ENABLE_FIXED_GRABBER float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); @@ -523,8 +507,17 @@ void GLGizmoAdvancedCut::on_render_for_picking() float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); #endif - m_move_grabber.color = picking_color_component(0); - m_move_grabber.render_for_picking(mean_size); + m_move_grabber.color = picking_color_component(0); + GLShaderProgram *shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); + + m_move_grabber.render_for_picking(mean_size); + + shader->stop_using(); + } + + glsafe(::glPopMatrix()); glsafe(::glEnable(GL_DEPTH_TEST)); auto inst_id = m_c->selection_info()->get_active_instance(); @@ -876,67 +869,112 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() point += object_offset; } - // draw plane glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + + GLShaderProgram *shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); - ::glBegin(GL_QUADS); - ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); - for (const Vec3d& point : plane_points_rot) { - ::glVertex3f(point(0), point(1), point(2)); - } - glsafe(::glEnd()); + // draw plane + { + m_plane.reset(); - glsafe(::glEnable(GL_CULL_FACE)); - glsafe(::glDisable(GL_BLEND)); + 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)); - // Draw the grabber and the connecting line - Vec3d plane_center_rot = calc_plane_center(plane_points_rot); - m_move_grabber.center = plane_center_rot + plane_normal_rot * Offset; - // m_move_grabber.angles = m_current_base_rotation + m_rotation; + // vertices + for (const Vec3d &point : plane_points_rot) { + init_data.add_vertex((Vec3f)point.cast()); + } - glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); - glsafe(::glColor3f(1.0, 1.0, 0.0)); - glLineStipple(1, 0x0FFF); - glEnable(GL_LINE_STIPPLE); - ::glBegin(GL_LINES); - ::glVertex3dv(plane_center_rot.data()); - ::glVertex3dv(m_move_grabber.center.data()); - glsafe(::glEnd()); - glDisable(GL_LINE_STIPPLE); + // indices + init_data.add_ushort_triangle(0, 1, 2); + init_data.add_ushort_triangle(2, 3, 0); - // std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_move_grabber.color); - // m_move_grabber.color = GrabberColor; - // m_move_grabber.hover_color = GrabberHoverColor; - // m_move_grabber.render(m_hover_id == get_group_id(), (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0)); - bool hover = (m_hover_id == get_group_id()); - ColorRGBA render_color; - if (hover) { - render_color = GrabberHoverColor; - } - else - render_color = GrabberColor; + m_plane.init_from(std::move(init_data)); + } + m_plane.render(); + + glsafe(::glEnable(GL_CULL_FACE)); + glsafe(::glDisable(GL_BLEND)); + + // Draw the grabber and the connecting line + Vec3d plane_center_rot = calc_plane_center(plane_points_rot); + m_move_grabber.center = plane_center_rot + plane_normal_rot * Offset; + // m_move_grabber.angles = m_current_base_rotation + m_rotation; + + { + m_grabber_connection.reset(); + + 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)); + + // vertices + init_data.add_vertex((Vec3f)plane_center_rot.cast()); + init_data.add_vertex((Vec3f)m_move_grabber.center.cast()); - const GLModel &cube = m_move_grabber.get_cube(); - // BBS set to fixed size grabber - // float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); - float fullsize = 8.0f; - if (GLGizmoBase::INV_ZOOM > 0) { - fullsize = m_move_grabber.FixedGrabberSize * GLGizmoBase::INV_ZOOM; + // indices + init_data.add_ushort_line(0, 1); + + m_grabber_connection.init_from(std::move(init_data)); + } + + glsafe(::glDisable(GL_DEPTH_TEST)); + glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); + glLineStipple(1, 0x0FFF); + glEnable(GL_LINE_STIPPLE); + m_grabber_connection.render(); + glDisable(GL_LINE_STIPPLE); + + shader->stop_using(); } - const_cast(&cube)->set_color(-1, render_color); + { + GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light"); + if (shader == nullptr) + return; + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); + // std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_move_grabber.color); + // m_move_grabber.color = GrabberColor; + // m_move_grabber.hover_color = GrabberHoverColor; + // m_move_grabber.render(m_hover_id == get_group_id(), (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0)); + bool hover = (m_hover_id == get_group_id()); + ColorRGBA render_color; + if (hover) { + render_color = GrabberHoverColor; + } + else + render_color = GrabberColor; + + GLModel &cube = m_move_grabber.get_cube(); + // BBS set to fixed size grabber + // float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); + float fullsize = 8.0f; + if (GLGizmoBase::INV_ZOOM > 0) { + fullsize = m_move_grabber.FixedGrabberSize * GLGizmoBase::INV_ZOOM; + } - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_move_grabber.center.x(), m_move_grabber.center.y(), m_move_grabber.center.z())); - glsafe(::glMultMatrixd(m_rotate_matrix.data())); + cube.set_color(render_color); - glsafe(::glScaled(fullsize, fullsize, fullsize)); - cube.render(); - glsafe(::glPopMatrix()); + glsafe(::glPushMatrix()); + glsafe(::glTranslated(m_move_grabber.center.x(), m_move_grabber.center.y(), m_move_grabber.center.z())); + glsafe(::glMultMatrixd(m_rotate_matrix.data())); + + glsafe(::glScaled(fullsize, fullsize, fullsize)); + cube.render(); + glsafe(::glPopMatrix()); + shader->stop_using(); + } // Should be placed at last, because GLGizmoRotate3D clears depth buffer set_center(m_cut_plane_center); @@ -1043,7 +1081,7 @@ void GLGizmoAdvancedCut::render_connector_model(GLModel &model, const ColorRGBA glsafe(::glMultMatrixd(view_model_matrix.data())); - model.set_color(-1, color); + model.set_color(color); model.render(); shader->stop_using(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp index 38abb30c3fe..c381dffff02 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp @@ -53,6 +53,8 @@ struct Rotate_data { bool m_place_on_cut_lower{false}; bool m_rotate_upper{false}; bool m_rotate_lower{false}; + GLModel m_plane; + GLModel m_grabber_connection; bool m_do_segment; double m_segment_smoothing_alpha; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 588e8ce58b8..32308233cac 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -68,26 +68,9 @@ void GLGizmoBase::load_render_colors() RenderColor::colors[RenderCol_Flatten_Plane_Hover] = ImGuiWrapper::to_ImVec4(GLGizmoBase::FLATTEN_HOVER_COLOR); } -GLGizmoBase::Grabber::Grabber() - : center(Vec3d::Zero()) - , angles(Vec3d::Zero()) - , dragging(false) - , enabled(true) +void GLGizmoBase::Grabber::render(bool hover, float size) { - color = GRABBER_NORMAL_COL; - hover_color = GRABBER_HOVER_COL; -} - -void GLGizmoBase::Grabber::render(bool hover, float size) const -{ - ColorRGBA render_color; - if (hover) { - render_color = hover_color; - } - else - render_color = color; - - render(size, render_color, false); + render(size, hover ? hover_color : color, false); } float GLGizmoBase::Grabber::get_half_size(float size) const @@ -100,28 +83,26 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const return get_half_size(size) * DraggingScaleFactor; } -const GLModel& GLGizmoBase::Grabber::get_cube() const +GLModel& GLGizmoBase::Grabber::get_cube() { - if (! cube_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 } }); - const_cast(cube_initialized) = true; + indexed_triangle_set its = its_make_cube(1., 1., 1.); + its_translate(its, Vec3f(-0.5, -0.5, -0.5)); + m_cube.init_from(its); } - return cube; + return m_cube; } -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_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 } }); - const_cast(cube_initialized) = true; + indexed_triangle_set its = its_make_cube(1., 1., 1.); + its_translate(its, Vec3f(-0.5, -0.5, -0.5)); + m_cube.init_from(its); } //BBS set to fixed size grabber @@ -132,7 +113,7 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo } - const_cast(&cube)->set_color(-1, render_color); + m_cube.set_color(render_color); glsafe(::glPushMatrix()); glsafe(::glTranslated(center.x(), center.y(), center.z())); @@ -140,11 +121,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) @@ -292,17 +272,23 @@ void GLGizmoBase::render_grabbers(float size) const void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); + #if ENABLE_FIXED_GRABBER - float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); + const float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); #else - float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); + const float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); #endif - 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); + 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); + } } + shader->stop_using(); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index a858954b471..b2b8c4626e8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -64,27 +64,26 @@ class GLGizmoBase static const float FixedGrabberSize; static const float FixedRadiusSize; - Vec3d center; - Vec3d angles; - ColorRGBA color; - ColorRGBA hover_color; - bool enabled; - bool dragging; + bool enabled{ true }; + bool dragging{ false }; + Vec3d center{ Vec3d::Zero() }; + Vec3d angles{ Vec3d::Zero() }; + ColorRGBA color{GRABBER_NORMAL_COL}; + ColorRGBA hover_color{GRABBER_HOVER_COL}; - 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; - const GLModel& get_cube() const; + GLModel& get_cube(); private: - void render(float size, const ColorRGBA& render_color, bool picking) const; + void render(float size, const ColorRGBA& render_color, bool picking); - GLModel cube; - bool cube_initialized = false; + GLModel m_cube; }; public: diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 8f73379e71c..c8514ed103c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -20,7 +20,6 @@ namespace GUI { GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) { - m_vbo_cylinder.init_from(its_make_cylinder(1., 1.)); } @@ -63,6 +62,9 @@ void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&) void GLGizmoHollow::on_render() { + if (!m_cylinder.is_initialized()) + m_cylinder.init_from(its_make_cylinder(1.0, 1.0)); + const Selection& selection = m_parent.get_selection(); const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info(); @@ -99,12 +101,14 @@ 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) { - GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light"); - if (shader) - shader->start_using(); - ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + 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(); }); 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(); @@ -126,28 +130,25 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons continue; // First decide about the color of the point. - if (picking) { + if (picking) render_color = picking_color_component(i); - } else { - if (size_t(m_hover_id) == i) { - render_color = {0.f, 1.f, 1.f, 1.f}; - } + if (size_t(m_hover_id) == i) + 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.f, 0.f, 0.f, .5f}; + render_color = { 1.0f, 0.0f, 0.0f, 0.5f }; } - else { // neigher hover nor picking + 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); - } } - const_cast(&m_vbo_cylinder)->set_color(-1, render_color); + m_cylinder.set_color(render_color); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. glsafe(::glPushMatrix()); - glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2))); + glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z())); glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); if (vol->is_left_handed()) @@ -155,13 +156,13 @@ 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)); - m_vbo_cylinder.render(); + m_cylinder.render(); glsafe(::glPopMatrix()); if (vol->is_left_handed()) @@ -172,8 +173,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 2cf08de2a0a..fa89e0febc2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -42,13 +42,14 @@ 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; ObjectID m_old_mo_id = -1; - GLModel m_vbo_cylinder; + GLModel m_cylinder; + float m_new_hole_radius = 2.f; // Size of a new hole. float m_new_hole_height = 6.f; mutable std::vector m_selected; // which holes are currently selected diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 483c833d742..e7c861cb02d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -25,9 +25,7 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam : GLGizmoBase(parent, icon_filename, sprite_id) //BBS: GUI refactor: add obj manipulation , m_object_manipulation(obj_manipulation) -{ - m_vbo_cone.init_from(its_make_cone(1., 1., 2*PI/36)); -} +{} std::string GLGizmoMove3D::get_tooltip() const { @@ -95,6 +93,9 @@ void GLGizmoMove3D::on_update(const UpdateData& data) void GLGizmoMove3D::on_render() { + if (!m_cone.is_initialized()) + m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0)); + const Selection& selection = m_parent.get_selection(); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); @@ -138,25 +139,20 @@ void GLGizmoMove3D::on_render() m_grabber_connections[id].old_center = center; m_grabber_connections[id].model.reset(); - GLModel::InitializationData init_data; - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::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()); - } - - entity.indices.reserve(2); - entity.indices.emplace_back(0); - entity.indices.emplace_back(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]); + 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()); + + // indices + init_data.add_ushort_line(0, 1); + + m_grabber_connections[id].model.init_from(std::move(init_data)); } glLineStipple(1, 0x0FFF); @@ -241,7 +237,7 @@ 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) { #if ENABLE_FIXED_GRABBER float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); @@ -258,15 +254,13 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box } } - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); if (shader == nullptr) return; - const_cast(&m_vbo_cone)->set_color(-1, color); - if (!picking) { - shader->start_using(); - shader->set_uniform("emission_factor", 0.1f); - } + m_cone.set_color(color); + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); glsafe(::glPushMatrix()); glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z())); @@ -277,11 +271,10 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box //glsafe(::glTranslated(0.0, 0.0, 2.0 * size)); glsafe(::glScaled(0.75 * size, 0.75 * size, 2.0 * size)); - m_vbo_cone.render(); + m_cone.render(); glsafe(::glPopMatrix()); - if (! picking) - shader->stop_using(); + shader->stop_using(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index 70ae525f78c..f4cc4f6c74c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -21,7 +21,7 @@ class GLGizmoMove3D : public GLGizmoBase Vec3d m_starting_box_center{ Vec3d::Zero() }; Vec3d m_starting_box_bottom_center{ Vec3d::Zero() }; - GLModel m_vbo_cone; + GLModel m_cone; struct GrabberConnection { GLModel model; @@ -59,7 +59,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 53fc03edcba..ab7f242ce51 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -194,23 +194,22 @@ void GLGizmoPainterBase::render_cursor_circle() 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)); } // BBS @@ -220,8 +219,14 @@ void GLGizmoPainterBase::render_cursor_circle() else if (m_button_down == Button::Right) render_color = this->get_cursor_sphere_right_button_color(); - m_circle.set_color(-1, render_color); - m_circle.render(); + m_circle.set_color(render_color); + + GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); + m_circle.render(); + shader->stop_using(); + } glsafe(::glPopAttrib()); glsafe(::glPopMatrix()); @@ -337,7 +342,7 @@ void GLGizmoPainterBase::update_contours(const TriangleMesh& vol_mesh, float cur const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params); if (!polys.empty()) { m_cut_contours.contours.init_from(polys, static_cast(cursor_z)); - m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f }); + m_cut_contours.contours.set_color({ 1.0f, 1.0f, 1.0f, 1.0f }); } } else if (box.center() != m_cut_contours.position) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 534070f6440..b58ec86688d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -228,24 +228,22 @@ void GLGizmoRotate::render_circle(const ColorRGBA& color, bool radius_changed) 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(); } @@ -257,13 +255,13 @@ void GLGizmoRotate::render_scale(const ColorRGBA& color, bool radius_changed) 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); @@ -272,19 +270,16 @@ void GLGizmoRotate::render_scale(const ColorRGBA& color, bool radius_changed) 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(); } @@ -297,13 +292,13 @@ void GLGizmoRotate::render_snap_radii(const ColorRGBA& color, bool radius_change 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); @@ -312,19 +307,16 @@ void GLGizmoRotate::render_snap_radii(const ColorRGBA& color, bool radius_change 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(); } @@ -333,24 +325,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); - - init_data.entities.emplace_back(entity); - m_reference_radius.init_from(init_data); + 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_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(); } @@ -362,24 +352,22 @@ void GLGizmoRotate::render_angle_arc(const ColorRGBA& color, bool radius_changed 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(); } @@ -389,28 +377,26 @@ 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); - - init_data.entities.emplace_back(entity); - m_grabber_connection.model.init_from(init_data); + 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); + + 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(); } -void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const +void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) { m_grabbers.front().color = m_highlight_color; render_grabbers(box); @@ -418,7 +404,7 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) { - double size = 0.75 * GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::INV_ZOOM; + const double size = 0.75 * GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::INV_ZOOM; //float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0); //double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size); @@ -426,15 +412,13 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick if (!picking && m_hover_id != -1) color = m_grabbers.front().hover_color; - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); if (shader == nullptr) return; - m_cone.set_color(-1, color); - if (!picking) { - shader->start_using(); - shader->set_uniform("emission_factor", 0.1f); - } + m_cone.set_color(color); + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); const Vec3d& center = m_grabbers.front().center; @@ -455,13 +439,12 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick m_cone.render(); glsafe(::glPopMatrix()); - if (! picking) - shader->stop_using(); + 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 bc546a89567..61ff0e20a0a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -82,7 +82,7 @@ class GLGizmoRotate : public GLGizmoBase void render_reference_radius(const ColorRGBA& color, bool radius_changed); void render_angle_arc(const ColorRGBA& color, bool radius_changed); void render_grabber_connection(const ColorRGBA& color, bool radius_changed); - 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 c89af3f0ee8..40478f6311b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -267,7 +267,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; @@ -278,27 +278,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; - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::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); glLineStipple(1, 0x0FFF); glEnable(GL_LINE_STIPPLE); m_grabber_connections[id].model.render(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 7b7cc2065de..aca431750d0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -622,7 +622,7 @@ void GLGizmoSimplify::init_model(const indexed_triangle_set& its) m_c->selection_info()->get_active_instance(), m_volume); if (const Selection&sel = m_parent.get_selection(); sel.get_volume_idxs().size() == 1) - m_glmodel.set_color(-1, sel.get_volume(*sel.get_volume_idxs().begin())->color); + m_glmodel.set_color(sel.get_volume(*sel.get_volume_idxs().begin())->color); m_triangle_count = its.indices.size(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 8cef43e5955..8745274f4b2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -28,7 +28,9 @@ namespace GUI { GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) -{} +{ +} + bool GLGizmoSlaSupports::on_init() { @@ -46,10 +48,6 @@ bool GLGizmoSlaSupports::on_init() m_desc["manual_editing"] = _L("Manual editing"); m_desc["clipping_of_view"] = _L("Clipping of view")+ ": "; m_desc["reset_direction"] = _L("Reset direction"); - - m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24)); - m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.)); - m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.)); return true; } @@ -79,6 +77,13 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S void GLGizmoSlaSupports::on_render() { + if (!m_cone.is_initialized()) + m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0)); + if (!m_sphere.is_initialized()) + m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0)); + if (!m_cylinder.is_initialized()) + m_cylinder.init_from(its_make_cylinder(1.0, 1.0, double(PI) / 12.0)); + ModelObject* mo = m_c->selection_info()->model_object(); const Selection& selection = m_parent.get_selection(); @@ -111,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(); @@ -169,8 +174,8 @@ 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); + m_cone.set_color(render_color); + m_sphere.set_color(render_color); if (shader && !picking) shader->set_uniform("emission_factor", 0.5f); @@ -222,7 +227,7 @@ 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); + m_cylinder.set_color(render_color); 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 08d4874bdb0..985b9aeb563 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -77,13 +77,9 @@ 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; - GLModel m_cone; - GLModel m_cylinder; - GLModel m_sphere; - bool m_lock_unique_islands = false; bool m_editing_mode = false; // Is editing mode active? float m_new_point_head_diameter; // Size of a new point. @@ -95,6 +91,10 @@ class GLGizmoSlaSupports : public GLGizmoBase std::vector m_normal_cache; // to restore after discarding changes or undo/redo ObjectID m_old_mo_id; + GLModel m_cone; + GLModel m_cylinder; + GLModel m_sphere; + // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. std::map m_desc; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index c50c80ea369..facfa464ede 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -447,7 +447,14 @@ void GLGizmoText::on_render() m_grabbers[0].enabled = true; ColorRGBA color = picking_color_component(0); m_grabbers[0].color = color; - m_grabbers[0].render_for_picking(mean_size); + + GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light"); + if (shader != nullptr) { + shader->start_using(); + m_grabbers[0].render_for_picking(mean_size); + + shader->stop_using(); + } } delete_temp_preview_text_volume(); @@ -492,7 +499,16 @@ void GLGizmoText::on_render_for_picking() m_grabbers[0].enabled = true; ColorRGBA color = picking_color_component(0); m_grabbers[0].color = color; - m_grabbers[0].render_for_picking(mean_size); + + GLShaderProgram *shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + glsafe(::glPushMatrix()); + shader->start_using(); + m_grabbers[0].render_for_picking(mean_size); + + shader->stop_using(); + glsafe(::glPopMatrix()); + } } } } diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 68702303da2..21096a01116 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1595,16 +1595,11 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif if (sidebar_field.empty()) return; - GLShaderProgram* shader = nullptr; - - if (!boost::starts_with(sidebar_field, "layer")) { - shader = wxGetApp().get_shader("gouraud_light"); - if (shader == nullptr) - return; + GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light"); + if (shader == nullptr) + return; - shader->start_using(); - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - } + shader->start_using(); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -1650,6 +1645,8 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif } } + if (!boost::starts_with(sidebar_field, "layer")) + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); if (boost::starts_with(sidebar_field, "position")) render_sidebar_position_hints(sidebar_field); else if (boost::starts_with(sidebar_field, "rotation")) @@ -1662,8 +1659,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif glsafe(::glPopMatrix()); - if (!boost::starts_with(sidebar_field, "layer")) - shader->stop_using(); + shader->stop_using(); } bool Selection::requires_local_axes() const @@ -2159,15 +2155,6 @@ void Selection::render_synchronized_volumes() } } -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) { const BoundingBoxf3& curr_box = m_box.get_bounding_box(); @@ -2178,79 +2165,74 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& co const Vec3f b_max = box.max.cast(); const Vec3f size = 0.2f * box.size().cast(); - GLModel::InitializationData init_data; - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::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)); @@ -2262,7 +2244,7 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& co 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(); } @@ -2276,16 +2258,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(); } } @@ -2300,16 +2282,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(); } } @@ -2322,7 +2304,7 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, boo bool uniform_scale = requires_uniform_scale() || gizmo_uniform_scale; auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) { - 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)); GLShaderProgram* shader = wxGetApp().get_current_shader(); if (shader != nullptr) shader->set_uniform("emission_factor", 0.0f); @@ -2400,69 +2382,53 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - 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; - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::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; - GUI::GLModel::InitializationData::Entity entity; - entity.type = GUI::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(); glsafe(::glEnable(GL_CULL_FACE));