Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Compute STL normals #70

Merged
merged 1 commit into from

3 participants

@bgamari

This fixes Issue #40. It seems, however, that the expression for the face normals given in this issue is off by a negative sign (comparing against normals computed by meshlab)

@colah
Owner

It isn't entirely clear this is the right course of action.

STL normals are ignored by basically all readers, or, at the very least, recomputed if you give a 0 vector. Why do extra work?

With regards to tabs/spaces, everything in ImplicitCAD is tabs right now, not just that file. Is there a good reason to switch to spaces? While it is trivial to run a sed script over it, merges of work done before hand would be a pain. And I kind of like tabs for indentation, spaces for alignment...

@bgamari

@colah, the untabify patch was simply because I saw that the rest of the file was using spaces. I assumed this was an inconsistency that was in need of fixing. It seems I resolved it in the wrong direction. That being said, I personally think that mixing tabs and spaces is a pretty bad idea. This explains why the code is often so mangled in my text editor (emacs). I have given up on using tabs in source code and now just use spaces for indentation (four spaces) and alignment everywhere. I've found my life has been simplified as a result.

As far as computing the normals, I don't see any reason not to do it. It's a pretty simple calculation and as Wikipedia says,

 in order to be entirely portable, a file should both provide the facet normal and order the vertices appropriately.
@matthewSorensen

If we are going to support stl with normal vectors (and I explicitly didn't add that when I rewrote all of the stl export), you'll also need to patch the binary stl implementation.

@bgamari

I've rebased this patch on top of master, added support to the binary STL implementation, and verified that both match meshlab's normals. I think this should be now ready.

@colah
Owner

Great!

@colah colah merged commit c0d7b41 into colah:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 1, 2012
  1. @bgamari

    stl: Compute face normals

    bgamari authored
This page is out of date. Refresh to see the latest.
Showing with 24 additions and 18 deletions.
  1. +24 −18 Graphics/Implicit/Export/TriangleMeshFormats.hs
View
42 Graphics/Implicit/Export/TriangleMeshFormats.hs
@@ -15,24 +15,29 @@ import Data.ByteString.Lazy (ByteString)
import Data.Storable.Endian
import Prelude hiding (replicate)
+import Data.VectorSpace
+import Data.Cross hiding (normal)
+
+normal :: (ℝ3,ℝ3,ℝ3) -> ℝ3
+normal (a,b,c) =
+ normalized $ (b + negateV a) `cross3` (c + negateV a)
stl triangles = toLazyText $ stlHeader <> mconcat (map triangle triangles) <> stlFooter
- where
- stlHeader = "solid ImplictCADExport\n"
- stlFooter = "endsolid ImplictCADExport\n"
- vertex :: ℝ3 -> Builder
- vertex (x,y,z) = mconcat ["vertex "
- ,bf x , " "
- ,bf y , " "
- ,bf z]
- triangle :: (ℝ3, ℝ3, ℝ3) -> Builder
- triangle (a,b,c) =
- "facet normal 0 0 0\n"
- <> "outer loop\n"
- <> vertex a <> "\n"
- <> vertex b <> "\n"
- <> vertex c
- <> "\nendloop\nendfacet\n"
+ where
+ stlHeader = "solid ImplictCADExport\n"
+ stlFooter = "endsolid ImplictCADExport\n"
+ vector :: ℝ3 -> Builder
+ vector (x,y,z) = bf x <> " " <> bf y <> " " <> bf z
+ vertex :: ℝ3 -> Builder
+ vertex v = "vertex " <> vector v
+ triangle :: (ℝ3, ℝ3, ℝ3) -> Builder
+ triangle (a,b,c) =
+ "facet normal " <> vector (normal (a,b,c)) <> "\n"
+ <> "outer loop\n"
+ <> vertex a <> "\n"
+ <> vertex b <> "\n"
+ <> vertex c
+ <> "\nendloop\nendfacet\n"
-- Write a 32-bit little-endian float to a buffer.
@@ -43,9 +48,10 @@ binaryStl :: [Triangle] -> ByteString
binaryStl triangles = toLazyByteString $ header <> lengthField <> mconcat (map triangle triangles)
where header = fromByteString $ replicate 80 0
lengthField = fromWord32le $ toEnum $ length triangles
- triangle (a,b,c) = normal <> point a <> point b <> point c <> fromWord16le 0
+ triangle (a,b,c) = normalV (a,b,c) <> point a <> point b <> point c <> fromWord16le 0
point (x,y,z) = fromWrite $ float32LE x <> float32LE y <> float32LE z
- normal = fromWrite $ float32LE 0 <> float32LE 0 <> float32LE 0
+ normalV ps = let (x,y,z) = normal ps
+ in fromWrite $ float32LE x <> float32LE y <> float32LE z
jsTHREE :: TriangleMesh -> Text
jsTHREE triangles = toLazyText $ header <> vertcode <> facecode <> footer
Something went wrong with that request. Please try again.