Finalize new sla backend interface

no has_mesh or get_mesh based on states, but specific methods to get the mesh type needed (support, pad, object)

Commented out everything that does not conform in frontend
This commit is contained in:
tamasmeszaros 2022-10-19 16:30:58 +02:00
parent 39a1ed0e1a
commit 15fa4c42d6
10 changed files with 366 additions and 294 deletions

View file

@ -1056,6 +1056,23 @@ const TriangleMesh& SLAPrintObject::pad_mesh() const
return EMPTY_MESH;
}
const TriangleMesh &SLAPrintObject::get_mesh_to_print() const {
const TriangleMesh *ret = nullptr;
int s = SLAPrintObjectStep::slaposCount;
while (s > 0 && !ret) {
--s;
if (is_step_done(SLAPrintObjectStep(s)) && !m_preview_meshes[s].empty())
ret = &m_preview_meshes[s];
}
if (!ret)
ret = &m_transformed_rmesh;
return *ret;
}
//const indexed_triangle_set &SLAPrintObject::hollowed_interior_mesh() const
//{
// if (m_hollowing_data && m_hollowing_data->interior &&

View file

@ -45,6 +45,24 @@ using _SLAPrintObjectBase =
enum SliceOrigin { soSupport, soModel };
} // namespace Slic3r
namespace std {
template<> struct hash<Slic3r::csg::VoxelizeParams> {
size_t operator() (const Slic3r::csg::VoxelizeParams &p) const {
std::string str = Slic3r::float_to_string_decimal_point(p.voxel_scale());
str += Slic3r::float_to_string_decimal_point(p.exterior_bandwidth());
str += Slic3r::float_to_string_decimal_point(p.interior_bandwidth());
return std::hash<std::string>{}(str);
}
};
} // namespace std
namespace Slic3r {
// Each sla object step can hold a collection of csg operations on the
// sla model to be sliced. Currently, Assembly step adds negative and positive
// volumes, hollowing adds the negative interior, drilling adds the hole cylinders.
@ -54,7 +72,7 @@ enum SliceOrigin { soSupport, soModel };
struct CSGPartForStep : public csg::CSGPart
{
SLAPrintObjectStep key;
mutable struct { VoxelGridPtr gridptr; csg::VoxelizeParams params; } cache;
mutable std::unordered_map<csg::VoxelizeParams, VoxelGridPtr> gridcache;
CSGPartForStep(SLAPrintObjectStep k, CSGPart &&p = {})
: key{k}, CSGPart{std::move(p)}
@ -64,6 +82,7 @@ struct CSGPartForStep : public csg::CSGPart
{
this->its_ptr = std::move(part.its_ptr);
this->operation = part.operation;
return *this;
}
@ -72,23 +91,27 @@ struct CSGPartForStep : public csg::CSGPart
namespace csg {
//inline VoxelGridPtr get_voxelgrid(const CSGPartForStep &part,
// const VoxelizeParams &p)
//{
// if (!part.cache.gridptr || get_voxel_scale(*part.cache.gridptr) < p.voxel_scale()) {
// part.cache.gridptr = mesh_to_grid(*csg::get_mesh(part), p.voxel_scale(),
// p.exterior_bandwidth(),
// p.interior_bandwidth());
inline bool operator==(const VoxelizeParams &a, const VoxelizeParams &b)
{
std::hash<Slic3r::csg::VoxelizeParams> h;
return h(a) == h(b);
}
// } /*else {
// float vscale = p.voxel_scale();
// float oscale = get_voxel_scale(*part.cache.gridptr);
inline VoxelGridPtr get_voxelgrid(const CSGPartForStep &part,
const VoxelizeParams &p)
{
VoxelGridPtr &ret = part.gridcache[p];
// rescale_grid(*part.cache.gridptr, oscale/vscale);
// }*/
if (!ret) {
ret = mesh_to_grid(*csg::get_mesh(part),
csg::get_transform(part),
p.voxel_scale(),
p.exterior_bandwidth(),
p.interior_bandwidth());
}
// return clone(*part.cache.gridptr);
//}
return clone(*ret);
}
} // namespace csg
@ -134,9 +157,7 @@ public:
// Get the mesh that is going to be printed with all the modifications
// like hollowing and drilled holes.
const TriangleMesh & get_mesh_to_print() const {
return !m_mesh_from_slices.empty() ? m_mesh_from_slices : m_transformed_rmesh;
}
const TriangleMesh & get_mesh_to_print() const;
// // This will return the transformed mesh which is cached
// const TriangleMesh& transformed_mesh() const;
@ -379,9 +400,16 @@ private:
};
std::unique_ptr<SupportData> m_supportdata;
TriangleMesh m_mesh_from_slices;
// Holds CSG operations for the printed object, prioritized by print steps.
std::multiset<CSGPartForStep> m_mesh_to_slice;
// Holds the preview of the object to be printed (as it will look like with
// all its holes and cavities, negatives and positive volumes unified.
// Essentially this should be a m_mesh_to_slice after the CSG operations
// or an approximation of that.
std::array<TriangleMesh, SLAPrintObjectStep::slaposCount> m_preview_meshes;
class HollowingData
{
public:

View file

@ -22,7 +22,7 @@
#include <libslic3r/QuadricEdgeCollapse.hpp>
#include <libslic3r/ClipperUtils.hpp>
#include <libslic3r/QuadricEdgeCollapse.hpp>
#include <libslic3r/ShortEdgeCollapse.hpp>
#include <boost/log/trivial.hpp>
@ -128,6 +128,54 @@ void SLAPrint::Steps::apply_printer_corrections(SLAPrintObject &po, SliceOrigin
}
}
void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep step)
{
Benchmark bench;
bench.start();
// update preview mesh
double vscale = 1. / (2. * po.m_config.layer_height.getFloat());
auto voxparams = csg::VoxelizeParams{}
.voxel_scale(vscale)
.exterior_bandwidth(1.f)
.interior_bandwidth(1.f);
auto grid = csg::voxelize_csgmesh(range(po.m_mesh_to_slice), voxparams);
indexed_triangle_set m = grid_to_mesh(*grid);
// if (!m.empty()) {
// // simplify mesh lossless
// std::cout << "simplify started" << std::endl;
// int expected_cnt = m.indices.size() * 0.8; //std::pow(po.m_transformed_rmesh.volume() / std::pow(1./vscale, 3), 2./3.);
// std::cout << "expected triangles " << expected_cnt << std::endl;
// float err = std::pow(vscale, 3);
// its_quadric_edge_collapse(m, 0U, &err);
// std::cout << "simplify ended " << m.indices.size() << " triangles" << std::endl;
// std::cout << "cleanup started" << std::endl;
// its_compactify_vertices(m);
// its_merge_vertices(m);
// std::cout << "cleanup ended" << std::endl;
// }
po.m_preview_meshes[step] = TriangleMesh{std::move(m)};
for (size_t i = size_t(step) + 1; i < slaposCount; ++i)
{
po.m_preview_meshes[i] = {};
}
bench.stop();
std::cout << "Preview gen took: " << bench.getElapsedSec() << std::endl;
using namespace std::string_literals;
report_status(-2, "Reload preview from step "s + std::to_string(int(step)), SlicingStatus::RELOAD_SLA_PREVIEW);
}
static inline
void clear_csg(std::multiset<CSGPartForStep> &s, SLAPrintObjectStep step)
{
auto r = s.equal_range(step);
@ -153,6 +201,8 @@ void SLAPrint::Steps::mesh_assembly(SLAPrintObject &po)
csg::model_to_csgmesh(*po.model_object(), po.trafo(),
csg_inserter{po.m_mesh_to_slice, slaposAssembly},
csg::mpartsPositive | csg::mpartsNegative);
generate_preview(po, slaposAssembly);
}
void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
@ -185,11 +235,24 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
po.m_hollowing_data.reset(new SLAPrintObject::HollowingData());
po.m_hollowing_data->interior = std::move(interior);
indexed_triangle_set &m = sla::get_mesh(*po.m_hollowing_data->interior);
if (!m.empty()) {
// simplify mesh lossless
float loss_less_max_error = 2*std::numeric_limits<float>::epsilon();
its_quadric_edge_collapse(m, 0U, &loss_less_max_error);
its_compactify_vertices(m);
its_merge_vertices(m);
}
// Put the interior into the target mesh as a negative
po.m_mesh_to_slice
.emplace(slaposHollowing,
csg::CSGPart{&sla::get_mesh(*po.m_hollowing_data->interior),
csg::CSGType::Difference});
generate_preview(po, slaposHollowing);
}
}
@ -203,14 +266,7 @@ void SLAPrint::Steps::drill_holes(SLAPrintObject &po)
csg::mpartsDrillHoles);
// update preview mesh
double vscale = 1. / 0.05;
auto voxparams = csg::VoxelizeParams{}
.voxel_scale(vscale)
.exterior_bandwidth(1.f)
.interior_bandwidth(1.f);
auto grid = csg::voxelize_csgmesh(range(po.m_mesh_to_slice), voxparams);
indexed_triangle_set mesh_from_slices = grid_to_mesh(*grid);
po.m_mesh_from_slices = TriangleMesh{mesh_from_slices};
generate_preview(po, slaposDrillHoles);
}
template<class Pred>
@ -331,38 +387,7 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
// We apply the printer correction offset here.
apply_printer_corrections(po, soModel);
// auto simpl_slices = reserve_vector<ExPolygons>(po.m_model_slices.size());
// for (const ExPolygons &slice : po.m_model_slices) {
// simpl_slices.emplace_back(expolygons_simplify(slice, scaled(1e-2)));
// }
// po.m_mesh_from_slices = TriangleMesh{
// slices_to_mesh(simpl_slices, slice_grid.front(), lhd, ilhd)};
double vscale = 1. / lhd;
auto voxparams = csg::VoxelizeParams{}
.voxel_scale(vscale)
.exterior_bandwidth(1.f)
.interior_bandwidth(1.f);
auto grid = csg::voxelize_csgmesh(range(po.m_mesh_to_slice), voxparams);
assert(grid);
// size_t max_face_cnt = 0;
// for (const CSGMesh &part : po.m_mesh_to_slice)
// max_face_cnt += part.its_ptr->indices.size();
indexed_triangle_set mesh_from_slices = grid_to_mesh(*grid);
// its_quadric_edge_collapse(mesh_from_slices, vscale * max_face_cnt);
// its_compactify_vertices(mesh_from_slices);
// its_merge_vertices(mesh_from_slices);
po.m_mesh_from_slices = TriangleMesh{mesh_from_slices};
// po.m_mesh_from_slices = TriangleMesh{sla::get_mesh(*po.m_hollowing_data->interior)};
generate_preview(po, slaposObjectSlice);
}
static void filter_support_points_by_modifiers(
@ -421,7 +446,10 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po)
if(!po.m_config.supports_enable.getBool()) return;
if (!po.m_supportdata)
po.m_supportdata.reset(new SLAPrintObject::SupportData(po.m_mesh_from_slices));
po.m_supportdata =
std::make_unique<SLAPrintObject::SupportData>(
po.m_preview_meshes[slaposObjectSlice]
);
po.m_supportdata->input.zoffset = csgmesh_positive_bb(po.m_mesh_to_slice)
.min.z();

View file

@ -44,6 +44,8 @@ private:
void initialize_printer_input();
void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o);
void generate_preview(SLAPrintObject &po, SLAPrintObjectStep step);
public:
explicit Steps(SLAPrint *print);

View file

@ -852,73 +852,73 @@ int GLVolumeCollection::load_object_volume(
return int(this->volumes.size() - 1);
}
// Load SLA auxiliary GLVolumes (for support trees or pad).
// This function produces volumes for multiple instances in a single shot,
// as some object specific mesh conversions may be expensive.
#if ENABLE_LEGACY_OPENGL_REMOVAL
void GLVolumeCollection::load_object_auxiliary(
const SLAPrintObject* print_object,
int obj_idx,
// pairs of <instance_idx, print_instance_idx>
const std::vector<std::pair<size_t, size_t>>& instances,
SLAPrintObjectStep milestone,
// Timestamp of the last change of the milestone
size_t timestamp)
#else
void GLVolumeCollection::load_object_auxiliary(
const SLAPrintObject *print_object,
int obj_idx,
// pairs of <instance_idx, print_instance_idx>
const std::vector<std::pair<size_t, size_t>>& instances,
SLAPrintObjectStep milestone,
// Timestamp of the last change of the milestone
size_t timestamp,
bool opengl_initialized)
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
{
assert(print_object->is_step_done(milestone));
Transform3d mesh_trafo_inv = print_object->trafo().inverse();
// Get the support mesh.
TriangleMesh mesh = print_object->get_mesh(milestone);
mesh.transform(mesh_trafo_inv);
// Convex hull is required for out of print bed detection.
TriangleMesh convex_hull = mesh.convex_hull_3d();
for (const std::pair<size_t, size_t>& instance_idx : instances) {
const ModelInstance& model_instance = *print_object->model_object()->instances[instance_idx.first];
this->volumes.emplace_back(new GLVolume((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
GLVolume& v = *this->volumes.back();
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_SMOOTH_NORMALS
v.model.init_from(mesh, true);
#else
v.model.init_from(mesh);
v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR);
#if ENABLE_RAYCAST_PICKING
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
#endif // ENABLE_RAYCAST_PICKING
#endif // ENABLE_SMOOTH_NORMALS
#else
#if ENABLE_SMOOTH_NORMALS
v.indexed_vertex_array.load_mesh(mesh, true);
#else
v.indexed_vertex_array.load_mesh(mesh);
#endif // ENABLE_SMOOTH_NORMALS
v.indexed_vertex_array.finalize_geometry(opengl_initialized);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
// Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.
if (&instance_idx == &instances.back())
v.set_convex_hull(std::move(convex_hull));
else
v.set_convex_hull(convex_hull);
v.is_modifier = false;
v.shader_outside_printer_detection_enabled = (milestone == slaposSupportTree);
v.set_instance_transformation(model_instance.get_transformation());
// Leave the volume transformation at identity.
// v.set_volume_transformation(model_volume->get_transformation());
}
}
//// Load SLA auxiliary GLVolumes (for support trees or pad).
//// This function produces volumes for multiple instances in a single shot,
//// as some object specific mesh conversions may be expensive.
//#if ENABLE_LEGACY_OPENGL_REMOVAL
//void GLVolumeCollection::load_object_auxiliary(
// const SLAPrintObject* print_object,
// int obj_idx,
// // pairs of <instance_idx, print_instance_idx>
// const std::vector<std::pair<size_t, size_t>>& instances,
// SLAPrintObjectStep milestone,
// // Timestamp of the last change of the milestone
// size_t timestamp)
//#else
//void GLVolumeCollection::load_object_auxiliary(
// const SLAPrintObject *print_object,
// int obj_idx,
// // pairs of <instance_idx, print_instance_idx>
// const std::vector<std::pair<size_t, size_t>>& instances,
// SLAPrintObjectStep milestone,
// // Timestamp of the last change of the milestone
// size_t timestamp,
// bool opengl_initialized)
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
//{
// assert(print_object->is_step_done(milestone));
// Transform3d mesh_trafo_inv = print_object->trafo().inverse();
// // Get the support mesh.
// TriangleMesh mesh = print_object->get_mesh(milestone);
// mesh.transform(mesh_trafo_inv);
// // Convex hull is required for out of print bed detection.
// TriangleMesh convex_hull = mesh.convex_hull_3d();
// for (const std::pair<size_t, size_t>& instance_idx : instances) {
// const ModelInstance& model_instance = *print_object->model_object()->instances[instance_idx.first];
// this->volumes.emplace_back(new GLVolume((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
// GLVolume& v = *this->volumes.back();
//#if ENABLE_LEGACY_OPENGL_REMOVAL
//#if ENABLE_SMOOTH_NORMALS
// v.model.init_from(mesh, true);
//#else
// v.model.init_from(mesh);
// v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR);
//#if ENABLE_RAYCAST_PICKING
// v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
//#endif // ENABLE_RAYCAST_PICKING
//#endif // ENABLE_SMOOTH_NORMALS
//#else
//#if ENABLE_SMOOTH_NORMALS
// v.indexed_vertex_array.load_mesh(mesh, true);
//#else
// v.indexed_vertex_array.load_mesh(mesh);
//#endif // ENABLE_SMOOTH_NORMALS
// v.indexed_vertex_array.finalize_geometry(opengl_initialized);
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
// v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
// v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
// // Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.
// if (&instance_idx == &instances.back())
// v.set_convex_hull(std::move(convex_hull));
// else
// v.set_convex_hull(convex_hull);
// v.is_modifier = false;
// v.shader_outside_printer_detection_enabled = (milestone == slaposSupportTree);
// v.set_instance_transformation(model_instance.get_transformation());
// // Leave the volume transformation at identity.
// // v.set_volume_transformation(model_volume->get_transformation());
// }
//}
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_OPENGL_ES

View file

@ -659,14 +659,14 @@ public:
int instance_idx);
// Load SLA auxiliary GLVolumes (for support trees or pad).
void load_object_auxiliary(
const SLAPrintObject* print_object,
int obj_idx,
// pairs of <instance_idx, print_instance_idx>
const std::vector<std::pair<size_t, size_t>>& instances,
SLAPrintObjectStep milestone,
// Timestamp of the last change of the milestone
size_t timestamp);
// void load_object_auxiliary(
// const SLAPrintObject* print_object,
// int obj_idx,
// // pairs of <instance_idx, print_instance_idx>
// const std::vector<std::pair<size_t, size_t>>& instances,
// SLAPrintObjectStep milestone,
// // Timestamp of the last change of the milestone
// size_t timestamp);
#if ENABLE_OPENGL_ES
int load_wipe_tower_preview(

View file

@ -2189,143 +2189,146 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
}
}
if (printer_technology == ptSLA) {
size_t idx = 0;
const SLAPrint *sla_print = this->sla_print();
std::vector<double> shift_zs(m_model->objects.size(), 0);
double relative_correction_z = sla_print->relative_correction().z();
if (relative_correction_z <= EPSILON)
relative_correction_z = 1.;
for (const SLAPrintObject *print_object : sla_print->objects()) {
SLASupportState &state = sla_support_state[idx ++];
const ModelObject *model_object = print_object->model_object();
// Find an index of the ModelObject
int object_idx;
// There may be new SLA volumes added to the scene for this print_object.
// Find the object index of this print_object in the Model::objects list.
auto it = std::find(sla_print->model().objects.begin(), sla_print->model().objects.end(), model_object);
assert(it != sla_print->model().objects.end());
object_idx = it - sla_print->model().objects.begin();
// Cache the Z offset to be applied to all volumes with this object_idx.
shift_zs[object_idx] = print_object->get_current_elevation() / relative_correction_z;
// Collect indices of this print_object's instances, for which the SLA support meshes are to be added to the scene.
// pairs of <instance_idx, print_instance_idx>
std::vector<std::pair<size_t, size_t>> instances[std::tuple_size<SLASteps>::value];
for (size_t print_instance_idx = 0; print_instance_idx < print_object->instances().size(); ++ print_instance_idx) {
const SLAPrintObject::Instance &instance = print_object->instances()[print_instance_idx];
// Find index of ModelInstance corresponding to this SLAPrintObject::Instance.
auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
[&instance](const ModelInstance *mi) { return mi->id() == instance.instance_id; });
assert(it != model_object->instances.end());
int instance_idx = it - model_object->instances.begin();
for (size_t istep = 0; istep < sla_steps.size(); ++ istep)
if (sla_steps[istep] == slaposDrillHoles) {
// Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance,
// not into its own GLVolume.
// There shall always be such a GLVolume allocated.
ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id);
auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
assert(!it->new_geometry());
GLVolume &volume = *m_volumes.volumes[it->volume_idx];
if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) {
// The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
#if ENABLE_LEGACY_OPENGL_REMOVAL
volume.model.reset();
#else
volume.indexed_vertex_array.release_geometry();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
if (state.step[istep].state == PrintStateBase::DONE) {
TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
assert(! mesh.empty());
// size_t idx = 0;
// const SLAPrint *sla_print = this->sla_print();
// std::vector<double> shift_zs(m_model->objects.size(), 0);
// double relative_correction_z = sla_print->relative_correction().z();
// if (relative_correction_z <= EPSILON)
// relative_correction_z = 1.;
// for (const SLAPrintObject *print_object : sla_print->objects()) {
// SLASupportState &state = sla_support_state[idx ++];
// const ModelObject *model_object = print_object->model_object();
// // Find an index of the ModelObject
// int object_idx;
// // There may be new SLA volumes added to the scene for this print_object.
// // Find the object index of this print_object in the Model::objects list.
// auto it = std::find(sla_print->model().objects.begin(), sla_print->model().objects.end(), model_object);
// assert(it != sla_print->model().objects.end());
// object_idx = it - sla_print->model().objects.begin();
// // Cache the Z offset to be applied to all volumes with this object_idx.
// shift_zs[object_idx] = print_object->get_current_elevation() / relative_correction_z;
// // Collect indices of this print_object's instances, for which the SLA support meshes are to be added to the scene.
// // pairs of <instance_idx, print_instance_idx>
// std::vector<std::pair<size_t, size_t>> instances[std::tuple_size<SLASteps>::value];
// for (size_t print_instance_idx = 0; print_instance_idx < print_object->instances().size(); ++ print_instance_idx) {
// const SLAPrintObject::Instance &instance = print_object->instances()[print_instance_idx];
// // Find index of ModelInstance corresponding to this SLAPrintObject::Instance.
// auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
// [&instance](const ModelInstance *mi) { return mi->id() == instance.instance_id; });
// assert(it != model_object->instances.end());
// int instance_idx = it - model_object->instances.begin();
// for (size_t istep = 0; istep < sla_steps.size(); ++ istep)
// if (sla_steps[istep] == slaposDrillHoles) {
// // Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance,
// // not into its own GLVolume.
// // There shall always be such a GLVolume allocated.
// ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id);
// auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
// assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
// assert(!it->new_geometry());
// GLVolume &volume = *m_volumes.volumes[it->volume_idx];
// if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) {
// // The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
//#if ENABLE_LEGACY_OPENGL_REMOVAL
// volume.model.reset();
//#else
// volume.indexed_vertex_array.release_geometry();
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
// if (state.step[istep].state == PrintStateBase::DONE) {
// TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
// assert(! mesh.empty());
// sla_trafo does not contain volume trafo. To get a mesh to create
// a new volume from, we have to apply vol trafo inverse separately.
const ModelObject& mo = *m_model->objects[volume.object_idx()];
Transform3d trafo = sla_print->sla_trafo(mo)
* mo.volumes.front()->get_transformation().get_matrix();
mesh.transform(trafo.inverse());
#if ENABLE_SMOOTH_NORMALS
#if ENABLE_LEGACY_OPENGL_REMOVAL
volume.model.init_from(mesh, true);
#else
volume.indexed_vertex_array.load_mesh(mesh, true);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#else
#if ENABLE_LEGACY_OPENGL_REMOVAL
volume.model.init_from(mesh);
#if ENABLE_RAYCAST_PICKING
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
#endif // ENABLE_RAYCAST_PICKING
#else
volume.indexed_vertex_array.load_mesh(mesh);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#endif // ENABLE_SMOOTH_NORMALS
}
else {
// Reload the original volume.
#if ENABLE_SMOOTH_NORMALS
#if ENABLE_LEGACY_OPENGL_REMOVAL
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
#else
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#else
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
volume.model.init_from(new_mesh);
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
#else
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
#endif // ENABLE_RAYCAST_PICKING
#else
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#endif // ENABLE_SMOOTH_NORMALS
}
#if !ENABLE_LEGACY_OPENGL_REMOVAL
volume.finalize_geometry(true);
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
}
//FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
// to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
// of various concenrs (model vs. 3D print path).
volume.offsets = { state.step[istep].timestamp };
}
else if (state.step[istep].state == PrintStateBase::DONE) {
// Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id);
if (it->new_geometry()) {
// This can be an SLA support structure that should not be rendered (in case someone used undo
// to revert to before it was generated). If that's the case, we should not generate anything.
if (model_object->sla_points_status != sla::PointsStatus::NoPoints)
instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx));
else
shift_zs[object_idx] = 0.;
}
else {
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
}
}
// // sla_trafo does not contain volume trafo. To get a mesh to create
// // a new volume from, we have to apply vol trafo inverse separately.
// const ModelObject& mo = *m_model->objects[volume.object_idx()];
// Transform3d trafo = sla_print->sla_trafo(mo)
// * mo.volumes.front()->get_transformation().get_matrix();
// mesh.transform(trafo.inverse());
//#if ENABLE_SMOOTH_NORMALS
//#if ENABLE_LEGACY_OPENGL_REMOVAL
// volume.model.init_from(mesh, true);
//#else
// volume.indexed_vertex_array.load_mesh(mesh, true);
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
//#else
//#if ENABLE_LEGACY_OPENGL_REMOVAL
// volume.model.init_from(mesh);
//#if ENABLE_RAYCAST_PICKING
// volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
//#endif // ENABLE_RAYCAST_PICKING
//#else
// volume.indexed_vertex_array.load_mesh(mesh);
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
//#endif // ENABLE_SMOOTH_NORMALS
// }
// else {
// // Reload the original volume.
//#if ENABLE_SMOOTH_NORMALS
//#if ENABLE_LEGACY_OPENGL_REMOVAL
// volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
//#else
// volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
//#else
//#if ENABLE_LEGACY_OPENGL_REMOVAL
//#if ENABLE_RAYCAST_PICKING
// const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
// volume.model.init_from(new_mesh);
// volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
//#else
// volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
//#endif // ENABLE_RAYCAST_PICKING
//#else
// volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
//#endif // ENABLE_SMOOTH_NORMALS
// }
//#if !ENABLE_LEGACY_OPENGL_REMOVAL
// volume.finalize_geometry(true);
//#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
// }
// //FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
// // to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
// // of various concenrs (model vs. 3D print path).
// volume.offsets = { state.step[istep].timestamp };
// }
// else if (state.step[istep].state == PrintStateBase::DONE) {
// // Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
// ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
// auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
// assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id);
// if (it->new_geometry()) {
// // This can be an SLA support structure that should not be rendered (in case someone used undo
// // to revert to before it was generated). If that's the case, we should not generate anything.
// if (model_object->sla_points_status != sla::PointsStatus::NoPoints)
// instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx));
// else
// shift_zs[object_idx] = 0.;
// }
// else {
// // Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
// m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
// m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
// }
// }
// }
// for (size_t istep = 0; istep < sla_steps.size(); ++istep)
// if (!instances[istep].empty())
//#if ENABLE_LEGACY_OPENGL_REMOVAL
// m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
//#else
// m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized);
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
// }
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
for (GLVolume* volume : m_volumes.volumes)
if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable()) {
const SLAPrintObject *po = sla_print()->objects()[volume->object_idx()];
float zoffs = po->get_current_elevation() / sla_print()->relative_correction().z();
volume->set_sla_shift_z(zoffs);
}
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
if (!instances[istep].empty())
#if ENABLE_LEGACY_OPENGL_REMOVAL
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
#else
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
}
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
for (GLVolume* volume : m_volumes.volumes)
if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable())
volume->set_sla_shift_z(shift_zs[volume->object_idx()]);
}
if (printer_technology == ptFFF && m_config->has("nozzle_diameter")) {
@ -7635,7 +7638,7 @@ void GLCanvas3D::_load_sla_shells()
// adds objects' volumes
for (const SLAPrintObject* obj : print->objects())
if (obj->is_step_done(slaposSliceSupports)) {
/*if (obj->is_step_done(slaposSliceSupports))*/ {
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
for (const SLAPrintObject::Instance& instance : obj->instances()) {
add_volume(*obj, 0, instance, obj->get_mesh_to_print(), GLVolume::MODEL_COLOR[0], true);

View file

@ -281,10 +281,10 @@ void HollowedMesh::on_update()
// If there is a valid SLAPrintObject, check state of Hollowing step.
if (print_object) {
if (print_object->is_step_done(slaposDrillHoles) && print_object->has_mesh(slaposDrillHoles)) {
if (print_object->is_step_done(slaposDrillHoles) && !print_object->get_mesh_to_print().empty()) {
size_t timestamp = print_object->step_state_with_timestamp(slaposDrillHoles).timestamp;
if (timestamp > m_old_hollowing_timestamp) {
const TriangleMesh& backend_mesh = print_object->get_mesh_to_slice();
const TriangleMesh& backend_mesh = print_object->get_mesh_to_print();
if (! backend_mesh.empty()) {
m_hollowed_mesh_transformed.reset(new TriangleMesh(backend_mesh));
Transform3d trafo_inv = (canvas->sla_print()->sla_trafo(*mo) * print_object->model_object()->volumes.front()->get_transformation().get_matrix()).inverse();
@ -292,10 +292,10 @@ void HollowedMesh::on_update()
m_drainholes = print_object->model_object()->sla_drain_holes;
m_old_hollowing_timestamp = timestamp;
indexed_triangle_set interior = print_object->hollowed_interior_mesh();
its_flip_triangles(interior);
m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior));
m_hollowed_interior_transformed->transform(trafo_inv);
// indexed_triangle_set interior = print_object->hollowed_interior_mesh();
// its_flip_triangles(interior);
// m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior));
// m_hollowed_interior_transformed->transform(trafo_inv);
}
else {
m_hollowed_mesh_transformed.reset(nullptr);

View file

@ -944,7 +944,7 @@ bool MainFrame::can_export_supports() const
const PrintObjects& objects = m_plater->sla_print().objects();
for (const SLAPrintObject* object : objects)
{
if (object->has_mesh(slaposPad) || object->has_mesh(slaposSupportTree))
if (!object->support_mesh().empty())
{
can_export = true;
break;

View file

@ -6155,19 +6155,13 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
const Transform3d mesh_trafo_inv = object->trafo().inverse();
const bool is_left_handed = object->is_left_handed();
TriangleMesh pad_mesh;
const bool has_pad_mesh = extended && object->has_mesh(slaposPad);
if (has_pad_mesh) {
pad_mesh = object->get_mesh(slaposPad);
pad_mesh.transform(mesh_trafo_inv);
}
auto pad_mesh = extended? object->pad_mesh() : TriangleMesh{};
pad_mesh = object->pad_mesh();
pad_mesh.transform(mesh_trafo_inv);
auto supports_mesh = extended ? object->support_mesh() : TriangleMesh{};
supports_mesh.transform(mesh_trafo_inv);
TriangleMesh supports_mesh;
const bool has_supports_mesh = extended && object->has_mesh(slaposSupportTree);
if (has_supports_mesh) {
supports_mesh = object->get_mesh(slaposSupportTree);
supports_mesh.transform(mesh_trafo_inv);
}
const std::vector<SLAPrintObject::Instance>& obj_instances = object->instances();
for (const SLAPrintObject::Instance& obj_instance : obj_instances) {
auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
@ -6184,19 +6178,19 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
TriangleMesh inst_mesh;
if (has_pad_mesh) {
if (!pad_mesh.empty()) {
TriangleMesh inst_pad_mesh = pad_mesh;
inst_pad_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_pad_mesh);
}
if (has_supports_mesh) {
if (!supports_mesh.empty()) {
TriangleMesh inst_supports_mesh = supports_mesh;
inst_supports_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_supports_mesh);
}
TriangleMesh inst_object_mesh = object->get_mesh_to_slice();
TriangleMesh inst_object_mesh = object->get_mesh_to_print();
inst_object_mesh.transform(mesh_trafo_inv);
inst_object_mesh.transform(inst_transform, is_left_handed);