Clusterrezzer.lsl
From Micasim
| Project | OpenSim Physics |
|---|---|
| Project Lead | Rob Knop |
| Project Homepage | NewtonPhysics |
This is the rezzer script described on Using NewtonPhysics that will rez out two stars orbiting in a circle. Read the instructions on Using NewtonPhysics to make it work. It rezzes a bunch of stars with a 1/r distribution (out to some cutoff), and then gives them random velocities with a v_rms that is roughly what you'd expect virially.
// Listens on channel 1 for instructions
// "rez" -- rez the stars
// "go" -- tell stars to apply initial velocity and go
// "stop" -- turns stars unphysical
// "start" -- turns stars physical
// "die" -- tells stars to die
integer chan = 3117;
// exponential scale length of the cluster
// or, maybe maximum radius of the cluster
float r = 25.0;
// mass of each star
float m = 0.5;
// Number of stars
integer n = 64;
// ***************
// internal variables
list starpos;
list starvel;
// ****************************************************
float exprand(float sigma)
{
float x = 0.0;
while (x == 0.0) x = llFrand(1.0);
return -llLog(x)*sigma;
}
// returns r distributed according to p(r) = 1/r,
// with a cutoff at maxr
float invrand(float maxr)
{
float maxx = llLog(maxr);
float x = llFrand(maxx);
return(llPow(2.71828182845905, x));
}
float gaussrand(float sigma)
{
float x1;
float x2;
float y1;
float y2;
float ftmp;
float R2 = 2.;
while (R2 > 1. || R2 ==0)
{
x1 = 2.0*llFrand(1.0) - 1.0;
x2 = 2.0*llFrand(1.0) - 1.0;
R2 = x1*x1 + x2*x2;
}
ftmp = llSqrt(-2. * llLog(R2) / R2);
y1 = x1 * ftmp;
y2 = x2 * ftmp; // Extra!
return y1 * sigma;
}
vector randsphere(float r)
{
float costheta = llFrand(2.0) - 1.0;
float sintheta = llSqrt(1.0 - costheta*costheta);
float phi = llFrand(TWO_PI);
return <sintheta * llCos(phi), sintheta*llSin(phi), costheta> * r;
}
rezstars()
{
integer i;
integer j;
float starrad;
vector thisstarpos;
vector thisstarvel;
float pe = 0.; // I wish we had doubles
float rmsvel = 0;
float dist;
llSay(0, "Rezzing " + (string)n + " stars...");
starpos = ["junk"];
starvel = ["junk"];
for (i = 1 ; i <= n ; ++i)
{
// starrad = exprand(r);
starrad = invrand(r);
thisstarpos = llGetPos() + randsphere(starrad);
starpos += [thisstarpos];
// llSay(0, "Star " + (string)i + " pos: " + (string)thisstarpos);
llRezObject("Star", llGetPos(), ZERO_VECTOR,
ZERO_ROTATION, i);
for (j = 1 ; j < i ; ++j)
{
dist = llVecMag(llList2Vector(starpos, j) - thisstarpos);
pe -= m * m / dist; // no divide-by-0 protection...
}
}
llSay(0, "PE = " + (string)pe);
rmsvel = llSqrt( -pe / (3.0 * m * n) );
llSay(0, "rmsvel = " + (string)rmsvel);
for (i = 1 ; i <= n ; ++i)
{
thisstarvel = <gaussrand(rmsvel), gaussrand(rmsvel), gaussrand(rmsvel)>;
starvel += [thisstarvel];
// llSay(0, "Star " + (string)i + " vel: " + (string)thisstarvel);
}
llSay(0, "...done rezzing stars.");
}
default
{
state_entry()
{
llListen(chan, "", "", "");
llListen(1, "", "", "");
}
touch_start(integer num)
{
}
listen(integer chan, string name, key id, string msg)
{
list params = llParseString2List(msg, [" "], []);
string command = llList2String(params, 0);
integer num = 0;
if (llGetListLength(params) > 1)
num = llList2Integer(params, 1);
if (command == "Hello" && num > 0 && num <= n)
{
// llSay(0, "Got Hello from star " + (string)num);
llSay(chan, "pos " + (string)num + " " + llList2String(starpos, num));
llSay(chan, "initvel " + (string)num + " " + llList2String(starvel, num));
}
else if (command == "rez")
{
rezstars();
}
else if (command == "go")
{
llRegionSay(3117, "go");
}
else if (command == "stop")
{
llRegionSay(3117, "stop");
}
else if (command == "start")
{
llRegionSay(3117, "start");
}
else if (command == "die")
{
llRegionSay(3117, "die");
}
}
}

