
|
If you were logged in you would be able to see more operations.
|
|
|
|
Issue Links:
|
Parent/Child
|
|
|
|
Relates
|
|
|
|
This issue is related to by:
|
|
|
SVC-4580 Positioning & rotating of linked objects changed in server 1.27
|
|
|
|
 |
|
SVC-4476 llSetLinkPrimitiveParams(LINK_SET,[PRIM_ROTATION... yields twice the intended rotation on child prims
|
|
|
|
 |
SVC-2608
llSetPrimitiveParams([PRIM_ROTATION, rot]) doesn't work right
|
|
|
|
 |
SVC-303
rotation around local axis in negative direction fails (quaternion division)
|
|
|
|
 |
|
SVC-129 Need PRIM_LOCAL_ROTATION and PRIM_LOCAL_POSITION to complement llGetLocalRot() and llGetLocalPos()
|
|
|
|
 |
SVC-102
PRIM_LOCALROT for llSetPrimitiveParams()
|
|
|
|
 |
MISC-322
llSetPrimitiveParams-Improvement
|
|
|
|
 |
MISC-104
Local to llSetLinkPrimitiveParams
|
|
|
|
|
|
MISC-2237 [hierarchical linking] Requiered additions and changes to objects and scripting, for improving content-creation capabilities.
|
|
|
|
|
|
|
| Linden Lab Issue ID: |
DEV-1178
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented incorrectly, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim should set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
It's not. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation rot using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimitiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation rot using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Furthermore, llGetRootRotation does not return a meaningful result for child prims in attachments.
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. Simply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
|
Description
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented incorrectly, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim should set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
It's not. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation rot using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimitiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation rot using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Furthermore, llGetRootRotation does not return a meaningful result for child prims in attachments.
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens [1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. Simply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2 |
Show » |
made changes - 06/Apr/07 09:35 AM
| Field |
Original Value |
New Value |
|
Link
|
|
This issue is related to by MISC-104
[ MISC-104
]
|
made changes - 06/Apr/07 09:38 AM
|
Description
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
{code}
llSetLocalRot(llGetLocalRot());
{code}
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
made changes - 06/Apr/07 09:39 AM
|
Description
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
{code}
llSetLocalRot(llGetLocalRot());
{code}
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
made changes - 06/Apr/07 11:12 PM
|
Description
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Furthermore, llGetRootRotation does not return a meaningful result for child prims in attachments.
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
made changes - 11/Apr/07 09:08 AM
|
Link
|
|
This issue is related to by SVC-102
[ SVC-102
]
|
made changes - 24/Apr/07 09:28 AM
|
Link
|
|
This issue is duplicated by SVC-129
[ SVC-129
]
|
made changes - 08/May/07 01:00 PM
|
Summary
|
llSetPrimitiveParams PRIM_POSITION and llSetRot incorrectly implemented for child prims
|
llSetPrimitiveParams PRIM_ROTATION and llSetRot incorrectly implemented for child prims
|
made changes - 09/May/07 03:22 PM
|
Summary
|
llSetPrimitiveParams PRIM_ROTATION and llSetRot incorrectly implemented for child prims
|
LSL -> llSetPrimitiveParams & llSetRot -> PRIM_ROTATION -> Child Prims -> Incorrect
|
made changes - 17/May/07 02:44 PM
|
Linden Lab Issue ID
|
|
SL-43173
|
made changes - 20/Jun/07 09:22 AM
|
Summary
|
LSL -> llSetPrimitiveParams & llSetRot -> PRIM_ROTATION -> Child Prims -> Incorrect
|
llSetPrimitiveParams PRIM_ROTATION and llSetRot incorrectly implemented for child prims
|
made changes - 20/Jun/07 09:23 AM
|
Link
|
|
This issue is related to by MISC-322
[ MISC-322
]
|
made changes - 30/Oct/07 07:19 AM
|
Link
|
|
This issue is related to by SVC-303
[ SVC-303
]
|
made changes - 22/Dec/07 12:57 AM
|
Workflow
|
jira
[ 10814
]
|
jira-2007-12-21
[ 20550
]
|
made changes - 22/Dec/07 01:13 AM
|
Workflow
|
jira
[ 20550
]
|
jira-2007-12-21
[ 21317
]
|
made changes - 22/Dec/07 01:43 AM
|
Workflow
|
jira
[ 21317
]
|
jira-2007-12-21
[ 23011
]
|
made changes - 23/Dec/07 12:09 AM
|
Workflow
|
jira-2007-12-21
[ 23011
]
|
jira-2007-12-22a
[ 48085
]
|
made changes - 23/Dec/07 12:26 AM
|
Workflow
|
jira-2007-12-21
[ 48085
]
|
jira-2007-12-22a
[ 48875
]
|
made changes - 28/Dec/07 10:32 AM
|
Link
|
|
This issue is related to by SVC-129
[ SVC-129
]
|
made changes - 28/Dec/07 10:33 AM
|
Link
|
This issue is duplicated by SVC-129
[ SVC-129
]
|
|
made changes - 14/Jul/08 02:14 PM
|
Link
|
|
This issue is related to by SVC-2608
[ SVC-2608
]
|
made changes - 14/Jul/08 02:28 PM
|
Link
|
|
This issue Relates to SVC-2608
[ SVC-2608
]
|
Andrew Linden made changes - 14/Aug/08 10:21 AM
|
Assignee
|
|
Andrew Linden
[ Andrew Linden
]
|
made changes - 14/Aug/08 11:01 AM
|
Link
|
This issue Relates to SVC-2608
[ SVC-2608
]
|
|
made changes - 13/Nov/08 12:01 PM
|
Workflow
|
jira-2007-12-22a
[ 48875
]
|
jira-2008-11-14
[ 80024
]
|
made changes - 13/Nov/08 04:26 PM
|
Workflow
|
jira-2008-11-14
[ 80024
]
|
jira-2008-11-14a
[ 85926
]
|
made changes - 13/Nov/08 04:37 PM
|
Workflow
|
jira-2008-11-14
[ 85926
]
|
jira-2008-11-14a
[ 89214
]
|
made changes - 13/Nov/08 04:45 PM
|
Workflow
|
jira-2008-11-14
[ 89214
]
|
jira-2008-11-14a
[ 91672
]
|
made changes - 18/Nov/08 10:48 AM
|
Linden Lab Issue ID
|
SL-43173
|
DEV-1178
|
made changes - 21/Jan/09 08:08 PM
|
Link
|
|
This issue is related to by MISC-2237
[ MISC-2237
]
|
made changes - 23/Jun/09 12:16 AM
|
Link
|
|
This issue parent of SVC-4447
[ SVC-4447
]
|
made changes - 30/Jun/09 07:12 PM
|
Link
|
|
This issue is related to by SVC-4476
[ SVC-4476
]
|
made changes - 17/Jul/09 12:32 PM
|
Link
|
|
This issue is related to by SVC-4580
[ SVC-4580
]
|
made changes - 15/Nov/09 04:18 AM
|
Description
|
This bug has been around for at least a year. In short, llSetPrimitiveParams([PRIM_POSITION, ...]) and llSetRot in a child prim is implemented INCORRECTLY, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. llSetLocalRot() sets this rotation verbatim. llSetRot() in a child prim SHOULD set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
llSetLocalRot(llGetLocalRot());
It is, in fact. The following should also be a no-op in a child prim:
llSetRot(llGetRot());
It's NOT. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of llSetRot() in a child prim:
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
The above code uses rotation division. In essence, this says, "tell me rot as a rotation relative to llGetRootRotation()". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
That's right: the internal code that implements llSetRot() and PRIM_ROTATION for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using llSetRot() in a child prim, and to get the same functionality by using llSetLocalRot() as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);. This means that you have no choice but to use the buggy PRIM_ROTATION implementation.
If you must set a child prim to a world-relative rotation "rot" using PRIM_ROTATION (or llSetRot()), use this:
llSetPrimtiiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
If you must set a child prim to a local rotation "rot" using PRIM_ROTATION, use this:
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
Furthermore, llGetRootRotation does not return a meaningful result for child prims in attachments.
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. SImply fixing PRIM_ROTATION will, unfortunately, break a lot of content. A new function, llSetRotCorrectly(), and a new operation, PRIM_ROTATION_CORRECT, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since llSetRot() was first implemented, and was carried on when llSetPrimitiveParams() was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
This bug has been around for at least a year. In short, {{llSetPrimitiveParams([PRIM_POSITION, ...])}} and {{llSetRot}} in a child prim is implemented *incorrectly*, resulting in unexpected results. I've been able to determine the exact nature of the implementation bug and have reported this in the past, but nevertheless the issue remains. I believe this is because rotation math is tricky stuff, so not many people notice that anything is actually wrong.
In a child prim, it the rotation of a child prim is stored internally by SL as a rotation relative to the root prim of the link set. {{llSetLocalRot()}} sets this rotation verbatim. {{llSetRot()}} in a child prim *should* set the prim such that its world-relative rotation is equal to the argument passed.
Logically, the following should be a no-op in a child prim:
{code}
llSetLocalRot(llGetLocalRot());
{code}
It is, in fact. The following should also be a no-op in a child prim:
{code}
llSetRot(llGetRot());
{code}
It's *not*. The result is that the child prim rotates some amount every time the preceding line is run.
Since child prim rotations are stored as a rotation relative to the root prim, the following should be a pseudo-implementation of {{llSetRot()}} in a child prim:
{code}
llSetRot(rotation rot) {
llSetLocalRot(rot/llGetRootRotation());
}
{code}
The above code uses rotation division. In essence, this says, "tell me {{rot}} as a rotation relative to {{llGetRootRotation()}}". This is how quaternions work.
Through extensive testing, I've determined that it's actually implemented as the following:
{code}
llSetRot(rotation rot) {
llSetLocalRot(rot * llGetRootRotation());
}
{code}
That's right: the internal code that implements {{llSetRot()}} and {{PRIM_ROTATION}} for child prims uses a quaternion multiplication when it should use a division. I'm absolutely sure of this.
To work around this, normally it's enough to just avoid using {{llSetRot()}} in a child prim, and to get the same functionality by using {{llSetLocalRot()}} as I showed above. However, if it's critical that the rotation and position of a child prim are set at the same instant, the only possible way to do this is {{llSetPrimitiveParams([PRIM_POSITION, ..., PRIM_ROTATION, ...]);}}. This means that you have no choice but to use the buggy {{PRIM_ROTATION}} implementation.
If you must set a child prim to a world-relative rotation {{rot}} using {{PRIM_ROTATION}} (or {{llSetRot()}}), use this:
{code}
llSetPrimitiveParams([PRIM_ROTATION, (rot / llGetRootRotation) / llGetRootRotation);
{code}
If you must set a child prim to a local rotation {{rot}} using PRIM_ROTATION, use this:
{code}
llSetPrimitiveParams([PRIM_ROTATION, rot/llGetRootRotation]);
{code}
Furthermore, {{llGetRootRotation}} does not return a meaningful result for child prims in attachments.
Those examples both illustrate quaternion math that does not make sense. They only work because of the errant multiply operation carried out behind the scenes. Countless scripters in-world and in the forums have essentially stumbled upon these workarounds by doing various quaternion operations until the right thing happens[1]. I (and possibly others) worked out the actual problem and use the above workarounds routinely when I need to. Simply fixing {{PRIM_ROTATION}} will, unfortunately, break a lot of content. A new function, {{llSetRotCorrectly()}}, and a new operation, {{PRIM_ROTATION_CORRECT}}, will need to be implemented to fix this bug.
As nearly as I can tell, this bug has been around since {{llSetRot()}} was first implemented, and was carried on when {{llSetPrimitiveParams()}} was implemented.
[1] http://forums.secondlife.com/showpost.php?p=943944&postcount=2
|
made changes - 15/Nov/09 09:56 AM
|
Comment
|
[ I have a sculpted object (horse). The linked child prim sculpted leg has the exact same script as a cut box linked prim wing in a bird flying around it.
The bird's wings flap fine as they have for years, now, but the linked horse's leg rotates the whole object (horse) !!
Using llSetLocalRot and the same:
llSetLocalRot( rot * llGetLocalRot() );
llSetPrimitiveParams([PRIM_ROTATION, ( rot* llGetLocalRot() )]);
( I tried changed the leg to plane, cyclinder, torus it still rotates the whole horse )
I change the horse to PHYSICAL (like the bird) and then nothing rotates.
Please fix.
]
|
|
|