teaching machines

Madeup Status Report #3

These past two weeks were host to a considerable number of bug fixes and model generation tweaks. Dowels can be rounded and their thickness can be changed. Better geometry is generated for surfaces of revolution and extrusion. And the user interface feels much more coherent and better remembers users’ settings. Read below for a daily breakdown of my activities and the model of the fortnight.

My record keeping this update may not be totally accurate. I’m trying my best to recall what happened when. My wife was in stop-and-go labor for a week and then delivered our fourth child a couple of days ago. Thanks to some great midwives, nurses, and family, the expansion of our family has gone very peacefully.



  • Adds support for both flat and smooth shading. Up till now, each face in a model had always been shaded independently of all others. Now, a face’s orientation can be averaged with surrounding faces’ orientations to get smoother shading. Not implemented yet is an algorithm that adaptively smooths. Under such an algorithm, faces that form a dihedral angle exceeding some threshold do not share their orientation.


  • Fixes windingness issues on surfaces of revolution and surfaces of extrusion.
  • My wife delivers our fourth child!


  • Incorporates face culling options. Many graphics APIs specify that faces on a model must be enumerated a certain way to determine its visibility. For example, OpenGL says that only faces whose vertices are listed in counterclockwise order when viewed are visible. If the vertices are listed clockwise when viewed, then it assumes the face is on the back side of the model and we are viewing the inside part of the face. Since we usually can’t see inside faces, there’s no point in rendering them. Most users probably won’t need to change the culling options, but while I’m tweaking the geometry generation, I occasionally produce some models with bad windings.


  • Fixes some bugs in the polygon triangulation code.


  • Implements the ear clipping algorithm to triangulate polygons, such as those found in surfaces of extrusion and surfaces of revolution (the exposed cross sections when not rotated a full 360 degrees). This algorithm was necessary because all models must be expressed as a mesh of triangles.


  • Reimplements preview path headers to 3D glyphs that reflect the cursor’s up direction. Previously I had used cones, which didn’t show the cursor’s roll. Then I switched to screen-aligned 2D arrowheads, which also didn’t show roll and whose shifting to stay screen-aligned was disorienting. I’ve switched to an asymmetric 3D arrowhead.

    The new cursor orientation glyph, which shows both the cursor's direction and roll.

    The new cursor orientation glyph, which shows both the cursor’s direction and roll.


  • Improves persistence of preferences in cookies. Now only settings that have been adjusted are saved, so that I can update defaults.
  • Fixes menu sizing to dynamically fit content. When a menu is opened, others now close.
  • Disables shading on wireframe, which may be reverted later.
  • Persists console and editor sizes.


  • Adds support for move 0 commands to paths. Why would you want to move 0 units along a path? When generating a dowel, you may want to widen it at some point. For instance, when tracing out an axle you stop at the point where the wheel should be. You then set the dowel’s radius to however big the wheel is and then move 0 units. This generates two points on the path, each with a different radius. You move to the other side of the wheel, restore the axle’s radius, and then move 0 units again to return to the axle. The end result is that the wheel is extruded out from the axle geometry.

    An example of using move 0 to generate path nodes with varying radii.

    An example of using move 0 to generate path nodes with varying radii.


  • Incorporates support for radius changes within dowel geometry. Instead of the shaft having a fixed radius throughout its length, the radius can be set per node.

    A normally square frame, but with the expanded radii at the top-left and bottom-right corners.

    A normally square frame, but with the expanded radii at the top-left and bottom-right corners.

2015/06/12 through 2015/06/15

  • Adds support for smooth bends in dowel geometry. The user can specify the maximum allowable angle. The geometry will be broken up to accommodate the request.
    Previously, bends in dowels were sharp.

    Previously, bends in dowels were sharp.

    Now bends can be amortized across multiple faces.

    Now bends can be amortized across multiple faces.


  • Adds string literals to Blockly.
  • Adds variables and functions to Blockly interface.
  • Removes blocks with explicit returns that Blockly automatically generates in the toolbox.
  • Adds timeout self-check to function calls as well as loops. Loops are not the only source of infinite execution. Infinite recursion may timeout as well, though it’s more likely to cause an out-of-memory error. Out-of-memory errors stop execution, so there’s little concern that they will bring down a web server.


  • Adds optional timeout to interpreter. Infinite loops are inevitable, and the web client needs some facility for halting execution of programs that would otherwise kill the web server. The earlier Java-based interpreter used ExecutorService and its timeout feature to halt execution. C++11 futures have a wait_for facility that we can use in a similar fashion, but we really don’t need concurrency until we implement a server-based architecture. For the time being, the interpreter synchronously evaluates the program, and expressions self-check to see if the allotted time has has been exceeded. Currently, only loops perform this self-check.


  • Fixes bad parse of for loops. With the by modifier, the upper bound was interpreted as an array. For example, parsing
    for i to 100 by 10

    yielded an incompletely specified 100 by 10 array. A complete specification has an initializing element:  100 by 10 of 0. Until I can think of a better fix, I have outlawed array constructions in for loops’ bound specifications. A better fix would be to catch the exception of the incomplete array construction and backtrack to just match the outer dimension 100 and leave by 10 for other rules to consume.

  • Fixes parameters that shadow a variable in the surrounding environment to no longer clobber the value in the surrounding environment. Instead of updating the existing entry in the environment on a function call, I replace it with an independent value. Previously, the code
    i = 7
    to foo i
      print i
    foo 13
    print i



    Now it correctly prints

  • Adds a polygon generator for testing my triangulation routines:

    Madeup now features a simple polygon generator, which triangulates the path of visited vertices.

    Madeup now features a simple polygon generator, which triangulates the path of visited vertices.

Model of the Fortnight

My 6- and 5-year-old sons joined me while I played the videogame Braid. They very much enjoyed the puzzles and the game’s mind-bending treatment of time. My son Lewis really wanted a ring that slows down time, as found in World 5, while my son Stewart really wanted a key like the one the character Tim uses to unlock doors. We designed both objects in Madeup and printed them. Stewart’s key can be seen being printed below.

My sons waiting for a freshly minted key to cool. The key was generated using the dowel command in Madeup.

My sons waiting for a freshly minted key to cool. The key was generated using the dowel command in Madeup.


  1. Curtis says:

    Hey Chris, as for storage, you might consider a flow like wavepot.com, which saves to your GitHub account if you’re logged in, or to an anonymous Gist if not, so you can still save and share without an account. The anonymous Gist is immutable, so it’s not perfect, but it’s a thought.

Leave a Reply

Your email address will not be published. Required fields are marked *