Mandelbrot Explorer

From Second Life Wiki
Jump to navigation Jump to search

<lsl> // Mandelbrot Explorer by Babbage Linden // // Interactive Fractal Explorer Demo // // Add this script to a screen made from 245 linked prisms each manipulated to show 5 faces in one direction //(The script here will create the correct shape object [[1]]) // to form a 35x35 pixel display. When rezzed or reset the object will calculate and display a mandelbrot set. // Clicking on the display will centre the view on the clicked prim and zoom in, allowing the fractal to be // explored. To return to the initial image either reset the script, or take and rez the object. // // Available under the Creative Commons Attribution-ShareAlike 2.5 license // http://creativecommons.org/licenses/by-sa/2.5/

list faces = [3,7,4,6,1];

integer xsize=35; integer ysize=35; integer numfaces=5; integer fwidth=7;

integer linkNumToX(integer linkNum) {

   integer result = ((linkNum - 1) % fwidth) * numfaces + (numfaces / 2);
   return result;

}

integer linkNumToY(integer linkNum) {

   integer result = ((linkNum - 1) / fwidth);
   return result;

}

setpixel(integer x, integer y, vector colour) {

   integer face = (y*xsize) + x;
   integer linknum = face/numfaces;
   integer primface = face - (linknum*5); 
   llSetLinkColor(linknum + 1, colour, llList2Integer(faces,primface));

}

mandlebrot(float startx, float starty, float zoom, integer width) {

   integer height = width;
   integer i;
   integer m = 60; // Max iterations.
   integer isOverLimit = FALSE;
   float Zr = 0.0;
   float Zi = 0.0;
   float Cr = 0.0;
   float Ci = 0.0;
   float Tr;
   float Ti;
   float limit2 = 4.0;

   integer y;
   for(y = 0; y < height; y++) 
   {
       integer x;
        for(x = 0; x < width; x++)
        {
           Zr = 0.0; Zi = 0.0;
           Cr = (2.0 * (x + (startx / zoom)) / width - 1.5) * zoom;
           Ci = (2.0 * (y + (starty / zoom)) / height - 1.0) * zoom;
    
           // Evaluate sequence until either max iterations has been
           // reached or threshold is breached.
           i = 0;
           do {
              Tr = Zr*Zr - Zi*Zi + Cr;
              Ti = 2.0*Zr*Zi + Ci;
              Zr = Tr; Zi = Ti;
              isOverLimit = Zr*Zr + Zi*Zi > limit2;
           } while (!isOverLimit && (++i < m));
           
           // Generate colour for each possible iteration.
           // First fill r, then overflow in to g, then b.
           vector colour = <0,0,0>;
           if(i < m)
           {
               float step = m / 3.0;
               if(i > 0)
               {
                   colour.x = i / step;
                   i -= (integer)step;
               }
               if(i > 0)
               {
                   colour.y = i / step;
                   i -= (integer)step;
               }
               if(i > 0)
               {
                   colour.z = i / step;
                   i -= (integer)step;
               }
           }
           setpixel(x, y, colour);    
       }
   }

}

float gZoom; float gMinX; float gMinY;

init() {

   // Draw initial fractal image.
   gZoom = 1.0;
   gMinX = 0;
   gMinY = 0;
   mandlebrot(gMinX, gMinY, gZoom, 35);

}

default {

   on_rez(integer param)
   {
       init();
   }
   
   state_entry()
   {        
       init();
   }
   
   touch_start(integer num)
   {
       // Convert link number in to screen space.
       float dx = linkNumToX(llDetectedLinkNumber(0));
       float dy = linkNumToY(llDetectedLinkNumber(0));
               
       // Make dx and dy relative to centre.
       dx -= (xsize / 2);
       dy -= (ysize / 2);
       
       // Adjust gMinX and gMinY by x and y.
       gMinX += dx * gZoom;
       gMinY += dy * gZoom;
       
       // Calculate Mandelbrot and increase zoom.
       mandlebrot(gMinX, gMinY, gZoom, 35);
       gZoom *= 0.9;
   }

} </lsl>