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@afcac6e2ea)
This commit is contained in:
enricoturri1966 2023-10-21 16:16:21 +08:00 committed by Noisyfox
parent 7e04448b7a
commit 354f8e20fb
27 changed files with 1527 additions and 1207 deletions

View file

@ -48,12 +48,14 @@ public:
static const ColorRGB BLACK() { return { 0.0f, 0.0f, 0.0f }; } 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 BLUE() { return { 0.0f, 0.0f, 1.0f }; }
static const ColorRGB BLUEISH() { return { 0.5f, 0.5f, 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_GRAY() { return { 0.25f, 0.25f, 0.25f }; }
static const ColorRGB DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f }; } 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 GRAY() { return { 0.5f, 0.5f, 0.5f }; }
static const ColorRGB GREEN() { return { 0.0f, 1.0f, 0.0f }; } 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 GREENISH() { return { 0.5f, 1.0f, 0.5f }; }
static const ColorRGB LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f }; } 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 ORANGE() { return { 0.92f, 0.50f, 0.26f }; }
static const ColorRGB RED() { return { 1.0f, 0.0f, 0.0f }; } static const ColorRGB RED() { return { 1.0f, 0.0f, 0.0f }; }
static const ColorRGB REDISH() { return { 1.0f, 0.5f, 0.5f }; } static const ColorRGB REDISH() { return { 1.0f, 0.5f, 0.5f }; }
@ -112,12 +114,14 @@ public:
static const ColorRGBA BLACK() { return { 0.0f, 0.0f, 0.0f, 1.0f }; } 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 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 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_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 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 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 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 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 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 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 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 REDISH() { return { 1.0f, 0.5f, 0.5f, 1.0f }; }

View file

@ -157,7 +157,7 @@ void Bed3D::load_render_colors()
RenderColor::colors[RenderCol_Axis_Z] = ImGuiWrapper::to_ImVec4(Bed3D::AXIS_Z_COLOR); 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) { auto render_axis = [this](const Transform3f& transform) {
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
@ -167,7 +167,7 @@ void Bed3D::Axes::render() const
}; };
if (!m_arrow.is_initialized()) if (!m_arrow.is_initialized())
const_cast<GLModel*>(&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"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr) if (shader == nullptr)
@ -179,15 +179,15 @@ void Bed3D::Axes::render() const
shader->set_uniform("emission_factor", 0.0f); shader->set_uniform("emission_factor", 0.0f);
// x axis // x axis
const_cast<GLModel*>(&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<float>()); render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
// y axis // y axis
const_cast<GLModel*>(&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<float>()); render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
// z axis // z axis
const_cast<GLModel*>(&m_arrow)->set_color(-1, AXIS_Z_COLOR); m_arrow.set_color(AXIS_Z_COLOR);
render_axis(Geometry::assemble_transform(m_origin).cast<float>()); render_axis(Geometry::assemble_transform(m_origin).cast<float>());
shader->stop_using(); 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, void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
bool show_axes) bool show_axes)
{ {
float* factor = const_cast<float*>(&m_scale_factor); m_scale_factor = scale_factor;
*factor = scale_factor;
if (show_axes) if (show_axes)
render_axes(); render_axes();
glsafe(::glEnable(GL_DEPTH_TEST)); 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) switch (m_type)
{ {
@ -456,13 +456,13 @@ std::tuple<Bed3D::Type, std::string, std::string> Bed3D::detect_type(const Point
return { Type::Custom, {}, {} }; return { Type::Custom, {}, {} };
} }
void Bed3D::render_axes() const void Bed3D::render_axes()
{ {
if (m_build_volume.valid()) if (m_build_volume.valid())
m_axes.render(); m_axes.render();
} }
void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const void Bed3D::render_system(GLCanvas3D& canvas, bool bottom)
{ {
if (!bottom) if (!bottom)
render_model(); render_model();
@ -471,7 +471,7 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const
render_texture(bottom, canvas);*/ 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<GLTexture*>(&m_texture); GLTexture* texture = const_cast<GLTexture*>(&m_texture);
GLTexture* temp_texture = const_cast<GLTexture*>(&m_temp_texture); GLTexture* temp_texture = const_cast<GLTexture*>(&m_temp_texture);
@ -656,34 +656,32 @@ GeometryBuffer Bed3D::update_bed_triangles() const
return new_triangles; return new_triangles;
} }
void Bed3D::render_model() const void Bed3D::render_model()
{ {
if (m_model_filename.empty()) if (m_model_filename.empty())
return; return;
GLModel* model = const_cast<GLModel*>(&m_model); 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);
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);
update_model_offset(); update_model_offset();
} }
if (!model->get_filename().empty()) { if (!m_model.get_filename().empty()) {
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.0f); shader->set_uniform("emission_factor", 0.0f);
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z())); glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z()));
model->render(); m_model.render();
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
shader->stop_using(); 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()) { if (m_model_filename.empty()) {
render_default(bottom); render_default(bottom);
@ -697,15 +695,15 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) const
render_texture(bottom, canvas);*/ render_texture(bottom, canvas);*/
} }
void Bed3D::render_default(bool bottom) const void Bed3D::render_default(bool bottom)
{ {
bool picking = false; bool picking = false;
const_cast<GLTexture*>(&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(); GeometryBuffer default_triangles = update_bed_triangles();
if (triangles_vcount > 0) { 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_DEPTH_TEST));
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));

View file

@ -70,7 +70,7 @@ public:
m_arrow.reset(); m_arrow.reset();
} }
float get_total_length() const { return m_stem_length + DefaultTipLength; } float get_total_length() const { return m_stem_length + DefaultTipLength; }
void render() const; void render();
}; };
public: public:
@ -159,12 +159,12 @@ private:
static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape); static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape);
void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
bool show_axes); bool show_axes);
void render_axes() const; void render_axes();
void render_system(GLCanvas3D& canvas, bool bottom) const; void render_system(GLCanvas3D& canvas, bool bottom);
//void render_texture(bool bottom, GLCanvas3D& canvas) const; //void render_texture(bool bottom, GLCanvas3D& canvas);
void render_model() const; void render_model();
void render_custom(GLCanvas3D& canvas, bool bottom) const; void render_custom(GLCanvas3D& canvas, bool bottom);
void render_default(bool bottom) const; void render_default(bool bottom);
void release_VBOs(); void release_VBOs();
}; };

View file

@ -332,10 +332,10 @@ void GLVolume::SinkingContours::render()
void GLVolume::SinkingContours::update() void GLVolume::SinkingContours::update()
{ {
int object_idx = m_parent.object_idx(); const int object_idx = m_parent.object_idx();
Model& model = GUI::wxGetApp().plater()->model(); 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(); 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()) { if (!m_old_box.size().isApprox(box.size()) || m_old_box.min.z() != box.min.z()) {
m_old_box = box; 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(); const TriangleMesh& mesh = model.objects[object_idx]->volumes[m_parent.volume_idx()]->mesh();
m_model.reset(); 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; MeshSlicingParams slicing_params;
slicing_params.trafo = m_parent.world_matrix(); slicing_params.trafo = m_parent.world_matrix();
Polygons polygons = union_(slice_mesh(mesh.its, 0.0f, slicing_params)); const 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))))) { for (const ExPolygon& expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) {
GUI::GLModel::InitializationData::Entity entity;
entity.type = GUI::GLModel::PrimitiveType::Triangles;
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(expoly); const std::vector<Vec3d> 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) { for (const Vec3d& v : triangulation) {
entity.positions.emplace_back(v.cast<float>() + Vec3f(0.0f, 0.0f, 0.015f)); // add a small positive z to avoid z-fighting init_data.add_vertex((Vec3f)(v.cast<float>() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
entity.normals.emplace_back(Vec3f::UnitZ()); ++vertices_counter;
const size_t positions_count = entity.positions.size(); if (vertices_counter % 3 == 0)
if (positions_count % 3 == 0) { init_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
entity.indices.emplace_back(positions_count - 3);
entity.indices.emplace_back(positions_count - 2);
entity.indices.emplace_back(positions_count - 1);
}
} }
init_data.entities.emplace_back(entity);
} }
m_model.init_from(std::move(init_data));
m_model.init_from(init_data);
} }
else else
m_shift = box.center() - m_old_box.center(); m_shift = box.center() - m_old_box.center();
@ -1247,6 +1244,9 @@ void GLVolumeCollection::render(
if (shader == nullptr) if (shader == nullptr)
return; return;
GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat");
GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat");
if (type == ERenderType::Transparent) { if (type == ERenderType::Transparent) {
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
@ -1272,13 +1272,18 @@ void GLVolumeCollection::render(
#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT #endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
// render sinking contours of non-hovered volumes // render sinking contours of non-hovered volumes
if (m_show_sinking_contours) shader->stop_using();
if (volume.first->is_sinking() && !volume.first->is_below_printbed() && if (sink_shader != nullptr) {
volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { sink_shader->start_using();
shader->stop_using(); if (m_show_sinking_contours) {
volume.first->render_sinking_contours(); if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
shader->start_using(); 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_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
@ -1341,17 +1346,21 @@ void GLVolumeCollection::render(
} }
if (m_show_sinking_contours) { if (m_show_sinking_contours) {
for (GLVolumeWithIdAndZ& volume : to_render) { shader->stop_using();
// render sinking contours of hovered/displaced volumes if (sink_shader != nullptr) {
if (volume.first->is_sinking() && !volume.first->is_below_printbed() && sink_shader->start_using();
(volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { for (GLVolumeWithIdAndZ& volume : to_render) {
shader->stop_using(); // render sinking contours of hovered/displaced volumes
glsafe(::glDepthFunc(GL_ALWAYS)); if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
volume.first->render_sinking_contours(); (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) {
glsafe(::glDepthFunc(GL_LESS)); glsafe(::glDepthFunc(GL_ALWAYS));
shader->start_using(); volume.first->render_sinking_contours();
glsafe(::glDepthFunc(GL_LESS));
}
} }
sink_shader->start_using();
} }
shader->start_using();
} }
if (disable_cullface) if (disable_cullface)

View file

@ -288,7 +288,7 @@ void GCodeViewer::SequentialView::Marker::init(std::string filename)
} else { } else {
m_model.init_from_file(filename); 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) 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 //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) if (!m_visible)
return; return;
@ -670,7 +670,7 @@ void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file()
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished mapping file " << m_filename; 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) if (has_render_path)
marker.render(canvas_width, canvas_height, view_type); marker.render(canvas_width, canvas_height, view_type);
@ -1346,7 +1346,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
} }
if (range.vbo > 0) { 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); buffer.model.model.render_instanced(range.vbo, range.count);
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_instanced_models_calls_count; ++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 // 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<double>(1.5f * curr.width); const double width = static_cast<double>(1.5f * curr.width);
const double height = static_cast<double>(1.5f * curr.height); const double height = static_cast<double>(1.5f * curr.height);
const Transform3d trafo = Geometry::assemble_transform((curr.position - 0.5f * curr.height * Vec3f::UnitZ()).cast<double>(), Vec3d::Zero(), { width, width, height }); const Transform3d trafo = Geometry::assemble_transform((curr.position - 0.5f * curr.height * Vec3f::UnitZ()).cast<double>(), Vec3d::Zero(), { width, width, height });
const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose();
for (const auto& entity : data.entities) { // append vertices
// append vertices const size_t vertices_count = data.vertices_count();
for (size_t i = 0; i < entity.positions.size(); ++i) { for (size_t i = 0; i < vertices_count; ++i) {
// append position // append position
const Vec3d position = trafo * entity.positions[i].cast<double>(); const Vec3d position = trafo * data.extract_position_3(i).cast<double>();
vertices.push_back(static_cast<float>(position.x())); vertices.push_back(float(position.x()));
vertices.push_back(static_cast<float>(position.y())); vertices.push_back(float(position.y()));
vertices.push_back(static_cast<float>(position.z())); vertices.push_back(float(position.z()));
// append normal // append normal
const Vec3d normal = normal_matrix * entity.normals[i].cast<double>(); const Vec3d normal = normal_matrix * data.extract_normal_3(i).cast<double>();
vertices.push_back(static_cast<float>(normal.x())); vertices.push_back(float(normal.x()));
vertices.push_back(static_cast<float>(normal.y())); vertices.push_back(float(normal.y()));
vertices.push_back(static_cast<float>(normal.z())); vertices.push_back(float(normal.z()));
}
} }
// append instance position // append instance position
@ -2323,11 +2322,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
instances_ids.push_back(move_id); instances_ids.push_back(move_id);
}; };
auto add_indices_as_model_batch = [](const GLModel::InitializationData& data, IndexBuffer& indices, IBufferType base_index) { auto add_indices_as_model_batch = [](const GLModel::Geometry& data, IndexBuffer& indices, IBufferType base_index) {
for (const auto& entity : data.entities) { const size_t indices_count = data.indices_count();
for (size_t i = 0; i < entity.indices.size(); ++i) { for (size_t i = 0; i < indices_count; ++i) {
indices.push_back(static_cast<IBufferType>(entity.indices[i] + base_index)); indices.push_back(static_cast<IBufferType>(data.extract_ushort_index(i) + base_index));
}
} }
}; };
@ -3868,7 +3866,7 @@ void GCodeViewer::render_toolpaths()
} }
if (range.vbo > 0) { 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); buffer.model.model.render_instanced(range.vbo, range.count);
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_instanced_models_calls_count; ++m_statistics.gl_instanced_models_calls_count;

View file

@ -311,7 +311,7 @@ class GCodeViewer
GLModel model; GLModel model;
ColorRGBA color; ColorRGBA color;
InstanceVBuffer instances; InstanceVBuffer instances;
GLModel::InitializationData data; GLModel::Geometry data;
void reset(); void reset();
}; };
@ -374,7 +374,7 @@ class GCodeViewer
} }
case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); }
case ERenderPrimitiveType::BatchedModel: { 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; !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0;
} }
default: { return false; } default: { return false; }
@ -642,7 +642,7 @@ public:
bool is_visible() const { return m_visible; } bool is_visible() const { return m_visible; }
void set_visible(bool visible) { m_visible = 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 on_change_color_mode(bool is_dark) { m_is_dark = is_dark; }
void update_curr_move(const GCodeProcessorResult::MoveVertex move); void update_curr_move(const GCodeProcessorResult::MoveVertex move);
@ -709,7 +709,7 @@ public:
std::vector<unsigned int> gcode_ids; std::vector<unsigned int> gcode_ids;
float m_scale = 1.0; float m_scale = 1.0;
bool m_show_gcode_window = false; 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 struct ETools

View file

@ -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 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; 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; m_profile.old_bar_rect = bar_rect;
// Baseline // Baseline
if (!m_profile.baseline.is_initialized() || bar_rect_changed) { if (!m_profile.baseline.is_initialized() || bar_rect_changed) {
m_profile.old_bar_rect = bar_rect; m_profile.old_bar_rect = bar_rect;
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::Lines; init_data.color = ColorRGBA::BLACK();
entity.positions.reserve(2); init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.emplace_back(x, bar_rect.get_bottom(), 0.0f); init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.positions.emplace_back(x, bar_rect.get_top(), 0.0f);
entity.normals.reserve(2); // vertices
for (size_t j = 0; j < 2; ++j) { init_data.add_vertex(Vec3f(x, bar_rect.get_bottom(), 0.0f));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_vertex(Vec3f(x, bar_rect.get_top(), 0.0f));
}
entity.indices.reserve(2); // indices
entity.indices.emplace_back(0); init_data.add_ushort_line(0, 1);
entity.indices.emplace_back(1);
init_data.entities.emplace_back(entity); m_profile.baseline.init_from(std::move(init_data));
m_profile.baseline.init_from(init_data);
m_profile.baseline.set_color(-1, ColorRGBA::BLACK());
} }
if (!m_profile.profile.is_initialized() || bar_rect_changed || m_profile.old_layer_height_profile != m_layer_height_profile) { 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.old_layer_height_profile = m_layer_height_profile;
m_profile.profile.reset(); m_profile.profile.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT };
entity.type = GLModel::PrimitiveType::LineStrip; init_data.color = ColorRGBA::BLUE();
entity.positions.reserve(m_layer_height_profile.size()); init_data.vertices.reserve(m_layer_height_profile.size() * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.normals.reserve(m_layer_height_profile.size()); init_data.indices.reserve(m_layer_height_profile.size() * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.indices.reserve(m_layer_height_profile.size());
for (unsigned int i = 0; i < unsigned int(m_layer_height_profile.size()); i += 2) { // vertices + indices
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); for (unsigned int i = 0; i < (unsigned int)m_layer_height_profile.size(); i += 2) {
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_vertex(Vec3f(bar_rect.get_left() + float(m_layer_height_profile[i + 1]) * scale_x,
entity.indices.emplace_back(i / 2); 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(std::move(init_data));
m_profile.profile.init_from(init_data);
m_profile.profile.set_color(-1, ColorRGBA::BLUE());
} }
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat");
@ -924,89 +919,51 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
m_perimeter.reset(); m_perimeter.reset();
m_fill.reset(); m_fill.reset();
if (!polygons.empty()) { 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) { if (m_render_fill) {
GLModel::InitializationData fill_data; GLModel::Geometry fill_data;
GLModel::InitializationData::Entity entity; fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT };
entity.type = GLModel::PrimitiveType::Triangles; fill_data.color = { 0.8f, 0.8f, 1.0f, 0.5f };
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);
// vertices + indices
const ExPolygons polygons_union = union_ex(polygons); const ExPolygons polygons_union = union_ex(polygons);
for (const ExPolygon &poly : polygons_union) { unsigned int vertices_counter = 0;
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(poly); for (const ExPolygon& poly : polygons_union) {
for (const Vec3d &v : triangulation) { const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(poly);
entity.positions.emplace_back(v.cast<float>() + Vec3f(0.0f, 0.0f, 0.0125f)); // add a small positive z to avoid z-fighting for (const Vec3d& v : triangulation) {
entity.normals.emplace_back(Vec3f::UnitZ()); fill_data.add_vertex((Vec3f)(v.cast<float>() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
const size_t positions_count = entity.positions.size(); ++vertices_counter;
if (positions_count % 3 == 0) { if (vertices_counter % 3 == 0)
entity.indices.emplace_back(positions_count - 3); fill_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
entity.indices.emplace_back(positions_count - 2);
entity.indices.emplace_back(positions_count - 1);
}
} }
} }
fill_data.entities.emplace_back(entity); m_fill.init_from(std::move(fill_data));
m_fill.init_from(fill_data);
} }
GLModel::InitializationData perimeter_data; m_perimeter.init_from(polygons, 0.025f); // add a small positive z to avoid z-fighting
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<float>(p.x()), unscale<float>(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_perimeter.init_from(perimeter_data);
} }
//BBS: add the height limit compute logic //BBS: add the height limit compute logic
if (!height_polygons.empty()) { if (!height_polygons.empty()) {
size_t height_triangles_count = 0; GLModel::Geometry height_fill_data;
for (const auto &poly : height_polygons) { height_triangles_count += poly.first.points.size() - 2; } height_fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT };
const size_t height_vertices_count = 3 * height_triangles_count; height_fill_data.color = {0.8f, 0.8f, 1.0f, 0.5f};
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);
// vertices + indices
unsigned int vertices_counter = 0;
for (const auto &poly : height_polygons) { for (const auto &poly : height_polygons) {
ExPolygon ex_poly(poly.first); ExPolygon ex_poly(poly.first);
const std::vector<Vec3d> height_triangulation = triangulate_expolygon_3d(ex_poly); const std::vector<Vec3d> height_triangulation = triangulate_expolygon_3d(ex_poly);
for (const Vec3d &v : height_triangulation) { for (const Vec3d &v : height_triangulation) {
Vec3d point{v.x(), v.y(), poly.second}; Vec3f point{(float) v.x(), (float) v.y(), poly.second};
height_entity.positions.emplace_back(point.cast<float>()); height_fill_data.add_vertex(point);
height_entity.normals.emplace_back(Vec3f::UnitZ()); ++vertices_counter;
const size_t height_positions_count = height_entity.positions.size(); if (vertices_counter % 3 == 0)
if (height_positions_count % 3 == 0) { height_fill_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
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);
}
} }
} }
height_fill_data.entities.emplace_back(height_entity); m_height_limit.init_from(std::move(height_fill_data));
m_height_limit.init_from(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 FILL_COLOR = { 0.7f, 0.7f, 1.0f, 0.5f };
const ColorRGBA NO_FILL_COLOR = { 0.75f, 0.75f, 0.75f, 0.75f }; 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) if (shader == nullptr)
return; return;
@ -1026,11 +983,11 @@ void GLCanvas3D::SequentialPrintClearance::render()
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); 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_perimeter.render();
m_fill.render(); m_fill.render();
//BBS: add height limit //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(); m_height_limit.render();
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));

File diff suppressed because it is too large Load diff

View file

@ -20,46 +20,108 @@ namespace GUI {
class GLModel class GLModel
{ {
public: public:
enum class PrimitiveType : unsigned char struct Geometry
{ {
Triangles, enum class EPrimitiveType : unsigned char
Lines, {
LineStrip, Points,
LineLoop Triangles,
TriangleStrip,
TriangleFan,
Lines,
LineStrip,
LineLoop
};
enum class EVertexLayout : unsigned char
{
P2, // position 2 floats
P2T2, // position 2 floats + texture coords 2 floats
P3, // position 3 floats
P3N3, // position 3 floats + normal 3 floats
};
enum class EIndexType : unsigned char
{
UINT, // unsigned int
USHORT // unsigned short
};
struct Format
{
EPrimitiveType type{ EPrimitiveType::Triangles };
EVertexLayout vertex_layout{ EVertexLayout::P3N3 };
EIndexType index_type{ EIndexType::UINT };
};
Format format;
std::vector<float> vertices;
std::vector<unsigned char> indices;
ColorRGBA color{ ColorRGBA::BLACK() };
void add_vertex(const Vec2f& position);
void add_vertex(const Vec3f& position);
void add_vertex(const Vec3f& position, const Vec3f& normal);
void add_ushort_index(unsigned short id);
void add_uint_index(unsigned int id);
void add_ushort_line(unsigned short id1, unsigned short id2);
void add_uint_line(unsigned int id1, unsigned int id2);
void add_ushort_triangle(unsigned short id1, unsigned short id2, unsigned short id3);
void add_uint_triangle(unsigned int id1, unsigned int id2, unsigned int id3);
Vec2f extract_position_2(size_t id) const;
Vec3f extract_position_3(size_t id) const;
Vec3f extract_normal_3(size_t id) const;
Vec2f extract_tex_coord_2(size_t id) const;
unsigned int extract_uint_index(size_t id) const;
unsigned short extract_ushort_index(size_t id) const;
size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); }
size_t indices_count() const { return indices.size() / index_stride_bytes(format); }
size_t vertices_size_floats() const { return vertices.size(); }
size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); }
size_t indices_size_bytes() const { return indices.size(); }
static size_t vertex_stride_floats(const Format& format);
static size_t vertex_stride_bytes(const Format& format) { return vertex_stride_floats(format) * sizeof(float); }
static size_t position_stride_floats(const Format& format);
static size_t position_stride_bytes(const Format& format) { return position_stride_floats(format) * sizeof(float); }
static size_t position_offset_floats(const Format& format);
static size_t position_offset_bytes(const Format& format) { return position_offset_floats(format) * sizeof(float); }
static size_t normal_stride_floats(const Format& format);
static size_t normal_stride_bytes(const Format& format) { return normal_stride_floats(format) * sizeof(float); }
static size_t normal_offset_floats(const Format& format);
static size_t normal_offset_bytes(const Format& format) { return normal_offset_floats(format) * sizeof(float); }
static size_t tex_coord_stride_floats(const Format& format);
static size_t tex_coord_stride_bytes(const Format& format) { return tex_coord_stride_floats(format) * sizeof(float); }
static size_t tex_coord_offset_floats(const Format& format);
static size_t tex_coord_offset_bytes(const Format& format) { return tex_coord_offset_floats(format) * sizeof(float); }
static size_t index_stride_bytes(const Format& format);
static bool has_position(const Format& format);
static bool has_normal(const Format& format);
static bool has_tex_coord(const Format& format);
}; };
struct RenderData struct RenderData
{ {
PrimitiveType type; Geometry geometry;
unsigned int vbo_id{ 0 }; unsigned int vbo_id{ 0 };
unsigned int ibo_id{ 0 }; unsigned int ibo_id{ 0 };
size_t vertices_count{ 0 };
size_t indices_count{ 0 }; size_t indices_count{ 0 };
ColorRGBA color;
}; };
struct InitializationData
{
struct Entity
{
PrimitiveType type;
std::vector<Vec3f> positions;
std::vector<Vec3f> normals;
std::vector<unsigned int> indices;
ColorRGBA color;
};
std::vector<Entity> entities;
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); }
size_t indices_count() const;
size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); }
};
private: private:
std::vector<RenderData> m_render_data; RenderData m_render_data;
BoundingBoxf3 m_bounding_box; BoundingBoxf3 m_bounding_box;
std::string m_filename; std::string m_filename;
@ -68,50 +130,59 @@ namespace GUI {
GLModel() = default; GLModel() = default;
virtual ~GLModel() { reset(); } virtual ~GLModel() { reset(); }
void init_from(const InitializationData& data); size_t vertices_count() const { return m_render_data.vertices_count > 0 ?
void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox); 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 indexed_triangle_set& its);
void init_from(const Polygons& polygons, float z); void init_from(const Polygons& polygons, float z);
bool init_from_file(const std::string& filename); bool init_from_file(const std::string& filename);
// if entity_id == -1 set the color of all entities void set_color(const ColorRGBA& color) { m_render_data.geometry.color = color; }
void set_color(int entity_id, const ColorRGBA& color); const ColorRGBA& get_color() const { return m_render_data.geometry.color; }
void reset(); void reset();
void render() const; void render();
void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; 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 BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
const std::string& get_filename() const { return m_filename; } const std::string& get_filename() const { return m_filename; }
private: private:
void send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices); bool send_to_gpu();
}; };
// create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution // 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 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 // the arrow has its axis of symmetry along the Z axis and is pointing upward
// used to render bed axes and sequential marker // 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 // 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 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 // the arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise
// used to render sidebar hints for rotations // 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 // create an arrow with the given dimensions
// the origin of the arrow is in the center of the stem cap // 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 // 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 // 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 // create a diamond with the given resolution
// the origin of the diamond is in its center // the origin of the diamond is in its center
// the diamond is contained into a box with size [1, 1, 1] // 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 GUI
} // namespace Slic3r } // namespace Slic3r

View file

@ -80,17 +80,17 @@ namespace GUI {
Size cnv_size = canvas.get_canvas_size(); Size cnv_size = canvas.get_canvas_size();
float cnv_half_width = 0.5f * (float)cnv_size.get_width(); float cnv_half_width = 0.5f * (float)cnv_size.get_width();
float cnv_half_height = 0.5f * (float)cnv_size.get_height(); 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; return;
Vec2d start(m_start_corner(0) - cnv_half_width, cnv_half_height - m_start_corner(1)); 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)); 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; const float left = (float)std::min(start(0), end(0)) * inv_zoom;
float top = (float)std::max(start(1), end(1)) * inv_zoom; const float top = (float)std::max(start(1), end(1)) * inv_zoom;
float right = (float)std::max(start(0), end(0)) * inv_zoom; const float right = (float)std::max(start(0), end(0)) * inv_zoom;
float bottom = (float)std::min(start(1), end(1)) * inv_zoom; const float bottom = (float)std::min(start(1), end(1)) * inv_zoom;
glsafe(::glLineWidth(1.5f)); glsafe(::glLineWidth(1.5f));
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
@ -100,7 +100,7 @@ namespace GUI {
// ensure that the rectangle is renderered inside the frustrum // ensure that the rectangle is renderered inside the frustrum
glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5))); glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5)));
// ensure that the overlay fits the frustrum near z plane // 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(::glScaled(gui_scale, gui_scale, 1.0));
glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glPushAttrib(GL_ENABLE_BIT));
@ -116,34 +116,28 @@ namespace GUI {
m_old_end_corner = m_end_corner; m_old_end_corner = m_end_corner;
m_rectangle.reset(); m_rectangle.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::LineLoop; init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(4); init_data.indices.reserve(4 * GLModel::Geometry::index_stride_bytes(init_data.format));
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); // vertices
for (size_t j = 0; j < 5; ++j) { init_data.add_vertex(Vec2f(left, bottom));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_vertex(Vec2f(right, bottom));
} init_data.add_vertex(Vec2f(right, top));
init_data.add_vertex(Vec2f(left, top));
entity.indices.reserve(6); // indices
entity.indices.emplace_back(0); init_data.add_ushort_index(0);
entity.indices.emplace_back(1); init_data.add_ushort_index(1);
entity.indices.emplace_back(2); init_data.add_ushort_index(2);
entity.indices.emplace_back(2); init_data.add_ushort_index(3);
entity.indices.emplace_back(3);
entity.indices.emplace_back(0);
init_data.entities.emplace_back(entity); m_rectangle.init_from(std::move(init_data));
m_rectangle.init_from(init_data);
} }
ColorRGBA color(0.0f, 1.0f, 0.38f, 1.0f); const ColorRGBA color(0.0f, 1.0f, 0.38f, 1.0f);
m_rectangle.set_color(-1, color); m_rectangle.set_color(color);
m_rectangle.render(); m_rectangle.render();
shader->stop_using(); shader->stop_using();
} }

View file

@ -27,30 +27,12 @@ const int c_connectors_group_id = 4;
const float UndefFloat = -999.f; const float UndefFloat = -999.f;
// connector colors // connector colors
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
static const ColorRGBA BLACK() { return {0.0f, 0.0f, 0.0f, 1.0f}; } static const ColorRGBA DOWEL_COLOR = ColorRGBA::DARK_YELLOW();
static const ColorRGBA BLUE() { return {0.0f, 0.0f, 1.0f, 1.0f}; } static const ColorRGBA HOVERED_PLAG_COLOR = ColorRGBA::CYAN();
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 HOVERED_DOWEL_COLOR = {0.0f, 0.5f, 0.5f, 1.0f}; 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_PLAG_COLOR = ColorRGBA::GRAY();
static const ColorRGBA SELECTED_DOWEL_COLOR = GRAY(); // DARK_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_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 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}; 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(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix());
BoundingBoxf3 box = m_parent.get_selection().get_bounding_box(); BoundingBoxf3 box = m_parent.get_selection().get_bounding_box();
#if ENABLE_FIXED_GRABBER #if ENABLE_FIXED_GRABBER
float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); 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); float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
#endif #endif
m_move_grabber.color = picking_color_component(0); m_move_grabber.color = picking_color_component(0);
m_move_grabber.render_for_picking(mean_size); 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)); glsafe(::glEnable(GL_DEPTH_TEST));
auto inst_id = m_c->selection_info()->get_active_instance(); auto inst_id = m_c->selection_info()->get_active_instance();
@ -876,67 +869,112 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
point += object_offset; point += object_offset;
} }
// draw plane
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glDisable(GL_CULL_FACE));
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); 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); // draw plane
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); {
for (const Vec3d& point : plane_points_rot) { m_plane.reset();
::glVertex3f(point(0), point(1), point(2));
}
glsafe(::glEnd());
glsafe(::glEnable(GL_CULL_FACE)); GLModel::Geometry init_data;
glsafe(::glDisable(GL_BLEND)); 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 // vertices
Vec3d plane_center_rot = calc_plane_center(plane_points_rot); for (const Vec3d &point : plane_points_rot) {
m_move_grabber.center = plane_center_rot + plane_normal_rot * Offset; init_data.add_vertex((Vec3f)point.cast<float>());
// m_move_grabber.angles = m_current_base_rotation + m_rotation; }
glsafe(::glDisable(GL_DEPTH_TEST)); // indices
glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); init_data.add_ushort_triangle(0, 1, 2);
glsafe(::glColor3f(1.0, 1.0, 0.0)); init_data.add_ushort_triangle(2, 3, 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);
// std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_move_grabber.color); m_plane.init_from(std::move(init_data));
// m_move_grabber.color = GrabberColor; }
// m_move_grabber.hover_color = GrabberHoverColor; m_plane.render();
// 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;
const GLModel &cube = m_move_grabber.get_cube(); glsafe(::glEnable(GL_CULL_FACE));
// BBS set to fixed size grabber glsafe(::glDisable(GL_BLEND));
// float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size));
float fullsize = 8.0f; // Draw the grabber and the connecting line
if (GLGizmoBase::INV_ZOOM > 0) { Vec3d plane_center_rot = calc_plane_center(plane_points_rot);
fullsize = m_move_grabber.FixedGrabberSize * GLGizmoBase::INV_ZOOM; 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<float>());
init_data.add_vertex((Vec3f)m_move_grabber.center.cast<float>());
// 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<GLModel*>(&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;
glsafe(::glPushMatrix()); GLModel &cube = m_move_grabber.get_cube();
glsafe(::glTranslated(m_move_grabber.center.x(), m_move_grabber.center.y(), m_move_grabber.center.z())); // BBS set to fixed size grabber
glsafe(::glMultMatrixd(m_rotate_matrix.data())); // 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(::glScaled(fullsize, fullsize, fullsize)); cube.set_color(render_color);
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 // Should be placed at last, because GLGizmoRotate3D clears depth buffer
set_center(m_cut_plane_center); 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())); glsafe(::glMultMatrixd(view_model_matrix.data()));
model.set_color(-1, color); model.set_color(color);
model.render(); model.render();
shader->stop_using(); shader->stop_using();

View file

@ -53,6 +53,8 @@ private:
bool m_place_on_cut_lower{false}; bool m_place_on_cut_lower{false};
bool m_rotate_upper{false}; bool m_rotate_upper{false};
bool m_rotate_lower{false}; bool m_rotate_lower{false};
GLModel m_plane;
GLModel m_grabber_connection;
bool m_do_segment; bool m_do_segment;
double m_segment_smoothing_alpha; double m_segment_smoothing_alpha;

View file

@ -68,26 +68,9 @@ void GLGizmoBase::load_render_colors()
RenderColor::colors[RenderCol_Flatten_Plane_Hover] = ImGuiWrapper::to_ImVec4(GLGizmoBase::FLATTEN_HOVER_COLOR); RenderColor::colors[RenderCol_Flatten_Plane_Hover] = ImGuiWrapper::to_ImVec4(GLGizmoBase::FLATTEN_HOVER_COLOR);
} }
GLGizmoBase::Grabber::Grabber() void GLGizmoBase::Grabber::render(bool hover, float size)
: center(Vec3d::Zero())
, angles(Vec3d::Zero())
, dragging(false)
, enabled(true)
{ {
color = GRABBER_NORMAL_COL; render(size, hover ? hover_color : color, false);
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);
} }
float GLGizmoBase::Grabber::get_half_size(float size) const 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; 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 // This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least). // initialized at that point (on Linux at least).
indexed_triangle_set mesh = its_make_cube(1., 1., 1.); indexed_triangle_set its = its_make_cube(1., 1., 1.);
its_translate(mesh, Vec3f(-0.5, -0.5, -0.5)); its_translate(its, Vec3f(-0.5, -0.5, -0.5));
const_cast<GLModel&>(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); m_cube.init_from(its);
const_cast<bool&>(cube_initialized) = true;
} }
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 // This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least). // initialized at that point (on Linux at least).
indexed_triangle_set mesh = its_make_cube(1., 1., 1.); indexed_triangle_set its = its_make_cube(1., 1., 1.);
its_translate(mesh, Vec3f(-0.5, -0.5, -0.5)); its_translate(its, Vec3f(-0.5, -0.5, -0.5));
const_cast<GLModel&>(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); m_cube.init_from(its);
const_cast<bool&>(cube_initialized) = true;
} }
//BBS set to fixed size grabber //BBS set to fixed size grabber
@ -132,7 +113,7 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
} }
const_cast<GLModel*>(&cube)->set_color(-1, render_color); m_cube.set_color(render_color);
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(center.x(), center.y(), center.z())); 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.y()), 0.0, 1.0, 0.0));
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
glsafe(::glScaled(fullsize, fullsize, fullsize)); glsafe(::glScaled(fullsize, fullsize, fullsize));
cube.render(); m_cube.render();
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
} }
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: m_parent(parent) : m_parent(parent)
, m_group_id(-1) , 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 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 #if ENABLE_FIXED_GRABBER
float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); const float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize);
#else #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 #endif
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) {
if (m_grabbers[i].enabled) { if (m_grabbers[i].enabled) {
m_grabbers[i].color = picking_color_component(i); m_grabbers[i].color = picking_color_component(i);
m_grabbers[i].render_for_picking(mean_size); m_grabbers[i].render_for_picking(mean_size);
}
} }
shader->stop_using();
} }
} }

View file

@ -64,27 +64,26 @@ protected:
static const float FixedGrabberSize; static const float FixedGrabberSize;
static const float FixedRadiusSize; static const float FixedRadiusSize;
Vec3d center; bool enabled{ true };
Vec3d angles; bool dragging{ false };
ColorRGBA color; Vec3d center{ Vec3d::Zero() };
ColorRGBA hover_color; Vec3d angles{ Vec3d::Zero() };
bool enabled; ColorRGBA color{GRABBER_NORMAL_COL};
bool dragging; ColorRGBA hover_color{GRABBER_HOVER_COL};
Grabber(); Grabber() = default;
void render(bool hover, float size) const; void render(bool hover, float size);
void render_for_picking(float size) const { render(size, color, true); } void render_for_picking(float size) { render(size, color, true); }
float get_half_size(float size) const; float get_half_size(float size) const;
float get_dragging_half_size(float size) const; float get_dragging_half_size(float size) const;
const GLModel& get_cube() const; GLModel& get_cube();
private: private:
void render(float size, const ColorRGBA& render_color, bool picking) const; void render(float size, const ColorRGBA& render_color, bool picking);
GLModel cube; GLModel m_cube;
bool cube_initialized = false;
}; };
public: public:

View file

@ -20,7 +20,6 @@ namespace GUI {
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, 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() 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 Selection& selection = m_parent.get_selection();
const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info(); const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info();
@ -99,12 +101,14 @@ void GLGizmoHollow::on_render_for_picking()
render_points(selection, true); 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"); GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
if (shader) if (shader == nullptr)
shader->start_using(); return;
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
shader->start_using();
ScopeGuard guard([shader]() { shader->stop_using(); });
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); 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(); 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; continue;
// First decide about the color of the point. // First decide about the color of the point.
if (picking) { if (picking)
render_color = picking_color_component(i); render_color = picking_color_component(i);
}
else { else {
if (size_t(m_hover_id) == i) { if (size_t(m_hover_id) == i)
render_color = {0.f, 1.f, 1.f, 1.f}; render_color = ColorRGBA::CYAN();
}
else if (m_c->hollowed_mesh() && else if (m_c->hollowed_mesh() &&
i < m_c->hollowed_mesh()->get_drainholes().size() && i < m_c->hollowed_mesh()->get_drainholes().size() &&
m_c->hollowed_mesh()->get_drainholes()[i].failed) { 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); render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
}
} }
const_cast<GLModel*>(&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. // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
glsafe(::glPushMatrix()); 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())); glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
if (vol->is_left_handed()) 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. // Matrices set, we can render the point mark now.
Eigen::Quaterniond q; Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>()); q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
Eigen::AngleAxisd aa(q); 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(::glPushMatrix());
glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glTranslated(0., 0., -drain_hole.height));
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
m_vbo_cylinder.render(); m_cylinder.render();
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
if (vol->is_left_handed()) if (vol->is_left_handed())
@ -172,8 +173,6 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
} }
bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
{ {
if (m_c->object_clipper()->get_position() == 0.) if (m_c->object_clipper()->get_position() == 0.)

View file

@ -42,13 +42,14 @@ private:
void on_render() override; void on_render() override;
void on_render_for_picking() 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); void hollow_mesh(bool postpone_error_messages = false);
bool unsaved_changes() const; bool unsaved_changes() const;
ObjectID m_old_mo_id = -1; 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_radius = 2.f; // Size of a new hole.
float m_new_hole_height = 6.f; float m_new_hole_height = 6.f;
mutable std::vector<bool> m_selected; // which holes are currently selected mutable std::vector<bool> m_selected; // which holes are currently selected

View file

@ -25,9 +25,7 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam
: GLGizmoBase(parent, icon_filename, sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id)
//BBS: GUI refactor: add obj manipulation //BBS: GUI refactor: add obj manipulation
, m_object_manipulation(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 std::string GLGizmoMove3D::get_tooltip() const
{ {
@ -95,6 +93,9 @@ void GLGizmoMove3D::on_update(const UpdateData& data)
void GLGizmoMove3D::on_render() 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(); const Selection& selection = m_parent.get_selection();
glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); 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].old_center = center;
m_grabber_connections[id].model.reset(); m_grabber_connections[id].model.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GUI::GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GUI::GLModel::PrimitiveType::Lines; init_data.color = AXES_COLOR[id];
entity.positions.reserve(2); init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.emplace_back(center.cast<float>()); init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.positions.emplace_back(m_grabbers[id].center.cast<float>());
entity.normals.reserve(2); // vertices
for (size_t j = 0; j < 2; ++j) { init_data.add_vertex((Vec3f)center.cast<float>());
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
}
entity.indices.reserve(2); // indices
entity.indices.emplace_back(0); init_data.add_ushort_line(0, 1);
entity.indices.emplace_back(1);
init_data.entities.emplace_back(entity); m_grabber_connections[id].model.init_from(std::move(init_data));
m_grabber_connections[id].model.init_from(init_data);
m_grabber_connections[id].model.set_color(-1, AXES_COLOR[id]);
} }
glLineStipple(1, 0x0FFF); glLineStipple(1, 0x0FFF);
@ -241,7 +237,7 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
return projection; 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 #if ENABLE_FIXED_GRABBER
float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); 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) if (shader == nullptr)
return; return;
const_cast<GLModel*>(&m_vbo_cone)->set_color(-1, color); m_cone.set_color(color);
if (!picking) { shader->start_using();
shader->start_using(); shader->set_uniform("emission_factor", 0.1f);
shader->set_uniform("emission_factor", 0.1f);
}
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z())); 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(::glTranslated(0.0, 0.0, 2.0 * size));
glsafe(::glScaled(0.75 * size, 0.75 * size, 2.0 * size)); glsafe(::glScaled(0.75 * size, 0.75 * size, 2.0 * size));
m_vbo_cone.render(); m_cone.render();
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
if (! picking) shader->stop_using();
shader->stop_using();
} }

View file

@ -21,7 +21,7 @@ class GLGizmoMove3D : public GLGizmoBase
Vec3d m_starting_box_center{ Vec3d::Zero() }; Vec3d m_starting_box_center{ Vec3d::Zero() };
Vec3d m_starting_box_bottom_center{ Vec3d::Zero() }; Vec3d m_starting_box_bottom_center{ Vec3d::Zero() };
GLModel m_vbo_cone; GLModel m_cone;
struct GrabberConnection struct GrabberConnection
{ {
GLModel model; GLModel model;
@ -59,7 +59,7 @@ protected:
private: private:
double calc_projection(const UpdateData& data) const; 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);
}; };

View file

@ -194,23 +194,22 @@ void GLGizmoPainterBase::render_cursor_circle()
m_old_cursor_radius = m_cursor_radius; m_old_cursor_radius = m_cursor_radius;
m_circle.reset(); m_circle.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity;
entity.type = GLModel::PrimitiveType::LineLoop;
static const unsigned int StepsCount = 32; static const unsigned int StepsCount = 32;
static const float StepSize = 2.0f * float(PI) / float(StepsCount); static const float StepSize = 2.0f * float(PI) / float(StepsCount);
entity.positions.reserve(StepsCount); init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.normals.reserve(StepsCount); init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f };
entity.indices.reserve(StepsCount); init_data.vertices.reserve(StepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
for (unsigned int i = 0; i < StepsCount; ++i) { 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); 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); init_data.add_vertex(Vec3f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius, 0.0f));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i);
entity.indices.emplace_back(i);
} }
init_data.entities.emplace_back(entity); m_circle.init_from(std::move(init_data));
m_circle.init_from(init_data);
} }
// BBS // BBS
@ -220,8 +219,14 @@ void GLGizmoPainterBase::render_cursor_circle()
else if (m_button_down == Button::Right) else if (m_button_down == Button::Right)
render_color = this->get_cursor_sphere_right_button_color(); render_color = this->get_cursor_sphere_right_button_color();
m_circle.set_color(-1, render_color); m_circle.set_color(render_color);
m_circle.render();
GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat");
if (shader != nullptr) {
shader->start_using();
m_circle.render();
shader->stop_using();
}
glsafe(::glPopAttrib()); glsafe(::glPopAttrib());
glsafe(::glPopMatrix()); 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); const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params);
if (!polys.empty()) { if (!polys.empty()) {
m_cut_contours.contours.init_from(polys, static_cast<float>(cursor_z)); m_cut_contours.contours.init_from(polys, static_cast<float>(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) { else if (box.center() != m_cut_contours.position) {

View file

@ -228,24 +228,22 @@ void GLGizmoRotate::render_circle(const ColorRGBA& color, bool radius_changed)
if (!m_circle.is_initialized() || radius_changed) { if (!m_circle.is_initialized() || radius_changed) {
m_circle.reset(); m_circle.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::LineLoop; init_data.vertices.reserve(ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(ScaleStepsCount); init_data.indices.reserve(ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.normals.reserve(ScaleStepsCount);
entity.indices.reserve(ScaleStepsCount); // vertices + indices
for (unsigned int i = 0; i < ScaleStepsCount; ++i) { for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
const float angle = float(i * ScaleStepRad); const float angle = float(i * ScaleStepRad);
entity.positions.emplace_back(::cos(angle) * m_radius, ::sin(angle) * m_radius, 0.0f); init_data.add_vertex(Vec3f(::cos(angle) * m_radius, ::sin(angle) * m_radius, 0.0f));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i);
entity.indices.emplace_back(i);
} }
init_data.entities.emplace_back(entity); m_circle.init_from(std::move(init_data));
m_circle.init_from(init_data);
} }
m_circle.set_color(-1, color); m_circle.set_color(color);
m_circle.render(); m_circle.render();
} }
@ -257,13 +255,13 @@ void GLGizmoRotate::render_scale(const ColorRGBA& color, bool radius_changed)
if (!m_scale.is_initialized() || radius_changed) { if (!m_scale.is_initialized() || radius_changed) {
m_scale.reset(); m_scale.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::Lines; init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(2 * ScaleStepsCount); init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.normals.reserve(2 * ScaleStepsCount);
entity.indices.reserve(2 * ScaleStepsCount); // vertices + indices
for (unsigned int i = 0; i < ScaleStepsCount; ++i) { for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
const float angle = float(i * ScaleStepRad); const float angle = float(i * ScaleStepRad);
const float cosa = ::cos(angle); const float cosa = ::cos(angle);
const float sina = ::sin(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_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; 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); init_data.add_vertex(Vec3f(in_x, in_y, 0.0f));
entity.positions.emplace_back(out_x, out_y, 0.0f); init_data.add_vertex(Vec3f(out_x, out_y, 0.0f));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i * 2);
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i * 2 + 1);
entity.indices.emplace_back(i * 2 + 0);
entity.indices.emplace_back(i * 2 + 1);
} }
init_data.entities.emplace_back(entity); m_scale.init_from(std::move(init_data));
m_scale.init_from(init_data); }
}
m_scale.set_color(-1, color); m_scale.set_color(color);
m_scale.render(); 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) { if (!m_snap_radii.is_initialized() || radius_changed) {
m_snap_radii.reset(); m_snap_radii.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::Lines; init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(2 * ScaleStepsCount); init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.normals.reserve(2 * ScaleStepsCount);
entity.indices.reserve(2 * ScaleStepsCount); // vertices + indices
for (unsigned int i = 0; i < ScaleStepsCount; ++i) { for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
const float angle = float(i * step); const float angle = float(i * step);
const float cosa = ::cos(angle); const float cosa = ::cos(angle);
const float sina = ::sin(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_x = cosa * out_radius;
const float out_y = sina * out_radius; const float out_y = sina * out_radius;
entity.positions.emplace_back(in_x, in_y, 0.0f); init_data.add_vertex(Vec3f(in_x, in_y, 0.0f));
entity.positions.emplace_back(out_x, out_y, 0.0f); init_data.add_vertex(Vec3f(out_x, out_y, 0.0f));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i * 2);
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i * 2 + 1);
entity.indices.emplace_back(i * 2 + 0);
entity.indices.emplace_back(i * 2 + 1);
} }
init_data.entities.emplace_back(entity); m_snap_radii.init_from(std::move(init_data));
m_snap_radii.init_from(init_data);
} }
m_snap_radii.set_color(-1, color); m_snap_radii.set_color(color);
m_snap_radii.render(); 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) { if (!m_reference_radius.is_initialized() || radius_changed) {
m_reference_radius.reset(); m_reference_radius.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::Lines; init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(2); init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
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); // vertices
m_reference_radius.init_from(init_data); 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(); 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) { if (!m_angle_arc.is_initialized() || radius_changed) {
m_angle_arc.reset(); m_angle_arc.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::LineStrip; init_data.vertices.reserve((1 + AngleResolution) * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(1 + AngleResolution); init_data.indices.reserve((1 + AngleResolution) * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.normals.reserve(1 + AngleResolution);
entity.indices.reserve(1 + AngleResolution); // vertices + indices
for (unsigned int i = 0; i <= AngleResolution; ++i) { for (unsigned short i = 0; i <= AngleResolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
entity.positions.emplace_back(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f); init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f));
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i);
entity.indices.emplace_back(i);
} }
init_data.entities.emplace_back(entity); m_angle_arc.init_from(std::move(init_data));
m_angle_arc.init_from(init_data);
} }
m_angle_arc.set_color(-1, color); m_angle_arc.set_color(color);
m_angle_arc.render(); 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.model.reset();
m_grabber_connection.old_center = m_grabbers.front().center; m_grabber_connection.old_center = m_grabbers.front().center;
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::Lines; init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(2); init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.positions.emplace_back(0.0f, 0.0f, 0.0f);
entity.positions.emplace_back(m_grabbers.front().center.cast<float>());
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); // vertices
m_grabber_connection.model.init_from(init_data); init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f));
init_data.add_vertex((Vec3f)m_grabbers.front().center.cast<float>());
// 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(); 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; m_grabbers.front().color = m_highlight_color;
render_grabbers(box); 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) 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); //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); //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) if (!picking && m_hover_id != -1)
color = m_grabbers.front().hover_color; 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) if (shader == nullptr)
return; return;
m_cone.set_color(-1, color); m_cone.set_color(color);
if (!picking) { shader->start_using();
shader->start_using(); shader->set_uniform("emission_factor", 0.1f);
shader->set_uniform("emission_factor", 0.1f);
}
const Vec3d& center = m_grabbers.front().center; const Vec3d& center = m_grabbers.front().center;
@ -455,13 +439,12 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
m_cone.render(); m_cone.render();
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
if (! picking) shader->stop_using();
shader->stop_using();
} }
void GLGizmoRotate::transform_to_local(const Selection& selection) const 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()) { 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); const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);

View file

@ -82,7 +82,7 @@ private:
void render_reference_radius(const ColorRGBA& color, bool radius_changed); void render_reference_radius(const ColorRGBA& color, bool radius_changed);
void render_angle_arc(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_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 render_grabber_extension(const BoundingBoxf3& box, bool picking);
void transform_to_local(const Selection& selection) const; void transform_to_local(const Selection& selection) const;

View file

@ -267,7 +267,7 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
return -1; return -1;
}; };
int id = grabber_connection(id_1, id_2); const int id = grabber_connection(id_1, id_2);
if (id == -1) if (id == -1)
return; 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].old_v2 = m_grabbers[id_2].center;
m_grabber_connections[id].model.reset(); m_grabber_connections[id].model.reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GUI::GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GUI::GLModel::PrimitiveType::Lines; init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(2); init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.positions.emplace_back(m_grabbers[id_1].center.cast<float>());
entity.positions.emplace_back(m_grabbers[id_2].center.cast<float>());
entity.normals.reserve(2); // vertices
for (size_t j = 0; j < 2; ++j) { init_data.add_vertex((Vec3f)m_grabbers[id_1].center.cast<float>());
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_vertex((Vec3f)m_grabbers[id_2].center.cast<float>());
}
entity.indices.reserve(2); // indices
entity.indices.emplace_back(0); init_data.add_ushort_line(0, 1);
entity.indices.emplace_back(1);
init_data.entities.emplace_back(entity); m_grabber_connections[id].model.init_from(std::move(init_data));
m_grabber_connections[id].model.init_from(init_data);
} }
m_grabber_connections[id].model.set_color(-1, color); m_grabber_connections[id].model.set_color(color);
glLineStipple(1, 0x0FFF); glLineStipple(1, 0x0FFF);
glEnable(GL_LINE_STIPPLE); glEnable(GL_LINE_STIPPLE);
m_grabber_connections[id].model.render(); m_grabber_connections[id].model.render();

View file

@ -622,7 +622,7 @@ void GLGizmoSimplify::init_model(const indexed_triangle_set& its)
m_c->selection_info()->get_active_instance(), m_volume); m_c->selection_info()->get_active_instance(), m_volume);
if (const Selection&sel = m_parent.get_selection(); sel.get_volume_idxs().size() == 1) 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(); m_triangle_count = its.indices.size();
} }

View file

@ -28,7 +28,9 @@ namespace GUI {
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id)
{} {
}
bool GLGizmoSlaSupports::on_init() bool GLGizmoSlaSupports::on_init()
{ {
@ -46,10 +48,6 @@ bool GLGizmoSlaSupports::on_init()
m_desc["manual_editing"] = _L("Manual editing"); m_desc["manual_editing"] = _L("Manual editing");
m_desc["clipping_of_view"] = _L("Clipping of view")+ ": "; m_desc["clipping_of_view"] = _L("Clipping of view")+ ": ";
m_desc["reset_direction"] = _L("Reset direction"); 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; return true;
} }
@ -79,6 +77,13 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
void GLGizmoSlaSupports::on_render() 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(); ModelObject* mo = m_c->selection_info()->model_object();
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
@ -111,7 +116,7 @@ void GLGizmoSlaSupports::on_render_for_picking()
render_points(selection, true); 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(); 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<GLModel*>(&m_cone)->set_color(-1, render_color); m_cone.set_color(render_color);
const_cast<GLModel*>(&m_sphere)->set_color(-1, render_color); m_sphere.set_color(render_color);
if (shader && !picking) if (shader && !picking)
shader->set_uniform("emission_factor", 0.5f); 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: // Now render the drain holes:
if (has_holes && ! picking) { if (has_holes && ! picking) {
render_color = { 0.7f, 0.7f, 0.7f, 0.7f }; render_color = { 0.7f, 0.7f, 0.7f, 0.7f };
const_cast<GLModel*>(&m_cylinder)->set_color(-1, render_color); m_cylinder.set_color(render_color);
if (shader) if (shader)
shader->set_uniform("emission_factor", 0.5f); shader->set_uniform("emission_factor", 0.5f);
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) { for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {

View file

@ -77,13 +77,9 @@ private:
void on_render() override; void on_render() override;
void on_render_for_picking() override; void on_render_for_picking() override;
void render_points(const Selection& selection, bool picking = false) const; void render_points(const Selection& selection, bool picking = false);
bool unsaved_changes() const; bool unsaved_changes() const;
GLModel m_cone;
GLModel m_cylinder;
GLModel m_sphere;
bool m_lock_unique_islands = false; bool m_lock_unique_islands = false;
bool m_editing_mode = false; // Is editing mode active? bool m_editing_mode = false; // Is editing mode active?
float m_new_point_head_diameter; // Size of a new point. float m_new_point_head_diameter; // Size of a new point.
@ -95,6 +91,10 @@ private:
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
ObjectID m_old_mo_id; 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 // 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. // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
std::map<std::string, wxString> m_desc; std::map<std::string, wxString> m_desc;

View file

@ -447,7 +447,14 @@ void GLGizmoText::on_render()
m_grabbers[0].enabled = true; m_grabbers[0].enabled = true;
ColorRGBA color = picking_color_component(0); ColorRGBA color = picking_color_component(0);
m_grabbers[0].color = color; 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(); delete_temp_preview_text_volume();
@ -492,7 +499,16 @@ void GLGizmoText::on_render_for_picking()
m_grabbers[0].enabled = true; m_grabbers[0].enabled = true;
ColorRGBA color = picking_color_component(0); ColorRGBA color = picking_color_component(0);
m_grabbers[0].color = color; 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());
}
} }
} }
} }

View file

@ -1595,16 +1595,11 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
if (sidebar_field.empty()) if (sidebar_field.empty())
return; return;
GLShaderProgram* shader = nullptr; GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light");
if (shader == nullptr)
return;
if (!boost::starts_with(sidebar_field, "layer")) { shader->start_using();
shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr)
return;
shader->start_using();
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
}
glsafe(::glEnable(GL_DEPTH_TEST)); 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")) if (boost::starts_with(sidebar_field, "position"))
render_sidebar_position_hints(sidebar_field); render_sidebar_position_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "rotation")) 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()); glsafe(::glPopMatrix());
if (!boost::starts_with(sidebar_field, "layer")) shader->stop_using();
shader->stop_using();
} }
bool Selection::requires_local_axes() const 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) void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& color)
{ {
const BoundingBoxf3& curr_box = m_box.get_bounding_box(); 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<float>(); const Vec3f b_max = box.max.cast<float>();
const Vec3f size = 0.2f * box.size().cast<float>(); const Vec3f size = 0.2f * box.size().cast<float>();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GUI::GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GUI::GLModel::PrimitiveType::Lines; init_data.vertices.reserve(48 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(48); init_data.indices.reserve(48 * GLModel::Geometry::index_stride_bytes(init_data.format));
entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_min.z())); // vertices
entity.positions.emplace_back(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()));
entity.positions.emplace_back(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()));
entity.positions.emplace_back(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()));
entity.positions.emplace_back(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()));
entity.positions.emplace_back(Vec3f(b_min.x(), b_min.y(), b_min.z() + size.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()));
entity.positions.emplace_back(Vec3f(b_max.x(), b_min.y(), b_min.z())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(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())); init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z() - size.z()));
entity.normals.reserve(48); // indices
for (size_t i = 0; i < 48; ++i) { for (unsigned short i = 0; i < 48; ++i) {
entity.normals.emplace_back(Vec3f::UnitZ()); init_data.add_ushort_index(i);
} }
entity.indices.reserve(48); m_box.init_from(std::move(init_data));
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);
} }
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
@ -2262,7 +2244,7 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& co
return; return;
shader->start_using(); shader->start_using();
m_box.set_color(-1, to_rgba(color)); m_box.set_color(to_rgba(color));
m_box.render(); m_box.render();
shader->stop_using(); 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")) { if (boost::ends_with(sidebar_field, "x")) {
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); 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(); m_arrow.render();
} }
else if (boost::ends_with(sidebar_field, "y")) { 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(); m_arrow.render();
} }
else if (boost::ends_with(sidebar_field, "z")) { else if (boost::ends_with(sidebar_field, "z")) {
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); 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(); 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")) { if (boost::ends_with(sidebar_field, "x")) {
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0)); 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(); render_sidebar_rotation_hint();
} }
else if (boost::ends_with(sidebar_field, "y")) { else if (boost::ends_with(sidebar_field, "y")) {
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); 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(); render_sidebar_rotation_hint();
} }
else if (boost::ends_with(sidebar_field, "z")) { 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(); 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; bool uniform_scale = requires_uniform_scale() || gizmo_uniform_scale;
auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) { 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(); GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader != nullptr) if (shader != nullptr)
shader->set_uniform("emission_factor", 0.0f); 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(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); 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<double>(), p1.cast<double>())) { if (!m_planes.models[0].is_initialized() || !is_approx(m_planes.check_points[0], p1)) {
m_planes.check_points[0] = p1; m_planes.check_points[0] = p1;
m_planes.models[0].reset(); m_planes.models[0].reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GUI::GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GUI::GLModel::PrimitiveType::Triangles; init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(4); init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
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); // vertices
for (size_t i = 0; i < 4; ++i) { init_data.add_vertex(Vec3f(p1.x(), p1.y(), z1));
entity.normals.emplace_back(Vec3f::UnitZ()); 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));
entity.indices.reserve(6); // indices
entity.indices.emplace_back(0); init_data.add_ushort_triangle(0, 1, 2);
entity.indices.emplace_back(1); init_data.add_ushort_triangle(2, 3, 0);
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_planes.models[0].init_from(std::move(init_data));
m_planes.models[0].init_from(init_data);
} }
if (!m_planes.models[1].is_initialized() || !is_approx(m_planes.check_points[1].cast<double>(), p2.cast<double>())) { if (!m_planes.models[1].is_initialized() || !is_approx(m_planes.check_points[1], p2)) {
m_planes.check_points[1] = p2; m_planes.check_points[1] = p2;
m_planes.models[1].reset(); m_planes.models[1].reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GUI::GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GUI::GLModel::PrimitiveType::Triangles; init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
entity.positions.reserve(4); init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
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); // vertices
for (size_t i = 0; i < 4; ++i) { init_data.add_vertex(Vec3f(p1.x(), p1.y(), z2));
entity.normals.emplace_back(Vec3f::UnitZ()); 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); // indices
entity.indices.emplace_back(0); init_data.add_ushort_triangle(0, 1, 2);
entity.indices.emplace_back(1); init_data.add_ushort_triangle(2, 3, 0);
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_planes.models[1].init_from(std::move(init_data));
m_planes.models[1].init_from(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[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(); m_planes.models[1].render();
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));