Difference between revisions of "User:Lum Pfohl/LSL Goodies/Snippet/Align Prim Between Two Points"

From Second Life Wiki
Jump to navigation Jump to search
m
 
Line 95: Line 95:
{
{
   state_entry() {
   state_entry() {
     llSay(0, "Hello, Avatar!");
     llSay(0, "Rezzer Ready!");
   }
   }
    
    

Latest revision as of 12:41, 22 September 2009

Align Prim Between Two Points

Occasionally, I have a need to rez a prim such as a cylinder or a stick between two points, lined up in that direction. The math for it is ridiculously easy, but maddeningly difficult to get right. So I've documented it below.


<lsl> rez (vector v1, vector v2) {

 // Determine the midpoint between the two vectors to rez the prim
 vector rezPos = (v1 + v2) / 2.0 + llGetPos();
 
 // Setup for determining the rotation at which the prim will be rezzed
 
 // First, apply any constant transformations to the prim. In the example
 // below, the rezzed prim is a cylinder (shaped into a 'stick'). Tilt
 // the 'stick' which is aligned vertically by default - sideways by
 // 90 degrees (or PI/2)
 rotation rezRot = llEuler2Rot(<0.0, PI_BY_TWO, 0.0>)
 
 // Get a Unit Vector that points along the space v1 -> v2
 vector difference = llVecNorm(v2 - v1);
 
 // Now calculate the new prim rotation by the 'angle' made between
 // an Unit Vector in the X-axis, and the one calculated above. This value
 // will be multiplied (we multiply rotations values to rotate the previous
 // value). This aligns the prim lengthwise between the two points, v1 v2
 rezRot *= llRotBetween(<1.0, 0.0, 0.0>, difference);
 
 // Optionally, we will calculate the distance between the two points and
 // send it to the rezzed object as a value. Unfortunately, we can only
 // send integer values, but by multiplying the float value by 1000, we
 // can capture sufficient significant digits to be passed as an integer
 // The rezzed prim will have an 'on_rez(integer param)' event, which
 // can take the incoming param value and cast it to a float then divide
 // by 1000.0 to get the length.
 integer resLength = (integer)(llVecMag(v2 - v1) * 1000.0);
 
 // All this setup - now we finally rez the prim. The ZERO_VECTOR value
 // is provided as the rezzed speed. We don't want our prim to fly away.
 // The rezzed object is called 'pentaedge' in my example.
 llRezObject("pentaedge", rezPos, ZERO_VECTOR, rezRot, resLength);

} </lsl>


This is handy if you'd like to rez geometric shapes of your own. Below is a series of scripts to rez a Dodecahedron above the rezzer...

This is the main rezzer script to go into a simple prim <lsl> vector offset = <0.0, 0.0, 2.0>;

rez (vector v1, vector v2) {

 // Determine the midpoint between the two vectors to rez the prim
 vector rezPos = (v1 + v2) / 2.0 + llGetPos();


 // Setup for determining the rotation at which the prim will be rezzed
 // First, apply any constant transformations to the prim.  In the example
 // below, the rezzed prim is a cylinder (shaped into a 'stick').  Tilt
 // the 'stick' which is aligned vertically by default - sideways by
 // 90 degrees (or PI/2)
 rotation rezRot = llEuler2Rot(<0.0, PI_BY_TWO, 0.0>);
 // Get a Unit Vector that points along the space   v1 -> v2
 vector difference = llVecNorm(v2 - v1);
 // Now calculate the new prim rotation by the 'angle' made between
 // an Unit Vector in the X-axis, and the one calculated above.  This value
 // will be multiplied (we multiply rotations values to rotate the previous
 // value).  This aligns the prim lengthwise between the two points, v1 v2
 rezRot *= llRotBetween(<1.0, 0.0, 0.0>, difference);
 // Optionally, we will calculate the distance between the two points and
 // send it to the rezzed object as a value.  Unfortunately, we can only
 // send integer values, but by multiplying the float value by 1000, we
 // can capture sufficient significant digits to be passed as an integer
 // The rezzed prim will have an 'on_rez(integer param)' event, which
 // can take the incoming param value and cast it to a float then divide
 // by 1000.0 to get the length.
 integer resLength = (integer)(llVecMag(v2 - v1) * 1000.0);
 // All this setup - now we finally rez the prim.  The ZERO_VECTOR value
 // is provided as the rezzed speed.  We don't want our prim to fly away.
 // The rezzed object is called 'pentaedge' in my example.
 llRezObject("pentaedge", rezPos, ZERO_VECTOR, rezRot, resLength);

}


default {

 state_entry() {
   llSay(0, "Rezzer Ready!");
 }
 
 touch_start(integer total_number) {
   
   // define the vertices
   vector v0  = < 0.607,  0.000,  0.795> + offset;
   vector v1  = < 0.188,  0.577,  0.795> + offset;
   vector v2  = <-0.491,  0.357,  0.795> + offset;
   vector v3  = <-0.491, -0.357,  0.795> + offset;
   vector v4  = < 0.188, -0.577,  0.795> + offset;
   vector v5  = < 0.982,  0.000,  0.188> + offset;
   vector v6  = < 0.304,  0.934,  0.188> + offset;
   vector v7  = <-0.795,  0.577,  0.188> + offset;
   vector v8  = <-0.795, -0.577,  0.188> + offset;
   vector v9  = < 0.304, -0.934,  0.188> + offset;
   vector v10 = < 0.795,  0.577, -0.188> + offset;
   vector v11 = <-0.304,  0.934, -0.188> + offset;
   vector v12 = <-0.982,  0.000, -0.188> + offset;
   vector v13 = <-0.304, -0.934, -0.188> + offset;
   vector v14 = < 0.795, -0.577, -0.188> + offset;
   vector v15 = < 0.491,  0.357, -0.795> + offset;
   vector v16 = <-0.188,  0.577, -0.795> + offset;
   vector v17 = <-0.607,  0.000, -0.795> + offset;
   vector v18 = <-0.188, -0.577, -0.795> + offset;
   vector v19 = < 0.491, -0.357, -0.795> + offset;
   // res spheres in the vertices    
   llRezObject("sphere", llGetPos() + v0 , ZERO_VECTOR, ZERO_ROTATION, 0 );
   llRezObject("sphere", llGetPos() + v1 , ZERO_VECTOR, ZERO_ROTATION, 1 );
   llRezObject("sphere", llGetPos() + v2 , ZERO_VECTOR, ZERO_ROTATION, 2 );
   llRezObject("sphere", llGetPos() + v3 , ZERO_VECTOR, ZERO_ROTATION, 3 );
   llRezObject("sphere", llGetPos() + v4 , ZERO_VECTOR, ZERO_ROTATION, 4 );
   llRezObject("sphere", llGetPos() + v5 , ZERO_VECTOR, ZERO_ROTATION, 5 );
   llRezObject("sphere", llGetPos() + v6 , ZERO_VECTOR, ZERO_ROTATION, 6 );
   llRezObject("sphere", llGetPos() + v7 , ZERO_VECTOR, ZERO_ROTATION, 7 );
   llRezObject("sphere", llGetPos() + v8 , ZERO_VECTOR, ZERO_ROTATION, 8 );
   llRezObject("sphere", llGetPos() + v9 , ZERO_VECTOR, ZERO_ROTATION, 9 );
   llRezObject("sphere", llGetPos() + v10, ZERO_VECTOR, ZERO_ROTATION, 10);
   llRezObject("sphere", llGetPos() + v11, ZERO_VECTOR, ZERO_ROTATION, 11);
   llRezObject("sphere", llGetPos() + v12, ZERO_VECTOR, ZERO_ROTATION, 12);
   llRezObject("sphere", llGetPos() + v13, ZERO_VECTOR, ZERO_ROTATION, 13);
   llRezObject("sphere", llGetPos() + v14, ZERO_VECTOR, ZERO_ROTATION, 14);
   llRezObject("sphere", llGetPos() + v15, ZERO_VECTOR, ZERO_ROTATION, 15);
   llRezObject("sphere", llGetPos() + v16, ZERO_VECTOR, ZERO_ROTATION, 16);
   llRezObject("sphere", llGetPos() + v17, ZERO_VECTOR, ZERO_ROTATION, 17);
   llRezObject("sphere", llGetPos() + v18, ZERO_VECTOR, ZERO_ROTATION, 18);
   llRezObject("sphere", llGetPos() + v19, ZERO_VECTOR, ZERO_ROTATION, 19);
   // Rez the edges using the above function
   rez(v0, v1);
   rez(v1, v2);
   rez(v2, v3);
   rez(v3, v4);
   rez(v4, v0);
   rez(v0, v5);
   rez(v1, v6);
   rez(v2, v7);
   rez(v3, v8);
   rez(v4, v9);
   rez(v5, v10);
   rez(v6, v10);
   rez(v6, v11);
   rez(v7, v11);
   rez(v7, v12);
   rez(v8, v12);
   rez(v8, v13);
   rez(v9, v13);
   rez(v9, v14);
   rez(v5, v14);
   rez(v10, v15);
   rez(v11, v16);
   rez(v12, v17);
   rez(v13, v18);
   rez(v14, v19);
   rez(v15, v16);
   rez(v16, v17);
   rez(v17, v18);
   rez(v18, v19);
   rez(v19, v15);
 }

} </lsl>

Put the following script into a small SPHERE object and name it 'sphere' and add it to the rezzer object inventory. <lsl> default {

 // Script to go into a 'sphere' object.  Name of object must be "sphere"
 
 // Upon being rezzed, display a number above the prim for 90 seconds 
 on_rez(integer parm) {
 	llSetText((string)parm, <1.0, 1.0, 1.0>, 1.0);
 	llSetTimerEvent(90.0);
 }
 
 // After 90 seconds, clear the text and delete the script
 timer() {
 	llSetText("", <1.0, 1.0, 1.0>, 1.0);
 	llSetTimerEvent(0.0);
 	llRemoveInventory("New Script");
 }

} </lsl>


Put the following script into a CYLINDER object and name it 'pentaedge' and add it to the rezzer object inventory. <lsl> default {

 // Script to go into a 'cylinder' object.  Name of object must be "pentaedge"
 // Upon being rezzed, set the length of the
 on_rez(integer parm) {
   // If we've rezzed the prim without a parameter (like from the inventory)
   // then do nothing.  Else set the prim's dimensions and delete the script
   if (parm != 0) {
     // Take the incoming length coded as an integer (from the rez() function above)
     // and convert it back to a float value
     vector length = (float)parm / 1000.0;
     // Set the prim's (dimension to be 0.05 diameter by 'length' meters
     llSetPrimitiveParams([PRIM_SIZE, <0.05, 0.05, length>]);
     // Delete this script
     llRemoveInventory("New Script");
   }
 }

} </lsl>

Lum Pfohl 13:53, 21 September 2009 (UTC)

Lum's Quick Links
LumSelfPortrait.jpg
Click to Enlarge


Related topics

edit