From e6b174a3b618907ed189c1fe95df7c9b19fc62ca Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 7 Oct 2014 16:15:53 +0200 Subject: Fix T42000: STL export scale incorrect. Not a bug, in fact, more like a feature request. Added an option to take into account scene's scale on both export and import time. Also added scaling/axis conversion to importer. --- io_mesh_stl/__init__.py | 86 +++++++++++++++++++++++++++++++++++++------- io_mesh_stl/blender_utils.py | 5 ++- 2 files changed, 77 insertions(+), 14 deletions(-) (limited to 'io_mesh_stl') diff --git a/io_mesh_stl/__init__.py b/io_mesh_stl/__init__.py index 7514983a..785bfb34 100644 --- a/io_mesh_stl/__init__.py +++ b/io_mesh_stl/__init__.py @@ -90,13 +90,59 @@ class ImportSTL(Operator, ImportHelper): subtype='DIR_PATH', ) + axis_forward = EnumProperty( + name="Forward", + items=(('X', "X Forward", ""), + ('Y', "Y Forward", ""), + ('Z', "Z Forward", ""), + ('-X', "-X Forward", ""), + ('-Y', "-Y Forward", ""), + ('-Z', "-Z Forward", ""), + ), + default='Y', + ) + axis_up = EnumProperty( + name="Up", + items=(('X', "X Up", ""), + ('Y', "Y Up", ""), + ('Z', "Z Up", ""), + ('-X', "-X Up", ""), + ('-Y', "-Y Up", ""), + ('-Z', "-Z Up", ""), + ), + default='Z', + ) + global_scale = FloatProperty( + name="Scale", + min=0.01, max=1000.0, + default=1.0, + ) + + use_scene_unit = BoolProperty( + name="Scene Unit", + description="Apply current scene's unit (as defined by unit scale) to imported data", + default=False, + ) + def execute(self, context): from . import stl_utils from . import blender_utils + from mathutils import Matrix paths = [os.path.join(self.directory, name.name) for name in self.files] + scene = context.scene + + # Take into account scene's unit scale, so that 1 inch in Blender gives 1 inch elsewhere! See T42000. + global_scale = self.global_scale + if scene.unit_settings.system != 'NONE' and self.use_scene_unit: + global_scale /= scene.unit_settings.scale_length + + global_matrix = axis_conversion(from_forward=self.axis_forward, + from_up=self.axis_up, + ).to_4x4() * Matrix.Scale(global_scale, 4) + if not paths: paths.append(self.filepath) @@ -109,7 +155,7 @@ class ImportSTL(Operator, ImportHelper): for path in paths: objName = bpy.path.display_name(os.path.basename(path)) tris, pts = stl_utils.read_stl(path) - blender_utils.create_and_link_mesh(objName, tris, pts) + blender_utils.create_and_link_mesh(objName, tris, pts, global_matrix) return {'FINISHED'} @@ -122,17 +168,6 @@ class ExportSTL(Operator, ExportHelper): filename_ext = ".stl" filter_glob = StringProperty(default="*.stl", options={'HIDDEN'}) - ascii = BoolProperty( - name="Ascii", - description="Save the file in ASCII file format", - default=False, - ) - use_mesh_modifiers = BoolProperty( - name="Apply Modifiers", - description="Apply the modifiers before saving", - default=True, - ) - axis_forward = EnumProperty( name="Forward", items=(('X', "X Forward", ""), @@ -161,6 +196,23 @@ class ExportSTL(Operator, ExportHelper): default=1.0, ) + use_scene_unit = BoolProperty( + name="Scene Unit", + description="Apply current scene's unit (as defined by unit scale) to exported data", + default=True, + ) + ascii = BoolProperty( + name="Ascii", + description="Save the file in ASCII file format", + default=False, + ) + use_mesh_modifiers = BoolProperty( + name="Apply Modifiers", + description="Apply the modifiers before saving", + default=False, + ) + + def execute(self, context): from . import stl_utils from . import blender_utils @@ -171,12 +223,20 @@ class ExportSTL(Operator, ExportHelper): "global_scale", "check_existing", "filter_glob", + "use_scene_unit", "use_mesh_modifiers", )) + scene = context.scene + + # Take into account scene's unit scale, so that 1 inch in Blender gives 1 inch elsewhere! See T42000. + global_scale = self.global_scale + if scene.unit_settings.system != 'NONE' and self.use_scene_unit: + global_scale *= scene.unit_settings.scale_length + global_matrix = axis_conversion(to_forward=self.axis_forward, to_up=self.axis_up, - ).to_4x4() * Matrix.Scale(self.global_scale, 4) + ).to_4x4() * Matrix.Scale(global_scale, 4) faces = itertools.chain.from_iterable( blender_utils.faces_from_mesh(ob, global_matrix, self.use_mesh_modifiers) diff --git a/io_mesh_stl/blender_utils.py b/io_mesh_stl/blender_utils.py index a13277ad..6c22cf57 100644 --- a/io_mesh_stl/blender_utils.py +++ b/io_mesh_stl/blender_utils.py @@ -21,11 +21,14 @@ import bpy -def create_and_link_mesh(name, faces, points): +def create_and_link_mesh(name, faces, points, global_matrix): """ Create a blender mesh and object called name from a list of *points* and *faces* and link it in the current scene. """ + from mathutils import Vector + + points = tuple(global_matrix * Vector(p) for p in points) mesh = bpy.data.meshes.new(name) mesh.from_pydata(points, [], faces) -- cgit v1.2.3