mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 07:27:41 -06:00
add the logic to reduce slicing time between shared-mesh objects
also reduce the storage size Change-Id: I61d6e0997979ec0ce701cc580fa6640a21b6260f
This commit is contained in:
parent
9245b4f36a
commit
fdd9582e3e
12 changed files with 446 additions and 125 deletions
|
@ -906,7 +906,11 @@ static ExPolygons outer_inner_brim_area(const Print& print,
|
||||||
std::vector<ModelVolume*> groupVolumePtrs;
|
std::vector<ModelVolume*> groupVolumePtrs;
|
||||||
for (auto& volumeID : volumeGroup.volume_ids) {
|
for (auto& volumeID : volumeGroup.volume_ids) {
|
||||||
ModelVolume* currentModelVolumePtr = nullptr;
|
ModelVolume* currentModelVolumePtr = nullptr;
|
||||||
for (auto volumePtr : object->model_object()->volumes) {
|
//BBS: support shared object logic
|
||||||
|
const PrintObject* shared_object = object->get_shared_object();
|
||||||
|
if (!shared_object)
|
||||||
|
shared_object = object;
|
||||||
|
for (auto volumePtr : shared_object->model_object()->volumes) {
|
||||||
if (volumePtr->id() == volumeID) {
|
if (volumePtr->id() == volumeID) {
|
||||||
currentModelVolumePtr = volumePtr;
|
currentModelVolumePtr = volumePtr;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -258,6 +258,8 @@ static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
|
||||||
static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
|
static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
|
||||||
static constexpr const char* SOURCE_IN_METERS = "source_in_meters";
|
static constexpr const char* SOURCE_IN_METERS = "source_in_meters";
|
||||||
|
|
||||||
|
static constexpr const char* MESH_SHARED_KEY = "mesh_shared";
|
||||||
|
|
||||||
static constexpr const char* MESH_STAT_EDGES_FIXED = "edges_fixed";
|
static constexpr const char* MESH_STAT_EDGES_FIXED = "edges_fixed";
|
||||||
static constexpr const char* MESH_STAT_DEGENERATED_FACETS = "degenerate_facets";
|
static constexpr const char* MESH_STAT_DEGENERATED_FACETS = "degenerate_facets";
|
||||||
static constexpr const char* MESH_STAT_FACETS_REMOVED = "facets_removed";
|
static constexpr const char* MESH_STAT_FACETS_REMOVED = "facets_removed";
|
||||||
|
@ -702,6 +704,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
std::string m_thumbnail_path;
|
std::string m_thumbnail_path;
|
||||||
std::vector<std::string> m_sub_model_paths;
|
std::vector<std::string> m_sub_model_paths;
|
||||||
|
|
||||||
|
std::map<int, ModelVolume*> m_shared_meshes;
|
||||||
|
|
||||||
//BBS: plater related structures
|
//BBS: plater related structures
|
||||||
bool m_is_bbl_3mf { false };
|
bool m_is_bbl_3mf { false };
|
||||||
bool m_parsing_slice_info { false };
|
bool m_parsing_slice_info { false };
|
||||||
|
@ -847,8 +851,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
|
|
||||||
bool _handle_start_relationship(const char** attributes, unsigned int num_attributes);
|
bool _handle_start_relationship(const char** attributes, unsigned int num_attributes);
|
||||||
|
|
||||||
void _generate_current_object_list(std::vector<Id> &sub_objects, Id object_id, IdToCurrentObjectMap current_objects);
|
void _generate_current_object_list(std::vector<Component> &sub_objects, Id object_id, IdToCurrentObjectMap current_objects);
|
||||||
bool _generate_volumes_new(ModelObject& object, const std::vector<Id> &sub_objects, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions);
|
bool _generate_volumes_new(ModelObject& object, const std::vector<Component> &sub_objects, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions);
|
||||||
bool _generate_volumes(ModelObject& object, const Geometry& geometry, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions);
|
bool _generate_volumes(ModelObject& object, const Geometry& geometry, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions);
|
||||||
|
|
||||||
// callbacks to parse the .model file
|
// callbacks to parse the .model file
|
||||||
|
@ -1281,7 +1285,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
add_error("3rd 3mf, can not find object, id " + std::to_string(object.first.second));
|
add_error("3rd 3mf, can not find object, id " + std::to_string(object.first.second));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::vector<Id> object_id_list;
|
std::vector<Component> object_id_list;
|
||||||
_generate_current_object_list(object_id_list, object.first, m_current_objects);
|
_generate_current_object_list(object_id_list, object.first, m_current_objects);
|
||||||
|
|
||||||
ObjectMetadata::VolumeMetadataList volumes;
|
ObjectMetadata::VolumeMetadataList volumes;
|
||||||
|
@ -1289,7 +1293,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
|
|
||||||
for (int k = 0; k < object_id_list.size(); k++)
|
for (int k = 0; k < object_id_list.size(); k++)
|
||||||
{
|
{
|
||||||
Id object_id = object_id_list[k];
|
Id object_id = object_id_list[k].object_id;
|
||||||
volumes.emplace_back(object_id.second);
|
volumes.emplace_back(object_id.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,7 +1348,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
model_object->sla_drain_holes = std::move(obj_drain_holes->second);
|
model_object->sla_drain_holes = std::move(obj_drain_holes->second);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
std::vector<Id> object_id_list;
|
std::vector<Component> object_id_list;
|
||||||
_generate_current_object_list(object_id_list, object.first, m_current_objects);
|
_generate_current_object_list(object_id_list, object.first, m_current_objects);
|
||||||
|
|
||||||
ObjectMetadata::VolumeMetadataList volumes;
|
ObjectMetadata::VolumeMetadataList volumes;
|
||||||
|
@ -1375,7 +1379,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
//volumes.emplace_back(0, (int)obj_geometry->second.triangles.size() - 1);
|
//volumes.emplace_back(0, (int)obj_geometry->second.triangles.size() - 1);
|
||||||
for (int k = 0; k < object_id_list.size(); k++)
|
for (int k = 0; k < object_id_list.size(); k++)
|
||||||
{
|
{
|
||||||
Id object_id = object_id_list[k];
|
Id object_id = object_id_list[k].object_id;
|
||||||
volumes.emplace_back(object_id.second);
|
volumes.emplace_back(object_id.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3279,34 +3283,34 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _BBS_3MF_Importer::_generate_current_object_list(std::vector<Id> &sub_objects, Id object_id, IdToCurrentObjectMap current_objects)
|
void _BBS_3MF_Importer::_generate_current_object_list(std::vector<Component> &sub_objects, Id object_id, IdToCurrentObjectMap current_objects)
|
||||||
{
|
{
|
||||||
std::list<Id> id_list;
|
std::list<Component> id_list;
|
||||||
id_list.push_back(object_id);
|
id_list.push_back({ object_id, Transform3d::Identity() });
|
||||||
|
|
||||||
while (!id_list.empty())
|
while (!id_list.empty())
|
||||||
{
|
{
|
||||||
Id current_id = id_list.front();
|
Component current_id = id_list.front();
|
||||||
id_list.pop_front();
|
id_list.pop_front();
|
||||||
IdToCurrentObjectMap::iterator current_object = current_objects.find(current_id);
|
IdToCurrentObjectMap::iterator current_object = current_objects.find(current_id.object_id);
|
||||||
if (current_object != current_objects.end()) {
|
if (current_object != current_objects.end()) {
|
||||||
//found one
|
//found one
|
||||||
if (!current_object->second.components.empty()) {
|
if (!current_object->second.components.empty()) {
|
||||||
for (const Component& comp: current_object->second.components)
|
for (const Component& comp: current_object->second.components)
|
||||||
{
|
{
|
||||||
id_list.push_back(comp.object_id);
|
id_list.push_back(comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(current_object->second.geometry.empty())) {
|
else if (!(current_object->second.geometry.empty())) {
|
||||||
//CurrentObject* ptr = &(current_objects[current_id]);
|
//CurrentObject* ptr = &(current_objects[current_id]);
|
||||||
//CurrentObject* ptr2 = &(current_object->second);
|
//CurrentObject* ptr2 = &(current_object->second);
|
||||||
sub_objects.push_back(current_object->first);
|
sub_objects.push_back({ current_object->first, current_id.transform });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _BBS_3MF_Importer::_generate_volumes_new(ModelObject& object, const std::vector<Id> &sub_objects, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions)
|
bool _BBS_3MF_Importer::_generate_volumes_new(ModelObject& object, const std::vector<Component> &sub_objects, const ObjectMetadata::VolumeMetadataList& volumes, ConfigSubstitutionContext& config_substitutions)
|
||||||
{
|
{
|
||||||
if (!object.volumes.empty()) {
|
if (!object.volumes.empty()) {
|
||||||
add_error("object already built with parts");
|
add_error("object already built with parts");
|
||||||
|
@ -3319,7 +3323,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
for (unsigned int index = 0; index < sub_objects.size(); index++)
|
for (unsigned int index = 0; index < sub_objects.size(); index++)
|
||||||
{
|
{
|
||||||
//find the volume metadata firstly
|
//find the volume metadata firstly
|
||||||
Id object_id = sub_objects[index];
|
Component sub_comp = sub_objects[index];
|
||||||
|
Id object_id = sub_comp.object_id;
|
||||||
IdToCurrentObjectMap::iterator current_object = m_current_objects.find(object_id);
|
IdToCurrentObjectMap::iterator current_object = m_current_objects.find(object_id);
|
||||||
if (current_object == m_current_objects.end()) {
|
if (current_object == m_current_objects.end()) {
|
||||||
add_error("sub_objects can not be found, id=" + std::to_string(object_id.second));
|
add_error("sub_objects can not be found, id=" + std::to_string(object_id.second));
|
||||||
|
@ -3338,29 +3343,55 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
|
|
||||||
Transform3d volume_matrix_to_object = Transform3d::Identity();
|
Transform3d volume_matrix_to_object = Transform3d::Identity();
|
||||||
bool has_transform = false;
|
bool has_transform = false;
|
||||||
|
int shared_mesh_id = -1;
|
||||||
if (volume_data)
|
if (volume_data)
|
||||||
{
|
{
|
||||||
|
int found_count = 0;
|
||||||
// extract the volume transformation from the volume's metadata, if present
|
// extract the volume transformation from the volume's metadata, if present
|
||||||
for (const Metadata& metadata : volume_data->metadata) {
|
for (const Metadata& metadata : volume_data->metadata) {
|
||||||
if (metadata.key == MATRIX_KEY) {
|
if (metadata.key == MATRIX_KEY) {
|
||||||
volume_matrix_to_object = Slic3r::Geometry::transform3d_from_string(metadata.value);
|
volume_matrix_to_object = Slic3r::Geometry::transform3d_from_string(metadata.value);
|
||||||
has_transform = ! volume_matrix_to_object.isApprox(Transform3d::Identity(), 1e-10);
|
has_transform = ! volume_matrix_to_object.isApprox(Transform3d::Identity(), 1e-10);
|
||||||
break;
|
found_count++;
|
||||||
}
|
}
|
||||||
|
else if (metadata.key == MESH_SHARED_KEY){
|
||||||
|
//add the shared mesh logic
|
||||||
|
shared_mesh_id = ::atoi(metadata.value.c_str());
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_count >= 2)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//create a volume_data
|
//create a volume_data
|
||||||
volume_data = &default_volume_data;
|
volume_data = &default_volume_data;
|
||||||
}
|
}
|
||||||
// splits volume out of imported geometry
|
|
||||||
indexed_triangle_set its;
|
ModelVolume* volume = nullptr;
|
||||||
its.indices.assign(sub_object->geometry.triangles.begin(), sub_object->geometry.triangles.end());
|
ModelVolume *shared_volume = nullptr;
|
||||||
const size_t triangles_count = its.indices.size();
|
if (shared_mesh_id != -1) {
|
||||||
|
std::map<int, ModelVolume*>::iterator iter = m_shared_meshes.find(shared_mesh_id);
|
||||||
|
if (iter != m_shared_meshes.end()) {
|
||||||
|
shared_volume = iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t triangles_count = sub_object->geometry.triangles.size();
|
||||||
if (triangles_count == 0) {
|
if (triangles_count == 0) {
|
||||||
add_error("found no trianges in the object " + std::to_string(sub_object->id));
|
add_error("found no trianges in the object " + std::to_string(sub_object->id));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!shared_volume){
|
||||||
|
// splits volume out of imported geometry
|
||||||
|
indexed_triangle_set its;
|
||||||
|
its.indices.assign(sub_object->geometry.triangles.begin(), sub_object->geometry.triangles.end());
|
||||||
|
//const size_t triangles_count = its.indices.size();
|
||||||
|
//if (triangles_count == 0) {
|
||||||
|
// add_error("found no trianges in the object " + std::to_string(sub_object->id));
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
for (const Vec3i& face : its.indices) {
|
for (const Vec3i& face : its.indices) {
|
||||||
for (const int tri_id : face) {
|
for (const int tri_id : face) {
|
||||||
if (tri_id < 0 || tri_id >= int(sub_object->geometry.vertices.size())) {
|
if (tri_id < 0 || tri_id >= int(sub_object->geometry.vertices.size())) {
|
||||||
|
@ -3394,12 +3425,30 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
if (triangle_mesh.volume() < 0)
|
if (triangle_mesh.volume() < 0)
|
||||||
triangle_mesh.flip_triangles();
|
triangle_mesh.flip_triangles();
|
||||||
|
|
||||||
ModelVolume* volume = object.add_volume(std::move(triangle_mesh));
|
volume = object.add_volume(std::move(triangle_mesh));
|
||||||
|
|
||||||
|
m_shared_meshes[sub_object->id] = volume;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//create volume to use shared mesh
|
||||||
|
volume = object.add_volume_with_shared_mesh(*shared_volume);
|
||||||
|
}
|
||||||
// stores the volume matrix taken from the metadata, if present
|
// stores the volume matrix taken from the metadata, if present
|
||||||
if (has_transform)
|
if (has_transform)
|
||||||
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
|
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
|
||||||
|
|
||||||
volume->calculate_convex_hull();
|
volume->calculate_convex_hull();
|
||||||
|
|
||||||
|
//set transform from 3mf
|
||||||
|
Slic3r::Geometry::Transformation comp_transformatino(sub_comp.transform);
|
||||||
|
volume->set_transformation(volume->get_transformation() * comp_transformatino);
|
||||||
|
if (shared_volume) {
|
||||||
|
const TriangleMesh& trangle_mesh = volume->mesh();
|
||||||
|
Vec3d shift = trangle_mesh.get_init_shift();
|
||||||
|
if (!shift.isApprox(Vec3d::Zero()))
|
||||||
|
volume->translate(shift);
|
||||||
|
}
|
||||||
|
|
||||||
// recreate custom supports, seam and mmu segmentation from previously loaded attribute
|
// recreate custom supports, seam and mmu segmentation from previously loaded attribute
|
||||||
if (m_load_config) {
|
if (m_load_config) {
|
||||||
volume->supported_facets.reserve(triangles_count);
|
volume->supported_facets.reserve(triangles_count);
|
||||||
|
@ -3448,7 +3497,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
volume->source.is_converted_from_inches = metadata.value == "1";
|
volume->source.is_converted_from_inches = metadata.value == "1";
|
||||||
else if (metadata.key == SOURCE_IN_METERS)
|
else if (metadata.key == SOURCE_IN_METERS)
|
||||||
volume->source.is_converted_from_meters = metadata.value == "1";
|
volume->source.is_converted_from_meters = metadata.value == "1";
|
||||||
else if (metadata.key == MATRIX_KEY)
|
else if ((metadata.key == MATRIX_KEY) || (metadata.key == MESH_SHARED_KEY))
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions);
|
volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions);
|
||||||
|
@ -4648,12 +4697,37 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
if (m_from_backup_save) {
|
if (m_from_backup_save) {
|
||||||
for (unsigned int index = 1; index <= object.volumes.size(); index ++) {
|
for (unsigned int index = 1; index <= object.volumes.size(); index ++) {
|
||||||
unsigned int ref_id = object_id | (index << 16);
|
unsigned int ref_id = object_id | (index << 16);
|
||||||
stream << " <" << COMPONENT_TAG << " objectid=\"" << ref_id << "\"/>\n";
|
stream << " <" << COMPONENT_TAG << " objectid=\"" << ref_id; // << "\"/>\n";
|
||||||
|
//add the transform of the volume
|
||||||
|
ModelVolume* volume = object.volumes[index - 1];
|
||||||
|
const Transform3d& transf = volume->get_matrix();
|
||||||
|
stream << "\" " << TRANSFORM_ATTR << "=\"";
|
||||||
|
for (unsigned c = 0; c < 4; ++c) {
|
||||||
|
for (unsigned r = 0; r < 3; ++r) {
|
||||||
|
stream << transf(r, c);
|
||||||
|
if (r != 2 || c != 3)
|
||||||
|
stream << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream << "\"/>\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (unsigned int index = object_id; index < volume_start_id; index ++)
|
for (unsigned int index = object_id; index < volume_start_id; index ++) {
|
||||||
stream << " <" << COMPONENT_TAG << " objectid=\"" << index << "\"/>\n";
|
stream << " <" << COMPONENT_TAG << " objectid=\"" << index; // << "\"/>\n";
|
||||||
|
//add the transform of the volume
|
||||||
|
ModelVolume* volume = object.volumes[index - object_id];
|
||||||
|
const Transform3d& transf = volume->get_matrix();
|
||||||
|
stream << "\" " << TRANSFORM_ATTR << "=\"";
|
||||||
|
for (unsigned c = 0; c < 4; ++c) {
|
||||||
|
for (unsigned r = 0; r < 3; ++r) {
|
||||||
|
stream << transf(r, c);
|
||||||
|
if (r != 2 || c != 3)
|
||||||
|
stream << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream << "\"/>\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4803,7 +4877,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
const Transform3d& matrix = volume->get_matrix();
|
const Transform3d& matrix = volume->get_matrix();
|
||||||
|
|
||||||
for (size_t i = 0; i < its.vertices.size(); ++i) {
|
for (size_t i = 0; i < its.vertices.size(); ++i) {
|
||||||
Vec3f v = (matrix * its.vertices[i].cast<double>()).cast<float>();
|
//don't save the volume's matrix into vertex data
|
||||||
|
//add the shared mesh logic
|
||||||
|
//Vec3f v = (matrix * its.vertices[i].cast<double>()).cast<float>();
|
||||||
|
Vec3f v = its.vertices[i];
|
||||||
char* ptr = buf;
|
char* ptr = buf;
|
||||||
boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << VERTEX_TAG << " x=\"");
|
boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << VERTEX_TAG << " x=\"");
|
||||||
ptr = format_coordinate(v.x(), ptr);
|
ptr = format_coordinate(v.x(), ptr);
|
||||||
|
@ -5205,6 +5282,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode)
|
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode)
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
std::map<const TriangleMesh*, int> shared_meshes;
|
||||||
// Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back
|
// Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back
|
||||||
// when loaded as accurately as possible.
|
// when loaded as accurately as possible.
|
||||||
stream << std::setprecision(std::numeric_limits<double>::max_digits10);
|
stream << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||||
|
@ -5297,6 +5375,17 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||||
stream << " <" << METADATA_TAG << " "<< KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n";
|
stream << " <" << METADATA_TAG << " "<< KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//add the shared mesh logic
|
||||||
|
const TriangleMesh* current_mesh = volume->mesh_ptr();
|
||||||
|
std::map<const TriangleMesh*,int>::iterator mesh_iter;
|
||||||
|
mesh_iter = shared_meshes.find(current_mesh);
|
||||||
|
if (mesh_iter != shared_meshes.end()) {
|
||||||
|
stream << " <" << METADATA_TAG << " "<< KEY_ATTR << "=\"" << MESH_SHARED_KEY << "\" " << VALUE_ATTR << "=\"" << mesh_iter->second << "\"/>\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shared_meshes[current_mesh] = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
// stores mesh's statistics
|
// stores mesh's statistics
|
||||||
const RepairedMeshErrors& stats = volume->mesh().stats().repaired_errors;
|
const RepairedMeshErrors& stats = volume->mesh().stats().repaired_errors;
|
||||||
stream << " <" << MESH_STAT_TAG << " ";
|
stream << " <" << MESH_STAT_TAG << " ";
|
||||||
|
|
|
@ -667,6 +667,7 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||||
--idx_tree_support_layer;
|
--idx_tree_support_layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layer_to_print.original_object = &object;
|
||||||
layers_to_print.push_back(layer_to_print);
|
layers_to_print.push_back(layer_to_print);
|
||||||
|
|
||||||
bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|
bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|
||||||
|
@ -2151,7 +2152,9 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
||||||
// Sequential print, single object is being printed.
|
// Sequential print, single object is being printed.
|
||||||
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
||||||
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
||||||
const PrintObject *print_object = layers[layer_id].object();
|
//BBS:add the support of shared print object
|
||||||
|
const PrintObject *print_object = layers[layer_id].original_object;
|
||||||
|
//const PrintObject *print_object = layers[layer_id].object();
|
||||||
if (print_object)
|
if (print_object)
|
||||||
out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx);
|
out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx);
|
||||||
}
|
}
|
||||||
|
@ -2161,7 +2164,9 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
||||||
sorted.reserve(objects_by_extruder.size());
|
sorted.reserve(objects_by_extruder.size());
|
||||||
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
||||||
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
||||||
const PrintObject *print_object = layers[layer_id].object();
|
//BBS:add the support of shared print object
|
||||||
|
const PrintObject *print_object = layers[layer_id].original_object;
|
||||||
|
//const PrintObject *print_object = layers[layer_id].object();
|
||||||
if (print_object)
|
if (print_object)
|
||||||
sorted.emplace_back(print_object, &object_by_extruder);
|
sorted.emplace_back(print_object, &object_by_extruder);
|
||||||
}
|
}
|
||||||
|
@ -2171,6 +2176,10 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
||||||
out.reserve(sorted.size());
|
out.reserve(sorted.size());
|
||||||
for (const PrintInstance *instance : *ordering) {
|
for (const PrintInstance *instance : *ordering) {
|
||||||
const PrintObject &print_object = *instance->print_object;
|
const PrintObject &print_object = *instance->print_object;
|
||||||
|
//BBS:add the support of shared print object
|
||||||
|
//const PrintObject* print_obj_ptr = &print_object;
|
||||||
|
//if (print_object.get_shared_object())
|
||||||
|
// print_obj_ptr = print_object.get_shared_object();
|
||||||
std::pair<const PrintObject*, ObjectByExtruder*> key(&print_object, nullptr);
|
std::pair<const PrintObject*, ObjectByExtruder*> key(&print_object, nullptr);
|
||||||
auto it = std::lower_bound(sorted.begin(), sorted.end(), key);
|
auto it = std::lower_bound(sorted.begin(), sorted.end(), key);
|
||||||
if (it != sorted.end() && it->first == &print_object)
|
if (it != sorted.end() && it->first == &print_object)
|
||||||
|
|
|
@ -201,10 +201,11 @@ public:
|
||||||
// public, so that it could be accessed by free helper functions from GCode.cpp
|
// public, so that it could be accessed by free helper functions from GCode.cpp
|
||||||
struct LayerToPrint
|
struct LayerToPrint
|
||||||
{
|
{
|
||||||
LayerToPrint() : object_layer(nullptr), support_layer(nullptr), tree_support_layer(nullptr) {}
|
LayerToPrint() : object_layer(nullptr), support_layer(nullptr), tree_support_layer(nullptr), original_object(nullptr) {}
|
||||||
const Layer* object_layer;
|
const Layer* object_layer;
|
||||||
const SupportLayer* support_layer;
|
const SupportLayer* support_layer;
|
||||||
const TreeSupportLayer* tree_support_layer;
|
const TreeSupportLayer* tree_support_layer;
|
||||||
|
const PrintObject* original_object; //BBS: used for shared object logic
|
||||||
const Layer* layer() const
|
const Layer* layer() const
|
||||||
{
|
{
|
||||||
if (object_layer != nullptr)
|
if (object_layer != nullptr)
|
||||||
|
@ -218,7 +219,11 @@ public:
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; }
|
|
||||||
|
const PrintObject* object() const
|
||||||
|
{
|
||||||
|
return (this->layer() != nullptr) ? this->layer()->object() : nullptr;
|
||||||
|
}
|
||||||
coordf_t print_z() const
|
coordf_t print_z() const
|
||||||
{
|
{
|
||||||
coordf_t sum_z = 0.;
|
coordf_t sum_z = 0.;
|
||||||
|
|
|
@ -1010,6 +1010,20 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other, TriangleMesh &&me
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelVolume* ModelObject::add_volume_with_shared_mesh(const ModelVolume &other, ModelVolumeType type /*= ModelVolumeType::INVALID*/)
|
||||||
|
{
|
||||||
|
ModelVolume* v = new ModelVolume(this, other.m_mesh);
|
||||||
|
if (type != ModelVolumeType::INVALID && v->type() != type)
|
||||||
|
v->set_type(type);
|
||||||
|
this->volumes.push_back(v);
|
||||||
|
// The volume should already be centered at this point of time when copying shared pointers of the triangle mesh and convex hull.
|
||||||
|
// v->center_geometry_after_creation();
|
||||||
|
// this->invalidate_bounding_box();
|
||||||
|
// BBS: backup
|
||||||
|
Slic3r::save_object_mesh(*this);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void ModelObject::delete_volume(size_t idx)
|
void ModelObject::delete_volume(size_t idx)
|
||||||
{
|
{
|
||||||
ModelVolumePtrs::iterator i = this->volumes.begin() + idx;
|
ModelVolumePtrs::iterator i = this->volumes.begin() + idx;
|
||||||
|
@ -2362,8 +2376,10 @@ void ModelVolume::center_geometry_after_creation(bool update_source_offset)
|
||||||
Vec3d shift = this->mesh().bounding_box().center();
|
Vec3d shift = this->mesh().bounding_box().center();
|
||||||
if (!shift.isApprox(Vec3d::Zero()))
|
if (!shift.isApprox(Vec3d::Zero()))
|
||||||
{
|
{
|
||||||
if (m_mesh)
|
if (m_mesh) {
|
||||||
const_cast<TriangleMesh*>(m_mesh.get())->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2));
|
const_cast<TriangleMesh*>(m_mesh.get())->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2));
|
||||||
|
const_cast<TriangleMesh*>(m_mesh.get())->set_init_shift(shift);
|
||||||
|
}
|
||||||
if (m_convex_hull)
|
if (m_convex_hull)
|
||||||
const_cast<TriangleMesh*>(m_convex_hull.get())->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2));
|
const_cast<TriangleMesh*>(m_convex_hull.get())->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2));
|
||||||
translate(shift);
|
translate(shift);
|
||||||
|
@ -3039,6 +3055,12 @@ void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FacetsAnnotation::equals(const FacetsAnnotation &other) const
|
||||||
|
{
|
||||||
|
const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>>& data = other.get_data();
|
||||||
|
return (m_data == data);
|
||||||
|
}
|
||||||
|
|
||||||
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
||||||
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
||||||
bool model_object_list_equal(const Model &model_old, const Model &model_new)
|
bool model_object_list_equal(const Model &model_old, const Model &model_new)
|
||||||
|
|
|
@ -308,6 +308,7 @@ public:
|
||||||
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
||||||
ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::INVALID);
|
ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::INVALID);
|
||||||
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh);
|
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh);
|
||||||
|
ModelVolume* add_volume_with_shared_mesh(const ModelVolume &other, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
||||||
void delete_volume(size_t idx);
|
void delete_volume(size_t idx);
|
||||||
void clear_volumes();
|
void clear_volumes();
|
||||||
void sort_volumes(bool full_sort);
|
void sort_volumes(bool full_sort);
|
||||||
|
@ -617,6 +618,7 @@ public:
|
||||||
void set_triangle_from_string(int triangle_id, const std::string& str);
|
void set_triangle_from_string(int triangle_id, const std::string& str);
|
||||||
// After deserializing the last triangle, shrink data to fit.
|
// After deserializing the last triangle, shrink data to fit.
|
||||||
void shrink_to_fit() { m_data.first.shrink_to_fit(); m_data.second.shrink_to_fit(); }
|
void shrink_to_fit() { m_data.first.shrink_to_fit(); m_data.second.shrink_to_fit(); }
|
||||||
|
bool equals(const FacetsAnnotation &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constructors to be only called by derived classes.
|
// Constructors to be only called by derived classes.
|
||||||
|
@ -676,6 +678,7 @@ public:
|
||||||
|
|
||||||
// The triangular model.
|
// The triangular model.
|
||||||
const TriangleMesh& mesh() const { return *m_mesh.get(); }
|
const TriangleMesh& mesh() const { return *m_mesh.get(); }
|
||||||
|
const TriangleMesh* mesh_ptr() const { return m_mesh.get(); }
|
||||||
void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
||||||
void set_mesh(TriangleMesh &&mesh) { m_mesh = std::make_shared<const TriangleMesh>(std::move(mesh)); }
|
void set_mesh(TriangleMesh &&mesh) { m_mesh = std::make_shared<const TriangleMesh>(std::move(mesh)); }
|
||||||
void set_mesh(const indexed_triangle_set &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
void set_mesh(const indexed_triangle_set &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
||||||
|
@ -859,6 +862,18 @@ private:
|
||||||
if (mesh.facets_count() > 1)
|
if (mesh.facets_count() > 1)
|
||||||
calculate_convex_hull();
|
calculate_convex_hull();
|
||||||
}
|
}
|
||||||
|
ModelVolume(ModelObject *object, const std::shared_ptr<const TriangleMesh> &mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART) : m_mesh(mesh), m_type(type), object(object)
|
||||||
|
{
|
||||||
|
assert(this->id().valid());
|
||||||
|
assert(this->config.id().valid());
|
||||||
|
assert(this->supported_facets.id().valid());
|
||||||
|
assert(this->seam_facets.id().valid());
|
||||||
|
assert(this->mmu_segmentation_facets.id().valid());
|
||||||
|
assert(this->id() != this->config.id());
|
||||||
|
assert(this->id() != this->supported_facets.id());
|
||||||
|
assert(this->id() != this->seam_facets.id());
|
||||||
|
assert(this->id() != this->mmu_segmentation_facets.id());
|
||||||
|
}
|
||||||
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
|
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
|
||||||
m_mesh(new TriangleMesh(std::move(mesh))), m_convex_hull(new TriangleMesh(std::move(convex_hull))), m_type(type), object(object) {
|
m_mesh(new TriangleMesh(std::move(mesh))), m_convex_hull(new TriangleMesh(std::move(convex_hull))), m_type(type), object(object) {
|
||||||
assert(this->id().valid());
|
assert(this->id().valid());
|
||||||
|
|
|
@ -1130,6 +1130,46 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintObject::set_shared_object(PrintObject *object)
|
||||||
|
{
|
||||||
|
m_shared_object = object;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, found shared object from %2%")%this%m_shared_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintObject::clear_shared_object()
|
||||||
|
{
|
||||||
|
if (m_shared_object) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, clear previous shared object data %2%")%this %m_shared_object;
|
||||||
|
m_layers.clear();
|
||||||
|
m_support_layers.clear();
|
||||||
|
m_tree_support_layers.clear();
|
||||||
|
|
||||||
|
m_shared_object = nullptr;
|
||||||
|
|
||||||
|
invalidate_all_steps_without_cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintObject::copy_layers_from_shared_object()
|
||||||
|
{
|
||||||
|
if (m_shared_object) {
|
||||||
|
m_layers.clear();
|
||||||
|
m_support_layers.clear();
|
||||||
|
m_tree_support_layers.clear();
|
||||||
|
|
||||||
|
firstLayerObjSliceByVolume.clear();
|
||||||
|
firstLayerObjSliceByGroups.clear();
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, copied layers from object %2%")%this%m_shared_object;
|
||||||
|
m_layers = m_shared_object->layers();
|
||||||
|
m_support_layers = m_shared_object->support_layers();
|
||||||
|
m_tree_support_layers = m_shared_object->tree_support_layers();
|
||||||
|
|
||||||
|
firstLayerObjSliceByVolume = m_shared_object->firstLayerObjSlice();
|
||||||
|
firstLayerObjSliceByGroups = m_shared_object->firstLayerObjGroups();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
BoundingBox PrintObject::get_first_layer_bbox(float& a, float& layer_height, std::string& name)
|
BoundingBox PrintObject::get_first_layer_bbox(float& a, float& layer_height, std::string& name)
|
||||||
{
|
{
|
||||||
|
@ -1179,15 +1219,115 @@ void Print::process()
|
||||||
{
|
{
|
||||||
name_tbb_thread_pool_threads_set_locale();
|
name_tbb_thread_pool_threads_set_locale();
|
||||||
|
|
||||||
|
//compute the PrintObject with the same geometries
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, enter")%this;
|
||||||
|
for (PrintObject *obj : m_objects)
|
||||||
|
obj->clear_shared_object();
|
||||||
|
|
||||||
|
//add the print_object share check logic
|
||||||
|
auto is_print_object_the_same = [this](const PrintObject* object1, const PrintObject* object2) -> bool{
|
||||||
|
if (object1->trafo().matrix() != object2->trafo().matrix())
|
||||||
|
return false;
|
||||||
|
const ModelObject* model_obj1 = object1->model_object();
|
||||||
|
const ModelObject* model_obj2 = object2->model_object();
|
||||||
|
if (model_obj1->volumes.size() != model_obj2->volumes.size())
|
||||||
|
return false;
|
||||||
|
bool has_extruder1 = model_obj1->config.has("extruder");
|
||||||
|
bool has_extruder2 = model_obj2->config.has("extruder");
|
||||||
|
if ((has_extruder1 != has_extruder2)
|
||||||
|
|| (has_extruder1 && model_obj1->config.extruder() != model_obj2->config.extruder()))
|
||||||
|
return false;
|
||||||
|
for (int index = 0; index < model_obj1->volumes.size(); index++) {
|
||||||
|
const ModelVolume &model_volume1 = *model_obj1->volumes[index];
|
||||||
|
const ModelVolume &model_volume2 = *model_obj2->volumes[index];
|
||||||
|
if (model_volume1.type() != model_volume2.type())
|
||||||
|
return false;
|
||||||
|
if (model_volume1.mesh_ptr() != model_volume2.mesh_ptr())
|
||||||
|
return false;
|
||||||
|
has_extruder1 = model_volume1.config.has("extruder");
|
||||||
|
has_extruder2 = model_volume2.config.has("extruder");
|
||||||
|
if ((has_extruder1 != has_extruder2)
|
||||||
|
|| (has_extruder1 && model_volume1.config.extruder() != model_volume2.config.extruder()))
|
||||||
|
return false;
|
||||||
|
if (!model_volume1.supported_facets.equals(model_volume2.supported_facets))
|
||||||
|
return false;
|
||||||
|
if (!model_volume1.seam_facets.equals(model_volume2.seam_facets))
|
||||||
|
return false;
|
||||||
|
if (!model_volume1.mmu_segmentation_facets.equals(model_volume2.mmu_segmentation_facets))
|
||||||
|
return false;
|
||||||
|
if (model_volume1.config.get() != model_volume2.config.get())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//if (!object1->config().equals(object2->config()))
|
||||||
|
// return false;
|
||||||
|
if (model_obj1->config.get() != model_obj2->config.get())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
int object_count = m_objects.size();
|
||||||
|
std::set<PrintObject*> need_slicing_objects;
|
||||||
|
for (int index = 0; index < object_count; index++)
|
||||||
|
{
|
||||||
|
PrintObject *obj = m_objects[index];
|
||||||
|
for (PrintObject *slicing_obj : need_slicing_objects)
|
||||||
|
{
|
||||||
|
if (is_print_object_the_same(obj, slicing_obj)) {
|
||||||
|
obj->set_shared_object(slicing_obj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!obj->get_shared_object())
|
||||||
|
need_slicing_objects.insert(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": total object counts %1% in current print, need to slice %2%")%m_objects.size()%need_slicing_objects.size();
|
||||||
BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info();
|
BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info();
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
obj->make_perimeters();
|
obj->make_perimeters();
|
||||||
for (PrintObject *obj : m_objects)
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posSlice))
|
||||||
|
obj->set_done(posSlice);
|
||||||
|
if (obj->set_started(posPerimeters))
|
||||||
|
obj->set_done(posPerimeters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PrintObject *obj : m_objects) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
obj->infill();
|
obj->infill();
|
||||||
for (PrintObject *obj : m_objects)
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posPrepareInfill))
|
||||||
|
obj->set_done(posPrepareInfill);
|
||||||
|
if (obj->set_started(posInfill))
|
||||||
|
obj->set_done(posInfill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PrintObject *obj : m_objects) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
obj->ironing();
|
obj->ironing();
|
||||||
for (PrintObject *obj : m_objects)
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posIroning))
|
||||||
|
obj->set_done(posIroning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PrintObject *obj : m_objects) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
obj->generate_support_material();
|
obj->generate_support_material();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posSupportMaterial))
|
||||||
|
obj->set_done(posSupportMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PrintObject *obj : m_objects)
|
||||||
|
{
|
||||||
|
if (need_slicing_objects.count(obj) == 0)
|
||||||
|
obj->copy_layers_from_shared_object();
|
||||||
|
}
|
||||||
if (this->set_started(psWipeTower)) {
|
if (this->set_started(psWipeTower)) {
|
||||||
m_wipe_tower_data.clear();
|
m_wipe_tower_data.clear();
|
||||||
m_tool_ordering.clear();
|
m_tool_ordering.clear();
|
||||||
|
@ -1290,8 +1430,17 @@ void Print::process()
|
||||||
this->set_done(psSkirtBrim);
|
this->set_done(psSkirtBrim);
|
||||||
}
|
}
|
||||||
//BBS
|
//BBS
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
obj->simplify_extrusion_path();
|
obj->simplify_extrusion_path();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posSimplifyPath))
|
||||||
|
obj->set_done(posSimplifyPath);
|
||||||
|
if (obj->set_started(posSimplifySupportPath))
|
||||||
|
obj->set_done(posSimplifySupportPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info();
|
BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info();
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,6 +415,11 @@ public:
|
||||||
//BBS
|
//BBS
|
||||||
BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name);
|
BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name);
|
||||||
|
|
||||||
|
PrintObject* get_shared_object() const { return m_shared_object; }
|
||||||
|
void set_shared_object(PrintObject *object);
|
||||||
|
void clear_shared_object();
|
||||||
|
void copy_layers_from_shared_object();
|
||||||
|
|
||||||
// BBS: Boundingbox of the first layer
|
// BBS: Boundingbox of the first layer
|
||||||
BoundingBox firstLayerObjectBrimBoundingBox;
|
BoundingBox firstLayerObjectBrimBoundingBox;
|
||||||
private:
|
private:
|
||||||
|
@ -495,6 +500,8 @@ private:
|
||||||
// BBS: per object skirt
|
// BBS: per object skirt
|
||||||
ExtrusionEntityCollection m_skirt;
|
ExtrusionEntityCollection m_skirt;
|
||||||
|
|
||||||
|
PrintObject* m_shared_object{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//BBS: When printing multi-material objects, this settings will make slicer to clip the overlapping object parts one by the other.
|
//BBS: When printing multi-material objects, this settings will make slicer to clip the overlapping object parts one by the other.
|
||||||
//(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).
|
//(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).
|
||||||
|
|
|
@ -629,6 +629,8 @@ protected:
|
||||||
{ return m_state.invalidate_multiple(il.begin(), il.end(), PrintObjectBase::cancel_callback(m_print)); }
|
{ return m_state.invalidate_multiple(il.begin(), il.end(), PrintObjectBase::cancel_callback(m_print)); }
|
||||||
bool invalidate_all_steps()
|
bool invalidate_all_steps()
|
||||||
{ return m_state.invalidate_all(PrintObjectBase::cancel_callback(m_print)); }
|
{ return m_state.invalidate_all(PrintObjectBase::cancel_callback(m_print)); }
|
||||||
|
bool invalidate_all_steps_without_cancel()
|
||||||
|
{ return m_state.invalidate_all([](){}); }
|
||||||
|
|
||||||
bool is_step_started_unguarded(PrintObjectStepEnum step) const { return m_state.is_started_unguarded(step); }
|
bool is_step_started_unguarded(PrintObjectStepEnum step) const { return m_state.is_started_unguarded(step); }
|
||||||
bool is_step_done_unguarded(PrintObjectStepEnum step) const { return m_state.is_done_unguarded(step); }
|
bool is_step_done_unguarded(PrintObjectStepEnum step) const { return m_state.is_done_unguarded(step); }
|
||||||
|
|
|
@ -86,6 +86,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor
|
||||||
|
|
||||||
PrintObject::~PrintObject()
|
PrintObject::~PrintObject()
|
||||||
{
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, m_shared_object %2%")%this%m_shared_object;
|
||||||
if (m_shared_regions && -- m_shared_regions->m_ref_cnt == 0) delete m_shared_regions;
|
if (m_shared_regions && -- m_shared_regions->m_ref_cnt == 0) delete m_shared_regions;
|
||||||
clear_layers();
|
clear_layers();
|
||||||
clear_support_layers();
|
clear_support_layers();
|
||||||
|
@ -535,9 +536,11 @@ std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> PrintObject::prepare
|
||||||
|
|
||||||
void PrintObject::clear_layers()
|
void PrintObject::clear_layers()
|
||||||
{
|
{
|
||||||
|
if (!m_shared_object) {
|
||||||
for (Layer *l : m_layers)
|
for (Layer *l : m_layers)
|
||||||
delete l;
|
delete l;
|
||||||
m_layers.clear();
|
m_layers.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Layer* PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z)
|
Layer* PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z)
|
||||||
|
@ -573,9 +576,11 @@ SupportLayer* PrintObject::get_support_layer_at_printz(coordf_t print_z, coordf_
|
||||||
|
|
||||||
void PrintObject::clear_tree_support_layers()
|
void PrintObject::clear_tree_support_layers()
|
||||||
{
|
{
|
||||||
|
if (!m_shared_object) {
|
||||||
for (TreeSupportLayer* l : m_tree_support_layers)
|
for (TreeSupportLayer* l : m_tree_support_layers)
|
||||||
delete l;
|
delete l;
|
||||||
m_tree_support_layers.clear();
|
m_tree_support_layers.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
||||||
|
@ -602,9 +607,11 @@ TreeSupportLayer* PrintObject::add_tree_support_layer(int id, coordf_t height, c
|
||||||
|
|
||||||
void PrintObject::clear_support_layers()
|
void PrintObject::clear_support_layers()
|
||||||
{
|
{
|
||||||
|
if (!m_shared_object) {
|
||||||
for (Layer *l : m_support_layers)
|
for (Layer *l : m_support_layers)
|
||||||
delete l;
|
delete l;
|
||||||
m_support_layers.clear();
|
m_support_layers.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SupportLayer* PrintObject::add_support_layer(int id, int interface_id, coordf_t height, coordf_t print_z)
|
SupportLayer* PrintObject::add_support_layer(int id, int interface_id, coordf_t height, coordf_t print_z)
|
||||||
|
|
|
@ -152,10 +152,14 @@ public:
|
||||||
|
|
||||||
const TriangleMeshStats& stats() const { return m_stats; }
|
const TriangleMeshStats& stats() const { return m_stats; }
|
||||||
|
|
||||||
|
void set_init_shift(const Vec3d &offset) { m_init_shift = offset; }
|
||||||
|
Vec3d get_init_shift() const { return m_init_shift; }
|
||||||
|
|
||||||
indexed_triangle_set its;
|
indexed_triangle_set its;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TriangleMeshStats m_stats;
|
TriangleMeshStats m_stats;
|
||||||
|
Vec3d m_init_shift {0.0, 0.0, 0.0};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Index of face indices incident with a vertex index.
|
// Index of face indices incident with a vertex index.
|
||||||
|
|
|
@ -2740,6 +2740,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||||
context += append;
|
context += append;
|
||||||
show_info(q, context, _L("Newer 3mf version"));
|
show_info(q, context, _L("Newer 3mf version"));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
//if the minor version is not matched
|
||||||
|
if (file_version.min() != app_version.min()) {
|
||||||
|
wxString text = wxString::Format(_L("The 3mf's version %s is newer than %s's version %s, Suggest to upgrade your software.\n"),
|
||||||
|
file_version.to_string(), std::string(SLIC3R_APP_FULL_NAME), app_version.to_string());
|
||||||
|
show_info(q, text, _L("Newer 3mf version"));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!load_config) {
|
} else if (!load_config) {
|
||||||
for (ModelObject *model_object : model.objects) {
|
for (ModelObject *model_object : model.objects) {
|
||||||
model_object->config.reset();
|
model_object->config.reset();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue