mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Implement modifier volumes and port _merge_loops() to XS
This commit is contained in:
		
							parent
							
								
									b17d06f9d1
								
							
						
					
					
						commit
						c8a48b4527
					
				
					 10 changed files with 195 additions and 109 deletions
				
			
		| 
						 | 
				
			
			@ -178,35 +178,57 @@ sub slice {
 | 
			
		|||
        $layer->region($_) for 0 .. ($regions_count-1);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    # process facets
 | 
			
		||||
    # get array of Z coordinates for slicing
 | 
			
		||||
    my @z = map $_->slice_z, @{$self->layers};
 | 
			
		||||
    
 | 
			
		||||
    # slice all non-modifier volumes
 | 
			
		||||
    for my $region_id (0..$#{$self->region_volumes}) {
 | 
			
		||||
        next if !defined $self->region_volumes->[$region_id];
 | 
			
		||||
        
 | 
			
		||||
        # compose mesh
 | 
			
		||||
        my $mesh;
 | 
			
		||||
        foreach my $volume_id (@{$self->region_volumes->[$region_id]}) {
 | 
			
		||||
            if (defined $mesh) {
 | 
			
		||||
                $mesh->merge($self->model_object->volumes->[$volume_id]->mesh);
 | 
			
		||||
            } else {
 | 
			
		||||
                $mesh = $self->model_object->volumes->[$volume_id]->mesh->clone;
 | 
			
		||||
        my $expolygons_by_layer = $self->_slice_region($region_id, \@z, 0);
 | 
			
		||||
        for my $layer_id (0..$#$expolygons_by_layer) {
 | 
			
		||||
            my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
 | 
			
		||||
            $layerm->slices->clear;
 | 
			
		||||
            foreach my $expolygon (@{ $expolygons_by_layer->[$layer_id] }) {
 | 
			
		||||
                $layerm->slices->append(Slic3r::Surface->new(
 | 
			
		||||
                    expolygon    => $expolygon,
 | 
			
		||||
                    surface_type => S_TYPE_INTERNAL,
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        # transform mesh
 | 
			
		||||
        # we ignore the per-instance transformations currently and only 
 | 
			
		||||
        # consider the first one
 | 
			
		||||
        $self->model_object->instances->[0]->transform_mesh($mesh, 1);
 | 
			
		||||
        
 | 
			
		||||
        # align mesh to Z = 0 and apply XY shift
 | 
			
		||||
        $mesh->translate((map unscale(-$_), @{$self->_copies_shift}), -$self->model_object->bounding_box->z_min);
 | 
			
		||||
        
 | 
			
		||||
        {
 | 
			
		||||
            my $loops = $mesh->slice([ map $_->slice_z, @{$self->layers} ]);
 | 
			
		||||
            for my $layer_id (0..$#$loops) {
 | 
			
		||||
                my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
 | 
			
		||||
                $layerm->make_surfaces($loops->[$layer_id]);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    # then slice all modifier volumes
 | 
			
		||||
    if (@{$self->region_volumes} > 1) {
 | 
			
		||||
        for my $region_id (0..$#{$self->region_volumes}) {
 | 
			
		||||
            my $expolygons_by_layer = $self->_slice_region($region_id, \@z, 1);
 | 
			
		||||
            
 | 
			
		||||
            # loop through the other regions and 'steal' the slices belonging to this one
 | 
			
		||||
            for my $other_region_id (0..$#{$self->region_volumes}) {
 | 
			
		||||
                next if $other_region_id == $region_id;
 | 
			
		||||
                
 | 
			
		||||
                for my $layer_id (0..$#$expolygons_by_layer) {
 | 
			
		||||
                    my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
 | 
			
		||||
                    my $other_layerm = $self->layers->[$layer_id]->regions->[$other_region_id];
 | 
			
		||||
                    
 | 
			
		||||
                    my $other_slices = [ map $_->p, @{$other_layerm->slices} ];  # Polygons
 | 
			
		||||
                    my $my_parts = intersection_ex(
 | 
			
		||||
                        $other_slices,
 | 
			
		||||
                        [ map @$_, @{ $expolygons_by_layer->[$layer_id] } ],
 | 
			
		||||
                    );
 | 
			
		||||
                    next if !@$my_parts;
 | 
			
		||||
                    
 | 
			
		||||
                    # append new parts to our region
 | 
			
		||||
                    foreach my $expolygon (@$my_parts) {
 | 
			
		||||
                        $layerm->slices->append(Slic3r::Surface->new(
 | 
			
		||||
                            expolygon    => $expolygon,
 | 
			
		||||
                            surface_type => S_TYPE_INTERNAL,
 | 
			
		||||
                        ));
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    # remove such parts from original region
 | 
			
		||||
                    $other_layerm->slices->clear;
 | 
			
		||||
                    $other_layerm->append($_) for @{ diff($other_slices, $my_parts) };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            # TODO: read slicing_errors
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -285,6 +307,38 @@ sub slice {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _slice_region {
 | 
			
		||||
    my ($self, $region_id, $z, $modifier) = @_;
 | 
			
		||||
 | 
			
		||||
    return [] if !defined $self->region_volumes->[$region_id];
 | 
			
		||||
 | 
			
		||||
    # compose mesh
 | 
			
		||||
    my $mesh;
 | 
			
		||||
    foreach my $volume_id (@{$self->region_volumes->[$region_id]}) {
 | 
			
		||||
        my $volume = $self->model_object->volumes->[$volume_id];
 | 
			
		||||
        next if $volume->modifier && !$modifier;
 | 
			
		||||
        next if !$volume->modifier && $modifier;
 | 
			
		||||
        
 | 
			
		||||
        if (defined $mesh) {
 | 
			
		||||
            $mesh->merge($volume->mesh);
 | 
			
		||||
        } else {
 | 
			
		||||
            $mesh = $volume->mesh->clone;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    next if !defined $mesh;
 | 
			
		||||
 | 
			
		||||
    # transform mesh
 | 
			
		||||
    # we ignore the per-instance transformations currently and only 
 | 
			
		||||
    # consider the first one
 | 
			
		||||
    $self->model_object->instances->[0]->transform_mesh($mesh, 1);
 | 
			
		||||
 | 
			
		||||
    # align mesh to Z = 0 and apply XY shift
 | 
			
		||||
    $mesh->translate((map unscale(-$_), @{$self->_copies_shift}), -$self->model_object->bounding_box->z_min);
 | 
			
		||||
    
 | 
			
		||||
    # perform actual slicing
 | 
			
		||||
    return $mesh->slice($z);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub make_perimeters {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue