Merge branch 'master' into et_world_coordinates

This commit is contained in:
Vojtech Bubnik 2022-03-23 14:05:33 +01:00
commit fe71e7c597
23 changed files with 638 additions and 227 deletions

View file

@ -529,7 +529,7 @@ void Bed3D::render_system(GLCanvas3D& canvas, const Transform3d& view_matrix, co
render_model(view_matrix, projection_matrix);
if (show_texture)
render_texture(bottom, canvas);
render_texture(bottom, canvas, view_matrix, projection_matrix);
}
#else
void Bed3D::render_system(GLCanvas3D& canvas, bool bottom, bool show_texture)
@ -542,11 +542,19 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom, bool show_texture)
}
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GL_SHADERS_ATTRIBUTES
void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix)
#else
void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
{
if (m_texture_filename.empty()) {
m_texture.reset();
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, false, view_matrix, projection_matrix);
#else
render_default(bottom, false);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
@ -559,7 +567,11 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
if (m_temp_texture.get_id() == 0 || m_temp_texture.get_source() != m_texture_filename) {
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
if (!m_temp_texture.load_from_svg_file(m_texture_filename, false, false, false, max_tex_size / 8)) {
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, false, view_matrix, projection_matrix);
#else
render_default(bottom, false);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
canvas.request_extra_frame();
@ -567,7 +579,11 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
// starts generating the main texture, compression will run asynchronously
if (!m_texture.load_from_svg_file(m_texture_filename, true, true, true, max_tex_size)) {
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, false, view_matrix, projection_matrix);
#else
render_default(bottom, false);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
}
@ -575,7 +591,11 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
if (m_temp_texture.get_id() == 0 || m_temp_texture.get_source() != m_texture_filename) {
if (!m_temp_texture.load_from_file(m_texture_filename, false, GLTexture::None, false)) {
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, false, view_matrix, projection_matrix);
#else
render_default(bottom, false);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
canvas.request_extra_frame();
@ -583,12 +603,20 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
// starts generating the main texture, compression will run asynchronously
if (!m_texture.load_from_file(m_texture_filename, true, GLTexture::MultiThreaded, true)) {
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, false, view_matrix, projection_matrix);
#else
render_default(bottom, false);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
}
else {
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, false, view_matrix, projection_matrix);
#else
render_default(bottom, false);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
}
@ -614,9 +642,8 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_matrix", projection_matrix);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
shader->set_uniform("transparent_background", bottom);
shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg"));
@ -768,7 +795,11 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bo
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
{
if (m_texture_filename.empty() && m_model_filename.empty()) {
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_default(bottom, picking, view_matrix, projection_matrix);
#else
render_default(bottom, picking);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
}
@ -780,10 +811,18 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bo
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (show_texture)
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_texture(bottom, canvas, view_matrix, projection_matrix);
#else
render_texture(bottom, canvas);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
}
#if ENABLE_GL_SHADERS_ATTRIBUTES
void Bed3D::render_default(bool bottom, bool picking, const Transform3d& view_matrix, const Transform3d& projection_matrix)
#else
void Bed3D::render_default(bool bottom, bool picking)
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
{
m_texture.reset();
@ -800,9 +839,8 @@ void Bed3D::render_default(bool bottom, bool picking)
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_matrix", projection_matrix);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glEnable(GL_DEPTH_TEST));

View file

@ -178,18 +178,18 @@ private:
void render_axes();
#if ENABLE_GL_SHADERS_ATTRIBUTES
void render_system(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_texture);
#else
void render_system(GLCanvas3D& canvas, bool bottom, bool show_texture);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
void render_texture(bool bottom, GLCanvas3D& canvas);
#if ENABLE_GL_SHADERS_ATTRIBUTES
void render_texture(bool bottom, GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix);
void render_model(const Transform3d& view_matrix, const Transform3d& projection_matrix);
void render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_texture, bool picking);
void render_default(bool bottom, bool picking, const Transform3d& view_matrix, const Transform3d& projection_matrix);
#else
void render_system(GLCanvas3D& canvas, bool bottom, bool show_texture);
void render_texture(bool bottom, GLCanvas3D& canvas);
void render_model();
void render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bool picking);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
void render_default(bool bottom, bool picking);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if !ENABLE_LEGACY_OPENGL_REMOVAL
void release_VBOs();
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL

View file

@ -459,6 +459,7 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u
static const ImVec4 COMMAND_COLOR = { 0.8f, 0.8f, 0.0f, 1.0f };
static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f };
static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f };
static const ImVec4 ELLIPSIS_COLOR = { 0.0f, 0.7f, 0.0f, 1.0f };
if (!m_visible || m_filename.empty() || m_lines_ends.empty() || curr_line_id == 0)
return;
@ -503,6 +504,35 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u
ImGuiWrapper& imgui = *wxGetApp().imgui();
auto add_item_to_line = [&imgui](const std::string& txt, const ImVec4& color, float spacing, size_t& current_length) {
static const size_t LENGTH_THRESHOLD = 60;
if (txt.empty())
return false;
std::string out_text = txt;
bool reduced = false;
if (current_length + out_text.length() > LENGTH_THRESHOLD) {
out_text = out_text.substr(0, LENGTH_THRESHOLD - current_length);
reduced = true;
}
current_length += out_text.length();
ImGui::SameLine(0.0f, spacing);
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(out_text);
ImGui::PopStyleColor();
if (reduced) {
ImGui::SameLine(0.0f, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, ELLIPSIS_COLOR);
imgui.text("...");
ImGui::PopStyleColor();
}
return reduced;
};
imgui.set_next_window_pos(0.0f, top, ImGuiCond_Always, 0.0f, 0.0f);
imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
@ -527,41 +557,22 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u
ImGui::GetColorU32(SELECTION_RECT_COLOR));
}
// render line number
const std::string id_str = std::to_string(id);
// spacer to right align text
ImGui::Dummy({ id_width - ImGui::CalcTextSize(id_str.c_str()).x, text_height });
ImGui::SameLine(0.0f, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, LINE_NUMBER_COLOR);
imgui.text(id_str);
ImGui::PopStyleColor();
if (!line.command.empty() || !line.comment.empty())
ImGui::SameLine();
// render command
if (!line.command.empty()) {
ImGui::PushStyleColor(ImGuiCol_Text, COMMAND_COLOR);
imgui.text(line.command);
ImGui::PopStyleColor();
}
// render parameters
if (!line.parameters.empty()) {
ImGui::SameLine(0.0f, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, PARAMETERS_COLOR);
imgui.text(line.parameters);
ImGui::PopStyleColor();
}
// render comment
if (!line.comment.empty()) {
if (!line.command.empty())
ImGui::SameLine(0.0f, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, COMMENT_COLOR);
imgui.text(line.comment);
ImGui::PopStyleColor();
}
size_t line_length = 0;
// render line number
bool stop_adding = add_item_to_line(id_str, LINE_NUMBER_COLOR, 0.0f, line_length);
if (!stop_adding && !line.command.empty())
// render command
stop_adding = add_item_to_line(line.command, COMMAND_COLOR, -1.0f, line_length);
if (!stop_adding && !line.parameters.empty())
// render parameters
stop_adding = add_item_to_line(line.parameters, PARAMETERS_COLOR, 0.0f, line_length);
if (!stop_adding && !line.comment.empty())
// render comment
stop_adding = add_item_to_line(line.comment, COMMENT_COLOR, line.command.empty() ? -1.0f : 0.0f, line_length);
}
imgui.end();
@ -1310,18 +1321,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
log_memory_used(label, vertices_size + indices_size);
};
// format data into the buffers to be rendered as points
auto add_vertices_as_point = [](const GCodeProcessorResult::MoveVertex& curr, VertexBuffer& vertices) {
vertices.push_back(curr.position.x());
vertices.push_back(curr.position.y());
vertices.push_back(curr.position.z());
};
auto add_indices_as_point = [](const GCodeProcessorResult::MoveVertex& curr, TBuffer& buffer,
unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
buffer.add_path(curr, ibuffer_id, indices.size(), move_id);
indices.push_back(static_cast<IBufferType>(indices.size()));
};
// format data into the buffers to be rendered as lines
auto add_vertices_as_line = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, VertexBuffer& vertices) {
#if !ENABLE_GL_SHADERS_ATTRIBUTES
@ -1816,7 +1815,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
switch (t_buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; }
case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; }
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, move_id, account_for_volumetric_rate); break; }
@ -2152,8 +2150,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - indiced_size_to_add) {
i_multibuffer.push_back(IndexBuffer());
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point &&
t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) {
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) {
Path& last_path = t_buffer.paths.back();
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, move_id - 1);
}
@ -2169,8 +2166,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
curr_vertex_buffer.second = 0;
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point &&
t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) {
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) {
Path& last_path = t_buffer.paths.back();
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, move_id - 1);
}
@ -2180,11 +2176,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
switch (t_buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
add_indices_as_point(curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id);
curr_vertex_buffer.second += t_buffer.max_vertices_per_segment();
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
add_indices_as_line(prev, curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id, account_for_volumetric_rate);
@ -2732,10 +2723,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
unsigned int size_in_indices = 0;
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
size_in_indices = buffer.indices_per_segment();
break;
}
case TBuffer::ERenderPrimitiveType::Line:
case TBuffer::ERenderPrimitiveType::Triangle: {
unsigned int segments_count = std::min(m_sequential_view.current.last, sub_path.last.s_id) - std::max(m_sequential_view.current.first, sub_path.first.s_id);
@ -2968,56 +2955,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
void GCodeViewer::render_toolpaths()
{
#if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
const float point_size = 20.0f;
#else
const float point_size = 0.8f;
#endif // ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
#if !ENABLE_GL_SHADERS_ATTRIBUTES
const std::array<float, 4> light_intensity = { 0.25f, 0.70f, 0.75f, 0.75f };
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera();
const double zoom = camera.get_zoom();
const std::array<int, 4>& viewport = camera.get_viewport();
const float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast<float>(viewport[3]) / (2.0f * static_cast<float>(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) :
static_cast<float>(viewport[3]) * 0.0005;
auto shader_init_as_points = [zoom, point_size, near_plane_height](GLShaderProgram& shader) {
#if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
shader.set_uniform("use_fixed_screen_size", 1);
#else
shader.set_uniform("use_fixed_screen_size", 0);
#endif // ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
shader.set_uniform("zoom", zoom);
shader.set_uniform("percent_outline_radius", 0.0f);
shader.set_uniform("percent_center_radius", 0.33f);
shader.set_uniform("point_size", point_size);
shader.set_uniform("near_plane_height", near_plane_height);
};
auto render_as_points = [
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE));
glsafe(::glEnable(GL_POINT_SPRITE));
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
assert(! path.sizes.empty());
assert(! path.offsets.empty());
shader.set_uniform(uniform_color, path.color);
glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_multi_points_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
glsafe(::glDisable(GL_POINT_SPRITE));
glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE));
};
#if !ENABLE_GL_SHADERS_ATTRIBUTES
auto shader_init_as_lines = [light_intensity](GLShaderProgram &shader) {
@ -3194,15 +3136,10 @@ void GCodeViewer::render_toolpaths()
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
int position_id = -1;
int normal_id = -1;
const Transform3d& view_matrix = camera.get_view_matrix();
shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
position_id = shader->get_attrib_location("v_position");
normal_id = shader->get_attrib_location("v_normal");
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) {
@ -3213,6 +3150,8 @@ void GCodeViewer::render_toolpaths()
else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) {
shader->set_uniform("emission_factor", 0.25f);
#if ENABLE_GL_SHADERS_ATTRIBUTES
const int position_id = shader->get_attrib_location("v_position");
const int normal_id = shader->get_attrib_location("v_normal");
render_as_batched_model(buffer, *shader, position_id, normal_id);
#else
render_as_batched_model(buffer, *shader);
@ -3221,8 +3160,8 @@ void GCodeViewer::render_toolpaths()
}
else {
#if ENABLE_GL_SHADERS_ATTRIBUTES
if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Point)
shader_init_as_points(*shader);
const int position_id = shader->get_attrib_location("v_position");
const int normal_id = shader->get_attrib_location("v_normal");
#else
switch (buffer.render_primitive_type) {
case TBuffer::ERenderPrimitiveType::Point: shader_init_as_points(*shader); break;
@ -3269,10 +3208,6 @@ void GCodeViewer::render_toolpaths()
// Render all elements with it_path->ibuffer_id == ibuffer_id, possible with varying colors.
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
render_as_points(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
glsafe(::glLineWidth(static_cast<GLfloat>(line_width(zoom))));
render_as_lines(it_path, buffer.render_paths.end(), *shader, uniform_color);
@ -3306,9 +3241,9 @@ void GCodeViewer::render_toolpaths()
}
#if ENABLE_GCODE_VIEWER_STATISTICS
auto render_sequential_range_cap = [this]
auto render_sequential_range_cap = [this, &camera]
#else
auto render_sequential_range_cap = []
auto render_sequential_range_cap = [&camera]
#endif // ENABLE_GCODE_VIEWER_STATISTICS
(const SequentialRangeCap& cap) {
const TBuffer* buffer = cap.buffer;
@ -3319,16 +3254,13 @@ void GCodeViewer::render_toolpaths()
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
int position_id = -1;
int normal_id = -1;
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d& view_matrix = camera.get_view_matrix();
shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
position_id = shader->get_attrib_location("v_position");
normal_id = shader->get_attrib_location("v_normal");
const int position_id = shader->get_attrib_location("v_position");
const int normal_id = shader->get_attrib_location("v_normal");
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, cap.vbo));
@ -4682,7 +4614,6 @@ void GCodeViewer::render_statistics()
}
if (ImGui::CollapsingHeader("OpenGL calls")) {
add_counter(std::string("Multi GL_POINTS:"), m_statistics.gl_multi_points_calls_count);
add_counter(std::string("Multi GL_LINES:"), m_statistics.gl_multi_lines_calls_count);
add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count);
add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count);

View file

@ -284,7 +284,6 @@ class GCodeViewer
{
enum class ERenderPrimitiveType : unsigned char
{
Point,
Line,
Triangle,
InstancedModel,
@ -325,7 +324,6 @@ class GCodeViewer
unsigned int max_vertices_per_segment() const {
switch (render_primitive_type)
{
case ERenderPrimitiveType::Point: { return 1; }
case ERenderPrimitiveType::Line: { return 2; }
case ERenderPrimitiveType::Triangle: { return 8; }
default: { return 0; }
@ -337,7 +335,6 @@ class GCodeViewer
unsigned int indices_per_segment() const {
switch (render_primitive_type)
{
case ERenderPrimitiveType::Point: { return 1; }
case ERenderPrimitiveType::Line: { return 2; }
case ERenderPrimitiveType::Triangle: { return 30; } // 3 indices x 10 triangles
default: { return 0; }
@ -347,7 +344,6 @@ class GCodeViewer
unsigned int max_indices_per_segment() const {
switch (render_primitive_type)
{
case ERenderPrimitiveType::Point: { return 1; }
case ERenderPrimitiveType::Line: { return 2; }
case ERenderPrimitiveType::Triangle: { return 36; } // 3 indices x 12 triangles
default: { return 0; }
@ -358,7 +354,6 @@ class GCodeViewer
bool has_data() const {
switch (render_primitive_type)
{
case ERenderPrimitiveType::Point:
case ERenderPrimitiveType::Line:
case ERenderPrimitiveType::Triangle: {
return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0;
@ -585,7 +580,6 @@ class GCodeViewer
int64_t refresh_time{ 0 };
int64_t refresh_paths_time{ 0 };
// opengl calls
int64_t gl_multi_points_calls_count{ 0 };
int64_t gl_multi_lines_calls_count{ 0 };
int64_t gl_multi_triangles_calls_count{ 0 };
int64_t gl_triangles_calls_count{ 0 };
@ -628,7 +622,6 @@ class GCodeViewer
}
void reset_opengl() {
gl_multi_points_calls_count = 0;
gl_multi_lines_calls_count = 0;
gl_multi_triangles_calls_count = 0;
gl_triangles_calls_count = 0;

View file

@ -1667,6 +1667,10 @@ void GLCanvas3D::render()
wxGetApp().plater()->init_environment_texture();
#endif // ENABLE_ENVIRONMENT_MAP
#if ENABLE_GLMODEL_STATISTICS
GLModel::reset_statistics_counters();
#endif // ENABLE_GLMODEL_STATISTICS
const Size& cnv_size = get_canvas_size();
// Probably due to different order of events on Linux/GTK2, when one switched from 3D scene
// to preview, this was called before canvas had its final size. It reported zero width
@ -1692,13 +1696,17 @@ void GLCanvas3D::render()
wxGetApp().imgui()->new_frame();
if (m_picking_enabled) {
if (m_rectangle_selection.is_dragging())
// picking pass using rectangle selection
_rectangular_selection_picking_pass();
else if (!m_volumes.empty())
// regular picking pass
_picking_pass();
}
#if ENABLE_NEW_RECTANGLE_SELECTION
if (m_rectangle_selection.is_dragging() && !m_rectangle_selection.is_empty())
#else
if (m_rectangle_selection.is_dragging())
#endif // ENABLE_NEW_RECTANGLE_SELECTION
// picking pass using rectangle selection
_rectangular_selection_picking_pass();
else if (!m_volumes.empty())
// regular picking pass
_picking_pass();
}
#if ENABLE_RENDER_PICKING_PASS
if (!m_picking_enabled || !m_show_picking_texture) {
@ -1776,6 +1784,9 @@ void GLCanvas3D::render()
#if ENABLE_CAMERA_STATISTICS
camera.debug_render();
#endif // ENABLE_CAMERA_STATISTICS
#if ENABLE_GLMODEL_STATISTICS
GLModel::render_statistics();
#endif // ENABLE_GLMODEL_STATISTICS
std::string tooltip;
@ -2917,8 +2928,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
if (imgui->update_key_data(evt)) {
render();
}
else
{
else {
if (!m_gizmos.on_key(evt)) {
if (evt.GetEventType() == wxEVT_KEY_UP) {
if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_SPACE) {
@ -2941,8 +2951,13 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
_update_selection_from_hover();
m_rectangle_selection.stop_dragging();
m_mouse.ignore_left_up = true;
#if !ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true;
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
}
#if ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true;
#endif // ENABLE_NEW_RECTANGLE_SELECTION
// set_cursor(Standard);
}
else if (keyCode == WXK_ALT) {
@ -2954,8 +2969,17 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
}
// set_cursor(Standard);
}
else if (keyCode == WXK_CONTROL)
else if (keyCode == WXK_CONTROL) {
#if ENABLE_NEW_CAMERA_MOVEMENTS
if (m_mouse.dragging) {
// if the user releases CTRL while rotating the 3D scene
// prevent from moving the selected volume
m_mouse.drag.move_volume_idx = -1;
m_mouse.set_start_position_3D_as_invalid();
}
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
m_dirty = true;
}
else if (m_gizmos.is_enabled() && !m_selection.is_empty()) {
translationProcessor.process(evt);
@ -2986,15 +3010,16 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
if (keyCode == WXK_SHIFT) {
translationProcessor.process(evt);
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports))
{
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) {
m_mouse.ignore_left_up = false;
// set_cursor(Cross);
}
#if ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true;
#endif // ENABLE_NEW_RECTANGLE_SELECTION
}
else if (keyCode == WXK_ALT) {
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports))
{
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) {
m_mouse.ignore_left_up = false;
// set_cursor(Cross);
}
@ -3413,6 +3438,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_layers_editing.state = LayersEditing::Editing;
_perform_layer_editing_action(&evt);
}
#if !ENABLE_NEW_RECTANGLE_SELECTION
else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
&& m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
@ -3422,23 +3448,52 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
}
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
else {
#if ENABLE_NEW_RECTANGLE_SELECTION
if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports &&
m_gizmos.get_current_type() != GLGizmosManager::FdmSupports &&
m_gizmos.get_current_type() != GLGizmosManager::Seam &&
m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) {
m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
m_dirty = true;
}
}
#endif // ENABLE_NEW_RECTANGLE_SELECTION
// Select volume in this 3D canvas.
// Don't deselect a volume if layer editing is enabled or any gizmo is active. We want the object to stay selected
// during the scene manipulation.
#if ENABLE_NEW_RECTANGLE_SELECTION
if (m_picking_enabled && (!any_gizmo_active || !evt.ShiftDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) &&
!m_rectangle_selection.is_dragging()) {
#else
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (evt.LeftDown() && !m_hover_volume_idxs.empty()) {
int volume_idx = get_first_hover_volume_idx();
bool already_selected = m_selection.contains_volume(volume_idx);
#if ENABLE_NEW_RECTANGLE_SELECTION
bool shift_down = evt.ShiftDown();
#else
bool ctrl_down = evt.CmdDown();
#endif // ENABLE_NEW_RECTANGLE_SELECTION
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
#if ENABLE_NEW_RECTANGLE_SELECTION
if (already_selected && shift_down)
m_selection.remove(volume_idx);
else {
m_selection.add(volume_idx, !shift_down, true);
#else
if (already_selected && ctrl_down)
m_selection.remove(volume_idx);
else {
m_selection.add(volume_idx, !ctrl_down, true);
#endif // ENABLE_NEW_RECTANGLE_SELECTION
m_mouse.drag.move_requires_threshold = !already_selected;
if (already_selected)
m_mouse.set_move_start_threshold_position_2D_as_invalid();
@ -3460,18 +3515,25 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
#if ENABLE_NEW_RECTANGLE_SELECTION
if (!m_hover_volume_idxs.empty() && !m_rectangle_selection.is_dragging()) {
#else
if (!m_hover_volume_idxs.empty()) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (evt.LeftDown() && m_moving_enabled && m_mouse.drag.move_volume_idx == -1) {
// Only accept the initial position, if it is inside the volume bounding box.
int volume_idx = get_first_hover_volume_idx();
const int volume_idx = get_first_hover_volume_idx();
BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box();
volume_bbox.offset(1.0);
if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(m_mouse.scene_position)) {
m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None;
// The dragging operation is initiated.
m_mouse.drag.move_volume_idx = volume_idx;
#if ENABLE_NEW_CAMERA_MOVEMENTS
m_selection.setup_cache();
m_mouse.drag.start_position_3D = m_mouse.scene_position;
if (!evt.CmdDown())
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
m_mouse.drag.start_position_3D = m_mouse.scene_position;
m_sequential_print_clearance_first_displacement = true;
m_moving = true;
}
@ -3479,31 +3541,36 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
}
#if ENABLE_NEW_CAMERA_MOVEMENTS
else if (evt.Dragging() && evt.LeftIsDown() && !evt.CmdDown() && m_layers_editing.state == LayersEditing::Unknown &&
m_mouse.drag.move_volume_idx != -1 && m_mouse.is_start_position_3D_defined()) {
#else
else if (evt.Dragging() && evt.LeftIsDown() && m_layers_editing.state == LayersEditing::Unknown && m_mouse.drag.move_volume_idx != -1) {
if (!m_mouse.drag.move_requires_threshold) {
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
if (!m_mouse.drag.move_requires_threshold) {
m_mouse.dragging = true;
Vec3d cur_pos = m_mouse.drag.start_position_3D;
// we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag
if (m_selection.contains_volume(get_first_hover_volume_idx())) {
const Camera& camera = wxGetApp().plater()->get_camera();
if (std::abs(camera.get_dir_forward()(2)) < EPSILON) {
if (std::abs(camera.get_dir_forward().z()) < EPSILON) {
// side view -> move selected volumes orthogonally to camera view direction
Linef3 ray = mouse_ray(pos);
Vec3d dir = ray.unit_vector();
const Linef3 ray = mouse_ray(pos);
const Vec3d dir = ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = ray.a + (m_mouse.drag.start_position_3D - ray.a).dot(dir) / dir.squaredNorm() * dir;
const Vec3d inters = ray.a + (m_mouse.drag.start_position_3D - ray.a).dot(dir) / dir.squaredNorm() * dir;
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_mouse.drag.start_position_3D;
const Vec3d inters_vec = inters - m_mouse.drag.start_position_3D;
Vec3d camera_right = camera.get_dir_right();
Vec3d camera_up = camera.get_dir_up();
const Vec3d camera_right = camera.get_dir_right();
const Vec3d camera_up = camera.get_dir_up();
// finds projection of the vector along the camera axes
double projection_x = inters_vec.dot(camera_right);
double projection_z = inters_vec.dot(camera_up);
const double projection_x = inters_vec.dot(camera_right);
const double projection_z = inters_vec.dot(camera_up);
// apply offset
cur_pos = m_mouse.drag.start_position_3D + projection_x * camera_right + projection_z * camera_up;
@ -3513,7 +3580,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// Get new position at the same Z of the initial click point.
float z0 = 0.0f;
float z1 = 1.0f;
cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2));
cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D.z());
}
}
@ -3525,7 +3592,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
else if (evt.Dragging() && evt.LeftIsDown() && m_picking_enabled && m_rectangle_selection.is_dragging()) {
#if ENABLE_NEW_RECTANGLE_SELECTION
// keeps the mouse position updated while dragging the selection rectangle
m_mouse.position = pos.cast<double>();
m_rectangle_selection.dragging(m_mouse.position);
#else
m_rectangle_selection.dragging(pos.cast<double>());
#endif // ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true;
}
else if (evt.Dragging()) {
@ -3538,13 +3611,19 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
// do not process the dragging if the left mouse was set down in another canvas
else if (evt.LeftIsDown()) {
#if ENABLE_NEW_CAMERA_MOVEMENTS
else if (evt.LeftIsDown() || evt.MiddleIsDown()) {
// if dragging over blank area with left button, rotate
if ((any_gizmo_active || evt.CmdDown() || evt.MiddleIsDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
#else
// if dragging over blank area with left button, rotate
else if (evt.LeftIsDown()) {
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.);
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.0) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.0);
if (wxGetApp().app_config->get("use_free_camera") == "1")
// Virtual track ball (similar to the 3DConnexion mouse).
wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.));
wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.0));
else {
// Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
// It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
@ -3557,15 +3636,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
m_mouse.drag.start_position_3D = Vec3d((double)pos.x(), (double)pos.y(), 0.0);
}
#if ENABLE_NEW_CAMERA_MOVEMENTS
else if (evt.RightIsDown()) {
// If dragging with right button, pan.
#else
else if (evt.MiddleIsDown() || evt.RightIsDown()) {
// If dragging over blank area with right button, pan.
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
if (m_mouse.is_start_position_2D_defined()) {
// get point in model space at Z = 0
float z = 0.0f;
const Vec3d& cur_pos = _mouse_to_3d(pos, &z);
Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
const Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
Camera& camera = wxGetApp().plater()->get_camera();
if (wxGetApp().app_config->get("use_free_camera") != "1")
// Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
@ -3638,7 +3722,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (!m_mouse.dragging) {
// do not post the event if the user is panning the scene
// or if right click was done over the wipe tower
bool post_right_click_event = m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower;
const bool post_right_click_event = m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower;
if (post_right_click_event)
post_event(RBtnEvent(EVT_GLCANVAS_RIGHT_CLICK, { logical_pos, m_hover_volume_idxs.empty() }));
}
@ -6331,7 +6415,9 @@ void GLCanvas3D::_update_volumes_hover_state()
return;
}
#if !ENABLE_NEW_RECTANGLE_SELECTION
bool selection_modifiers_only = m_selection.is_empty() || m_selection.is_any_modifier();
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
bool hover_modifiers_only = true;
for (int i : m_hover_volume_idxs) {
@ -6360,9 +6446,14 @@ void GLCanvas3D::_update_volumes_hover_state()
if (volume.hover != GLVolume::HS_None)
continue;
#if ENABLE_NEW_RECTANGLE_SELECTION
bool deselect = volume.selected && ((shift_pressed && m_rectangle_selection.is_empty()) || (alt_pressed && !m_rectangle_selection.is_empty()));
bool select = !volume.selected && (m_rectangle_selection.is_empty() || (shift_pressed && !m_rectangle_selection.is_empty()));
#else
bool deselect = volume.selected && ((ctrl_pressed && !shift_pressed) || alt_pressed);
// (volume->is_modifier && !selection_modifiers_only && !is_ctrl_pressed) -> allows hovering on selected modifiers belonging to selection of type Instance
bool select = (!volume.selected || (volume.is_modifier && !selection_modifiers_only && !ctrl_pressed)) && !alt_pressed;
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (select || deselect) {
bool as_volume =
@ -7280,7 +7371,7 @@ void GLCanvas3D::_update_selection_from_hover()
bool ctrl_pressed = wxGetKeyState(WXK_CONTROL);
if (m_hover_volume_idxs.empty()) {
if (!ctrl_pressed && (m_rectangle_selection.get_state() == GLSelectionRectangle::Select))
if (!ctrl_pressed && m_rectangle_selection.get_state() == GLSelectionRectangle::EState::Select)
m_selection.remove_all();
return;
@ -7297,7 +7388,10 @@ void GLCanvas3D::_update_selection_from_hover()
}
bool selection_changed = false;
if (state == GLSelectionRectangle::Select) {
#if ENABLE_NEW_RECTANGLE_SELECTION
if (!m_rectangle_selection.is_empty()) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (state == GLSelectionRectangle::EState::Select) {
bool contains_all = true;
for (int i : m_hover_volume_idxs) {
if (!m_selection.contains_volume((unsigned int)i)) {
@ -7308,7 +7402,7 @@ void GLCanvas3D::_update_selection_from_hover()
// the selection is going to be modified (Add)
if (!contains_all) {
wxGetApp().plater()->take_snapshot(_(L("Selection-Add from rectangle")), UndoRedo::SnapshotType::Selection);
wxGetApp().plater()->take_snapshot(_L("Selection-Add from rectangle"), UndoRedo::SnapshotType::Selection);
selection_changed = true;
}
}
@ -7323,21 +7417,24 @@ void GLCanvas3D::_update_selection_from_hover()
// the selection is going to be modified (Remove)
if (contains_any) {
wxGetApp().plater()->take_snapshot(_(L("Selection-Remove from rectangle")), UndoRedo::SnapshotType::Selection);
wxGetApp().plater()->take_snapshot(_L("Selection-Remove from rectangle"), UndoRedo::SnapshotType::Selection);
selection_changed = true;
}
}
#if ENABLE_NEW_RECTANGLE_SELECTION
}
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (!selection_changed)
return;
Plater::SuppressSnapshots suppress(wxGetApp().plater());
if ((state == GLSelectionRectangle::Select) && !ctrl_pressed)
if (state == GLSelectionRectangle::EState::Select && !ctrl_pressed)
m_selection.clear();
for (int i : m_hover_volume_idxs) {
if (state == GLSelectionRectangle::Select) {
if (state == GLSelectionRectangle::EState::Select) {
if (hover_modifiers_only) {
const GLVolume& v = *m_volumes.volumes[i];
m_selection.add_volume(v.object_idx(), v.volume_idx(), v.instance_idx(), false);

View file

@ -4,6 +4,10 @@
#include "3DScene.hpp"
#include "GUI_App.hpp"
#include "GLShader.hpp"
#if ENABLE_GLMODEL_STATISTICS
#include "Plater.hpp"
#include "GLCanvas3D.hpp"
#endif // ENABLE_GLMODEL_STATISTICS
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Model.hpp"
@ -13,6 +17,10 @@
#include "libslic3r/Geometry/ConvexHull.hpp"
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GLMODEL_STATISTICS
#include <imgui/imgui_internal.h>
#endif // ENABLE_GLMODEL_STATISTICS
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string/predicate.hpp>
@ -380,6 +388,10 @@ size_t GLModel::Geometry::indices_count() const
}
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GLMODEL_STATISTICS
GLModel::Statistics GLModel::s_statistics;
#endif // ENABLE_GLMODEL_STATISTICS
#if ENABLE_LEGACY_OPENGL_REMOVAL
void GLModel::init_from(Geometry&& data)
#else
@ -702,10 +714,16 @@ void GLModel::reset()
if (m_render_data.ibo_id > 0) {
glsafe(::glDeleteBuffers(1, &m_render_data.ibo_id));
m_render_data.ibo_id = 0;
#if ENABLE_GLMODEL_STATISTICS
s_statistics.gpu_memory.indices.current -= indices_size_bytes();
#endif // ENABLE_GLMODEL_STATISTICS
}
if (m_render_data.vbo_id > 0) {
glsafe(::glDeleteBuffers(1, &m_render_data.vbo_id));
m_render_data.vbo_id = 0;
#if ENABLE_GLMODEL_STATISTICS
s_statistics.gpu_memory.vertices.current -= vertices_size_bytes();
#endif // ENABLE_GLMODEL_STATISTICS
}
m_render_data.vertices_count = 0;
@ -899,6 +917,10 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
#if ENABLE_GLMODEL_STATISTICS
++s_statistics.render_calls;
#endif // ENABLE_GLMODEL_STATISTICS
}
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
@ -1054,6 +1076,10 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
#if ENABLE_GLMODEL_STATISTICS
++s_statistics.render_instanced_calls;
#endif // ENABLE_GLMODEL_STATISTICS
}
#if ENABLE_LEGACY_OPENGL_REMOVAL
@ -1076,6 +1102,10 @@ bool GLModel::send_to_gpu()
glsafe(::glBufferData(GL_ARRAY_BUFFER, data.vertices_size_bytes(), data.vertices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
m_render_data.vertices_count = vertices_count();
#if ENABLE_GLMODEL_STATISTICS
s_statistics.gpu_memory.vertices.current += data.vertices_size_bytes();
s_statistics.gpu_memory.vertices.max = std::max(s_statistics.gpu_memory.vertices.current, s_statistics.gpu_memory.vertices.max);
#endif // ENABLE_GLMODEL_STATISTICS
data.vertices = std::vector<float>();
// indices
@ -1107,10 +1137,75 @@ bool GLModel::send_to_gpu()
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
m_render_data.indices_count = indices_count;
#if ENABLE_GLMODEL_STATISTICS
s_statistics.gpu_memory.indices.current += data.indices_size_bytes();
s_statistics.gpu_memory.indices.max = std::max(s_statistics.gpu_memory.indices.current, s_statistics.gpu_memory.indices.max);
#endif // ENABLE_GLMODEL_STATISTICS
data.indices = std::vector<unsigned int>();
return true;
}
#if ENABLE_GLMODEL_STATISTICS
void GLModel::render_statistics()
{
static const float offset = 175.0f;
ImGuiWrapper& imgui = *wxGetApp().imgui();
auto add_memory = [&imgui](const std::string& label, int64_t memory) {
auto format_string = [memory](const std::string& units, float value) {
return std::to_string(memory) + " bytes (" +
Slic3r::float_to_string_decimal_point(float(memory) * value, 3)
+ " " + units + ")";
};
static const float kb = 1024.0f;
static const float inv_kb = 1.0f / kb;
static const float mb = 1024.0f * kb;
static const float inv_mb = 1.0f / mb;
static const float gb = 1024.0f * mb;
static const float inv_gb = 1.0f / gb;
imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, label);
ImGui::SameLine(offset);
if (static_cast<float>(memory) < mb)
imgui.text(format_string("KB", inv_kb));
else if (static_cast<float>(memory) < gb)
imgui.text(format_string("MB", inv_mb));
else
imgui.text(format_string("GB", inv_gb));
};
auto add_counter = [&imgui](const std::string& label, int64_t counter) {
imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, label);
ImGui::SameLine(offset);
imgui.text(std::to_string(counter));
};
imgui.set_next_window_pos(0.5f * wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_width(), 0.0f, ImGuiCond_Once, 0.5f, 0.0f);
ImGui::SetNextWindowSizeConstraints({ 300.0f, 100.0f }, { 600.0f, 900.0f });
imgui.begin(std::string("GLModel Statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize);
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
add_counter(std::string("Render calls:"), s_statistics.render_calls);
add_counter(std::string("Render instanced calls:"), s_statistics.render_instanced_calls);
if (ImGui::CollapsingHeader("GPU memory")) {
ImGui::Indent(10.0f);
if (ImGui::CollapsingHeader("Vertices")) {
add_memory(std::string("Current:"), s_statistics.gpu_memory.vertices.current);
add_memory(std::string("Max:"), s_statistics.gpu_memory.vertices.max);
}
if (ImGui::CollapsingHeader("Indices")) {
add_memory(std::string("Current:"), s_statistics.gpu_memory.indices.current);
add_memory(std::string("Max:"), s_statistics.gpu_memory.indices.max);
}
ImGui::Unindent(10.0f);
}
imgui.end();
}
#endif // ENABLE_GLMODEL_STATISTICS
#else
void GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
{

View file

@ -177,6 +177,29 @@ namespace GUI {
private:
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GLMODEL_STATISTICS
struct Statistics
{
struct Buffers
{
struct Data
{
size_t current{ 0 };
size_t max{ 0 };
};
Data indices;
Data vertices;
};
Buffers gpu_memory;
int64_t render_calls{ 0 };
int64_t render_instanced_calls{ 0 };
};
static Statistics s_statistics;
#endif // ENABLE_GLMODEL_STATISTICS
RenderData m_render_data;
// By default the vertex and index buffers data are sent to gpu at the first call to render() method.
@ -272,6 +295,14 @@ namespace GUI {
ret += indices_size_bytes();
return ret;
}
#if ENABLE_GLMODEL_STATISTICS
static void render_statistics();
static void reset_statistics_counters() {
s_statistics.render_calls = 0;
s_statistics.render_instanced_calls = 0;
}
#endif // ENABLE_GLMODEL_STATISTICS
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
private:

View file

@ -13,12 +13,12 @@ namespace GUI {
void GLSelectionRectangle::start_dragging(const Vec2d& mouse_position, EState state)
{
if (is_dragging() || (state == Off))
if (is_dragging() || state == EState::Off)
return;
m_state = state;
m_start_corner = mouse_position;
m_end_corner = mouse_position;
m_end_corner = mouse_position;
}
void GLSelectionRectangle::dragging(const Vec2d& mouse_position)
@ -36,7 +36,7 @@ namespace GUI {
if (!is_dragging())
return out;
m_state = Off;
m_state = EState::Off;
const Camera& camera = wxGetApp().plater()->get_camera();
Matrix4d modelview = camera.get_view_matrix().matrix();
@ -66,7 +66,7 @@ namespace GUI {
void GLSelectionRectangle::stop_dragging()
{
if (is_dragging())
m_state = Off;
m_state = EState::Off;
}
void GLSelectionRectangle::render(const GLCanvas3D& canvas)
@ -108,8 +108,8 @@ namespace GUI {
glsafe(::glLineWidth(1.5f));
#if !ENABLE_LEGACY_OPENGL_REMOVAL
float color[3];
color[0] = (m_state == Select) ? 0.3f : 1.0f;
color[1] = (m_state == Select) ? 1.0f : 0.3f;
color[0] = (m_state == EState::Select) ? 0.3f : 1.0f;
color[1] = (m_state == EState::Select) ? 1.0f : 0.3f;
color[2] = 0.3f;
glsafe(::glColor3fv(color));
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
@ -169,7 +169,7 @@ namespace GUI {
shader->set_uniform("projection_matrix", Transform3d::Identity());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
m_rectangle.set_color(ColorRGBA((m_state == Select) ? 0.3f : 1.0f, (m_state == Select) ? 1.0f : 0.3f, 0.3f, 1.0f));
m_rectangle.set_color(ColorRGBA((m_state == EState::Select) ? 0.3f : 1.0f, (m_state == EState::Select) ? 1.0f : 0.3f, 0.3f, 1.0f));
m_rectangle.render();
shader->stop_using();
}

View file

@ -14,7 +14,7 @@ class GLCanvas3D;
class GLSelectionRectangle {
public:
enum EState {
enum class EState {
Off,
Select,
Deselect
@ -35,7 +35,11 @@ public:
void render(const GLCanvas3D& canvas);
bool is_dragging() const { return m_state != Off; }
bool is_dragging() const { return m_state != EState::Off; }
#if ENABLE_NEW_RECTANGLE_SELECTION
bool is_empty() const { return m_state == EState::Off || m_start_corner.isApprox(m_end_corner); }
#endif // ENABLE_NEW_RECTANGLE_SELECTION
EState get_state() const { return m_state; }
float get_width() const { return std::abs(m_start_corner.x() - m_end_corner.x()); }
@ -46,7 +50,7 @@ public:
float get_bottom() const { return std::min(m_start_corner.y(), m_end_corner.y()); }
private:
EState m_state{ Off };
EState m_state{ EState::Off };
Vec2d m_start_corner{ Vec2d::Zero() };
Vec2d m_end_corner{ Vec2d::Zero() };
#if ENABLE_LEGACY_OPENGL_REMOVAL

View file

@ -122,8 +122,7 @@ bool GLShaderProgram::init_from_texts(const std::string& name, const ShaderSourc
for (size_t i = 0; i < static_cast<size_t>(EShaderType::Count); ++i) {
const std::string& source = sources[i];
if (!source.empty())
{
if (!source.empty()) {
EShaderType type = static_cast<EShaderType>(i);
auto [result, id] = create_shader(type);
if (result)
@ -303,6 +302,19 @@ void GLShaderProgram::set_uniform(int id, const Matrix3d& value) const
}
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GL_IMGUI_SHADERS
void GLShaderProgram::set_uniform(int id, const Matrix4f& value) const
{
if (id >= 0)
glsafe(::glUniformMatrix4fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.data())));
}
void GLShaderProgram::set_uniform(int id, const Matrix4d& value) const
{
set_uniform(id, (Matrix4f)value.cast<float>());
}
#endif // ENABLE_GL_IMGUI_SHADERS
void GLShaderProgram::set_uniform(int id, const Vec3f& value) const
{
if (id >= 0)

View file

@ -64,6 +64,10 @@ public:
#if ENABLE_GL_SHADERS_ATTRIBUTES
void set_uniform(const char* name, const Matrix3d& value) const { set_uniform(get_uniform_location(name), value); }
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GL_IMGUI_SHADERS
void set_uniform(const char* name, const Matrix4f& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Matrix4d& value) const { set_uniform(get_uniform_location(name), value); }
#endif // ENABLE_GL_IMGUI_SHADERS
void set_uniform(const char* name, const Vec3f& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Vec3d& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const ColorRGB& value) const { set_uniform(get_uniform_location(name), value); }
@ -86,6 +90,10 @@ public:
#if ENABLE_GL_SHADERS_ATTRIBUTES
void set_uniform(int id, const Matrix3d& value) const;
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GL_IMGUI_SHADERS
void set_uniform(int id, const Matrix4f& value) const;
void set_uniform(int id, const Matrix4d& value) const;
#endif // ENABLE_GL_IMGUI_SHADERS
void set_uniform(int id, const Vec3f& value) const;
void set_uniform(int id, const Vec3d& value) const;
void set_uniform(int id, const ColorRGB& value) const;

View file

@ -35,6 +35,8 @@ std::pair<bool, std::string> GLShadersManager::init()
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
// imgui shader
valid &= append_shader("imgui", { "imgui.vs", "imgui.fs" });
// basic shader, used to render all what was previously rendered using the immediate mode
valid &= append_shader("flat_attr", { "flat_attr.vs", "flat.fs" });
// basic shader for textures, used to render textures

View file

@ -293,7 +293,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
if (m_hover_id == -1) {
if (shift_down || alt_down) {
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect);
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
}
}
else {
@ -359,7 +359,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
trafo, wxGetApp().plater()->get_camera(), points_inside,
m_c->object_clipper()->get_clipping_plane()))
{
if (rectangle_status == GLSelectionRectangle::Deselect)
if (rectangle_status == GLSelectionRectangle::EState::Deselect)
unselect_point(points_idxs[idx]);
else
select_point(points_idxs[idx]);

View file

@ -600,11 +600,17 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
return;
#if ENABLE_GL_SHADERS_ATTRIBUTES
assert(shader->get_name() == "mm_gouraud_attr");
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_model_matrix = camera.get_view_matrix() * matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
#else
assert(shader->get_name() == "mm_gouraud");
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx)
for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx) {
if (m_gizmo_scene.has_VBOs(color_idx)) {
if (color_idx > m_colors.size()) // Seed fill VBO
shader->set_uniform("uniform_color", TriangleSelectorGUI::get_seed_fill_color(color_idx == (m_colors.size() + 1) ? m_default_volume_color : m_colors[color_idx - (m_colors.size() + 1) - 1]));
@ -613,6 +619,7 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
m_gizmo_scene.render(color_idx);
}
}
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
@ -724,19 +731,41 @@ void GLMmSegmentationGizmo3DScene::render(size_t triangle_indices_idx) const
assert(this->vertices_VBO_id != 0);
assert(this->triangle_indices_VBO_ids[triangle_indices_idx] != 0);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float))));
#if ENABLE_GL_SHADERS_ATTRIBUTES
GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr)
return;
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_VBO_id));
#if ENABLE_GL_SHADERS_ATTRIBUTES
const GLint position_id = shader->get_attrib_location("v_position");
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (GLvoid*)0));
glsafe(::glEnableVertexAttribArray(position_id));
}
// Render using the Vertex Buffer Objects.
if (this->triangle_indices_VBO_ids[triangle_indices_idx] != 0 &&
this->triangle_indices_sizes[triangle_indices_idx] > 0) {
#else
glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float))));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
// Render using the Vertex Buffer Objects.
if (this->triangle_indices_sizes[triangle_indices_idx] > 0) {
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_ids[triangle_indices_idx]));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_sizes[triangle_indices_idx]), GL_UNSIGNED_INT, nullptr));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
#if ENABLE_GL_SHADERS_ATTRIBUTES
if (position_id != -1)
glsafe(::glDisableVertexAttribArray(position_id));
#else
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}

View file

@ -195,8 +195,7 @@ void GLGizmoRotate::on_render()
#if ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d view_model_matrix = camera.get_view_matrix() * m_grabbers.front().matrix;
const Transform3d view_model_matrix = camera.get_view_matrix() * m_grabbers.front().matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES

View file

@ -419,7 +419,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
if (m_hover_id == -1) {
if (shift_down || alt_down) {
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect);
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
}
}
else {
@ -490,7 +490,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
{
if (idx >= orig_pts_num) // this is a cone-base, get index of point it belongs to
idx -= orig_pts_num;
if (rectangle_status == GLSelectionRectangle::Deselect)
if (rectangle_status == GLSelectionRectangle::EState::Deselect)
unselect_point(points_idxs[idx]);
else
select_point(points_idxs[idx]);

View file

@ -26,13 +26,18 @@
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
#include "libslic3r/Color.hpp"
#include "3DScene.hpp"
#include "GUI.hpp"
#include "I18N.hpp"
#include "Search.hpp"
#include "BitmapCache.hpp"
#if ENABLE_GL_IMGUI_SHADERS
#include "GUI_App.hpp"
#endif // ENABLE_GL_IMGUI_SHADERS
#include "../Utils/MacDarkMode.hpp"
#include "nanosvg/nanosvg.h"
#include "nanosvg/nanosvgrast.h"
@ -1442,13 +1447,31 @@ void ImGuiWrapper::init_style()
void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
{
if (draw_data == nullptr || draw_data->CmdListsCount == 0)
return;
#if ENABLE_GL_IMGUI_SHADERS
GLShaderProgram* shader = wxGetApp().get_shader("imgui");
if (shader == nullptr)
return;
#endif // ENABLE_GL_IMGUI_SHADERS
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO();
const int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
const int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
const int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
return;
#if ENABLE_GL_IMGUI_SHADERS
GLShaderProgram* curr_shader = wxGetApp().get_current_shader();
if (curr_shader != nullptr)
curr_shader->stop_using();
shader->start_using();
#else
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
#endif // ENABLE_GL_IMGUI_SHADERS
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
@ -1456,25 +1479,43 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode));
GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport));
GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box));
GLint last_texture_env_mode; glsafe(::glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_texture_env_mode));
glsafe(::glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glsafe(::glDisable(GL_CULL_FACE));
glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glEnable(GL_SCISSOR_TEST));
#if !ENABLE_GL_IMGUI_SHADERS
glsafe(::glDisable(GL_LIGHTING));
glsafe(::glDisable(GL_COLOR_MATERIAL));
glsafe(::glEnable(GL_SCISSOR_TEST));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY));
glsafe(::glEnableClientState(GL_COLOR_ARRAY));
#endif // !ENABLE_GL_IMGUI_SHADERS
glsafe(::glEnable(GL_TEXTURE_2D));
glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
GLint texture_env_mode = GL_MODULATE;
glsafe(::glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &texture_env_mode));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
#if ENABLE_GL_IMGUI_SHADERS
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
glsafe(::glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
const float L = draw_data->DisplayPos.x;
const float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
const float T = draw_data->DisplayPos.y;
const float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
Matrix4f ortho_projection;
ortho_projection <<
2.0f / (R - L), 0.0f, 0.0f, (R + L) / (L - R),
0.0f, 2.0f / (T - B), 0.0f, (T + B) / (B - T),
0.0f, 0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f;
shader->set_uniform("Texture", 0);
shader->set_uniform("ProjMtx", ortho_projection);
#else
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
glsafe(::glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
@ -1485,16 +1526,55 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
#endif // ENABLE_GL_IMGUI_SHADERS
#if ENABLE_GL_IMGUI_SHADERS
// Will project scissor/clipping rectangles into framebuffer space
const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
#else
const ImVec2 pos = draw_data->DisplayPos;
#endif // ENABLE_GL_IMGUI_SHADERS
// Render command lists
ImVec2 pos = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; ++n) {
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
#if ENABLE_GL_IMGUI_SHADERS
const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
GLuint vbo_id;
glsafe(::glGenBuffers(1, &vbo_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, vbo_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, vtx_buffer, GL_STATIC_DRAW));
GLuint ibo_id;
glsafe(::glGenBuffers(1, &ibo_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id));
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, idx_buffer, GL_STATIC_DRAW));
const int position_id = shader->get_attrib_location("Position");
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
glsafe(::glEnableVertexAttribArray(position_id));
}
const int uv_id = shader->get_attrib_location("UV");
if (uv_id != -1) {
glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
glsafe(::glEnableVertexAttribArray(uv_id));
}
const int color_id = shader->get_attrib_location("Color");
if (color_id != -1) {
glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
glsafe(::glEnableVertexAttribArray(color_id));
}
#else
glsafe(::glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos))));
glsafe(::glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))));
glsafe(::glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))));
#endif // ENABLE_GL_IMGUI_SHADERS
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; ++cmd_i) {
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
@ -1502,34 +1582,71 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
// User callback (registered via ImDrawList::AddCallback)
pcmd->UserCallback(cmd_list, pcmd);
else {
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
#if ENABLE_GL_IMGUI_SHADERS
// Project scissor/clipping rectangles into framebuffer space
const ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
const ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)));
// Bind texture, Draw
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
#else
const ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) {
// Apply scissor/clipping rectangle
glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)));
// Bind texture, Draw
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId));
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer));
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
}
#endif // ENABLE_GL_IMGUI_SHADERS
}
idx_buffer += pcmd->ElemCount;
}
#if ENABLE_GL_IMGUI_SHADERS
if (position_id != -1)
glsafe(::glDisableVertexAttribArray(position_id));
if (uv_id != -1)
glsafe(::glDisableVertexAttribArray(uv_id));
if (color_id != -1)
glsafe(::glDisableVertexAttribArray(color_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glDeleteBuffers(1, &ibo_id));
glsafe(::glDeleteBuffers(1, &vbo_id));
#endif // ENABLE_GL_IMGUI_SHADERS
}
// Restore modified state
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texture_env_mode));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_texture_env_mode));
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture));
#if !ENABLE_GL_IMGUI_SHADERS
glsafe(::glDisableClientState(GL_COLOR_ARRAY));
glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture));
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glPopMatrix());
glsafe(::glMatrixMode(GL_PROJECTION));
glsafe(::glPopMatrix());
#endif // !ENABLE_GL_IMGUI_SHADERS
glsafe(::glPopAttrib());
glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]));
glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]));
glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]));
#if ENABLE_GL_IMGUI_SHADERS
if (curr_shader != nullptr)
curr_shader->start_using();
#endif // ENABLE_GL_IMGUI_SHADERS
}
bool ImGuiWrapper::display_initialized() const