OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::GLCanvas3D::CenterOfMass Class Reference
Collaboration diagram for Slic3r::GUI::GLCanvas3D::CenterOfMass:

Classes

struct  Marker
struct  Bodies
struct  Pick

Public Member Functions

void render (GLCanvas3D &canvas)
bool on_left_down (GLCanvas3D &canvas, const Vec2d &mouse)
void render_details (GLCanvas3D &canvas)

Private Types

enum  MarkerKind : size_t {
  mkPlate , mkObject , mkSupport , mkBody ,
  mkCount
}
using Sum = GCodeProcessorResult::ObjectMass::Sum
using Markers = std::array<std::vector<Marker>, mkCount>

Private Member Functions

Markers model_markers (const GLCanvas3D &canvas)

Private Attributes

std::array< GLModel, 2 > m_octants
std::map< size_t, MassProperties > m_meshes
std::map< size_t, Bodies > m_bodies
std::array< Markers, 2 > m_drawn
size_t m_top_layer { 0 }
std::optional< Pick > m_picked

Detailed Description


Class Documentation

◆ Slic3r::GUI::GLCanvas3D::CenterOfMass::Bodies

struct Slic3r::GUI::GLCanvas3D::CenterOfMass::Bodies
Collaboration diagram for Slic3r::GUI::GLCanvas3D::CenterOfMass::Bodies:
Class Members
vector< SolidBody > bodies
size_t slabs { 0 }
vector< Volume > volumes

◆ Slic3r::GUI::GLCanvas3D::CenterOfMass::Pick

struct Slic3r::GUI::GLCanvas3D::CenterOfMass::Pick
Class Members
size_t count
size_t index
size_t kind
size_t set

Member Typedef Documentation

◆ Markers

using Slic3r::GUI::GLCanvas3D::CenterOfMass::Markers = std::array<std::vector<Marker>, mkCount>
private

◆ Sum

Member Enumeration Documentation

◆ MarkerKind

Enumerator
mkPlate 
mkObject 
mkSupport 
mkBody 
mkCount 
487: size_t { mkPlate, mkObject, mkSupport, mkBody, mkCount };
@ mkBody
Definition GLCanvas3D.hpp:487
@ mkObject
Definition GLCanvas3D.hpp:487
@ mkCount
Definition GLCanvas3D.hpp:487
@ mkSupport
Definition GLCanvas3D.hpp:487
@ mkPlate
Definition GLCanvas3D.hpp:487

Member Function Documentation

◆ model_markers()

GLCanvas3D::CenterOfMass::Markers Slic3r::GUI::GLCanvas3D::CenterOfMass::model_markers ( const GLCanvas3D & canvas)
private
1035{
1036 Markers markers;
1037 if (canvas.get_model() == nullptr)
1038 return markers;
1039
1040 struct Instance
1041 {
1042 Transform3d trafo;
1043 std::vector<const GLVolume*> volumes;
1044 };
1045 std::map<int, std::map<int, Instance>> objects;
1046 const ModelObjectPtrs& model_objects = canvas.get_model()->objects;
1047 for (const GLVolume* volume : canvas.get_volumes().volumes) {
1048 const int obj_idx = volume->object_idx();
1049 const int vol_idx = volume->volume_idx();
1050 if (!volume->is_active || volume->is_wipe_tower || obj_idx < 0 || obj_idx >= int(model_objects.size()) || vol_idx < 0 ||
1051 vol_idx >= int(model_objects[obj_idx]->volumes.size()))
1052 continue;
1053 Instance& instance = objects[obj_idx][volume->instance_idx()];
1054 instance.trafo = volume->get_instance_transformation().get_matrix();
1055 instance.volumes.emplace_back(volume);
1056 }
1057
1058 // From the filament presets, as the plater config holds the values of the last filament edited only.
1059 const PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
1060 std::vector<double> filament_densities;
1061 for (const std::string& name : preset_bundle.filament_presets)
1062 filament_densities.emplace_back(preset_bundle.filaments.find_preset(name, true)->config.opt_float("filament_density", 0));
1063 const auto density = [&filament_densities](const ModelVolume& volume) {
1064 const size_t filament = size_t(std::max(1, volume.extruder_id()));
1065 const double density = filament <= filament_densities.size() ? filament_densities[filament - 1] : 0.;
1066 return density > 0. ? density : double(DEFAULT_FILAMENT_DENSITY);
1067 };
1068
1069 // One per plate, of the instances on it.
1070 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
1071 std::map<int, Marker> plates;
1072 std::map<size_t, MassProperties> meshes;
1073 std::map<size_t, Bodies> bodies;
1074 for (const auto& [obj_idx, instances] : objects) {
1075 const ModelObject& object = *model_objects[obj_idx];
1076 // An assembly is sliced, so that its overlapping parts are united and its negative volumes cut away, in the
1077 // order of its volumes, as the later one prints where two overlap.
1078 std::vector<const GLVolume*> volumes = instances.begin()->second.volumes;
1079 std::sort(volumes.begin(), volumes.end(), [](const GLVolume* l, const GLVolume* r) { return l->volume_idx() < r->volume_idx(); });
1080 std::vector<MeshInPlace> solids;
1081 std::vector<double> densities;
1082 std::vector<MeshInPlace> negatives;
1083 std::vector<Bodies::Volume> sliced;
1084 for (const GLVolume* volume : volumes) {
1085 const ModelVolume& model_volume = *object.volumes[volume->volume_idx()];
1086 if (!model_volume.is_model_part() && !model_volume.is_negative_volume())
1087 continue;
1088 const Transform3d trafo = volume->get_volume_transformation().get_matrix();
1089 if (model_volume.is_model_part()) {
1090 solids.emplace_back(&model_volume.mesh().its, trafo);
1091 densities.emplace_back(density(model_volume));
1092 } else
1093 negatives.emplace_back(&model_volume.mesh().its, trafo);
1094 sliced.push_back({ model_volume.id().id, model_volume.is_negative_volume(), model_volume.is_model_part() ? densities.back() : 0., trafo });
1095 }
1096 const std::vector<SolidBody>* assembly = nullptr;
1097 if (solids.size() > 1 || (!solids.empty() && !negatives.empty())) {
1098 // Coarser while a part is dragged.
1099 const size_t slabs = canvas.is_dragging() ? 100 : 500;
1100 const auto cached = m_bodies.find(object.id().id);
1101 const bool valid = cached != m_bodies.end() && cached->second.slabs >= slabs && cached->second.volumes == sliced;
1102 Bodies& entry = bodies[object.id().id];
1103 entry = valid ? std::move(cached->second) : Bodies{ std::move(sliced), slabs, solid_bodies(solids, densities, negatives, slabs) };
1104 assembly = &entry.bodies;
1105 }
1106
1107 for (const auto& [inst_idx, instance] : instances) {
1108 // The box of its parts, which the object's size shows.
1109 Marker object_marker;
1110 object_marker.assembly = assembly != nullptr;
1111 for (const GLVolume* volume : instance.volumes)
1112 if (object.volumes[volume->volume_idx()]->is_model_part())
1113 object_marker.box.merge(volume->transformed_convex_hull_bounding_box());
1114 if (assembly != nullptr) {
1115 std::vector<Marker> parts;
1116 for (const SolidBody& body : *assembly)
1117 if (body.mass > 0.) {
1118 parts.push_back({ mass_sum(body.transformed(instance.trafo)), body.bounding_box(instance.trafo) });
1119 object_marker.sum.add(parts.back().sum);
1120 }
1121 if (parts.size() > 1)
1122 append(markers[mkBody], std::move(parts));
1123 } else
1124 for (const GLVolume* volume : instance.volumes) {
1125 // The parts the object info's volume sums.
1126 const ModelVolume& model_volume = *object.volumes[volume->volume_idx()];
1127 if (!model_volume.is_model_part())
1128 continue;
1129 const auto [it, inserted] = meshes.try_emplace(model_volume.id().id);
1130 if (inserted) {
1131 const auto cached = m_meshes.find(it->first);
1132 it->second = cached != m_meshes.end() ? cached->second : its_mass_properties(model_volume.mesh().its);
1133 }
1134 MassProperties part = it->second.transformed(volume->world_matrix());
1135 part.mass *= density(model_volume);
1136 object_marker.sum.add(mass_sum(part));
1137 }
1138 if (object_marker.sum.mass > 0.) {
1139 if (const int plate = plate_list.find_instance(obj_idx, inst_idx); plate >= 0) {
1140 plates[plate].sum.add(object_marker.sum);
1141 plates[plate].box.merge(object_marker.box);
1142 }
1143 markers[mkObject].emplace_back(std::move(object_marker));
1144 }
1145 }
1146 }
1147 m_meshes = std::move(meshes);
1148 m_bodies = std::move(bodies);
1149 for (auto& [plate, marker] : plates)
1150 markers[mkPlate].emplace_back(std::move(marker));
1151 return markers;
1152}
std::map< size_t, MassProperties > m_meshes
Definition GLCanvas3D.hpp:504
std::array< std::vector< Marker >, mkCount > Markers
Definition GLCanvas3D.hpp:499
std::map< size_t, Bodies > m_bodies
Definition GLCanvas3D.hpp:524
@ Instance
Definition GUI_Geometry.hpp:10
static GCodeProcessorResult::ObjectMass::Sum mass_sum(const MassProperties &solid)
Definition GLCanvas3D.cpp:1014
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
std::vector< SolidBody > solid_bodies(const std::vector< MeshInPlace > &solids, const std::vector< double > &densities, const std::vector< MeshInPlace > &negatives, size_t slabs)
Definition ConnectedBodies.cpp:184
constexpr float DEFAULT_FILAMENT_DENSITY
Definition GCodeProcessor.hpp:42
MassProperties its_mass_properties(const indexed_triangle_set &its)
Definition TriangleMesh.cpp:1508
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157
bool assembly
Definition GLCanvas3D.hpp:494

References Slic3r::GUI::GLCanvas3D::GLCanvas3D(), Slic3r::GCodeProcessorResult::ObjectMass::Sum::add(), Slic3r::append(), Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::assembly, Slic3r::GUI::GLCanvas3D::CenterOfMass::Bodies::bodies, Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::box, Slic3r::Preset::config, Slic3r::DEFAULT_FILAMENT_DENSITY, Slic3r::PresetBundle::filament_presets, Slic3r::PresetBundle::filaments, Slic3r::GUI::PartPlateList::find_instance(), Slic3r::PresetCollection::find_preset(), Slic3r::GUI::GLCanvas3D::get_model(), Slic3r::GUI::GLCanvas3D::get_volumes(), Slic3r::ObjectBase::id(), Slic3r::ObjectID::id, Slic3r::GUI::Instance, Slic3r::GUI::GLCanvas3D::is_dragging(), Slic3r::ModelVolume::is_model_part(), Slic3r::ModelVolume::is_negative_volume(), Slic3r::TriangleMesh::its, Slic3r::its_mass_properties(), m_bodies, m_meshes, Slic3r::GCodeProcessorResult::ObjectMass::Sum::mass, Slic3r::MassProperties::mass, Slic3r::GUI::mass_sum(), Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::ModelVolume::mesh(), mkBody, mkObject, mkPlate, model_markers(), Slic3r::Model::objects, Slic3r::DynamicConfig::opt_float(), Slic3r::solid_bodies(), Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::sum, Slic3r::MassProperties::transformed(), Slic3r::GLVolume::transformed_convex_hull_bounding_box(), Slic3r::GLVolume::volume_idx(), Slic3r::GLVolumeCollection::volumes, and Slic3r::GLVolume::world_matrix().

Referenced by model_markers(), and render().

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

◆ on_left_down()

bool Slic3r::GUI::GLCanvas3D::CenterOfMass::on_left_down ( GLCanvas3D & canvas,
const Vec2d & mouse )
1248{
1249 const bool shown = m_picked.has_value();
1250 const Camera& camera = wxGetApp().plater()->get_camera();
1251 const double scale = marker_scale(canvas) * camera.get_inv_zoom();
1252 m_picked.reset();
1253 // In the order they cover each other: what is printed so far over the finished print, smaller kinds over larger ones.
1254 for (size_t set = m_drawn.size(); set-- > 0 && !m_picked;)
1255 for (size_t kind = mkCount; kind-- > 0 && !m_picked;)
1256 for (size_t index = 0; index < m_drawn[set][kind].size(); ++index) {
1257 const Vec3d center = m_drawn[set][kind][index].center();
1258 const std::vector<Vec3d> ends = { center, center + marker_radii[kind] * scale * camera.get_dir_right() };
1259 const Points screen = CameraUtils::project(camera, ends);
1260 if ((screen[0].cast<double>() - mouse).norm() <= (screen[1] - screen[0]).cast<double>().norm()) {
1261 m_picked = Pick{ set, kind, index, m_drawn[set][kind].size() };
1262 break;
1263 }
1264 }
1265 if (shown || m_picked)
1266 canvas._set_overlay_as_dirty();
1267 return m_picked.has_value();
1268}
int scale(const int val)
Definition WipeTowerDialog.cpp:58
static Points project(const Camera &camera, const std::vector< Vec3d > &points)
Project point throw camera to 2d coordinate into imgui window.
Definition CameraUtils.cpp:23
std::optional< Pick > m_picked
Definition GLCanvas3D.hpp:536
std::array< Markers, 2 > m_drawn
Definition GLCanvas3D.hpp:526
Definition GLCanvas3D.hpp:530
Camera camera
Definition GLCanvas3D.hpp:794
@ Camera
Definition Shortcuts.hpp:72
static constexpr std::array< double, 4 > marker_radii
Definition GLCanvas3D.cpp:1022
static double marker_scale(const GLCanvas3D &canvas)
Definition GLCanvas3D.cpp:1025
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299
void set(id object, const void *key, id value)
Definition MacIME.mm:24
Vec3d get_dir_right() const
Definition Camera.hpp:121
double get_inv_zoom() const
Definition Camera.hpp:104

References Slic3r::GUI::GLCanvas3D::GLCanvas3D(), Slic3r::GUI::GLCanvas3D::_set_overlay_as_dirty(), Slic3r::GUI::GLCanvas3D::camera, Slic3r::cast(), Slic3r::center(), m_drawn, m_picked, Slic3r::GUI::marker_radii, Slic3r::GUI::marker_scale(), mkCount, on_left_down(), Slic3r::GUI::CameraUtils::project(), and scale().

Referenced by on_left_down().

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

◆ render()

void Slic3r::GUI::GLCanvas3D::CenterOfMass::render ( GLCanvas3D & canvas)
1155{
1156 m_drawn = {};
1157 const bool preview = canvas.m_canvas_type == ECanvasType::CanvasPreview;
1158 // The other gizmos work on the surface the marker would cover.
1159 const GLGizmosManager::EType gizmo = canvas.get_gizmos_manager().get_current_type();
1160 if (!wxGetApp().show_center_of_mass() || canvas.m_design_canvas ||
1161 !(canvas.m_canvas_type == ECanvasType::CanvasView3D || (preview && canvas.m_render_preview)) ||
1164 return;
1165 GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
1166 if (shader == nullptr)
1167 return;
1168
1169 // Preview adds markers for what is printed up to the top layer shown.
1170 if (preview) {
1171 const GCodeViewer& gcode_viewer = canvas.get_gcode_viewer();
1172 m_top_layer = gcode_viewer.get_layers_z_range()[1];
1173 const auto add = [this](const GCodeProcessorResult::ObjectMass& mass, MarkerKind kind) {
1174 if (const Sum total = mass.total(); total.mass > 0.)
1175 m_drawn[0][kind].push_back({ total, mass.box, mass.assembly });
1176 if (!mass.printed_up_to_layer.empty())
1177 if (const Sum& sum = mass.printed_up_to_layer[std::min(m_top_layer, mass.printed_up_to_layer.size() - 1)]; sum.mass > 0.)
1178 m_drawn[1][kind].push_back({ sum, mass.box, mass.assembly });
1179 };
1180 add(gcode_viewer.get_plate_mass(), mkPlate);
1181 for (const GCodeProcessorResult::ObjectMass& object : gcode_viewer.get_object_masses())
1182 add(object, mkObject);
1183 for (const GCodeProcessorResult::ObjectMass& body : gcode_viewer.get_body_masses())
1184 add(body, mkBody);
1185 for (const GCodeProcessorResult::ObjectMass& support : gcode_viewer.get_support_masses())
1186 add(support, mkSupport);
1187 } else
1188 m_drawn[0] = model_markers(canvas);
1189 if (std::all_of(m_drawn.begin(), m_drawn.end(),
1190 [](const Markers& markers) { return std::all_of(markers.begin(), markers.end(), [](const auto& kind) { return kind.empty(); }); }))
1191 return;
1192
1193 if (!m_octants[0].is_initialized()) {
1194 // A resolution divisible by 4 puts every triangle within one octant.
1195 const GLModel::Geometry sphere = smooth_sphere(32, 1.f);
1196 std::array<GLModel::Geometry, 2> octants;
1197 for (size_t i = 0; i + 2 < sphere.indices_count(); i += 3) {
1198 const std::array<unsigned int, 3> ids = { sphere.extract_index(i), sphere.extract_index(i + 1), sphere.extract_index(i + 2) };
1199 const Vec3f c = sphere.extract_position_3(ids[0]) + sphere.extract_position_3(ids[1]) + sphere.extract_position_3(ids[2]);
1200 GLModel::Geometry& octant = octants[c.x() * c.y() * c.z() > 0.f ? 0 : 1];
1201 for (const unsigned int id : ids)
1202 octant.add_vertex(sphere.extract_position_3(id), sphere.extract_normal_3(id));
1203 const auto n = (unsigned int)octant.vertices_count();
1204 octant.add_triangle(n - 3, n - 2, n - 1);
1205 }
1206 for (size_t i = 0; i < octants.size(); ++i)
1207 m_octants[i].init_from(std::move(octants[i]));
1208 }
1209
1210 const Camera& camera = wxGetApp().plater()->get_camera();
1211 const Transform3d& view_matrix = camera.get_view_matrix();
1212 const double scale = marker_scale(canvas) * camera.get_inv_zoom();
1213
1214 // Seen through the object it lies in; culling keeps the sphere's far half behind its near one.
1217 shader->start_using();
1218 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
1219 shader->set_uniform("view_normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3));
1220 shader->set_uniform("emission_factor", 0.1f);
1221 const std::array<std::array<ColorRGBA, 2>, mkCount> colors = { {
1222 { ColorRGBA(0.1f, 0.1f, 0.1f, 1.f), ColorRGBA::WHITE() },
1223 { ColorRGBA(0x5A / 255.f, 0x9B / 255.f, 0xD4 / 255.f, 1.f), ColorRGBA::WHITE() },
1224 { ColorRGBA(0.f, 0.6f, 0.f, 1.f), ColorRGBA(0.1f, 0.1f, 0.1f, 1.f) },
1225 { ColorRGBA(0.7f, 0.f, 0.f, 1.f), ColorRGBA::YELLOW() },
1226 } };
1227 const auto draw = [&](const Markers& markers, float alpha) {
1228 for (size_t kind = 0; kind < mkCount; ++kind)
1229 for (const Marker& marker : markers[kind]) {
1230 shader->set_uniform("view_model_matrix", view_matrix * Geometry::translation_transform(marker.center()) *
1232 for (size_t i = 0; i < m_octants.size(); ++i) {
1233 ColorRGBA color = colors[kind][i];
1234 color.a(alpha);
1235 m_octants[i].set_color(color);
1236 m_octants[i].render();
1237 }
1238 }
1239 };
1240 // Preview fades the finished parts' markers under those of what is printed so far.
1241 draw(m_drawn[0], preview ? 0.4f : 1.f);
1242 draw(m_drawn[1], 1.f);
1243 shader->stop_using();
1245}
#define glsafe(cmd)
Definition OpenGLUtils.hpp:25
static const ColorRGBA YELLOW()
Definition Color.hpp:141
static const ColorRGBA WHITE()
Definition Color.hpp:142
GCodeProcessorResult::ObjectMass::Sum Sum
Definition GLCanvas3D.hpp:486
Markers model_markers(const GLCanvas3D &canvas)
Definition GLCanvas3D.cpp:1034
MarkerKind
Definition GLCanvas3D.hpp:487
std::array< GLModel, 2 > m_octants
Definition GLCanvas3D.hpp:502
size_t m_top_layer
Definition GLCanvas3D.hpp:527
bool is_initialized() const
Definition GLCanvas3D.hpp:948
@ CanvasPreview
Definition GLCanvas3D.hpp:627
@ CanvasView3D
Definition GLCanvas3D.hpp:626
EType
Definition GLGizmosManager.hpp:86
@ Move
Definition GLGizmosManager.hpp:88
@ Flatten
Definition GLGizmosManager.hpp:91
@ Undefined
Definition GLGizmosManager.hpp:109
@ Scale
Definition GLGizmosManager.hpp:90
@ Rotate
Definition GLGizmosManager.hpp:89
#define glEnable
Definition gl.h:3667
#define GL_DEPTH_TEST
Definition gl.h:574
#define GL_CULL_FACE
Definition gl.h:500
#define glDisable
Definition gl.h:3607
void draw(const IconManager::Icon &icon, const ImVec2 &size, const ImVec4 &tint_col, const ImVec4 &border_col)
Draw imgui image with icon.
Definition IconManager.cpp:373
@ GCodeViewer
Definition Process.cpp:38
GLModel::Geometry smooth_sphere(unsigned int resolution, float radius)
Definition GLModel.cpp:1293
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:346
void scale_transform(Transform3d &transform, double scale)
Definition Geometry.cpp:372
SpiralVase::SpiralPoint add(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:26
indexed_triangle_set sphere(double rho, Portion portion, double fa)
Definition SupportTreeMesher.cpp:14
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
Eigen::Matrix< double, 3, 3, Eigen::DontAlign > Matrix3d
Definition Point.hpp:86
const Transform3d & get_projection_matrix() const
Definition Camera.hpp:116
const Transform3d & get_view_matrix() const
Definition Camera.hpp:115

References Slic3r::GUI::GLCanvas3D::GLCanvas3D(), Slic3r::GCodeProcessorResult::ObjectMass::assembly, Slic3r::GCodeProcessorResult::ObjectMass::box, Slic3r::GUI::GLCanvas3D::CanvasPreview, Slic3r::GUI::GLCanvas3D::CanvasView3D, Slic3r::GUI::GLGizmosManager::Flatten, Slic3r::GUI::GCodeViewer::get_body_masses(), Slic3r::GUI::GLGizmosManager::get_current_type(), Slic3r::GUI::GLCanvas3D::get_gcode_viewer(), Slic3r::GUI::GLCanvas3D::get_gizmos_manager(), Slic3r::GUI::GCodeViewer::get_layers_z_range(), Slic3r::GUI::GCodeViewer::get_object_masses(), Slic3r::GUI::GCodeViewer::get_plate_mass(), Slic3r::GUI::GCodeViewer::get_support_masses(), Slic3r::GUI::GLCanvas3D::m_canvas_type, Slic3r::GUI::GLCanvas3D::m_design_canvas, m_drawn, Slic3r::GUI::GLCanvas3D::m_render_preview, m_top_layer, Slic3r::GCodeProcessorResult::ObjectMass::Sum::mass, mkBody, mkObject, mkPlate, mkSupport, model_markers(), Slic3r::GUI::GLGizmosManager::Move, Slic3r::GCodeProcessorResult::ObjectMass::printed_up_to_layer, render(), Slic3r::GUI::GLGizmosManager::Rotate, Slic3r::GUI::GLGizmosManager::Scale, Slic3r::GCodeProcessorResult::ObjectMass::total(), and Slic3r::GUI::GLGizmosManager::Undefined.

Referenced by render().

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

◆ render_details()

void Slic3r::GUI::GLCanvas3D::CenterOfMass::render_details ( GLCanvas3D & canvas)
1271{
1272 if (!m_picked)
1273 return;
1274 const Pick& pick = *m_picked;
1275 const std::vector<Marker>& markers = m_drawn[pick.set][pick.kind];
1276 // Gone with the markers, or with what it stood for.
1277 if (markers.size() != pick.count) {
1278 m_picked.reset();
1279 return;
1280 }
1281 const Marker& marker = markers[pick.index];
1282 const Sum& sum = marker.sum;
1283 const Vec3d center = marker.center();
1284 // About the axes through the center, from how far the mass spreads along the two others.
1285 const Vec3d spread = (sum.second / sum.mass - center.cwiseProduct(center)).cwiseMax(0.);
1286 const Vec3d inertia = sum.mass * Vec3d(spread.y() + spread.z(), spread.x() + spread.z(), spread.x() + spread.y());
1287
1288 // Beside the marker.
1289 const Point screen = CameraUtils::project(wxGetApp().plater()->get_camera(), center);
1290 ImGuiWrapper& imgui = *wxGetApp().imgui();
1291 imgui.set_next_window_pos(float(screen.x() + 2. * marker_radii[pick.kind] * marker_scale(canvas)), float(screen.y()), ImGuiCond_Always, 0.f, 0.5f);
1292 const std::string title = pick.kind == mkPlate ? _u8L("Plate center of mass") :
1293 pick.kind == mkBody ? _u8L("Part center of mass") :
1294 pick.kind == mkSupport ? _u8L("Support center of mass") :
1295 marker.assembly ? _u8L("Assembly center of mass") :
1296 _u8L("Object center of mass");
1297 bool open = true;
1298 imgui.begin(title + "###center_of_mass", &open,
1299 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
1300 if (ImGui::IsWindowAppearing())
1301 imgui.set_requires_extra_frame();
1302 if (canvas.get_canvas_type() == ECanvasType::CanvasPreview)
1303 imgui.text(pick.set == 0 ? _u8L("Finished print") : (boost::format(_u8L("Printed up to layer %1%")) % (m_top_layer + 1)).str());
1304 // Masses are in mg, volumes in mm³.
1305 const auto xyz = [](const Vec3d& v, const char* format, const std::string& unit) {
1306 return (boost::format(format) % v.x() % v.y() % v.z()).str() + " " + unit;
1307 };
1308 if (ImGui::BeginTable("##center_of_mass_details", 2)) {
1309 const auto row = [](const std::string& label, const std::string& value) {
1310 ImGui::TableNextRow();
1311 ImGui::TableSetColumnIndex(0);
1313 ImGui::TableSetColumnIndex(1);
1314 ImGuiWrapper::text(value);
1315 };
1316 row(_u8L("Weight"), (boost::format("%.2f g") % (sum.mass / 1000.)).str());
1317 row(_u8L("Volume"), (boost::format(u8"%.2f cm³") % (sum.volume / 1000.)).str());
1318 if (marker.box.defined) {
1319 row(_u8L("Center in bounding box"), xyz(center - marker.box.min, "X: %.2f, Y: %.2f, Z: %.2f", _u8L("mm")));
1320 row(_u8L("Bounding box size"), xyz(marker.box.size(), "X: %.2f, Y: %.2f, Z: %.2f", _u8L("mm")));
1321 }
1322 row(_u8L("Moment of inertia"), xyz(inertia / 1000., "X: %.0f, Y: %.0f, Z: %.0f", u8"g·mm²"));
1323 ImGui::EndTable();
1324 }
1325 imgui.end();
1326 if (!open) {
1327 m_picked.reset();
1328 canvas._set_overlay_as_dirty();
1329 }
1330}
Camera & get_camera()
Definition GLCanvas3D.cpp:2194
static void text_colored(const ImVec4 &color, const char *label)
Definition ImGuiWrapper.cpp:1157
static const ImVec4 COL_ORCA
Definition ImGuiWrapper.hpp:408
static void text(const char *label)
Definition ImGuiWrapper.cpp:1128
static Plater * plater()
Definition GUI_Factories.cpp:400
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
#define _u8L(s)
Definition I18N.hpp:11

References Slic3r::GUI::GLCanvas3D::GLCanvas3D(), Slic3r::GUI::GLCanvas3D::_set_overlay_as_dirty(), _u8L, Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::assembly, Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::box, Slic3r::GUI::GLCanvas3D::CanvasPreview, Slic3r::center(), Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::center(), Slic3r::GUI::ImGuiWrapper::COL_ORCA, Slic3r::GUI::GLCanvas3D::CenterOfMass::Pick::count, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::defined, Slic3r::GUI::ImGuiWrapper::end(), Slic3r::GUI::format(), Slic3r::GUI::GLCanvas3D::get_camera(), Slic3r::GUI::GLCanvas3D::get_canvas_type(), Slic3r::GUI::GLCanvas3D::CenterOfMass::Pick::index, Slic3r::GUI::GLCanvas3D::CenterOfMass::Pick::kind, m_drawn, m_picked, m_top_layer, Slic3r::GUI::marker_radii, Slic3r::GUI::marker_scale(), Slic3r::GCodeProcessorResult::ObjectMass::Sum::mass, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, mkBody, mkPlate, mkSupport, Slic3r::GUI::plater(), Slic3r::GUI::CameraUtils::project(), render_details(), Slic3r::GCodeProcessorResult::ObjectMass::Sum::second, Slic3r::GUI::GLCanvas3D::CenterOfMass::Pick::set, Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), Slic3r::GUI::ImGuiWrapper::set_requires_extra_frame(), Slic3r::BoundingBox3Base< PointType >::size(), Slic3r::GUI::GLCanvas3D::CenterOfMass::Marker::sum, Slic3r::GUI::ImGuiWrapper::text(), Slic3r::GUI::ImGuiWrapper::text_colored(), and Slic3r::GCodeProcessorResult::ObjectMass::Sum::volume.

Referenced by render_details().

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

Member Data Documentation

◆ m_bodies

std::map<size_t, Bodies> Slic3r::GUI::GLCanvas3D::CenterOfMass::m_bodies
private

Referenced by model_markers().

◆ m_drawn

std::array<Markers, 2> Slic3r::GUI::GLCanvas3D::CenterOfMass::m_drawn
private

◆ m_meshes

std::map<size_t, MassProperties> Slic3r::GUI::GLCanvas3D::CenterOfMass::m_meshes
private

Referenced by model_markers().

◆ m_octants

std::array<GLModel, 2> Slic3r::GUI::GLCanvas3D::CenterOfMass::m_octants
private

◆ m_picked

std::optional<Pick> Slic3r::GUI::GLCanvas3D::CenterOfMass::m_picked
private

Referenced by on_left_down(), and render_details().

◆ m_top_layer

size_t Slic3r::GUI::GLCanvas3D::CenterOfMass::m_top_layer { 0 }
private
527{ 0 };

Referenced by render(), and render_details().


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