Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Can you rotate a child around an arbitrary axis?

HtF Visconti
Registered User
Join date: 21 Jul 2006
Posts: 123
09-02-2006 05:20
I hope I put that one right in the title .... I've been playing with this for a couple of hours and couldn't get a result. What I'm trying to do is:

Imagine a house, a hinge and a door. I want them all to be linked together and I want the door to open and close. So far all my results got me was the door rotaing properly but around its center of *origin*. The only way I could make it rotate around the hinge so far was to cheat and add a translation after the rotation. Because of the penalties in the functions this looks yucky at best.

So - am I missing something here? I've never cared about vehicles but this would mean you cannot have operating car doors? If it is really possible, please give me a hint on what I have been overlooking so far in setting the rotational point of origin.

If there is no way ... a couple of good cheats will do as well - maybe an alpha mapped door might help with half of the door hidden so the center of origin could be placed at the hinge?
Adriana Caligari
Registered User
Join date: 21 Apr 2005
Posts: 458
09-02-2006 06:46
Can you rotate a child about an arbitary axis ?

1st attach rope to child - tie other end to axis - push child very hard - that works :-)


Yes you can - lets take the door

Make it a cube and use cut to and from ( .375 and .825 if memory serves correctly ) - that way the door's center is now it's edge.

Now move the door so that the edge is where the RL hinge would be.

Link it to your house.

Apply a script to the door to use local rotation ( llSetLocalRot - I believe ) try out a few combinations of the original rotation and rotation + 90 in an axis until you get it rotating correctly.

Works well, and the door stays with the house when you rotate the house as well ( just happened to have demonstrated this to someone the other day who had a similar question )

ps
Forgot a bit

Make sure the door isnt the main prim else your house will "open" and "close" instead of the door.
_____________________
Maker of quality Gadgets
Caligari Designs Store
HtF Visconti
Registered User
Join date: 21 Jul 2006
Posts: 123
09-02-2006 06:59
Lol - I was just waiting for the "child" to be taken literally, I knew someone wouldn't be able to resist ... :)

I have already tried the "cut path" thingy - the door looks a bit strange from the cut side and this is one of those "cheating" things I mentioned. :) I stopped pursuing it further because the cut angle was different to my intended direction and this would have played merry hell with my axis .... I so hate it when x is no longer x :)

Thanks for the input - I *will* pursue this path if there is no other alternative.

The trouble is that I planned to have things attached to the door - well - I think I kann kiss this idea a jolly goodbye then, if I really can only rotate by cheating - there's no way a, say, nailed horseshoe would be able to follow the door because I cannot use the same cheat with the cut off bottom part with it.

@Lindens: if this is really true .... please do a function with which to rotate around an arbitrary axis. (Or allow rotational and lateral movement be combined in a way that looks smooth).
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
09-02-2006 10:59
Not tried it personally, but allegedly llSetPrimitiveParams() will let you do this. You set the position and the rotation and the rendering gives you a smooth swing around the actual edge.
_____________________
Eloise's MiniMall
Visit Eloise's Minimall
New, smaller footprint, same great materials.

Check out the new blog
HtF Visconti
Registered User
Join date: 21 Jul 2006
Posts: 123
09-03-2006 01:34
Hm,

thanks Eloise! I'll try to rescue my test set from the trash bin and continue fiddling with it.
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
09-03-2006 03:13
Well, this sort of works
CODE

vector offset; // storage variable, to maintain location of hinge in relation to root prim, in local coordinates of the set

rotate( rotation Spin ) {

vector lever = ( llGetLocalPos() - offset );
lever = lever * Spin;
llSetPrimitiveParams( [ PRIM_POSITION, offset + lever, PRIM_ROTATION, Spin * llGetLocalRot() / llGetRootRotation() ] );
}

default {

touch_start( integer ContactsTotal ) {

if( llDetectedKey(0) != llGetOwner() ) return;

// hinge is point of rotation, in local coordinates from prim center point
// by default it's placed on Y-axis edge of prim. could be anywhere though
// calculations are done here rather than cached, to avoid script breaking if the position and/or size of door is modified after script was placed in the prim
vector size = llGetScale();
vector hinge = < 0.0, size.y * 0.5 , 0.0>;
offset = llGetLocalPos() + ( hinge * llGetLocalRot() );

rotation spin;
spin = llAxisAngle2Rot( <0.0, 0.0, 1.0>, (9 * DEG_TO_RAD) ); // rotate in 10 steps on (local) Z axis
integer idx;
for( idx = 0; idx < 10; ++idx ) { rotate( spin ); }
llSleep( 1.0 );
spin = llAxisAngle2Rot( <0.0, 0.0, 1.0>, (-9 * DEG_TO_RAD) ); // rotate back
for( idx = 0; idx < 10; ++idx ) { rotate( spin ); }
}
}

edit: fixed issue with script breaking when root prim was rotated. keep in mind in some situations it can still break if the child prim is rotated and you try to perform further rotation on it... see what happens with prim rotated 90 degree on x-axie, e.g :/
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
09-05-2006 05:24
Hi HtF

This is the start of a door script that I have been playing with. The swing parameters are in the door description. It can be a root prim so you should be able to link other prims to it, eg, doorknob and knockers etc (but not the rest of the house, or you will see that move too). I am still working on the close, but the open action seems to work ok.

For example:
CODE

H0Q9;<0, -1.1, 0.0>;<0, 0, 9>

H0 establishes that this door is at the home position, Q9 indicates we want 10 steps, moving the door a total of 90 degrees. Make sure that it is H0 when you position the door. The script allows for the initial door position rotation.

The first vector is the position of the fulcrum wrt the centre of the door and will be multiplied by the rotation of the door. The second is the rotation angle (euler and in degrees) for each positional move.

I have not yet tried this as a linked prim. I may need to substitute setLocalRot for setRot etc on condition of the link number (>1 would be linked to another root prim).

Do with it what you want. You are free to use this script anyway you want, though I will be very unhappy if I see it being sold by itself.

Ed
CODE

//description parameters
// B - want bell
// H0 - home position
// Q9 - number of steps - 1 (eg, 9 (max) produces 10 steps)

integer debug = FALSE;

integer gSetUp = FALSE;
//vector turnPos;

vector gEulDegStep;
string gsEulDegStep; // keep ascii source for brevity
rotation gRotStep;
vector gRelFulcrum;
string gsRelFulcrum; // keep ascii source for brevity

integer gH = 0; // step counter
integer gQ = 0; // step quantitu target

string gSettings; // the first part of the description
integer gSettingsPtr;

list gDescWords; // list from description

vector gHomePos;
rotation gHomeRot;

vector gActFulcrum;
vector gLever;

integer gEnableBell = FALSE;
integer itisSet = FALSE;




string getSettingsChar () {
string c = ";";
if (gSettingsPtr < llStringLength (gSettings))
c = llGetSubString (gSettings, gSettingsPtr, gSettingsPtr);
++gSettingsPtr;
return c;
}



integer getDigitNo () {
string nums = "0123456789";
string c = getSettingsChar ();
integer pos = llSubStringIndex (nums, c);
return pos;
}





getH () {
gH = getDigitNo ();
if (gH == 0) {
gHomeRot = llGetRot ();
gHomePos = llGetPos ();
--gH;
}

}



integer getSettings () {
string z = "getParams ";
itisSet = 0; // FALSE
if (debug)
llOwnerSay (z + "gSettingsPtr=" + (string) gSettingsPtr);
string c = getSettingsChar ();
if (debug)
llOwnerSay ("c=" + c);
if (c == "B") {gEnableBell = TRUE; return FALSE;}
if (c == "H") {getH (); gSetUp = TRUE; return FALSE;}
if (c == "Q") {gQ = getDigitNo (); gSetUp = TRUE; return FALSE;}
if (c == ";") {return TRUE;}
llOwnerSay (z + " error want B, H or Q, got " + c);
return (TRUE);
}



integer isSetup () {
integer ok;
ok = TRUE;
return gSetUp;
}







getParams()
{
//if (llGetLinkNumber () == 1)
// llOwnerSay ("This prim is not allowed to be the root prim");
// gSetUp = FALSE;


gDescWords = llParseString2List(llGetObjectDesc(), [";"], []);
integer len = llGetListLength(gDescWords);
if (len > 2) {
gSettings = llList2String(gDescWords, 0);
if (debug)
llOwnerSay ("gSettings=" + gSettings);
gSettingsPtr = 0;
integer fin = FALSE;
while (!fin && (gSettingsPtr < llStringLength (gSettings)))
fin = getSettings ();
if (debug)
llOwnerSay ("gH=" + (string) gH);
if (gH < 0) {
gsRelFulcrum = llList2String (gDescWords, 1);
gRelFulcrum = ((vector) gsRelFulcrum) * llGetRot ();
gsEulDegStep = llList2String (gDescWords, 2);
gEulDegStep = (vector) gsEulDegStep;
gRotStep = llEuler2Rot(gEulDegStep * DEG_TO_RAD); //convert to quaternion
gLever = (-gRelFulcrum);
gActFulcrum = gHomePos + gRelFulcrum;
if (debug)
llOwnerSay ("actFulcrum = " + (string) gActFulcrum);
}
}
if (debug)
llOwnerSay ("gSetUp=" + (string) gSetUp);
}




setParams() {
string settings = "";
if (gEnableBell)
settings += "B";
settings += "H" + (string) gH;
settings += "Q" + (string) gQ;
string parm = settings + ";" + gsRelFulcrum + ";" +
gsEulDegStep + ";" +
(string) gHomePos + ";" +
(string) gHomeRot;
llSetObjectDesc (parm);
if (debug)
llOwnerSay ("setDoorParams: " + parm);
}








close1 () {
string z = "close1 ";
if (debug)
llOwnerSay (z + "gHomePos=" + (string) gHomePos + " gHomeRot=" + (string) gHomeRot);
if (gHomePos.z > 0.1)
llSetPrimitiveParams( [ PRIM_POSITION, gHomePos, PRIM_ROTATION, gHomeRot] );
gH = 0;

}

close () {
getParams ();
gHomePos = (vector) llList2String(gDescWords, 3);
gHomeRot = (rotation) llList2String(gDescWords, 4);
close1 ();
setParams ();
}




open1 () {
string z = "open1 ";
rotation r = llGetRot();
vector p0 = llGetPos ();
gLever *= gRotStep;
if (debug) {
llOwnerSay (z + "gLever = " + (string) gLever);
llOwnerSay (z + "gLever llVecMag = " + (string) llVecMag (gLever));
}
p0 = gActFulcrum + gLever;
llSetPrimitiveParams( [ PRIM_POSITION, p0, PRIM_ROTATION, r * gRotStep] );

if (debug) {
llOwnerSay (z + "new rot = " + (string) llGetRot ());
llOwnerSay (z + "new pos = " + (string) p0);
}
gH++;
if (debug)
llOwnerSay (z + "exit gH=" + (string) gH);
}


open () {
getParams ();
while (gH < gQ)
open1 ();
setParams ();

}



default
{
state_entry()
{
getParams ();
//gScale = llGetScale ();
//llOwnerSay ("gScale=" + (string) gScale);
if (debug) {
llOwnerSay ("relFulcrum=" + (string) gRelFulcrum);
llOwnerSay ("gEulDegStep=" + (string) gEulDegStep);
}

//llOwnerSay ("llVecMag" + (string) llVecMag(relFulcrum));
//relFulcrum /= rot315;
if (debug)
llOwnerSay ("relFulcrum llVecMag = " + (string) llVecMag(gRelFulcrum));
}


touch_start(integer total_number)
{
if (debug)
llOwnerSay("Touched.");
if (gH > 0) {
if (gQ > 0)
close ();
else
open ();

} else
if (gQ > 0)
open ();
else {
getParams ();
open ();
}
}
}

Sander Kuiper
Registered User
Join date: 4 Nov 2006
Posts: 3
Here
11-10-2006 12:43
Found this on these forums some where, im to lazy to search for the link, plus isn't it easier just to post the code:
CODE

// center_position the new "center point"
// rot_amount the amount of rotation. Wait a sec..
vector llOffsetRot(vector center_position, rotation rot_amount)
{
// Are new awesome rotation
rotation new_rot = llGetLocalRot() * rot_amount;

// Offset the position to match
vector currentPos = llGetLocalPos();
vector newPos = center_position + ((currentPos - center_position) * rot_amount);

// HaHa just set it all at once for a "smooth" effect, though not very smooth :(
llSetPrimitiveParams([PRIM_ROTATION, new_rot, PRIM_POSITION, newPos]);

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

Works perfect, attachments require some finissing. Hopefully this will also help other people looking for this.