Clusterrezzer.lsl

From Micasim

Jump to: navigation, search


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");
        }
        
    }       
}
Personal tools