Tuesday, December 26, 2006

LoopRez v0.6

LoopRez v0.6, by Ged Larsen, 2006 Dec 20

This script helps place multiple copies of an object in a circular or elliptical shape. Some uses might be to help place the panels of a skirt or beads of a necklace.

Natalia Zelmanov has written an excellent tutorial on using the script to create skirts

Each object faces "outwards" in the ellipse. Further, the objects can optionally be made to flare outwards (i.e., panels of a skirt that hang straight down vs. poofing outwards).

QUICK START:
- chose an object to use and name it "Object"
- drag the "Object" from your inventory into the contents of the prim containing the LoopRez script
- click on the prim containing the LoopRez script
- watch it generate an ellipse with multiple copies of your object

Configurable settings:
- the object to be used
- the number of copies of the object in the completed ellipse
- the radius of the ellipse along the X-axis (front-to-back)
- the radius of the ellipse along the Y-axis (side-to-side)
- the angle that each panel flares outwards

Advanced settings:
- introducing a "bend" to the ellipse, to form a saddle shape that might be helpful for necklaces
- correcting the initial rotation of the object
- adjusting the location where the ellipse of objects will be rezzed

Have fun! Please let me know if you find the script helpful (I'd love to see pics of any designs that benefited from the script), or if you have any suggestions.

====

Please post any comments or suggestions you might have:

PHP Code:
////////////////////////////////////////////////////////////////////////////////
// LoopRez v0.6, by Ged Larsen, 20 December 2006
//
// - rez a number of objects in an ellipse, whose size is determined by xRadius and yRadius
// - all facing "outwards", along a tangent to the ellipse
// - can set how much the objects flare outwards
// - properly handles object rotation corrections (for example, X-axis 180 degree rotation helps for flexi-prim skirts)
// - can also get a 'saddle' bend, to generate a bend that might help for necklaces (from Ariane Brodie)
//
// To use:
// 1) create a prim that will contain this script and the object to use
// 2) put the script into the prim
// 3) create an object that will be used, and name it "Object"
// 4) put "Object" into the prim containing the script, by dragging it from your inventory
// 5) get out of Edit Mode, and touch the prim
//
// Random note:
// - this version does NOT insure equal spacing of objects along the perimeter of the ellipse
// - i.e., objects "bunch up" at the long ends of an ellipse; the effect should be acceptable for non-extreme ellipses
// - even spacing of objects can be accomplished, but requires simulation of integral calculus, which slows down the script
//
// References:
// - tangent formulas from: http://mathworld.wolfram.com/Ellipse.html


////////////////////////////////////////////////////////////////////////////////
// CONFIGURATION PARAMETERS, change these to your liking

string objectName = "Object"; // object to use; will need to be in the inventory of the prim containing this script
integer numObjects = 12; // how many objects
float xRadius = 0.6; // ellipse x-axis radius in meters
float yRadius = 1.0; // ellipse y-axis radius in meters
float flareAngle = 30.0; // how many DEGREES the bottom of object will flare outwards, the "poof" factor
float bendCoefficient = 0.0; // makes a "saddle shape", bends DOWN this number of meters at extremes of X-axis
vector rotOffset = <0.0, 0.0, 0.0>; // rotation offset in DEGREES -- fixes the rotation of ALL objects; for flexi prims, often you will want <180.0,>
vector posOffset = <0.0, 0.0, 2.0>; // position offset



////////////////////////////////////////////////////////////////////////////////
// No need to mess with anything below here

makeLoop()
{
integer n; // which object is being placed
float theta; // angle in radians
vector pos; // position
rotation rot; // rotation in quaternion format

for(n = 0; n < numObjects; n++) {

theta = TWO_PI * ( (float)n / (float)numObjects );

pos.x = xRadius * llCos(theta); // ellipse: 2x xRadius meters wide
pos.y = yRadius * llSin(theta); // ellipse: 2x yRadius meters wide
pos.z = -bendCoefficient*llCos(theta)*llCos(theta); // saddle shape, bending downwards on X-axis
pos = pos + llGetPos() + posOffset;

rot = llEuler2Rot(<rotOffset.x*DEG_TO_RAD, rotOffset.y*DEG_TO_RAD, rotOffset.z*DEG_TO_RAD>); // user-chosen rotation offset correction
rot = rot * llEuler2Rot(<0, -1*flareAngle*DEG_TO_RAD, 0>); // flare generation (poof)

// the following make the objects face outwards properly for an ellipse; using theta alone is only correct for a circle
// the scary formula calculates a unit vector TANGENTIAL to the ellipse, and llRotBetween is used to figure out how much the object needs to rotate to lie parallel to the tangent
rot = rot * llRotBetween(<0.0,1.0,0.0>, <-1.0 * xRadius * llSin(theta) / ( llSqrt ( (yRadius*yRadius * llCos(theta) * llCos(theta)) + (xRadius*xRadius * llSin(theta) * llSin(theta))) ),yRadius * llCos(theta) / ( llSqrt ( (yRadius*yRadius * llCos(theta) * llCos(theta)) + (xRadius*xRadius * llSin(theta) * llSin(theta))) ),0.0>);
if (
n== (numObjects/2) ) // LSL's implementation of llRotBetween at theta = pi radians is reversed at 180 degrees, so this manually corrects it
rot = rot * llEuler2Rot( <0,PI,0> );

llRezObject(objectName, pos, ZERO_VECTOR, rot, 0);
}
}

default
{
touch_start(integer total_number)
{
if (
llDetectedOwner(0) == llGetOwner())
{
makeLoop();
}
}
}



====

Incidentally, LoopRez is a fairly bare-bones script. I'm also working on a rather more involved version, which is much more interactive and flexible in what it can do. It's more fun to play with as well, watching the skirt panels zip around, rotate, and even morph, in response to voice commands.