Dora Gustafson Posted December 4, 2011 Share Posted December 4, 2011 I made this script to turn a box-prim 90 degrees around one edge.It is meant to be a general script that works on the same edge no matter the prim orientation.Each touch reverse the direction, it is meant to open and close on touches.integer open=FALSE; float angle=PI_BY_TWO; // angle to turn [radians] turn( float ang, float time) { vector v1 = 0.5*llGetScale()*llGetRot(); rotation deltaRot = llAxisAngle2Rot(llRot2Up(llGetRot()), ang); llSetKeyframedMotion([v1*deltaRot-v1, deltaRot, time], []); } default { state_entry() { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware } touch_end(integer total_number) { open=!open; if (open) turn( angle, 2.0); else turn( -angle, 2.0); } }It works fine as long as the Z axis of the prim is vertical.When it is not vertical the motion goes berserk.To test the math I substituted the KFM with simple llSetPos and llSetRot functions:turn( float ang, float time) { vector v1 = 0.5*llGetScale()*llGetRot(); rotation deltaRot = llAxisAngle2Rot(llRot2Up(llGetRot()), ang); llSetPos(llGetPos()+v1*deltaRot-v1); llSetRot(llGetRot()*deltaRot); }With this I get the end results right for all the orientations that do not work with the KFM function.Am I doing something stupid or is the llSetKeyframedMotion broken? Link to comment Share on other sites More sharing options...
Cerise Sorbet Posted December 4, 2011 Share Posted December 4, 2011 Yes it is still glitchy yet. Rotation along X looks fine, Y can get a strange elliptical movement but the start and end postiitons will be right. It tends to look better when there is a decent amount of translation, mostly or only rotation really shows off the glitchiness. Link to comment Share on other sites More sharing options...
Rolig Loon Posted December 4, 2011 Share Posted December 4, 2011 I'm getting some random glitchiness when I just rotate on Z, too. I've been experimenting wih door scripts. I can create a keyframe - driven door that works beautifully, but one that I Shift-drag a copy of will sometimes have a funny elliptical drift as it rotates. It's frustrating. This is SUCH an easy way to create a smooth rotating door, but that little unpredictable drift during the movement is annoying. Link to comment Share on other sites More sharing options...
Miranda Umino Posted December 4, 2011 Share Posted December 4, 2011 Not broken in this cas . Just debug in displayind llOwnerSay(llList2CSV(yourlistofmotions)); You don t send the same informations between the different clicks For instance with an inital RotX = 30 degrees list=, <-0.500000, 0.000000, 0.000000>, <0.000000, -0.353553, 0.612372, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <0.433013, -0.216531, 0.124957>, <0.353554, 0.530310, -0.306221, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <-0.266800, -0.412352, 0.093720>, <0.438756, -0.163451, 0.529884, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <0.114807, 0.406020, -0.268267>, <-0.657138, 0.245159, 0.089818, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <0.068671, -0.362525, -0.337431>, <-0.100604, -0.486981, 0.502721, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <0.145453, 0.005032, 0.478349>, <-0.266578, 0.650714, 0.074215, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <0.208265, -0.415030, -0.185406>, <-0.642050, -0.254229, -0.152117, 0.707107>, 2.000000, 1.570796[15:01] Object: list=, <-0.267259, -0.401657, -0.131317>, <-0.050111, -0.188837, 0.679581, 0.707107>, 2.000000, 1.570796 I think you want more something like this integer open=FALSE;float angle=PI_BY_TWO; // angle to turn [radians]turn( vector v1, float ang, float time){ rotation deltaRot = llEuler2Rot(<0, 0 , ang>); llSetKeyframedMotion([v1, deltaRot, time], []); llOwnerSay(llList2CSV(["list=",v1, deltaRot, time, llRot2Angle(deltaRot)]));}default{ state_entry() { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware } touch_end(integer total_number) { open=!open; if (open) turn( 0.5* llGetScale(), angle, 2.0); else turn( -0.5* llGetScale(), -angle, 2.0); }} Don t forget that your input to llSKFM are relatives , not absolutes or something like this integer open=FALSE;float angle=PI_BY_TWO; // angle to turn [radians]vector T ;turn( vector v1, float ang, float time){ rotation deltaRot = llEuler2Rot(<0, 0 , ang>); llSetKeyframedMotion([v1, deltaRot, time], []); llOwnerSay(llList2CSV(["list=",v1, deltaRot, time, llRot2Angle(deltaRot)]));}default{ state_entry() { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware T = 0.5* llGetScale() * llGetRot(); } touch_end(integer total_number) { open=!open; if (open) turn( T, angle, 2.0); else turn( -T, -angle, 2.0); }} Link to comment Share on other sites More sharing options...
Dora Gustafson Posted December 4, 2011 Author Share Posted December 4, 2011 Miranda Umino wrote: Not broken in this cas . Just debug in displayind llOwnerSay(llList2CSV(yourlistofmotions)); You don t send the same informations between the different clicks For instance with an inital RotX = 30 degrees That is no wonder since the prim lands in very odd positions and each new click starts wit the position and orientation the prim has when clicked Link to comment Share on other sites More sharing options...
Miranda Umino Posted December 4, 2011 Share Posted December 4, 2011 No , The third click , in your instance , should have exactly the same inputs that the first click . See my code at teh last post You compute in using llGetRot , but rotations in llsetkeyframedmotion rotates always relatively with its actual rotation . You don t need llgetrot Link to comment Share on other sites More sharing options...
Dora Gustafson Posted December 4, 2011 Author Share Posted December 4, 2011 Yes but when the prim has drifted off it is not in same position or rotation as on first click. Only the relative(in the local prim coordinates) values should be the same. llSetKeyframedMotion() uses relative values in the global system. Link to comment Share on other sites More sharing options...
Miranda Umino Posted December 4, 2011 Share Posted December 4, 2011 In relative, you need to send Keyframe 1 : vector T for translation , rotation R , time t1 KeyFrame 2 : Vector -T for translation, ZERO_ROTATION / R, time t2 So Keyframe1 +Keyframe2 = T - T = ZERO_VECTOR for translation, so invariant R * ZERO_ROTATION / R = ZERO_ROTATION , so invariant Link to comment Share on other sites More sharing options...
Miranda Umino Posted December 5, 2011 Share Posted December 5, 2011 integer open=FALSE;float angle=PI_BY_TWO; // angle to turn [radians]vector T ;rotation R;turn( vector v1, rotation deltaRot , float time){ llSetKeyframedMotion([v1, deltaRot, time], []); llSetTimerEvent(time); if ( TRUE) state turning; }default{ state_entry() { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware vector v1 = 0.5*llGetScale()*llGetRot(); rotation deltaRot = llAxisAngle2Rot(llRot2Up(llGetRot()), angle); R = llEuler2Rot(< 0,0,angle>); T = v1*deltaRot-v1; } touch_end(integer total_number) { turn( T, R, 2.0); }}state turning{ timer() { state waiting; }}state waiting{ touch_end(integer t) { T = -T; R = ZERO_ROTATION / R; turn( T, R, 2.0); } } Avoid to be touched while turning , because it can launch a second animation with wrong initial relative values. If you care , use KFM_COMMAND : the commands KFM_PLAY andKFM_STOP Link to comment Share on other sites More sharing options...
Miranda Umino Posted December 5, 2011 Share Posted December 5, 2011 In fact , in your llsetpos code , you do the transformation llGetRot() * deltaRot so the result is a global rotation in the world. It s normal because llSetRot waits a global rotation llSetKeyframedMotion seems to do the inverse : deltaRot * llGetRot() so the result is a local rotation For instance with an initial rotation of 30 degrees on X-Axis llGetRot, <0.258819, 0.000000, 0.000000, 0.965926>,, llRotup, <0.000000, -0.500000, 0.866025>,, deltaRot, <0.000000, -0.353553, 0.612372, 0.707107>,, llGetRot*deltarot, <0.183013, -0.183013, 0.683013, 0.683013>,, deltaror*llGetRot, <0.183013, -0.500000, 0.500000, 0.683013>, after motion<0.18302, -0.49997, 0.49997, 0.68305> turn( float ang, float time){ llOwnerSay( llList2CSV( [ "llGetRot", llGetRot(), "\n", "llRotup",llRot2Up(llGetRot()), "\n", "deltaRot",llAxisAngle2Rot(llRot2Up(llGetRot()), ang),"\n", "llGetRot*deltarot",llGetRot()*llAxisAngle2Rot(llRot2Up(llGetRot()), ang),"\n", "deltaror*llGetRot",llAxisAngle2Rot(llRot2Up(llGetRot()), ang)*llGetRot(),"\n" ] )); vector v1 = 0.5*llGetScale()*llGetRot(); rotation deltaRot = llAxisAngle2Rot(llRot2Up(llGetRot()), ang); llSetKeyframedMotion([v1*deltaRot-v1, deltaRot, time], []); llSleep(time+1.0); llOwnerSay("after motion"+(string)llGetRot());} Taken from the wiki http://wiki.secondlife.com/wiki/Rotation In LSL, the difference between doing a local or global rotation is the order the rotations are evaluated in the statement. This does a local 30 degree rotation by putting the constant 30 degree rotation to the left of the object's starting rotation (myRot). It is like the first operation in the first example above, just twisting the dart 30 degrees around its own long axis. rotation localRot = rot30X * myRot; // do a local rotation by multiplying a constant rotation by a world rotation To do a global rotation, use the same rotation values, but in the opposite order. This is like the second operation in the second example, the dart rotating up and to the right around the world X axis. In this case, the existing rotation (myRot) is rotated 30 degrees around the global X axis. rotation globalRot = myRot * rot30X; // do a global rotation by multiplying a world rotation by a constant rotation Let s guess you want to do the same rotation as in your llsetpos code . You have llGetRot * deltarot = unknownRot * llGetRot Divide per llGetRot llGetRot * deltarot / llGetRot = unknownRot * llGetRot / llGetrot = unknownRot So you should give as parameter to llSetKeyframedMotion: llGetRot * deltarot / llGetRot for the rotation Link to comment Share on other sites More sharing options...
Dora Gustafson Posted December 5, 2011 Author Share Posted December 5, 2011 @Miranda: Thank you for that. You made me see what it takes.If I substitute the rotation part of the OP script with llEuler2Rot(< 0,0,ang>), then it works exactly as I want it to. What confused me is that The transition part is in relative global parameters and the rotation is in relative local parameters.I took it for granted both would be one or the other:smileyvery-happy: In this case a key-frame is defined like this:The prim moves from it's initial position relatively to a point in region coordinates; this is global.The prim rotates from it's initial rotation relatively around one of the prim axis no matter how the prim is orientated; this is local. My final script looks like this: integer open=FALSE;float angle=PI_BY_TWO; // angle to turn [radians]turn( float ang, float time){ vector v1 = 0.5*llGetScale()*llGetRot(); rotation deltaRot = llAxisAngle2Rot(llRot2Up(llGetRot()), ang); llSetKeyframedMotion([v1*deltaRot-v1, llEuler2Rot(< 0,0,ang>), time], []);}default{ state_entry() { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware } touch_end(integer total_number) { open=!open; if (open) turn( angle, 2.0); else turn( -angle, 2.0); }} Note: This script doesn't care for drifting the way Miranda has outlined.This script is basic to the bone and can be refined and specialized in many ways Link to comment Share on other sites More sharing options...
Miranda Umino Posted December 5, 2011 Share Posted December 5, 2011 Ok , now with this version , you finish your movement where you want . Nevertheless , your version has again a problem . What does exactly your prim : - it rotates around the center of the prim - it moves the center of the prim from A to B with a straight line Nevertheless , when you look a door , the center of the door doesn t a movement in a straight line but in a arc of circle . If you are looking carefully your prim when it rotates, near the axis of rotation , your prim goes in the back while it rotates the half of the rotation . In the real your door is sticked to the axis of rotation. For instance let s guess your prim goes from < 1,0,0> to <0,1,0> . At the half , your prim is at <0.5,0.5,0>. A real door should be at <0.707,0.707,0>. So your movement is wrong. Problem : there are no commands in llsetkeyframedmotion to tell to my prim "do a circle" Problem 2 : there are no interpolation of curves in llSetKeyframedmotion . And we NEED it So , you need to create a motion with several keyframes . Each one of translations do an approximation of an arc of circle . For instance with two steps . you go from <1,0,0> to <0.707,0.707,0> ( first keyframe) and from <0.707,0.707,0> to <0,1,0> But you can repeat with several steps . Nevertheless : 1) in every keys , because your translation has a slope different , you will have the feeling it s "jerky" when you go from one key to an another key . 2) more you do some keys , more the movement is realistic . It fits better the movement of rotation between the two points 3) more you do some keys , less the "jerky" effect will be visible , because the difference of slopes between the translations will be smaller 4) unfortunately , you can t repeat this at infinity as in mathematics . Because linden impose 0.1 seconds between every keys . So the soltion of door with llsetkeyframedmotion will have always a "jerky" effect 5) you need to be careful of the time in every keys to be multiple of the time of one frame . 6) more you add keys , more you will have approximations of llsetkeyframedmotion , and more you will have drift . Don t think it s an important drift . It s very light , and for your door , with 2 seconds of rotation you will be limited to 18 keys max , so it won t be important . But there are some animations who could be more important with sveral thousand of keys .Particulary when the movement does many curves . In this cas , you could have signifant errors 7) May it creates some lag with more keys ? While you build your list of keys certainly , but it s done once time . While the animation is played , i don t know . Maybe yes , maybe no , as the interpolation on the sim is done frame per frame , it has maybe no effects Finally , the old trick to rotate doors in cutting them by half to have the center of rotation on one side of the prim will be always useful This is the code to fix the movement of the center of the prim integer open=FALSE;float angle=PI_BY_TWO; // angle to turn [radians]turn( float ang, float time){ list FrameList; integer maxsteps=(integer)(time * 9); float newtime = maxsteps / 9.0; integer i ; vector v1; rotation deltaRot = llAxisAngle2Rot(llRot2Up(llGetRot()), ang/(float)maxsteps); for ( i = 0; i < maxsteps ; i++) { v1 = 0.5*llGetScale() * llEuler2Rot(< 0,0,i * ang/(float)maxsteps>) * llGetRot(); FrameList += [ v1 * deltaRot - v1 , llEuler2Rot(< 0,0,ang/(float)maxsteps>), newtime/(float)maxsteps ]; } llSetTimerEvent(newtime); llSetKeyframedMotion( FrameList, []); if ( TRUE ) state turning; }default{ state_entry() { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware } touch_end(integer total_number) { turn( angle, PI); }}state turning{ timer() { state waitingTouch; }}state waitingTouch{ touch_end(integer t) { llOwnerSay((string)llGetPos()+" "+(string)llGetRot()); angle = - angle; turn( angle, PI); } } Just for information , i display the rotations and positions to every touchs I have , for instance [10:15] Object: <80.78793, 144.08410, 56.51097> <0.18346, 0.01934, 0.57035, 0.80042>[10:15] Object: <98.93296, 105.77510, 40.66754> <0.11606, 0.14340, -0.16267, 0.96928>[10:15] Object: <80.78656, 144.08310, 56.51110> <0.18346, 0.01934, 0.57035, 0.80042>[10:15] Object: <98.93204, 105.77430, 40.66765> <0.11606, 0.14340, -0.16267, 0.96928>[10:15] Object: <80.78549, 144.08220, 56.51120> <0.18346, 0.01934, 0.57035, 0.80042>[10:15] Object: <98.93098, 105.77340, 40.66775> <0.11606, 0.14340, -0.16268, 0.96928>[10:16] Object: <80.78500, 144.08190, 56.51123> <0.18346, 0.01934, 0.57035, 0.80042> As you can see the drift is low but i don t knwow any solutions actually to fix it Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted December 5, 2011 Share Posted December 5, 2011 It's annoying, but at least LL knows about this issue. I opened SVC-7462 and Maestro Linden is able to reproduce it. Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now