Logo by S Nelson - Contribute your own Logo!

END OF AN ERA, FRACTALFORUMS.COM IS CONTINUED ON FRACTALFORUMS.ORG

it was a great time but no longer maintainable by c.Kleinhuis contact him for any data retrieval,
thanks and see you perhaps in 10 years again

this forum will stay online for reference
News: Visit us on facebook
 
*
Welcome, Guest. Please login or register. April 24, 2024, 07:52:59 AM


Login with username, password and session length


The All New FractalForums is now in Public Beta Testing! Visit FractalForums.org and check it out!


Pages: [1]   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: Mandelbox 2D vs 3D and bailing  (Read 4656 times)
0 Members and 1 Guest are viewing this topic.
asimes
Fractal Lover
**
Posts: 212



asimes
WWW
« on: January 11, 2015, 09:45:09 PM »

I am familiar with the idea of bailing for the Mandelbrot Set and then coloring based on the number of iterations. I can somewhat generalize the idea to the Mandelbox in 2D although it is less clear what the bailout value should be. I know that for the typical values (scale = 2.0, box fold = 1.0, min radius = 0.5, and fixed radius = 1.0) that the Mandelbox stretches from -6.0 to 6.0 along each dimension. This would make me think that a bailout value should be 6.0 (or 36.0 without taking the square root)

Also I have a fairly good understanding of sphere tracing and creating a Mandelbox in 3D. However what I don't understand is why the returned value based on length of the marching point and the running derivative works. Also it does not make sense to me why no bail condition is needed. Simpler shapes like the Euclidean ones Iñigo Quilez has on his websites make sense to me

I have two Processing sketches that are as similar as I could make them for posting here (they do not make use of much Processing specific code to make it easier to follow in this post). The 2D version iterates from -8.0 to 8.0 along x and y and uses a bail condition of 1024.0 because 36.0 doesn't seem to be large enough for whatever reason. The 3D version places the camera at (0.0, 0.0, -25.0), the Mandelbox is at the origin, and the rays fire down the z-axis

Can anyone explain the difference between 2D and 3D (specifically bailing)? Below are the two Processing sketches if anyone cares to take a look

2D Mandelbox:
Code:
float scale = 2.0;
int maxIterations = 20;

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

void draw() {
  int start = millis();
  float delta = 16.0/max(width, height);
  
  float cx = -8.0;
  for (int i = 0; i < width; i++) {
    float cy = -8.0;
    for (int j = 0; j < height; j++) {
      float zx = cx;
      float zy = cy;

      int k = 0;
      for (; k < maxIterations; k++) {
        if (zx > 1.0) zx = 2.0-zx;
        else if (zx < -1.0) zx = -2.0-zx;
        if (zy > 1.0) zy = 2.0-zy;
        else if (zy < -1.0) zy = -2.0-zy;

        float dot = zx*zx+zy*zy;
        if (dot < 0.5) {
          zx *= 2.0;
          zy *= 2.0;
        } else if (dot < 1.0) {
          float inversion = 1.0/dot;
          zx *= inversion;
          zy *= inversion;
        }

        zx = scale*zx+cx;
        zy = scale*zy+cy;

        if (dot > 1024.0) break;
      }

      if (k == maxIterations) pixels[i+j*width] = 0;
      else pixels[i+j*width] = 0xffffffff;

      cy += delta;
    }
    cx += delta;
  }

  println("Time: "+(millis()-start));
  updatePixels();
}


3D Mandelbox:
Code:
float scale = 2.0;
int maxIterations = 20;

float maxDist = 50.0;
float minDist = 0.0001;

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

float mandelboxDist(float zx, float zy, float zz) {
  float d = 1.0;

  float cx = zx;
  float cy = zy;
  float cz = zz;

  for (int i = 0; i < maxIterations; i++) {
    if (zx > 1.0) zx = 2.0-zx;
    else if (zx < -1.0) zx = -2.0-zx;
    if (zy > 1.0) zy = 2.0-zy;
    else if (zy < -1.0) zy = -2.0-zy;
    if (zz > 1.0) zz = 2.0-zz;
    else if (zz <- 1.0) zz = -2.0-zz;

    float dot = zx*zx+zy*zy+zz*zz;
    if (dot < 0.5) {
      zx *= 2.0;
      zy *= 2.0;
      zz *= 2.0;
      d *= 2.0;
    } else if (dot < 1.0) {
      float inversion = 1.0/dot;
      zx *= inversion;
      zy *= inversion;
      zz *= inversion;
      d *= inversion;
    }

    zx = scale*zx+cx;
    zy = scale*zy+cy;
    zz = scale*zz+cz;
    d = d*scale+1.0;
  }

  return sqrt(zx*zx+zy*zy+zz*zz)/d;
}

void draw() {
  int start = millis();

  float ratio = (float)height/width;

  for (int i = 0; i < width; i++) {
    for (int j = 0; j < height; j++) {
      float cameraDirX = (float)i/width-0.5;
      float cameraDirY = ((float)j/height-0.5)*ratio;
      float cameraDirZ = 1.0;

      float normMult = 1.0/sqrt(cameraDirX*cameraDirX+cameraDirY*cameraDirY+1.0);
      cameraDirX *= normMult;
      cameraDirY *= normMult;
      cameraDirZ *= normMult;

      float marchX = 0.0;
      float marchY = 0.0;
      float marchZ = -25.0;

      float t = 0.0;
      float currDist = maxDist;
      int steps = 255;

      for (; steps >= 0; steps--) {
        currDist = mandelboxDist(marchX, marchY, marchZ);
        if (currDist < minDist) break;

        t += currDist;
        if (t > maxDist) break;

        marchX = cameraDirX*t;
        marchY = cameraDirY*t;
        marchZ = cameraDirZ*t-25.0;
      }

      if (currDist < minDist)
        pixels[i+j*width] = 0xff000000|(steps<<16)|(steps<<8)|steps;
      else pixels[i+j*width] = 0;
    }
  }

  println("Time: "+(millis()-start));
  updatePixels();
}
« Last Edit: January 11, 2015, 09:47:31 PM by asimes » Logged
asimes
Fractal Lover
**
Posts: 212



asimes
WWW
« Reply #1 on: January 12, 2015, 05:38:30 AM »

I just realized that I can apply the DE formula in 2D and that it produces a significantly nicer looking image than the 2D code I posted earlier. Doesn't involve any bailout value as well although I am still wondering about the lack of bailout value for DE

To the left is the bailout method and to the right is a 2D DE:


Code for the 2D DE:
Code:
float scale = 2.0;
int maxIterations = 20;

float xmin = -8.0;
float ymin = -8.0;
float wh = 16.0;

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

void draw() {
  int start = millis();

  float delta = 16.0/max(width, height);
  float colorMap = 1.0/delta*255.0;

  float xStart = xmin-min((width-height)*0.5*delta, 0.0);
  float yStart = ymin-min((height-width)*0.5*delta, 0.0);

  float cx = xStart;
  for (int i = 0; i < width; i++) {
    float cy = yStart;
    for (int j = 0; j < height; j++) {
      float zx = cx;
      float zy = cy;
      float d = 1.0;

      for (int k = 0; k < maxIterations; k++) {
        if (zx > 1.0) zx = 2.0-zx;
        else if (zx < -1.0) zx = -2.0-zx;
        if (zy > 1.0) zy = 2.0-zy;
        else if (zy < -1.0) zy = -2.0-zy;

        float dot = zx*zx+zy*zy;
        if (dot < 0.5) {
          zx *= 2.0;
          zy *= 2.0;
          d *= 2.0;
        } else if (dot < 1.0) {
          float inversion = 1.0/dot;
          zx *= inversion;
          zy *= inversion;
          d *= inversion;
        }

        zx = scale*zx+cx;
        zy = scale*zy+cy;
        d = d*scale+1.0;
      }

      float dist = sqrt(zx*zx+zy*zy)/d;
      int val = min((int)(dist*colorMap), 255);
      pixels[i+j*width] = 0xff000000|(val<<16)|(val<<8)|val;

      cy += delta;
    }
    cx += delta;
  }

  println("Time: "+(millis()-start));
  updatePixels();
}
Logged
eiffie
Guest
« Reply #2 on: January 12, 2015, 05:01:51 PM »

I have no idea about your original question "what should a bail out be" but I hopefully can answer "why the returned value based on length of the marching point and the running derivative works". You understand how the DE for a sphere works. Let us say you have one that looks like this:
float DE(vec3 p){return length(p)-1.0;} //the radius is hard coded
Now if you want to draw a sphere that is 10 times smaller, but the radius is hard coded, you can do this:
float d=DE(p*10.0)/10.0;
We are scaling p and inverse scaling the result. Now look at MandelBox Julia code. We are just applying a number of scales, folds and offsets then drawing a sphere with the result inverse scaled. The folds and julia (constant for any space) offsets do not effect the scale.
The standard MandelBox code on the other hand adds the original position which changes thru space so we have to account for that stretch. Since the stretch is at max 1x more we add 1 to our running derivative or "running scale".
In other words all we are doing is drawing a tiny sphere and you already know how to do that.
Logged
mclarekin
Fractal Senior
******
Posts: 1739



« Reply #3 on: January 13, 2015, 02:52:14 AM »

I think I understand what asimes meant about bailout, but have since got more confused with the more that I thought about it. In the Mandelbox  used in Mandelbulber we have this code (or something similar)


Code:
#endif 
if (r > 1024.0f) { dist = r / fabs(DE); out.colourIndex = colourMin / i * 300.0f; break;}
with r being the length of vector z

so I assumed that "bailout" was r > 1024.0f.

Then I thought, as all points calculated that are far from the origin keep getting folded in, then a bailout is not required, so I was left confused.

Then we add in something called an orbit trap so I thought this is the "bailout". I remain confused.

Logged
asimes
Fractal Lover
**
Posts: 212



asimes
WWW
« Reply #4 on: January 13, 2015, 04:50:51 AM »

@eiffie, thanks, it took me a bit to make sense of the example you gave with scaling the sphere. I tried it out and it works, not totally clear on why

Say there is a sphere at the origin, the camera is at (0.0, 0.0, -5.0), and the radius is 1.0. Normally the distance would be (5.0 - 1.0) or 4.0 for the ray pointing directly at the sphere, it seems like your example makes the distance become (((5.0 * 10.0) - 1.0) / 10.0) or 4.9. The sphere appears to be smaller because more iterations are required to approach the surface? Edit: Thought about this a bit more, I think that it does not affect the ray directly pointing at it, it affects the rays pointing nearby as they would now possibly miss the sphere

Also I never thought of considering the Mandelbox to be like a transformed sphere but I can kind of see it due to the return value. That one takes quite a bit of mental gymnastics, I think of it more as being a point rather than a sphere because nothing is subtracted

@mclarekin, I ended up using 1024.0 in my code because I saw it online. I am pretty sure that the value is overkill (arbitrarily large) but still don't quite make sense of the bailout for the Mandelbox
« Last Edit: January 13, 2015, 06:21:38 AM by asimes » Logged
mclarekin
Fractal Senior
******
Posts: 1739



« Reply #5 on: January 13, 2015, 05:36:27 AM »

I suspect if I search the forums posts it will all become clear to me, and yes 1024.0f seems very large and I have changed it with no apparent difference in the result. Definitely with some hybrids I had to "trial and error" the value to get a good image, it maybe time for me to stretch my mind and try to follow what really going on. smiley
Logged
eiffie
Guest
« Reply #6 on: January 14, 2015, 12:54:16 AM »

Your almost there! Go back to your example and calculate the distance when the sphere is ten times smaller. The radius is 0.1 so the distance is 4.9
I think bailouts were initially used to speed up rendering and prevent overflow. Coloring is usually done with the minimum radius of the orbit.
Logged
asimes
Fractal Lover
**
Posts: 212



asimes
WWW
« Reply #7 on: January 14, 2015, 07:29:54 AM »

Ha ha ha, I can't believe I didn't realize that it produces the same value as when the radius is actually 0.1

If you are willing to look at the first 2D code I posted the bailout can prevent k from being equal to maxIterations (k is the number of Mandelbox iterations). The "coloring" is then entirely black or white:

Code:
if (k == maxIterations) pixels[i+j*width] = 0; // Black
else pixels[i+j*width] = 0xffffffff; // White

Although that being said using the orbit produces more interesting results
Logged
Pages: [1]   Go Down
  Print  
 
Jump to:  

Related Topics
Subject Started by Replies Views Last post
Mandelbox Man! Fractal Humor Sockratease 9 4316 Last post March 12, 2010, 12:00:16 AM
by kram1032
mandelbox Images Showcase (Rate My Fractal) visual.bermarte 1 1648 Last post May 27, 2010, 11:33:10 PM
by knighty
More Mandelbox ! Mandelbulb Renderings bib 12 4080 Last post June 07, 2010, 08:07:01 PM
by bib
Mandelbox how to? Programming flexiverse 1 3980 Last post June 25, 2010, 07:07:50 PM
by cKleinhuis
Mandelbox Egg Images Showcase (Rate My Fractal) Power 8 2 2914 Last post January 09, 2011, 11:07:00 AM
by The Rev

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines

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