Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Offset Rotations...

Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
01-16-2005 01:57
A thread was started in the "Feature Suggestions" area of the forum, asking for an LSL system that allowed rotation around an arbitrary point.

Strife Onizuka got the ball rolling with some suggested scripts; but after I failed to get them to work, I came up with a few solutions of my own. This is the final version of the function - although further development work can certainly be done in terms of "safety" and enhanced capability for offsets greater than 10 meters away.

In any case - here is the llOffsetRot() function - 3d capable and ready to rock!

CODE

vector llOffsetRot(vector center_position, rotation rot_amount)
{

vector temp = llGetLocalPos();

vector offset = temp - center_position;

vector final_position = <0,0,0>;

//The following line calculates the new coordinates based on
//the rotation & offset
final_position = offset * rot_amount;

//Since the rotation is calculated in terms of our offset, we need to add
//our original center_position back in - to get the final coordinates.
final_position += center_position;

llSetPos(final_position);

//This sets up the amount to rotate the actual prim, and combines it
//with the existing prim's rotation.
llSetRot(rot_amount * llGetLocalRot());

//This isn't absolutely necessary; but it may come in handy.
return final_position;
}



Take care,

--Noel "HB" Wade
(Tread Whiplash)

P.S. FYI: I tested values greater than 10 meters - and it appears to clamp all movements to a max of 10 meters.
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
10-meter limit....
01-16-2005 11:26
Well, after testing, I've found that the movement vector doesn't need to be corrected for offsets greater than 10 meters - ONLY the llSetPos() function clamps things (as I had expected)....

So you can get around the "10 meter limit" by replacing
CODE

llSetPos(final_position);


with
CODE

//SANITY CHECKS - MAKE SURE WE AREN'T MOVING OFF-WORLD.
//This may or may not limit sim-crossing situations; but due to the
// loop below, it is very necessary. Otherwise the prim might
// move off-world; and as soon as you re-rez it from lost & found,
// it begins moving again until it flies off-world!
// If these limits are hit, it may change the actual total angle &
// distance moved. I'm leaving it up to the user to make sure
// this doesn't happen, or correct for it.

if(final_position.x < 0)
final_position.x = 0;
else if(final_position.x > 256)
final_position.x = 256;
if(final_position.y < 0)
final_position.y = 0;
else if(final_position.y > 256)
final_position.y = 256;
if(final_position.z <= 0)
final_position.z = 0;

//While loop: As long as we haven't reached our destination, keep trying.
// llSetPos() will moveup to 10 meters at each iteration. The prim may
// not move completely smoothly, but it will reach its destination rapidly.

while(llVecDist(final_position,llGetPos())>0.001)
llSetPos(final_position);


You *could* concievably correct for the proper angle anytime you hit the sim coordinates limits (by scaling the vector relative to the amount it was "clamped" by) - but I'll leave that as an exercise for the ambitious folks out there. :rolleyes:

Enjoy!

Take care,

--Noel "HB" Wade
(Tread Whiplash)
Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-17-2005 04:09
Sorry, the function above does not do a smooth mov/rot. It does the same thing my original code does (what I'm trying to clean up). It moves the prim in 2 discrete motions. A separate move and rotate.

CODE
integer has_moved;
vector prim_mov;
rotation prim_rot;

// Object to be rotated
// Prims initial vector and rotation
vector position_A = <0.295746, 0.995255, 0.319721>;
rotation rotation_A = <1.0, 0.0, 0.0, 0.0>;

// Prims destination vector and rotation
vector position_B = <0.556702, 0.995255, 1.222816>;
rotation rotation_B = <-0.819152, 0.0, 0.573576, 0.0>;

default
{
state_entry()
{
// Assume object has not moved to start with...
has_moved = FALSE;

// The prims vector and rotation changes based on the above raw data...
prim_mov = position_B - position_A;
prim_rot = rotation_B - rotation_A;
}

touch_start(integer n)
{
if (llDetectedKey(0) == llGetOwner())
{
if (has_moved)
{
llSetRot(llGetLocalRot() + prim_rot );
llSetPos(llGetLocalPos() - prim_mov );
has_moved = FALSE;
}
else
{
llSetPos(llGetLocalPos() + prim_mov );
llSetRot(llGetLocalRot() - prim_rot );
has_moved = TRUE;
}
}
}
}

I'm trying to get a move and rotate 'all-in-one-motion'.

EG: Take 2 prims (A & B) and put a rotate script in prim A. Then link prim B to A with A being the base prim. When A rotates, B makes a smooth, offset center rotation around A. I want to get B to make that exact movement but without having to have any A prim involved...

Racer P.
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
Improvements...
01-19-2005 22:10
Okay, I hate to keep replying to my own thread - but I wanted to make sure it got posted here for Posterity:

Racer Plisskin came up with a clever improvement to this code!

By using llSetRot() and llSetPos(), you are incurring a 0.2 second penalty after each one - which means a pause in-between rotating and moving the object.

Racer Plisskin posted:
From: someone
By figuring out the vector and rotation I needed separately and then combining them in a single llSetPrimitiveParams call, the movement and rotation is achieved in one, smooth motion.


Thanks Racer - wish I'd thought of this myself! :rolleyes:

----------

Also, just for clarity: These solutions will always move the object in a straight line from its current position to the "end" position. If you want the object to follow a curved path, the only way I can think of to do this, would be to repeatedly call the function and move a very small amount each time. Because of the forced delays in LSL, you won't achieve totally smooth movement; but its the closest you can come, with this sort of solution.

Take care,

--Noel "HB" Wade
(Tread Whiplash)
AJ DaSilva
woz ere
Join date: 15 Jun 2005
Posts: 1,993
10-19-2005 07:35
I found Tred's script to give incorrect rotaions (rotating on the wrong axis) when the object wasn't upright. Here's the script I've been using (basically the one from the wiki IIRC):

CODE
offsetRot(vector rotPoint, rotation rotAngle)
{
rotation new_rot = llGetRot() * rotAngle;
llSetRot(new_rot);

vector currentPos = llGetPos();
vector newPos = rotPoint + ((currentPos - rotPoint) * rotAngle);
llSetPos(newPos);
}