Page MenuHome

optional-normals-patch.diff

File Metadata

Author
Fabio Arnold (donfabio)
Created
Mar 25 2014, 9:40 PM

optional-normals-patch.diff

diff --git a/io_mesh_stl/__init__.py b/io_mesh_stl/__init__.py
index 4074aec..f022833 100644
--- a/io_mesh_stl/__init__.py
+++ b/io_mesh_stl/__init__.py
@@ -128,6 +128,11 @@ class ExportSTL(Operator, ExportHelper):
description="Save the file in ASCII file format",
default=False,
)
+ use_normals = BoolProperty(
+ name="Write Normals",
+ description="Export one normal per face, to represent flat faces and sharp edges",
+ default=False,
+ )
use_mesh_modifiers = BoolProperty(
name="Apply Modifiers",
description="Apply the modifiers before saving",
@@ -176,7 +181,8 @@ class ExportSTL(Operator, ExportHelper):
blender_utils.faces_from_mesh(ob, global_matrix, self.use_mesh_modifiers)
for ob in context.selected_objects)
- stl_utils.write_stl(self.filepath, faces, self.ascii)
+ stl_utils.write_stl(self.filepath, faces, self.ascii,
+ EXPORT_NORMALS=self.use_normals)
return {'FINISHED'}
diff --git a/io_mesh_stl/stl_utils.py b/io_mesh_stl/stl_utils.py
index 49e8d0f..5701f71 100644
--- a/io_mesh_stl/stl_utils.py
+++ b/io_mesh_stl/stl_utils.py
@@ -30,6 +30,7 @@ import struct
import mmap
import contextlib
import itertools
+from mathutils import Vector # for face normal construction
# TODO: endien
@@ -156,7 +157,7 @@ def _ascii_read(data):
for l_item in (l, data.readline(), data.readline())]
-def _binary_write(filename, faces):
+def _binary_write(filename, faces, EXPORT_NORMALS):
with open(filename, 'wb') as data:
# header
# we write padding at header beginning to avoid to
@@ -165,36 +166,58 @@ def _binary_write(filename, faces):
# 3 vertex == 9f
pack = struct.Struct('<9f').pack
- # pad is to remove normal, we do use them
- pad = b'\0' * struct.calcsize('<3f')
- nb = 0
- for verts in faces:
- # write pad as normal + vertexes + pad as attributes
- data.write(pad + pack(*itertools.chain.from_iterable(verts)))
- data.write(b'\0\0')
- nb += 1
+ nb = 0 # number of vertices written
+
+ if EXPORT_NORMALS:
+ for verts in faces:
+ # calculate face normal
+ normal = Vector.cross(verts[1] - verts[0], verts[2] - verts[0]).normalized()
+ # write normal + vertexes + pad as attributes
+ data.write(struct.pack('<3f', *normal) + pack(*itertools.chain.from_iterable(verts)))
+ data.write(b'\0\0') # attribute byte count (unused)
+ nb += 1
+ else:
+ # pad is to remove normal, we do use them
+ pad = b'\0' * struct.calcsize('<3f')
+
+ for verts in faces:
+ # write pad as normal + vertexes + pad as attributes
+ data.write(pad + pack(*itertools.chain.from_iterable(verts)))
+ data.write(b'\0\0') # attribute byte count (unused)
+ nb += 1
# header, with correct value now
data.seek(0)
data.write(struct.pack('<80sI', _header_version().encode('ascii'), nb))
-def _ascii_write(filename, faces):
+def _ascii_write(filename, faces, EXPORT_NORMALS):
with open(filename, 'w') as data:
header = _header_version()
data.write('solid %s\n' % header)
- for face in faces:
- data.write('''facet normal 0 0 0\nouter loop\n''')
- for vert in face:
- data.write('vertex %f %f %f\n' % vert[:])
- data.write('endloop\nendfacet\n')
+ if EXPORT_NORMALS:
+ for face in faces:
+ # calculate face normal
+ normal = Vector.cross(face[1] - face[0], face[2] - face[0]).normalized()
+ data.write('facet normal %f %f %f\nouter loop\n' % normal[:])
+ for vert in face:
+ data.write('vertex %f %f %f\n' % vert[:])
+ data.write('endloop\nendfacet\n')
+ else:
+ for face in faces:
+ data.write('''facet normal 0 0 0\nouter loop\n''')
+ for vert in face:
+ data.write('vertex %f %f %f\n' % vert[:])
+ data.write('endloop\nendfacet\n')
data.write('endsolid %s\n' % header)
-def write_stl(filename, faces, ascii=False):
+def write_stl(filename, faces, ascii=False,
+ EXPORT_NORMALS=False
+ ):
"""
Write a stl file from faces,
@@ -206,8 +229,11 @@ def write_stl(filename, faces, ascii=False):
ascii
save the file in ascii format (very huge)
+
+ EXPORT_NORMALS
+ calculate face normals and write them
"""
- (_ascii_write if ascii else _binary_write)(filename, faces)
+ (_ascii_write if ascii else _binary_write)(filename, faces, EXPORT_NORMALS)
def read_stl(filename):

Event Timeline