OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::GLGizmoCut3D::PartSelection Class Reference
Collaboration diagram for Slic3r::GUI::GLGizmoCut3D::PartSelection:

Classes

struct  Part

Public Member Functions

 PartSelection ()=default
 PartSelection (const ModelObject *mo, const Transform3d &cut_matrix, int instance_idx, const Vec3d &center, const Vec3d &normal, const CommonGizmosDataObjects::ObjectClipper &oc)
 PartSelection (const ModelObject *mo, int instance_idx_in)
 ~PartSelection ()
void render (const Vec3d *normal, GLModel &sphere_model)
void toggle_selection (const Vec2d &mouse_pos)
void turn_over_selection ()
ModelObject * model_object ()
bool valid () const
bool is_one_object () const
const std::vector< Part > & parts () const
const std::vector< size_t > * get_ignored_contours_ptr () const
std::vector< Cut::Part > get_cut_parts ()

Private Member Functions

void add_object (const ModelObject *object)

Private Attributes

Model m_model
int m_instance_idx
std::vector< Part > m_parts
bool m_valid = false
std::vector< std::pair< std::vector< size_t >, std::vector< size_t > > > m_contour_to_parts
std::vector< size_t > m_ignored_contours
std::vector< Vec3d > m_contour_points
std::vector< std::vector< Vec3d > > m_debug_pts

Detailed Description


Class Documentation

◆ Slic3r::GUI::GLGizmoCut3D::PartSelection::Part

struct Slic3r::GUI::GLGizmoCut3D::PartSelection::Part
Collaboration diagram for Slic3r::GUI::GLGizmoCut3D::PartSelection::Part:
Class Members
GLModel glmodel
bool is_modifier
MeshRaycaster raycaster
bool selected

Constructor & Destructor Documentation

◆ PartSelection() [1/3]

Slic3r::GUI::GLGizmoCut3D::PartSelection::PartSelection ( )
default

References Slic3r::center(), and Slic3r::normal().

Here is the call graph for this function:

◆ PartSelection() [2/3]

Slic3r::GUI::GLGizmoCut3D::PartSelection::PartSelection ( const ModelObject * mo,
const Transform3d & cut_matrix,
int instance_idx,
const Vec3d & center,
const Vec3d & normal,
const CommonGizmosDataObjects::ObjectClipper & oc )
2083 : m_instance_idx(instance_idx_in)
2084{
2085 Cut cut(mo, instance_idx_in, cut_matrix);
2086 add_object(cut.perform_with_plane().front());
2087
2088 const ModelVolumePtrs& volumes = model_object()->volumes;
2089
2090 // split to parts
2091 for (int id = int(volumes.size())-1; id >= 0; id--)
2092 if (volumes[id]->is_splittable())
2093 volumes[id]->split(1, false); // No need to remap paint here, we do it later in perform_by_contour
2094
2095 m_parts.clear();
2096 for (const ModelVolume* volume : volumes) {
2097 assert(volume != nullptr);
2098 m_parts.emplace_back(Part{GLModel(), MeshRaycaster(volume->mesh()), true, !volume->is_model_part()});
2099 m_parts.back().glmodel.set_color({ 0.f, 0.f, 1.f, 1.f });
2100 m_parts.back().glmodel.init_from(volume->mesh());
2101
2102 // Now check whether this part is below or above the plane.
2103 Transform3d tr = (model_object()->instances[m_instance_idx]->get_matrix() * volume->get_matrix()).inverse();
2104 Vec3f pos = (tr * center).cast<float>();
2105 Vec3f norm = (tr.linear().inverse().transpose() * normal).cast<float>();
2106 for (const Vec3f& v : volume->mesh().its.vertices) {
2107 double p = (v - pos).dot(norm);
2108 if (std::abs(p) > EPSILON) {
2109 m_parts.back().selected = p > 0.;
2110 break;
2111 }
2112 }
2113 }
2114
2115 // Now go through the contours and create a map from contours to parts.
2116 m_contour_points.clear();
2117 m_contour_to_parts.clear();
2118 m_debug_pts = std::vector<std::vector<Vec3d>>(m_parts.size(), std::vector<Vec3d>());
2119 if (std::vector<Vec3d> pts = oc.point_per_contour();! pts.empty()) {
2120
2121 m_contour_to_parts.resize(pts.size());
2122
2123 for (size_t pt_idx=0; pt_idx<pts.size(); ++pt_idx) {
2124 const Vec3d& pt = pts[pt_idx];
2125 const Vec3d dir = (center-pt).dot(normal) * normal;
2126 m_contour_points.emplace_back(dir + pt); // the result is in world coordinates.
2127
2128 // Now, cast a ray from every contour point and see which volumes of the ones above
2129 // the plane are hit from the inside.
2130 for (size_t part_id=0; part_id<m_parts.size(); ++part_id) {
2131 const AABBMesh& aabb = m_parts[part_id].raycaster.get_aabb_mesh();
2132 const Transform3d& tr = (translation_transform(model_object()->instances[m_instance_idx]->get_offset()) * translation_transform(model_object()->volumes[part_id]->get_offset())).inverse();
2133 for (double d : {-1., 1.}) {
2134 const Vec3d dir_mesh = d * tr.linear().inverse().transpose() * normal;
2135 const Vec3d src = tr * (m_contour_points[pt_idx] + d*0.01 * normal);
2136 AABBMesh::hit_result hit = aabb.query_ray_hit(src, dir_mesh);
2137
2138 m_debug_pts[part_id].emplace_back(src);
2139
2140 if (hit.is_inside()) {
2141 // This part belongs to this point.
2142 if (d == 1.)
2143 m_contour_to_parts[pt_idx].first.emplace_back(part_id);
2144 else
2145 m_contour_to_parts[pt_idx].second.emplace_back(part_id);
2146 }
2147 }
2148 }
2149 }
2150
2151 }
2152
2153
2154 m_valid = true;
2155}
#define EPSILON
Definition ColorUtils.cpp:64
ModelObject * model_object()
Definition GLGizmoCut.hpp:197
void add_object(const ModelObject *object)
Definition GLGizmoCut.cpp:2068
int m_instance_idx
Definition GLGizmoCut.hpp:207
std::vector< std::pair< std::vector< size_t >, std::vector< size_t > > > m_contour_to_parts
Definition GLGizmoCut.hpp:210
std::vector< std::vector< Vec3d > > m_debug_pts
Definition GLGizmoCut.hpp:214
bool m_valid
Definition GLGizmoCut.hpp:209
std::vector< Part > m_parts
Definition GLGizmoCut.hpp:208
std::vector< Vec3d > m_contour_points
Definition GLGizmoCut.hpp:213
ModelInstancePtrs instances
Definition Model.hpp:390
ModelVolumePtrs volumes
Definition Model.hpp:393
@ Cut
Definition Shortcuts.hpp:33
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:346
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112
std::vector< ModelVolume * > ModelVolumePtrs
Definition Model.hpp:139
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References add_object(), Slic3r::cast(), Slic3r::center(), Slic3r::dot(), EPSILON, Slic3r::ModelObject::instances, m_contour_points, m_contour_to_parts, m_debug_pts, m_instance_idx, m_parts, m_valid, model_object(), Slic3r::normal(), Slic3r::Cut::perform_with_plane(), Slic3r::GUI::CommonGizmosDataObjects::ObjectClipper::point_per_contour(), Slic3r::AABBMesh::query_ray_hit(), Slic3r::Geometry::translation_transform(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ PartSelection() [3/3]

Slic3r::GUI::GLGizmoCut3D::PartSelection::PartSelection ( const ModelObject * mo,
int instance_idx_in )
2159 : m_instance_idx (instance_idx_in)
2160{
2161 add_object(object);
2162
2163 m_parts.clear();
2164
2165 for (const ModelVolume* volume : object->volumes) {
2166 assert(volume != nullptr);
2167 m_parts.emplace_back(Part{ GLModel(), MeshRaycaster(volume->mesh()), true, !volume->is_model_part() });
2168 m_parts.back().glmodel.init_from(volume->mesh());
2169
2170 // Now check whether this part is below or above the plane.
2171 m_parts.back().selected = volume->is_from_upper();
2172 }
2173
2174 m_valid = true;
2175}

References add_object(), Slic3r::ModelVolume::is_from_upper(), Slic3r::ModelVolume::is_model_part(), m_instance_idx, m_parts, m_valid, Slic3r::ModelVolume::mesh(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ ~PartSelection()

Slic3r::GUI::GLGizmoCut3D::PartSelection::~PartSelection ( )
inline
185{ m_model.clear_objects(); }
Model m_model
Definition GLGizmoCut.hpp:206

References m_model.

Member Function Documentation

◆ add_object()

void Slic3r::GUI::GLGizmoCut3D::PartSelection::add_object ( const ModelObject * object)
private
2069{
2070 m_model = Model();
2071 m_model.add_object(*object);
2072
2073 const double sla_shift_z = wxGetApp().plater()->canvas3D()->get_selection().get_first_volume()->get_sla_shift_z();
2074 if (!is_approx(sla_shift_z, 0.)) {
2075 Vec3d inst_offset = model_object()->instances[m_instance_idx]->get_offset();
2076 inst_offset[Z] += sla_shift_z;
2077 model_object()->instances[m_instance_idx]->set_offset(inst_offset);
2078 }
2079}
@ Z
Definition GLGizmoCut.hpp:45
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:320

References Slic3r::ModelObject::instances, Slic3r::is_approx(), m_instance_idx, m_model, model_object(), and Slic3r::GUI::GLGizmoCut3D::Z.

Referenced by PartSelection(), and PartSelection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_cut_parts()

std::vector< Cut::Part > Slic3r::GUI::GLGizmoCut3D::PartSelection::get_cut_parts ( )
2274{
2275 std::vector<Cut::Part> parts;
2276
2277 for (const auto& part : m_parts)
2278 parts.push_back({part.selected, part.is_modifier});
2279
2280 return parts;
2281}
const std::vector< Part > & parts() const
Definition GLGizmoCut.hpp:200

References m_parts, and parts().

Here is the call graph for this function:

◆ get_ignored_contours_ptr()

const std::vector< size_t > * Slic3r::GUI::GLGizmoCut3D::PartSelection::get_ignored_contours_ptr ( ) const
inline
201{ return (valid() ? &m_ignored_contours : nullptr); }
bool valid() const
Definition GLGizmoCut.hpp:198
std::vector< size_t > m_ignored_contours
Definition GLGizmoCut.hpp:211

References m_ignored_contours, and valid().

Here is the call graph for this function:

◆ is_one_object()

bool Slic3r::GUI::GLGizmoCut3D::PartSelection::is_one_object ( ) const
2260{
2261 // In theory, the implementation could be just this:
2262 // return m_contour_to_parts.size() == m_ignored_contours.size();
2263 // However, this would require that the part-contour correspondence works
2264 // flawlessly. Because it is currently not always so for self-intersecting
2265 // objects, let's better check the parts itself:
2266 if (m_parts.size() < 2)
2267 return true;
2268 return std::all_of(m_parts.begin(), m_parts.end(), [this](const Part& part) {
2269 return part.is_modifier || part.selected == m_parts.front().selected;
2270 });
2271}

References m_parts.

◆ model_object()

ModelObject * Slic3r::GUI::GLGizmoCut3D::PartSelection::model_object ( )
inline
197{ return m_model.objects.front(); }

References m_model.

Referenced by PartSelection(), add_object(), render(), and toggle_selection().

Here is the caller graph for this function:

◆ parts()

const std::vector< Part > & Slic3r::GUI::GLGizmoCut3D::PartSelection::parts ( ) const
inline
200{ return m_parts; }

References m_parts.

Referenced by get_cut_parts().

Here is the caller graph for this function:

◆ render()

void Slic3r::GUI::GLGizmoCut3D::PartSelection::render ( const Vec3d * normal,
GLModel & sphere_model )
2178{
2179 if (! valid())
2180 return;
2181
2182 const Camera& camera = wxGetApp().plater()->get_camera();
2183
2184 if (GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light")) {
2185 shader->start_using();
2186 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
2187 shader->set_uniform("emission_factor", 0.f);
2188
2189 // FIXME: Cache the transforms.
2190
2191 const Vec3d inst_offset = model_object()->instances[m_instance_idx]->get_offset();
2192 const Transform3d view_inst_matrix= camera.get_view_matrix() * translation_transform(inst_offset);
2193
2194 const bool is_looking_forward = normal && camera.get_dir_forward().dot(*normal) < 0.05;
2195
2196 for (size_t id=0; id<m_parts.size(); ++id) {
2197 if (!m_parts[id].is_modifier && normal && ((is_looking_forward && m_parts[id].selected) ||
2198 (!is_looking_forward && !m_parts[id].selected) ) )
2199 continue;
2200 shader->set_uniform("view_model_matrix", view_inst_matrix * model_object()->volumes[id]->get_matrix());
2201 if (m_parts[id].is_modifier) {
2204 }
2205 m_parts[id].glmodel.set_color(m_parts[id].is_modifier ? MODIFIER_COLOR : (m_parts[id].selected ? UPPER_PART_COLOR : LOWER_PART_COLOR));
2206 m_parts[id].glmodel.render();
2207 if (m_parts[id].is_modifier)
2209 }
2210
2211 shader->stop_using();
2212 }
2213
2214
2215
2216 // { // Debugging render:
2217
2218 // static int idx = -1;
2219 // ImGui::Begin("DEBUG");
2220 // for (int i=0; i<m_parts.size(); ++i)
2221 // if (ImGui::Button(std::to_string(i).c_str()))
2222 // idx = i;
2223 // if (idx >= m_parts.size())
2224 // idx = -1;
2225 // ImGui::End();
2226
2227 // ::glDisable(GL_DEPTH_TEST);
2228 // if (valid()) {
2229 // for (size_t i=0; i<m_contour_points.size(); ++i) {
2230 // const Vec3d& pt = m_contour_points[i];
2231 // ColorRGBA col = ColorRGBA::GREEN();
2232
2233 // bool red = false;
2234 // bool yellow = false;
2235 // for (size_t j=0; j<m_contour_to_parts[i].first.size(); ++j) {
2236 // red |= m_parts[m_contour_to_parts[i].first[j]].selected;
2237 // yellow |= m_parts[m_contour_to_parts[i].second[j]].selected;
2238 // }
2239 // if (red)
2240 // col = ColorRGBA::RED();
2241 // if (yellow)
2242 // col = ColorRGBA::YELLOW();
2243
2244 // GLGizmoCut3D::render_model(sphere_model, col, camera.get_view_matrix() * translation_transform(pt));
2245 // }
2246 // }
2247
2248 // if (idx != -1) {
2249 // render_model(m_parts[idx].glmodel, ColorRGBA::RED(), camera.get_view_matrix());
2250 // for (const Vec3d& pt : m_debug_pts[idx]) {
2251 // render_model(sphere_model, ColorRGBA::GREEN(), camera.get_view_matrix() * translation_transform(pt));
2252 // }
2253 // }
2254 // ::glEnable(GL_DEPTH_TEST);
2255 // }
2256}
#define glsafe(cmd)
Definition OpenGLUtils.hpp:25
bool is_looking_forward() const
Definition GLGizmoCut.cpp:496
#define glEnable
Definition gl.h:3667
#define GL_SRC_ALPHA
Definition gl.h:1621
#define GL_BLEND
Definition gl.h:275
#define GL_ONE_MINUS_SRC_ALPHA
Definition gl.h:1239
#define glDisable
Definition gl.h:3607
#define glBlendFunc
Definition gl.h:3325
@ Camera
Definition Shortcuts.hpp:72
static const ColorRGBA LOWER_PART_COLOR
Definition GLGizmoCut.cpp:82
static const ColorRGBA MODIFIER_COLOR
Definition GLGizmoCut.cpp:83
static const ColorRGBA UPPER_PART_COLOR
Definition GLGizmoCut.cpp:81

References Slic3r::GUI::Camera::get_dir_forward(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), GL_BLEND, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glDisable, glEnable, glsafe, Slic3r::GUI::GLGizmoCut3D::is_looking_forward(), Slic3r::GUI::LOWER_PART_COLOR, m_instance_idx, m_parts, model_object(), Slic3r::GUI::MODIFIER_COLOR, Slic3r::normal(), Slic3r::Geometry::translation_transform(), Slic3r::GUI::UPPER_PART_COLOR, and valid().

Here is the call graph for this function:

◆ toggle_selection()

void Slic3r::GUI::GLGizmoCut3D::PartSelection::toggle_selection ( const Vec2d & mouse_pos)
2285{
2286 // FIXME: Cache the transforms.
2287 const Camera& camera = wxGetApp().plater()->get_camera();
2288 const Vec3d& camera_pos = camera.get_position();
2289
2290 Vec3f pos;
2291 Vec3f normal;
2292
2293 std::vector<std::pair<size_t, double>> hits_id_and_sqdist;
2294
2295 for (size_t id=0; id<m_parts.size(); ++id) {
2296// const Vec3d volume_offset = model_object()->volumes[id]->get_offset();
2297 Transform3d tr = translation_transform(model_object()->instances[m_instance_idx]->get_offset()) * translation_transform(model_object()->volumes[id]->get_offset());
2298 if (m_parts[id].raycaster.unproject_on_mesh(mouse_pos, tr, camera, pos, normal)) {
2299 hits_id_and_sqdist.emplace_back(id, (camera_pos - tr*(pos.cast<double>())).squaredNorm());
2300 }
2301 }
2302 if (! hits_id_and_sqdist.empty()) {
2303 size_t id = std::min_element(hits_id_and_sqdist.begin(), hits_id_and_sqdist.end(),
2304 [](const std::pair<size_t, double>& a, const std::pair<size_t, double>& b) { return a.second < b.second; })->first;
2305 m_parts[id].selected = ! m_parts[id].selected;
2306
2307 // And now recalculate the contours which should be ignored.
2308 m_ignored_contours.clear();
2309 size_t cont_id = 0;
2310 for (const auto& [parts_above, parts_below] : m_contour_to_parts) {
2311 for (size_t upper : parts_above) {
2312 bool upper_sel = m_parts[upper].selected;
2313 if (std::find_if(parts_below.begin(), parts_below.end(), [this, &upper_sel](const size_t& i) { return m_parts[i].selected == upper_sel; }) != parts_below.end()) {
2314 m_ignored_contours.emplace_back(cont_id);
2315 break;
2316 }
2317 }
2318 ++cont_id;
2319 }
2320 }
2321}

References Slic3r::GUI::Camera::get_position(), m_contour_to_parts, m_ignored_contours, m_instance_idx, m_parts, model_object(), Slic3r::normal(), and Slic3r::Geometry::translation_transform().

Here is the call graph for this function:

◆ turn_over_selection()

void Slic3r::GUI::GLGizmoCut3D::PartSelection::turn_over_selection ( )
2324{
2325 for (Part& part : m_parts)
2326 part.selected = !part.selected;
2327}

References m_parts.

◆ valid()

bool Slic3r::GUI::GLGizmoCut3D::PartSelection::valid ( ) const
inline
198{ return m_valid; }

References m_valid.

Referenced by get_ignored_contours_ptr(), and render().

Here is the caller graph for this function:

Member Data Documentation

◆ m_contour_points

std::vector<Vec3d> Slic3r::GUI::GLGizmoCut3D::PartSelection::m_contour_points
private

Referenced by PartSelection().

◆ m_contour_to_parts

std::vector<std::pair<std::vector<size_t>, std::vector<size_t> > > Slic3r::GUI::GLGizmoCut3D::PartSelection::m_contour_to_parts
private

Referenced by PartSelection(), and toggle_selection().

◆ m_debug_pts

std::vector<std::vector<Vec3d> > Slic3r::GUI::GLGizmoCut3D::PartSelection::m_debug_pts
private

Referenced by PartSelection().

◆ m_ignored_contours

std::vector<size_t> Slic3r::GUI::GLGizmoCut3D::PartSelection::m_ignored_contours
private

◆ m_instance_idx

int Slic3r::GUI::GLGizmoCut3D::PartSelection::m_instance_idx
private

◆ m_model

Model Slic3r::GUI::GLGizmoCut3D::PartSelection::m_model
private

◆ m_parts

std::vector<Part> Slic3r::GUI::GLGizmoCut3D::PartSelection::m_parts
private

◆ m_valid

bool Slic3r::GUI::GLGizmoCut3D::PartSelection::m_valid = false
private

Referenced by PartSelection(), PartSelection(), and valid().


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp