llSetPrimitiveParams() bug: any workaround?
|
Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
|
03-19-2006 13:36
Create two prims, link them, then put the following into the touch_start in the child prim: llOwnerSay("Rotating to <0,0,0,1> using llSetPrimitiveParams."); llSetPrimitiveParams([PRIM_ROTATION,<0,0,0,1>]); llOwnerSay("Actual rotation is " + (string)(llGetLocalRot())); llSleep(5); llOwnerSay("Rotating to <0,0,0,1> using llSetLocalRot."); llSetLocalRot(<0,0,0,1>); llOwnerSay("Actual rotation is " + (string)(llGetLocalRot()));
It works fine as long as the root prim isn't rotated. Rotate the root prim, though, and the child prim goes berserk at the llSetPrimitiveParams call, rotating to all kinds of bizarre angles. Does anyone have any idea what's going on and/or if there's a workaround for this? I presume this is a fairly old bug, due to the lack of outcry over newly broken objects in v1.9..
|
Jillian Callahan
Rotary-winged Neko Girl
Join date: 24 Jun 2004
Posts: 3,766
|
03-19-2006 13:42
No, it's predictable rotation in a child prim, you just have to understand how things move in relation to one another. Try this: rotation LocalRot(rotation localrot) { rotation LocRot = localrot / ( (ZERO_ROTATION / llGetLocalRot()) * llGetRot()); return LocRot; }
default { touch_start(integer n) { llSetPrimitiveParams([PRIM_ROTATION,LocalRot(<0,0,0,1>)]); } }
|
Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
|
03-19-2006 13:47
From: Jillian Callahan No, it's predictable rotation in a child prim, you just have to understand how things move in relation to one another. Hmm, ok! So what's actually going on with the llSetPrimitiveParams version? Is that rotation added onto the existing rotation rather than setting it directly? The equation in your functions seems to say "take the rotation, apply the reverse of the current root rotation, then apply the old local rotation" - is that right?
|
Jillian Callahan
Rotary-winged Neko Girl
Join date: 24 Jun 2004
Posts: 3,766
|
03-19-2006 14:09
Take the inverse of the local rotation (rotation relative to the root prim) add the current global roation and subtract the result from the target rotation to get the new relative rotation.
Now, there's probably an easier way to go about that. I'm not all that good with rotations yet.
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
03-19-2006 16:52
I don't use PRIM_ROTATION for this reason. Why LL wrote these functions to work like this is beyond me.
_____________________
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
|
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
|
03-20-2006 02:06
It's even madder in attachments.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
|
Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
|
03-20-2006 07:29
So can anyone explain to me what value PRIM_ROTATION actually sets in this context? It's not local rotation, it's not global rotation, can anyone tell me what it actually is? 
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
03-20-2006 10:14
From: Yumi Murakami So can anyone explain to me what value PRIM_ROTATION actually sets in this context? It's not local rotation, it's not global rotation, can anyone tell me what it actually is? As it turns out, llSetRot() and llSetPrimitiveParams([PRIM_ROTATION]) in child prims are broken! I've done extensive research on this, and I'm quite sure of my result. I've reported it to the lindens. Here's what's wrong. llSetRot( rot) in a child prim should, logically, set the child prim to a world-relative rot that you specify. From what I can tell, rotations of child prims are stored internally in SL as a local rotation from the parent prim. Say the parent prim's rotation is rootRot. If you want to figure out the local rotation to set a child prim to that corresponds to a world-relative rotation rot, you'd do rot/ rootRot. That says "get me rot in terms of rootRot's axes". Instead, llSetRot() internally is implemented to set the child's local rotation to rot * rootRot. Yes. They used the wrong operator. I'm absolutely sure of this. If you want to set a child prim in a link set to an absolute rotation rot, use one of these: rotation rootRot = llGetRootRotation(); llSetRot((rot/rootRot)/rootRot); llSetPrimitiveParams([PRIM_ROTATION,(rot/rootRot)/rootRot);
If you want to just set a local rotation using llSetRot() or llSetPrimitiveParams(), use one of these: rotation rootRot = llGetRootRotation(); llSetRot(rot/rootRot); llSetPrimitiveParams([PRIM_ROTATION,rot/rootRot);
This is a hack, to get around the erroneous multiplication by the root rotation that SL does internally for you. If LL decides to fix llSetRot and llSetPrimitiveParams for child prims, this code will break (but then again, so will any other code using llSetRot() or llSetPrimitiveParams() to set the rotation of a child prim). The only reason why I went through several hours of debugging to trace through and figure out what exactly is happening here is because, for one of my scripts, it was very important that I was able to set the rotation and position of a child prim in one call using llSetPrimitiveParams(). I highly suggest that if this isn't the case for you, you always use llSetLocalRot(), which bypasses the bug. To set a world-relative rotation using llSetLocalRot(): rotation rootRot = llGetRootRotation(); llSetLocalRot(rot/rootRot);
To set a root-relative rotation using llSetLocalRot()... well, that's trivial, just pass the rotation in directly  Let me say again, I'm completely sure of my results here. I know for sure that there's an erroneous multiplication in there, because I've done many tests to figure it out empirically, and it makes perfect sense as the kind of mistake that can slip through the cracks. A few months ago, I'd have been hard pressed to even tell you why multiplying by the root rotation in this case is wrong, but it is. Incidentally, I think all of the math in Jillian's LocalRot function reduces down to this: LocRot = localrot / rootRot;
There's just some calculation of the root rotation from the local and world-relative rotations of the child prim.
|
Soen Eber
Registered User
Join date: 3 Aug 2006
Posts: 428
|
04-09-2007 17:11
Bump so someone can put this in the rotation section of the WIKI, as Bloodsong suggested in /54/85/170765/1.html. This really does need to go to the wiki - I don't know how to make that change, though.
|
Adrian Zobel
Registered User
Join date: 4 Jan 2006
Posts: 49
|
04-10-2007 07:41
I've been using llSetLinkPrimitiveParams() from a script in the root prim without seeing this bug.
I've successfully used [PRIM_ROTATION, rot/rootRot] to make other prims (and sitting avatars) rotate relative to the object, not [PRIM_ROTATION, (rot/rootRot)/rootRot].
I haven't actually tested to see if this affects only llSetLinkPrimitiveParams, or if llSetPrimitiveParams and llSetRot are fixed too.
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
04-11-2007 08:36
From: Adrian Zobel I've been using llSetLinkPrimitiveParams() from a script in the root prim without seeing this bug.
I've successfully used [PRIM_ROTATION, rot/rootRot] to make other prims (and sitting avatars) rotate relative to the object, not [PRIM_ROTATION, (rot/rootRot)/rootRot].
I haven't actually tested to see if this affects only llSetLinkPrimitiveParams, or if llSetPrimitiveParams and llSetRot are fixed too. Huh? If you look at my code above, I said that using [PRIM_ROTATION, rot/rootRot] is for setting a local rotation on a child prim under the broken implementation. [PRIM_ROTATION, (rot/rootRot)/rootRot] was the recipe for setting an absolute rotation on a child prim. I'll go test it myself, but it sounds to me like you've just confirmed that the bug still exists for llSetLinkPrimitiveParams. Hey... when you say "and sitting avatars", do you mean that llSetLinkPrimitiveParams() lets us move sitting avatars?! That's AWESOME!
|
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
|
04-11-2007 09:59
I just really wish they'd combine the functionality of these so that a person could do llSetLinkPrimitiveParams for multiple child prims in one call....or get rid of the delay due to this restriction.
I know that typically I would need to change more than one child at a time, and I hate the look of them moving due to separate scripts and the delays from link messages hitting each prim at different times.
|
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
|
04-11-2007 11:05
From: Tiarnalalon Sismondi I just really wish they'd combine the functionality of these so that a person could do llSetLinkPrimitiveParams for multiple child prims in one call. I'm sure you mean other than using LINK_SET, LINK_ALL_CHILDREN, etc. I also originally thought putting the prim number separate from the rules list was casually sadistic of them, but when I really thought about it, it makes perfect sense. Look at it this way: A rules list contains "commands," which are just aliases to specific integer values, such as PRIM_COLOR or PRIM_TEXTURE, followed by a series of elements of a specific number and type, depending on what the "command" is. e.g. PRIM_COLOR must be followed by an integer, a vector and a float. If any other type appears in those 3 slots, you get a run-time error. The next element in the list, if any, must be another integer representing another command, followed by the required number and types of data for that command, and so on. Now, if integers representing intended prim numbers were to be included in the list, how would they be differentiated from the "command" integers? Say you want to send two different PRIM_COLOR commands to two different prims in the same rules list. Would the syntax be something like: [ PRIM#, PRIM_COLOR, face, color, alpha, PRIM#, PRIM_COLOR, face, color, alpha ] How would the system know that the 2nd PRIM# isn't supposed to be another command intended for the first prim? Would a PRIM# have to precede each individual command? Would a PRIM# be followed by another integer, indicating the number of following commands that would apply to that prim? What if you want to send the same PRIM_COLOR command to 2 different prims? Would you have to duplicate the command and data (as above, assume both sets of data are identical), or would there be a flag to specify that the following x prims are to receive the following y commands? I'm not saying it's not possible, I'm just saying it's not as easy as it might look at first glance. As it is now, it just has to take a single rules list, identical in structure to one which would be passed to llSetPrimitiveParams, and apply it to one or more prims using the link mask. Not ideal, but when you include prim addresses in the rules list, things get a whole lot more complicated.
|
BamBam Sachertorte
floral engineer
Join date: 12 Jul 2005
Posts: 228
|
04-11-2007 11:20
From: Lex Neva Hey... when you say "and sitting avatars", do you mean that llSetLinkPrimitiveParams() lets us move sitting avatars?! That's AWESOME! It's true! You can move an avatar around after they have sat down (rotate them too). Unfortunately the link-set distance rules are applied instead of the much more relaxed sit target rules. I think that this is a bug, but I haven't gotten around to filing it.
|
BamBam Sachertorte
floral engineer
Join date: 12 Jul 2005
Posts: 228
|
04-11-2007 11:38
I updated the LSL Portal with info on this bug. I will go back and put in example code.
|
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
|
04-11-2007 12:28
You are correct in that I was referring to multiples other than the standard groupings.
I can think of several ways around this without having to rewrite the primitiveparams standard set, tho I obviously have no idea if they would be implementable or not.
The easiest would just be to make it where it uses a list instead of a standard single integer so it would be more like llSetLinkPrimitiveParams([1,5,2,99],[PRIM_COLOR...., PRIM_SIZE...]); as I'm pretty sure it would still support something like llSetLinkPrimitiveParams([LINK_SET],[PRIM....]);
The only real downside I see to that would be that the compiler wouldn't be able to catch invalid link numbers until the script actually tried to execute or they would just let it silently fail.
|
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
|
04-11-2007 13:20
From: Tiarnalalon Sismondi llSetLinkPrimitiveParams([1,5,2,99],[PRIM_COLOR...., PRIM_SIZE...]); This would work, at least within the confines of your purpose. I guess I was leaping beyond your question to the next logical step, which has also been asked, "What if we want to send different commands to different prims in a single llSetLinkPrimitiveParams call?" From: someone The only real downside I see to that would be that the compiler wouldn't be able to catch invalid link numbers until the script actually tried to execute or they would just let it silently fail. Which is essentially how all of the link-specific functions we have now operate, anyway.
|
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
|
04-11-2007 16:56
Yea Deanna, I would prefer it the most myself if it was setup like:
llSetLinkPrimitiveParams(LINK#,[Rules],NextLink,[Rules]);
|