Difference between revisions of "User:Lum Pfohl/LSL Goodies/Snippet/Align Prim Between Two Points"
m |
|||
Line 5: | Line 5: | ||
==Align Prim Between Two Points== | ==Align Prim Between Two Points== | ||
<div style="padding: 0.5em"> | <div style="padding: 0.5em"> | ||
Occasionally, I have a need to rez a prim such as a cylinder | 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... | |||
<B>This is the main rezzer script to go into a simple prim</B> | |||
<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, "Hello, Avatar!"); | |||
} | |||
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> | |||
<B>Put the following script into a small SPHERE object and name it 'sphere' and add it to the rezzer object inventory.</B> | |||
<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> | |||
<B>Put the following script into a CYLINDER object and name it 'pentaedge' and add it to the rezzer object inventory.</B> | |||
<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> | |||
</div> | </div> | ||
</div> | </div> |
Revision as of 09:22, 22 September 2009
Align Prim Between Two PointsOccasionally, 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.
// 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 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); }
state_entry() { llSay(0, "Hello, Avatar!"); } 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>
// 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) |
|