News: Visit UltraFractalWiki for hints & tutorials on UltraFractal5
 
*
Welcome, Guest. Please login or register. August 21, 2014, 02:22:58 AM


Login with username, password and session length



Pages: 1 ... 7 8 [9] 10   Go Down
  Print  
Share this topic on DiggShare this topic on FacebookShare this topic on GoogleShare this topic on RedditShare this topic on StumbleUponShare this topic on Twitter
Author Topic: Kaleidoscopic (escape time) IFS  (Read 33776 times)
Description: An interresing class of fractals
0 Members and 1 Guest are viewing this topic.
knighty
Fractal Bachius
*
Posts: 564


« Reply #120 on: May 25, 2010, 10:24:00 PM »

It's just a simplification of the one fold family. Nothing new. I've implemented it and it works.  smiley
Short answer:
The algorithm I already used was something like this (in vectorial form):
Code:
// v is the input point
i=0;
r=dot(v,v);
while (i<max_iterations && r<bailout_squared) do{
      rotate1(v);
      fold(v);
      rotate2(v);
      v=scale*v-(scale-1)*offset;
      r=dot(v,v);
      i=i+1;
}
distance=sqrt(r)/scale^i;
the first rotation have the side effect of rotating the whole fractal. so we can place it after the scaling but the fractal will not rotate anymore, which is a good thing grin.
As Syntopia has noticed, a fold by an arbitrary plane is equivalent to an abs() operation in a different coordinates frame.
So we can do (+ some algebraic manipulations):

Code:
// v is the input point
i=0;
r=dot(v,v);
while (i<max_iterations && r<bailout_squared) do{
     
      v.z=abs(v.z);//for example
      rotate2(v);//rotation
      v=v-offset*(scale-1)/scale;//translation, ((scale-1)/scale) is here just in order to keep the size of the fractal "constant" while changing the scale.
      v=scale*v;//scale
      rotate1(v);//rotation
      r=dot(v,v);
      i=i+1;
}
distance=sqrt(r)/scale^i;
As you know, using homogeneous coordinates make it possible to express translation operation as a matrix. thus, the transformation in the above code can be written:
v=(v.x,v.y,abs(v.z));
v=R1*S*T*R2*v=A*v;

Of course, it's possible to apply the abs() operation to x or y or z or x and y...etc.

(See also this post)
Logged
Syntopia
Fractal Bachius
*
Posts: 585



syntopiadk
WWW
« Reply #121 on: May 25, 2010, 11:18:49 PM »

As Syntopia has noticed, a fold by an arbitrary plane is equivalent to an abs() operation in a different coordinates frame.

Actually I tried, and couldn't get it to work.

What I wanted to do was to take the following (where n1,n2,n3 are not perpendicular):

Code:
if (dot(p, n1)>0.0) { p *= n1Mat; }
 if (dot(p, n2)>0.0) { p *= n2Mat; }
 if (dot(p, n3)>0.0) { p *= n3Mat; }
 (repeated the necessary number of times)

And optimize it by using a coordinate system where n1,n2,n3 are axis-aligned:

Code:
// The columns of the (skewed) transformation-matrix M should be the normals: n1,n2,n3
 p = M*abs(M_inverse*p);

But it did not work. Suggestions are welcome :-)

« Last Edit: May 25, 2010, 11:20:55 PM by Syntopia, Reason: Formatting » Logged
David Makin
Global Moderator
Fractal Senior
******
Posts: 2258



Makin' Magic Fractals
WWW
« Reply #122 on: May 25, 2010, 11:24:08 PM »


As you know, using homogeneous coordinates make it possible to express translation operation as a matrix. thus, the transformation in the above code can be written:
v=(v.x,v.y,abs(v.z));
v=R1*S*T*R2*v=A*v;

Of course, it's possible to apply the abs() operation to x or y or z or x and y...etc.

(See also this post)

So basically the single fold version is a single transform standard escape-time IFS with the addition of one or more abs() operators ?

And the multi-fold version is essentially standard escape-time LRIFS but again with the addition of abs() operators and restriction based on dot products ? (Language Restricted IFS, see http://www.fractalforums.com/programming/escape-time-lrifs/)
« Last Edit: May 25, 2010, 11:37:33 PM by David Makin » Logged

The meaning and purpose of life is to give life purpose and meaning.

http://www.fractalgallery.co.uk/
"Makin' Magic Music" on Jango
knighty
Fractal Bachius
*
Posts: 564


« Reply #123 on: May 26, 2010, 10:39:27 PM »

Well, I don't know sad. I'll try to dig the subject smiley.

As Syntopia has noticed, a fold by an arbitrary plane is equivalent to an abs() operation in a different coordinates frame.

Actually I tried, and couldn't get it to work.

What I wanted to do was to take the following (where n1,n2,n3 are not perpendicular):

Code:
if (dot(p, n1)>0.0) { p *= n1Mat; }
 if (dot(p, n2)>0.0) { p *= n2Mat; }
 if (dot(p, n3)>0.0) { p *= n3Mat; }
 (repeated the necessary number of times)

And optimize it by using a coordinate system where n1,n2,n3 are axis-aligned:

Code:
// The columns of the (skewed) transformation-matrix M should be the normals: n1,n2,n3
 p = M*abs(M_inverse*p);

But it did not work. Suggestions are welcome :-)
It works that way only if M is a combination of a rotation (+ eventually a symmetry) and a translation. This imply that the three planes have to be orthogonal to each other.
For a sigle fold it always works. That's what I was talking about.smiley

___________________________________________
Here is another version of the menger Sponge (that makes it a true "Kaleidoscopic IFS"):
Code:
Menger3(x,y,z){
   r=x*x+y*y+z*z;
   for(i=0;i<MI && r<bailout;i++){
      rotate1(x,y,z);

      x=abs(x);y=abs(y);z=abs(z);
      if(x-y<0){x1=y;y=x;x=x1;}
      if(x-z<0){x1=z;z=x;x=x1;}
      if(y-z<0){y1=z;z=y;y=y1;}
     
      z-=0.5*CZ*(scale-1)/scale;
      z=-abs(-z);
      z+=0.5*CZ*(scale-1)/scale;

      rotate2(x,y,z);
   
      x=scale*x-CX*(scale-1);
      y=scale*y-CY*(scale-1);
      z=scale*z;
     
      r=x*x+y*y+z*z;
   }
   return sqrt(x*x+y*y+z*z)*scale^(-i);
}
Logged
Softology
Safarist
******
Posts: 84


« Reply #124 on: May 28, 2010, 06:10:38 AM »

It's just a simplification of the one fold family. Nothing new. I've implemented it and it works.  smiley

OK, so the variations now come down to;

option to pre-rotate before main loop
for i=1 to maxiterations
    rotate1 (if not already set as a pre-rotate)
    fold (whichever fold method - tetra/cubic/icosa etc)
    rotate2
    stretch
    if radius>bailout then break
end

The rotatations can either be around the origin or around the stretch center.  I originally had the rotations around the strech center which was incorrect but it leads to other unique images so I left it in as an option.

Also for the stretching, it can be the usual
     z.x=scale*z.x-kcx*(scale-1)
     z.y=scale*z.y-kcy*(scale-1)
     z.z=scale*z.z-kcz*(scale-1)
kcx/y/z the center of stretch.  This can either be constrained to the unit sphere (normalised) or used as is.  I have an option for both.
Including the option to alternate the z stretch with
     z.z=scale*z.z
     if (z.z>0.5*kcz*(scale-1)) then z.z:=z.z-kcz*(scale-1)
also gives another method for new fractals

Does that cover all the variations so far?

Here are another 2 sample movies.  Both are created by only morphing/tweening the rotate1 and rotate2 values between frames.  Both really need to be watched in the full HD resolution to see the finer fractal details.

<a href="http://www.youtube.com/v/eJI0PW6EQhI&rel=1&fs=1&hd=1" target="_blank">http://www.youtube.com/v/eJI0PW6EQhI&rel=1&fs=1&hd=1</a>

<a href="http://www.youtube.com/v/renxaQZfsdk&rel=1&fs=1&hd=1" target="_blank">http://www.youtube.com/v/renxaQZfsdk&rel=1&fs=1&hd=1</a>

Jason.
« Last Edit: May 28, 2010, 07:53:08 AM by Softology » Logged
Syntopia
Fractal Bachius
*
Posts: 585



syntopiadk
WWW
« Reply #125 on: May 28, 2010, 12:24:31 PM »

As you know, using homogeneous coordinates make it possible to express translation operation as a matrix. thus, the transformation in the above code can be written:
v=(v.x,v.y,abs(v.z));
v=R1*S*T*R2*v=A*v;

Btw, I tried out using homogeneous coordinates (Pixel Bender supports 4-component matrices and vectors):

Code:
// Prefolds.
p = abs(p);
t=dot(p,n1); if (t>0.0) { p-=2.0*t*n1; }
t=dot(p,n2); if (t>0.0) { p-=2.0*t*n2; }
 
while (n < maxIterations) {
   // folds
   p = abs(p);           
   t=dot(p,n1); if (t>0.0) { p-=2.0*t*n1; }
   t=dot(p,n2); if (t>0.0) { p-=2.0*t*n2; }
   
   // rotate1,scale,rotate2
   p4.xyz = p; p4.w = 1.0;
   p = (M*p4).xyz;
   
   n++;         
}

Where M is precalculated once-per-frame as:

Code:
M = toMatrix4(rotationMatrix2) * translate(offset) * scale4x4(scale) * translate(-offset) * toMatrix4(rotationMatrix1);

The framerate went from 13.9 to 17.2 fps, or ~23% faster, so it might be worth implementing (at least on a GPU).

However in order to combine the matrix, you'll have to move the first rotation below the folds, and I think you restrict the variety of shapes this way. I could imagine the rotation matrices becoming more dependent this way.
Logged
knighty
Fractal Bachius
*
Posts: 564


« Reply #126 on: May 28, 2010, 10:05:00 PM »

It's just a simplification of the one fold family. Nothing new. I've implemented it and it works.  smiley
OK, so the variations now come down to;

option to pre-rotate before main loop
for i=1 to maxiterations
    rotate1 (if not already set as a pre-rotate)
    fold (whichever fold method - tetra/cubic/icosa etc)
    rotate2
    stretch
    if radius>bailout then break
end
I would say it comes down to:
Code:
for i=1 to maxiterations
    fold (whichever fold planes set)
    Multiply by An affine (or projective?) transform matrix. (in general a composition of translations, rotations and uniform scaling. You can obtain interresting results with other types of transformation but the Distance estimation must be adapted in this case)
    if radius>bailout then break
end
This formulation is good on the side of the computer because it's simple, general and fast. On the side of the user that's perhaps not the best representation.

The rotatations can either be around the origin or around the stretch center.  I originally had the rotations around the strech center which was incorrect but it leads to other unique images so I left it in as an option.
That was not incorrect just different smiley. In fact you can use any center for the rotations.

Does that cover all the variations so far?
Honestly, I don't know. The case of the menger sponge makes me think that there is an ingredient that is missing in the above "general" algorithm.

Nice videos. Thanks for sharing. I like particulary the second: it look like a boiling cloud smiley

However in order to combine the matrix, you'll have to move the first rotation below the folds, and I think you restrict the variety of shapes this way. I could imagine the rotation matrices becoming more dependent this way.
I don't think so. The only difference I could see is an overall rotation.

GPUs are optimized for matrix-vector operations. It seem that they are very well optimized w00t !!. Have you tried the alternate formulation with rotations and abs() (without branchings)? Is it faster this way?
Logged
Syntopia
Fractal Bachius
*
Posts: 585



syntopiadk
WWW
« Reply #127 on: May 29, 2010, 12:17:58 AM »

However in order to combine the matrix, you'll have to move the first rotation below the folds, and I think you restrict the variety of shapes this way. I could imagine the rotation matrices becoming more dependent this way.
I don't think so. The only difference I could see is an overall rotation.

I get different results? For instance, for the icosa, if I rotate 180 degrees around the x-axis before the folds, the icosa is unaffected. If I do the same rotation after the folds, but before the scaling, it completely disappears (which seems fair because we rotate away from the scaling center). Also, for the icosa I get no overall rotation from the first rotation - it happens for the dodeca, though.

GPUs are optimized for matrix-vector operations. It seem that they are very well optimized w00t !!. Have you tried the alternate formulation with rotations and abs() (without branchings)? Is it faster this way?

Not yet, but the conditional reflections are expensive. If I omit them (and get a very crippled icosa) I get around 40 fps.
Logged
Nahee_Enterprises
World Renowned
Fractal Senior
******
Posts: 2251


use email to contact


nahee_enterprises Nahee.Enterprises NaheeEnterprise
WWW
« Reply #128 on: May 29, 2010, 03:43:42 AM »

    Here are another 2 sample movies.  Both are created by only
    morphing/tweening the rotate1 and rotate2 values between frames.  Both really need to be watched in the full HD resolution to see the finer fractal details.

Really enjoyed seeing the various shapes possible in the first one of these two videos.    smiley
 
Logged

kram1032
Fractal Senior
******
Posts: 1550


« Reply #129 on: May 29, 2010, 09:57:29 AM »

Softology: Those animations where great cheesy
Both of them varried in brightness for just a second. Was that due to the surface or was it a bug?
Logged
Softology
Safarist
******
Posts: 84


« Reply #130 on: May 29, 2010, 12:21:50 PM »

Softology: Those animations where great cheesy
Both of them varried in brightness for just a second. Was that due to the surface or was it a bug?

I think it comes down to the surface.  When the surface is rough there are not as many smooth surfaces to catch the light so it darkens.  Both of them use a single light phong shading model.

Jason.


« Last Edit: May 29, 2010, 12:25:13 PM by Softology » Logged
kram1032
Fractal Senior
******
Posts: 1550


« Reply #131 on: May 29, 2010, 12:44:59 PM »

Ok, that's what I thought smiley
Logged
AndyAlias
Forums Newbie
*
Posts: 9


acaudwell
« Reply #132 on: August 08, 2011, 06:58:12 AM »

I found a small optimization for GPU implementations:

Quote
t=dot(p,n1);
if (t>0.0) { p-=2.0*t*n1; }

Can be rewritten as:

Quote
p-=2.0 * max(0.0, dot(p, n1)) * n1;

Edit: I think it may depend a bit on a case by case basis if this is actually faster. ie if the branch condition mostly is true for the particular IFS.
« Last Edit: July 16, 2012, 05:12:07 AM by AndyAlias » Logged

knighty
Fractal Bachius
*
Posts: 564


« Reply #133 on: August 26, 2011, 01:34:27 AM »

Thanks. smiley
Logged
Imagyx
Alien
***
Posts: 24


Finally 3D and more... Thank you !! ;-)


« Reply #134 on: October 25, 2011, 10:20:28 PM »

Thank you for these formulas.  smiley
Logged
Pages: 1 ... 7 8 [9] 10   Go Down
  Print  
 
Jump to:  



Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2013, Simple Machines

Valid XHTML 1.0! Valid CSS! Dilber MC Theme by HarzeM
Page created in 0.346 seconds with 28 queries. (Pretty URLs adds 0.019s, 2q)