Ao is a tool for programmatic computer-aided design.
If you prefer visual explanations, start by watching a 4-minute demo.
In Ao, solid models are defined as Scheme scripts, and there are no opaque function calls into the geometry kernel: everything is visible to the user.
What does that mean? To make a sphere in OpenSCAD, you would write:
sphere(2); // Where does this function come from?
The primitive shape
sphere is an opaque call into the kernel,
and users can go no further.
The library of basic shapes is delimited
by the primitives provided by the language.
Let's compare to drawing a sphere in Ao from first principles:
(define (sphere r) (lambda ( x y z ) (- (sqrt (+ (* x x) (* y y) (* z z))) r))) (define s (sphere 2)) (ao-show s)
In most scripting systems, there's a clear barrier between user-controlled
code and calls into the geometry kernel. In Ao, that barrier is pushed so
far back as to be effectively invisible:
ao-show accepts a lambda function
and draws it on the screen.
Ao is run as a command-line application that embeds GNU Guile. Models can be created in the command line or in standalone scripts.
The screenshow above shows the command line on the left, a text editor on the bottom right, and the 3D viewport on the top right.
To get started, you need to know three functions:
(ao-list-shapes)lists available shape functions.
(ao-show ...)shows a shape in the 3D viewport.
(ao-watch ...)automatically re-runs a script whenever it is saved
To try it out for yourself, clone the source from Github and build it.
Formats and Exports
Models are described in one or more Scheme scripts.
At the moment, there's no way to work with existing models (like
since they're a fundamentally different representation.
In a concession to the outside world, Ao does have a few export functions:
(ao-export-heightmap ...)saves a 16-bit
.pngheightmap, suitable for use in the Fab Modules or similar tools.
(ao-export-mesh ...)saves a
.stlfile. Ao uses dual contouring to produce watertight meshes with sharp edges and corners.
Ever wonder what you'd get if you cut a sphere from a Menger sponge? Here's an example designed in Ao, exported as a mesh, and rendered in Blender: Notice that the corners and edges are sharp, unlike what you would see with a marching cubes triangulation.
Representation and JIT
Shapes are represented as lambda functions, but Scheme isn't designed for the manyfold evaluation needed in an f-rep kernel. How does the kernel turn a Scheme function into a form that can be rendered quickly?
Nested transforms lead to deep expression trees. Can we do better? This post describes a strategy for keeping trees small by automatically detecting and combining affine transforms.
Bounds and transforms
Applying a transform to a shape will change its bounding box, but hard-coding the bounds transform is tedious. How can we automatically derive a new bounding box for the transformed shape?