diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 1949a83a0..d3bbae030 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -259,45 +259,6 @@ sub add_instance { } } -sub split_object { - my ($self) = @_; - - if (@{$self->volumes} > 1) { - # We can't split meshes if there's more than one volume, because - # we can't group the resulting meshes by object afterwards - my $o = $self->model->_add_object($self); - return [$o]; - } - - my @new_objects = (); - my $volume = $self->volumes->[0]; - foreach my $mesh (@{$volume->mesh->split}) { - $mesh->repair; - - push @new_objects, my $new_object = $self->model->add_object( - input_file => $self->input_file, - config => $self->config->clone, - layer_height_ranges => $self->layer_height_ranges, # TODO: this needs to be cloned - origin_translation => $self->origin_translation, - ); - $new_object->add_volume( - mesh => $mesh, - name => $volume->name, - material_id => $volume->material_id, - config => $volume->config, - ); - - # add one instance per original instance - $new_object->add_instance( - offset => Slic3r::Pointf->new(@{$_->offset}), - rotation => $_->rotation, - scaling_factor => $_->scaling_factor, - ) for @{ $self->instances }; - } - - return [@new_objects]; -} - sub rotate { my ($self, $angle, $axis) = @_; diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index dad84cf63..d5e9aa6ee 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -44,9 +44,9 @@ Model::add_object() } ModelObject* -Model::add_object(const ModelObject &other) +Model::add_object(const ModelObject &other, bool copy_volumes) { - ModelObject* new_object = new ModelObject(this, other); + ModelObject* new_object = new ModelObject(this, other, copy_volumes); this->objects.push_back(new_object); return new_object; } @@ -269,7 +269,7 @@ ModelObject::ModelObject(Model *model) : model(model) {} -ModelObject::ModelObject(Model *model, const ModelObject &other) +ModelObject::ModelObject(Model *model, const ModelObject &other, bool copy_volumes) : model(model), name(other.name), input_file(other.input_file), @@ -281,11 +281,12 @@ ModelObject::ModelObject(Model *model, const ModelObject &other) _bounding_box(other._bounding_box), _bounding_box_valid(other._bounding_box_valid) { - - this->volumes.reserve(other.volumes.size()); - for (ModelVolumePtrs::const_iterator i = other.volumes.begin(); i != other.volumes.end(); ++i) - this->add_volume(**i); - + if (copy_volumes) { + this->volumes.reserve(other.volumes.size()); + for (ModelVolumePtrs::const_iterator i = other.volumes.begin(); i != other.volumes.end(); ++i) + this->add_volume(**i); + } + this->instances.reserve(other.instances.size()); for (ModelInstancePtrs::const_iterator i = other.instances.begin(); i != other.instances.end(); ++i) this->add_instance(**i); @@ -589,6 +590,34 @@ ModelObject::cut(coordf_t z, Model* model) const } } +void +ModelObject::split(ModelObjectPtrs* new_objects) +{ + if (this->volumes.size() > 1) { + // We can't split meshes if there's more than one volume, because + // we can't group the resulting meshes by object afterwards + new_objects->push_back(this); + return; + } + + ModelVolume* volume = this->volumes.front(); + TriangleMeshPtrs meshptrs = volume->mesh.split(); + for (TriangleMeshPtrs::iterator mesh = meshptrs.begin(); mesh != meshptrs.end(); ++mesh) { + (*mesh)->repair(); + + ModelObject* new_object = this->model->add_object(*this, false); + ModelVolume* new_volume = new_object->add_volume(**mesh); + new_volume->name = volume->name; + new_volume->config = volume->config; + new_volume->modifier = volume->modifier; + new_volume->material_id(volume->material_id()); + + new_objects->push_back(new_object); + } + + return; +} + #ifdef SLIC3RXS REGISTER_CLASS(ModelObject, "Model::Object"); #endif diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index c5123e5fc..9cbe6be40 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -39,7 +39,7 @@ class Model void swap(Model &other); ~Model(); ModelObject* add_object(); - ModelObject* add_object(const ModelObject &other); + ModelObject* add_object(const ModelObject &other, bool copy_volumes = true); void delete_object(size_t idx); void clear_objects(); @@ -60,7 +60,6 @@ class Model void translate(coordf_t x, coordf_t y, coordf_t z); void mesh(TriangleMesh* mesh) const; void raw_mesh(TriangleMesh* mesh) const; - // void split_meshes(); // std::string get_material_name(t_model_material_id material_id); @@ -133,13 +132,14 @@ class ModelObject size_t facets_count() const; bool needed_repair() const; void cut(coordf_t z, Model* model) const; + void split(ModelObjectPtrs* new_objects); void update_bounding_box(); // this is a private method but we expose it until we need to expose it via XS private: Model* model; ModelObject(Model *model); - ModelObject(Model *model, const ModelObject &other); + ModelObject(Model *model, const ModelObject &other, bool copy_volumes = true); ModelObject& operator= (ModelObject other); void swap(ModelObject &other); ~ModelObject(); diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 43d03e9cf..fd31a93d4 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -14,8 +14,8 @@ %code%{ RETVAL = THIS; %}; %name{_add_object} Ref add_object(); - Ref _add_object_clone(ModelObject* other) - %code%{ RETVAL = THIS->add_object(*other); %}; + Ref _add_object_clone(ModelObject* other, bool copy_volumes = true) + %code%{ RETVAL = THIS->add_object(*other, copy_volumes); %}; void delete_object(size_t idx); void clear_objects(); size_t objects_count() @@ -206,6 +206,12 @@ ModelMaterial::attributes() RETVAL = new Model(); THIS->cut(z, RETVAL); %}; + + ModelObjectPtrs* split_object() + %code%{ + RETVAL = new ModelObjectPtrs(); // leak? + THIS->split(RETVAL); + %}; };