mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-22 14:13:57 -06:00
Tech ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - Fixed detection of collision with circular printbed for pre-gcode preview and sla preview
This commit is contained in:
parent
c4edff72d0
commit
6ff4d6c3f5
3 changed files with 170 additions and 38 deletions
|
@ -37,6 +37,12 @@
|
|||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
#include <libqhullcpp/Qhull.h>
|
||||
#include <libqhullcpp/QhullFacetList.h>
|
||||
#include <libqhullcpp/QhullVertexSet.h>
|
||||
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
|
||||
#ifdef HAS_GLSAFE
|
||||
void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char* function_name)
|
||||
{
|
||||
|
@ -614,6 +620,106 @@ void GLVolume::render_sinking_contours()
|
|||
m_sinking_contours.render();
|
||||
}
|
||||
|
||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
void GLVolume::calc_convex_hull_3d()
|
||||
{
|
||||
if (this->indexed_vertex_array.vertices_and_normals_interleaved.empty())
|
||||
return;
|
||||
|
||||
TriangleMesh mesh;
|
||||
for (size_t i = 0; i < this->indexed_vertex_array.vertices_and_normals_interleaved.size(); i += 6) {
|
||||
const size_t v_id = 3 + i;
|
||||
mesh.its.vertices.push_back({ this->indexed_vertex_array.vertices_and_normals_interleaved[v_id + 0],
|
||||
this->indexed_vertex_array.vertices_and_normals_interleaved[v_id + 1],
|
||||
this->indexed_vertex_array.vertices_and_normals_interleaved[v_id + 2]
|
||||
});
|
||||
}
|
||||
|
||||
const std::vector<Vec3f>& vertices = mesh.its.vertices;
|
||||
|
||||
// The qhull call:
|
||||
orgQhull::Qhull qhull;
|
||||
qhull.disableOutputStream(); // we want qhull to be quiet
|
||||
std::vector<realT> src_vertices;
|
||||
try
|
||||
{
|
||||
#if REALfloat
|
||||
qhull.runQhull("", 3, (int)vertices.size(), (const realT*)(vertices.front().data()), "Qt");
|
||||
#else
|
||||
src_vertices.reserve(vertices.size() * 3);
|
||||
// We will now fill the vector with input points for computation:
|
||||
for (const stl_vertex& v : vertices)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
src_vertices.emplace_back(v(i));
|
||||
qhull.runQhull("", 3, (int)src_vertices.size() / 3, src_vertices.data(), "Qt");
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "GLVolume::calc_convex_hull_3d() - Unable to create convex hull" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// Let's collect results:
|
||||
std::vector<Vec3f> dst_vertices;
|
||||
std::vector<Vec3i> dst_facets;
|
||||
// Map of QHull's vertex ID to our own vertex ID (pointing to dst_vertices).
|
||||
std::vector<int> map_dst_vertices;
|
||||
#ifndef NDEBUG
|
||||
Vec3f centroid = Vec3f::Zero();
|
||||
for (const auto& pt : vertices)
|
||||
centroid += pt;
|
||||
centroid /= float(vertices.size());
|
||||
#endif // NDEBUG
|
||||
for (const orgQhull::QhullFacet& facet : qhull.facetList()) {
|
||||
// Collect face vertices first, allocate unique vertices in dst_vertices based on QHull's vertex ID.
|
||||
Vec3i indices;
|
||||
int cnt = 0;
|
||||
for (const orgQhull::QhullVertex vertex : facet.vertices()) {
|
||||
const int id = vertex.id();
|
||||
assert(id >= 0);
|
||||
if (id >= int(map_dst_vertices.size()))
|
||||
map_dst_vertices.resize(next_highest_power_of_2(size_t(id + 1)), -1);
|
||||
if (int i = map_dst_vertices[id]; i == -1) {
|
||||
// Allocate a new vertex.
|
||||
i = int(dst_vertices.size());
|
||||
map_dst_vertices[id] = i;
|
||||
orgQhull::QhullPoint pt(vertex.point());
|
||||
dst_vertices.emplace_back(pt[0], pt[1], pt[2]);
|
||||
indices[cnt] = i;
|
||||
}
|
||||
else
|
||||
// Reuse existing vertex.
|
||||
indices[cnt] = i;
|
||||
|
||||
if (cnt++ == 3)
|
||||
break;
|
||||
}
|
||||
assert(cnt == 3);
|
||||
if (cnt == 3) {
|
||||
// QHull sorts vertices of a face lexicographically by their IDs, not by face normals.
|
||||
// Calculate face normal based on the order of vertices.
|
||||
const Vec3f n = (dst_vertices[indices(1)] - dst_vertices[indices(0)]).cross(dst_vertices[indices(2)] - dst_vertices[indices(1)]);
|
||||
auto* n2 = facet.getBaseT()->normal;
|
||||
const auto d = n.x() * n2[0] + n.y() * n2[1] + n.z() * n2[2];
|
||||
#ifndef NDEBUG
|
||||
const Vec3f n3 = (dst_vertices[indices(0)] - centroid);
|
||||
const auto d3 = n.dot(n3);
|
||||
assert((d < 0.f) == (d3 < 0.f));
|
||||
#endif // NDEBUG
|
||||
// Get the face normal from QHull.
|
||||
if (d < 0.f)
|
||||
// Fix face orientation.
|
||||
std::swap(indices[1], indices[2]);
|
||||
dst_facets.emplace_back(indices);
|
||||
}
|
||||
}
|
||||
|
||||
TriangleMesh out_mesh{ std::move(dst_vertices), std::move(dst_facets) };
|
||||
this->set_convex_hull(out_mesh);
|
||||
}
|
||||
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
|
||||
std::vector<int> GLVolumeCollection::load_object(
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
|
@ -771,7 +877,10 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
|||
|
||||
volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume& v = *volumes.back();
|
||||
v.indexed_vertex_array.load_mesh(mesh);
|
||||
v.indexed_vertex_array.load_mesh(mesh);
|
||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
v.calc_convex_hull_3d();
|
||||
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
||||
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
|
||||
|
@ -964,12 +1073,16 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
|||
#if ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION
|
||||
bool contained = false;
|
||||
bool intersects = false;
|
||||
bool is_sla = GUI::wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA;
|
||||
const BoundingBoxf3 bb = is_sla ? volume->transformed_convex_hull_bounding_box() : volume->transformed_non_sinking_bounding_box();
|
||||
bool is_aux_volume = volume->is_sla_support() || volume->is_sla_pad() || volume->is_wipe_tower;
|
||||
const BoundingBoxf3 bb = is_aux_volume ? volume->transformed_convex_hull_bounding_box() : volume->transformed_non_sinking_bounding_box();
|
||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||
ModelInstanceEPrintVolumeState volume_state;
|
||||
if (is_sla)
|
||||
volume_state = printbed_collision_state(bed_poly, bed_height, bb);
|
||||
if (is_aux_volume) {
|
||||
if (volume->is_sla_support() || volume->is_wipe_tower) {
|
||||
const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast<float>(), 0.0f);
|
||||
volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z());
|
||||
}
|
||||
}
|
||||
else {
|
||||
const indexed_triangle_set& its = GUI::wxGetApp().plater()->model().objects[volume->object_idx()]->volumes[volume->volume_idx()]->mesh().its;
|
||||
const Polygon volume_hull_2d = its_convex_hull_2d_above(its, volume->world_matrix().cast<float>(), 0.0f);
|
||||
|
@ -1061,35 +1174,28 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
|
|||
std::vector<Color> colors(colors_count);
|
||||
|
||||
unsigned char rgb[3];
|
||||
for (unsigned int i = 0; i < colors_count; ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < colors_count; ++i) {
|
||||
const std::string& txt_color = config->opt_string("extruder_colour", i);
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
{
|
||||
colors[i].set(txt_color, rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
const std::string& txt_color = config->opt_string("filament_colour", i);
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
colors[i].set(txt_color, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
for (GLVolume* volume : volumes)
|
||||
{
|
||||
if ((volume == nullptr) || volume->is_modifier || volume->is_wipe_tower || (volume->volume_idx() < 0))
|
||||
for (GLVolume* volume : volumes) {
|
||||
if (volume == nullptr || volume->is_modifier || volume->is_wipe_tower || (volume->volume_idx() < 0))
|
||||
continue;
|
||||
|
||||
int extruder_id = volume->extruder_id - 1;
|
||||
if ((extruder_id < 0) || ((int)colors.size() <= extruder_id))
|
||||
if (extruder_id < 0 || (int)colors.size() <= extruder_id)
|
||||
extruder_id = 0;
|
||||
|
||||
const Color& color = colors[extruder_id];
|
||||
if (!color.text.empty())
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (!color.text.empty()) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
volume->color[i] = (float)color.rgb[i] * inv_255;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue