|
|
|
I already mentioned one overridingly important reason for using PRIM_ROTATION in a child prim: cases in which you need to update the position and rotation simultaneously. This happens in doors and windows, among other things. In these cases, there's no choice but to use PRIM_ROTATION. Also, believe it or not, it is occasionally necessary to set a world-relative position and rotation in a child prim... for example, this is useful in installed, nonmoving link sets that are linked to take advantage of llMessageLinked().
I would recommend that PRIM_ROTATION_CORRECT continue to set the world-relative rotation like PRIM_ROTATION purports to do in order to avoid confusion, and if necessary, add PRIM_ROTATION_LOCAL (and PRIM_POSITION_LOCAL?) that does the equivalent of llSetLocalRot(). Didn't notice this when I posted my feature request
In this event, I'm all for the last proposal here, PRIM_ROTATION_LOCAL and PRIM_ROTATION_CORRECT would be huge benefits. I'm currently working on a project where I really want to update child-prims in a single step, especially with the horrendous lag and packet-loss we've been getting lately, if only the move out of a move/rotate pair makes it through, the result looks awful. I'd prefer it to go through in a single step, this way if it's delayed I don't get pieces floating in odd places or rotated before they've been moved into position. All the functionality (llGetRot() and llGetLocalRot()) is already here as you've mentioned in the original post, it's just a case of setting values in the prim with some degree of sanity. I would of course love to have this sooner rather than later, especially since work has been done on prim-param functions recently that I see no reason to stop now when there are areas that could still be improved before moving onto something else. Are we past the point of no return with this? I.e. is there now too much content that relies on the broken behavior for us to change it now?
I'm afraid we probably are. This bug appears to have been around ever since PRIM_ROTATION and/or llSetRot() in a child prim was implemented. If you look at the forum post I linked to, you can see that people do depend on the current behavior. I think changing this could cause quite a lot of stuff to break, because people tend to experiment with dividing and multiplying quaternions around until things do what they want, without actually knowing how it's supposed to work. Fixing this will probably confuse people even worse and is likely to break some very old content.
I know a fair amount of my stuff relies on the broken behavior, as does that made by people who followed my suggested workaround. I think this bug definitely does need fixing, but I think too much content unfortunately depends on it to fix the behavior in-place. I'm afraid a PRIM_ROTATION_CORRECT style of solution is probably the best way to go. We would need new flags at this point. Fixing the old values is a very bad idea.
That said. You could legacy the old flag value and reuse the name (like what was done with PRIM_TYPE in 1.5.0). It would only bork scripts that were recompiled. It simplifies the documentation if there are PRIM_*_LEGACY flags (for consistency). It makes the documentation look unprofessional to have constants without handles. You don't have to include the PRIM_*_LEGACY flags in drop down box in the script editor but it would be nice if they highlighted. I know old bug is old... but "Recompile scripts in selection" is pretty much permanantly broken now... so it might be a little safer to fix this now. Save still recompiles of course but no end user should be hitting that.
I stumbled upon that problem, too. I agree to Strife Onizuka's suggestion to reassign new values to constants for correct behaviour, though this won't help for llSetRot. My suggestion besides llSetRotCorrect is llSetGlobalRot for a correct implementation of llSetRot. That would complement llSetLocalRot.
Strife's suggestion sounds good.
I think that should be done. I still vote against slamming the PRIM_ROTATION constant to a new value and changing its behavior. I don't like the idea that a simple recompile will take code that worked and make it not work. Someone will invariably go into their ages-old script, change some constant at the top, and suddenly find their rotation math broken. Worse, many people use quaternions without really understanding them fully, so they won't necessarily know how to fix this. Almost no one knows there was a bug in the first place without reading my explanation; see the forum thread linked in the description above.
Rotation math scares people enough. Let's not scare them worse by changing the way their code works out from under them, bolstering their impression that rotation math is not to be trusted. Good point. New flags then but maybe remove the old flags from the highlighter (we don't want to encourage people to use the old flag).
Maybe the new flag should be named PRIM_ROT, short and concise. (i never liked having to type out PRIM_ROTATION) That sounds like a good compromise. I mainly wanted to change the existing ones because I like correctness. but PRIM_ROT sounds just as official as PRIM_ROTATION, so I think it should be done.
And then after that, PRIM_LOCAL_ROT maybe ? Again, I think I want to urge a different path. Having PRIM_POSITION and PRIM_ROT would be confusing. Having PRIM_ROT and a deprecated PRIM_ROTATION seems even more confusing. How will people know which to use? There's no hint in "PRIM_ROT" that this is the new one, the one to use from now on. Plus, "prim rot" sounds like a disease afflicting simulators.
I know it's ugly, but I think we really need to go with PRIM_ROTATION_CORRECT. The thing is, the solution to this is NOT going to be pretty, and I don't think we should let our programmers' aesthetics be injured by something like PRIM_ROTATION_CORRECT. The only thing that would satisfy our sense of API cleanliness would be if PRIM_ROTATION did the right thing in the first place, and it doesn't. We just need to deal with the legacy we have. I don't see PRIM_ROT is confusing, it is what I think it should be, and wish it was anyway, PRIM_ROTATION is a pain to type out, PRIM_ROTATION_CORRECT even more so.
If I had not read this and been aware of the issue, and it was changed to PRIM_ROT, I think I would have seen it become highlighted in the script when it got to PRIM_ROT and I would have left it at that unaware that it had changed. My first problem was that if the root is rotated using llSetPrimitiveParams, than when the link is rotated using the same function, for some angles no rotation takes place. If the root is rotated manually than the rotation works for all angles.
Second problem was that the rotation wasn't relative to the root. I think that the issue you report takes care of the my second problem. Both of our issues are about what happens when llSetPrimitiveParams is used to set the rotation on linked prims. That is why I linked them. I started following the llSetPrimitiveParams() code path which is convoluted (cry) and eventually found this comment (edited for public consumption) in the relevant place:
// [Dev's initials]: this is seriously [$&#*]ed up, but apparently our users work around it Yes, since people have worked around it there is no way to "fix" it because all sorts of content will suddenly break. The only way to resolve the problem is to make a new call, or a new param type (as per the PRIM_ROT vs PRIM_ROTATION_CORRECT) discussion above. (Sigh... it is times like this that I wish we could completely rewrite LSL and the associated callbacks – LSL3!) I'll have to ask Babbage and Don Linden what they think about this bug. Ooh, nice! I was pretty sure about my conclusions, but it's nice to have this confirmed once and for all. I myself have plenty of code that depends on the bug, whether or not I like it, so yeah... just fixing it, tempting though it is, won't work. It really would be nice to have a new param (and don't forget a new function llSetRotCorrect()!) to address this. It'll save us the extra quaternion operations necessary to work , and, according to my description above, the workaround isn't even possible in attachments
You can make it work for child prims of attachments, you just have to pass the root rotation (which is llGetLocalRot() when in the root prim of the attachment) to the child prim in a link message when you're about to play the frame.
oy. just hit my head on this issue, AGAIN.
our transformation API is a complete mess. position is treated differently than rotation. rotation is just plain broken. rotation of attachments is broken. scale is completely ignored. and most obviously, the transformation hierarchy can only be one layer deep. it's embarassing. and it'll be a nightmare to fix. hands Qarl an icepack for his head
Well, thanks for the update, good to know you're aware of it, and good luck! Is there a list of such features, that should be considered in the development of LSL3 or C#?
A conclusion to these comments can be found at http://jira.secondlife.com/browse/MISC-2237
Qarl, please don't fix it! I went through h311 getting my rotating aim-able sensor hud to work and I don't want to do it again
Dahlia - never fear. however it gets fixed, the system needs to maintain backward compatibility for content just like yours.
for example - we might create a new function named "llSetPrimitiveParameters" instead of "llSetPrimitiveParams", and "llSetRotation" instead of "llSetRot"... etc. the old functions would keep their old (busted) behavior. Why isn't there a PRIM_LOCAL_ROTATION yet?
Finally, a Linden understands the mess we have to deal with!
Function renaming* is a good idea but it would require the likewise named functions to also be renamed too, I recommend removing the old functions from the highlighter (god only knows how you do that!) so they can still be used but not clog up the dropdown. Is it non-trivial to add a PRIM_LOCAL_ROTATION parameter to llSetPrimitiveParams? We've been waiting for a fix for two years now, what gives?
Blasphemy! We couldn't have such a simple solution Chris. We need one that breaks huge amounts of content and confuses the heck out of people.
It seems pretty trivial on the face but there are some complications. Code for both attachments and child prims need to be straightened out... then expanded to work with both llGetPrimitiveParms and llSetLinkPrimitiveParams
This seems like the best solution, then mark the other ones for deprecation on the wiki. That way the names still make sense and people know not to use them. Then at some point just get rid of the pages and act like they don't exist On a side note:
That just sounds like being anal. You wouldn't have to rename all the likewise named functions. For anyone that does care they will just go "Huh that is strange. Oh well." , move on and never think about it again. Why make more work than there has to be, just to make it look a little neater. "llSetPrimitiveParameters"
"llSetPrimitiveParams" "llSetRotation" "llSetRot"... etc ... That seems to be the unavoidable short-term workaround. But to a certain degree it also shows, that LSL2 is a dead end. The important comments here are: "Sigh... it is times like this that I wish we could completely rewrite LSL and the associated callbacks - LSL3!" and "our transformation API is a complete mess. position is treated differently than rotation. rotation is just plain broken. rotation of attachments is broken. scale is completely ignored. and most obviously, the transformation hierarchy can only be one layer deep." The only reasonable conclusion that came to my mind is summarized here: http://jira.secondlife.com/browse/MISC-2237 Please, please, PLEASE do not create "llSetPrimitiveParameters()" and deprecate "llSetPrimitiveParams()" as a fix to this issue. While this would, technically, solve the problem, and it might even look tempting from an aesthetic point of view, think of how this will seem to people who were not privy to this conversation. A new LSL programmer, trying to learn the language, will be incredibly confused by the two similarly-named functions, and it will seem incredibly arbitrary that the difference between the two is merely that one works properly. That's the kind of gotcha that would make a language like this very frustrating to learn.
I'd much rather see PRIM_ROTATION_CORRECT and llSetRotCorrect(). I know these look like warts on the language, but at least they serve to make it clear to new LSL programmers that something weird is going on here and that they need to investigate further.
First, anyone who can read can see at the top of the function page not to use functions marked for deprecation. Second just change the page of the old function to say use the new function and link to it, that would be the only thing on its wiki page. Then I don't know about you but last I checked deprecation means at some point the functions listing and page will be removed. If any confusion does occur which I will presume very little will if they read the pages, it will only happen for a short period of time; a few months or so. In the long term I think this is a sacrifice that should be made. Personally if at some point llSetRotCorrect existed but not llSetRot i'd probably get confused as to why its called that. I'm sure either way there might be very little confusion and i'd much rather come out of it with functions names that make more sense, specifically when learning it. My feelings on new function vs new parameter constant: Whichever way we go, it'll be another wart on the language, but there's no way to avoid a wart while still retaining backwards compatibility. So, we ought to pick the less disruptive, more maintainable, and more usable wart – which I think is a new parameter constant, in particular PRIM_ROTATION_CORRECT. I'll elaborate:
Now, eventually – hopefully – LSL2 will be superceded by LSL3 or some other language, and the designers of that language can avoid the mistakes and warts of LSL2. But until that day comes, we're stuck with LSL2, so I want it to be the most usable language it can be. Achieving that requires keeping in mind the realities of human memory and the environment in which the language will be used, rather than pursuing the abstraction of superficial cleanliness. Thank you, Jacek, for a very lucid argument in favor of PRIM_ROTATION_CORRECT. One more argument in its favor occurred to me as I was reading your comment. If LL does go with "llSetPrimitiveParameters()", they would also have to create "llSetLinkPrimitiveParameters()". Furthermore, then we'd have the confusing dichotomy of llSetPrimitiveParameters() and llGetPrimitiveParams() which will make things even more confusing.
Thanks for so clearly describing the problem.
The only reason for choosing function renaming in my mind is to keep the constant names short... which while well meaning causes bigger problems then it solves (hence the asterisk in my previous comment... which I forgot to elaborate on). the big problem with using a token like PRIM_ROTATION_CORRECT is that it only works once. the next time we need to make an adjustment, things just become silly (PRIM_ROTATION_NOTHISONEISTHERIGHTONE.)
and - in 10 years, when this issue is long forgotten, _CORRECT will be out of place. perhaps if we use _CORRECT as a temporary crutch? i'm not sure. we should see what other APIs/languages do when they need to make a change like this. But Qarl, that's also an argument for not going the llSetPrimitiveParameters route. What if you need to make a correction to the functionality of some other prim-param constant? llSetPrimitiveParamerthingies()? The function-renaming route just compounds that problem.
I agree with seeing how other APIs have dealt with this. But Qarl, that's also an argument for not going the llSetPrimitiveParameters route. What if you need to make a correction to the functionality of some other prim-param constant? llSetPrimitiveParamerthingies()? The function-renaming route just compounds that problem.
I agree with seeing how other APIs have dealt with this. @Qarl: Hopefully, this time there will be a suite of unit tests proving beyond a doubt that the mathematics involved are actually correct. Right?
And as Lex says, the problem you mention exists with the "make a new function" strategy too, only to a much, much greater degree. Every time you discover a single parameter is wrong, you'd have to create at least 3 new functions to correct the behavior (Get, Set, and SetLink). If you wanted to be certain that the new function is correct (and thus won't require yet another function being added later), you'd have to create a suite of new unit tests for every parameter it supports (and every argument those parameters accept), rather than just the one parameter that was fixed/added. Both solutions are icky, but I think a new constant is by far the lesser of two icks. (P.S. I certainly hope that we won't still be using LSL2 in the year 2019! You're scaring me, talking like that! o_O) The real answer is that the LSL library functions are supplied in different versions, so that scripts use the version they're compiled with, until the developer sets them to a different version. Which leads into we could do with library support in LSL, and back to the fact that LSL really needs to be taken outside, shot in the head, and replaced with something saner.
So lets go with PRIM_ROTATION_CORRECT until we can get a sensible scripting language in? Versioning is one way. That can be done with libraries or with a version flag (LSL version [2.0|v] with a pulldown offering 1.2, 1.3, 2.0, 2.1, 3.0, ...) or with feature tests (#feature prim_param_rotation_2).
Another way is to create new named or numbered functions (seek, lseek, llseek, or wait, waitpid, wait2, wait3, wait4). As for something saner, I vote for Forth! The underlying bytecode is already stack-oriented. (no, wait, stop, I was kidding, owahhh, that hurts) More seriously, how about LOGO? My votes are for PRIM_ROT_LOCAL and PRIM_ROT_GLOBAL, with an explanation of the deprecated PRIM_ROTATION for those curious. Each would need a new number.
The more serious error is that the code is unmaintainable, so that the crew can't take the time to figure how much time would be required. Finding that sucker is a halting problem of intimidation. The Code of llSetPrimitiveParams, llGetPrimitiveParams, llSetLinkPrimitiveParams, llGetLinkPrimitiveParams and llGetObjectPrimitiveParams has got to be straightened out to maintainable, before some point in the history of Open Grid. In addition to llGetObjectPrimitiveParams(), I'd also like llGetAvatarTarget(), which doesn't seem to be avatar position. I'd also like some way of finding an object in inventory and saying, "Make me look like that, in these listed features." Qarl if we are still using the LSL2 function API in 5 years let alone 10 years... you better hope you are out of the office the day I stop by.
Seriously LSL needs to be rebuilt and redesigned from the ground up. We have been hobbling along for years, we keep slapping new functionality on without properly cutting away the dead wood. Do you know off hand (no cheating) which one of these is deprecated: llPreloadSound or llSoundPreload? I sure don't. The situation is terrible and creating new functions doesn't solve this problem. Now don't forget there is a third option and it was the option taken in 2004. In 2004 the value of PRIM_TYPE (1) was retired, and the constant was assigned a new value (9); this radical change broke code but brought new functionality. I believe Don Linden spear headed the project and it turned out well; all of the bugs in the old interface were fixed and some of the feature suggested were implemented (Guess who suggested twist on spheres _). If you are worried about naming... why not: but if history is any indication of the future, then in 2019 when LL finally has all the bugs worked out it will be Personally I would like C# 3.0 (or better yet 4.0 _) I brought this up last Thursday, along with the obligatory SVC-22, at Simon (San Andrew) Office Hour, and pretty much came to the conclusion that all PrimitiveParams, llGet-llSet, Link and Other, needs to be rewritten, from a blank piece of paper. I don't know what level of development training this would be appropriate for but, a Blank Paper Team should be organized on this legendary problem, as an excersize in Maintainable Code.
Talk about PrimitiveParamatersV4And20 is nonsense, since PRIM_ROT_LOCAL and PRIM_ROT_GLOBAL are just a couple Integers, and it's the underlying code that is a problem of Maintainability. I wonder if all unmaintainable code should be held as a possible effort to hijack Job Security, and penalized Triple Damages. 'Sup guise; totally uneducated, inexperienced, new-as-in-I've-only-been-on-SL-for-less-than-a-week person here to rant for a little while. But hey, I'm the sort of person a fix of this issue would affect, so maybe that makes my opinion a little more useful? Just don't mind the fact that I haven't finished college Calc II, let alone linear algebra (I'm sure it'll be fun though, given what I've tried to read thus far about quaternions), and don't know a thing in the world about API's, the structure of programming languages, or any other important things that make me sound like I'm not a moron and actually know what I'm talking about.
Hm. A bit of a pipe dream, but wouldn't it be possible to do a huge find/replace operation in the affected content's source code to replace the broken function+workaround with the syntax for a corrected implementation, then recompile everything? Surely Linden Labs has access to all the content in Second Life. Just take all the servers down for a few days, explain to the users what's going on and why this is happening, and just do it? If I may input my two cents though, I think that the longer everyone spends debating how to fix the issue, the more instances of the broken function being used will arise. This has been an issue for two years, and there is still no resolution. Think of how many more scripts that utilize the broken llSetRot function and its workaround have been created since the issue was first reported. If the problem is, in fact, just a misplaced operator, then shouldn't priority be placed on just getting a fix out there? LSL is not, from my experiences, something that most people can just pick up without referring to the wiki or some other reference source at some point. As an inexperienced scripter, I knew that from the beginning, and never hesitated to refer to the LSL Portal when I needed to know exactly how to use a function. There's already enough convolution to the current set of functions to justify adding one more. No, it doesn't look very professional to have a dozen revised and depreciated functions out there, but by the same token, is it any more professional to leave a broken function in place? "Rules of rotation older than contact with JIRA. Did not mention correctness. Rules change caught up in committee. Not come through yet."
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
An additional function llGetAttachmentRot should be added to return the rotation of the root of an attachment relative to the attach point (if the object is not attached it should return the same value as llGetRootRotation).