Introducing Antimony, free graph-based 3D CAD system

It seems that boxes and noodles are slowly taking over the world. Matt Keeter uses acyclic graphs in Antimony, a free/libre 3D CAD system streamlined for personal manufacturing.

With QCAD, LibreCAD, FreeCAD, BRL-CAD, and less known projects like ZCAD you'd think we are more or less settled with free/libre software for 2D/3D drafting and modeling. But most existing apps are built around concepts that we know from DXF: layers, blocks etc.

Antimony takes a different approach and relies on graph composition where nodes represent 2D/3D shapes and primitives, boolean and math operations, various transformations etc. That will certainly please a lot of people who are already used to node-based compositing in VFX software.

The project was launched by Matt Keeter who currently works as engineer at Formlabs, a popular 3D printer/accessories vendor.

Editing (or should we say compositing?) in Antimony doesn't rely on just using noodles to connect boxes. The 3D view window also provides basic editing features. You can move an object along an axis or scale it, and corresponding nodes will be automatically updated in the graph composition window. So far Antimony only exports heightmaps for 2.5D processes and STL files.

Matt demonstrated the basics of using Antimony in this great video:

He also kindly agreed to answer a few questions about design specifics of Antimony and his future plans.

What was your main problem with existing CAD tools? I gather it has something to do with "drafting tables", lack of innovation etc. :)

First of all, a brief disclaimer: though I’m competent with Solidworks and Blender, I’m not a practicing mechanical engineer, so take my thought with a grain of salt.

That being said, most sketch-based CAD tools are based on manipulating a big blob of global state (in the form of sketches or solid models); there’s more emphasis on stacking machining operations than encoding user design decisions and intent.

There’s also a discontinuity between the modeling system (in the form of constraint solving and geometry kernels) and user interaction.

Antimony pushes that discontinuity a bit farther from view: instead of “extrude” being an opaque operation that does something in the geometry kernel, it’s a script that you can open up and change.

How much pluggable is everything? I see that nodes definitely are. What about file loaders / savers?

Nodes are very pluggable — Antimony looks into a particular directory on startup and builds up menus from “.node” files that it finds there. Loading and saving of Antimony files is all hard-coded in C++; not much room for modification there.

Exporting is somewhere in between: Python scripts can declare that they want to export something, which calls back into C++ and sets up the UI for an export process, but defining new export formats requires changing the application core (rather than scripts).

Is this something you think might/should change in the future, for both importing and exporting?

Maybe, but the cost / benefit ratio is too high at the moment — it would require some architecture changes, and there isn’t enough demand for custom import/export pipelines to warrant it.

So far Antimony looks like a tool best suited for 3D manufacturing. Do you think it could grow into more directions like mechanical engineering (which means FEM and assembly among other things), architecture and BIM workflows, etc.? Would the app's architecture allow for that? Would it even be a good idea?

I’m definitely focused on personal-scale manufacturing at the moment, making tools for individuals and small teams that work with laser cutters, 3D printers, small mills, etc. This is mostly because of my background — when I was at CBA [MIT's Center for Bits & Atoms — LGW], I did a bunch of work with these smaller-scale tools.

Working with assemblies is a natural extension: once I add graph nesting, it will be very simple to create a top-level file that combines a bunch of parts. For bigger systems and architecture workflows, I’d start getting more concerned with evaluation and rendering speed. On the rendering side, there’s an interesting optimization of creating / caching meshes to save on f-rep re-evaluation when the camera angle changes.

The case of assemblies is particularly interesting, because it might mean huge graphs, and that might impact navigation (among other things). Have you tried creating really large graphs (how large?) and seeing how it works in terms of performance, usability etc.?

The largest stuff that I’ve seen is about ~100 nodes. If those graphs are building a small number of parts (rather than multi-part assemblies), rendering isn’t a huge concern. The bigger challenge is in editing the graph — it’s still responsive if you’re editing things downstream, but making a change to a far-upstream parameter causes a noticeable pause as every script re-evaluates itself.

I think that there’s a lot of low-hanging fruit for speeding up big graphs. For example, I’m not even taking the obvious step of saving compiled Python byte-code; every node is being evaluated as a string (even if the text hasn’t changed).

What's your current development focus?

Right now, I’m doing a bunch of polishing for the 0.8.0 tagged release. One of the big changes is to the library of nodes: a few different people have written nodes, all with different styles and using different ways to define shapes; I’m doing a pass over the library to make it consistent and to make sure that all of the shapes are available in the fab.shapes module.

There are also a bunch of small bug-fixes and polishing going into 0.8.0.

Beyond that point, an unordered list of bigger tasks that I’m considering:

Switching to a QML-based UI

Optimizing graph evaluation speed (caching, delayed parsing, etc)

Computing gradients exactly rather than approximately (for better shaded rendering)