Edge Rotate Function
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
03-10-2007 16:54
heyas; ged wrote a nifty little function that rotates an object on its z edge. which will no doubt work for my flappy flexi wings.... ::has to get back to that sometime soon!:: but, i thought maybe i could expand it and... well, make it do more. so i did, and this is what i came up with. HOWEVER, i only works if the prim is not rotated, or sometimes if it is only rotated on one axis. once it starts getting rotated more, simple x rotations start getting translated into y rotations and other crap which i just can't handle. if anybody wants to tinker with it and make it work perfectly all the time -- good luck! but that would be nice. //--edge rotate originally by ged //--expanded by bloodsong //--not very reliable unless prims aren't rotated much to start
//--side constants. pos is towards arrow point, neg is towards arrow butt integer X_POS = 1; integer X_NEG = 2; integer Y_POS = 3; integer Y_NEG = 4; integer Z_POS = 5; integer Z_NEG = 6;
//--axis constants integer X_AXIS = 1; integer Y_AXIS = 2; integer Z_AXIS = 3;
//--RotFromEdge: (angle, edge, axis) //-- input your degrees in normal everyday degrees //-- input what edge you want the axis on //-- and which axis you want to rotate about RotFromEdge(float fAngle, integer iSide, integer iAxis) { //--part one initial setup vector size = llGetScale(); //--gets length of sides to find edges. vector currentRot = llRot2Euler(llGetLocalRot()); rotation desiredRot; vector rotOriginBefore; //--adjust for different axes and edges if(iAxis == X_AXIS) { currentRot.x = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } else if (iAxis == Y_AXIS) { currentRot.y = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } else if (iAxis == Z_AXIS) { currentRot.z = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } if(iSide == X_POS) { rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * size.x / 2.0); } else if (iSide == Y_POS) { rotOriginBefore = (llRot2Left(llGetLocalRot()) * size.y / 2.0); } else if (iSide == Z_POS) { rotOriginBefore = (llRot2Up(llGetLocalRot()) * size.z / 2.0); } else if (iSide == X_NEG) { rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * (size.x / -2)); } else if (iSide == Y_NEG) { rotOriginBefore = (llRot2Left(llGetLocalRot()) * (size.y / -2)); } else if (iSide == Z_NEG) { rotOriginBefore = (llRot2Up(llGetLocalRot()) * (size.z / -2)); } //--part two, more calculations rotation newLocalRot = desiredRot * llGetLocalRot(); vector rotOriginAfter; //--change from defaults, if needed if(iSide == X_POS) { rotOriginAfter = (llRot2Fwd(newLocalRot) * size.x / 2.0); } else if (iSide == Y_POS) { rotOriginAfter = (llRot2Left(newLocalRot) * size.y / 2.0); } else if (iSide == Z_POS) { rotOriginAfter = (llRot2Up(newLocalRot) * size.z / 2.0); } else if (iSide == X_NEG) { rotOriginAfter = (llRot2Fwd(newLocalRot) * (size.x / -2)); } else if (iSide == Y_NEG) { rotOriginAfter = (llRot2Left(newLocalRot) * (size.y / -2)); } else if (iSide == Z_NEG) { rotOriginAfter = (llRot2Up(newLocalRot) * (size.z / -2)); }
//--part 3, apply the rotation llSetPrimitiveParams([PRIM_POSITION, llGetLocalPos() + rotOriginBefore - rotOriginAfter, PRIM_ROTATION, newLocalRot]);
}
default { touch_start(integer num) { //--this is just a test to see if it works. this loops it around in a complete circle. integer n; for (n=0; n<12; ++n) { RotFromEdge(30.0, Z_NEG, X_AXIS); } } }
|
Ged Larsen
thwarted by quaternions
Join date: 4 Dec 2006
Posts: 294
|
03-10-2007 17:54
The main reason I never expanded my code snippet was that it's very difficult to make generalizable. Sizes in the X, Y, and, Z dimensions are no longer accurate, if you have prim cuts / twists / skews, etc.
Calculating prim dimensions and the relative change of the "prim center" based on the primitive parameters -- now, that would be the true challenge.
_____________________
- LoopRez, flexi prim skirt generating tool - LinkRez, a necklace chain generator
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
03-15-2007 07:07
heh;
well, if i could cut the prim in half, i wouldn't have to rotate it from the edge now, would i? ;) but yeah, finding an edge on a mutated prim would be a pain. and calculating it from cuts and twists and... WAY too much math for me!
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
Edge Rotation Fixed (almost works, but...)
03-16-2007 06:20
heyas; okay, i found a MAJOR flaw in my function, which has to do with the start values for calculating the rots. ged just used 0's on his non-active axes, and i thought that would only work if the object wasn't rotated to start. and that i would have to start with the current rotation. well, turns out i was wrong. only one line change: vector currentRot = <0.0,0.0,0.0>; now it works, no matter how you rotate the fool prim to start. yay! the bad news is, it TOTALLY fails to work right if the prim is a child of anything. ::sob:: also as noted above, not 100% accurate for figuring 'edge' of cut/twisted/sheared/etc prims. //--edge rotate originally by ged //--expanded by bloodsong //--not very reliable unless prims aren't rotated much to start
//--side constants. pos is towards arrow point, neg is towards arrow butt integer X_POS = 1; integer X_NEG = 2; integer Y_POS = 3; integer Y_NEG = 4; integer Z_POS = 5; integer Z_NEG = 6;
//--axis constants integer X_AXIS = 1; integer Y_AXIS = 2; integer Z_AXIS = 3;
//--RotFromEdge: (angle, edge, axis) //-- input your degrees in normal everyday degrees //-- input what edge you want the axis on //-- and which axis you want to rotate about RotFromEdge(float fAngle, integer iSide, integer iAxis) { //--part one initial setup vector size = llGetScale(); //--gets length of sides to find edges. vector currentRot = <0.0,0.0,0.0>; rotation desiredRot; vector rotOriginBefore; //--adjust for different axes and edges if(iAxis == X_AXIS) { currentRot.x = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } else if (iAxis == Y_AXIS) { currentRot.y = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } else if (iAxis == Z_AXIS) { currentRot.z = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } if(iSide == X_POS) { rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * size.x / 2.0); } else if (iSide == Y_POS) { rotOriginBefore = (llRot2Left(llGetLocalRot()) * size.y / 2.0); } else if (iSide == Z_POS) { rotOriginBefore = (llRot2Up(llGetLocalRot()) * size.z / 2.0); } else if (iSide == X_NEG) { rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * (size.x / -2)); } else if (iSide == Y_NEG) { rotOriginBefore = (llRot2Left(llGetLocalRot()) * (size.y / -2)); } else if (iSide == Z_NEG) { rotOriginBefore = (llRot2Up(llGetLocalRot()) * (size.z / -2)); } //--part two, more calculations rotation newLocalRot = desiredRot * llGetLocalRot(); vector rotOriginAfter; //--change from defaults, if needed if(iSide == X_POS) { rotOriginAfter = (llRot2Fwd(newLocalRot) * size.x / 2.0); } else if (iSide == Y_POS) { rotOriginAfter = (llRot2Left(newLocalRot) * size.y / 2.0); } else if (iSide == Z_POS) { rotOriginAfter = (llRot2Up(newLocalRot) * size.z / 2.0); } else if (iSide == X_NEG) { rotOriginAfter = (llRot2Fwd(newLocalRot) * (size.x / -2)); } else if (iSide == Y_NEG) { rotOriginAfter = (llRot2Left(newLocalRot) * (size.y / -2)); } else if (iSide == Z_NEG) { rotOriginAfter = (llRot2Up(newLocalRot) * (size.z / -2)); }
//--part 3, apply the rotation llSetPrimitiveParams([PRIM_POSITION, llGetLocalPos() + rotOriginBefore - rotOriginAfter, PRIM_ROTATION, newLocalRot]);
}
default { touch_start(integer num) { //--this is just a test to see if it works. this loops it around in a complete circle. integer n; for (n=0; n<12; ++n) { RotFromEdge(30.0, Z_NEG, X_AXIS); } } }
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
It Works!!!!!!!!!!!!!
04-09-2007 16:38
okay, after SCOURING the forums here for anything to do with rotations, i found this Very Important Bit of Information: /54/c1/94705/1.htmlin short, llsetlocalrot and llsetprimparameters is bugged. now why didn't somebody just SAY so? come to think of it, why doesnt the WIKI say so? this seems a crucial workaround, here. nobody knows it??? okay, two functions here, which is probably overkill if all you want to do is rotate a flexiprim on its stable edge. RotFromEdge, which works for single, root, or child prims but NOT on attachments (actually, a root on an attachment should work) AttachedRotFromEdge, which works for child prims in an attachment, but you must pass it the root's local rotation. enjoy! //--ged larsson's edge rotation script, expanded to a function //--to rotate on any edge/axis combination //--fixed for child/attached prims with info from lex neva //--compiled by bloodsong termagant
//--side constants. pos is towards arrow point, neg is towards arrow butt integer X_POS = 1; integer X_NEG = 2; integer Y_POS = 3; integer Y_NEG = 4; integer Z_POS = 5; integer Z_NEG = 6;
//--axis constants integer X_AXIS = 1; integer Y_AXIS = 2; integer Z_AXIS = 3;
//--RotFromEdge: (angle, edge, axis) //-- input your degrees in normal everyday degrees //-- input what edge you want the axis on //-- and which axis you want to rotate about RotFromEdge(float fAngle, integer iSide, integer iAxis) { //--part one initial setup vector size = llGetScale(); //--gets length of sides to find edges. //--NOTE: does not work for cut or twisted prims vector currentRot = <0.0,0.0,0.0>; //do not use the local rot! start at zero to add to current rotation (multiply, do weird quarternion math with, whatever) rotation desiredRot; //--we will build this from our single angle vector rotOriginBefore; //--starting origin position rotation //--adjust for different axes and edges //--insert our angle into the desired rotation if(iAxis == X_AXIS) { currentRot.x = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } else if (iAxis == Y_AXIS) { currentRot.y = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } else if (iAxis == Z_AXIS) { currentRot.z = fAngle*DEG_TO_RAD; desiredRot = llEuler2Rot(currentRot); } //--this gets the rotation times half (or negative half) side of the thing. //--this is ged's part, i have no idea what it really means :X if(iSide == X_POS) { rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * size.x / 2.0); } else if (iSide == Y_POS) { rotOriginBefore = (llRot2Left(llGetLocalRot()) * size.y / 2.0); } else if (iSide == Z_POS) { rotOriginBefore = (llRot2Up(llGetLocalRot()) * size.z / 2.0); } else if (iSide == X_NEG) { rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * (size.x / -2)); } else if (iSide == Y_NEG) { rotOriginBefore = (llRot2Left(llGetLocalRot()) * (size.y / -2)); } else if (iSide == Z_NEG) { rotOriginBefore = ( (size.z / -2) * llRot2Up(llGetLocalRot())); } //--part two, more calculations //--our new rotation will be our desired change mixed with the current rotation rotation newLocalRot = desiredRot * llGetLocalRot(); // llGetRot(); //--not llGetLocalRot() * vector rotOriginAfter; //--as it rotates, the origin will change to something new //--change for different edges //--same as before, but with our new rotation if(iSide == X_POS) { rotOriginAfter = (llRot2Fwd(newLocalRot) * size.x / 2.0); } else if (iSide == Y_POS) { rotOriginAfter = (llRot2Left(newLocalRot) * size.y / 2.0); } else if (iSide == Z_POS) { rotOriginAfter = (llRot2Up(newLocalRot) * size.z / 2.0); } else if (iSide == X_NEG) { rotOriginAfter = (llRot2Fwd(newLocalRot) * (size.x / -2)); } else if (iSide == Y_NEG) { rotOriginAfter = (llRot2Left(newLocalRot) * (size.y / -2)); } else if (iSide == Z_NEG) { rotOriginAfter = ( (size.z / -2) * llRot2Up(newLocalRot)); }
//--part 3, apply the rotation //--but FIRST... find out if we are attached (in which case, this wont work), or a child, in which case, we need to divide by the root rot
if(llGetAttached() != 0) {//--need a new function for this, with the roots rotation passed to it llOwnerSay("Error: Edge Rotate does not work on attachments."); return; } if(llGetLinkNumber() > 1) {//--if not lone (0) or root (1), use this formula rotation R = llGetRootRotation(); llSetPrimitiveParams([PRIM_POSITION, llGetLocalPos() + rotOriginBefore - rotOriginAfter, PRIM_ROTATION, newLocalRot/R]); return; } //--else it'll work fine. use normal. llSetPrimitiveParams([PRIM_POSITION, llGetLocalPos() + rotOriginBefore - rotOriginAfter, PRIM_ROTATION, newLocalRot]);
}
default { touch_start(integer num) { integer n; for (n=0; n<6; ++n) { RotFromEdge(45, Z_NEG, X_AXIS); llSleep(1.0); RotFromEdge(-45, Z_NEG, X_AXIS); llSleep(1.0); }
} }
|
Frank Northmead
Registered User
Join date: 24 Oct 2006
Posts: 13
|
workaorund for attached rotation?
05-05-2007 17:53
I have tried this sript and it works fine except when attached. I have added passing in the local rot of the root (I am rotating a child) and tried that but can not get it to work.
I am making a locket on a necklace that opens - all is fine when not attached.
When attached I get weird rotations:
Here is my change in the attached rotation test:
if(llGetAttached() != 0) {//--need a new function for this, with the roots rotation passed to it rotation R = llGetRootRotation(); llSetPrimitiveParams([PRIM_POSITION, (llGetLocalPos() + rotOriginBefore - rotOriginAfter)/root_rot, PRIM_ROTATION, newLocalRot/R]); return; }
Could someone post the wrokaround for attached rotation of a child prim?
TIA,
Frank
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
05-07-2007 07:46
heyas frank!
okay, the problem is that on an attachment, llGetRotRotation gets the AVATAR's rotation, not the root prim, which is what we need.
what i usually do for attachment children is on rez, have the root prim link message its rotation to the children. (change the rotation to a string and pass it via the string section of the message.)
then in the child i want to rotate, in the link message event, i decode the rotation string and set it to my RR (or your R in this case).
then just use that variable when you want to rotate the child.
ps: i have no idea what would happen if the user changes the rotation of the attachment while wearing it. probably blows it up again. ::sigh::
|
Anthony Hocken
Registered User
Join date: 16 Apr 2006
Posts: 121
|
05-10-2007 16:09
From: Bloodsong Termagant ps: i have no idea what would happen if the user changes the rotation of the attachment while wearing it. probably blows it up again. :  igh:: In that scenario you might be able to catch the rotation with the moving_end() event handler and update the variable which stores the root rotation via linked message.
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
05-11-2007 07:14
doesn't moving_end (and start) also happen when the avatar just walks around, though? does it happen if an attachment is on your arm and the avatar waves the arm?
i know some attachments 'sense' motion/speed of an avatar. or themselves ON an avatar.
wouldn't it be like changed and.... something? :/ i haven't run into it as a problem yet, that's why i dont know ;D
|
Anthony Hocken
Registered User
Join date: 16 Apr 2006
Posts: 121
|
05-11-2007 08:22
You can not use the changed() event for this as far as I know.
|
DrFran Babcock
Registered User
Join date: 30 Apr 2006
Posts: 69
|
Please help a poor, math-challenged avie
05-11-2007 10:27
So, does this thing work or not? And if it works, which of the multitude of snippets of scripts works? /me shakes her head in self-pity
|
Lee Ponzu
What Would Steve Do?
Join date: 28 Jun 2006
Posts: 1,770
|
05-11-2007 12:26
From: Bloodsong Termagant in short, llsetlocalrot and llsetprimparameters is bugged. now why didn't somebody just SAY so? come to think of it, why doesnt the WIKI say so? this seems a crucial workaround, here. nobody knows it???
Good question...did you modify the WIKI to add this important info? You can, you know.
|
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
|
05-12-2007 06:54
the only wiki i use is rpg stats, and rpgstats says not to make edits to the wiki, because it's going to re-download from somewhere else.
so, no.
ive seen "if(changed & change_somekindorother)" but only in passing. as you can tell, im not exactly sure how/where this goes. and i still haven't tested any of this. i know, i get distracted by -- ooh, lookit that neat avatar!
dr fran, the LAST and LATEST script is the one that works, of course. ;) gotta get the latest version.
_____________________
Why Johnny Can't Rotate: http://forums.secondlife.com/showthread.php?t=94705
|
Ratus Waydelich
Registered User
Join date: 7 Mar 2007
Posts: 14
|
09-14-2007 00:47
Hi. I just opened a thred to discuss methods how to optain the local rotation of the root object: /54/07/210449/1.html#post1676079
|