With no cache:
$ time bin/dat2stl --ldrawdir=ldraw --file ldraw/parts/11295.dat > 11295.stl
real 0m1.857s
user 0m1.764s
sys 0m0.092s
$ time bin/dat2stl --ldrawdir=ldraw --file ldraw/parts/11295.dat > 11295.stl
real 0m1.834s
user 0m1.786s
sys 0m0.048s
With cache:
$ time bin/dat2stl --cache --ldrawdir=ldraw --file ldraw/parts/11295.dat > 11295.stl
real 0m1.084s
user 0m1.044s
sys 0m0.040s
$ time bin/dat2stl --cache --ldrawdir=ldraw --file ldraw/parts/11295.dat > 11295.stl
real 0m1.076s
user 0m1.028s
sys 0m0.048s
Before this commit it appeared that STL viewers could handle the output. However,
rendering the models in OpenGL revealed that the surface normals were all messed up. I
believe most STL viewers just don't care about surface normals, because I suppose they
don't really matter for 3d slicing.
The problem ended up being really a complex issue around the winding order of triangles in
sub-parts, and how this is affected by the "inversion" state. The winding order of
triangles in ldraw is a complex combination of BFC meta commands and transformation
matricies that "mirror" sub-parts. I tried to leave extensive comments in the code rather
than go into it in the commit message.
Also added a json output for rendering as OpenGL buffers. This is to help me debug issues
with the surface normals.
While working on this I also realized that the output of parsing a sub-part can be cached,
as long at the "invert" flag is part of the cache key. This could make a huge difference
in performance, because for example a "stud" gets generated many many times, and in this
version of the code that results in a lot of repeated processing.
I was concatenating paths together using the unix slash `/`. This change used
`File::Spec::catpath` instead, however I haven't been able to test it on Windows, and
there may be other path issues. Also note: without debugging on the user doesn't see when
files are not found (eg: due to path issues), so it silently creates an empty STL file.
There are two major changes here:
1) Previously I was inverting the winding of verticies only when calculating the normal. This was the wrong approach and I instead needed to invert the order of the verticies before calculating the normal. This is because most STL processing software (eg: Slic3r) will recalculate the normals based off the winding (correctly).
2) I *think* I am doing proper BFC handling now, although TBH the BFC handling logic in ldraw is super complex to me. See: https://www.ldraw.org/article/415 ("Rendering Engine Guidelines").
There was bad behaviour if there were nested include files combined with a recursive invert flag, resulting in incorrect surface normals for sub-parts. For example try ldraw/parts/3020.dat before this commit. This is not the best way to solve the problem, but it may suffice for now. IMO the best way would be to "flip" the invert flag between states, rather than explcitely set it to 1 or 0. That way recursively setting invert would simply flip the flag.