qr code


Bill Gates touched my MacBook Pro

Wire: Part I - Intro

[ code , golang , creative-coding ]

Over the last couple of weeks I’ve been working on a somewhat unique 3d library. I call it wire. It’s written in Go and is designed to work with my own blcairo and bitlib libraries.

What’s somewhat unique about this library is that it doesn’t support drawing 3d solids or even filled triangles. It’s all about drawing 3d lines or paths … or wires if you will. It will also draw indiviual 3d points. It also purposely does not do any z-sorting and is really designed to be monocrhomatic so that it doesn’t matter what order lines and points are drawn.

To get us on the same page on what I mean before we dive in deeper, here’s an example.


There are a small set of primitive objects that everything else is made from.


At the base of everything is a 3d point. This just has an x, y, z position and a bunch of methods that can operate on it. Your usual selection of 3d transform methods and some others, and of course a method that projects the 3d point to a 2d screen coordinate.


Points then go into point lists. These are used either to create a single path of “wires” or to render a bunch of individual points. All of the point transform methods also apply to the point lists. So you can rotate, scale, translate, etc. an entire list of points with one command. This follows the same pattern I described in an earlier post on 2d points. And there are methods to render the list of points as a single path or do draw each point individually.


One step up from there is a shape. A shape is a list of point lists. Some shapes can be drawn with a single path - a circle for example. Others need multiple paths, like a 3d box - you could do it in a single path, but you’d have to retrace lines, which would make some lines darker/brighter. There are multiple ways to solve this. I went with multiple paths. You can also call just about any point method on a shape, which will cascade down and operate on every point in every path in that shape. And then you can draw that shape in the same way. For a quick snippet of what this looks like, here’s how you could draw a 3d box.

box := wire.Box(300, 300, 300)
box.Rotate(0.2, 0.5, 0)
3d box


Finally, there is a world object. This contains values that help define how things are rendered, like the center point of the world, the perspective, and near and far clipping distances.

Predefined Shapes

Those are the main types of the whole library. Beyond that, there are a bunch of predefined shape objects, including:

These are just shape objects with predefined sets of paths in them.

The box you’ve seen above. But here it is in motion.

The circle creates a 2d circle that can be transformed in 3d. The sphere, cylinder, cone and torus are all created with a series of circles.

The pyramid and grid plane, like the box, are drawn with longer straight lines.

The string object creates vector text objects from a string of characters. I spent a lot of time on this and it was really fun. I’ll probably do a whole post just on that.

Finally, the torus knot is a complex mathematical structure. It’s actually what started this whole project. I ran across the concept of a torus knot and coded it up. That gave me the base point and path types, and the 3d transform and rendering code. This was pretty easy to put together because I’ve been hand-coding 3d systems like this for well over 20 years. I’m not bragging. Just saying that I keep doing the same things over and over. OK, maybe a humble brag. Anyway, once I had the torus knot looking good, I just started adding other shapes to it.

Render Quality

I’ll acknowledge that the quality of these animations is a bit aliased. This is just how things look straight out of the box. There’s a lot more to cover here, including some tricks I’ve been using to make these look a lot better.

I also want to cover rendering points directly, which doesn’t sound very exciting, but can actually be very cool. So stay tuned on a few additional posts on this library.

The Code

The library is up on github already at https://github.com/bit101/wire. As I said, it all depends on my other two personal libraries, so it’s unlikely you’ll wind up using it directly, but there might be some interesting techniques in there for you to peruse.

« Previous Post
Next Post »

Comments? Best way to shout at me is on Mastodon

Or share this post directly on Mastodon