WIP: Cut with TAG

Added experimental rendering for the cutPlane mesh
This commit is contained in:
YuSanka 2023-07-14 17:32:02 +02:00
parent 9067f601d8
commit 34af44b4bf
2 changed files with 308 additions and 4 deletions

View File

@ -187,6 +187,7 @@ GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename,
, m_connector_shape_id (int(CutConnectorShape::Circle))
{
m_connector_type = CutConnectorType::Snap;
m_mode = size_t(CutMode::cutTongueAndGroove);
m_modes = { _u8L("Planar"), _u8L("Tongue and Groove")//, _u8L("Grid")
// , _u8L("Radial"), _u8L("Modular")
@ -487,6 +488,10 @@ bool GLGizmoCut3D::render_cut_mode_combo()
m_contour_width = CutMode(m_mode) == CutMode::cutTongueAndGroove ? 0.f : 0.4f;
oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width));
}
if (m_use_TAG_mesh) {
m_plane.reset();
on_unregister_raycasters_for_picking();
}
reset_cut_by_contours();
}
@ -861,6 +866,263 @@ indexed_triangle_set GLGizmoCut3D::its_make_sides_groove_plane(float flaps_width
};
}
indexed_triangle_set GLGizmoCut3D::its_make_groove_plane()
{
// values for calculation
const float side_width = is_approx(m_groove_flaps_angle, 0.f) ? m_groove_depth : (m_groove_depth / sin(m_groove_flaps_angle));
const float flaps_width = 2.f * side_width * cos(m_groove_flaps_angle);
const float groove_half_width_upper = 0.5f * (m_groove_width);
const float groove_half_width_lower = 0.5f * (m_groove_width + flaps_width);
const float cut_plane_radius = 1.5f * float(m_radius);
const float cut_plane_length = 1.5f * cut_plane_radius;
const float groove_half_depth = 0.5f * m_groove_depth;
const float x = 0.5f * cut_plane_radius;
const float y = 0.5f * cut_plane_length;
float z_upper = groove_half_depth;
float z_lower = -groove_half_depth;
const float proj = y * tan(m_groove_angle);
float ext_upper_x = groove_half_width_upper + proj; // upper_x extension
float ext_lower_x = groove_half_width_lower + proj; // lower_x extension
float nar_upper_x = groove_half_width_upper - proj; // upper_x narrowing
float nar_lower_x = groove_half_width_lower - proj; // lower_x narrowing
const float cut_plane_thiknes = 0.02f;// 0.02f * (float)get_grabber_mean_size(m_bounding_box); // cut_plane_thiknes
// Different cases of groove plane:
// groove is open
if (groove_half_width_upper > proj && groove_half_width_lower > proj) {
indexed_triangle_set mesh;
auto get_vertices = [x, y](float z_upper, float z_lower, float nar_upper_x, float nar_lower_x, float ext_upper_x, float ext_lower_x) {
return std::vector<stl_vertex>({
// upper left part vertices
{-x, -y, z_upper}, {-x, y, z_upper}, {-nar_upper_x, y, z_upper}, {-ext_upper_x, -y, z_upper},
// lower part vertices
{-ext_lower_x, -y, z_lower}, {-nar_lower_x, y, z_lower}, {nar_lower_x, y, z_lower}, {ext_lower_x, -y, z_lower},
// upper right part vertices
{ext_upper_x, -y, z_upper}, {nar_upper_x, y, z_upper}, {x, y, z_upper}, {x, -y, z_upper}
});
};
mesh.vertices = get_vertices(z_upper, z_lower, nar_upper_x, nar_lower_x, ext_upper_x, ext_lower_x);
mesh.vertices.reserve(2 * mesh.vertices.size());
z_upper -= cut_plane_thiknes;
z_lower -= cut_plane_thiknes;
if (m_use_TAG_mesh_full) {
const float under_x_shift = cut_plane_thiknes / tan(0.5f * m_groove_flaps_angle);
nar_upper_x += under_x_shift;
nar_lower_x += under_x_shift;
ext_upper_x += under_x_shift;
ext_lower_x += under_x_shift;
std::vector<stl_vertex> vertices = get_vertices(z_upper, z_lower, nar_upper_x, nar_lower_x, ext_upper_x, ext_lower_x);
mesh.vertices.insert(mesh.vertices.end(), vertices.begin(), vertices.end());
mesh.indices = {
// above view
{5,4,7}, {5,7,6}, // lower part
{3,4,5}, {3,5,2}, // left side
{9,6,8}, {8,6,7}, // right side
{1,0,2}, {2,0,3}, // upper left part
{9,8,10}, {10,8,11}, // upper right part
// under view
{20,21,22}, {20,22,23}, // upper right part
{12,13,14}, {12,14,15}, // upper left part
{18,21,20}, {18,20,19}, // right side
{16,15,14}, {16,14,17}, // left side
{16,17,18}, {16,18,19}, // lower part
// left edge
{1,13,0}, {0,13,12},
// front edge
{0,12,3}, {3,12,15}, {3,15,4}, {4,15,16}, {4,16,7}, {7,16,19}, {7,19,20}, {7,20,8}, {8,20,11}, {11,20,23},
// right edge
{11,23,10}, {10,23,22},
// back edge
{1,13,2}, {2,13,14}, {2,14,17}, {2,17,5}, {5,17,6}, {6,17,18}, {6,18,9}, {9,18,21}, {9,21,10}, {10,21,22}
};
}
else {
std::vector<stl_vertex> vertices = get_vertices(z_upper, z_lower, nar_upper_x, nar_lower_x, ext_upper_x, ext_lower_x);
mesh.vertices.insert(mesh.vertices.end(), vertices.begin(), vertices.end());
mesh.indices = {
// above view
{5,4,7}, {5,7,6}, // lower part
{3,4,2}, {2,4,5}, // left side
{9,6,8}, {8,6,7}, // right side
{1,0,2}, {2,0,3}, // upper left part
{9,8,10}, {10,8,11}, // upper right part
// under view
{16,15,14}, {16,14,17}, // left side
{18,21,20}, {18,20,19}, // right side
{16,17,18}, {16,18,19} // lower part
};
}
return mesh;
}
float cross_pt_upper_y = groove_half_width_upper / tan(m_groove_angle);
// groove is closed
if (groove_half_width_upper < proj && groove_half_width_lower < proj) {
float cross_pt_lower_y = groove_half_width_lower / tan(m_groove_angle);
indexed_triangle_set mesh;
auto get_vertices = [x, y](float z_upper, float z_lower, float cross_pt_upper_y, float cross_pt_lower_y, float ext_upper_x, float ext_lower_x) {
return std::vector<stl_vertex>({
// upper part vertices
{-x, -y, z_upper}, {-x, y, z_upper}, {x, y, z_upper}, {x, -y, z_upper},
{ext_upper_x, -y, z_upper}, {0.f, cross_pt_upper_y, z_upper}, {-ext_upper_x, -y, z_upper},
// lower part vertices
{-ext_lower_x, -y, z_lower}, {0.f, cross_pt_lower_y, z_lower}, {ext_lower_x, -y, z_lower}
});
};
mesh.vertices = get_vertices(z_upper, z_lower, cross_pt_upper_y, cross_pt_lower_y, ext_upper_x, ext_lower_x);
mesh.vertices.reserve(2 * mesh.vertices.size());
z_upper -= cut_plane_thiknes;
z_lower -= cut_plane_thiknes;
if (m_use_TAG_mesh_full) {
const float under_x_shift = cut_plane_thiknes / tan(0.5f * m_groove_flaps_angle);
cross_pt_upper_y += cut_plane_thiknes;
cross_pt_lower_y += cut_plane_thiknes;
ext_upper_x += under_x_shift;
ext_lower_x += under_x_shift;
std::vector<stl_vertex> vertices = get_vertices(z_upper, z_lower, cross_pt_upper_y, cross_pt_lower_y, ext_upper_x, ext_lower_x);
mesh.vertices.insert(mesh.vertices.end(), vertices.begin(), vertices.end());
mesh.indices = {
// above view
{8,7,9}, // lower part
{5,8,6}, {6,8,7}, // left side
{4,9,8}, {4,8,5}, // right side
{1,0,6}, {1,6,5},{1,5,2}, {2,5,4}, {2,4,3}, // upper part
// under view
{10,11,16}, {16,11,15}, {15,11,12}, {15,12,14}, {14,12,13}, // upper part
{18,15,14}, {14,18,19}, // right side
{17,16,15}, {17,15,18}, // left side
{17,18,19}, // lower part
// left edge
{1,11,0}, {0,11,10},
// front edge
{0,10,6}, {6,10,16}, {6,17,16}, {6,7,17}, {7,17,19}, {7,19,9}, {4,14,19}, {4,19,9}, {4,14,13}, {4,13,3},
// right edge
{3,13,12}, {3,12,2},
// back edge
{2,12,11}, {2,11,1}
};
}
else {
std::vector<stl_vertex> vertices = get_vertices(z_upper, z_lower, cross_pt_upper_y, cross_pt_lower_y, ext_upper_x, ext_lower_x);
mesh.vertices.insert(mesh.vertices.end(), vertices.begin(), vertices.end());
mesh.indices = {
// above view
{8,7,9}, // lower part
{5,8,6}, {6,8,7}, // left side
{4,9,8}, {4,8,5}, // right side
{1,0,6}, {1,6,5},{1,5,2}, {2,5,4}, {2,4,3}, // upper part
// under view
{18,15,14}, {14,18,19}, // right side
{17,16,15}, {17,15,18}, // left side
{17,18,19}, // lower part
};
}
return mesh;
}
// groove is closed from the roof
indexed_triangle_set mesh;
mesh.vertices = {
// upper part vertices
{-x, -y, z_upper}, {-x, y, z_upper}, {x, y, z_upper}, {x, -y, z_upper},
{ext_upper_x, -y, z_upper}, {0.f, cross_pt_upper_y, z_upper}, {-ext_upper_x, -y, z_upper},
// lower part vertices
{-ext_lower_x, -y, z_lower}, {-nar_lower_x, y, z_lower}, {nar_lower_x, y, z_lower}, {ext_lower_x, -y, z_lower}
};
mesh.vertices.reserve(2 * mesh.vertices.size() + 1);
z_upper -= cut_plane_thiknes;
z_lower -= cut_plane_thiknes;
const float under_x_shift = cut_plane_thiknes / tan(0.5f * m_groove_flaps_angle);
nar_lower_x += under_x_shift;
ext_upper_x += under_x_shift;
ext_lower_x += under_x_shift;
std::vector<stl_vertex> vertices = {
// upper part vertices
{-x, -y, z_upper}, {-x, y, z_upper}, {x, y, z_upper}, {x, -y, z_upper},
{ext_upper_x, -y, z_upper}, {under_x_shift, cross_pt_upper_y, z_upper}, {-under_x_shift, cross_pt_upper_y, z_upper}, {-ext_upper_x, -y, z_upper},
// lower part vertices
{-ext_lower_x, -y, z_lower}, {-nar_lower_x, y, z_lower}, {nar_lower_x, y, z_lower}, {ext_lower_x, -y, z_lower}
};
mesh.vertices.insert(mesh.vertices.end(), vertices.begin(), vertices.end());
if (m_use_TAG_mesh_full) {
mesh.indices = {
// above view
{8,7,10}, {8,10,9}, // lower part
{5,8,7}, {5,7,6}, // left side
{4,10,9}, {4,9,5}, // right side
{1,0,6}, {1,6,5},{1,5,2}, {2,5,4}, {2,4,3}, // upper part
// under view
{11,12,18}, {18,12,17}, {17,12,16}, {16,12,13}, {16,13,15}, {15,13,14}, // upper part
{21,16,15}, {21,15,22}, // right side
{19,18,17}, {19,17,20}, // left side
{19,20,21}, {19,21,22}, // lower part
// left edge
{1,12,11}, {1,11,0},
// front edge
{0,11,18}, {0,18,6}, {7,19,18}, {7,18,6}, {7,19,22}, {7,22,10}, {10,22,15}, {10,15,4}, {4,15,14}, {4,14,3},
// right edge
{3,14,13}, {3,14,2},
// back edge
{2,13,12}, {2,12,1}, {5,16,21}, {5,21,9}, {9,21,20}, {9,20,8}, {5,17,20}, {5,20,8}
};
}
else {
mesh.indices = {
// above view
{8,7,10}, {8,10,9}, // lower part
{5,8,7}, {5,7,6}, // left side
{4,10,9}, {4,9,5}, // right side
{1,0,6}, {1,6,5}, {1,5,2}, {2,5,4}, {2,4,3}, // upper part
// under view
{21,16,15}, {21,15,22}, // right side
{19,18,17}, {19,17,20}, // left side
{19,20,21}, {19,21,22}, // lower part
};
}
return mesh;
}
void GLGizmoCut3D::render_cut_plate_for_tongue_and_groove(GLShaderProgram* shader)
{
const Camera & camera = wxGetApp().plater()->get_camera();
@ -925,6 +1187,17 @@ void GLGizmoCut3D::render_cut_plane()
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
if (m_use_TAG_mesh) {
ColorRGBA cp_clr = can_perform_cut() && has_valid_contour() ? CUT_PLANE_DEF_COLOR : CUT_PLANE_ERR_COLOR;
if (m_mode == size_t(CutMode::cutTongueAndGroove))
cp_clr.a(cp_clr.a() - 0.1f);
m_plane.model.set_color(cp_clr);
const Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
shader->set_uniform("view_model_matrix", view_model_matrix);
m_plane.model.render();
}
else {
m_plane.model.set_color(can_perform_cut() && has_valid_contour() ? CUT_PLANE_DEF_COLOR : CUT_PLANE_ERR_COLOR);
if (m_mode == size_t(CutMode::cutPlanar)) {
@ -934,7 +1207,7 @@ void GLGizmoCut3D::render_cut_plane()
}
else if (m_mode == size_t(CutMode::cutTongueAndGroove))
render_cut_plate_for_tongue_and_groove(shader);
}
glsafe(::glEnable(GL_CULL_FACE));
glsafe(::glDisable(GL_BLEND));
@ -1731,7 +2004,7 @@ void GLGizmoCut3D::update_bb()
// input params for cut with tongue and groove
m_groove_depth = m_groove_depth_init = 0.5f * float(get_grabber_mean_size(m_bounding_box));
m_groove_width = m_groove_width_init = 4.0f * m_groove_depth;
m_groove_flaps_angle = m_groove_flaps_angle_init = float(PI) / 3.f;// 0.25f * float(PI);
m_groove_flaps_angle = m_groove_flaps_angle_init = float(PI) / 3.f;
m_groove_angle = m_groove_angle_init = 0.f;
m_plane.reset();
m_cone.reset();
@ -1768,7 +2041,13 @@ void GLGizmoCut3D::init_picking_models()
if (!m_plane.model.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
const double cp_width = 0.02 * get_grabber_mean_size(m_bounding_box);
indexed_triangle_set its = its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4);
indexed_triangle_set its;
if (m_use_TAG_mesh)
its = m_mode == size_t(CutMode::cutTongueAndGroove) ? its_make_groove_plane() :
its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4);
else
its = its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4);
m_plane.model.init_from(its);
m_plane.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
}
@ -2097,12 +2376,23 @@ void GLGizmoCut3D::on_render()
void GLGizmoCut3D::render_debug_input_window(float x)
{
return;
m_imgui->begin(wxString("DEBUG"));
ImVec2 pos = ImGui::GetWindowPos();
pos.x = x;
ImGui::SetWindowPos(pos, ImGuiCond_Always);
bool is_changed = m_imgui->checkbox(("Render Cut plane as a one mesh"), m_use_TAG_mesh);
is_changed |= m_imgui->checkbox(("Render Cut plane as a full mesh"), m_use_TAG_mesh_full);
if (is_changed)
{
m_plane.reset();
on_unregister_raycasters_for_picking();
}
m_imgui->end();
return;
/*
static bool hide_clipped = false;
static bool fill_cut = false;
@ -2483,6 +2773,10 @@ void GLGizmoCut3D::render_groove_float_input(const std::string& label, float& in
m_imgui->disabled_end();
if (is_changed) {
if (m_use_TAG_mesh) {
m_plane.reset();
on_unregister_raycasters_for_picking();
}
reset_cut_by_contours();
// Plater::TakeSnapshot snapshot(wxGetApp().plater(), format_wxstr("%1%: %2%", _L("Groove change"), label), UndoRedo::SnapshotType::GizmoAction);
}
@ -2519,6 +2813,10 @@ void GLGizmoCut3D::render_groove_angle_input(const std::string& label, float& in
m_imgui->disabled_end();
if (is_changed) {
if (m_use_TAG_mesh) {
m_plane.reset();
on_unregister_raycasters_for_picking();
}
reset_cut_by_contours();
// Plater::TakeSnapshot snapshot(wxGetApp().plater(), format_wxstr("%1%: %2%", _L("Groove change"), label), UndoRedo::SnapshotType::GizmoAction);
}

View File

@ -235,6 +235,11 @@ class GLGizmoCut3D : public GLGizmoBase
std::map<std::string, std::string> m_labels_map;
// Debug values
bool m_use_TAG_mesh {true};
bool m_use_TAG_mesh_full {true};
//
public:
GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
@ -376,6 +381,7 @@ private:
indexed_triangle_set its_make_upper_groove_plane();
indexed_triangle_set its_make_lower_groove_plane(float flaps_width);
indexed_triangle_set its_make_sides_groove_plane(float flaps_width);
indexed_triangle_set its_make_groove_plane();
indexed_triangle_set get_connector_mesh(CutConnectorAttributes connector_attributes);
void apply_cut_connectors(ModelObject* mo, const std::string& connector_name);