Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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 from
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.