Styrofoam IFS - .ifs files

IFS is short for Iterated Function System.
An IFS-fractal contains several functions which takes a point in space as parameter and returns another point in space based. These functions are called transforms.
StyrofoamIFS uses the chaos game algorithm with these transforms to construct a point-cloud that is then raytraced in the next stage. Points in space are represented by spheres which have radius, color and reflection.
Commands in a transform is executed in serie, their order may matter.
To create a new fractal you need to create a new .ifs file. Either copy an old one, or create a new from scratch in your text editor.

Words in italics can either be numerical values, variables or mathematical functions.
The | sign is used to delimit different identifiers.
Example: x|y|z means that you can put either a 'x', an 'y' or a 'z' in that spot.
Anywhere where you can write a value, a mathematical formula will work as well.
Example: let p,cos(pi*anim/36)
Any time '//' is found on a row the rest of the row will be discarded as a comment.
Multiline-comments starts with '/*' and ends with '*/'.

See 2d variations for 2d-variants of variations.

Supported commands

Commands for transforms

xform [name][,name2,...]

The first row of a transform. The following commands only apply to this until the next transform.
A name can be given to a transform if it needs to be referenced later on.
Names don't need to be unique and will form a group of transforms.
If you give several names, several transforms will be created in parallell (see prefixing later for use of this).

Example: xform 0

newmap [name][,name2,...]

Same as xform.

Example: newmap 0

final

The first row of the final transform.
This is a special transform that there can only be one of.
After a normal transform has been calculated (xform or newmap), the final transform is always applied before storing the position.
The next transform will be using the position from before the final transform.

Example:
//Inverted fractal
final
power -1

tag name[,name2,...]

Gives the transform one or more names. Transforms can have several names.

Example: tag grp_a

ifs

Stop applying commands to the current transform and hereafter apply commands to all previous transforms.

Example: ifs

translate a,b,c[,d]

Moves the point in space a given distance.
x,y and z are translated with the values a,b and c.
x=x+a, y=y+b, z=z+c, and if d is present, w=w+d

Example: translate 0,0,-0.5

scale a,b,c[,d]

x,y and z are scaled with the given values.
x=x*a, y=y*b, z=z*c, and if d is present, w=w*d

Example: scale 0.5,0.5,0.5

scale a

Shortcut for scale a,a,a

Example: scale 0.5

rotate x|y|z,angle

Rotate angle degrees around the axis given by the first parameter
Note that this angle is in degrees, not radians!

Example: rotate x,45

rotate xaxis,yaxis,zaxis,angle

Rotate angle degrees around the axis given by the vector xaxis,yaxis,zaxis
Note that this angle is in degrees, not radians!

Example: rotate 1,1,0,45

power p

Applies the geometric power.
Calculate angle and radius, and do radius ^ p

Example: power -1

sinusoidal

Based on the sinusoidal transform in Apophysis
x=sin(x), y=sin(y), z=sin(z)

Example: sinusoidal

asinusoidal

x=asin(clamp(x,-1,1)), y=asin(clamp(y,-1,1)), z=asin(clamp(z,-1,1))

Example: asinusoidal

spherical

Based on the spherical transform in Apophysis
r=sqrt(x2+y2+z2)
x=x/r, y=y/r, z=z/r

Example: spherical

swirl

Based on the swirl transform in Apophysis
r=sqrt(x2+y2+z2)
x=x*sin(r2)-y*cos(r2), y=x*cos(r2)+y*sin(r2), z=x*cos(r2)-z*sin(r2)

Example: swirl

horseshoe

Based on the horseshoe transform in Apophysis
r=sqrt(x2+y2+z2)
x=(x-y)*(x+y)/r, y=2*x*y/r, z=(x-z)*(x+z)/r

Example: horseshoe

polar

Based on the polar transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=θ/π, y=r-1, z=θ2

Example: polar

handkerchief

Based on the handkerchief transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=r*sin(θ+r), y=r*cos(θ-r), z=r*sin(θ2+r)

Example: handkerchief

heart

Based on the heart transform in Apophysis
r=sqrt(x2+y2+z2)
r1=sqrt(x2+y2)
r2=sqrt(x2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=r*sin(θ*r1), y=-r*cos(θ*r1), z=-r*cos(θ2*r2)

Example: heart

disc

Based on the disc transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=θ/π*sin(π*r), y=θ/π*cos(π*r), z=θ2/π*cos(π*r)

Example: disc

spiral

Based on the spiral transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=(cos(θ)+sin(r))/r, y=(sin(θ)-cos(r))/r, z=(cos(θ2)+sin(r))/r

Example: spiral

hyperbolic

Based on the hyperbolic transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=sin(θ)/r, y=r*cos(θ), z=sin(θ2)/r

Example: hyperbolic

diamond

Based on the diamond transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=sin(θ)*cos(r), y=cos(θ)*sin(r), z=sin(θ2)*cos(r)

Example: diamond

ex

Based on the ex transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
p0=sin(θ+r)
p1=cos(θ-r)
p2=sin(θ2+r)
p3=cos(θ2-r)
x=r*(p03+p13), y=r*(p03-p13), z=r*(p23-p33)

Example: ex

julia

Based on the julia transform in Apophysis
r=sqrt(x2+y2+z2)
θ=atan(y/x)
θ2=atan(z/x)
x=sqrt(r)*cos(θ/2), y=sqrt(r)*sin(θ/2), z=sqrt(r)*sin(θ2/2)

Example: julia

bent

Based on the bent transform in Apophysis
x=x, y=y, z=z, x≥0, y≥0
x=2*x, y=y, z=2*z, x<0, y≥0
x=x, y=y/2, z=z/2, x≥0, y<0
x=2*x, y=y/2, z=z, x<0, y<0

Example: bent

wave b,c

Based on the wave transform in Apophysis
x=x+b*sin(y/c2), y=y+b*sin(x/c2), z=z+b*sin(z/c2)

Example: wave 0.5,2

fisheye

Based on the fisheye transform in Apophysis
r=sqrt(x2+y2+z2)
x=2*y/(r+1), y=2*x/(r+1), z=2*z/(r+1)

Example: fisheye

popcorn h

Based on the popcorn transform in Apophysis
x = x - h*sin(y + tan(3*y))
y = y - h*sin(z + tan(3*z))
z = z - h*sin(x + tan(3*x))

Example: popcorn 0.1

exponential

Based on the exponential transform in Apophysis
x=ex-1*cos(π*y), y=ex-1*sin(π*y), z=ex-1*sin(π*z)

Example: exponential

cosine

Based on the cosine transform in Apophysis
x=cos(π*x)*cosh(y), y=-sin(π*x)*sinh(y), z=sin(x)

Example: cosine

foci

x=( 0.5*ex-2*e-x ) / ( 0.5*ex+2*e-x - cos(y)*cos(z))
y=sin(y) / ( 0.5*ex+2*e-x - cos(y)*cos(z))
z=sin(z) / ( 0.5*ex+2*e-x - cos(y)*cos(z))

Example: foci

gnarl s,a,b,c,d

repeat the following 16 times:

x' = x - s*sin(z + a*sin(b*z + c*y + d*x))
y' = y - s*sin(x + a*sin(b*x + c*z + d*y))
z' = z - s*sin(y + a*sin(b*y + c*x + d*z))
x = x', y = y', z = z'

Example: gnarl 0.05,3,2,0.2,0

linear a,b,c,d,e,f

x = x * a + d
y = y * b + e
z = z * c + f

Example: linear 0,0,0, 1,1,1

julian power,dist

Based on the juliaN transform in Apophysis
θ=atan(y/x)
θ2=atan(z/x)
r=sqrt(x2+y2+z2)
rnd=random number in [0,1]
x = rdist/power * cos(θ + 2 * π * trunc(abs(power) * rnd))
y = rdist/power * sin(θ + 2 * π * trunc(abs(power) * rnd))
z = rdist/power * sin(θ2 + 2 * π * trunc(abs(power) * rnd))

Example: julian 2,-1

blur

Based on the blur transform in Apophysis
rnd=random number in [0,1]
rnd2=random number in [0,1]
rnd3=random number in [0,1]
x = rnd * cos(2 * π * rnd2)
y = rnd * sin(2 * π * rnd2)
z = rnd * sin(2 * π * rnd3)

Example: blur

preblur

Based on the pre_blur transform in Apophysis

The following values are stored between calls:

gauss_rnd0=random number in [0,1]
gauss_rnd1=random number in [0,1]
gauss_rnd2=random number in [0,1]
gauss_rnd3=random number in [0,1]
gauss_rnd4=random number in [0,1]
gauss_rnd5=random number in [0,1]
gauss_N=0
r=gauss_rnd0+gauss_rnd1+gauss_rnd2+gauss_rnd3+gauss_rnd4+gauss_rnd5 - 3
rnd=random number in [0,1]
rnd2=random number in [0,1]
x = r * sin(rnd * π) * cos(rnd2 * 2 * π)
y = r * sin(rnd * π) * sin(rnd2 * 2 * π)
z = r * cos(rnd * π)

Recalculate one stored value each call:
gauss_rndgauss_N=random number in [0,1]
gauss_N=gauss_N modulo 6

Example: preblur

splits a,b,c

Based on the splits transform in Apophysis
x = (x >= 0) ? x + a : x - a
y = (y >= 0) ? y + b : y - b
z = (z >= 0) ? z + c : z - c

Example: splits 0,0,0

elliptic

Based on the elliptic transform in Apophysis
TODO

Example: elliptic

cube a,b,c

rnda=random number in [0,1], rndb=random number in [0,1], rndc=random number in [0,1]
x = x + a * (rnda - 0.5)
y = y + b * (rndb - 0.5)
z = z + c * (rndc - 0.5)

Example: cube 0.5,0.5,0.5

center

Stores the current position and moves the point to origo (0,0,0)
xstore=x, ystore=y, zstore=z
x=0, y=0, z=0

Example: center

decenter

Adds the position last stored with center
x=x+xstore, y=y+ystore, z=z+zstore

Example: decenter

matrix_mul a,b,c,p,q,r,u,v,w

Multiply x with the matrix abc
ypqr
zuvw

sphere_radius r

Sets the radius of the resulting point
Note that this applies to all radiuses from here onward, also from other transforms

Example: sphere_radius 0.1

sphere_radius_factor f

Deprecated!
Use sphere_radius base_sphere_radius*value instead.

Example: replace sphere_radius_factor 0.5 with sphere_radius base_sphere_radius*0.5

sphere_grow r

The resulting point will have its volume grown by r every time instead
Note that the number of iterations will influence the outcome.

Example: sphere_grow 0.0002

reflection r

The resulting point will have a reflectivness of r.
0=no reflection, 1=full reflection
See properties for more info.

Example: reflection 0.5

color

The resulting point will have a its color taken from the palette at it's current position.
See properties for more info.

Example: color

color a,b

The resulting point will have a its color taken from the palette at position a,b.
See properties for more info.

Example: color 0,1

color r,g,b

The resulting point will get the color r,g,b.
See properties for more info.

Example: color 0.7,0.7,0.7

weight a

Sets the probability factor that this transform will get picked in the chaos game.
Default weight is 1.
This command is not supported inside path conditions.

Example: weight 0.07

xaos name[,name2,...]

List the names of the transforms that can be reached from this transform.
Note that several transforms can have the same name and they will all be available.
If xaos is not used, all transforms can be reached.
This command is not supported inside path conditions.

Example: xaos grp_a,grp_b

path name[,name2,...]
...
[else]
...
end

Conditionally executes commands depending on the which transforms where executed previously.
Similar to if/then/else in common programming languages but applies to the path taken by the chaos game.
If any conditions don't apply, the commands after the path command won't be executed, up until the next else/end command.
Every path must have a closing end command, the else is optional.
The first position refers to the currently executed transform, the condition is met if it has one of the tags listed.
The next position refers to the previously executed transform, if it had one of the tags listed the condition is met.
The position after that refers to the transform executed two transforms ago, and so on.
Leaving a position empty means that any transform could have been executed.
Name can refer to any xform name or tag, if multiple tags should be allowed write [tag1,tag2,...].
To allow different paths on the same line, write path (name,name2)(name3,name4)
Weight and xaos commands are currently not supported inside path conditions.

Example:
path ,,grp_a,[grp_a,grp_b]
//commands here will only be executed if the transform executed two transforms ago had a grp_a tag
//and if the transform executed before that had either a grp_a or a grp_b tag
end

sum [w1,w2,...]
...
endsum

Calculates a weighted sum of commands instead of applying them in serially.
This is based on the flame formula that Apophysis is using except the concepts of post-transform and final transform is not applicable.
w1 is the weight of the first term, w2 the weight of the second and so on. All weights are set to 1 if w1 is left out.
If there are more commands than weights, the last weight will be used for the remaining commands.

Example:
sum 1,0.1
polar
preblur
endsum

flame [w1,w2,...]
...
endflame

Same as sum/endsum.

Example:
flame 1,0.1
polar
preblur
endflame

stack
...
endstack

Doesn't execute the commands between stack and endstack but instead adds them to a stack.
Use runstack to run the commands in the stack or clearstack to clear the stack.

Example:
stack
rotate x,5
endstack

runstack

Runs all the commands in the current stack.
Use stack ... endstack to add comands to the stack.

Example: runstack

clearstack

Clears all the commands in the current stack.

Example: clearstack

model filename,scale

Moves the x,y,z position to a random point in a 3d object given by a .ply file.
Use scale to scale the object.

Example: model c:\temp\bun_zipper_res4.ply, 5

Commands not applying to a specific transform but to the whole fractal

let name,value

Defines a variable that can be used in calculations later.

Example: let angle,45

color00 r,g,b

Sets the color of the 0,0 position in the palette.
See properties for more info.

Example: color00 1,1,0.5

color01 r,g,b

Sets the color of the 0,1 position in the palette.
See properties for more info.

Example: color01 1,0,0.5

color10 r,g,b

Sets the color of the 1,0 position in the palette.
See properties for more info.

Example: color10 0,1,0.5

color11 r,g,b

Sets the color of the 1,1 position in the palette.
See properties for more info.

Example: color11 0,0,0.5

color_png filepath

Uses the color on an image as palette
Only png format is supported. See properties for more info.

Example: color_png D:\StyrofoamIFS\background\palette.png

draw n

Transforms with draw 0 will not make a point in the point-cloud.
Note! Changed name from drawsphere.

Example: draw 0

post_filter x|y|z|w,min,max

Only points on the given axis between min and max will make it to the point cloud.

Example: post_filter z,0,99

post_filter plane,normalx,normaly,normalz[,normalw],min,max

Only points at a distance between min and max from the plane given by normalx,normaly,normalz and optionally normalw will make it to the point cloud.

Example: post_filter plane,1,1,1,-99,0

post_filter radius3d[,centerx,centery,centerz],min,max

Only points at a radius between min and max from origo (or from a point at centerx,centery,centerz) will make it to the point cloud.

Example: post_filter radius3d,0.5,1

post_filter radius4d[,centerx,centery,centerz,centerw],min,max

Only points at a radius between min and max from origo (or from a point at centerx,centery,centerz,centerw) will make it to the point cloud.

Example: post_filter radius4d,0.5,1

print v

Print a variable to output. Used for debugging.

Example: print pi

Prefixing

Prefixing rows with [name,name2,...] makes only transforms with the names inside the brackets get the command. This is useful when defining several transforms at the same time. Prefixing only works for commands that apply to the current transform.

Example:

xform a,b,c //create three transforms, one named "a", one named "b", one named "c"
scale 0.5 //all three transforms will get this line
[a]transform 0.5,0.5,0 //only transform a will get this line
[b,c]transform 0.5,-0.5,0 //only transforms b and c will get this line

Predefined variables

pi 3.14159265358979323846
e 2.71828182845904523536
anim The current frame

All parameters in the .scene file is automatically imported as variables.

Supported mathematical functions

Most of these functions are the same as their standard C/C++ counterpart and left without comment.

sin(a)
cos(a)
tan(a)
sinh(a)
cosh(a)
tanh(a)
asin(a)
acos(a)
atan(a)
asinh(a)
acosh(a)
atanh(a)
sqrt(a)
log(a)
log2(a)
log10(a)
abs(a)
ceil(a)
floor(a)
rad(a) Convert a degrees to radians
deg(a) Convert a radians to degrees
step(a) Returns 1 if a >=0, else 0
rnd(a) Random value between 0 and a
pow(a,b)
max(a,b)
min(a,b)
atan2(a,b)
fmod(a,b) Modulo
remainder(a,b)
step(a,b) Returns 1 if a >=0 and b < 0, else 0
clamp(a,b,c) Clamps a between b (min) and c (max)