Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Rot From Edge Revisited: Rotations on 3 Axes at Once?

Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
08-11-2008 06:37
okay, i tried reinterpreting your method, and it didnt work. (which isnt to say it DOESNT, just my reinterpretation of t doesnt...) so.... i just adjusted my code to use 3 axes for rotations.

it works, EXCEPT... when i tell it to do 30 degrees on the x and z axes simultanesouly, 12 steps doesnt put them back to where they started (supposedly 360 degrees). im sure its some kind of local quaternion rotation conspiracy going on....


CODE

//--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
RotFromEdge3(vector vAngle, integer iSide)
{
//--part one initial setup
vector size = llGetScale(); //--gets length of sides to find edges.
vector currentRot = <0.0,0.0,0.0>;

rotation desiredRot = llEuler2Rot(vAngle*DEG_TO_RAD);
vector rotOriginBefore;

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 total_number)
{
integer n;

for (n=0; n<12; ++n)
{
RotFromEdge3(<30.0, 0.0, 30.0>, Z_NEG);
llSleep(2.0);
}
}
}




okay... any idea how to pass it an absolute euler rotation as a target for it to rotate to? instead of an increment for it to rotate from where it is?
_____________________
Why Johnny Can't Rotate:
http://forums.secondlife.com/showthread.php?t=94705
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
08-11-2008 07:51
From: Bloodsong Termagant
what, if anything, needs to be changed in the RotFromEdge code to be able to rotate on all 3 axes from one edge? for example, if i want somethings perceived center of rotation to be the middle of the negative x side?
Ok, without trying to decypher the posted code (which, at first glance, looks *way* too complicated for what you're talking about), let's just define what the problem is, at least as I understand it:

You want to pick an arbitrary point relative to a prim, and rotate the prim "about" that point. This involves a combination of rotation and translation, such that the world position relative to the prim's orientation remains in the same before and after the transformation is applied.

So, start with where that pivot point is, as described in your example above:

CODE
vector pivot = < -0.25, 0, 0 >;


This is defined in prim-space, assuming a default cube 0.5m to a side. To convert that to world-space, multiply it by the prim's rotation:

CODE
vector pivot_w = pivot * llGetRot();


Now you'll need to know the offset of the prim's center from the pivot. To get that, subtract the pivot from the prim's position:

CODE
vector offset = llGetPos() - pivot_w;


This is in world-space. Now all you really need to do is apply the same rotation to both the offset and the prim's rotation:

CODE
rotation some_rot = llEuler2Rot( < 90, 45, 30 > * DEG_TO_RAD ); // example, chosen arbitrarily
vector new_offset = offset * some_rot;
rotation new_rot = llGetRot() * some_rot;


Add new_offset to pivot_w, and that's the new world-space position of the prim. new_rot is its new rotation. Apply both, and you've just (apparently) rotated the prim about the arbitrary pivot:

CODE
llSetPrimitiveParams( [ PRIM_POSITION, pivot_w + new_offset, PRIM_ROTATION, new_rot ] );
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
08-13-2008 07:37
heyas;

okay, i tried this and.... um... my object sank about 200 meters.


CODE

//--edge rotate originally by ged, retranslate by deanna trollop
//--expanded by bloodsong


//--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;



RotFromEdge3(vector vAngle, integer iSide)
{
//-- the offset of the arbitrary pivot point
vector pivot = ZERO_VECTOR;
//-- convert to what side
vector size = llGetScale(); //--gets length of sides to find edges.
if(iSide == X_POS)
pivot.x = size.x/2.0;
else if (iSide == Y_POS)
pivot.y = size.y/2.0;
else if (iSide == Z_POS)
pivot.z = size.z/2.0;
else if(iSide == X_NEG)
pivot.x = size.x/ -2.0;
else if (iSide == Y_NEG)
pivot.y = size.y/ -2.0;
else if (iSide == Z_NEG)
pivot.z = size.z/ -2.0;

//--2 convert to world by Xing with local rot
pivot = pivot * llGetLocalRot(); //--or GetRot???

//--3 prim center offset is... subtract pos - pivot
vector offset = llGetLocalPos() - pivot;

//--4 voodoo apply desired rotation to pos and rotation
rotation rRot = llEuler2Rot(vAngle*DEG_TO_RAD);
offset = offset * rRot;
pivot = pivot - offset;
rotation newRot = llGetLocalRot() * rRot;

//--5 apply the pos/rot
llSetPrimitiveParams([ PRIM_POSITION, pivot,
PRIM_ROTATION, newRot]);


}



default
{


touch_start(integer total_number)
{
integer n;

for (n=0; n<12; ++n)
{
RotFromEdge3(<30.0, 0.0, 30.0>, Z_NEG);
}
}
}


using llGetRot instead of Local doesnt help any. also, doing to 30 degrees on 2 axes 12 times is not making each go through a whole 360 degrees. although doing just one axis at a time works.

apparently, i have mis-interpreted or mis-implemented your steps. or something has gone missing from ged's original new pivot finding code, as he did all the steps at once.
ie: rotOriginBefore = (llRot2Fwd(llGetLocalRot()) * size.x / 2.0);
and: rotOriginAfter = (llRot2Fwd(newLocalRot) * size.x / 2.0);

notice how he is only using the pertinent rotation axis (fwd,up,whatever) to adjust the origin of the side. i have no idea what this means.
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
08-14-2008 01:48
From: Bloodsong Termagant
okay, i tried this and.... um... my object sank about 200 meters.
Ah crud... that's what I get for posting untested code when I'm just barely awake. When converting pivot from prim-space to world-space, I applied the rotation, but forgot to add to llGetPos(). Here's a better way to do it anyhow:

The world-pivot to object offset is just the inverse of the local pivot, so just apply the rotation to that:
CODE
vector offset = -pivot * llGetRot();


Then the world-pivot is the world-offset subtracted from object position:
CODE
vector pivot_w = llGetPos() - offset;



So in your code, since you just apply the prim's rotation to the pivot value directly, you just need to change the line under step 3 to:

CODE
vector offset = -pivot;

And add:
CODE
pivot = llGetPos() - offset;


Oh, and under "voodoo" ;), you're supposed to add offset to pivot, not subtract from it.

Tested this out in-world, and appears to work.

From: someone
llGetLocalRot(); //--or GetRot???
Depends on if this is a single/root prim or child prim you're rotating. llGetRot and llGetLocalRot are identical returns for a single or root prim, (ditto for Pos) but you'd want Local for a child prim. However, since I'm using a single llSetPrimitiveParams call instead of separate llSetPos and llSetRot calls (which would have a built-in delay between them), this would get real screwy for a child prim, since llSetPrimitiveParams doesn't work well with rotations in child prims.

From: someone
notice how he is only using the pertinent rotation axis (fwd,up,whatever) to adjust the origin of the side. i have no idea what this means.
Ok, what he's doing there is feeding the prim's rotation into a function which will return an axis unit vector (llGetRotFwd = x, Left = y, Up = z) for the given rotation. A unit vector has a length of 1.0, so he then multiplies it by the corresponding scale component, and divides by 2 to get an offset one half prim length/width/height from its origin.

This assumes the pivot point will fall exactly along one of the prim's six cardinal directions, but the way I was thinking, you could specify an arbitrary pivot anywhere around the prim (providing that the translation operation wouldn't require a single jump of more than 10m), rather than being limited to just those six.
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
08-18-2008 09:23
heyas;

okay! i dont understand any of it, but it works! as for putting an arbitrary rotation point anywhere... i wouldnt have the faintest idea how to define 'anywhere.' the edge of the prim is all i need ;)


now, what i have discovered that i REALLY want to do... is pre-define an absolute rotation (lets say <45.0, 0.0, 90.0>) and have this rot from edge thing put itself into that rotation, while leaving its selected edge at its 'home' position.
i know how to set a local rot vs how to calculate a local or global rotation increment... but add the edge offset pivot whatevers in there, and i'm way lost again.


OH! oh, i see where it is!

okay, now it doesnt work. it doesnt work because... if i leave in the loop that sets the same rotation 12 times... the prim scoots off into the distance. (it keeps the same rotation, as it should.)
so what its doing.... is finding the new pivot based on where the edge of the prim is now. but... the edge SHOULD be staying still, since that's what we're trying to calculate for it to do.


i can't figure it out. :/

CODE

//--edge rotate originally by ged, retranslate by deanna trollop
//--expanded by bloodsong


//--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;



RotFromEdge3(vector vAngle, integer iSide)
{
//-- the offset of the arbitrary pivot point; start at zero
vector pivot = ZERO_VECTOR;

//-- convert to what side
vector size = llGetScale(); //--gets length of sides to find edges.
if(iSide == X_POS)
pivot.x = size.x/2.0;
else if (iSide == Y_POS)
pivot.y = size.y/2.0;
else if (iSide == Z_POS)
pivot.z = size.z/2.0;
else if(iSide == X_NEG)
pivot.x = size.x/ -2.0;
else if (iSide == Y_NEG)
pivot.y = size.y/ -2.0;
else if (iSide == Z_NEG)
pivot.z = size.z/ -2.0;

//--2 convert to world by Xing with local rot
pivot = pivot * llGetLocalRot();

//--3 prim center offset is... negative pivot
vector offset = -pivot;
//-- and do this to find the pivot location away from the center
pivot = llGetPos() - offset;

//--4 voodoo apply desired rotation to pos and rotation
rotation rRot = llEuler2Rot(vAngle*DEG_TO_RAD);
offset = offset * rRot;
//--add offset to pivot
pivot = pivot + offset;
// rotation newRot = llGetLocalRot() * rRot;

//--5 apply the pos/rot
llSetPrimitiveParams([ PRIM_POSITION, pivot,
PRIM_ROTATION, rRot]);


}



default
{


touch_start(integer total_number)
{
integer n;

for (n=0; n<12; ++n)
{
RotFromEdge3(< 45.0, 0.0, 30.0>, Z_NEG);
}
}
}


Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
10-05-2008 07:12
stop running away, i need some SERIOUS help here.


WHAT IT SHOULD DO:

1: i give it a euler vector of what rotation i want it to go into. ie: 30, 0,0 = 30 degrees tilted on the x axis. this should be local to it/its linkset.

2: have it calculate an 'arbitrary pivot point' which is one edge defined by the contsants. ie: Z_NEG, the butt-end of the z arrow.

3: stick itself in THAT rotation, with it's z-butt apparently not moving from where i put it.




i revisited the script, and the wiki scrap of information on it... and totally failed to figure things out.

first, i tried to clean up all that stuff deanna was telling me to do above into something simple and organized. here are my notes:

//--now according to deanna voodoo, there should be more rotation multiplications in here
//--okay wait, as far as i can tell, all this pivot/offset done in the other script is just undoing what it did all along.
//1: pivot = zero rotation
//2: pivot = zero rotation with one side edge calculated
//3: pivot = that * the current rotationt
//4: pivot = local pos - - pivot (ie: +pivot) which is what im currently using as offset....
//5: offset = -pivot
//6: offset = * target rotation
//7: pivot = pivot + offset
//--OR-- = pivot + (-pivot * target rotation)
//8: and PIVOT is what the targetpos is.

//-- so what it is REALLY doing is....
//1: pivot starts at zero, and has a half size ln added to it.
//2: that is * the current rotation
//3: now the offset is... localpos + pivot
//3: target pos is... -pivot * target rot... +offset
//-- which except for the negative, is the formula the geeks suggest...??? i think?? or it is, but i added the pivot to the center instead of subtracting.
//--of course... all this could only be functional at zero rotation at all.
//--but it does work in a child prim. at zero rotation. so far.
//-- yep. its totally fubar in standalone or child if you rotate the object. OMFG I HATE ROTATIONS!!!


this is the wiki note written by geeks (interjection mine)

//Note: An object can be rotated around an arbitrary point by multiplying a vector by a rotation in the manner described above. The vector should be the difference between the object's current position and the desired "center-point" of rotation. Take the result of the multiplication and add it to the point of rotation WHICH POINT OF ROTATION YOU IDIOTIC GEEKS!?!?!?. This vector will be the "new location" the object should be moved to.


so i've come up with offset = center + pivot (not minus)
and targetPos = (-pivot * targetRot) + offset are the formulae that (seem to) work.

so now i have the following script.
and it DOES work. under severely controlled circumstances.


what DOESNT work?

1: its totally fubar if the object is rotated away from 0 0 0

2: if i apply the same rotation that it already has, it moves away from its pivot point. its SUPPOSED to keep its z-butt in one spot at any/all rotations! (it doesnt rotate any more, it stays in the same orientation, at least.)

3: if i attempt to see if the new rotation i'm trying to plug in is the same it is already in... the check utterly fails to recognize either
llRot2Euler(llGetLocalRot()) == vAngle
or
llGetLocalRot() == llEuler2Rot(vAngle)

so somehow it has to figure out how/when NOT to change its position depending on whether this rotation i'm setting it to is actually the SAME as it already is in or not.


note:
PIVOT is the edge of the prim, where it should 'appear' to be rotating from.
OFFSET is the distance between the pivot and the center.
TARGETPOS is the end result of calculating where to stick the prim so it's edge(pivot) stays in the same spot



CODE

//--edge rotate originally by ged, retranslate by deanna trollop
//--expanded by bloodsong


//--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;



RotFromEdge3(vector vAngle, integer iSide)
{
//--okay, FIRST.... figure out the rotations, and if we need to be here at all

rotation startRot = llGetLocalRot();
rotation targetRot = llEuler2Rot(vAngle*DEG_TO_RAD);

if(startRot == targetRot) return; //--easy enough
//UTTERLY FAILS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


//--now we do pivot point voodoo.
//Note: An object can be rotated around an arbitrary point by multiplying a vector by a rotation in the manner described above. The vector should be the difference between the object's current position and the desired "center-point" of rotation. Take the result of the multiplication and add it to the point of rotation. This vector will be the "new location" the object should be moved to.

//-- okay so X---x----
//-- X= desired point
//-- x=center
//-- [---] = difference between them.

vector center = llGetLocalPos(); //--i would think
vector pivot = ZERO_VECTOR; //--which will be the edge based on...
vector offset; //-- center - pivot. or vice versa. crap.

//-- convert to what side
vector size = llGetScale(); //--gets length of sides to find edges.
if(iSide == X_POS)
pivot.x = size.x/2.0;
else if (iSide == Y_POS)
pivot.y = size.y/2.0;
else if (iSide == Z_POS)
pivot.z = size.z/2.0;
else if(iSide == X_NEG)
pivot.x = size.x/ -2.0;
else if (iSide == Y_NEG)
pivot.y = size.y/ -2.0;
else if (iSide == Z_NEG)
pivot.z = size.z/ -2.0;

//--according to deanna's voodoo, this has to be * the current rotation to 'convert to world coordinates.'
pivot = pivot * startRot;


offset = center + pivot; //--as far as i can tell.
//-- plus because - is going the wrong way


//--okay, this is the vector * rotation part except we havent found the relationship between the target rot and the current rot. oh well, here goes...

vector targetPos = (-pivot * targetRot) + offset; //--lets try the center as the 'point of rotation.' no... okay, lets try pivot no... all right center again...
//--and this is giving crap results when the plain offset is where the target SHOULD BE
//--so lets try the offset, which has nothing to do with any 'center of rotation.' nope! same crap.
//--so, against all logic, lets make it -pivot * target rot + offset
//ooookay, that works. go figure. something is screwy.


llOwnerSay("Center="+(string)center+"\ntarget="+(string)targetPos);

llSetPrimitiveParams([ PRIM_POSITION, targetPos,
PRIM_ROTATION, targetRot]);



}



default
{


touch_start(integer total_number)
{

vector home = llGetLocalPos();
integer n;

for (n=0; n<4; ++n)
{
RotFromEdge3(< 30.0, 0.0, 00.0>, Z_NEG);
}
llSleep(5.0);
llSetPos(home);
while (llGetLocalPos() != home)
llSetPos(home);
llSetRot(ZERO_ROTATION);

}
}




the rotfromedge (on one axis) works. the rotfromedge (on 3 axes) works if i want to 'add' a rotation to the current. why does it totally not work when i just want to set an 'absolute' rotational aspect?
_____________________
Why Johnny Can't Rotate:
http://forums.secondlife.com/showthread.php?t=94705
Thickbrick Sleaford
Baffled
Join date: 28 Dec 2006
Posts: 26
10-06-2008 04:48
I think you are mixing world and local coordinates and rotations there. Solution: abstract into simpler pieces.

About the check for if the rotation is need, I think that aside from the weirdness of quaternions, it is not likely to be identical because of rounding errors in the trig conversions that llEuler2Rot does. I replaced it with llAgleBetween, but I don't see why it's needed.

Does this do what you intended? Hopefully I didn't confuse things further.

CODE

//--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;

//rotate by local rotation around a local-coords pivot
//this can and should be done with less variables.
localRotByAround(rotation localRot, vector localPivot) {
//get current world rotation
rotation startRot = llGetRot();
//since we got a local rotation, convert it to world rotation
rotation targetRot = localRot * startRot;
//the world-coords vector from original center to pivot point
vector oldCenterToPivot = localPivot * startRot;
//the world-coords vector from new center to pivot point
vector newCenterToPivot = localPivot * targetRot;
//move center to pivot point, then move it back, but in the new rotation
vector targetPos = llGetPos() + oldCenterToPivot - newCenterToPivot;
llSetPrimitiveParams([PRIM_POSITION, targetPos, PRIM_ROTATION, targetRot]);
}


RotFromEdge3(vector vAngle, integer iSide)
{
rotation localRot = llEuler2Rot(vAngle*DEG_TO_RAD);
if (llAngleBetween(localRot, ZERO_ROTATION) < 0.001) {
llOwnerSay("too small a rotation. go away.");
return;
}
vector pivot = ZERO_VECTOR; //--which will be the edge based on...
//-- convert to what side
vector size = llGetScale(); //--gets length of sides to find edges.
if(iSide == X_POS)
pivot.x = size.x/2.0;
else if (iSide == Y_POS)
pivot.y = size.y/2.0;
else if (iSide == Z_POS)
pivot.z = size.z/2.0;
else if(iSide == X_NEG)
pivot.x = size.x/ -2.0;
else if (iSide == Y_NEG)
pivot.y = size.y/ -2.0;
else if (iSide == Z_NEG)
pivot.z = size.z/ -2.0;
// llOwnerSay("Center="+(string)center+"\ntarget="+(string)targetPos);

localRotByAround(localRot, pivot);
}


default
{
touch_start(integer total_number)
{
vector home = llGetLocalPos();
integer n;
for (n=0; n<12; ++n)
{
RotFromEdge3(< 30.0, 0.0, 00.0>, Z_NEG);
}
llSleep(5.0);
llSetPos(home);
while (llGetLocalPos() != home)
llSetPos(home);
llSetRot(ZERO_ROTATION);
}
}
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
10-24-2008 11:17
heyas;

sorry, thick. yours is rotating it around by adding 30 degrees to each iteration. i want i set at x=30 and to stay at x=30. and not go around.
_____________________
Why Johnny Can't Rotate:
http://forums.secondlife.com/showthread.php?t=94705
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
10-24-2008 11:39
wait hang on....

okay... this is handy. i changed the 'this is too small and angle go away' comparison from ZERO_ROTATION to llGetLocalRot(). NOW it moves one time and says go away the other 11.


sooooo... let's see what else this puppy can do....


okay, rotated the object. it went all the way around.

okay, i linked it to another prim. it rotated from its own center. but only once. (at zero rotation anyhow.) (mm, yeah, and went around TWICE when i rotated the object.)



oh, maybe all i need to do is divide it by the root rotation, like usual... but first, it has to work on a root prim that is rotated, and it isnt. we gotta figure out WHY. :(


rotations give me a quadruple migraine!!!
Thickbrick Sleaford
Baffled
Join date: 28 Dec 2006
Posts: 26
10-24-2008 14:46
Oops, I thought you were trying to set the rotation relative to the current rotation of the object. Also, I confused things further by using the term localRot, while I meant "rotation relative to current attitude of the prim."

Anyway, if you are trying to do the equivalent of llSetRot (set a rotation by starting to count from the world axes, ignoring whatever rotation the prim was at,) replacing the line:
rotation targetRot = localRot * startRot;
with:
rotation targetRot = localRot;
will do it. I think.

As for using it in child prims, I think it's just a matter of choosing the right function to apply and sense the rotations, from the table here:
http://wiki.secondlife.com/wiki/Rotation#Single_or_Root_Prims_vs_Linked_Prims_vs_Attachments
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
10-26-2008 04:50
OMG!!!

its workiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiing!!!!!!!!!!!!!!!!!!!! ::FAINT!::


and yeah, once i get it working in a single prim, i know how to fix it for child prims and/or attachments etc.


but the question is still in my mind.... if the other formula worked (and it DID)... why would putting it into the same rotation calculate a different endpoint each time and make it move out of place???

and probably.... it involves quaternion and vector math, so i REALLY don't want to know. but, really.... the angle comparison check shouldn't be needed. i would think. then again... doing the check circumvents doing all that math when it really isnt needed, so... what the heck.


now let me see if i can apply this how i want it and the rotations and child prims and rotated child prims.... then omg, i'll have to finish some projects i was kinda.... not doing. ::cough::


thanks thick!


oh! i took out the angle check, and it STILL WORKS! its great! wish i knew what the heck you did... but thats okay, i prolly can't understand it anyway.
_____________________
Why Johnny Can't Rotate:
http://forums.secondlife.com/showthread.php?t=94705
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
10-26-2008 07:17
okay...

i wont bore you with the hair tearing last little bits to get this far.


HERE IS THE FINAL, FULLY-WORKING FUNCTION. use at your own risk.


CODE


//--edge rotate originally by ged, retranslated by deanna trollop
//--expanded by bloodsong
//--reworked by thickbrick

//--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;


//-- Rotate From Edge 3 Axis, Absolute Rotation Setting
//-- enter the real-world angle (ie X, Y, Z rotations in the build palette)
//-- what side you want to pivot from (see constants above)
//-- the root rotation. use ZERO_ROTATION if not in an attachment.
//-- if it IS an attachment, and this is a child prim, you MUST
//-- have the root prim send its llGetLocalRot to this script
//-- via link-message when you call this function.
RotFromEdge3Abs(vector vAngle, integer iSide, rotation RR)
{
rotation targetRot = llEuler2Rot(vAngle*DEG_TO_RAD);
if (llAngleBetween(targetRot, llGetLocalRot()) < 0.1)
return;

vector pivot = ZERO_VECTOR; //--which will be the edge based on...
//-- convert to what side
vector size = llGetScale(); //--gets length of sides to find edges.
if(iSide == X_POS)
pivot.x = size.x/2.0;
else if (iSide == Y_POS)
pivot.y = size.y/2.0;
else if (iSide == Z_POS)
pivot.z = size.z/2.0;
else if(iSide == X_NEG)
pivot.x = size.x/ -2.0;
else if (iSide == Y_NEG)
pivot.y = size.y/ -2.0;
else if (iSide == Z_NEG)
pivot.z = size.z/ -2.0;

//get current world rotation
rotation startRot = llGetLocalRot();
//the world-coords vector from original center to pivot point
vector oldCenterToPivot = pivot * startRot;
//the world-coords vector from new center to pivot point
vector newCenterToPivot = pivot * targetRot;
//move center to pivot point, then move it back, but in the new rotation
vector targetPos = llGetLocalPos() + oldCenterToPivot - newCenterToPivot;

if(llGetLinkNumber() < 2) //--single or root prim
llSetPrimitiveParams([PRIM_POSITION, targetPos, PRIM_ROTATION, targetRot]);
else if(!llGetAttached()) //--a child prim on a standalone object
llSetPrimitiveParams([PRIM_POSITION, targetPos, PRIM_ROTATION, targetRot/llGetRootRotation()]);
else //--it is attached and not the root
llSetPrimitiveParams([PRIM_POSITION, targetPos, PRIM_ROTATION, targetRot/RR]);
}


default
{
touch_start(integer total_number)
{//this is only a test. it should move ONE TIME, then return in 5 seconds
vector home = llGetLocalPos();
rotation homeRot = llGetLocalRot();
integer n;
for (n=0; n<12; ++n)
{
RotFromEdge3Abs(< 30.0, 0.0, 00.0>, Z_NEG, ZERO_ROTATION);
}
llSleep(5.0);
llSetPos(home);
while (llGetLocalPos() != home)
llSetPos(home);
llSetLocalRot(homeRot);
}
}


_____________________
Why Johnny Can't Rotate:
http://forums.secondlife.com/showthread.php?t=94705
Bloodsong Termagant
Manic Artist
Join date: 22 Jan 2007
Posts: 615
10-31-2008 08:45
WARNING:

it doesnt work unless you 'read off' the euler rotations for the child prims while the object is at 0,0,0 rotation.

::sigh::

if you use quaternions, it doesnt matter. yah, okay, so... score one for them.
_____________________
Why Johnny Can't Rotate:
http://forums.secondlife.com/showthread.php?t=94705