The waving tentacles of the alien brain above were constructed in Pov-Ray using sphere_sweeps

and some trigonometry.

*Helix Algorithms*

Consider the code below which generates a helix:

and some trigonometry.

background { color White*0 } light_source { <10,100,-100> color White*1 } light_source { <10,100,100> color White*1 } global_settings { ambient_light <1,1,1>*1 } camera { location <0, 0, -100> look_at <0, 0, 2> } union{ #declare R = 5; #declare r = 1; #declare L = 5; #declare P = 2; sphere_sweep { b_spline 15 <0,0,0> r <R*cos(0),1*L,R*sin(0)>, r <R*cos(1*P),2*L,R*sin(1*P)>, r <R*cos(2*P),3*L,R*sin(2*P)>, r <R*cos(3*P),4*L,R*sin(3*P)>, r <R*cos(4*P),5*L,R*sin(4*P)>, r <R*cos(5*P),6*L,R*sin(5*P)>, r <R*cos(6*P),7*L,R*sin(6*P)>, r <R*cos(7*P),8*L,R*sin(7*P)>, r <R*cos(8*P),9*L,R*sin(8*P)>, r <R*cos(9*P),10*L,R*sin(9*P)>, r <R*cos(10*P),11*L,R*sin(10*P)>, r <R*cos(11*P),12*L,R*sin(11*P)>, r <R*cos(12*P),13*L,R*sin(12*P)>, r <R*cos(13*P),14*L,R*sin(13*P)>, r } translate <0,-30,0> pigment { rgbt <2,1,0,0> } finish { ambient 0.5 phong 0.7 phong_size 20 reflection { 0.0 } } } |

R = 5, P = 2

R = 5, P = 1

First a background colour, lights and camera are set-up as standard.

The helix is contained within the union. First 4 parameters are declared to enable changes to be

made easily:

R is the radius of the circle or helix;

r is the radius of the rod that is coiled to form the helix;

L is the length of the helix (the vertical or y-distance between each pair of points);

P is a phase multiplier, in other words how much we increment the parameter P between each pair

of points.

The sphere-sweep itself consists of a series of points <x,y,z> and an accompanying radius, r, through

which a mathematical curve (in this case a b_spline) is calculated, resulting in a smooth shape.

Finally we add a yellow-orange pigment (normally colours consist of a triple of RGB values, with each

value ranging from 0 to 1, however, giving values greater than 1 (here red = 2) makes the colours

appear luminous). Here we mix red and green to give a yellow colour. RGB colour charts can be used

if specific hues are required, though this also depends on the lighting, and with practise colour values

can be 'gestimated' quite closely. The finish adds a slightly shiny, slimy look which is good for many

living organisms.

This code is still a little clumsy, if we want a longer helix, then we need to add more points to our

sphere_sweep, but since we are using regular;y spaced points this can be done with a sinple while

loop:

The helix is contained within the union. First 4 parameters are declared to enable changes to be

made easily:

R is the radius of the circle or helix;

r is the radius of the rod that is coiled to form the helix;

L is the length of the helix (the vertical or y-distance between each pair of points);

P is a phase multiplier, in other words how much we increment the parameter P between each pair

of points.

The sphere-sweep itself consists of a series of points <x,y,z> and an accompanying radius, r, through

which a mathematical curve (in this case a b_spline) is calculated, resulting in a smooth shape.

Finally we add a yellow-orange pigment (normally colours consist of a triple of RGB values, with each

value ranging from 0 to 1, however, giving values greater than 1 (here red = 2) makes the colours

appear luminous). Here we mix red and green to give a yellow colour. RGB colour charts can be used

if specific hues are required, though this also depends on the lighting, and with practise colour values

can be 'gestimated' quite closely. The finish adds a slightly shiny, slimy look which is good for many

living organisms.

This code is still a little clumsy, if we want a longer helix, then we need to add more points to our

sphere_sweep, but since we are using regular;y spaced points this can be done with a sinple while

loop:

To generate a circle (using parametric equations) we

simply plot:

x = R*cos(P) and z = R*sin(P) and y = constant

It does not matter which coordinates (x,y,z) we use,

this simply alters the plane of the circle, which we can

do later by rotating, but here I chose x and z which

generates a horizontal circle at height y (we can set y

= 0 and so forget about it for now). P is a parameter

and we advance P for each point (x,z) that we plot. In

Pov-Ray sin and cos take an argument in radians, so

P = 2*pi (about 6.28) radians correspond to 360

degrees or a complete circle. All we do to get a helix,

is keep plotting the circle over multiples of 360

degrees whilst advancing the height y and we get a

vertical helix.

simply plot:

x = R*cos(P) and z = R*sin(P) and y = constant

It does not matter which coordinates (x,y,z) we use,

this simply alters the plane of the circle, which we can

do later by rotating, but here I chose x and z which

generates a horizontal circle at height y (we can set y

= 0 and so forget about it for now). P is a parameter

and we advance P for each point (x,z) that we plot. In

Pov-Ray sin and cos take an argument in radians, so

P = 2*pi (about 6.28) radians correspond to 360

degrees or a complete circle. All we do to get a helix,

is keep plotting the circle over multiples of 360

degrees whilst advancing the height y and we get a

vertical helix.

union{ #declare R = 5; #declare r = 1; #declare L = 5; #declare P = 2; #declare points = 20; #declare pt = 1; sphere_sweep{ b_spline points <0,0,0>, 1 #while(pt < points) <R*cos(pt*P), pt*L, R*sin(pt*P)>, r #declare pt = pt + 1; #end } translate <0,-50,0> pigment { rgbt <2,1,0,0> } finish { ambient 0.5 phong 0.7 phong_size 20 reflection { 0.0 } } } |

Note that Pov-Ray requires us to set the first point of our sphere-sweep explicitly (otherwise the

compiler fails to recognise what we are trying to do). It is also useful to make sure that the first point

of our helix is at the origin, (0,0,0), since this makes it easy to rotate it around the origin to get the

desired orientation before we translate it to our desired position (otherwise our rotations may move

the helix into positions that are hard to predict - it is usually easiest to rotate first and then translate).

The optional alpha-channel, specified by t in an rgbt colour, gives the object transparency, currently

I have set this to zero (no transparency, the default value) but transparency is often a feature of

living tissues and so adding a bit can give realistic effects.

A helix is fine for representing such things as spirochaete bacteria (one type of which causes syphilis

and drills into the body's tissues!) and flagella, but usually biological structures will not be exactly

helical, but be capable of additional movement and flexing - we are only part-way to making a

tentacle!

Next we will look at two main ways to get more natural shapes:

1. Superposition of sine waves;

2. Partial randomisation.

*Wave Equations and the Superposition of Waves*

The general equation for a sine wave in 1D is:

compiler fails to recognise what we are trying to do). It is also useful to make sure that the first point

of our helix is at the origin, (0,0,0), since this makes it easy to rotate it around the origin to get the

desired orientation before we translate it to our desired position (otherwise our rotations may move

the helix into positions that are hard to predict - it is usually easiest to rotate first and then translate).

The optional alpha-channel, specified by t in an rgbt colour, gives the object transparency, currently

I have set this to zero (no transparency, the default value) but transparency is often a feature of

living tissues and so adding a bit can give realistic effects.

A helix is fine for representing such things as spirochaete bacteria (one type of which causes syphilis

and drills into the body's tissues!) and flagella, but usually biological structures will not be exactly

helical, but be capable of additional movement and flexing - we are only part-way to making a

tentacle!

Next we will look at two main ways to get more natural shapes:

1. Superposition of sine waves;

2. Partial randomisation.

y(t) = A x sin(wt + p) |

Where, y is the height of the wave at each point (such as the displacement of water or of a guitar

string), w is the angular frequency, which determines how many oscillations occur in each interval of

the parameter t (t might be time, for say a buoy bobbing up and down on the water), p is the phase

(which specifies where the wave begins in its cycle at t = 0, if we wish to start level with the surface of

calm water then p = 0) and A is the amplitude (maximum height/depth of the wave above/below the

surface of calm water).

This would only give us a simple wave, like those we have already used, however, real waves consist

of a number (possibly infinite) of sine waves added together. By the Principle of Superposition

adding two or more waves together generates another wave. (See waves for more details of the

physics).

Let's see what happens in practice. I have changed the code for the union as shown below:

string), w is the angular frequency, which determines how many oscillations occur in each interval of

the parameter t (t might be time, for say a buoy bobbing up and down on the water), p is the phase

(which specifies where the wave begins in its cycle at t = 0, if we wish to start level with the surface of

calm water then p = 0) and A is the amplitude (maximum height/depth of the wave above/below the

surface of calm water).

This would only give us a simple wave, like those we have already used, however, real waves consist

of a number (possibly infinite) of sine waves added together. By the Principle of Superposition

adding two or more waves together generates another wave. (See waves for more details of the

physics).

Let's see what happens in practice. I have changed the code for the union as shown below:

union{ #declare R = 5; #declare r = 1; #declare L = 10; #declare P = 1; #declare points = 14; #declare pt = 0; sphere_sweep{ b_spline points+1 <0,0,0>, 1 #while(pt < points) <R*cos(pt*P)+5*R*cos(pt*P*0.1), pt*L, R*sin(pt*P)+5*R*sin(pt*P*0.1)>, r #declare r = r + 0.2; #declare pt = pt + 1; #end } translate <0,-60,0> pigment { rgbt <2,1,0,0> } finish { ambient 0.5 phong 0.7 phong_size 20 reflection { 0.0 } } } |

There are an infinity of possibilities, but here I added the sine wave:

5*R*sin(pt*P*0.1)

to the z-coordinate and a corresponding cos wave to the x-coordinate.

(Remember that the only difference between sine and cosine is the phase:

cos(t) = sin(t + P) where P = pi/2 radians (90 degrees)). Adding two or more

waves together gives an apparently irregular waveform (though it does

repeat at intervals if we repeat the pattern far enough).

I have also increased r slightly for each point through the sweep, giving a

tapering tentacle.

[Finally, I took a few points off the end (setting points = 14) but then I added

one point to the start (setting pt = 0 initially) to get the desired look,

resulting in a total of 15 points (points + 1) in the sphere-sweep.]

Now we have something which looks much more like a tentacle!

5*R*sin(pt*P*0.1)

to the z-coordinate and a corresponding cos wave to the x-coordinate.

(Remember that the only difference between sine and cosine is the phase:

cos(t) = sin(t + P) where P = pi/2 radians (90 degrees)). Adding two or more

waves together gives an apparently irregular waveform (though it does

repeat at intervals if we repeat the pattern far enough).

I have also increased r slightly for each point through the sweep, giving a

tapering tentacle.

[Finally, I took a few points off the end (setting points = 14) but then I added

one point to the start (setting pt = 0 initially) to get the desired look,

resulting in a total of 15 points (points + 1) in the sphere-sweep.]

Now we have something which looks much more like a tentacle!

Note: we can create a travelling wave to animate the tentacles (as in the alien brain at the top) by

incrementing the phase of one of the sine waves in each frame. Below is a simple animated GIF of 6

frames, where the phase of the smaller sine/cosine wave (the one we started with) by adding one each

time, e.g. the last frame was given by:

<R*cos(pt*P+5)+5*R*cos(pt*P*0.1), pt*L, R*sin(pt*P+5)+5*R*sin(pt*P*0.1)>, r

incrementing the phase of one of the sine waves in each frame. Below is a simple animated GIF of 6

frames, where the phase of the smaller sine/cosine wave (the one we started with) by adding one each

time, e.g. the last frame was given by:

<R*cos(pt*P+5)+5*R*cos(pt*P*0.1), pt*L, R*sin(pt*P+5)+5*R*sin(pt*P*0.1)>, r

Note: the tentacle is off to one side because the first and last points of the sphere-sweep are not visible

(they are control points used to construct the b_spline curve) and so the first visible point is actually

<1,10,0> as cos(0) = 1, sin(0) = 0. (You can set the second point explicitly to <0,0,0> or translate <-1,0,0>

to move the tentacle back to the origin. [UnFREEz 2.1 has been used to create the animated GIFs and is

free software available online]. Note the 'kink; in the tail. This is neither an error nor is it necessary, it is due

to the first point of the sphere-sweep, <0,0,0>, set manually and is included to show you that you can

specify or randomise as many of the points in the sphere-sweep as you wish. Manually determined points

can be added to both ends if required, or the whole can be generated by the trig functions, to give an exact

sine wave.

*Adding Randomisation*

Randomisation can be a good tool to help with generating natural shapes.

(they are control points used to construct the b_spline curve) and so the first visible point is actually

<1,10,0> as cos(0) = 1, sin(0) = 0. (You can set the second point explicitly to <0,0,0> or translate <-1,0,0>

to move the tentacle back to the origin. [UnFREEz 2.1 has been used to create the animated GIFs and is

free software available online]. Note the 'kink; in the tail. This is neither an error nor is it necessary, it is due

to the first point of the sphere-sweep, <0,0,0>, set manually and is included to show you that you can

specify or randomise as many of the points in the sphere-sweep as you wish. Manually determined points

can be added to both ends if required, or the whole can be generated by the trig functions, to give an exact

sine wave.

This is a model of a bootlace worm, the longest of which are the

longest known animals on Earth (up to 30 to 60 metres in length)!

They have a habit of coiling themselves into knots and springs -

shapes that are clearly based on sine waves, but with a great deal

of variability thrown in. The main part of this worm's body was

modeled using the wave equation:

<amp1*sin(pt*freq1)+pt/2+RV1+RV5*sin(pt*0.5),

amp2*cos(RV4*freq2)+ptl/2+RV1+RV5*cos(pt*0.5), amp3*sin(pt*freq3)+pt/2+RV1>, rad

with:

#declare RV0 = RRand(1,2,1);

#declare RV4 = RRand(-10,10,1);

#declare RV5 = RRand(5,20,1);

#declare amp1 = RRand(5,15,0);

#declare amp3 = RRand(5,15,0);

Where the function RRand generates a random number between

the first two values specified in brackets and using the third

number as a random seed (changing the third number changes

the sequence of random numbers generated). New random

numbers being generated for each point (pt) plotted.

longest known animals on Earth (up to 30 to 60 metres in length)!

They have a habit of coiling themselves into knots and springs -

shapes that are clearly based on sine waves, but with a great deal

of variability thrown in. The main part of this worm's body was

modeled using the wave equation:

<amp1*sin(pt*freq1)+pt/2+RV1+RV5*sin(pt*0.5),

amp2*cos(RV4*freq2)+ptl/2+RV1+RV5*cos(pt*0.5), amp3*sin(pt*freq3)+pt/2+RV1>, rad

with:

#declare RV0 = RRand(1,2,1);

#declare RV4 = RRand(-10,10,1);

#declare RV5 = RRand(5,20,1);

#declare amp1 = RRand(5,15,0);

#declare amp3 = RRand(5,15,0);

Where the function RRand generates a random number between

the first two values specified in brackets and using the third

number as a random seed (changing the third number changes

the sequence of random numbers generated). New random

numbers being generated for each point (pt) plotted.

Helices have been used to generate the flagella of this swimming

bacterial cell (see bacteria). Adding some randomisation is useful

when the flagella fly apart as the cell tumbles to change its

direction at random.

bacterial cell (see bacteria). Adding some randomisation is useful

when the flagella fly apart as the cell tumbles to change its

direction at random.

Sphere_sweeps are also good for generating worm-like

(vermiform) shapes, as in this acorn worm.

(vermiform) shapes, as in this acorn worm.