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
|
@ -270,7 +270,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print
|
||||||
return diff_ex(brim_area, no_brim_area);
|
return diff_ex(brim_area, no_brim_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBS: the brims of different objs will not overlapped with each other, and are stored by objs and by extruders
|
// BBS: the brims of different objs will not overlapped with each other, and are stored by objs and by extruders
|
||||||
static ExPolygons top_level_outer_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim,
|
static ExPolygons top_level_outer_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim,
|
||||||
const float no_brim_offset, double& brim_width_max, std::map<ObjectID, double>& brim_width_map,
|
const float no_brim_offset, double& brim_width_max, std::map<ObjectID, double>& brim_width_map,
|
||||||
std::map<ObjectID, ExPolygons>& brimAreaMap,
|
std::map<ObjectID, ExPolygons>& brimAreaMap,
|
||||||
|
@ -453,7 +453,7 @@ static ExPolygons inner_brim_area(const Print &print,
|
||||||
return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area);
|
return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBS: the brims of different objs will not overlapped with each other, and are stored by objs and by extruders
|
// BBS: the brims of different objs will not overlapped with each other, and are stored by objs and by extruders
|
||||||
static ExPolygons inner_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim,
|
static ExPolygons inner_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim,
|
||||||
const float no_brim_offset, std::map<ObjectID, ExPolygons>& brimAreaMap,
|
const float no_brim_offset, std::map<ObjectID, ExPolygons>& brimAreaMap,
|
||||||
std::map<ObjectID, ExPolygons>& supportBrimAreaMap,
|
std::map<ObjectID, ExPolygons>& supportBrimAreaMap,
|
||||||
|
@ -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;
|
||||||
|
@ -1066,7 +1070,7 @@ static void optimize_polylines_by_reversing(Polylines *polylines)
|
||||||
double dist_to_start = (next.first_point() - prev.last_point()).cast<double>().norm();
|
double dist_to_start = (next.first_point() - prev.last_point()).cast<double>().norm();
|
||||||
double dist_to_end = (next.last_point() - prev.last_point()).cast<double>().norm();
|
double dist_to_end = (next.last_point() - prev.last_point()).cast<double>().norm();
|
||||||
|
|
||||||
if (dist_to_end < dist_to_start)
|
if (dist_to_end < dist_to_start)
|
||||||
next.reverse();
|
next.reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,68 +3343,112 @@ 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;
|
||||||
}
|
}
|
||||||
for (const Vec3i& face : its.indices) {
|
if (!shared_volume){
|
||||||
for (const int tri_id : face) {
|
// splits volume out of imported geometry
|
||||||
if (tri_id < 0 || tri_id >= int(sub_object->geometry.vertices.size())) {
|
indexed_triangle_set its;
|
||||||
add_error("invalid vertex id in object " + std::to_string(sub_object->id));
|
its.indices.assign(sub_object->geometry.triangles.begin(), sub_object->geometry.triangles.end());
|
||||||
return false;
|
//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 int tri_id : face) {
|
||||||
|
if (tri_id < 0 || tri_id >= int(sub_object->geometry.vertices.size())) {
|
||||||
|
add_error("invalid vertex id in object " + std::to_string(sub_object->id));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
its.vertices.assign(sub_object->geometry.vertices.begin(), sub_object->geometry.vertices.end());
|
its.vertices.assign(sub_object->geometry.vertices.begin(), sub_object->geometry.vertices.end());
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
for (const std::string prop_str : sub_object->geometry.face_properties) {
|
for (const std::string prop_str : sub_object->geometry.face_properties) {
|
||||||
FaceProperty face_prop;
|
FaceProperty face_prop;
|
||||||
face_prop.from_string(prop_str);
|
face_prop.from_string(prop_str);
|
||||||
its.properties.push_back(face_prop);
|
its.properties.push_back(face_prop);
|
||||||
}
|
|
||||||
|
|
||||||
TriangleMesh triangle_mesh(std::move(its), volume_data->mesh_stats);
|
|
||||||
|
|
||||||
if (m_version == 0) {
|
|
||||||
// if the 3mf was not produced by BambuStudio and there is only one instance,
|
|
||||||
// bake the transformation into the geometry to allow the reload from disk command
|
|
||||||
// to work properly
|
|
||||||
if (object.instances.size() == 1) {
|
|
||||||
triangle_mesh.transform(object.instances.front()->get_transformation().get_matrix(), false);
|
|
||||||
object.instances.front()->set_transformation(Slic3r::Geometry::Transformation());
|
|
||||||
//FIXME do the mesh fixing?
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (triangle_mesh.volume() < 0)
|
|
||||||
triangle_mesh.flip_triangles();
|
|
||||||
|
|
||||||
ModelVolume* volume = object.add_volume(std::move(triangle_mesh));
|
TriangleMesh triangle_mesh(std::move(its), volume_data->mesh_stats);
|
||||||
|
|
||||||
|
if (m_version == 0) {
|
||||||
|
// if the 3mf was not produced by BambuStudio and there is only one instance,
|
||||||
|
// bake the transformation into the geometry to allow the reload from disk command
|
||||||
|
// to work properly
|
||||||
|
if (object.instances.size() == 1) {
|
||||||
|
triangle_mesh.transform(object.instances.front()->get_transformation().get_matrix(), false);
|
||||||
|
object.instances.front()->set_transformation(Slic3r::Geometry::Transformation());
|
||||||
|
//FIXME do the mesh fixing?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (triangle_mesh.volume() < 0)
|
||||||
|
triangle_mesh.flip_triangles();
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
@ -41,11 +41,11 @@ class OozePrevention {
|
||||||
public:
|
public:
|
||||||
bool enable;
|
bool enable;
|
||||||
Points standby_points;
|
Points standby_points;
|
||||||
|
|
||||||
OozePrevention() : enable(false) {}
|
OozePrevention() : enable(false) {}
|
||||||
std::string pre_toolchange(GCode &gcodegen);
|
std::string pre_toolchange(GCode &gcodegen);
|
||||||
std::string post_toolchange(GCode &gcodegen);
|
std::string post_toolchange(GCode &gcodegen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _get_temp(GCode &gcodegen);
|
int _get_temp(GCode &gcodegen);
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ class Wipe {
|
||||||
public:
|
public:
|
||||||
bool enable;
|
bool enable;
|
||||||
Polyline path;
|
Polyline path;
|
||||||
|
|
||||||
Wipe() : enable(false) {}
|
Wipe() : enable(false) {}
|
||||||
bool has_path() const { return !this->path.points.empty(); }
|
bool has_path() const { return !this->path.points.empty(); }
|
||||||
void reset_path() { this->path = Polyline(); }
|
void reset_path() { this->path = Polyline(); }
|
||||||
|
@ -136,15 +136,15 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class GCode {
|
class GCode {
|
||||||
public:
|
public:
|
||||||
GCode() :
|
GCode() :
|
||||||
m_origin(Vec2d::Zero()),
|
m_origin(Vec2d::Zero()),
|
||||||
m_enable_loop_clipping(true),
|
m_enable_loop_clipping(true),
|
||||||
m_enable_cooling_markers(false),
|
m_enable_cooling_markers(false),
|
||||||
m_enable_extrusion_role_markers(false),
|
m_enable_extrusion_role_markers(false),
|
||||||
m_last_processor_extrusion_role(erNone),
|
m_last_processor_extrusion_role(erNone),
|
||||||
m_layer_count(0),
|
m_layer_count(0),
|
||||||
m_layer_index(-1),
|
m_layer_index(-1),
|
||||||
m_layer(nullptr),
|
m_layer(nullptr),
|
||||||
m_object_layer_over_raft(false),
|
m_object_layer_over_raft(false),
|
||||||
//m_volumetric_speed(0),
|
//m_volumetric_speed(0),
|
||||||
|
@ -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.;
|
||||||
|
@ -249,7 +254,7 @@ private:
|
||||||
|
|
||||||
bool is_open() const { return f; }
|
bool is_open() const { return f; }
|
||||||
bool is_error() const;
|
bool is_error() const;
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
@ -257,12 +262,12 @@ private:
|
||||||
void write(const std::string& what) { this->write(what.c_str()); }
|
void write(const std::string& what) { this->write(what.c_str()); }
|
||||||
void write(const char* what);
|
void write(const char* what);
|
||||||
|
|
||||||
// Write a string into a file.
|
// Write a string into a file.
|
||||||
// Add a newline, if the string does not end with a newline already.
|
// Add a newline, if the string does not end with a newline already.
|
||||||
// Used to export a custom G-code section processed by the PlaceholderParser.
|
// Used to export a custom G-code section processed by the PlaceholderParser.
|
||||||
void writeln(const std::string& what);
|
void writeln(const std::string& what);
|
||||||
|
|
||||||
// Formats and write into a file the given data.
|
// Formats and write into a file the given data.
|
||||||
void write_format(const char* format, ...);
|
void write_format(const char* format, ...);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -375,7 +380,7 @@ private:
|
||||||
InstanceToPrint(ObjectByExtruder &object_by_extruder, size_t layer_id, const PrintObject &print_object, size_t instance_id) :
|
InstanceToPrint(ObjectByExtruder &object_by_extruder, size_t layer_id, const PrintObject &print_object, size_t instance_id) :
|
||||||
object_by_extruder(object_by_extruder), layer_id(layer_id), print_object(print_object), instance_id(instance_id) {}
|
object_by_extruder(object_by_extruder), layer_id(layer_id), print_object(print_object), instance_id(instance_id) {}
|
||||||
|
|
||||||
// Repository
|
// Repository
|
||||||
ObjectByExtruder &object_by_extruder;
|
ObjectByExtruder &object_by_extruder;
|
||||||
// Index into std::vector<LayerToPrint>, which contains Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
// Index into std::vector<LayerToPrint>, which contains Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
||||||
const size_t layer_id;
|
const size_t layer_id;
|
||||||
|
@ -500,14 +505,14 @@ private:
|
||||||
bool object_layer_over_raft() const { return m_object_layer_over_raft; }
|
bool object_layer_over_raft() const { return m_object_layer_over_raft; }
|
||||||
|
|
||||||
friend ObjectByExtruder& object_by_extruder(
|
friend ObjectByExtruder& object_by_extruder(
|
||||||
std::map<unsigned int, std::vector<ObjectByExtruder>> &by_extruder,
|
std::map<unsigned int, std::vector<ObjectByExtruder>> &by_extruder,
|
||||||
unsigned int extruder_id,
|
unsigned int extruder_id,
|
||||||
size_t object_idx,
|
size_t object_idx,
|
||||||
size_t num_objects);
|
size_t num_objects);
|
||||||
friend std::vector<ObjectByExtruder::Island>& object_islands_by_extruder(
|
friend std::vector<ObjectByExtruder::Island>& object_islands_by_extruder(
|
||||||
std::map<unsigned int, std::vector<ObjectByExtruder>> &by_extruder,
|
std::map<unsigned int, std::vector<ObjectByExtruder>> &by_extruder,
|
||||||
unsigned int extruder_id,
|
unsigned int extruder_id,
|
||||||
size_t object_idx,
|
size_t object_idx,
|
||||||
size_t num_objects,
|
size_t num_objects,
|
||||||
size_t num_islands);
|
size_t num_islands);
|
||||||
|
|
||||||
|
|
|
@ -185,10 +185,10 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
||||||
|
|
||||||
if (model.objects.empty())
|
if (model.objects.empty())
|
||||||
throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty");
|
throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty");
|
||||||
|
|
||||||
for (ModelObject *o : model.objects)
|
for (ModelObject *o : model.objects)
|
||||||
o->input_file = input_file;
|
o->input_file = input_file;
|
||||||
|
|
||||||
if (options & LoadStrategy::AddDefaultInstances)
|
if (options & LoadStrategy::AddDefaultInstances)
|
||||||
model.add_default_instances();
|
model.add_default_instances();
|
||||||
|
|
||||||
|
@ -259,14 +259,14 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
//CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
|
//CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_UPDATE_GCODE\n");
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_UPDATE_GCODE\n");
|
||||||
if (proFn) {
|
if (proFn) {
|
||||||
proFn(IMPORT_STAGE_UPDATE_GCODE, 0, 1, cb_cancel);
|
proFn(IMPORT_STAGE_UPDATE_GCODE, 0, 1, cb_cancel);
|
||||||
if (cb_cancel)
|
if (cb_cancel)
|
||||||
throw Slic3r::RuntimeError("Canceled");
|
throw Slic3r::RuntimeError("Canceled");
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomGCode::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z);
|
CustomGCode::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_CHECK_MODE_GCODE\n");
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_CHECK_MODE_GCODE\n");
|
||||||
|
@ -416,7 +416,7 @@ void Model::collect_reusable_objects(std::vector<ObjectBase*>& objects)
|
||||||
std::mem_fn(&ObjectBase::id));
|
std::mem_fn(&ObjectBase::id));
|
||||||
model_object->volumes.clear();
|
model_object->volumes.clear();
|
||||||
}
|
}
|
||||||
// we never own these objects
|
// we never own these objects
|
||||||
this->objects.clear();
|
this->objects.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +591,7 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
||||||
assert(this->objects.size() >= 2);
|
assert(this->objects.size() >= 2);
|
||||||
if (this->objects.size() < 2)
|
if (this->objects.size() < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ModelObject* object = new ModelObject(this);
|
ModelObject* object = new ModelObject(this);
|
||||||
object->input_file = this->objects.front()->input_file;
|
object->input_file = this->objects.front()->input_file;
|
||||||
object->name = boost::filesystem::path(this->objects.front()->input_file).stem().string();
|
object->name = boost::filesystem::path(this->objects.front()->input_file).stem().string();
|
||||||
|
@ -601,7 +601,7 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
||||||
|
|
||||||
for (const ModelObject* o : this->objects)
|
for (const ModelObject* o : this->objects)
|
||||||
for (const ModelVolume* v : o->volumes) {
|
for (const ModelVolume* v : o->volumes) {
|
||||||
// If there are more than one object, put all volumes together
|
// If there are more than one object, put all volumes together
|
||||||
// Each object may contain any number of volumes and instances
|
// Each object may contain any number of volumes and instances
|
||||||
// The volumes transformations are relative to the object containing them...
|
// The volumes transformations are relative to the object containing them...
|
||||||
Geometry::Transformation trafo_volume = v->get_transformation();
|
Geometry::Transformation trafo_volume = v->get_transformation();
|
||||||
|
@ -620,7 +620,7 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
||||||
} else {
|
} else {
|
||||||
for (const ModelInstance* i : o->instances)
|
for (const ModelInstance* i : o->instances)
|
||||||
// ...so, transform everything to a common reference system (world)
|
// ...so, transform everything to a common reference system (world)
|
||||||
copy_volume(object->add_volume(*v))->set_transformation(i->get_transformation() * trafo_volume);
|
copy_volume(object->add_volume(*v))->set_transformation(i->get_transformation() * trafo_volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -1324,7 +1338,7 @@ Polygon ModelObject::convex_hull_2d(const Transform3d& trafo_instance) const
|
||||||
|
|
||||||
void ModelObject::center_around_origin(bool include_modifiers)
|
void ModelObject::center_around_origin(bool include_modifiers)
|
||||||
{
|
{
|
||||||
// calculate the displacements needed to
|
// calculate the displacements needed to
|
||||||
// center this object around the origin
|
// center this object around the origin
|
||||||
const BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box();
|
const BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box();
|
||||||
|
|
||||||
|
@ -1476,8 +1490,8 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, ConversionType con
|
||||||
|
|
||||||
// Perform conversion only if the target "imperial" state is different from the current one.
|
// Perform conversion only if the target "imperial" state is different from the current one.
|
||||||
// This check supports conversion of "mixed" set of volumes, each with different "imperial" state.
|
// This check supports conversion of "mixed" set of volumes, each with different "imperial" state.
|
||||||
if (//vol->source.is_converted_from_inches != from_imperial &&
|
if (//vol->source.is_converted_from_inches != from_imperial &&
|
||||||
(volume_idxs.empty() ||
|
(volume_idxs.empty() ||
|
||||||
std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end())) {
|
std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end())) {
|
||||||
vol->scale_geometry_after_creation(koef);
|
vol->scale_geometry_after_creation(koef);
|
||||||
vol->set_offset(Vec3d(koef, koef, koef).cwiseProduct(volume->get_offset()));
|
vol->set_offset(Vec3d(koef, koef, koef).cwiseProduct(volume->get_offset()));
|
||||||
|
@ -1598,7 +1612,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, std::array<Vec3d, 4> plane_poi
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepLower))
|
if (attributes.has(ModelObjectCutAttribute::KeepLower))
|
||||||
lower->add_volume(*volume);
|
lower->add_volume(*volume);
|
||||||
}
|
}
|
||||||
else if (! volume->mesh().empty()) {
|
else if (! volume->mesh().empty()) {
|
||||||
// Transform the mesh by the combined transformation matrix.
|
// Transform the mesh by the combined transformation matrix.
|
||||||
// Flip the triangles in case the composite transformation is left handed.
|
// Flip the triangles in case the composite transformation is left handed.
|
||||||
TriangleMesh mesh(volume->mesh());
|
TriangleMesh mesh(volume->mesh());
|
||||||
|
@ -1744,7 +1758,7 @@ ModelObjectPtrs ModelObject::segment(size_t instance, unsigned int max_extruders
|
||||||
// Modifiers are not cut, but we still need to add the instance transformation
|
// Modifiers are not cut, but we still need to add the instance transformation
|
||||||
// to the modifier volume transformation to preserve their shape properly.
|
// to the modifier volume transformation to preserve their shape properly.
|
||||||
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
||||||
upper->add_volume(*volume);
|
upper->add_volume(*volume);
|
||||||
}
|
}
|
||||||
else if (!volume->mesh().empty()) {
|
else if (!volume->mesh().empty()) {
|
||||||
// Transform the mesh by the combined transformation matrix.
|
// Transform the mesh by the combined transformation matrix.
|
||||||
|
@ -2185,7 +2199,7 @@ void ModelObject::print_info() const
|
||||||
using namespace std;
|
using namespace std;
|
||||||
cout << fixed;
|
cout << fixed;
|
||||||
boost::nowide::cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
|
boost::nowide::cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
|
||||||
|
|
||||||
TriangleMesh mesh = this->raw_mesh();
|
TriangleMesh mesh = this->raw_mesh();
|
||||||
BoundingBoxf3 bb = mesh.bounding_box();
|
BoundingBoxf3 bb = mesh.bounding_box();
|
||||||
Vec3d size = bb.size();
|
Vec3d size = bb.size();
|
||||||
|
@ -2203,7 +2217,7 @@ void ModelObject::print_info() const
|
||||||
cout << "manifold = " << (mesh.stats().manifold() ? "yes" : "no") << endl;
|
cout << "manifold = " << (mesh.stats().manifold() ? "yes" : "no") << endl;
|
||||||
if (! mesh.stats().manifold())
|
if (! mesh.stats().manifold())
|
||||||
cout << "open_edges = " << mesh.stats().open_edges << endl;
|
cout << "open_edges = " << mesh.stats().open_edges << endl;
|
||||||
|
|
||||||
if (mesh.stats().repaired()) {
|
if (mesh.stats().repaired()) {
|
||||||
const RepairedMeshErrors& stats = mesh.stats().repaired_errors;
|
const RepairedMeshErrors& stats = mesh.stats().repaired_errors;
|
||||||
if (stats.degenerate_facets > 0)
|
if (stats.degenerate_facets > 0)
|
||||||
|
@ -2286,7 +2300,7 @@ void ModelVolume::set_material_id(t_model_material_id material_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelMaterial* ModelVolume::material() const
|
ModelMaterial* ModelVolume::material() const
|
||||||
{
|
{
|
||||||
return this->object->get_model()->get_material(m_material_id);
|
return this->object->get_model()->get_material(m_material_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -2803,7 +2819,7 @@ double Model::getThermalLength(const std::vector<ModelVolume*> modelVolumePtrs)
|
||||||
}
|
}
|
||||||
return thermalLength;
|
return thermalLength;
|
||||||
}
|
}
|
||||||
// max printing speed, difference in bed temperature and envirument temperature and bed adhension coefficients are considered
|
// max printing speed, difference in bed temperature and envirument temperature and bed adhension coefficients are considered
|
||||||
double ModelInstance::get_auto_brim_width(double deltaT, double adhension) const
|
double ModelInstance::get_auto_brim_width(double deltaT, double adhension) const
|
||||||
{
|
{
|
||||||
BoundingBoxf3 raw_bbox = object->raw_mesh_bounding_box();
|
BoundingBoxf3 raw_bbox = object->raw_mesh_bounding_box();
|
||||||
|
@ -2896,7 +2912,7 @@ double ModelInstance::get_auto_brim_width() const
|
||||||
void ModelInstance::get_arrange_polygon(void* ap) const
|
void ModelInstance::get_arrange_polygon(void* ap) const
|
||||||
{
|
{
|
||||||
// static const double SIMPLIFY_TOLERANCE_MM = 0.1;
|
// static const double SIMPLIFY_TOLERANCE_MM = 0.1;
|
||||||
|
|
||||||
Vec3d rotation = get_rotation();
|
Vec3d rotation = get_rotation();
|
||||||
rotation.z() = 0.;
|
rotation.z() = 0.;
|
||||||
Transform3d trafo_instance =
|
Transform3d trafo_instance =
|
||||||
|
@ -2909,7 +2925,7 @@ void ModelInstance::get_arrange_polygon(void* ap) const
|
||||||
// pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
// pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
||||||
// if (!pp.empty()) p = pp.front();
|
// if (!pp.empty()) p = pp.front();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
arrangement::ArrangePolygon& ret = *(arrangement::ArrangePolygon*)ap;
|
arrangement::ArrangePolygon& ret = *(arrangement::ArrangePolygon*)ap;
|
||||||
ret.poly.contour = std::move(p);
|
ret.poly.contour = std::move(p);
|
||||||
ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))};
|
ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))};
|
||||||
|
@ -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)
|
||||||
|
@ -3140,22 +3162,22 @@ bool model_property_changed(const ModelObject &model_object_old, const ModelObje
|
||||||
|
|
||||||
bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject& mo_new)
|
bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject& mo_new)
|
||||||
{
|
{
|
||||||
return model_property_changed(mo, mo_new,
|
return model_property_changed(mo, mo_new,
|
||||||
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
||||||
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.supported_facets.timestamp_matches(mv_new.supported_facets); });
|
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.supported_facets.timestamp_matches(mv_new.supported_facets); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool model_custom_seam_data_changed(const ModelObject& mo, const ModelObject& mo_new)
|
bool model_custom_seam_data_changed(const ModelObject& mo, const ModelObject& mo_new)
|
||||||
{
|
{
|
||||||
return model_property_changed(mo, mo_new,
|
return model_property_changed(mo, mo_new,
|
||||||
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
||||||
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.seam_facets.timestamp_matches(mv_new.seam_facets); });
|
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.seam_facets.timestamp_matches(mv_new.seam_facets); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool model_mmu_segmentation_data_changed(const ModelObject& mo, const ModelObject& mo_new)
|
bool model_mmu_segmentation_data_changed(const ModelObject& mo, const ModelObject& mo_new)
|
||||||
{
|
{
|
||||||
return model_property_changed(mo, mo_new,
|
return model_property_changed(mo, mo_new,
|
||||||
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
||||||
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.mmu_segmentation_facets.timestamp_matches(mv_new.mmu_segmentation_facets); });
|
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.mmu_segmentation_facets.timestamp_matches(mv_new.mmu_segmentation_facets); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3189,7 +3211,7 @@ bool model_has_advanced_features(const Model &model)
|
||||||
void check_model_ids_validity(const Model &model)
|
void check_model_ids_validity(const Model &model)
|
||||||
{
|
{
|
||||||
std::set<ObjectID> ids;
|
std::set<ObjectID> ids;
|
||||||
auto check = [&ids](ObjectID id) {
|
auto check = [&ids](ObjectID id) {
|
||||||
assert(id.valid());
|
assert(id.valid());
|
||||||
assert(ids.find(id) == ids.end());
|
assert(ids.find(id) == ids.end());
|
||||||
ids.insert(id);
|
ids.insert(id);
|
||||||
|
|
|
@ -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) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
|
obj->make_perimeters();
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posSupportMaterial))
|
||||||
|
obj->set_done(posSupportMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->make_perimeters();
|
{
|
||||||
for (PrintObject *obj : m_objects)
|
if (need_slicing_objects.count(obj) == 0)
|
||||||
obj->infill();
|
obj->copy_layers_from_shared_object();
|
||||||
for (PrintObject *obj : m_objects)
|
}
|
||||||
obj->ironing();
|
|
||||||
for (PrintObject *obj : m_objects)
|
|
||||||
obj->generate_support_material();
|
|
||||||
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) {
|
||||||
obj->simplify_extrusion_path();
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
@ -1632,7 +1781,7 @@ void Print::_make_wipe_tower()
|
||||||
for (LayerTools& layer_tools : layer_tools_array) {
|
for (LayerTools& layer_tools : layer_tools_array) {
|
||||||
layer_tools.has_wipe_tower = true;
|
layer_tools.has_wipe_tower = true;
|
||||||
if (layer_tools.wipe_tower_partitions == 0) {
|
if (layer_tools.wipe_tower_partitions == 0) {
|
||||||
layer_tools.wipe_tower_partitions = 1;
|
layer_tools.wipe_tower_partitions = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
for (Layer *l : m_layers)
|
if (!m_shared_object) {
|
||||||
delete l;
|
for (Layer *l : m_layers)
|
||||||
m_layers.clear();
|
delete l;
|
||||||
|
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()
|
||||||
{
|
{
|
||||||
for (TreeSupportLayer* l : m_tree_support_layers)
|
if (!m_shared_object) {
|
||||||
delete l;
|
for (TreeSupportLayer* l : m_tree_support_layers)
|
||||||
m_tree_support_layers.clear();
|
delete l;
|
||||||
|
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()
|
||||||
{
|
{
|
||||||
for (Layer *l : m_support_layers)
|
if (!m_shared_object) {
|
||||||
delete l;
|
for (Layer *l : m_support_layers)
|
||||||
m_support_layers.clear();
|
delete l;
|
||||||
|
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