User:Lum Pfohl/LSL Goodies/Snippet/Align Prim Between Two Points
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, "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>
// 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) |
|