Rendering Metal Surfaces
[mathematica
santafe
art
opencascade
]
I want to try computationally modeling the surface of indented tinwork items (after taking a class with Cleo Romero at MAKE Santa Fe). The physically based rendering provided by MaterialShading should do the heavy lifting of rendering objects created by constructive solid geometry, but there are some tricks to make this work….
The Setup
Begin by defining the work plane and some positive and negative indentations (viewed from the top), and combine them using CSGRegion:
positive = CSGRegion@
Table[Ball[{RandomReal[{-5, 5}], RandomReal[{-5, 5}], 0}, 0.2], 10];
negative = CSGRegion@
Table[Ball[{RandomReal[{-5, 5}], RandomReal[{-5, 5}], 0}, 0.2], 10];
plane = Cuboid[{-5, -5, -0.2}, {5, 5, 0.0}];
g = CSGRegion["Difference", {#, negative}]&@ CSGRegion["Union", {positive, plane}]
The Problem: CSGRegions do not render
Except, there is a problem: The resulting CSGRegion does not accept MaterialShading:
Graphics3D[{MaterialShading["Gold"], g}]
There is also another problem with the CSGRegion….it does not export to an STL file! If we round trip this, we only get the flat sheet:
Export["~/Downloads/foo.stl", g]
Import[%]
(*"~/Downloads/foo.stl"*)
How shall we fix this problem?
OpenCascadeLink to the Rescue
OpenCascadeLink help us in exporting this, but even then there are some tricks to consider. Conveniently, OpenCascadeShape accepts any CSGRegion as input, which is convenient:
Needs["OpenCascadeLink`"]
oc = OpenCascadeShape[g]
OpenCascadeShapeSurfaceMeshToBoundaryMesh[oc]["Wireframe"] (* visualize *)
We are not out of the woods yet, as it does not export these expressions!
Export["~/Downloads/foo1.stl", oc]
(*$Failed*)
However, the OpenCascadeLink Import/Export documentation describes a workaround, which involves converting a shape into a a MeshRegion for export to fix problematic boundary normals:
mr = MeshRegion@ OpenCascadeShapeSurfaceMeshToBoundaryMesh[oc];
Export["~/Downloads/foo2.stl", mr]
(*"~/Downloads/foo2.stl"*)
We can then Import the STL back in (where it will get converted to a Graphics3D item) and see that it renders nicely:
Graphics3D[
{MaterialShading["Gold"],
Import["Downloads/foo2.stl"]},
Lighting -> "Neutral"]
Our desired pattern is more silvery; there are a few options but Iron is reasonable:
Graphics3D[
{MaterialShading["Iron"],
Import["Downloads/foo2.stl"]},
Lighting -> "Neutral"]
Ideas to explore: Rendering complex patterns
-
Halftone shading–specifically stochastic screening
-
Floyd-Steinberg dithering … or better yet, an Atkinson dither
-
Ditherpunk is an aesthetic
-
There is an App for that… whose core code (in python) for the Atkinson dither is available on github
ToJekyll["Rendering Metal Surfaces", "mathematica santafe art opencascade"]