The sun was out in Liverpool today, creating crisp and long evening shadows. So it seemed like a great opportunity to take photos of recent 3D printed Functy objects. The full images are rather large, but show the grain of the printing, which I think is rather interesting in itself. Click on the images for the full views.
Following on from my previous post, I thought it’d be interesting to make an animated render of the Lissajous figure. If you have an APNG-capable browser (e.g. Firefox) you can see the result on DeviantArt.
While it’s neat to be able to print static versions of these Lissajous figures, in the future I’m sure it’ll be possible to make the fully moving version as well. Now that would be really something!
Sines and Cosines have been responsible for some of the most elegant mathematical constructs. Lissajous curves are a particularly simple, yet elegant example. Put simply, a Lissajous is a parametric curve where each axis follows a sinusoidal path. By tweaking the amplitude and cycle length for each axis, a myriad of different patterns can be generated, from circles to intricately woven lattices.
The parametric curves in Functy are particularly suitable for generating nice Lissajous curves, and as usual, they can be output for 3D printing. The results of pumping them through a 3D printer, courtesy of Shapeways, can be seen in the photos below, along with a Blender Cycles render of one of the curves.
If you fancy getting really up-close-and-personal with them, you can order your own copies as unusual desk ornaments, from the Shapeways site.
As part of an experimental game project I’ve been trying to use the Functy rendering routines to visualise network structures. At the moment it’s at a very early stage, but has - I think - already generated some interesting results.
The screenshot below shows a network of 60 nodes, each one rendered as a spherical co-ordinate function, joined together using links rendered as curves. I just plucked some simple functions out of the air to see what the results would be like but am hoping to extend it with more interesting shapes as things progress.
The various parts of the network are a little hard to discern with a static image, but when I tried to capture a video the result was a mess of fuzzy artefacts (I think there must be something going wrong with my screen capture software), so I gave up on that.
The next step, after neatening up the code, is to arrange better animation of the nodes and links, with dynamic movement based on things like the forces between the nodes. I’m hoping this will produce some really nice effects, and if anything comes of it I’ll put a bit more effort into getting a successful video capture.
In an earlier post I talked about Sederberg et al.’s paper that uses Elimination Theory to demonstrate how parametric curves can be represented in implicit form. Reading through the literature it quickly becomes clear that this is important work if you’re interested in rendering parametric curves or surfaces. Unfortunately it can be difficult to get to grips with the theory without also being able to play around with the functions themselves. Consequently I’d expected to spend much of my summer writing software to render the different types of curves for exploring them and play around with their different representations.
That was, until I realised Functy was quite capable of doing it already. Functy’s parametric curves are already perfectly suited to the rendering of parametric equations. This part might be obvious. Less obvious for me was that the colouring of a flat Cartesian surface is perfect for the rendering of the implicit form.
Above are a couple of screenshots showing the two types of function. These are both taken from the example in another paper by Sederberg, Anderson and Goldman about “Implicitization, Inversion, and Intersection of Planar Rational Cubic Curves” (available from ScienceDirect). The curve is a quartic monoid which can be expressed parametrically and implicitly as follows.
(x4 - 2x3y + 3x2y2 - xy3 +y4) + (2x3 - x2y + xy2 + 3y3) = 0
x = - (3t3 + t2 - t + 2) / (t4 - t3 + 3t2 - 2t + 1)
y = - (3t4 + t3 - t2 + 2t) / (t4 - t3 + 3t2 - 2t + 1)
In the screenshots the red line is the parametric version of the curve for t in the interval (0, 1). The other colours on the surface represent the values of the implicit function. Note that the implicit function actually lies at the boundary of the yellow and blue areas. You can see this slightly better in the 3D version, where the height represents the value of the implicit function. The actual curve occurs only where this is zero - in other words where the surface cuts through the plane z = 0.
It was reassuring to see that the parametric curve matches the implicit version. It’s also interesting to note that the implicit version is rendered entirely using the shaders in a resolution-independent way. It’s possible to zoom in as much as you like without getting pixelisation. This is exciting for me since, although it’s not what I’m really trying to achieve (that would be too easy!), it hints at the possibility.
A parcel arrived from Shapeways recently containing some of the 3D printed ring prototypes I generated using Functy. The models were exported directly from Functy and converted into STY format before being directly uploaded to Shapeways for printing. All based on sine/cosine curves, there’s a flat version, a slightly bulging version and an irregular version. Since Shapeways did such a brilliant job printing the prototypes, the next step is to get them to print them in silver. Click on the links if you fancy having your own printed!
The Functy function files for all of these rings are up in the repository and will be included as example files in the next full release.
After prompting by Tony’s superb gallery of images, I’ve spent a bit of time playing around using Blender to render models created using Functy.
This has also prompted a bit of extra functionality, and I’m hoping it will soon be able to export out multiple models from Functy to support animated functions. Using the current experimental code (there’s no front-end yet, but it’s in the pipeline) I managed to generate a kind of animated mercury whirlpool. It’s up on deviantart, and if you’re happy to wait for the download, please do take a look at the full animated version.
Tony Ralano has been creating some amazing renders by combining Functy models with his impressive Blender and 3DS Max skills. The image below is an example of a function exported out, then manipulated and rendered using Blender.
One of the obvious but neat consequences of having the new STL export functionality from Functy is that the generated models can be imported in to other things. One of these things… well, p3d.in provides a clever HTML5 in-browser model renderer, which means the models can now be rendered interactively directly into this site (or indeed any others). Check out this version of a ball made from string, generated as a couple of curve functions in Functy. Just click and drag to rotate the model. And if you like it, you can even print a copy in 3D!
One of the main aims with Functy has always been to allow functions to be rendered using shaders on the GPU and using the function derivative to generate normals. This should be faster than rendering on the CPU. Defining the normals mathematically should also give more accurate results, and since we have the functions to play around with, it just seems like the sensible thing to do.
This presented a bit of a challenge for the new curve functions though. As is so often the case when using shaders, the problem is one of parallelism. If you have a function, the position of each vector in the model should be independent of the others and therefore a prime target for parallelism. With a curve you have the path of the curve and the radius at a particular point determined mathematically as long as you have the position along the curve, s and the rotation around the curve p given to you. However, what isn’t necessarily pre-determined is the orientation of the curve.
To explain this a bit further, consider the curve in the diagram below. Notice how the vectors perpendicular to the curve change direction as you move along the curve. These vectors are used to define the thickness of the curve at a particular point. In two-dimensions this is fine, as there’s no ambiguity about which direction these vectors should be pointing in.
However, lets now consider this in 3D. Suddenly these vectors can rotate around the axis of the curve, and while the vector must always lie within the plane perpendicular to the curve, there’s still an infinite number of possible directions that the vector can point.
In Functy, we use all of these directions, because the p variable defines a full rotation around the curve, so that it becomes a tube (rather than a line). But we still need to decide which direction the zero angle should point.
Some how or other a choice has to be made for this. There are a number of possibilities. We could set it randomly. However, this means there will be no consistency from one piece of the curve to the next, and if the cross section isn’t a circle, will result in a random twisting of the curve. This would look rubbish, so it’s not an option.
In my 3D Celtic Knot program I came up against exactly the same problem. Since it was essential for the start and end of a curve to match up exactly, I used an iterative approach there. For each piece, the rotation between the previous and next point on the curve is calculated and the perpendicular vector transformed by this in order to establish its new position. At the end of the curve an adjustment is made to ensure pairs of curves will always fit perfectly together. This is possible because the maximum adjustment needed will never be more than 2π/x radians where x is the number of segments that make up the cross section of the curve (called the Radial Accuracy in Functy).
However, unfortunately this technique can’t be easily parallelised since the orientation of each piece depends on the last, meaning that it couldn’t be translated easily into shader code. For Functy I therefore needed a different solution.
Luckily for me this isn’t a new problem, and the solution came in the form of Frenet Frames. A Frenet Frame is an orthogonal set of axes that’s defined based on the curvature and torsion of the curve at a particular point. Since it’s (in general) canonically defined at each point on the curve, it can be calculated independently from the other points, by calculating the derivatives and second-derivatives of the curve. More specifically, it requires that the tangent, normal and binormal vectors of the curve be calculated. There’s a decent explanation in the Wikipedia section “Other expressions of the frame”, and there’s also a neat Wolfram Demonstration too.
Since these three vectors can be calculated using the derivative of the curve, there’s no need to iterate along the curve, which makes it perfect for calculation using shaders. This is now implemented in Functy, and it seems to work pretty well. On my laptop, which has a decent but not mindblowing graphics card, animating a Frenet curve on the GPU using shader code is considerably faster than using the CPU.
The only problem is that this method has a tendency to generate curves with twists in. That is, the axis can make sudden rotations around the direction of the curve. In general this isn’t a problem, but can cause the curve to ‘pinch’ if the resolution of the pieces is too low. Below is a particularly extreme example.
Usually it’s not as bad as this, but it’s a shame nonetheless. For the benefit to be had from parallelisation I’m willing to live with it.