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) |
|