Difference between revisions of "Talk:LlSitTarget"

From Second Life Wiki
Jump to navigation Jump to search
(Fixed all the LSL on the page)
 
(58 intermediate revisions by 15 users not shown)
Line 1: Line 1:
==Optimization==
== Unsitting on wrong side or camera rotation ==
<pre>
 
Hi, i am getting frustrated with this. I create a board and set the sit target with
<code>llSitTarget(<0.4, 0.0, 0.0>, ZERO_ROTATION);</code>
and an animation which for "standing". So while the person technical sits, she stands in front of the board.
But I have a problem with that: If the board stand freely, the person unsits right through it towards the other side. I can put the board with the back  facing a large wall. In the case the unsitting is correctly in front of it. But on sit down the camera rotates, so that it is behind the avatar again; on the other side of the wall.
 
If anyone has an idea how to fix, please tell me (even if it is just an idea where to look for more information). --[[User:Maike Short|Maike Short]] 12:41, 24 February 2008 (PST)
 
:You could position the camera with the {{LSLGC|Camera}} functions.  -- [[User:Strife Onizuka|Strife Onizuka]] 04:46, 25 February 2008 (PST)
 
==GetSitTarget==
 
<source lang="lsl2">
list GetSitTarget(integer prim, key av)
list GetSitTarget(integer prim, key av)
{//WARNING: llGetObjectDetails can introduce an error that goes as far as the 5th decimal place.
{//WARNING: llGetObjectDetails can introduce an error that goes as far as the 5th decimal place.
Line 12: Line 24:
         rotation f = llList2Rot(details = (llGetObjectDetails(llGetLinkKey(prim), details) + llGetObjectDetails(av, details)), 1);
         rotation f = llList2Rot(details = (llGetObjectDetails(llGetLinkKey(prim), details) + llGetObjectDetails(av, details)), 1);
      
      
         return [(llRot2Up(f = (llList2Rot(details, 3) / f)) * tp.z * 0.02638) + ((llList2Vector(details, 2) - llList2Vector(details, 0)) / f) - <0.0, 0.0, 0.4>, f];
         return [(llRot2Up(f = (llList2Rot(details, 3) / f)) * tp.z * 0.02638) +
                ((llList2Vector(details, 2) - llList2Vector(details, 0)) / f) - <0.0, 0.0, 0.4>, f];
     }
     }
     return [];
     return [];
}//Written by Strife Onizuka
}//Written by Strife Onizuka
</pre>
</source>
Hi Strife! This version of your GetSitTarget, and the other version on the actual LlSitTarget page, both always return <0.000000, 0.000000, 0.707107, 0.707107> for the rotation. --[[User:MartinRJ Fayray|MartinRJ Fayray]] 07:52, 21 January 2013 (PST)
 
:I haven't touched this in 5 years but I don't see a reason why it should be doing what you say. Are you sure you are using it properly? The prim parameter specifies what prim the location will be local to. The function was written to aid in determining sit targets when making furniture. You have the avatar sit on one object and then you get it's position local to the furniture so you can program in the sit target.
 
:Just to clarify, you are saying that when you sit on an object with the following script in it, you don't get approximately the specified value? -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 20:37, 22 January 2013 (PST)
 
:It seems to work now. No idea what I was doing wrong. Thank you strife!--[[User:MartinRJ Fayray|MartinRJ Fayray]] 07:36, 3 February 2013 (PST)
 
<source lang="lsl2">
vector vOffset = <0,0,1>;
rotation rOffset = <0,0,0,1>;
 
list GetSitTarget(integer prim, key av)
{//WARNING: llGetObjectDetails can introduce an error that goes as far as the 5th decimal place!
//This is highly unlikely to be ever noticed unless compounded over time.
//Do not use while moving (like in a moving vehicle)!!!
    vector tp = llGetAgentSize(av);
    if(tp)
    {
        if(prim == LINK_THIS)//llGetLinkKey doesn't like LINK_THIS
            prim = llGetLinkNumber();
        list details = [OBJECT_POS, OBJECT_ROT];
        rotation f = llList2Rot(details = (llGetObjectDetails(llGetLinkKey(prim), details) + llGetObjectDetails(av, details)), 1);
        rotation r = llList2Rot(details, 3) / f;
        return [((llList2Vector(details, 2) - llList2Vector(details, 0)) / f) + (llRot2Up(r) * tp.z * 0.02638) - <0.0, 0.0, 0.4>, r];
    }
    return [];
}//Written by Strife Onizuka
 
default{
    state_entry(){
        llSitTarget(vOffset, rOffset);
    }
    changed(integer change){
        key id = llAvatarOnSitTarget();
        if(id)
            llOwnerSay("["+llList2CSV([vOffset, rOffset]) +"] ~ [" + llList2CSV(GetSitTarget(LINK_THIS, id))+"]");
    }
}
</source>
 
 
'''Note''': the above two scripts in this paragraph are incorrect. Most notably, the position of an avatar (it's Avatar Center) is NOT dependent on the AgentSize of the seated avatar. I added another script that returns the sit target, below. [[User:Timmy Foxclaw|Timmy Foxclaw]] 10:31, 7 April 2014 (PDT)
 
<source lang="lsl2">
// A script to develop and test sbGetLinkSitTarget
//
// Copyright(c) Timmy Songbird @DreamNation
//              Timmy Foxclaw  @SL,
//              2014
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.')
 
//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:4"
// This script sets a "random"-ish sit target on every prim in an object.
// Recommended for your test is an object existing of two default cubes
// with arbitrary rotations and position. Put this script only in the
// root prim.
//
// The script sets the sit targets on compile or touch. Please touch
// the object after editting one of the prims.
//
// When an avatar (un)sits on one of the prims, the script prints for every
// sit target that has a seated avatar the return value of sbGetLinkSitTarget.
// This value should be (almost) equal to the values passed to llSitTarget.
 
// Example output:
 
// Object: [<0.200000, 0.300000, 0.500000>, <0.100000, 0.150000, 0.120000, 0.976268>] set with llSitTarget on 2 prims.
// Object: [<0.199999, 0.300001, 0.499999>, <0.100000, 0.150000, 0.120000, 0.976268>] returned by sbGetLinkSitTarget(1).
// Object: [<0.199998, 0.300002, 0.499998>, <0.100000, 0.150000, 0.120000, 0.976268>] returned by sbGetLinkSitTarget(2).
 
// GitLocation: tests/sbGetLinkSitTarget_Test.m4s
 
//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:26"
vector sitTarget_pos_link = <0.2, 0.3, 0.5>;
rotation sitTarget_rot_link = <0.1, 0.15, 0.12, 0.9762684>;
 
//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:31"
// Returns the correct values to use for llSitTarget to make
// the currently seated avatar sit in the same way when re-seated.
// If no avatar is currently sitting then [ZERO_VECTOR, ZERO_ROTATION] is returned.
//
// [1] http://wiki.secondlife.com/wiki/User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations#LSL_functions
// [2] http://wiki.secondlife.com/wiki/User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations#Converting_between_coordinate_systems
list sbGetLinkSitTarget(integer link)
{
  // Calling llAvatarOnLinkSitTarget(0) always returns NULL_KEY because the link
  // number of an unlinked prim changes from 0 to 1 as soon as an avatar sits on
  // it. So if 0 was passed then they probably meant 1.
  if (link == 0)
  {
    link = 1;
  }
  key av = llAvatarOnLinkSitTarget(link);
  if (av != NULL_KEY)
  {
    // Get link_pos_oc and link_rot_oc. See table 2 in [1].
    vector link_pos_oc = ZERO_VECTOR;
    rotation link_rot_oc = ZERO_ROTATION;
    if (link > 1)
    {
      list params = llGetLinkPrimitiveParams(link, [PRIM_POS_LOCAL, PRIM_ROT_LOCAL]);
      link_pos_oc = llList2Vector(params, 0);
      link_rot_oc = llList2Rot(params, 1);
    }
    // Find the link number of the seated avatar.
    integer avNum = llGetNumberOfPrims();
    do
    {
        if (av == llGetLinkKey(avNum))
        {
            // Get ac_pos_oc and ac_rot_oc (ac stands for Avatar Center), exactly the same as above
            // except that we don't need to test if avNum > 1, because it always will be.
            list params = llGetLinkPrimitiveParams(avNum, [PRIM_POS_LOCAL, PRIM_ROT_LOCAL]);
            vector ac_pos_oc = llList2Vector(params, 0);
            rotation ac_rot_oc = llList2Rot(params, 1);
 
            // Convert that to link coordinates. See formula (3) in [2].
            vector ac_pos_link = (ac_pos_oc - link_pos_oc) / link_rot_oc;
            rotation ac_rot_link = ac_rot_oc / link_rot_oc;
 
            // Now we have this little vector in the Avatar Center coordinates.
            vector sit_pos_ac = <0.0, 0.0, 0.05>;
 
            // Convert that to link coordinates. See formula (1) in [2].
            vector sit_pos_link = sit_pos_ac * ac_rot_link + ac_pos_link;
 
            // Return the values, accounting for the sit target bug of 0.4m.
            return [sit_pos_link - <0.0, 0.0, 0.4>, ac_rot_link];
        }
    }
    while (--avNum);
  }
  return [ZERO_VECTOR, ZERO_ROTATION];
}
 
setSitTargets()
{
  // Set the same sit target on every prim.
  integer n = llGetNumberOfPrims();
  llSay(0, "[" +  llList2CSV([sitTarget_pos_link, sitTarget_rot_link]) + "] set with llSitTarget on " + (string)n + " prims.");
  do
  {
    llLinkSitTarget(n, sitTarget_pos_link, sitTarget_rot_link);
  }
  while(--n);
}
 
//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:105"
default
{
  state_entry()
  {
    setSitTargets();
  }
 
  touch_start(integer n)
  {
    setSitTargets();
  }
 
  changed(integer change)
  {
    if ((change & CHANGED_LINK))
    {
      integer n = llGetNumberOfPrims();
      do
      {
        key av = llAvatarOnLinkSitTarget(n);
        if (av != NULL_KEY)
        {
          llSay(0, "[" + llList2CSV(sbGetLinkSitTarget(n)) + "] returned by sbGetLinkSitTarget(" + (string)n + ").");
        }
      }
      while(--n);
    }
  }
}
</source>
:Yes the above two scripts are older versions. The 0.05 offset has been tried before. {{User|Talarus Luan}} [https://wiki.secondlife.com/w/index.php?title=LlSitTarget&diff=1179695&oldid=1179694 could not get it to work]. {{User|Talarus Luan}} went on to work out a quadratic equation that provided a more accurate result. See [[#UpdateSitTarget_changes.3F|#UpdateSitTarget changes?]] below. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 12:38, 7 April 2014 (PDT)
 
::Hi Strife. There must be some miscommunication - we seem to be talking about different things. After extensive research (see [[ User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations|this link]], especially the script at the end), I have found that the value is exactly 0.05 and not depend on the height of the avatar in SecondLife. The function sbGetLinkSitTarget as defined in the script above returns the exact values (within the normal floating point round off error of 0.000002 or so), no matter what position and rotation you passed to llSitTarget. Perhaps we can meet in some sandbox in SL? I'd like to understand where your quadratic expression exactly comes in. Maybe you can show me the test object and the tests that you did to determine it. [[User:Timmy Foxclaw|Timmy Foxclaw]] 15:41, 7 April 2014 (PDT)
 
:::I'd love to meet you inworld but my current schedule precludes that for about the next month (it has sucked, I missed my own 10 year birthday). Beyond inserting the changes proposed by others I haven't done any of the work on this myself, I code mostly for the fun of it and do testing in LSLEditor. I have been watching your ACSaR article evolve, I've been thinking it might be worth bringing into the main namespace. I don't know how LL did such a wonderful job of screwing sittargets up. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 19:18, 7 April 2014 (PDT)
 
::::Hey Timmy.  I'm guessing that the quadratic equation to wihch Strife is referring is the one at the end of the [[#UpdateSitTarget_changes.3F|#UpdateSitTarget changes?]] section below, where {{User|Talarus Luan}} arrives at the quadratic equation
 
offset = 0.008906 * z^3 - 0.049831 * z^2 + 0.088967 * z
 
::::where z is avatar height.  If I plug z = 1.16 and z = 2.45 into this equation, I get the values 0.050050466 and 0.049831322 respectively.  The difference between these two values is just 0.000219144, so it's all very close to 0.05.  However, I'd love to know the exact calculation in order to get this right in the next release of OpenSimulator.  On a very unscientific eyeballing, they both seem more accurate than the z * 0.02638 calculation in the script (which has a value range of 0.0306008 to 0.064631) but between these two it's much harder to tell.  How do you perform your measurements? -- [[User:Fenn Meredith|Fenn Meredith]] 16:26, 18 April 2014 (PDT)
 
:::::Hi Fenn, I gave you a test object in SL. It prints out the values. A little drawing would make things a lot more clear but well, that's a bit hard :p. The idea is that if you pass some vector to llSitTarget then you have to add 0.4 to it's Z value to arrive at the same point as the vector in the Avatar center Coordinate system (AC) that points along the Z-axis of that coordinate system (lets call that point S). Hence if you apply no rotation then S is 0.4m above the sittarget, and the AC is 0.05m below that, hence 0.35m above the set sittarget. If you apply a rotation of 180 degrees, they will add up and AC ends up at 0.45m above the set sittarget. While, if you use a rotation of 90 degrees then AC ends up 0.4m above the set sittarget, but 0.05m to the left (or right) of it. The latter is thus the easiest way to distinguish them with a single sit. Here is a script that does that:
 
<source lang="lsl2">
vector sit_pos_link = <0.0, 0.0, 1.0>;
rotation ac_rot_link;
 
default
{
  state_entry()
  {
    vector rot = <90.0, 0.0, 0>;
    ac_rot_link = llEuler2Rot(rot * DEG_TO_RAD);
    llSitTarget(sit_pos_link, ac_rot_link);
  }
 
  changed(integer change)
  {
    if ((change & CHANGED_LINK))
    {
      key av = llAvatarOnSitTarget();
      if (av != NULL_KEY)
      {
        llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
      }
    }
  }
 
  run_time_permissions(integer perm)
  {
    if ((perm & PERMISSION_TRIGGER_ANIMATION))
    {
      key user = llAvatarOnSitTarget();
      if (user)
      {
        integer linkNum = llGetNumberOfPrims();
        do
        {
          if (user == llGetLinkKey(linkNum))
          {
            list params = llGetLinkPrimitiveParams(linkNum, [PRIM_POS_LOCAL, PRIM_SIZE]);
            vector ac_pos_link = llList2Vector(params, 0);
            vector offsets = ac_pos_link - sit_pos_link;
            vector agentSize = llList2Vector(params, 1);
            float z = agentSize.z;
            llSay(0, "The agentSize.z is " + (string)z + " -->\n0.008906 * z^3 - 0.049831 * z^2 + 0.088967 * z = " + (string)(((0.008906 * z - 0.049831) * z + 0.088967) * z));
            llSay(0, "The actual offsets are:\n" + (string)offsets.z + " and " + (string)offsets.y + " (+/- 0.000002)");
            jump end;
          }
        }
        while (--linkNum);
      }
      @end;
    }
  }
}
</source>
 
:::::You can use this script also in opensim to see what it gives there. In 0.8-dev you might also want to print offsets.y / z (which will give -0.02638). [[User:Timmy Foxclaw|Timmy Foxclaw]] 06:25, 20 April 2014 (PDT)
::::::Using your script, it certainly looks like 0.05 is correct (or near as makes no difference).  But I'm surprised you can demonstrate this with such a simple script bearing in mind all the extensive discussion and painstaking curve fitting that went on above and below -- [[User:Fenn Meredith|Fenn Meredith]] 11:46, 23 April 2014 (PDT)
:::::::Coming into this part of the conversation a little bit late, but to clarify a few things: firsly, the sit target most certainly *IS* affected by avatar height (apparently, from offline discussions, it is tied to the length of the thigh "bone"). Secondly, the parabolic curve fitting was necessary to eliminate a significant amount of error in the original linear adjustment that I discovered when working on various projects using UpdateSitTarget. I determined the values empirically, by using an in-world test apparatus that allowed me to visually measure the disparity between the original UpdateSitTarget setting, and the actual llSitTarget positioning. I had numerous subjects (20+ residents) wearing different avatars with a range of heights sit on the test apparatus, and I measured their height and the deviation for each. I plugged the values into a 4th-order equation solver and got the coefficients for a parabolic function which made the deviation as small as possible. Before, the deviation was often very noticeable; afterwards, it was imperceptible in most cases without zooming in to the sub-millimeter level. If you are trying to replicate the LL llSitTarget functionality in OpenSim, I would *strongly* advise against it. Instead, I would suggest harmonizing the avatar's hip bone position set by PRIM_POSITION with the llSitTarget position. Yes, this means that there will be a discrepancy with scripts made for use in SL directly ported to OpenSim, but if you simplify this mess, it makes life REAL easy in that it won't need the UpdateSitTarget correction at all, which is, in my opinion, far preferable.[[User:Talarus Luan|Talarus Luan]] 13:26, 26 July 2014 (PDT)
 
==Using llSetLinkPrimitiveParams for skydiving: why limited to 5m in a linked set?==
llSetLinkPrimitiveParams can be used as a handy tool to adjust an avatar's position and rotation.
This works perfectly when the object consists of 1 prim, with a range for setting the avatar position away to 500m easily!
When there are more prims linked, this offset seems to be limited to 5m (measured with llVecDist). This is an awfull sideeffect!
 
Put this next script inside a prim and sit on the prim, it will bring you to 1000.0 higher then the prim.
Next link this prim to another prim and try again. You will notice you are limited to 5m. My Question: why is this limited?
<source lang="lsl2">
// by Randur Source
 
integer heightcnt = 0;
list heights = [0.0, 1.0, 5.0, 6.0, 10.0, 100.0, 300.0, 500.0, 800.0, 1000.0];
 
default
{
    state_entry()
    {
        llSitTarget(ZERO_VECTOR,ZERO_ROTATION); // Clear the current sittarget for a clear test
        llSetRot(ZERO_ROTATION); // set the prim to no rotation, for simple z axis movement
    }
   
    changed(integer change)
    {
        if (change & CHANGED_LINK) // detect linked prims and avatars
        {
            integer primnum = llGetNumberOfPrims(); // the avatar is the last linked prim
            if (primnum <= 1) // stop if there is only 1 prim
                return;
       
            key avatar = llGetLinkKey(primnum);
            if (llGetAgentSize(avatar) == ZERO_VECTOR) // stop if this is not an avatar
                return;
               
            // loop through the list of test heights:
            for (heightcnt = 0; heightcnt < llGetListLength(heights); heightcnt++)
            {
                float height = llList2Float(heights,heightcnt);
                llSetLinkPrimitiveParams(primnum,[PRIM_POSITION,<0.0,0.0,height>]); // set this to the wanted height using a vector z axis
               
                vector avatarpos = llList2Vector(llGetObjectDetails(avatar,[OBJECT_POS]),0); // detect the avatar position within the sim
                float distance = llVecDist(llGetPos(),avatarpos);
                llOwnerSay("Attempt to move " + llKey2Name(llGetLinkKey(primnum)) +
                          " to " + (string)height + "m high resulting to " + (string)distance + "m");
               
                llSleep(1.0);
            }
            llUnSit(avatar);
        }
    }
}
</source>
 
'''Posted by Sylvio Runo : Answer ''' :
The correct limit is 54 meters.
You can't move a linked object more than 54 meters away from the axis of the root prim.
On SecondLife (other grids like OsGrid, may works diferent) when an agent sit on prim, the agent is attached to it, so the agent is a linked prim of the link set.
 
More information about link rules, you will find here : http://wiki.secondlife.com/wiki/Linkability_Rules [http://wiki.secondlife.com/wiki/Linkability_Rules]
 
==UpdateSitTarget changes?==
I recently worked on a project where I used a version of this function, and it appears that it is a little off. A couple of things I noted: the Z-offset of the sit target is 0.35, not 0.4, and the avatar size doesn't seem to affect this position at all. When I used this function verbatim, I noticed discrepancies between the actual sit target and the set position call. When I changed the script as noted, I got a perfect match. Has the handling of the sit target been changed since this was written? [[User:Talarus Luan|Talarus Luan]] 22:57, 1 July 2009 (UTC)
:Seconded. I wish I'd looked at this discussion before spending an hour on trying to figure out how the code actually behaved. -- [[User:Tonya Souther|Tonya Souther]] 15:11, 19 August 2009 (UTC)
 
::This is news to me but I haven't been in world in ages :( -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 22:56, 20 August 2009 (UTC)
 
:::From some quick testing in 1.40, this seems to be how the "true" offset is computed:
:::1. Start with offset as provided by LSL.
:::2. Add < 0.0 , 0.0 , 0.4 >
:::3. Subtract llRot2Up( rot ) * 0.05
:::[[User:Gregory Maurer|--Gregory Maurer]] 20:00, 28 August 2010 (UTC)
 
::::Confirmed. The following appears to work fine:
<source lang="lsl2">llSetLinkPrimitiveParams(linkNum, [PRIM_POS_LOCAL, pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * 0.05), PRIM_ROT_LOCAL, rot]);</source>
::::This of course using the new <code>PRIM_POS_LOCAL</code> and <code>PRIM_ROT_LOCAL</code> values for simplicity. If one or two others can confirm that the above code works correctly, then I can splice it into the example.<br/>-- '''[[User:Haravikk_Mistral|Haravikk]]''' <sup><small>([[User_talk:Haravikk_Mistral|talk]]|[[Special:Contributions/Haravikk_Mistral|contribs]])</small></sup> 14:16, 26 December 2011 (PST)
 
:::::Be sure to test it with avatars of different shapes, and shoe configurations. I recall that being an issue. {{User|Escort DeFarge}} would know about this best. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 22:05, 26 December 2011 (PST)
 
::::::I tried with my two main avatar appearances, one average human height and one closer to 8 feet tall, and it didn't seem to make a difference. The test I used was a simple object with sit-target set, and a menu allowing it to be repositioned, causing the sit-target to move and if an avatar is seated on it, they will be repositioned using <code>llSetLinkPrimitiveParams()</code> as done above. In my case the position of the avatar was consistent both when sitting on the object (using the sit-target) and being repositioned. Avatar height appears to have no effect, as the sit-target seems to define the avatar's hip-location, which is seemingly the avatar's "centre" when seated. I'll try to run some more tests when I get a chance, as it's possible this behaviour may not hold true if the object doesn't have a sit-target on it. The height of the avatar does however have a marked visual impact, depending exactly what you're trying to line up where, but that's a general issue with sitting on objects.<br/>-- '''[[User:Haravikk_Mistral|Haravikk]]''' <sup><small>([[User_talk:Haravikk_Mistral|talk]]|[[Special:Contributions/Haravikk_Mistral|contribs]])</small></sup> 05:38, 28 December 2011 (PST)
:::::::Sorry for my long delay in responding. Due to various RL issues and SL/LL burnout, I took a year off from SL to pursue other activities. That said, it seems to work fine to me, Haravikk; however, I have not done exhaustive testing with tons of different avs, shoes, etc. I would consider going ahead and changing it, because the version as it is right now is not correct for the majority of avatars, regardless. If Escort DeFarge or someone else wants to amend it later to include edge cases, that's great, but a better base accuracy is more important at this point. In fact, I think I will go ahead and edit it in, since it has been so long anyway.[[User:Talarus Luan|Talarus Luan]] 12:12, 5 July 2013 (PDT)
:::::::Holding up on the edit, further testing is revealing that if the script is in a prim other than the root, it is off by varying amounts depending on the rotation.[[User:Talarus Luan|Talarus Luan]] 12:39, 5 July 2013 (PDT)
:::::::OK, I think I found the error. Still need to keep the local position/rotation values for the child prim the script is in, like so:
<source lang="lsl2">llSetLinkPrimitiveParams(linkNum, PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * 0.05)) * localrot + localpos, PRIM_ROT_LOCAL, rot * localrot]);</source>
:::::::I'll hold off on the edit until I can get another verify that this code is good.[[User:Talarus Luan|Talarus Luan]] 12:51, 5 July 2013 (PDT)
:::::::OK. I think I have analyzed this to death today and have come to the conclusion that Strife's original code is largely correct, but the error I am seeing comes from the "magic constants" 0.4 and 0.02638. Haravikk's code is simply a reduced form of Strife's code. The 0.4 magic constant is still there, but Haravikk is using just a close, but fixed, magic constant of 0.05 instead of Strife's (size.z * 0.02638), which comes out very close to 0.5 for most normal human avs. Thus, I am concluding that the inaccuracy is in the "magic constants" themselves, and I am going to hold off on the edit until I can get some more information on the source of these constants and see if there are better, more accurate values. It is annoying that, in all these years, we still haven't gotten LL to just tell us what the damn difference is between avatar sit targets and local position offsets in a linkset. It can't be that hard for someone who is familiar with the code to look at it and document it. -.- [[User:Talarus Luan|Talarus Luan]] 13:24, 5 July 2013 (PDT)
 
::::::::Welcome back! I'd like to take credit for that but that's the part that Escort contributed. As to where 0.02638 comes from, I vaguely recall it came from Escort's testing. I was driven more by "wouldn't it be cool to write a function that..." than anything else. I do agree the values have always been not quite right. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 23:10, 5 July 2013 (PDT)
:::::::::Thanks! OK, I did a bunch of empirical testing, sampling a bunch of avatars from 1.16m to 2.45m in height, as reported by llGetAgentSize. I picked the lowest and highest and one about standard height, and fitted a parabolic curve through them. I have reduced the inaccuracies to a great degree, but it still isn't 100% perfect for all sizes in that range, just the ones that I used to solve the curve equation. The rest show a *tiny* bit of movement, but they are very close. Obviously, the difference isn't parabolic, probably just some kind of discrete step function, but it works.[[User:Talarus Luan|Talarus Luan]] 11:16, 14 July 2013 (PDT)
<source lang="lsl2">vector vCoefficients = <0.008906,-0.049831,0.088967>;
float fAdjust = vCoefficients.x * size.z * size.z + vCoefficients.y * size.z + vCoefficients.z;
llSetLinkPrimitiveParamsFast(linkNum,
    [PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * size.z * fAdjust)) * localrot + localpos,
    PRIM_ROT_LOCAL, rot * localrot]);</source>
 
::::::::::I see you mind reading abilities haven't diminished (I contemplated suggesting the tests you have done, decided to go to bed instead). Any reason not to use parentheses? It looks like something that could get optimized to an a series of FMAs (by the VM). -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 21:33, 14 July 2013 (PDT)
 
<source lang="lsl2">vector vCoefficients = <0.008906,-0.049831,0.088967>;
float fAdjust = ((((vCoefficients.x * size.z) + vCoefficients.y) * size.z) + vCoefficients.z) * size.z;
llSetLinkPrimitiveParamsFast(linkNum,
    [PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * fAdjust)) * localrot + localpos,
    PRIM_ROT_LOCAL, rot * localrot]);</source>
:::::::::::Yeah, I thought about optimizing it a bit after I posted it, but decided to leave it unoptimized here so the path from the current function to this change was clear, for demonstrability purposes. Besides, I had to leave some room for it to be Strifed&trade;. :P [[User:Talarus Luan|Talarus Luan]] 15:17, 17 July 2013 (PDT)
 
::::::::::::I appreciate the gesture :p and I'm not as bad as I use to be. I'm not going to optimize out fAdjust, it's more readable this way. This is more for myself later as my memory is crap, the reasoning behind using llRot2Up is that it solves the pesky problem of the quaternion not having a magnitude of one. While the following isn't optimal, it is cool. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 00:00, 18 July 2013 (PDT)
<source lang="lsl2">
size.x = (size.z * (size.y = (size.z * size.z)));
float fAdjust = vCoefficients * size;
</source>
:::::::::::::Yeah, that is a nice way to represent it, for those used to the LSL representation for vector dot product. I'm a little less enthused about the size vector assignment chain, but that's just my general dislike for C value assignments and such. In my mind, I separate assignments from expressions, so seeing them mixed together causes a bit of a train wreck in my brain's lexical analyzer. :P[[User:Talarus Luan|Talarus Luan]] 10:00, 21 July 2013 (PDT)
 
::::::::::::::I don't think anyone uses the LSL vector dot product. It took me three days to remember it existed and then I look up the syntax just to make sure I wasn't crazy (yes yes, I agree it's insane to think that looking up the syntax of an obscure feature is proof against insanity but I'm sticking to it, my cat agrees). I think a train wreck was my goal. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 11:13, 21 July 2013 (PDT)
 
== Avatars Floating After Sit ==
 
The position of avatars will sometimes change, generally noticeable as a rise on the Z axis of perhaps half a meter - common triggers for this is typing or another AV sitting on the same object - though these are not exhaustive.  Does anyone have a clue why this happens, and how to prevent it from happening? [[User:TaraLi Jie|TaraLi Jie]] 21:14, 11 March 2012 (PDT)
 
:Hmm, there are a few possible causes, but the main cause are the animations involved, so it's worth remembering that any animation overrider can potentially cause weirdness while on a sit-target, which is why most good ones can turn themselves off while seated. It's a bit difficult to describe specific problems with animations, but I think that sometimes it can be caused by animations that have a weird first frame, since it's used to calculate all the offsets etc. for the rest of the animation; normally this will be a neutral pose since you don't actually see it in the animation, but if it's something odd then it can mess with positioning. -- <br/>-- '''[[User:Haravikk_Mistral|Haravikk]]''' <sup><small>([[User_talk:Haravikk_Mistral|talk]]|[[Special:Contributions/Haravikk_Mistral|contribs]])</small></sup> 05:34, 12 March 2012 (PDT)
 
::When I've had problems with this, the root cause has usually been that I've (or something has) inadvertently stopped an animation that's holding the avatar in place before starting another one.  Because animations are all made differently, neither the animator with whom I work most of the time nor I have ever managed to figure out exactly what to avoid, but certainly when it happens to me, I always start debugging by looking very carefully at where I'm turning animations off and considering whether, in fact, I need to turn them off at all.  Quite often, I find that simply turning off the default sit animation when my first animation starts, and then keeping the first animation going throughout, starting and stopping other ones over it, as necessary, solves the problem.
 
::One "gotcha" is that stopping an animation and then immediately restarting it doesn't work.  It confuses the viewer something horrible, and often leads to people floating in mid-air.  [[User:Innula Zenovka|Innula Zenovka]] 09:04, 12 March 2012 (PDT)
 
:::In developing a multi-sit script, I did some experiments. I did 20 tests using only llSitTarget() and every time that I started typing, my avatar shifted up. I then did 20 tests in which I repositioned myself using SLPPF after sitting.  My avatar position didn't jump on typing in any of the 20 tests with SLPPF. Looking hopeful. [[User:Omei Qunhua|Omei Qunhua]] 11:54, 11 May 2014 (PDT)
 
::::Yeah SLPPF rocks. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 18:28, 11 May 2014 (PDT)
 
== Sit Target 0.4m 'bug' ==
The notes say
"rot affects the position of the sit-target in a buggy way way.
To correct for the rot bug, simply subtract <0,0,0.4> from the position when rot is zero. See example below."
 
But the example script adjusts z by 0.4m when rotation is NOT zero.
<source lang="lsl2">
if (rot!=ZERO_ROTATION) pos -=<0,0,0.4>;  //here is the work around
</source>
 
Which should it be?
 
I've just been doing some tests without any 0.4m adjustment, and I am unable to observe any difference in my z position whether rotation is zero or not. Has something changed? If so, wouldn't the change screw up some furniture?
[[User:Omei Qunhua|Omei Qunhua]] 14:09, 16 March 2014 (PDT)
 
:You are right, there shouldn't be a test there. My understanding is that you always need to subtract 0.4 from z. Changing it would screw up furniture. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 21:02, 16 March 2014 (PDT)
 
::Then, Strife, the notes and the example need correcting. Do you have sufficient understanding to word it as it should be? Not sure that I do. [[User:Omei Qunhua|Omei Qunhua]] 01:42, 12 May 2014 (PDT)

Latest revision as of 00:01, 31 July 2016

Unsitting on wrong side or camera rotation

Hi, i am getting frustrated with this. I create a board and set the sit target with llSitTarget(<0.4, 0.0, 0.0>, ZERO_ROTATION); and an animation which for "standing". So while the person technical sits, she stands in front of the board. But I have a problem with that: If the board stand freely, the person unsits right through it towards the other side. I can put the board with the back facing a large wall. In the case the unsitting is correctly in front of it. But on sit down the camera rotates, so that it is behind the avatar again; on the other side of the wall.

If anyone has an idea how to fix, please tell me (even if it is just an idea where to look for more information). --Maike Short 12:41, 24 February 2008 (PST)

You could position the camera with the Camera functions. -- Strife Onizuka 04:46, 25 February 2008 (PST)

GetSitTarget

list GetSitTarget(integer prim, key av)
{//WARNING: llGetObjectDetails can introduce an error that goes as far as the 5th decimal place.
    vector tp = llGetAgentSize(av);
    if(tp)
    {
        if(prim == LINK_THIS)//llGetLinkKey doesn't like LINK_THIS
            prim = llGetLinkNumber();
    
        list details = OBJECT_POS + (list)OBJECT_ROT;
        rotation f = llList2Rot(details = (llGetObjectDetails(llGetLinkKey(prim), details) + llGetObjectDetails(av, details)), 1);
    
        return [(llRot2Up(f = (llList2Rot(details, 3) / f)) * tp.z * 0.02638) +
                ((llList2Vector(details, 2) - llList2Vector(details, 0)) / f) - <0.0, 0.0, 0.4>, f];
    }
    return [];
}//Written by Strife Onizuka

Hi Strife! This version of your GetSitTarget, and the other version on the actual LlSitTarget page, both always return <0.000000, 0.000000, 0.707107, 0.707107> for the rotation. --MartinRJ Fayray 07:52, 21 January 2013 (PST)

I haven't touched this in 5 years but I don't see a reason why it should be doing what you say. Are you sure you are using it properly? The prim parameter specifies what prim the location will be local to. The function was written to aid in determining sit targets when making furniture. You have the avatar sit on one object and then you get it's position local to the furniture so you can program in the sit target.
Just to clarify, you are saying that when you sit on an object with the following script in it, you don't get approximately the specified value? -- Strife (talk|contribs) 20:37, 22 January 2013 (PST)
It seems to work now. No idea what I was doing wrong. Thank you strife!--MartinRJ Fayray 07:36, 3 February 2013 (PST)
vector vOffset = <0,0,1>;
rotation rOffset = <0,0,0,1>;

list GetSitTarget(integer prim, key av)
{//WARNING: llGetObjectDetails can introduce an error that goes as far as the 5th decimal place!
 //This is highly unlikely to be ever noticed unless compounded over time.
 //Do not use while moving (like in a moving vehicle)!!!
    vector tp = llGetAgentSize(av);
    if(tp)
    {
        if(prim == LINK_THIS)//llGetLinkKey doesn't like LINK_THIS
            prim = llGetLinkNumber();
 
        list details = [OBJECT_POS, OBJECT_ROT];
        rotation f = llList2Rot(details = (llGetObjectDetails(llGetLinkKey(prim), details) + llGetObjectDetails(av, details)), 1);
        rotation r = llList2Rot(details, 3) / f;
 
        return [((llList2Vector(details, 2) - llList2Vector(details, 0)) / f) + (llRot2Up(r) * tp.z * 0.02638) - <0.0, 0.0, 0.4>, r];
    }
    return [];
}//Written by Strife Onizuka

default{
    state_entry(){
        llSitTarget(vOffset, rOffset);
    }
    changed(integer change){
        key id = llAvatarOnSitTarget();
        if(id)
            llOwnerSay("["+llList2CSV([vOffset, rOffset]) +"] ~ [" + llList2CSV(GetSitTarget(LINK_THIS, id))+"]");
    }
}


Note: the above two scripts in this paragraph are incorrect. Most notably, the position of an avatar (it's Avatar Center) is NOT dependent on the AgentSize of the seated avatar. I added another script that returns the sit target, below. Timmy Foxclaw 10:31, 7 April 2014 (PDT)

// A script to develop and test sbGetLinkSitTarget
//
// Copyright(c) Timmy Songbird @DreamNation
//              Timmy Foxclaw  @SL,
//              2014
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.')

//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:4"
// This script sets a "random"-ish sit target on every prim in an object.
// Recommended for your test is an object existing of two default cubes
// with arbitrary rotations and position. Put this script only in the
// root prim.
//
// The script sets the sit targets on compile or touch. Please touch
// the object after editting one of the prims.
//
// When an avatar (un)sits on one of the prims, the script prints for every
// sit target that has a seated avatar the return value of sbGetLinkSitTarget.
// This value should be (almost) equal to the values passed to llSitTarget.

// Example output:

// Object: [<0.200000, 0.300000, 0.500000>, <0.100000, 0.150000, 0.120000, 0.976268>] set with llSitTarget on 2 prims.
// Object: [<0.199999, 0.300001, 0.499999>, <0.100000, 0.150000, 0.120000, 0.976268>] returned by sbGetLinkSitTarget(1).
// Object: [<0.199998, 0.300002, 0.499998>, <0.100000, 0.150000, 0.120000, 0.976268>] returned by sbGetLinkSitTarget(2).

// GitLocation: tests/sbGetLinkSitTarget_Test.m4s

//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:26"
vector sitTarget_pos_link = <0.2, 0.3, 0.5>;
rotation sitTarget_rot_link = <0.1, 0.15, 0.12, 0.9762684>;

//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:31"
// Returns the correct values to use for llSitTarget to make
// the currently seated avatar sit in the same way when re-seated.
// If no avatar is currently sitting then [ZERO_VECTOR, ZERO_ROTATION] is returned.
//
// [1] http://wiki.secondlife.com/wiki/User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations#LSL_functions
// [2] http://wiki.secondlife.com/wiki/User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations#Converting_between_coordinate_systems
list sbGetLinkSitTarget(integer link)
{
  // Calling llAvatarOnLinkSitTarget(0) always returns NULL_KEY because the link
  // number of an unlinked prim changes from 0 to 1 as soon as an avatar sits on
  // it. So if 0 was passed then they probably meant 1.
  if (link == 0)
  {
    link = 1;
  }
  key av = llAvatarOnLinkSitTarget(link);
  if (av != NULL_KEY)
  {
    // Get link_pos_oc and link_rot_oc. See table 2 in [1].
    vector link_pos_oc = ZERO_VECTOR;
    rotation link_rot_oc = ZERO_ROTATION;
    if (link > 1)
    {
      list params = llGetLinkPrimitiveParams(link, [PRIM_POS_LOCAL, PRIM_ROT_LOCAL]);
      link_pos_oc = llList2Vector(params, 0);
      link_rot_oc = llList2Rot(params, 1);
    }
    // Find the link number of the seated avatar.
    integer avNum = llGetNumberOfPrims();
    do
    {
        if (av == llGetLinkKey(avNum))
        {
            // Get ac_pos_oc and ac_rot_oc (ac stands for Avatar Center), exactly the same as above
            // except that we don't need to test if avNum > 1, because it always will be.
            list params = llGetLinkPrimitiveParams(avNum, [PRIM_POS_LOCAL, PRIM_ROT_LOCAL]);
            vector ac_pos_oc = llList2Vector(params, 0);
            rotation ac_rot_oc = llList2Rot(params, 1);

            // Convert that to link coordinates. See formula (3) in [2].
            vector ac_pos_link = (ac_pos_oc - link_pos_oc) / link_rot_oc;
            rotation ac_rot_link = ac_rot_oc / link_rot_oc;

            // Now we have this little vector in the Avatar Center coordinates.
            vector sit_pos_ac = <0.0, 0.0, 0.05>;

            // Convert that to link coordinates. See formula (1) in [2].
            vector sit_pos_link = sit_pos_ac * ac_rot_link + ac_pos_link;

            // Return the values, accounting for the sit target bug of 0.4m.
            return [sit_pos_link - <0.0, 0.0, 0.4>, ac_rot_link];
        }
    }
    while (--avNum);
  }
  return [ZERO_VECTOR, ZERO_ROTATION];
}

setSitTargets()
{
  // Set the same sit target on every prim.
  integer n = llGetNumberOfPrims();
  llSay(0, "[" +  llList2CSV([sitTarget_pos_link, sitTarget_rot_link]) + "] set with llSitTarget on " + (string)n + " prims.");
  do
  {
    llLinkSitTarget(n, sitTarget_pos_link, sitTarget_rot_link);
  }
  while(--n);
}

//----------------------------------------------------------------------------
//#line "/opt/secondlife/scripts/scripts/tests/sbGetLinkSitTarget_Test.m4s:105"
default
{
  state_entry()
  {
    setSitTargets();
  }

  touch_start(integer n)
  {
    setSitTargets();
  }

  changed(integer change)
  {
    if ((change & CHANGED_LINK))
    {
      integer n = llGetNumberOfPrims();
      do
      {
        key av = llAvatarOnLinkSitTarget(n);
        if (av != NULL_KEY)
        {
          llSay(0, "[" + llList2CSV(sbGetLinkSitTarget(n)) + "] returned by sbGetLinkSitTarget(" + (string)n + ").");
        }
      }
      while(--n);
    }
  }
}
Yes the above two scripts are older versions. The 0.05 offset has been tried before. Talarus Luan could not get it to work. Talarus Luan went on to work out a quadratic equation that provided a more accurate result. See #UpdateSitTarget changes? below. -- Strife (talk|contribs) 12:38, 7 April 2014 (PDT)
Hi Strife. There must be some miscommunication - we seem to be talking about different things. After extensive research (see this link, especially the script at the end), I have found that the value is exactly 0.05 and not depend on the height of the avatar in SecondLife. The function sbGetLinkSitTarget as defined in the script above returns the exact values (within the normal floating point round off error of 0.000002 or so), no matter what position and rotation you passed to llSitTarget. Perhaps we can meet in some sandbox in SL? I'd like to understand where your quadratic expression exactly comes in. Maybe you can show me the test object and the tests that you did to determine it. Timmy Foxclaw 15:41, 7 April 2014 (PDT)
I'd love to meet you inworld but my current schedule precludes that for about the next month (it has sucked, I missed my own 10 year birthday). Beyond inserting the changes proposed by others I haven't done any of the work on this myself, I code mostly for the fun of it and do testing in LSLEditor. I have been watching your ACSaR article evolve, I've been thinking it might be worth bringing into the main namespace. I don't know how LL did such a wonderful job of screwing sittargets up. -- Strife (talk|contribs) 19:18, 7 April 2014 (PDT)
Hey Timmy. I'm guessing that the quadratic equation to wihch Strife is referring is the one at the end of the #UpdateSitTarget changes? section below, where Talarus Luan arrives at the quadratic equation
offset = 0.008906 * z^3 - 0.049831 * z^2 + 0.088967 * z
where z is avatar height. If I plug z = 1.16 and z = 2.45 into this equation, I get the values 0.050050466 and 0.049831322 respectively. The difference between these two values is just 0.000219144, so it's all very close to 0.05. However, I'd love to know the exact calculation in order to get this right in the next release of OpenSimulator. On a very unscientific eyeballing, they both seem more accurate than the z * 0.02638 calculation in the script (which has a value range of 0.0306008 to 0.064631) but between these two it's much harder to tell. How do you perform your measurements? -- Fenn Meredith 16:26, 18 April 2014 (PDT)
Hi Fenn, I gave you a test object in SL. It prints out the values. A little drawing would make things a lot more clear but well, that's a bit hard :p. The idea is that if you pass some vector to llSitTarget then you have to add 0.4 to it's Z value to arrive at the same point as the vector in the Avatar center Coordinate system (AC) that points along the Z-axis of that coordinate system (lets call that point S). Hence if you apply no rotation then S is 0.4m above the sittarget, and the AC is 0.05m below that, hence 0.35m above the set sittarget. If you apply a rotation of 180 degrees, they will add up and AC ends up at 0.45m above the set sittarget. While, if you use a rotation of 90 degrees then AC ends up 0.4m above the set sittarget, but 0.05m to the left (or right) of it. The latter is thus the easiest way to distinguish them with a single sit. Here is a script that does that:
vector sit_pos_link = <0.0, 0.0, 1.0>;
rotation ac_rot_link;

default
{
  state_entry()
  {
    vector rot = <90.0, 0.0, 0>;
    ac_rot_link = llEuler2Rot(rot * DEG_TO_RAD);
    llSitTarget(sit_pos_link, ac_rot_link);
  }

  changed(integer change)
  {
    if ((change & CHANGED_LINK))
    {
      key av = llAvatarOnSitTarget();
      if (av != NULL_KEY)
      {
        llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
      }
    }
  }

  run_time_permissions(integer perm)
  {
    if ((perm & PERMISSION_TRIGGER_ANIMATION))
    {
      key user = llAvatarOnSitTarget();
      if (user)
      {
        integer linkNum = llGetNumberOfPrims();
        do
        {
          if (user == llGetLinkKey(linkNum))
          {
            list params = llGetLinkPrimitiveParams(linkNum, [PRIM_POS_LOCAL, PRIM_SIZE]);
            vector ac_pos_link = llList2Vector(params, 0);
            vector offsets = ac_pos_link - sit_pos_link;
            vector agentSize = llList2Vector(params, 1);
            float z = agentSize.z;
            llSay(0, "The agentSize.z is " + (string)z + " -->\n0.008906 * z^3 - 0.049831 * z^2 + 0.088967 * z = " + (string)(((0.008906 * z - 0.049831) * z + 0.088967) * z));
            llSay(0, "The actual offsets are:\n" + (string)offsets.z + " and " + (string)offsets.y + " (+/- 0.000002)");
            jump end;
          }
        }
        while (--linkNum);
      }
      @end;
    }
  }
}
You can use this script also in opensim to see what it gives there. In 0.8-dev you might also want to print offsets.y / z (which will give -0.02638). Timmy Foxclaw 06:25, 20 April 2014 (PDT)
Using your script, it certainly looks like 0.05 is correct (or near as makes no difference). But I'm surprised you can demonstrate this with such a simple script bearing in mind all the extensive discussion and painstaking curve fitting that went on above and below -- Fenn Meredith 11:46, 23 April 2014 (PDT)
Coming into this part of the conversation a little bit late, but to clarify a few things: firsly, the sit target most certainly *IS* affected by avatar height (apparently, from offline discussions, it is tied to the length of the thigh "bone"). Secondly, the parabolic curve fitting was necessary to eliminate a significant amount of error in the original linear adjustment that I discovered when working on various projects using UpdateSitTarget. I determined the values empirically, by using an in-world test apparatus that allowed me to visually measure the disparity between the original UpdateSitTarget setting, and the actual llSitTarget positioning. I had numerous subjects (20+ residents) wearing different avatars with a range of heights sit on the test apparatus, and I measured their height and the deviation for each. I plugged the values into a 4th-order equation solver and got the coefficients for a parabolic function which made the deviation as small as possible. Before, the deviation was often very noticeable; afterwards, it was imperceptible in most cases without zooming in to the sub-millimeter level. If you are trying to replicate the LL llSitTarget functionality in OpenSim, I would *strongly* advise against it. Instead, I would suggest harmonizing the avatar's hip bone position set by PRIM_POSITION with the llSitTarget position. Yes, this means that there will be a discrepancy with scripts made for use in SL directly ported to OpenSim, but if you simplify this mess, it makes life REAL easy in that it won't need the UpdateSitTarget correction at all, which is, in my opinion, far preferable.Talarus Luan 13:26, 26 July 2014 (PDT)

Using llSetLinkPrimitiveParams for skydiving: why limited to 5m in a linked set?

llSetLinkPrimitiveParams can be used as a handy tool to adjust an avatar's position and rotation. This works perfectly when the object consists of 1 prim, with a range for setting the avatar position away to 500m easily! When there are more prims linked, this offset seems to be limited to 5m (measured with llVecDist). This is an awfull sideeffect!

Put this next script inside a prim and sit on the prim, it will bring you to 1000.0 higher then the prim. Next link this prim to another prim and try again. You will notice you are limited to 5m. My Question: why is this limited?

// by Randur Source

integer heightcnt = 0;
list heights = [0.0, 1.0, 5.0, 6.0, 10.0, 100.0, 300.0, 500.0, 800.0, 1000.0];

default
{
    state_entry()
    {
        llSitTarget(ZERO_VECTOR,ZERO_ROTATION); // Clear the current sittarget for a clear test
        llSetRot(ZERO_ROTATION); // set the prim to no rotation, for simple z axis movement
    }
    
    changed(integer change)
    {
        if (change & CHANGED_LINK) // detect linked prims and avatars
        {
            integer primnum = llGetNumberOfPrims(); // the avatar is the last linked prim
            if (primnum <= 1) // stop if there is only 1 prim
                return;
        
            key avatar = llGetLinkKey(primnum);
            if (llGetAgentSize(avatar) == ZERO_VECTOR) // stop if this is not an avatar
                return;
                
            // loop through the list of test heights:
            for (heightcnt = 0; heightcnt < llGetListLength(heights); heightcnt++)
            {
                float height = llList2Float(heights,heightcnt);
                llSetLinkPrimitiveParams(primnum,[PRIM_POSITION,<0.0,0.0,height>]); // set this to the wanted height using a vector z axis
                
                vector avatarpos = llList2Vector(llGetObjectDetails(avatar,[OBJECT_POS]),0); // detect the avatar position within the sim
                float distance = llVecDist(llGetPos(),avatarpos);
                llOwnerSay("Attempt to move " + llKey2Name(llGetLinkKey(primnum)) +
                           " to " + (string)height + "m high resulting to " + (string)distance + "m");
                
                llSleep(1.0);
            }
            llUnSit(avatar);
        }
    }
}

Posted by Sylvio Runo : Answer  : The correct limit is 54 meters. You can't move a linked object more than 54 meters away from the axis of the root prim. On SecondLife (other grids like OsGrid, may works diferent) when an agent sit on prim, the agent is attached to it, so the agent is a linked prim of the link set.

More information about link rules, you will find here : http://wiki.secondlife.com/wiki/Linkability_Rules [1]

UpdateSitTarget changes?

I recently worked on a project where I used a version of this function, and it appears that it is a little off. A couple of things I noted: the Z-offset of the sit target is 0.35, not 0.4, and the avatar size doesn't seem to affect this position at all. When I used this function verbatim, I noticed discrepancies between the actual sit target and the set position call. When I changed the script as noted, I got a perfect match. Has the handling of the sit target been changed since this was written? Talarus Luan 22:57, 1 July 2009 (UTC)

Seconded. I wish I'd looked at this discussion before spending an hour on trying to figure out how the code actually behaved. -- Tonya Souther 15:11, 19 August 2009 (UTC)
This is news to me but I haven't been in world in ages :( -- Strife (talk|contribs) 22:56, 20 August 2009 (UTC)
From some quick testing in 1.40, this seems to be how the "true" offset is computed:
1. Start with offset as provided by LSL.
2. Add < 0.0 , 0.0 , 0.4 >
3. Subtract llRot2Up( rot ) * 0.05
--Gregory Maurer 20:00, 28 August 2010 (UTC)
Confirmed. The following appears to work fine:
llSetLinkPrimitiveParams(linkNum, [PRIM_POS_LOCAL, pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * 0.05), PRIM_ROT_LOCAL, rot]);
This of course using the new PRIM_POS_LOCAL and PRIM_ROT_LOCAL values for simplicity. If one or two others can confirm that the above code works correctly, then I can splice it into the example.
-- Haravikk (talk|contribs) 14:16, 26 December 2011 (PST)
Be sure to test it with avatars of different shapes, and shoe configurations. I recall that being an issue. Escort DeFarge would know about this best. -- Strife (talk|contribs) 22:05, 26 December 2011 (PST)
I tried with my two main avatar appearances, one average human height and one closer to 8 feet tall, and it didn't seem to make a difference. The test I used was a simple object with sit-target set, and a menu allowing it to be repositioned, causing the sit-target to move and if an avatar is seated on it, they will be repositioned using llSetLinkPrimitiveParams() as done above. In my case the position of the avatar was consistent both when sitting on the object (using the sit-target) and being repositioned. Avatar height appears to have no effect, as the sit-target seems to define the avatar's hip-location, which is seemingly the avatar's "centre" when seated. I'll try to run some more tests when I get a chance, as it's possible this behaviour may not hold true if the object doesn't have a sit-target on it. The height of the avatar does however have a marked visual impact, depending exactly what you're trying to line up where, but that's a general issue with sitting on objects.
-- Haravikk (talk|contribs) 05:38, 28 December 2011 (PST)
Sorry for my long delay in responding. Due to various RL issues and SL/LL burnout, I took a year off from SL to pursue other activities. That said, it seems to work fine to me, Haravikk; however, I have not done exhaustive testing with tons of different avs, shoes, etc. I would consider going ahead and changing it, because the version as it is right now is not correct for the majority of avatars, regardless. If Escort DeFarge or someone else wants to amend it later to include edge cases, that's great, but a better base accuracy is more important at this point. In fact, I think I will go ahead and edit it in, since it has been so long anyway.Talarus Luan 12:12, 5 July 2013 (PDT)
Holding up on the edit, further testing is revealing that if the script is in a prim other than the root, it is off by varying amounts depending on the rotation.Talarus Luan 12:39, 5 July 2013 (PDT)
OK, I think I found the error. Still need to keep the local position/rotation values for the child prim the script is in, like so:
llSetLinkPrimitiveParams(linkNum, PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * 0.05)) * localrot + localpos, PRIM_ROT_LOCAL, rot * localrot]);
I'll hold off on the edit until I can get another verify that this code is good.Talarus Luan 12:51, 5 July 2013 (PDT)
OK. I think I have analyzed this to death today and have come to the conclusion that Strife's original code is largely correct, but the error I am seeing comes from the "magic constants" 0.4 and 0.02638. Haravikk's code is simply a reduced form of Strife's code. The 0.4 magic constant is still there, but Haravikk is using just a close, but fixed, magic constant of 0.05 instead of Strife's (size.z * 0.02638), which comes out very close to 0.5 for most normal human avs. Thus, I am concluding that the inaccuracy is in the "magic constants" themselves, and I am going to hold off on the edit until I can get some more information on the source of these constants and see if there are better, more accurate values. It is annoying that, in all these years, we still haven't gotten LL to just tell us what the damn difference is between avatar sit targets and local position offsets in a linkset. It can't be that hard for someone who is familiar with the code to look at it and document it. -.- Talarus Luan 13:24, 5 July 2013 (PDT)
Welcome back! I'd like to take credit for that but that's the part that Escort contributed. As to where 0.02638 comes from, I vaguely recall it came from Escort's testing. I was driven more by "wouldn't it be cool to write a function that..." than anything else. I do agree the values have always been not quite right. -- Strife (talk|contribs) 23:10, 5 July 2013 (PDT)
Thanks! OK, I did a bunch of empirical testing, sampling a bunch of avatars from 1.16m to 2.45m in height, as reported by llGetAgentSize. I picked the lowest and highest and one about standard height, and fitted a parabolic curve through them. I have reduced the inaccuracies to a great degree, but it still isn't 100% perfect for all sizes in that range, just the ones that I used to solve the curve equation. The rest show a *tiny* bit of movement, but they are very close. Obviously, the difference isn't parabolic, probably just some kind of discrete step function, but it works.Talarus Luan 11:16, 14 July 2013 (PDT)
vector vCoefficients = <0.008906,-0.049831,0.088967>;
float fAdjust = vCoefficients.x * size.z * size.z + vCoefficients.y * size.z + vCoefficients.z;
llSetLinkPrimitiveParamsFast(linkNum,
    [PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * size.z * fAdjust)) * localrot + localpos,
     PRIM_ROT_LOCAL, rot * localrot]);
I see you mind reading abilities haven't diminished (I contemplated suggesting the tests you have done, decided to go to bed instead). Any reason not to use parentheses? It looks like something that could get optimized to an a series of FMAs (by the VM). -- Strife (talk|contribs) 21:33, 14 July 2013 (PDT)
vector vCoefficients = <0.008906,-0.049831,0.088967>;
float fAdjust = ((((vCoefficients.x * size.z) + vCoefficients.y) * size.z) + vCoefficients.z) * size.z;
llSetLinkPrimitiveParamsFast(linkNum,
    [PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * fAdjust)) * localrot + localpos,
     PRIM_ROT_LOCAL, rot * localrot]);
Yeah, I thought about optimizing it a bit after I posted it, but decided to leave it unoptimized here so the path from the current function to this change was clear, for demonstrability purposes. Besides, I had to leave some room for it to be Strifed™. :P Talarus Luan 15:17, 17 July 2013 (PDT)
I appreciate the gesture :p and I'm not as bad as I use to be. I'm not going to optimize out fAdjust, it's more readable this way. This is more for myself later as my memory is crap, the reasoning behind using llRot2Up is that it solves the pesky problem of the quaternion not having a magnitude of one. While the following isn't optimal, it is cool. -- Strife (talk|contribs) 00:00, 18 July 2013 (PDT)
size.x = (size.z * (size.y = (size.z * size.z)));
float fAdjust = vCoefficients * size;
Yeah, that is a nice way to represent it, for those used to the LSL representation for vector dot product. I'm a little less enthused about the size vector assignment chain, but that's just my general dislike for C value assignments and such. In my mind, I separate assignments from expressions, so seeing them mixed together causes a bit of a train wreck in my brain's lexical analyzer. :PTalarus Luan 10:00, 21 July 2013 (PDT)
I don't think anyone uses the LSL vector dot product. It took me three days to remember it existed and then I look up the syntax just to make sure I wasn't crazy (yes yes, I agree it's insane to think that looking up the syntax of an obscure feature is proof against insanity but I'm sticking to it, my cat agrees). I think a train wreck was my goal. -- Strife (talk|contribs) 11:13, 21 July 2013 (PDT)

Avatars Floating After Sit

The position of avatars will sometimes change, generally noticeable as a rise on the Z axis of perhaps half a meter - common triggers for this is typing or another AV sitting on the same object - though these are not exhaustive. Does anyone have a clue why this happens, and how to prevent it from happening? TaraLi Jie 21:14, 11 March 2012 (PDT)

Hmm, there are a few possible causes, but the main cause are the animations involved, so it's worth remembering that any animation overrider can potentially cause weirdness while on a sit-target, which is why most good ones can turn themselves off while seated. It's a bit difficult to describe specific problems with animations, but I think that sometimes it can be caused by animations that have a weird first frame, since it's used to calculate all the offsets etc. for the rest of the animation; normally this will be a neutral pose since you don't actually see it in the animation, but if it's something odd then it can mess with positioning. --
-- Haravikk (talk|contribs) 05:34, 12 March 2012 (PDT)
When I've had problems with this, the root cause has usually been that I've (or something has) inadvertently stopped an animation that's holding the avatar in place before starting another one. Because animations are all made differently, neither the animator with whom I work most of the time nor I have ever managed to figure out exactly what to avoid, but certainly when it happens to me, I always start debugging by looking very carefully at where I'm turning animations off and considering whether, in fact, I need to turn them off at all. Quite often, I find that simply turning off the default sit animation when my first animation starts, and then keeping the first animation going throughout, starting and stopping other ones over it, as necessary, solves the problem.
One "gotcha" is that stopping an animation and then immediately restarting it doesn't work. It confuses the viewer something horrible, and often leads to people floating in mid-air. Innula Zenovka 09:04, 12 March 2012 (PDT)
In developing a multi-sit script, I did some experiments. I did 20 tests using only llSitTarget() and every time that I started typing, my avatar shifted up. I then did 20 tests in which I repositioned myself using SLPPF after sitting. My avatar position didn't jump on typing in any of the 20 tests with SLPPF. Looking hopeful. Omei Qunhua 11:54, 11 May 2014 (PDT)
Yeah SLPPF rocks. -- Strife (talk|contribs) 18:28, 11 May 2014 (PDT)

Sit Target 0.4m 'bug'

The notes say "rot affects the position of the sit-target in a buggy way way. To correct for the rot bug, simply subtract <0,0,0.4> from the position when rot is zero. See example below."

But the example script adjusts z by 0.4m when rotation is NOT zero.

if (rot!=ZERO_ROTATION) pos -=<0,0,0.4>;  //here is the work around

Which should it be?

I've just been doing some tests without any 0.4m adjustment, and I am unable to observe any difference in my z position whether rotation is zero or not. Has something changed? If so, wouldn't the change screw up some furniture? Omei Qunhua 14:09, 16 March 2014 (PDT)

You are right, there shouldn't be a test there. My understanding is that you always need to subtract 0.4 from z. Changing it would screw up furniture. -- Strife (talk|contribs) 21:02, 16 March 2014 (PDT)
Then, Strife, the notes and the example need correcting. Do you have sufficient understanding to word it as it should be? Not sure that I do. Omei Qunhua 01:42, 12 May 2014 (PDT)