Mandelbrot Explorer

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
// 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 http://wiki.secondlife.com/wiki/XyText_1.5)
// 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;
    }
}