In the last article I talked about the various ways that you can repeat 3d space within a distance estimator. As well as folding space along flat planes, there’s a second type of fold which comes up in various 3d fractals, the sphere fold.

The way to imagine a sphere fold is that space on one side of the sphere is a reflection of the space on the other side. To get a handle on this, let’s consider a 2d example of the principle. Let’s consider this a “circle fold”. I have no idea if such a thing exists, but in the following diagram you can see a 2d line intersecting with a circle.

There are two ways to fold space around this circle boundary. Firstly space can be folded inside the sphere. In this case you can imagine that the space inside the circle is simply a reflection of the space outside the circle. In this case all lines will tend towards the centre of the circle, kind of like magnetic field lines. Here’s what happens in 2d with that simple red line now appearing as the green line.

The opposite fold is where space outside the circle is the mirror image of what’s inside the circle. In this case the magnetic field line effect still occurs, but now it’s outside the circle.

The 2d diagram hopefully makes it easier to understand what happens when we extend this effect into three dimensions. First off I’m going to start with a repeating grid of cuboids in three dimensions. So that we can better understand what’s going on inside the folding sphere I’m going to clip them to an outer sphere that fits inside the -1,1 cuboid.

shader gridcuboids { distance = max( // intersection sphere(pos, vec(0,0,0), 1.0), // unit sphere box(vec(fold(getx(pos),0.1), // repeat x axis 0.1 fold(gety(pos),0.1), // repeat y axis 0.1 fold(getz(pos),0.1)), // repeat z axis 0.1 vec(0.5,0.02,0.02), // cuboid long on x axis vec(0,0,0))) // no offset }

So now onto the sphere using an inner sphere fold. This means that all positions inside the sphere are actually reflections of space outside the sphere.

shader gridcuboids { distance = max( sphere(pos, vec(0,0,0), 1.0), box(vec(fold(getx(spherefold(pos,0.9)),0.1), // repeat sphere folded space fold(gety(spherefold(pos,0.9)),0.1), // repeat sphere folded space fold(getz(spherefold(pos,0.9)),0.1)), // repeat sphere folded space vec(0.5,0.02,0.02), vec(0,0,0))) }

As you can see, in this render the cuboids almost look like they’re following magnetic force lines inside the sphere, all being pulled into the centre of the unit sphere.

So let’s take a look at an outer sphere fold. In this example the cuboids inside the sphere are now reflected outside the sphere.

shader gridcuboids { distance = max( sphere(pos, vec(0,0,0), 1.0), box(vec(fold(getx(outerspherefold(pos,0.6)),0.1), // repeat sphere folded space fold(gety(outerspherefold(pos,0.6)),0.1), // repeat sphere folded space fold(getz(outerspherefold(pos,0.6)),0.1)), // repeat sphere folded space vec(0.5,0.02,0.02), vec(0,0,0))) }

Again, this looks like magnetic field lines, but this time the cuboids are wrapping around outside the inner sphere where the cuboids remain linear. There are many ways that these folds can be used when building up 3d fractals, and the mandelbox is a nice example of a fractal which relies on this type of spherical fold to build the fractal structure.

In case you’re struggling to see exactly what’s going on at the centre of these gridlines I’ll add a further detailed render of the centre of the inner sphere fold example where you can see the DE starting to breakdown.

So that’s it on the introduction to spherical folds. These functions are now supported in Wooscripter, so feel free to download the application and play around some more with these scripts. The full script in case you want to copy and paste is…

rule main { scale = vec(8,8,8) distanceiterations=1000 distanceminimum=0.001 stepsize=1 distancefunction(gridcuboids) diff = vec(0.6,0.4,0.2) refl = vec(0.6,0.6,0.6) spec = vec(0.3,0.3,0.3) gloss = 0.98 power = 15 distance } shader gridcuboids { distance = max(sphere(pos, vec(0,0,0), 1.0), box(vec(fold(getx(outerspherefold(pos,0.6)),0.1), fold(gety(outerspherefold(pos,0.6)),0.1), fold(getz(outerspherefold(pos,0.6)),0.1)), vec(0.5,0.02,0.02), vec(0,0,0))) }