Welcome to Fractal Forums

Fractal Software => Programming => Topic started by: asimes on February 26, 2012, 03:22:02 PM




Title: Mandelbrot to Mandelbulb
Post by: asimes on February 26, 2012, 03:22:02 PM
I've gotten comfortable with programming the Mandelbrot (2D) after having played with it for a long time and want to generalize it to a Mandelbulb (3D). I have two different methods at the moment for making a Mandelbrot:

1. z = sq(z)+c method (where I test every point through this equation):
- I like this method and understand why it works
- Fast
- It is easy enough to set the equation to higher powers (multiply more binomials)
- I have no idea how to generalize it to 3D

2. Rotation method (based on following these instructions): http://www.skytopia.com/project/fractal/mandelbrot.html#pandora
- It does correctly make a Mandelbrot but I don't understand why
- Slow
- I don't know how to set higher powers
- Making it work in 3D seems to just require Spherical Positioning instead of Polar Positioning

If anyone reading this has Processing installed you can check out simplified versions of either code:

- Equation method:
Code:
float xmin = -2.5; 
float ymin = -2.0;
float wh = 4;
int maxIterations = 255;

void setup() {
  size(800, 800, P2D);
}

void draw() {
  loadPixels();
  float xmax = xmin+wh;
  float ymax = ymin+wh;
  float dx = (xmax-xmin)/width;
  float dy = (ymax-ymin)/height;
  float x = xmin;
  for (int i = 0; i < width; i++) {
    float y = ymin;
    for (int j = 0;  j < height; j++) {
      float zr = x;
      float zi = y;
      int n = 0;
      while (n < maxIterations) {
        float zrr = zr*zr;
        float zii = zi*zi;
        float twori = 2*zr*zi;
        zr = zrr-zii+x;
        zi = twori+y;
        if (zrr+zii > 16) break;
        n++;
      }
      if (n == maxIterations) pixels[i+j*width] = 0;
      else pixels[i+j*width] = color(n);
      y += dy;
    }
    x += dx;
  }
  updatePixels();
  noLoop();
}

- Rotation method:
Code:
float xmin = -2.5;
float ymin = -2;
float wh = 4;
int maxIterations = 255;

void setup() {
  size(800, 800, P2D);
  noLoop();
}

void draw() {
  loadPixels();
  float xmax = xmin+wh;
  float ymax = ymin+wh;
  float dx = (xmax-xmin)/width;
  float dy = (ymax-ymin)/height;
  float x = xmin;
  for (int i = 0; i < width; i++) {
    float y = ymin;
    for (int j = 0; j < height; j++) {
      float a = atan2(y, x);
      float d = sqrt(x*x+y*y);
      float nx = x;
      float ny = y;
      int n = 0;
      while (n < maxIterations) {
        float na = atan2(ny, nx);
        float nd = sqrt(nx*nx+ny*ny);
        nx = cos(na*2)*nd*nd+cos(a)*d;
        ny = sin(na*2)*nd*nd+sin(a)*d;
        if (nx*nx+ny*ny > 16) break;
        n++;
      }
      if (n == maxIterations) pixels[i+j*width] = 0;
      else pixels[i+j*width] = color(n);
      y += dy;
    }
    x += dx;
  }
  updatePixels();
}

I would strongly prefer to use the equation method although I don't know how to test 3D space like this. In 2D I just test the x-axis for real numbers and the y-axis for imaginary numbers so it would be great if this could be generalized for 3D space. If not then any help with setting higher powers for the rotation method would be appreciated.


Title: Re: Mandelbrot to Mandelbulb
Post by: cKleinhuis on February 26, 2012, 03:35:08 PM
for better understanding the triplex variant, just use the polar coordinates for your 2d mandelbrot, this way you magically can create exponents of rational numbers, e.g.2,5 this isnt possible with your int power method where you repeat the squaring ... from the polar exponentiation the bulb method arose, because it was just straightforward to include another angle in the polar exponentiation, as a reminder polar exponentiation on complex numbers equals to exponentiating the distance, and multiplying the angles ... if i still got this right


Title: Re: Mandelbrot to Mandelbulb
Post by: asimes on February 26, 2012, 04:47:27 PM
...I just realized using different powers for the rotation one is really easy:

nx = cos(na*power)*pow(nd, power)+cos(a)*d;
ny = sin(na*power)*pow(nd, power)+sin(a)*d;

instead of:

nx = cos(na*2)*nd*nd+cos(a)*d;
ny = sin(na*2)*nd*nd+sin(a)*d;

Although, you are right, this does just seem to magically work. I have no idea why the tutorial I followed works at all to be honest, it just correctly makes a Mandelbrot. I'm pretty sure I can make my own Mandelbulb from this now but I'd like to understand how to do it the other way for conceptual reasons (also it is waaaaaay faster than the rotation method). Could you point me in a direction where I might figure this out please?


Title: Re: Mandelbrot to Mandelbulb
Post by: bib on February 26, 2012, 05:38:33 PM

- It does correctly make a Mandelbrot but I don't understand why


Because it's the same as the first method :)

http://en.wikipedia.org/wiki/Euler's_formula


Title: Re: Mandelbrot to Mandelbulb
Post by: asimes on February 28, 2012, 06:30:43 AM
I have a 3D Mandelbulb finally working in Processing. I used the rotation method but with Spherical Coordinates and unfortunately it is really, really slow. I tried rendering a bounding box of 400x400x400 points and it took about an hour. Is this normal? I feel like if I can generalize the link Bib put it would be much faster.

The current method takes a point in Cartesian Coordinates (x, y, z), converts it Spherical Coordinates (r, theta, phi), applies the rotation similarly to the rotation code I posted above but in 3D obviously, stores the new point as Cartesian Coordinates again, and then tests the new point in a while loop to see if it tends toward infinity. This is probably why it is so slow and why I'd like to use the other method (if it is possible?).

Bib, thank you for the link although the math is still currently over my head. I'm looking into tutorials on using imaginary numbers as exponents and then attempting to tackle translating the rotation method. I don't really understand the math from the wikipedia article yet, although it seems to have an explanation on the relationship between the equation and rotation method but in 2D.

If anyone could help me understand what is going on in the article Bib put I'd really appreciate it. Also I have a new problem which is how to represent the data. Right now I just represent points with spheres but I'll tackle that problem after I have the code running at a reasonable speed.


Title: Re: Mandelbrot to Mandelbulb
Post by: bib on February 28, 2012, 09:22:18 AM
I can't help much about programming but I can explain complex numbers.

Don't worry too much about the imaginary number as an exponent. Let's assume it's just a practical notation. Note however that Euler's formula is probably the most elegant and intriguing formula of all mathematics because it features some of the most important and mysterious numbers in maths : e, i, 1, pi

e^i*pi=-1

Why the methods are the same is very simple. Any complex number can be written either in cartesian coordinates x+iy or in polar coordinates r*e^i*theta. With x=r*cos(theta) and y=r*sin(theta). r is the distance to origin, and theta is the angle to the x axis. So squaring a number (x+iy)²=x²-y²+2ixy is the same as doing r²*e^i2*theta : you have squared the distance and doubled the angle. Hence the equivalence of the 2 methods.

Euler's formula e^i*pi=-1 means that when you rotate the  number 1 (x=1, y=0) of 180° (pi) around the origin, then you end up on the other side (x=-1, y=0).

Basically the use of i as an exponent of e is like a rotation operator.

The original idea of the Mandelbulb was to transpose the rotation method to 3D, using the elevation angle in addition to theta, instead of trying with do to it with cartesian coordinates and matrix calculation.


Title: Re: Mandelbrot to Mandelbulb
Post by: Syntopia on February 28, 2012, 01:28:21 PM
While you can create a trigonometric-free version of the Mandelbulb formula (search Fractal Forums), it won't make your renderings that much faster.

Most 3D fractals tool use distance estimated rendering to speed up calculations (I've written an introduction to this here (http://blog.hvidtfeldts.net/index.php/2011/06/distance-estimated-3d-fractals-part-i/)). This will be much faster (but also more complex) than the grid approach.


Title: Re: Mandelbrot to Mandelbulb
Post by: asimes on February 29, 2012, 08:48:21 AM
Bib, I know you said not to worry about imaginary exponents but I don't think I can program this speed-up if I don't understand. I tried some searches on google for an explanation on how to use some imaginary number as an exponent to another number but I just get results for Euler's formula or examples of how to easily see what 'i' raised by an exponent will be. What I want to figure out would be for example:

2^i = ???
2^2i = ???
2^3i = ???

The reason I'm using Cartesian Coordinates is because my Mandelbulb is inside of a box of "voxels". By that I mean I make a box of arbitrary size (for example 400x400x400) and test every (x, y, z) point inside. Maybe I'm thinking about this in the wrong way? It seems like your explanation for Euler's formula is for 2D, does it generalize to 3D? I don't understand how the complex plane is generalized by my 3D rotation method, I just know that points on a complex plane are converted to Polar Coordinates in the 2D rotation version and I know how to generalize 2D rotation to 3D.

Sythopia, I'm having a hard time finding an explanation on this as well. I think the problem is I don't know the technical name of what I'm searching for, I just call it the "equation method". What would a non-trig version be called?

Even if I turn my rendering off (I don't represent the points I tested in any way whatsoever) it still takes about a minute and a half to test 400x400x400 points. I looked through your article to get a feel of what distance estimation is, I really like it, the results look great. I'm just kind of obsessing over the actual point testing before I get into rendering. I will definitely try out the distance estimation rendering after.


Title: Re: Mandelbrot to Mandelbulb
Post by: asimes on February 29, 2012, 09:01:47 AM
Ha ha ha, I didn't realize writing three question marks would make a confused guy face.

I was rereading the posts and realized cKleinhuis mentioned triplex numbers. I found this: http://www.fractalforums.com/theory/triplex-algebra/

Sythopia, is that the non-trig form you were talking about? I don't quite understand it yet but I guess I'll just keep rereading it until it makes enough sense to be programmed.