#!/usr/bin/perl use strict; use warnings; use Slic3r::XS; use Test::More; use IO::Uncompress::Unzip qw(unzip $UnzipError) ; use Cwd qw(abs_path); use File::Basename qw(dirname); # Removes '\n' and '\r\n' from a string. sub clean { my $text = shift; $text =~ s/\n//g; $text =~ s/\r//g; return $text; } my $current_path = abs_path($0); my $expected_content_types = " \n" ."\n" ."\n" ."\n" ."\n"; my $expected_relationships = " \n" ."\n" ."\n"; # Test 1: Check read/write. { my $input_path = dirname($current_path). "/models/3mf/box.3mf"; my $output_path = dirname($current_path). "/models/3mf/box2.3mf"; # Create a new model. my $model = Slic3r::Model->new; my $result = $model->read_tmf($input_path); is($result, 1, 'Basic 3mf read test.'); $result = $model->write_tmf($output_path); is($result, 1, 'Basic 3mf write test.'); # Delete the created file. unlink($output_path); } # Test 2: Check read metadata/ objects/ components/ build items w/o or with tansformation matrics. { my $input_path = dirname($current_path). "/models/3mf/gimblekeychain.3mf"; # Create a new model. my $model = Slic3r::Model->new; $model->read_tmf($input_path); # Check the number of read matadata. is($model->metadata_count(), 8, 'Test 2: metadata count check.'); # Check the number of read objects. is($model->objects_count(), 1, 'Test 2: objects count check.'); # Check the number of read instances. is($model->get_object(0)->instances_count(), 1, 'Test 2: object instances count check.'); # Check the read object part number. is($model->get_object(0)->part_number(), -1, 'Test 2: object part number check.'); # Check the number of read volumes. is($model->get_object(0)->volumes_count(), 3, 'Test 2: object volumes count check.'); # Check the number of read number of facets (triangles). is($model->get_object(0)->facets_count(), 19884, 'Test 2: object number of facets check.'); # Check the affine transformation matrix decomposition. # Check translation. cmp_ok($model->get_object(0)->get_instance(0)->offset()->x(), '<=', 0.0001, 'Test 2: X translation check.'); cmp_ok($model->get_object(0)->get_instance(0)->offset()->y(), '<=', 0.0001, 'Test 2: Y translation check.'); cmp_ok($model->get_object(0)->get_instance(0)->z_translation() - 0.0345364, '<=', 0.0001, 'Test 2: Z translation check.'); # Check scale. cmp_ok($model->get_object(0)->get_instance(0)->scaling_vector()->x() - 25.4, '<=', 0.0001, 'Test 2: X scale check.'); cmp_ok($model->get_object(0)->get_instance(0)->scaling_vector()->y() - 25.4, '<=', 0.0001, 'Test 2: Y scale check.'); cmp_ok($model->get_object(0)->get_instance(0)->scaling_vector()->z() - 25.4, '<=', 0.0001, 'Test 2: Z scale check.'); # Check X, Y, & Z rotation. cmp_ok($model->get_object(0)->get_instance(0)->x_rotation() - 6.2828, '<=', 0.0001, 'Test 2: X rotation check.'); cmp_ok($model->get_object(0)->get_instance(0)->y_rotation() - 6.2828, '<=', 0.0001, 'Test 2: Y rotation check.'); cmp_ok($model->get_object(0)->get_instance(0)->rotation(), '<=', 0.0001, 'Test 2: Z rotation check.'); } # Test 3: Read an STL and write it as 3MF. { my $input_path = dirname($current_path). "/models/stl/spikey_top.stl"; my $output_path = dirname($current_path). "/models/3mf/spikey_top.3mf"; my $model = Slic3r::Model->new; my $result = $model->read_stl($input_path); is($result, 1, 'Test 3: read the stl model file.'); # Check initialization of 3mf specific atttributes. is($model->metadata_count(), 0, 'Test 3: read stl model metadata count check .'); is($model->get_object(0)->instances_count(), 0, 'Test 3: object instances count check.'); is($model->get_object(0)->part_number(), -1, 'Test 3: object partnumber check.'); is($model->material_count(), 0, 'Test 3: model materials count check.'); $result = $model->write_tmf($output_path); is($result, 1, 'Test 3: Write the 3mf model file.'); unlink($output_path); } # Test 4: Read an 3MF containig multiple objects and volumes and write it as STL. { my $input_path = dirname($current_path). "/models/3mf/gimblekeychain.3mf"; my $output_path = dirname($current_path). "/models/stl/gimblekeychain.stl"; my $model = Slic3r::Model->new; my $result = $model->read_tmf($input_path); is($result, 1, 'Test 4: Read 3MF file check.'); $result = $model->write_stl($output_path); is($result, 1, 'Test 4: convert to stl check.'); unlink($output_path); } # Test 5: Basic Test with model containing vertices and triangles. { my $amf_test_file = dirname($current_path). "/models/amf/FaceColors.amf.xml"; my $tmf_output_file = dirname($current_path). "/models/3mf/FaceColors.3mf"; my $expected_model = "\n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ." \n" ."\n"; # Create a new model. my $model = Slic3r::Model->new; # Read a simple AMF file. $model->read_amf($amf_test_file); # Write in 3MF format. $model->write_tmf($tmf_output_file); # Check contents in 3dmodel.model. my $model_output ; unzip $tmf_output_file => \$model_output, Name => "3D/3dmodel.model" or die "unzip failed: $UnzipError\n"; is (clean($model_output), clean($expected_model), "Test 5: 3dmodel.model file matching"); # Check contents in content_types.xml. my $content_types_output ; unzip $tmf_output_file => \$content_types_output, Name => "[Content_Types].xml" or die "unzip failed: $UnzipError\n"; is (clean($content_types_output), clean($expected_content_types), "Test 5: [Content_Types].xml file matching"); # Check contents in _rels.xml. my $relationships_output ; unzip $tmf_output_file => \$relationships_output, Name => "_rels/.rels" or die "unzip failed: $UnzipError\n"; is (clean($relationships_output), clean($expected_relationships), "Test 5: _rels/.rels file matching"); unlink($tmf_output_file); } # Test 6: Read a Slic3r exported 3MF file. { my $input_path = dirname($current_path). "/models/3mf/chess.3mf"; my $output_path = dirname($current_path). "/models/3mf/chess_2.3mf"; # Read a 3MF model. my $model = Slic3r::Model->new; my $result = $model->read_tmf($input_path); is($result, 1, 'Test 6: Read 3MF file check.'); # Export the 3MF file. $result = $model->write_tmf($output_path); is($result, 1, 'Test 6: Write 3MF file check.'); # Re-read the exported file. my $model_2 = Slic3r::Model->new; $result = $model_2->read_tmf($output_path); is($result, 1, 'Test 6: Read second 3MF file check.'); is($model->metadata_count(), $model_2->metadata_count(), 'Test 6: metadata match check.'); # Check the number of read objects. is($model->objects_count(), $model_2->objects_count(), 'Test 6: objects match check.'); unlink($output_path); } # Finish finish test cases. done_testing(); __END__