Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

llOffsetRot

Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-14-2005 15:21
I've been trying to figure a way to rotate a prim around an arbitrary point.

If there were a rotation function that allowed the center of a prim to be temporarily placed at some arbitrary location, my scripting problem would be solved.

limiting an offset to no more than 5m for any direction would keep it within the max 10m cubed volume of the given prim.

EG:
---
MyPos = llGetPos();
RotCent_x = MyPos.x + Xoffset;
RotCent_y = MyPos.y + Yoffset;
RotCent_z = MyPos.z + Zoffset;
llOffsetRot(<RotCent_x,RotCent_y,RotCent_z,0,0,0,1>;);

The example above wold have the effect of rotating a prim ZERO_ROTATION around some arbitrary point relative to that prim.

The issue I'm trying to solve is that I can only get the prim to move and rotate to the new location I want in a 2 stage process of move-rotate or rotate-move but it looks very wierd/wrong doing it that way.

Thanks,
Racer P.
Driftwood Nomad
Registered User
Join date: 10 May 2003
Posts: 451
01-14-2005 15:33
I would love to see something like this. Although I'm sure it can be done mathematically somehow, but I haven't figured that part out yet :)
_____________________
Driftwood Nomad
D&D Dogs Co-founder

"Second Life’s first AI companion animal"
The Second Opinion, 08/05/2003

D&D Dogs HQ Pawaii (127, 63)
Mainland Store Kuula (214, 124)

http://www.sldogs.com

SL Dogs Zazzle store!
DoteDote Edison
Thinks Too Much
Join date: 6 Jun 2004
Posts: 790
01-14-2005 17:23
If the prim doesn't need to be linked with a larger object, you could simply create a prim at your center of rotation. Make that prim invisible and link your object to that prim. Put the rotation script in the 'pivot prim' and there you have it. Of course, it's limiting, but maybe would help in certain situations.
Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-14-2005 19:43
I have a version of the project that does exacly that just so I could see what It's supposed to look like if I can ever really make it work.

The problem is I'm trying to create scisor or gullwing doors on vehicals...

EG: Lamborghini...

A simultaneous rotate/move needs to be accomplished within a single prim for it to be of use in this project.
Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-14-2005 20:00
From: Driftwood Nomad
I would love to see something like this. Although I'm sure it can be done mathematically somehow, but I haven't figured that part out yet :)


Well, I did figure out how to do it, but the problem is that there is no llsetPosRot or equivalent.

You can set position or rotation but not both together. only in sequential steps.

Also, the llsetPos and llsetRot functions have a built in 0.2 second pause so you can't even run one right after the other and kind of 'slip it past' the audience at high speed hoping noone will notice... The pause between motions is hugely obvious.

I can make a rectangular door open scisor style by taking a cube and cutting it so that 3/4 are cut away. Then the x,y,x center point of the prim is the corner of the visibly remaining 1/4. Rotate that with a standard door script on the X instead of the Z axis and 'wala!' a scisor style door with a completely useless shape for what I need.

Why I'm sure this will work is demonstrated above. If prim B can be rotated around prim A in a 2 prim set (using prim As centerpoint) why can't prim B simply rotate around a virtual centerpoint equivalent to having prim A present.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
01-14-2005 20:17
CODE

vector llOffsetRot(vector local_pos, rotation local_rot)
{
vector pos = local_pos - local_pos * local_rot;
vector cpos = pos;
if(llVecMag(pos)>10)
pos*=10/llVecMag(pos);
llSetPrimitiveParams([PRIM_POSITION, pos + llGetLocalPos(),
PRIM_ROTATION, llGetLocalRot()*local_rot]); //or is it local_rot * llGetLocalRot()?
return cpos - pos;
}


CODE

vector a = llGetLocalPos() + llOffsetRot(some_vector, some_rot);
while(llVecDist(a,llGetPos())>0.001)
llSetPos(a);


EDITS:
order of operations in pre while loop corrections
pos sign correction
using llSetPrimitiveParams instead of llSetPos & llSetRot
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
01-15-2005 16:29
Isn't it possible to use llSetPrimitiveParams to combine the rotation and position changes so they occur simultaniously?
==Chris
Jillian Callahan
Rotary-winged Neko Girl
Join date: 24 Jun 2004
Posts: 3,766
01-15-2005 19:44
From: Christopher Omega
Isn't it possible to use llSetPrimitiveParams to combine the rotation and position changes so they occur simultaniously?
==Chris
Yef. :)
_____________________
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
01-15-2005 22:19
Now that i'm awake i have re-write the code and simplified it. I wasn't exactly awake when i posted it...
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
Almost...
01-15-2005 22:59
Sorry, Strife -

Doesn't work completely. This function you've posted rotates a prim about its center, then translates it by what seems to be a vector who's magnitude is equal to the "offset point", rotated around the global axis by the supplied rotation. But the "cpos" vector is coming out screwy and the end result is that the "While" loop causes the prim to be moved back to its point of origin. Disabling the "While" loop seems to fix the problem; however, I have not tested the effects of a rotation with a vector-magnitude greater than 10 meters.

It is worth noting that the offset-point is relative to the object's *current position* - so repeated applications with the same offset point will appear to translate the prim along a straight line. If you want the "offset-point" to be a fixed point in the world, you must re-compute the offset-point between each call of the function!

Take care,

--Noel "HB" Wade
(Tread Whiplash)
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
hrmmmm.....
01-15-2005 23:27
Well, the translation part of the function doesn't appear to be working 100% correctly, either.

I set up a fixed coordinate in the world close to my prim (2 meters away in the X axis, for the curious), and set "basePos" equal to that.

Then, before each iteration of the "llOffsetRot()" function provided by Strife, I made the following calculation:
vector some_vector = basePos - llGetLocalPos();

...My thought was that this would give me a vector to the "center point" of my rotation, every time I ran the code. However, now instead of moving the prim along a straight line, I get the prim jumping around at "improper angles" when translated. A 45-degree Z-axis translation should "cycle" the prim around a point at 4 discrete points, if the function is repeatedly called. However, I get prim movements that translate "across the interior" of the imaginary circle that this movement should describe - in other words, the translated positions are at angles greater-than what I specified... much greater. Changing to a 30-degree Z-axis rotation also resulted in similar behavior.

Does anyone see anything wrong with what I'm doing; or does this point to a fatal flaw in the function?

Thanks, take care,

--Noel "HB" Wade
(Tread Whiplash)
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
2d solution - how about 3d? Shortcuts?
01-15-2005 23:49
Sorry for spamming the thread with several posts. My only excuse is that its late and I'm starting to get fuzzy-headed. :p

Okay all, I pulled this out of a C# 2d game program I wrote a little while back... have attempted to translate it into LSL here. I think this can be converted to 3d fairly straight-forwardly; if I come up with that I'll edit the post.

The following code should take 2 points (your object's location and a "center-point" location) - and translate the object around the center-point as if it were being rotated. NOTE that this code ignores the 10 meter restriction at the moment. Being 2d, this deals with the equivalent of "Z-axis" rotations only.

CODE

vector ll2DOffsetRot(vector center_position, float degrees_to_rotate)
{

vector temp = llGetLocalPos();

vector offset = temp - center_position;

vector final_position = <0,0,0>;
final_position.z = temp.z;

//The following two lines calculate the new coordinates based on
//the rotation & offset
final_position.x = (offset.x * llCos(DEG_TO_RAD * degrees_to_rotate) )
- ( offset.y * llSin(DEG_TO_RAD * degrees_to_rotate) );
final_position.y = (offset.y * llCos(DEG_TO_RAD * degrees_to_rotate) )
+ ( offset.x * llSin(DEG_TO_RAD * degrees_to_rotate) );

//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.x += center_position.x;
final_position.y += center_position.y;

llSetPos(final_position);

//This sets up the amount to rotate the actual prim, and combines it
//with the existing prim's rotation.
rotation newRot = llEuler2Rot(<0,0,degrees_to_rotate> * DEG_TO_RAD);
llSetRot(newRot * llGetLocalRot());

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


Enjoy,

--Noel "HB" Wade
(Tread Whiplash)

P.S. I have compiled and tested this code in-game. As long as you avoid 10-meter limits, it works just fine; but is restricted to Z-axis rotations only, until we enhance it to be truly 3d.
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
I'm the only one replying?
01-16-2005 00:47
Well, I don't suppose I should expect too many responses at midnight-PST on this...

I've found the simple 3d solution - thanks to LSL's ability to multiply vector and rotation data-types together. It actually makes this fairly trivial!

Now, I'm still ignoring the 10-meter restriction; and looking back, I think that's what tripped Strife up as well, somehow...

EDIT: I've moved this to the "Scripting Library" section of the forums - as this probably belongs there more than it does here... That forum is moderated, so it may take a couple of hours to show up.


Take care,

--Noel "HB" Wade
(Tread Whiplash)
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
01-16-2005 10:15
yeah sorry
vector pos = local_pos + local_pos * local_rot;
should be
vector pos = local_pos - local_pos * local_rot;

i should have caught that earlier. (a null rotation should have no effect duh)

this version uses a local rot for the pos as well so the same center will always have the same effect (or should, i hope).

the problem with the while loop was an order of operations issue.

CODE

vector llOffsetRot(vector local_pos, rotation local_rot)
{
rotation rot = llGetLocalRot();
// llWhisper(0,(string)(llGetLocalPos() - (local_pos * rot)));
// llWhisper(0,(string)(local_pos * rot));
// llWhisper(0,(string)pos);
vector pos = (local_pos - local_pos * local_rot) * rot;
vector cpos = pos;
if(llVecMag(pos)>10)
pos*=10/llVecMag(pos);
llSetPrimitiveParams([PRIM_POSITION, pos + llGetLocalPos(),
PRIM_ROTATION, rot * local_rot]);
return cpos - pos;
}


CODE

vector a = llGetLocalPos() + llOffsetRot(some_vector, some_rot);
while(llVecDist(a,llGetPos())>0.001)
llSetPos(a);


PS: i'm too tired atm to do anymore debbuging (and i actualy did compile it and do some testing, i think i may have gotten somehting wronge with the center calculation. 3d rotations have never been my strong area.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
"cpos" unnecessary?
01-16-2005 11:29
Strife,

Check out the code I posted here:

/15/f5/33104/1.html

...I've found that the vector magnitude check and "cpos" variable bits to be unnecessary.

I have a pending reply in that thread which shows how to get around the 10-meter limit simply by calling llSetPos() repeatedly within the function (since the vector & rotation items are not limited by distance - only the llSetPos() call is). I also have put in a couple of "sanity checks" regarding edge-of-world coordinates.

Thanks Strife for getting the ball rolling on this one!

Take care,

--Noel "HB" Wade
(Tread Whiplash)
Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-19-2005 17:46
OK,

I've finaly got an 'approximation' of the motion I wanted.

By figuring out the vector and rotation I needed separatly and then combining them in a single llSetPrimitiveParams call, the movement and rotation is achieved in one, smooth motion.

The downside is that the centerpoint of the object being rotated moves in a straight line from position A to position B while the rotation is occuring.

Since I'm building a door that hinges on the corner of the prim, it looks slightly 'off' while opening and closing but it does get the job done in a single, quick motion.

Also, because I'm only rotating the door 70 degrees it still looks reasonably OK if you don't stare at it too hard while it opens/closes.

This solution would not work for larger rotations around a set point as the prim would end up spining through the centerpoint rather than around it.

Thanks for all the suggestions and code examples above guys.

I STILL would like an llOffsetRot function to replace my workaround code and greatly improve the motions of the prims involved though.

I think it's a good function to add as noone has yet been able to come up with a viable way to duplicate that motion for anything other than a 2 prim link specificaly created as a hinge/door combo etc... As the rotation of that type of door causes no issues for the 3D rendering engine, I see no reason why code to achive the same motion without the need for the hinge prim to exist could not be added in some future version release.

The code already has to exist for doors to work, we simply need a way to access it and interactively provide a vector and rotation for an 'imaginary' prim to rotate around rather than having to 'physicaly' provide that prim as a base for the moving prim...

To modify my original example...
llOffsetRot(<x,y,z>,<x,y,z,s>,<x,y,z,s>;);
The first vector points the the location of the 'imaginary prim'.
The first rotation gives us the rotation of the 'imaginary prim' so the code has an axis to rotate around...
The third vector supplies the rotation angle we want our prim to move around our 'imaginary axis generated by the first two entries.

In a limited sense, this already does exist as we can rotate objects around the center point of a mapgrid... I want to be able to achive that other than around the <0,0,0> vector.

-Racer P.
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
"Straight line move"...
01-19-2005 20:18
You're right that the motion from the object's current position through to its final position does not describe a curve. I don't believe there is any way to make objects follow a truly cruved path by any means in SL.

The best approximation would be to do a bunch of move commands in rapid succession, each one only moving the object a few degrees at a time around the center-point. llSetPrimitiveParams() does incurr the same forced script-delays as llSetPos() and llSetRot() do, but if you're combining them, then it is clearly superior as you will incurr only 1 delay instead of 2. Good thinking!

Take care,

--Noel "HB" Wade
(Tread Whiplash)
Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-20-2005 13:02
It's not the delay so much as the obvious two-step move rotate you get doing it with llSetPos and llSetRot. Even if there were no delay, it would still look completely wrong.

There is a very easy way to get exactly the motion I'm describing. It just requires a 2 prim link to make it happen.

Make a 'hinge' prim and link it to the prim you want to do the offset rotation on.

Put a few llSetRot(<x,y,z,s>;) script entries into the hinge prim and triger it.

The satelite prim will smoothly rotate around the hinge prim (otherwise known as the 'offset centerpoint' as far as the stelite prim is concerned).

That tells me that all the code needed to do what I want already exists... I can see it happen any time I want with my own eyes.

The problem is that if you want to achieve that same motion in an individual prim within a larger link group, there's no way to tell the engine what you want it to do.

By providing the position and rotation of the axis to rotate around you are providing the engine with everything it would ordinarily need to get from the 'hinge' prim in the 2 prim example I gave above.

Seems prety simple to me. I dunno. Maybe it isn't due to some other constraints in the system that I don't know about.

-Racer P
Tread Whiplash
Crazy Crafter
Join date: 25 Dec 2004
Posts: 291
Reasons...
01-20-2005 18:10
Racer -

I believe the reasons for this are that "Hinges" incorporate the use of the Havok physics engine; while standard Prims do not. I would expect that if we could look "under the hood" at the server's execution of these two different methods, we would find that the "hinge" method is a lot more complicated and taxing on the server.

Just my $0v02...

Take care,

--Noel "HB" Wade
(Tread Whiplash)
Racer Plisskin
Rezerator
Join date: 2 Jan 2005
Posts: 147
01-27-2005 02:36
Sorry I took so long to get back to this thread...

By 'hinge' I didn't mean the joint type of hinge. I meant a prim (usualy a long slim cylinder) used as a 'base/root' prim which has a flat panel linked to it. The flat panel gets a 'door' texture applied.

Now put your door/rotate script into the 'base/root' cylinder prim. The cylinder acts as the hinge that the door panel rotates around and is what I was refering to in the posts above..

I've just described a very simple door that works quite well and is found all over SL.

Giving us a scripting command that allows us to "describe" that hinges/cylinders axis of rotation instead of forcing ust to actualy link to that cylinder to rotate around it is what I'm asking for.

It would allow for the easy creation of 1 prim doors that could rotate the same way a 2 prim link door works now without having to use any fancy prim tricks... (see below).

I HAVE figured out a 1 prim door BTW...

Take a cube and use cut to remove 1/2 of the pannel. This makes the apparent edge of the pannel the center of rotation. Now just drop the door script in and adjust the axis you want to rotate around so it looks right. Simple...

Also, if you cut away 3/4 of the cube (putting the center on one of the remaining corners) and choose the correct axis of rotation, you can get a smooth 'scissor' door (or draw bridge, or whatever) motion that way.

I couldn't use this 3/4 method because A) the door I needed isn't square and B) I needed to move a window pannel together with it and it isn't square either... Fun, eh?
Merlin Alphabeta
Registered User
Join date: 12 Feb 2006
Posts: 83
02-24-2006 07:17
I don't want to just repeat everything in this thread but my main problem is that there's no way to treat a collection of prims as a rigid subpart of an object and rotate them all simultaneously around a joint.

Imagine you wanted to make an ostrich - you'd make the wings, make the legs, make the feet, make the body, make the neck, make the head.

Now your ostrich needs to be one object so you select it all and then link it.

Now my problem is; how do you flap the wings? How do you move the leg joints? I just don't see any way to do it...

This is a problem I'm going to try to solve this weekend. So far I can see three ways to go about it; I could link the limbs up, use point-to-point hinges, and llApplyImpulse or llRot on them. Each limb then has its own management script in its root prim to do the rotations and whatnot, and everything is using llMessageLinked (does that pass messages across joints?) or llSay(my_channel, "command";) to synchronize.

Or I could setup lists of limbs and local rotation points using the functions presented here - which would work but probably be a lot of coding and would change something fundamental; the physical properties of how the limb interacts with the main body would be partially represented in the model and partially represented in the script. General best practice would be to represent that information as fully as possible in one system or the other so if, for instance, you move a limb, you don't have to ALSO edit your code.

The third option is to create a hierarchy of links - remember, you rotate the root prim, everything else rotates about it's access. If I have a hierarchy of links then I could probably do it - but I'm not even sure that a hierarchy is possible!

Does anyone have any tips?