07-30-2007 01:02
**Warning This script is very prim intensive (can easily go over 8,000 prims with an iteration of 20 and a large enough initial object size). I reccomend playing with this in a sand-box before using it to create something in a residential or private sim.


There are 7 scripts in total: the fractal generator, the building block script, and 5 scripts for distributed rezzes.

How to use. stick the generator and 5 rezzing scripts in your standard wooden cube. create an object (1 prim prefferably) and call it "fractal block" drop the building block script in there, set it to temp on rez, and then drop your fractal block into your wooden cube. start up the fractal generator script and watch it go.


*note* the terminology is off in my script. the variable "iteration" is really more of a resolution level (pixels defining a curve). the generator is only 3 iterations deep, but I did not want to go farther due to the sheer number of prims that it would create. with a low resolution of just 5 prims, 3 iterations would have 5^3 prims (125) with a 4th iteration it would have 5^4 prims (625). if you up your resolution to 10, you have 1000 prims theoretically at 3 iterations, and 10,000 prims at 4 iterations (over half a sim's prim allotment!)

some interesting numbers to try and set the variance for:

PI/4
PI/2
PI
0
.75*PI

The fractals are meant to be viewed from the top down. also, since my rotation math is shakey in SL, the code only produces the intended effect when the generator prim is at zero rotation.

***Generator***
CODE

string block;
float scale=.75;//how much to shrink your block as it goes along
integer iterations=10;//how many blocks being defined in the curve
float variance;



iterate(float size, rotation rot, vector pos)//2nd iteration
{
integer i;
for(i=1; i<= iterations; i++)
{
if(i==1)
{
rot=llRotBetween(<1,0,0>,<0,1,0>)*rot;//rotate your base of the curve by 90 degrees
}

size=size*scale;
integer int=(integer)(size*1000);
rot=llRotBetween(<llSin(((float)i/(float)iterations)*variance),llCos(((float)i/(float)iterations)*variance),0>,llRot2Fwd(rot))*llGetRot();//orbits the curve variance number of times
pos += <size/2,size/2,size/2>*rot;//sets the position of the next block on the curve to be at half it's radius away (sorta)

if(size <=.01)
{
return;//smallest block size, so don't rez anymore and finish.
}

llMessageLinked(LINK_THIS,0,(string)block + "//" + (string)pos + "//" + (string)rot + "//" + (string)int,NULL_KEY);//send out the rez command
llSetText("Orbital attractor=" +(string)(variance/PI) + "*PI",<1,1,1>,1);//show text on what setting we're using.
iterate2(size,rot,pos);/2nd iteration
}

}

iterate2(float size, rotation rot, vector pos)//2nd iteration I suppose if I really wanted to I could have made these recursive functions rather than an explicitly defined number of iterations. it's pretty much a straight up copy and paste job to add in more iterations if needed.
{
integer i;

for(i=1; i<= iterations; i++)
{
if(i==1)
{
rot=llRotBetween(<1,0,0>,<0,1,0>)*rot;
}

size=size*scale;
integer int=(integer)(size*1000);
rot=llRotBetween(<llSin(((float)i/(float)iterations)*variance),llCos(((float)i/(float)iterations)*variance),0>,llRot2Fwd(rot))*llGetRot();
pos += <size/2,size/2,size/2>*rot;
if(size <=.01)
{
return;
}

llMessageLinked(LINK_THIS,0,(string)block + "//" + (string)pos + "//" + (string)rot + "//" + (string)int,NULL_KEY);
iterate3(size,rot,pos);

}

}

iterate3(float size, rotation rot, vector pos)//third iteration.
{
integer i;
integer rc;//rez counter to distribute the rez command
for(i=1; i<= iterations; i++)
{
if(i==1)
{
rot=llRotBetween(<1,0,0>,<0,1,0>)*rot;
}

size=size*scale;
integer int=(integer)(size*1000);
rot=llRotBetween(<llSin(((float)i/(float)iterations)*variance),llCos(((float)i/(float)iterations)*variance),0>,llRot2Fwd(rot))*llGetRot();
pos += <size/2,size/2,size/2>*rot;
if(size<=.01)
{
return;
}
rc++;
if(rc==5)
{
rc=0;
}
llMessageLinked(LINK_THIS,rc,(string)block + "//" + (string)pos + "//" + (string)rot + "//" + (string)int,NULL_KEY);
llSleep(.01);//work around for bug in distributed rezzing
}

}



default
{
state_entry()
{


block=llGetInventoryName(INVENTORY_OBJECT,(integer)llFrand(llGetInventoryNumber(INVENTORY_OBJECT)));//randomly picks a block to use from the inventory
llSleep(1);//work around for a bug
llSay(-23408,"die");

vector v=llGetScale();
variance =llFrand(4)*PI;//number of orbits the curve makes
iterate(v.x,llGetRot(),llGetPos());//create our fractal using the generator's size, rotation, and position as initial seeds.
}

}


***fractal block***
CODE

default
{
on_rez(integer num)
{
float scale=(float)num/(float)1000;
//llSetText((string)num,<1,1,1>,1);
llSetScale(<1,1,1>*scale);
}

state_entry()
{
llSetText("",<1,1,1>,1);
llListen(-23408,"",NULL_KEY,"");
}

listen(integer channel, string name, key id, string message)
{
if(message=="die")
{
llDie();
}
}
}


***rezzer 1***
CODE

default
{
link_message(integer sender, integer i, string str, key id)
{
if(i==0)
{
list l=llParseString2List(str,["//"],[]);
string block=llList2String(l,0);
vector pos=(vector)llList2String(l,1);
rotation rot=(rotation)llList2String(l,2);
integer int=(integer)llList2String(l,3);
llRezAtRoot(block,pos,ZERO_VECTOR,rot,int);
}
}
}


***rezzer 2***
CODE

default
{
link_message(integer sender, integer i, string str, key id)
{
if(i==1)
{
list l=llParseString2List(str,["//"],[]);
string block=llList2String(l,0);
vector pos=(vector)llList2String(l,1);
rotation rot=(rotation)llList2String(l,2);
integer int=(integer)llList2String(l,3);
llRezAtRoot(block,pos,ZERO_VECTOR,rot,int);
}
}
}


***rezzer 3***
CODE

default
{
link_message(integer sender, integer i, string str, key id)
{
if(i==2)
{
list l=llParseString2List(str,["//"],[]);
string block=llList2String(l,0);
vector pos=(vector)llList2String(l,1);
rotation rot=(rotation)llList2String(l,2);
integer int=(integer)llList2String(l,3);
llRezAtRoot(block,pos,ZERO_VECTOR,rot,int);
}
}
}


***rezzer 4***
CODE

default
{
link_message(integer sender, integer i, string str, key id)
{
if(i==3)
{
list l=llParseString2List(str,["//"],[]);
string block=llList2String(l,0);
vector pos=(vector)llList2String(l,1);
rotation rot=(rotation)llList2String(l,2);
integer int=(integer)llList2String(l,3);
llRezAtRoot(block,pos,ZERO_VECTOR,rot,int);
}
}
}


***rezzer 5***
CODE

default
{
link_message(integer sender, integer i, string str, key id)
{
if(i==4)
{
list l=llParseString2List(str,["//"],[]);
string block=llList2String(l,0);
vector pos=(vector)llList2String(l,1);
rotation rot=(rotation)llList2String(l,2);
integer int=(integer)llList2String(l,3);
llRezAtRoot(block,pos,ZERO_VECTOR,rot,int);
}
}
}


***Note. This script is distributed "as is" with no garauntees on future performance when patches become available. Only restrictions on use is that this is not used in a griefing manner, and if it's used in a sellable item, to give credit to myself, the author, in the product. have fun.
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.