Don't click here unless you want to be banned.

LSL Wiki : LibraryFractalGenerator

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are crawl338.us.archive.org
The following is a set of scripts for generating fractals (strictly speaking, fractal trees). I used variants of this script to build all of the fractals in my (2005) burning life build.

///////////////////////////////////////////
//////////Fractal Generator 1.0////////////
///////////////////////////////////////////
///////////////////by//////////////////////
///////////////////////////////////////////
/////////////Seifert Surface///////////////
/////////////2G!tGLf 2nLt9cG/////Aug 2005//
///////////////////////////////////////////

//Instructions for use:

//Rez a prim, mess around with it however you want. When you're done, make 3 copies of it.
//Put this script ("Fractal Generator 1.0") in one, which will be the base prim of the
//fractal. Put the script "Fractal Generator 1.0 Child" in another, and "Fractal Generator
//1.0 Rescaler" in the third. Take the "rescaler" prim, make sure it's name is "Object",
//and put it in the contents of the base prim (the one with this script). The scripts will
//build the fractal out of copies of this "rescaler" prim.

//Now we tell the scripts how we want the fractal to be built. Make some number of copies
//of the "child" prims (2 or 3 is a good number), and arrange them near or touching the
//"base" prim. Rotating them is fine, scaling them (down usually) is a good idea, but
//remember whenever you scale it to scale all three dimensions equally (use the grey boxes
//in the "Stretch" tool, not the red, green or blue). Rotating or moving the base prim is
//fine, but don't rescale it at this stage (the scripts rely on the "rescaler" prim to be
//an exact copy of the base prim).

//Now decide how many iterations you want the fractal to contain. 3 is a good number to
//start with. This script calculates beforehand how many prims the final fractal will
//contain, and will not build if it contains more than the "prim_limit" below. You can
//change this number (it is set in the first line of code below) to something bigger, but
//I take no responsibility if you end up crashing a sim! This is *not* a piece of self
//replicating code, but it will rez many prims relatively quickly. You have been warned.

//The formula for the number of prims in the final fractal, starting from b children and
//doing i iterations is:
// i+1                    if b == 1
// (b^(i+1) - 1)/(b - 1)  if b >= 1

//Having decided on the number of iterations you want, simply enter this number into the
//"Description" of the object (in the "General" tab of the extended editing controls).
//Finally, link all the child prims to the base prim, making sure that the base prim is
//the root of the link set. To do this, select the child prims first, add the base prim to
//the selection last (by holding down Shift and clicking on it), and then link (Ctrl-L, or
//selecting "Link" from the "Tools" menu).

//Now say "go" (the script will only listen to its owner), and the fractal will begin
//building (as long as the final fractal wouldn't contain too many prims). A good trick is
//to have the base and child prims (which are now linked) selected in edit mode, so that
//once the fractal is built, you can easily move the generator away. The generator will
//rez copies of the base and the child prims in their exact locations, so it can be
//difficult to select them.

//If you don't like how it turned out, simply edit the positions and scales of the child
//prims (you might want to unlink first and then relink again), and when you're happy, say
//"go" again, and it will generate the new fractal.

//Issues:

//It is impossible to rez a prim that is smaller than 0.01 metres, or larger than 10.0
//metres in any dimension. The script will detect when it tries to do so, and counts how
//many prims fail to rez because of this. It is also impossible to rez a prim further than
//around 10 metres distance from the rezzing object, which is the base prim. Unfortunately
//it doesn't seem to be exactly 10 metres, so I haven't implemented a similar check to see
//how many prims would be too far from the base prim to be rezzed. The code is in there,
//but commented out. Let me know if you work out something reliable. As is, attempting to
//rez a prim too far from the base will silently fail.

//If you modify the code, please keep my name with it, and make sure you don't crash a sim!
//Please do not sell this code, or anything with this code in it. Selling objects created
//with this code is ok. It would be nice if people would let me know what they're making
//with it :)

//   Seifert Surface
//   2G!tGLf 2nLt9cG

///////Start of code///////

integer prim_limit = 255; //wont build anything with more than this number of prims
integer iterations;  //number of levels to go down
integer branching;  //number of elts in each list

list posns;
list rotns;
list scales;

vector base_posn;

integer listen_control;
integer count_replies;      //for making sure that all child prims in the base have replied
integer bad_scales = 0;     //counting how many prims were too small or too big to rez
//integer bad_positions = 0;  //counting how many prims were too far away from the generator to rez
//this seems unreliable - according to the wiki rezzing at a distance of more than 10 meters fails silently,
//but it seems to be able to go a little further (11 meters?). So the distance checking code is here but commented out,
//you can experiment with it if you like. As is, when trying to rez prims too far away, it will just fail silently.

rez_children(vector pos, rotation rot, float scl, integer iters)
{
    integer branch = 0;
    for(branch = 0; branch < branching; branch++)
    {
        //llSay(0, "iter: "+(string)iters+" branch: "+(string)branch);
        vector check_scale = llGetScale()*llList2Float(scales, branch)*scl;
        if(check_scale.x < 0.01 || check_scale.x > 10.0 || check_scale.y < 0.01 || check_scale.y > 10.0 || check_scale.z < 0.01 || check_scale.z > 10.0)
        {
            bad_scales++;
        }
        else
        {
            //start of distance checking code, commented out due to unreliability
            //vector check_pos = pos + scl*(llList2Vector(posns, branch)*rot);
            //
            //if(llVecMag(check_pos) > 10)
            // {
            //     bad_positions++;
            //  }
            //  else        
            //  {        
            //end of dist checking code
                llRezObject("Object", base_posn + pos + scl*(llList2Vector(posns, branch)*rot), //position to rez
                <0,0,0>,   //given vel... ignore
                llList2Rot(rotns, branch)*rot, //rotation to rez
                llRound(1000000.0 * llList2Float(scales, branch)*scl)  //scaling, including workaround passing integer
                );
            // }   //(from dist checking code)
        }

        //llSleep(1.0);  //if you want to slow it down to see what its doing
        if(iters > 1)
        {
        rez_children((pos + scl*llList2Vector(posns, branch)*rot), llList2Rot(rotns, branch)*rot, llList2Float(scales, branch)*scl, iters - 1);
        }              
    }
}    

default
{
    state_entry()
    {
        key owner = llGetOwner();  //will only listen to its owner
        listen_control = llListen(0, "", owner, "");
    }

    on_rez(integer number)
    {
        llResetScript();
    }

    listen(integer channel, string name, key id, string message)
    {
        if(message == "go")  //say "go" to make it start
        {
            llSay(0, "Recording data...");
            state Recording;           
        }
    }   
    
    state_exit()
    {
        llListenRemove(listen_control);
    }   
}

state Recording
{
   state_entry()
   {
        branching = llGetNumberOfPrims() - 1; //dont count the root prim
        if(branching <= 0)
        {
            llSay(0, "Link child prims first!");
            state default;
        }
        //llSay(0, "branching: "+(string)branching);
        //check how many prims there will be... (assuming none too small/big/far away)
        iterations = (integer)llGetObjectDesc();  //put desired number of iterations in the object description
        if(iterations <= 0)
        {
            llSay(0, "Number of iterations (enter it into the object description) must be a positive integer!");
            state default;
        }
        //llSay(0, "iterations: "+(string)iterations);
        integer num_prims;
        if(branching == 1)
        {
           num_prims = iterations + 1;
        }
        else
        {  
        float fi = (float)iterations;
        float fb = (float)branching;
        float temp1 = llPow(fb,(fi + 1)) - 1.0;  //some math here...
        float temp2 = (fb - 1.0);
        num_prims = llRound(temp1/temp2);
        }
        llSay(0, "Final fractal will contain prims: "+(string)num_prims);
        if(num_prims > prim_limit)
        {
            llSay(0, "Too many prims!");
            state default;
        }
       
        count_replies = 0; //going to need all of the child prims to reply

        posns = [];
        rotns = [];
        scales = [];
        integer branch = 0;
        for(branch = 0; branch < branching; branch++)
        {  //reset lists to correct lengths
        posns = llListInsertList(posns, [ZERO_VECTOR], branch);
        rotns = llListInsertList(rotns, [ZERO_ROTATION], branch);
        scales = llListInsertList(scales, [1.0], branch);
        }
       
        llMessageLinked(LINK_ALL_OTHERS, 0, "return", NULL_KEY);  //ask all child prims to report their parameters
   }

   link_message(integer sender_num, integer num, string str, key id)
   {
        count_replies++;
        integer branch = sender_num - 2;
        llSay(0, "Replied, child prim: "+(string)branch);

        list reply = llParseString2List(str, ["|"], []);  //reply is of form <position>|<rotation>|scale
       
        vector temp_pos = (vector)llList2String(reply, 0);
        rotation temp_rot = (rotation)llList2String(reply, 1);
       
        vector temp = llGetScale();    //only measures scaling in x, but doesnt matter which: child prims should
        float tempx = temp.x;          //be scaled in all coords equally for code to work properly
        float temp_scale = (float)llList2String(reply, 2)/tempx;  //stored scale is relative to root prim scale
       
        //llSay(0, (string)temp_pos+(string)temp_rot+(string)temp_sca  le);
       
        posns = llListReplaceList(posns, [temp_pos], branch, branch);
        rotns = llListReplaceList(rotns, [temp_rot], branch, branch);
        scales = llListReplaceList(scales, [temp_scale], branch, branch);

        if(count_replies >= branching)
        {
           //llSay(0, "posns: "+llDumpList2String(posns, "|"));
           //llSay(0, "rotns: "+llDumpList2String(rotns, "|"));
           //llSay(0, "scales: "+llDumpList2String(scales, "|"));
           state Building;
        }
    }
}   

state Building
{
    state_entry()
    {            
        //llSay(0, "Starting...depth: "+(string)iterations)+" branching: "+(string)branching);
        base_posn = llGetPos();
        bad_scales = 0;
        //bad_positions = 0;
            
        llRezObject("Object", base_posn, <0,0,0>, llGetRot(),1); //rez copy of the base  
        rez_children(<0,0,0>, llGetRot(), 1.0, iterations);      //yay recursion!!
        llSay(0, "Done! "+(string)bad_scales+" prims had sizes too large or too small.");
        //llSay(0, "(string)bad_positions+" had positions too far from base prim.");
        state default;
    }
}

///////////////////////////////////////////
///////Fractal Generator 1.0 Child/////////
///////////////////////////////////////////
///////////////////by//////////////////////
///////////////////////////////////////////
/////////////Seifert Surface///////////////
/////////////2G!tGLf 2nLt9cG/////Aug 2005//
///////////////////////////////////////////

default
{
    state_entry()
    {
    }
    link_message(integer sender_num, integer num, string str, key id)
    {
        vector pos = llGetLocalPos();
        rotation rot = llGetLocalRot();
        vector temp = llGetScale();
        float scale = temp.x;  //everything assumes scaling happens on all 3 axes equally, so just pick one
        list data = [pos, rot, scale];
        string reply = llDumpList2String(data, "|");
        llMessageLinked(1, 0, reply, NULL_KEY);
    }
}

///////////////////////////////////////////
/////Fractal Generator 1.0 Rescaler////////
///////////////////////////////////////////
///////////////////by//////////////////////
///////////////////////////////////////////
/////////////Seifert Surface///////////////
/////////////2G!tGLf 2nLt9cG/////Aug 2005//
///////////////////////////////////////////

default
{
    state_entry()
    {
    }

    on_rez(integer number)
    {
        if(number != 0) //when rezzed by an avatar, don't do anything
        {
            float scale = (float)number/1000000.0;  //sneaky way to get a float in here using an integer...
            llSetScale(llGetScale()*scale);
            llRemoveInventory(llGetScriptName());   //kill the script when done
        }
    }
}
There is no comment on this page. [Display comments/form]