Making Time with Twoville, a Language for Fabrication

2025-12-15. Filed in twoville, talks.

Following are the notes from a talk I gave at the computer science education conference CCSC Eastern 2025 at Arcadia University in Glenside, Pennsylvania. The campus featured a castle. The paper was the result of a collaboration with student Devran Turson.

Hi, folks. Sometimes in the middle of lecture, I find myself questioning my life choices. Wouldn't it have been wiser to do something directly related to my survival, like growing food? Why is so much of my day spent in virtual experiences, when I have a body that seems tuned for physical experiences? So a few years ago, I started working on a context for teaching computer science that bridged the virtual and physical worlds. It's called Twoville. It's a programming language and development environment that I use to design real objects. I send its output to fabrication machines to make stickers, cards, clothing, and acrylic or plywood sculptures—none of which require a computer to enjoy.

My goal today is to share Twoville with you. First, I will demonstrate how one can make physical designs. Second, I will share a new feature that student collaborator Devran and I have been working on: animation. Animation and physical fabrication aren't natural partners, which is an issue that we'll have to resolve.

Here are some possible outcomes that might emerge from my sharing:

Static Design

Let's take Twoville for a test spin by modeling a hexagonal nut. With middle schoolers, I usually start with a cloud, but you all seem ready for something a little more algorithmic. We start with a circle that will be the hole:

Design work isn't very fun or humane if you can only modify shapes indirectly through code. That's why Twoville supports direct manipulation. If I select the circle by dropping the cursor in its code, draggable handles show up. Through them we can resize the circle or move it around.

This direct manipulation works with variables too. Suppose I add a second circle and I want it to be a little bit bigger than the first. I factor out a variable that both circles depend on:

The update or repair algorithm is fun to experiment with. It tries to preserve the user's expression as much as possible. For instance, if I resize the outer circle, it holds inner constant and solves for a new value to replace the 1.

Instead of an outer circle, we want an outer hexagon. We generate the vertex positions by looping through polar coordinates, and we round them slightly with a fillet:

Resizing the inner circle reveals some problems that would be more challenging to find without direct manipulation. The relationship between the hexagon and the circle is brittle. The ratio between them tends toward 1. We want a multiplicative relationship. The rounding should also be proportional to the radius. This program feels much better:

That's how we make static shapes in Twoville. There are many commands that I can't cover today, like mirroring, Bézier curves, and mosaics. There's a fairly thorough tutorial on Twoville's website if you'd like to learn more.

Animation Design

Use any tool long enough, and it will start to get used for things beyond its original purpose. That has happened with Twoville. We enjoyed making physical things with it, and we wanted to use it to make icons and figures and visualizations. Some of these needed animations, so my collaborator Devran and I started exploring a system for programming animation. Many animation tools use a graphical keyframe editor, like this from the Unity game engine:

Time is on the x-axis and the value of the animated property is on the y-axis. These particular curves show an object that does a complete rotation and also rises and falls.

We wanted to build timelines like this but with a code interface—because code has redeeming qualities. It is explicit, can be copied and pasted, and expresses repetition, choice, and abstraction. We considered the common patterns we see in animation curves and identified these seven primitives:

The top three are moments that describe a value's property as we arrive or depart from a keyframe. The bottom four are holds that describe a period of constancy between keyframes. This is the syntax we formed to express these primitives:

This uses an after moment and a before moment to form a linear curve. We can put an around moment in with non-linear interpolation to get a continuous loop:

If we scrub to a keyframe, we can still use direct manipulation to modify the animated properties.

Fabricating Time

This seemed like an interesting way to program animations that didn't take away our ability to do bidirectional editing. But then another question emerged. Can we show animation in a fabricated object? This same question has inspired sculptors, painters, photographers, and textbook authors for centuries, so we borrowed some of their solutions.

One solution is to superimpose frames onto one stroboscopic image and then fabricate that. In this design, we randomly generate a star and have it orbit around the origin. When we uncomment the strobe command, we see the sampled frames laid atop one another and colored by age:

We could cut this or stitch this. If we sample very frequently, then we can stack the images up along the third axis and fit a 3D surface across the shape. Here's a program that traces out a Lissajous curve:

It doesn't use keyframe animation but instead references a time variable. We sample it very frequently, and then turn the stack of frames into this 3D model, which we could print:

Instead of plotting frames on top of one another, we can also arrange them in a grid or storyboard display, like this animated yin-yang:

We could print this storyboard and insert it into a zoetrope, an early animation machine made of a spinning wheel. The frames are placed inside the spinning wheel. Across from each is a slot. Viewers look through one of the slots, set the wheel spinning, and then mentally reconstruct the animation as the frames go by.

Our fourth and final strategy for fabricating time is a picket-fence animation. You may have seen this technique in the Scanimation books by Rufus Butler Seder. We view the design through a fence that can slide back and forth. Each position shows slices of one frame. As the fence moves, we see slices from a different frame. Consider this animation of a flapping bird:

The sliced view is confusing to interpret without a fence. I built one in Twoville and cut it on my vinyl cutter so that we could experience this physically. We can also emulate it digitally:

Conclusion

Speaking of time, I think I am out of it. I've shared with you Twoville, a language and platform for making designs using both indirect manipulation via code and direct manipulation via the mouse. Recently we have added support for programmatic animation, but we have tried to preserve the qualities that we value about Twoville: direct manipulation and its orientation around fabrication. That has led us to find ways to show time in physical objects.