Change font size
It is currently Tue Jul 17, 2018 11:33 pm

Forum rules


{L_IMAGE}



Post a new topicPost a reply Page 1 of 2   [ 18 posts ]
Go to page 1, 2  Next
Author Message
 Post subject: Geodesic Dome Builder Script
PostPosted: Fri Sep 03, 2010 12:24 pm 
OSG Elite
User avatar

Joined: Thu Dec 11, 2008 7:51 am
Posts: 392
Location: England UK
Below are scripts to build a 'Geodesic Dome Builder', based on the original scripts and instructions here: http://www.sparticarroll.com/Geodesic+Dome+Builder.ashx. All credit goes to the original creator (Shine Renoir) except for the modifications I have made.

If you use this on a public sandbox, please clean up after yourself!


I have modified the scripts to work better with OpenSim and also added a few variables to adjust the line and triangle thicknesses and added some delays to make our script engine cope the script. There is also a part of the script I have disabled as I couldn't get it to work properly as it seems either vector floats or llSetPos isn't quite accurate. I couldn't nail it down to what exactly, but there is a workaround, and that is to adjust the 'ScriptDistanceLimitFactor' in opensim.ini to allow scripted objects to move more than 10m. This is a multiplier of 10, so setting it to 3 would enable scripted objects to move 30m. Setting it to 10 will allow 100m and so on. I set mine to 50 to allow scripted objects to move upto 500m.

I have also added code to remove the script from the lines and triangles once they have been rezzed and resized.

You may also want to colour/texture the Line and Triangle prims before you add them to the Dome Builder prim contents as doing so later can be a tedious task.

Experiment and have fun!


Instructions:

- Adjust ScriptDistanceLimitFactor in opensim.ini to allow scripted objects to move more than 10m, and restart opensim. You will need to adjust this depending on how big the dome you intend to create.
- Create a cylinder and name it 'Line' and resize to 0.05,0.05,1.00
- Create a cube and call it 'Triangle' and resize to 1.309,0.01,1.311, also taper x=1.00,y=0.00
- Create a cube and call it 'Dome Builder', or whatever you want to call it and leave it at it's default size.
- Drop the 'Line' script in the 'Line' prim
- Drop the 'Triangle' script in the 'Triangle' prim
- Take both the Line and Triangle prims into your inventory, then place them in the contents of the Dome Builder prim
- Drop the 'Dome Builder' script into the Dome Builder prim and position at the center base of where you want the dome to be created, then touch and sit back and watch :)

Dome Builder Script:
{L_CODE}:
// Dome Builder
// 2007 Copyright by Shine Renoir (fb@frank-buss.de)
// Use it for whatever you want, but keep this copyright notice
// and credit my name in notecards etc., if you use it in
// closed source objects
// Modified by Adelle Fitzgerald for OpenSim

integer subdivision = 2; //Change for the amount of vertices
float length = 5.0; //Change this for the size of the dome
float lineWidth = 0.2; //'Thickness' of the lines
float triangleThickness = 0.05; //Thickness of the triangles
float delay = 0.1; //Delay between rezzing the prims and setting the properties - increase this if you experience 'bad' prims.
float initialDelay = 1.0; //Delay for the first few prims. Once the first few have rezzed it reverts to the delay above. Increase this if you experience 'bad' prims for the first few.

//Some good sizes to play with: subdevision = 2, length = 5 : subdevision = 3, length = 10 : subdevision = 4, length = 20 : subdevision = 5, length = 30
//And for something spectacular, subdevision = 18, length = 150 -- Do place the builder at the center of a region as this will pretty much fill it and create ~3600 prims in the process ;-)

vector base;
float r;
integer start;

move(vector destination)
{
    // llSetPos is limited to 10m distances,
    // so it is called until the target is reached
    //vector p = ZERO_VECTOR;
    //while (p.z != destination.z) {
    //    llSetPos(destination);
    //    p = llGetPos();
    //}
   
    //The original code above wouldn't work reliably in OpenSim, so as a workaround increase the 'ScriptDistanceLimitFactor' in opensim.ini to allow the prim to move more than the max of 10m. I set mine to 50 (ScriptDistanceLimitFactor = 50.0) to allow scripted prims to move upto 500m using llSetPos.
    llSetPos(destination);
}

drawLine(vector v1, vector v2)
{
    vector line = v2 - v1;
    vector pos = base + line / 2 + v1;
    float len = llVecMag(line);
    vector size = <lineWidth, lineWidth, len>;
    vector up = <0, 0, 1>;
    rotation rot = llRotBetween(up, llVecNorm(line));
    move(pos);
    llRezObject("Line", pos, ZERO_VECTOR, rot, 0);
    if (start < 6)
    {
        start += 1;
        llSleep(initialDelay);
    }
    else
    {
        llSleep(delay);
    }
    llSay(-43, (string) size);
}

drawTriangle(vector v1, vector v2, vector v3)
{
    // assuming a normal triangle: no zero area

    // make v1-v3 the longest side
    integer i = 0;
    for (i = 0; i < 2; i++) {
        float ax = llVecDist(v2, v3);
        float bx = llVecDist(v1, v3);
        float cx = llVecDist(v1, v2);
        if (ax > bx || cx > bx) {
            vector tmp = v1;
            v1 = v2;
            v2 = v3;
            v3 = tmp;
        }
    }
   
    // calculate side lengths
    float a = llVecDist(v2, v3);
    float b = llVecDist(v1, v3);
    float c = llVecDist(v1, v2);

    // b=b1+b2, a^2=h^2+b2^2, c^2=b1^2+h^2, solving:
    float b2 = (a*a + b*b - c*c)/2.0/b;
    float b1 = b - b2;
    float h = llSqrt(a*a - b2*b2);  // triangle height

    // calculate triangle height vector and shear value
    float hPosition = b1 / b;
    vector vb1 = (v3 - v1) * hPosition;
    vector vh = v2 - (v1 + vb1);
    float shear = hPosition - 0.5;

    // calculate position and rotation
    vector pos = base + v1 + (v3 - v1) / 2 + vh / 2;
    vector size = <b, triangleThickness, h>;
    vector up = <0.0, 0.0, 1.0>;
    rotation rot = llRotBetween(up, llVecNorm(vh));
    vector fwd = llVecNorm(v3 - v1);  // fwd is the base
    vector left = llVecNorm(vh);
    left = llVecNorm(left % fwd);  // "left" is cross product (orthogonal to base and left)
    rot = llAxes2Rot(fwd, left, fwd % left);  // calculate the needed rotation
   
    // create object
    llRezObject("Triangle", pos, ZERO_VECTOR, rot, 0);
   
    // set size and shear value
    list send = [size, shear ] ;
    if (start < 6)
    {
        start += 1;
        llSleep(initialDelay);
    }
    else
    {
        llSleep(delay);
    }
    llSay(-42, llList2CSV(send));
}

vector scaleToSphere(vector v)
{
    float l = llVecMag(v);
    return r / l * v;
}

drawSide(vector bottomLeft, vector top, vector bottomRight)
{
    integer i;
    integer segments = subdivision + 1;
    vector dx = (bottomRight - bottomLeft) / segments;
    vector dy = (top - bottomLeft) / segments;
    for (i = 0; i < segments; i++) {
        integer j;
        for (j = 0; j < subdivision * 2 + 1 - 2 * i; j++) {
            if ((j % 2) == 0) {
                // even, draw left and bottom line
                integer l = j / 2;
                vector v1 = scaleToSphere(bottomLeft + l * dx + i * dy);
                vector v2 = scaleToSphere(bottomLeft + l * dx + (i+1) * dy);
                vector v3 = scaleToSphere(bottomLeft + (l+1) * dx + i * dy);
                drawLine(v1, v2);
                drawLine(v1, v3);
                drawTriangle(v1, v2, v3);
            } else {
                // odd, draw right line
                integer l = (j - 1) / 2;
                vector v1 = scaleToSphere(bottomLeft + l * dx + (i+1) * dy);
                vector v2 = scaleToSphere(bottomLeft + (l+1) * dx + i * dy);
                vector v3 = scaleToSphere(bottomLeft + (l+1) * dx + (i+1) * dy);
                drawLine(v1, v2);
                drawTriangle(v1, v2, v3);
            }
        }
    }
}

drawDome()
{
    float l2 = length / 2.0;
    vector bottomLeft = <-l2, -l2, 0.0>;
    vector topLeft = <-l2, l2, 0.0>;
    vector topRight = <l2, l2, 0.0>;
    vector bottomRight = <l2, -l2, 0.0>;
    vector top = <0, 0, length * llSqrt(6.0) / 3.0>;
    r = llVecMag(bottomLeft - topRight) / 2.0;
    drawSide(bottomLeft, top, bottomRight);
    drawSide(topLeft, top, bottomLeft);
    drawSide(topRight, top, topLeft);
    drawSide(bottomRight, top, topRight);
}

initialize()
{
    llSetText("Position at the center of the dome and touch.", <1, 0, 0>, 1.0);
    llSitTarget(<0.5, 0.0, 0.7>, ZERO_ROTATION);
    base = llGetPos();
}

default
{
    touch_start(integer total_number)
    {
        start = 0;
        initialize();
        drawDome();
        base.z += length + 1.0;
        move(base);
    }

    on_rez(integer start_param)
    {
        initialize();
    }
   
    state_entry()
    {
        initialize();
    }
}


Line Script:
{L_CODE}:
// One time scale script
// 2007 Copyright by Shine Renoir (fb@frank-buss.de)
// Use it for whatever you want, but keep this copyright notice
// and credit my name in notecards etc., if you use it in
// closed source objects
// Modified by Adelle Fitzgerald for OpenSim

integer handle;

default
{
    state_entry()
    {
        handle = llListen(-43, "", NULL_KEY, "" );
    }
   
    listen(integer channel, string name, key id, string message)
    {
        llSetScale((vector) message);
        llListenRemove(handle);
        llSleep(2);
        llRemoveInventory(llGetScriptName());
    }
   
    on_rez(integer param) {
        llResetScript();
    }
}


Triangle Script:
{L_CODE}:
// One time scale and shear script
// 2007 Copyright by Shine Renoir (fb@frank-buss.de)
// Use it for whatever you want, but keep this copyright notice
// and credit my name in notecards etc., if you use it in
// closed source objects
// Modified by Adelle Fitzgerald for OpenSim

integer handle;

default
{
    state_entry()
    {
        handle = llListen(-42, "", NULL_KEY, "" );
    }
   
    listen(integer channel, string name, key id, string message)
    {
        list tokens = llCSV2List(message);
        vector size = (vector) llList2String(tokens, 0);
        float shear = (float) llList2String(tokens, 1);
        llSetPrimitiveParams([
            PRIM_TYPE, PRIM_TYPE_BOX,
            0,  // hollow shape
            <0.0, 1.0, 0.0>,  // cut
            0.0,  // hollow
            <0.0, 0.0, 0.0>,  // twist
            <0.0, 1.0, 0.0>,  // taper
            <shear, 0.0, 0.0>,  // top shear
            PRIM_SIZE, size
        ]);
        llListenRemove(handle);
        llSleep(2);
        llRemoveInventory(llGetScriptName());
    }
   
    on_rez(integer param) {
        llResetScript();
    }
}

_________________
"Nothing lasts forever; It's scientific"
~David Byrne (Talking Heads)


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Fri Sep 03, 2010 7:11 pm 

Joined: Tue Jan 05, 2010 4:07 pm
Posts: 19
Thank you Adelle, nice Script :)

Regards
Slow


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Tue Sep 14, 2010 4:45 pm 
OSG Elite

Joined: Wed Aug 05, 2009 1:59 am
Posts: 417
Yesh, Awesome script! Thanks Adelle:)

(Is there a 'Remove-hundreds-of-domes-from-a-sim' script btw?)


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Wed Sep 15, 2010 12:03 pm 
OSG Elite
User avatar

Joined: Thu Dec 11, 2008 7:51 am
Posts: 392
Location: England UK
Oddball Otoole {L_WROTE}:
(Is there a 'Remove-hundreds-of-domes-from-a-sim' script btw?)


Nope! hehe

I did think about altering the line and triangle script to keep their listeners open and scripts intact until happy then you could either say something like /42die to kill the prim, and /42remscript to remove the script... but i didnt do this yet.

Reason I didnt is that I didn't want 3000 active listeners on my sim. What do you think?

_________________
"Nothing lasts forever; It's scientific"
~David Byrne (Talking Heads)


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Mon Nov 01, 2010 11:21 am 

Joined: Mon Nov 01, 2010 11:14 am
Posts: 2
Adelle Fitzgerald {L_WROTE}:
Oddball Otoole {L_WROTE}:
(Is there a 'Remove-hundreds-of-domes-from-a-sim' script btw?)


Nope! hehe

I did think about altering the line and triangle script to keep their listeners open and scripts intact until happy then you could either say something like /42die to kill the prim, and /42remscript to remove the script... but i didnt do this yet.

Reason I didnt is that I didn't want 3000 active listeners on my sim. What do you think?


Thanks for sharing this. I will try this script for sure. To remove say 3000 prims I would create one listener prim and once that listener activates it sends out a llMessageLinked to the rest of the 2999 prims at the same time by which is using link_message.


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Mon Nov 01, 2010 11:54 am 
OSG Elite
User avatar

Joined: Thu Dec 11, 2008 7:51 am
Posts: 392
Location: England UK
Jonathan Radikal {L_WROTE}:
Thanks for sharing this. I will try this script for sure. To remove say 3000 prims I would create one listener prim and once that listener activates it sends out a llMessageLinked to the rest of the 2999 prims at the same time by which is using link_message.


When you use the script, the prims are not linked so using llMessageLinked will not work, unless you link them of course. But linking 3000 prims.... hehe good luck! The most I have managed is about 1300 before my sim goes poof! It also gets to be a bit of a strain when you start linking nested link sets.

Also, from what I have noticed using opensim, llMessageLinked can put more of a strain on the simulator (CPU mainly) with the more prims you have linked so it really is a balancing act as to which works better. I personally think 3000 listeners would have less of an impact than sending a link message to 3000 prims.

Have a play about with it and if you do find anything, or any ways of removing the scripts effieiently then please do share :)

_________________
"Nothing lasts forever; It's scientific"
~David Byrne (Talking Heads)


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Mon Nov 01, 2010 3:29 pm 
Furious Typer
User avatar

Joined: Mon Aug 10, 2009 11:53 pm
Posts: 258
Well - it is OpenSim - so you could just have the prims... as they are created ... RegionSay their UUID and have the creation prim make a notecard and start stacking those prim UUIDs in their and then then nasty part is, just enable osConsoleCommand... and then you could simply kill each prim by UUID as you saw fit. You would want to ensure that you only enabled this command to your own personal key only, and keep your threat level at VeryLow.

This is how I have my region setup... any commands I want to use that are above VeryLow, I have setup using the prefix 'Allow_os<command> = <myUUIDhere>' and *NOT* simply '= true'. In this fashion, any script that calls these functions will fail if not being called by you specifically.

osConsoleCommand is very dangerous in the wrong hands, but in this instance is a good example of how useful it can really be. Only one listener required for the duration of the creation of the dome. After that, it is all 'behind the scenes'.

Just my 2c

Take care,
- Hap

_________________
Sorry, I was just thinking upon the immortal words of Socrates who said ... "I drank what?? ... "
- Real Genius


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Mon Nov 01, 2010 5:40 pm 

Joined: Mon Nov 01, 2010 11:14 am
Posts: 2
Well I played around with. I will share some of the stuff I did.

To get a half dome, remove the original dome builder script and put this in the dome builder box. Basically it counts until it's half way there and does a llResetScript().

{L_CODE}:
// Dome Builder
// 2007 Copyright by Shine Renoir (fb@frank-buss.de)
// Use it for whatever you want, but keep this copyright notice
// and credit my name in notecards etc., if you use it in
// closed source objects
// Modified by Adelle Fitzgerald for OpenSim

integer subdivision = 2; //Change for the amount of vertices
float length = 5.0; //Change this for the size of the dome
float lineWidth = 0.2; //'Thickness' of the lines
float triangleThickness = 0.05; //Thickness of the triangles
float delay = 0.1; //Delay between rezzing the prims and setting the properties - increase this if you experience 'bad' prims.
float initialDelay = 1.0; //Delay for the first few prims. Once the first few have rezzed it reverts to the delay above. Increase this if you experience 'bad' prims for the first few.

//Some good sizes to play with: subdevision = 2, length = 5 : subdevision = 3, length = 10 : subdevision = 4, length = 20 : subdevision = 5, length = 30
//And for something spectacular, subdevision = 18, length = 150 -- Do place the builder at the center of a region as this will pretty much fill it and create ~3600 prims in the process ;-)

vector base;
float r;
integer start;

move(vector destination)
{
   // llSetPos is limited to 10m distances,
   // so it is called until the target is reached
   //vector p = ZERO_VECTOR;
   //while (p.z != destination.z) {
   //    llSetPos(destination);
   //    p = llGetPos();
   //}
   
   //The original code above wouldn't work reliably in OpenSim, so as a workaround increase the 'ScriptDistanceLimitFactor' in opensim.ini to allow the prim to move more than the max of 10m. I set mine to 50 (ScriptDistanceLimitFactor = 50.0) to allow scripted prims to move upto 500m using llSetPos.
   llSetPos(destination);
}

drawLine(vector v1, vector v2)
{
   vector line = v2 - v1;
   vector pos = base + line / 2 + v1;
   float len = llVecMag(line);
   vector size = <lineWidth, lineWidth, len>;
   vector up = <0, 0, 1>;
   rotation rot = llRotBetween(up, llVecNorm(line));
   move(pos);
   llRezObject("Line", pos, ZERO_VECTOR, rot, 0);
   if (start < 6)
   {
       start += 1;
       llSleep(initialDelay);
   }
   else
   {
       llSleep(delay);
   }
   llSay(-43, (string) size);
}

drawTriangle(vector v1, vector v2, vector v3)
{
   // assuming a normal triangle: no zero area

   // make v1-v3 the longest side
   integer i = 0;
   for (i = 0; i < 2; i++) {
       float ax = llVecDist(v2, v3);
       float bx = llVecDist(v1, v3);
       float cx = llVecDist(v1, v2);
       if (ax > bx || cx > bx) {
           vector tmp = v1;
           v1 = v2;
           v2 = v3;
           v3 = tmp;
       }
   }
   
   // calculate side lengths
   float a = llVecDist(v2, v3);
   float b = llVecDist(v1, v3);
   float c = llVecDist(v1, v2);

   // b=b1+b2, a^2=h^2+b2^2, c^2=b1^2+h^2, solving:
   float b2 = (a*a + b*b - c*c)/2.0/b;
   float b1 = b - b2;
   float h = llSqrt(a*a - b2*b2);  // triangle height

   // calculate triangle height vector and shear value
   float hPosition = b1 / b;
   vector vb1 = (v3 - v1) * hPosition;
   vector vh = v2 - (v1 + vb1);
   float shear = hPosition - 0.5;

   // calculate position and rotation
   vector pos = base + v1 + (v3 - v1) / 2 + vh / 2;
   vector size = <b, triangleThickness, h>;
   vector up = <0.0, 0.0, 1.0>;
   rotation rot = llRotBetween(up, llVecNorm(vh));
   vector fwd = llVecNorm(v3 - v1);  // fwd is the base
   vector left = llVecNorm(vh);
   left = llVecNorm(left % fwd);  // "left" is cross product (orthogonal to base and left)
   rot = llAxes2Rot(fwd, left, fwd % left);  // calculate the needed rotation
   
   // create object
   llRezObject("Triangle", pos, ZERO_VECTOR, rot, 0);
   
   // set size and shear value
   list send = [size, shear ] ;
   if (start < 6)
   {
    counter++;
       start += 1;
       llSleep(initialDelay);     
   }
   else
   {
       counter++;
       llSleep(delay);
   }
   llSay(-42, llList2CSV(send));
    if(counter == 18)
  {
      llResetScript();
  }
}

vector scaleToSphere(vector v)
{
   float l = llVecMag(v);
   return r / l * v;
}

drawSide(vector bottomLeft, vector top, vector bottomRight)
{
   integer i;
   integer segments = subdivision + 1;
   vector dx = (bottomRight - bottomLeft) / segments;
   vector dy = (top - bottomLeft) / segments;
   for (i = 0; i < segments; i++) {
     
       integer j;
       for (j = 0; j < subdivision * 2 + 1 - 2 * i; j++) {
                 
           if ((j % 2) == 0) {
               // even, draw left and bottom line
               integer l = j / 2;
               vector v1 = scaleToSphere(bottomLeft + l * dx + i * dy);
               vector v2 = scaleToSphere(bottomLeft + l * dx + (i+1) * dy);
               vector v3 = scaleToSphere(bottomLeft + (l+1) * dx + i * dy);
               drawLine(v1, v2);
               drawLine(v1, v3);
               drawTriangle(v1, v2, v3);
           } else {
               // odd, draw right line
               integer l = (j - 1) / 2;
               vector v1 = scaleToSphere(bottomLeft + l * dx + (i+1) * dy);
               vector v2 = scaleToSphere(bottomLeft + (l+1) * dx + i * dy);
               vector v3 = scaleToSphere(bottomLeft + (l+1) * dx + (i+1) * dy);
               drawLine(v1, v2);
               drawTriangle(v1, v2, v3);
           }
       }
   }
}

integer counter = 0;

drawDome()
{
   float l2 = length / 1.0;
   vector bottomLeft = <-l2, -l2, 0.0>;
   vector topLeft = <-l2, l2, 0.0>;
   vector topRight = <l2, l2, 0.0>;
   vector bottomRight = <l2, -l2, 0.0>;
   vector top = <0, 0, length * llSqrt(6.0) / 3.0>;
   r = llVecMag(bottomLeft - topRight) / 2.0;
   drawSide(bottomLeft, top, bottomRight);
   drawSide(topLeft, top, bottomLeft);
   drawSide(topRight, top, topLeft);
   drawSide(bottomRight, top, topRight);
}

initialize()
{
   llSetText("Position at the center of the dome and touch.", <1, 0, 0>, 1.0);
   llSitTarget(<0.5, 0.0, 0.7>, ZERO_ROTATION);
   base = llGetPos();
}

default
{
   touch_start(integer total_number)
   {
       counter = 0;
       start = 0;
       initialize();
       drawDome();
       base.z += length + 1.0;
       move(base);
   }

   on_rez(integer start_param)
   {
       initialize();
   }
   state_entry()
   {
       initialize();
   }
}


For me it was only possible to remove small domes using llListen() and normal linkage. When you link prims and one prim receive the llDie() all prims are removed. Maybe future versions of OpenSim are able to handle greater number of linkages. So in other words only one script is necessary to remove a linked dome.

If using example below type /2 remove in chat to remove dome.
I'm using llSetAlpha() to make it invisible.
Create a box named remove and put this code in it:

{L_CODE}:
default
{
   state_entry()
   {
       llSay(0, "Script running");
       llSetAlpha(0.0, ALL_SIDES);
       llListen( 2, "", "", "" );
   }
listen( integer chan, string name, key id, string msg )
{     
       if( chan == 2 )
       {
           
        if (msg == "remove")
        {
              llDie();
        } 
       }
  }
}


In order to have the remove box rezzed while it's building the dome, we need to use this script instead of the original dome builder script.

{L_CODE}:
// Dome Builder
// 2007 Copyright by Shine Renoir (fb@frank-buss.de)
// Use it for whatever you want, but keep this copyright notice
// and credit my name in notecards etc., if you use it in
// closed source objects
// Modified by Adelle Fitzgerald for OpenSim

integer subdivision = 2; //Change for the amount of vertices
float length = 5.0; //Change this for the size of the dome
float lineWidth = 0.2; //'Thickness' of the lines
float triangleThickness = 0.05; //Thickness of the triangles
float delay = 0.1; //Delay between rezzing the prims and setting the properties - increase this if you experience 'bad' prims.
float initialDelay = 1.0; //Delay for the first few prims. Once the first few have rezzed it reverts to the delay above. Increase this if you experience 'bad' prims for the first few.

//Some good sizes to play with: subdevision = 2, length = 5 : subdevision = 3, length = 10 : subdevision = 4, length = 20 : subdevision = 5, length = 30
//And for something spectacular, subdevision = 18, length = 150 -- Do place the builder at the center of a region as this will pretty much fill it and create ~3600 prims in the process ;-)

vector base;
float r;
integer start;

move(vector destination)
{
   // llSetPos is limited to 10m distances,
   // so it is called until the target is reached
   //vector p = ZERO_VECTOR;
   //while (p.z != destination.z) {
   //    llSetPos(destination);
   //    p = llGetPos();
   //}
   
   //The original code above wouldn't work reliably in OpenSim, so as a workaround increase the 'ScriptDistanceLimitFactor' in opensim.ini to allow the prim to move more than the max of 10m. I set mine to 50 (ScriptDistanceLimitFactor = 50.0) to allow scripted prims to move upto 500m using llSetPos.
   llSetPos(destination);
}

drawLine(vector v1, vector v2)
{
   vector line = v2 - v1;
   vector pos = base + line / 2 + v1;
   float len = llVecMag(line);
   vector size = <lineWidth, lineWidth, len>;
   vector up = <0, 0, 1>;
   rotation rot = llRotBetween(up, llVecNorm(line));
   move(pos);
   llRezObject("Line", pos, ZERO_VECTOR, rot, 0);
   if (start < 6)
   {
       start += 1;
       llSleep(initialDelay);
   }
   else
   {
       llSleep(delay);
   }
   llSay(-43, (string) size);
}

drawTriangle(vector v1, vector v2, vector v3)
{
   // assuming a normal triangle: no zero area

   // make v1-v3 the longest side
   integer i = 0;
   for (i = 0; i < 2; i++) {
       float ax = llVecDist(v2, v3);
       float bx = llVecDist(v1, v3);
       float cx = llVecDist(v1, v2);
       if (ax > bx || cx > bx) {
           vector tmp = v1;
           v1 = v2;
           v2 = v3;
           v3 = tmp;
       }
   }
   
   // calculate side lengths
   float a = llVecDist(v2, v3);
   float b = llVecDist(v1, v3);
   float c = llVecDist(v1, v2);

   // b=b1+b2, a^2=h^2+b2^2, c^2=b1^2+h^2, solving:
   float b2 = (a*a + b*b - c*c)/2.0/b;
   float b1 = b - b2;
   float h = llSqrt(a*a - b2*b2);  // triangle height

   // calculate triangle height vector and shear value
   float hPosition = b1 / b;
   vector vb1 = (v3 - v1) * hPosition;
   vector vh = v2 - (v1 + vb1);
   float shear = hPosition - 0.5;

   // calculate position and rotation
   vector pos = base + v1 + (v3 - v1) / 2 + vh / 2;
   vector size = <b, triangleThickness, h>;
   vector up = <0.0, 0.0, 1.0>;
   rotation rot = llRotBetween(up, llVecNorm(vh));
   vector fwd = llVecNorm(v3 - v1);  // fwd is the base
   vector left = llVecNorm(vh);
   left = llVecNorm(left % fwd);  // "left" is cross product (orthogonal to base and left)
   rot = llAxes2Rot(fwd, left, fwd % left);  // calculate the needed rotation
   
   // create object
   llRezObject("Triangle", pos, ZERO_VECTOR, rot, 0);
   
   // set size and shear value
   list send = [size, shear ] ;
   if (start < 6)
   {
    counter++;
       start += 1;
       llSleep(initialDelay);     
   }
   else
   {
       counter++;
       llSleep(delay);
   }
   llSay(-42, llList2CSV(send));
    if(counter == 36)
  {
      llRezObject("remove", llGetPos() + <0, 0, 1.5>, ZERO_VECTOR, ZERO_ROTATION, 42);
  }
}

vector scaleToSphere(vector v)
{
   float l = llVecMag(v);
   return r / l * v;
}

drawSide(vector bottomLeft, vector top, vector bottomRight)
{
   integer i;
   integer segments = subdivision + 1;
   vector dx = (bottomRight - bottomLeft) / segments;
   vector dy = (top - bottomLeft) / segments;
   for (i = 0; i < segments; i++) {
     
       integer j;
       for (j = 0; j < subdivision * 2 + 1 - 2 * i; j++) {
                 
           if ((j % 2) == 0) {
               // even, draw left and bottom line
               integer l = j / 2;
               vector v1 = scaleToSphere(bottomLeft + l * dx + i * dy);
               vector v2 = scaleToSphere(bottomLeft + l * dx + (i+1) * dy);
               vector v3 = scaleToSphere(bottomLeft + (l+1) * dx + i * dy);
               drawLine(v1, v2);
               drawLine(v1, v3);
               drawTriangle(v1, v2, v3);
           } else {
               // odd, draw right line
               integer l = (j - 1) / 2;
               vector v1 = scaleToSphere(bottomLeft + l * dx + (i+1) * dy);
               vector v2 = scaleToSphere(bottomLeft + (l+1) * dx + i * dy);
               vector v3 = scaleToSphere(bottomLeft + (l+1) * dx + (i+1) * dy);
               drawLine(v1, v2);
               drawTriangle(v1, v2, v3);
           }
       }
   }
}

integer counter = 0;

drawDome()
{
   float l2 = length / 1.0;
   vector bottomLeft = <-l2, -l2, 0.0>;
   vector topLeft = <-l2, l2, 0.0>;
   vector topRight = <l2, l2, 0.0>;
   vector bottomRight = <l2, -l2, 0.0>;
   vector top = <0, 0, length * llSqrt(6.0) / 3.0>;
   r = llVecMag(bottomLeft - topRight) / 2.0;
   drawSide(bottomLeft, top, bottomRight);
   drawSide(topLeft, top, bottomLeft);
   drawSide(topRight, top, topLeft);
   drawSide(bottomRight, top, topRight);
}

initialize()
{
   llSetText("Position at the center of the dome and touch.", <1, 0, 0>, 1.0);
   llSitTarget(<0.5, 0.0, 0.7>, ZERO_ROTATION);
   base = llGetPos();
}

default
{
   touch_start(integer total_number)
   {
       counter = 0;
       start = 0;
       initialize();
       drawDome();
       base.z += length + 1.0;
       move(base);
   }

   on_rez(integer start_param)
   {
       initialize();
   }
   
   state_entry()
   {
       initialize();
   }
}


Then finally copy the remove box into inventory and put it into the dome builder box. Create the dome and link all prims. Happy "doming"!


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Tue Nov 02, 2010 12:26 am 
Furious Typer
User avatar

Joined: Mon Aug 10, 2009 11:53 pm
Posts: 258
Ok - so here is my take on these scripts. Sorry I just couldn't help myself. I love all the os commands :)

So... I left everything as Adelle originally posted with just two changes to her 'Line' and 'Triangle' Scripts, and they are as follows:

In both scripts you will see a line that says:
{L_CODE}:
llSleep(2);


You need to add to that a line just below that says:
{L_CODE}:
llSay(-25,llGetKey());   

llRegionSay(-25,llGetKey()) would probably be better for huge domes

Now then a precursor to the following two scripts. Use them at your own risk, and I highly advise you to use caution and common sense when implementing these functions.
You will need to enable the following functions in your OpenSim.ini fiel for these scripts to work:
Allow_osMakeNotecard = <yourUUIDhere>
Allow_osConsoleCommand = <yourUUIDhere>
I HIGHLY recommend using this format, rather than setting your threat level to the ridiculous as you would set yourself up for problems.

Now then onto the fun part.

Drop the following into a Prim, and click it BEFORE you start making your dome. It will start listening for all those prims to shout out their uuids as they are being made. Once your dome is built. Click it again, and it will give you a notecard containing all of the uuid for every prim in that new dome :)

{L_CODE}:
integer switch = FALSE;
string uuidPkg = "";
integer handle;

default
{
    state_entry()
    {
        handle = llListen (-25,"",NULL_KEY,"");
    }
   
    touch_start(integer num)
    {
        if (switch == FALSE)
        {
            uuidPkg = "";
            llOwnerSay("Channel open, now recording...");
            switch = TRUE;
        }
        else if (switch == TRUE)
        {
            llOwnerSay("Closing Channel, compiling information...");
            osMakeNotecard("KillDomeObjNote",uuidPkg);
            llOwnerSay("Notecard has been created.");
            llGiveInventory(llGetOwner(),"KillDomeObjNote");
            llRemoveInventory("KillDomeObjNote");
            switch = FALSE;
        }
    } 
   
    listen (integer channel, string name, key id, string msg)
    {
        if (msg!="")
        {
            uuidPkg += msg+"\n";
        }
    }
}


Drop this next script and your newly made notecard into another prim, and click it. Do not click it until you are ready to watch your dome go bye-bye!

{L_CODE}:
string kQuery;
integer iLine = 0;
default
{
    state_entry()
    {
        llSetText("Dome Removal. Touch to start.\nTHIS CANNOT BE UNDONE!",<1,0,0>,1);
    }
    touch_start(integer num)
    {
        iLine = 0;
        if (llGetInventoryNumber(INVENTORY_ALL) > 1)
        {
            llOwnerSay("Reading in Notecard...");
            kQuery = llGetNotecardLine("KillDomeObjNote", iLine);
        }
    }
    dataserver(key query_id, string data)
    {
        if (data == EOF)                                       // If we reach the ond of the file, exit out.
            {   
                llOwnerSay("No more lines in notecard, read " + (string)iLine + " lines.");
            }
        else
            {   
                if ( data != "" )                              //If we have empty lines somewhere.. ignore them
                {                                             
                    osConsoleCommand ("kill uuid "+data);      //The nasty bits - send the prim uuid to the console to be killed!
                    llSleep(.2);
                }
               
                ++iLine;                                              // Increment for next line
                kQuery = llGetNotecardLine("KillDomeObjNote", iLine); // Grab it.
            }
    }
}


I am sure there are ways you could combine all of this easily into a nice simple hud, or part of it into Adelle's original scripts, but this is a down and dirty easy way to make very minor changes to the original, and once the notecard is made... there is ZERO load on the system, no scripts laying around, nothing. Until such time as you decide to drop a prim on the ground, put a script and notecard in there, click it and delete your dome.

This has been successfully tested on 4 different sized domes on a standalone here on my home server. I have not yet tried this on my region attached to OSGrid. I will update this post at some point when I get the chance to do so.

Take care,
- Hap

_________________
Sorry, I was just thinking upon the immortal words of Socrates who said ... "I drank what?? ... "
- Real Genius


Top
 Profile  
 
 Post subject: Re: Geodesic Dome Builder Script
PostPosted: Sun Dec 12, 2010 5:17 am 

Joined: Sun Dec 12, 2010 4:24 am
Posts: 4
This thread is very interesting, I will play with simple examples as I am a real fan of domes including geodesic ones. Scripting the removal of the prims is of course a nice elegant way to do it and I guess that's the way to go, but there is a way that is maybe easier if it works for this many prims. Just cam to an overhead view, right click on the ground and select the arrow tool, draw a box enclosing the prims to select them all at once, then finally just delete or return the selected prims. It could be done in chunks if osgrid cannot select that many prims at once. This technique allows me to select most ungrouped prim collections all at once without also selecting other objects behind them.

Is this too obvious or am i missing something? Oh, and thanks for posting your work!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post a new topicPost a reply Page 1 of 2   [ 18 posts ]
Go to page 1, 2  Next


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
610nm Style by Daniel St. Jules of Gamexe.net