# User:Lum Pfohl/LSL Goodies/Snippet/Align Prim Between Two Points

## 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() {
}

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 Click to Enlarge External Wiki Contributions Related topics edit