Jump to content

Options for Scripting Doors


Lolita Erin
 Share

You are about to reply to a thread that has been inactive for 501 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

  • 1 month later...
On 3/18/2017 at 12:48 PM, Innula Zenovka said:

I think I'd look for a different door in that case, one that has its pivot point in the center, and then use llTargetOmega to move the door at the desired speed and, on a timer,  llSetLocalRot or llSetLinkPPFast to snap it into place when llTargetOmega had done its stuff.

Toy Wylie's script does this, and it works well in prim builds.  But for mesh builds, I would not suggest llTargetOmega in a door script...it does bad things to your doorways.

The non-scripting workaround is to "edit" your doorway...just the simple act of opening the edit window on the build fixes the problem (without leaving any evidence there was a problem in the first place).  But who wants to left click a door and then right click the doorway to enter a building?  

Link to comment
Share on other sites

2 hours ago, RozWright said:

Toy Wylie's script does this, and it works well in prim builds.  But for mesh builds, I would not suggest llTargetOmega in a door script...it does bad things to your doorways.

The non-scripting workaround is to "edit" your doorway...just the simple act of opening the edit window on the build fixes the problem (without leaving any evidence there was a problem in the first place).  But who wants to left click a door and then right click the doorway to enter a building?  

Sorry but I have to disagree with you there.     There's nothing wrong with using llTargetOmega in doors in mesh builds -- I do it all the time, as do many other regulars here.    the issues described in that post are to do with the specific build and the way the meshes are set.   

llTargetOmega, unless it's called in something which has been set as physics-enabled (so a car wheel rather than a house door) is entirely client side.   Whether it's called in a prim or a mesh, the object doesn't actually move at all as far as the simulator is concerned.    So you need to to call both llTargetOmega to make the door open and close smoothly and also call llSetRot actually to open and close it so people can or can't walk through the doorway.

The only real issue with using llTargetOmega in doors is that you can't offset the centre of rotation, which is why you need either to pathcut regular prims or to offset it in a mesh door using the method described early in the thread, because you can't pathcut the mesh door.

  • Like 1
Link to comment
Share on other sites

Link to comment
Share on other sites

Thanks, @Whirly Fizzle.      I'm not particularly familiar with the details of mesh modelling, and I'd not seen that bug report before.

This is probably a very stupid question, but I note the title stresses that the bug affects "un-analysed meshes with 'Prim Physics'," and the fact that the mesh must be "un-analysed" is several times stressed in the description.

Does this mean the problem is confined to meshes that have been uploaded with first having the viewer's uploader analyse them, and only then if they are physics enabled (that is, if you raise it off the ground with the edit tools and release it, it will fall to the ground or other solid surface rather than remain suspended in mid air) and is there any good reason for not analysing the mesh before uploading it?    

On the face of it, I can't see any reason why you'd want a house door to be physics enabled, since that's unnecessary and is simply asking for trouble,  and even if you did, could you not remedy the problem by re-uploading the mesh only this time remembering first to ask the uploader to analyse it?

All I can say is that I've worked with plenty of mesh houses and doors, and so have plenty of other experienced scripters, and never had this sort of problem -- though admittedly I've never thought to set a door to physics enabled, and I didn't make the meshes myself but I have every confidence in the skills of the mesh makers who did, so maybe they realised the importance of analysing the mesh before uploading it -- and I know for a fact (since the Mole who scripted them is a friend of mine) that many, if not all,  of the houses and houseboats on Bellissaria have mesh doors that use llTargetOmega and llSetRot, and people seem to be able to use them without much difficulty, so it would appear that the issue is easily avoided.

 

Edited by Innula Zenovka
Link to comment
Share on other sites

1 hour ago, Innula Zenovka said:

Does this mean the problem is confined to meshes that have been uploaded with first having the viewer's uploader analyse them

WITHOUT first having the viewer's uploader analyse them, yes.

1 hour ago, Innula Zenovka said:

and only then if they are physics enabled (that is, if you raise it off the ground with the edit tools and release it, it will fall to the ground or other solid surface rather than remain suspended in mid air) and is there any good reason for not analysing the mesh before uploading it?  

No, Prim physics is nothing to do with being physics enabled. It means that the mesh is using the physics model that you uploaded, and not the "convex hull"  (no holes) or "none"  options. It mostly affects things like whether your avatar will collide with an object or walk through it, or whether you can walk on it, or if you can rez on it (you've probably met mesh floors that refuse to allow rezzing - that's usually a bad physics model).

And, confusingly, "phantom" is a different thing again.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

36 minutes ago, Ana Stubbs said:

WITHOUT first having the viewer's uploader analyse them, yes.

No, Prim physics is nothing to do with being physics enabled. It means that the mesh is using the physics model that you uploaded, and not the "convex hull"  (no holes) or "none"  options. It mostly affects things like whether your avatar will collide with an object or walk through it, or whether you can walk on it, or if you can rez on it (you've probably met mesh floors that refuse to allow rezzing - that's usually a bad physics model).

And, confusingly, "phantom" is a different thing again.

Ah.. that makes a bit more sense.    Thanks.   Now I start to understand.

I was thrown by the reference in the title to "un-analyzed meshes with "Prim Physics,"  which I took to mean PRIM_PHYSICS,  but it presumably means PRIM_PHYSICS_SHAPE_TYPE, PHYSICS_SHAPE_TYPE_something.     I'm not sure what the "something" is, though -- PRIM_PHYSICS_SHAPE_TYPE_PRIM presumably, since that's all that's left if it's neither convex hull or none. 

Now that I've read the repro more closely, the issue seems to be not with the door but with the root object.    What happens if I make the root prim not the unanalysed mesh I've uploaded but, instead, a regular prim?    How does the mesh object behave then after region restarts?

Maybe it's just the mesh modellers I've worked with but my impression was that they tend to make things like houses with regular collision prims  for the floors and walls and so on,  link the house mesh to it and adjust things so that the collision prims are inside the floors and walls, set them to  invisible, and then set the house mesh to PRIM_PHYSICS_SHAPE_TYPE_NONE.     That seems to avoid most problems and also generally keeps the LI down.

And if the whole thing is avoided simply by remembering to have the viewer's uploader analyse the mesh before you upload it, that's not much of a problem, I would have thought.

Edited by Innula Zenovka
Link to comment
Share on other sites

19 minutes ago, Innula Zenovka said:

my impression was that they tend to make things like houses with regular collision prims  for the floors and walls and so on,  link the house mesh to it and adjust things so that the collision prims are inside the floors and walls, set them to  invisible, and then set the house mesh to PRIM_PHYSICS_SHAPE_TYPE_NONE.     That seems to avoid most problems and also generally keeps the LI down.

That's the lazy way to do it. I don't mean that as a perjorative description, i've done it that way myself plenty of times, but a proper physics model, done well, is the ideal.

22 minutes ago, Innula Zenovka said:

And if the whole thing is avoided simply by remembering to have the viewer's uploader analyse the mesh before you upload it, that's not much of a problem, I would have thought.

Some types of physics models are better as unanalysed.

  • Like 1
Link to comment
Share on other sites

On 6/15/2019 at 1:15 PM, Innula Zenovka said:

All I can say is that I've worked with plenty of mesh houses and doors, and so have plenty of other experienced scripters, and never had this sort of problem

With mesh came a lot of new door scripts that don't require that the "hinge" of the door also be its center (as it was with the cutpath prim), so those scripts wouldn't be using llTargetOmega.  Someone graciously offered me a door script she'd created (that didn't use llTO) and the problem was solved. From my experience, the physics shape changed when llTargetOmega was called in the script (which was every time the door was opened or closed), not while it was in  motion.  So for things like ceiling fans it's not much of a problem, the build is already in edit mode when the rotation is set, and there's not much need for llTargetOmega to be called beyond that.

There's no rational reason a client side effect would cause a problem like this, and yet it does, which makes troubleshooting it a mind melting experience.

Edited by RozWright
Link to comment
Share on other sites

34 minutes ago, RozWright said:

With mesh came a lot of new door scripts that don't require that the "hinge" of the door also be its center (as it was with the cutpath prim), so those scripts wouldn't be using llTargetOmega.  Someone graciously offered me a door script she'd created (that didn't use llTO) and the problem was solved.

I'm not quite sure I understand the example you're describing here -- I would need to see the door and the script to comment, and I must stress that while I do know something about doors and rotations, I don't know a great deal about making mesh.

However, the basic scripting is quite simple, as are the constraints.   

By default, LSL  rotations pivot round the centre of the object being rotated.    The simplest workaround for when you need to pivot something on its edge -- a door, for example -- is to change the design of the object, by shifting its visual centre away from its actual centre, whether by path-cutting a prim or by manipulating  a mesh door by adding a small hidden point offset from the edge of the door mesh, so it appears the centre of the resulting mesh object is, in fact, one edge of the visible area.

If that's not possible (you didn't make the mesh) it's certainly possible, though rather fiddly,  to offset the rotation by script, using a combination of llSetRot and llSetPos.   

That works for anything server-side, but not for llTargetOmega, since all its effects are client side.    There's nothing you can do to fool llTargetOmega about where the centre of the object is.

There's an added problem with llTargetOmega doors that, because that function is client-side, you also need to change the door's actual rotation, so the simulator knows what it is.    Otherwise the door will seem open but you won't be able to pass through it because, while your CPU and GPU think the door should be drawn as open, the simulator thinks it's closed until the actual rotation is changed with llSetRot or similar.    

That can cause problems with scripted doors that use TargetOmega -- sometimes the way such doors are scripted mean that the door doesn't actually unblock or block the doorway until llTargetOmega has finished, which can be confusing.    Typically I'll call llSetRot or llSetLocalRot several times on a timer while llTargetOmega is running, so the door's actual and represented rotations are always within 10° or 20° of each other, but not everyone bothers to do that, which can confuse users a lot.

(I'm not saying that's the problem here.. just taking the opportunity to note it for future readers).

 

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

   I have a mesh house by a well known builder. All of its parts, doors and windows are a single linked object. The doors use the method of llTargetOmega() to make them appear to smoothly rotate, then setting the open or closed rotation after an appropriate delay. Because a door mesh was only actually rotated to the open position when that process completed, I was unable to walk through that doorway until it had.

   I wanted better realism. While the house is modifiable, the scripts in the doors (and windows) are not. I replaced them with a version using the aforementioned method, adding to the beginning and end of the door state change processes, respectively, llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]) and llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_PRIM]). This allows a much more realistic simulation, letting me gracefully make a grand entrance into my writing room, where my typewriter, sitting on a desk, balefully inquires of me "And where have you been?"

Edited by Ivanova Shostakovich
because too many to.
Link to comment
Share on other sites

  • 2 weeks later...

I have been trying to learn from this thread to solve a problem I have and so far I'm not getting there, yet, lol. Here is my issue. I have a roomba in my shop on a floating island. The roomba is physical, so that it can bump around the walls on the inside of the building. I have sliding double doors in the shop. The doors are mesh, they are linked to a frame that is separate from the building. If need be, I could unlink them from the frame and have them as separate objects if necessary.

When all goes well, the sliding doors open and close to let people go in and out but the roomba stays in. Every so often, someone gets the doors to stick and stay open. The roomba goes out..... and then it's off vacuuming the sky..... So, I'd like to find a more reliable script for my door that would only let avatars go in and out. I would prefer the double doors to slide, but I tried Rollig's cafe doors. I thought they would do it until I watched the roomba open them and go out! I don't know a lot about scripting, can anyone guide me towards something that's not super complicated (or well explained) that would do a good job for what I want?

Link to comment
Share on other sites

That's fortunately quite simple.  Scripters don't usually need to worry about Roombas and such, so we don't bother to tell our scripts to obey only avatars.  However, that's what the llDetectedType() function is designed for.  All you need to do is include a simple test in whatever touch* or collision* event activates your door, as in:

touch_start( integer num )
{
    if ( llDetectedType(0) & AGENT )
    {
        //Go ahead and open the door
    }
}

 

Link to comment
Share on other sites

  • 1 year later...

Scripters are often called upon to script double doors that will swing together when either one is touched.  There are many ways to do that, depending on how the doors are constructed.  Here's one.  In this example, we have two identical doors ("Left Door" and "Right Door") that might be simple prims or mesh objects.  They are parts of a linkset in which the root is the black prim below the doors. 

569248196_DoubleDoorDemo.jpg.3b5a7a329714ba175bae6af918d15b05.jpg 

The doors might be linked to a building or a wall, in which case the root of that building or wall would take the place of the black prim in this image.  The doors are named "Left Door" and "Right Door" and are designed so that their local X axes point toward each other.  If you do that, the doors will hinge on their outer edges.  

In this example, I am starting with the simple door script posted by Innula Zenovka earlier in this thread >>> https://community.secondlife.com/forums/topic/338230-options-for-scripting-doors/?tab=comments#comment-1616538 .  In state_entry, we first identify the link numbers of the two doors and save them in global integer variables, iLeftDoor and iRightDoor. The script assumes that because the doors are identical, I can use the dimensions of either one to determine where the hinge edges of both doors are.  The value vOffset is determined in state_entry and saved as a global vector.  The touch_start event, then, essentially blends two copies of Innula's touch_start event  (one for each door) and then rotates both with a single llSetLinkPrimitiveParamsFast statement.  The script is only activated if someone touches one of the two doors.  With a little bit of thought, it should be possible to generalize this approach for use in a linkset with more than one set of double doors, or to construct a double door script that begins with a different approach than Innula's.

integer intSwing = 90;   // Door swing in degrees   
rotation rotSwing;
vector vOffset;
vector vOffsetR;
integer iLeftDoor;
integer iRightDoor;

default{    

    state_entry()
    {
        //First, find the door prims ....
        integer len = llGetNumberOfPrims();
        integer i;
        while ( i < len)
        {
            ++i;
            string name = llGetLinkName(i);
            if (name == "Left Door")
            {
                iLeftDoor = i;
            }
            else if (name == "Right Door")
            {
                iRightDoor = i;
            }
        }
        // Now, covert intSwing to a rotation in radians around the Z-axis
        rotSwing = llEuler2Rot(<0.0,0.0,(float)intSwing>*DEG_TO_RAD); 
        
        // And calculate how far each door's hinge edge is from the centerline of the door   
        vector size = (vector)llList2String(llGetLinkPrimitiveParams(iLeftDoor,[PRIM_SIZE]),0);       
        vOffset = <(size.x*-0.5),(size.y*-0.5),0.0>;
        vOffsetR = <(size.x*-0.5),(size.y*0.5),0.0>; //Note the sign difference in the Y dimension's offset 
    }    

    touch_start(integer total_number)
    {
        if ( llDetectedLinkNumber(0) == iLeftDoor || llDetectedLinkNumber(0) == iRightDoor)
        {
            // Get the current local position and rotation of each door
            list lParamsL = llGetLinkPrimitiveParams(iLeftDoor,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
            vector vLeft = llList2Vector(lParamsL,0);
            rotation rLeft = llList2Rot(lParamsL,1);
            list lParamsR = llGetLinkPrimitiveParams(iRightDoor,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
            vector vRight = llList2Vector(lParamsR,0);
            rotation rRight = llList2Rot(lParamsR,1);
            rotation rotSwingRight = <rotSwing.x,rotSwing.y,rotSwing.z,-rotSwing.s>;  //So, rotSwingRight rotates the door in the opposite direction
            
            // Now, swing both doors simlutaneously 
            llSetLinkPrimitiveParams(LINK_SET,[34,iLeftDoor,PRIM_POS_LOCAL,vLeft+(vOffset - vOffset*rotSwing)*rLeft,PRIM_ROT_LOCAL,rotSwing*rLeft,
                34,iRightDoor,PRIM_POS_LOCAL,vRight+(vOffsetR - vOffsetR*rotSwingRight)*rRight,PRIM_ROT_LOCAL,rotSwingRight*rRight]);
                
            // And finally, reverse the direction of swing, ready for the next touch
            rotSwing.s*=-1;
        }  
    }
}

EDIT:  Thank you to Mollymews for pointing out that because the left and right doors are mirrored, the arithmetic sign of the hinge offset in Y for the Right Door has to be the reverse of the sign for the Left Door.  I have introduced vOffsetR to recognize that and have updated the script above to include it.  It's a small correction -- most noticeable for a thick door -- but it assures that the two doors align correctly with a door jamb.

Edited by Rolig Loon
typos. as always.
  • Like 2
Link to comment
Share on other sites

little typo in this line - 

vOffsetR = <(size.x*-0.5),(size.y*0.5),0.0); //Note the sign difference in the Y dimension's offset 
    }   

i think should be...

        vOffsetR = <(size.x*-0.5),(size.y*0.5),0.0>; //Note the sign difference in the Y dimension's offset 

?

Emma Noob scripter :) 

Link to comment
Share on other sites

@siennasprout asked about sensor to open a linked double door set in other post

i had a play with the above Rolig/Innula double door script and added a door sensor to it

here is a pic.

red and green are the doors.  Orange is the sensor. Blue are the quadrants

doors open when person is in either blue quadrant and is facing the doors

quaddoors_001.png.6527e5d8d763833f8ad5f65d12e0b1bd.png

 

example script
 

// mod of Innula Zenovka / Rolig Loon double linked door script to add a sensor opener
// this script goes in a sensor prim by the doors, the door frame is a good place to put it in

integer intSwing = 90;   // Door swing in degrees   
rotation rotSwing;
vector vOffset;
vector vOffsetR;
integer iLeftDoor;
integer iRightDoor;

integer isOpen;

swing()
{
    // Get the current local position and rotation of each door
    list lParamsL = llGetLinkPrimitiveParams(iLeftDoor,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
    vector vLeft = llList2Vector(lParamsL,0);
    rotation rLeft = llList2Rot(lParamsL,1);
    list lParamsR = llGetLinkPrimitiveParams(iRightDoor,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
    vector vRight = llList2Vector(lParamsR,0);
    rotation rRight = llList2Rot(lParamsR,1);
    rotation rotSwingRight = <rotSwing.x,rotSwing.y,rotSwing.z,-rotSwing.s>;  //So, rotSwingRight rotates the door in the opposite direction
            
    // Now, swing both doors simlutaneously
    llSetLinkPrimitiveParams(LINK_SET,[34,iLeftDoor,PRIM_POS_LOCAL,vLeft+(vOffset - vOffset*rotSwing)*rLeft,PRIM_ROT_LOCAL,rotSwing*rLeft,
        34,iRightDoor,PRIM_POS_LOCAL,vRight+(vOffsetR - vOffsetR*rotSwingRight)*rRight,PRIM_ROT_LOCAL,rotSwingRight*rRight]);
                
    // And finally, reverse the direction of swing, ready for the next touch
    rotSwing.s*=-1;
    isOpen = !isOpen;
}

default{    

    state_entry()
    {
        //First, find the door prims ....
        integer len = llGetNumberOfPrims();
        integer i;
        while ( i < len)
        {
            ++i;
            string name = llGetLinkName(i);
            if (name == "Left Door")
            {
                iLeftDoor = i;
            }
            else if (name == "Right Door")
            {
                iRightDoor = i;
            }
        }
        // Now, covert intSwing to a rotation in radians around the Z-axis
        rotSwing = llEuler2Rot(<0.0,0.0,(float)intSwing>*DEG_TO_RAD);
        
        // And calculate how far each door's hinge edge is from the centerline of the door   
        vector size = (vector)llList2String(llGetLinkPrimitiveParams(iLeftDoor,[PRIM_SIZE]),0);       
        vOffset = <(size.x*-0.5),(size.y*-0.5),0.0>;
        vOffsetR = <(size.x*-0.5),(size.y*0.5),0.0>; //Note the sign difference in the Y dimension's offset
    
        // goto state door_closed
        state door_closed;
    }
}
    
state door_closed
{
    state_entry()
    {
        // start sensor
        llSensorRepeat("", NULL_KEY, AGENT, 5.0, PI, 1.0);
    }
             
    sensor(integer num)
    {                
        while (!isOpen && ~--num)
        {
            // is agent within the diagonal quadrants in front of and behind the sensor ?
            // and when so is agent looking at the door ?
            vector bearing = llVecNorm(llDetectedPos(num) - llGetPos());
            float quadrant = llFabs(llRot2Fwd(llGetRot()) * bearing); // quadrant range [0.0 .. 1.0]. 0.0 is wider
            float compass = -llRot2Fwd(llDetectedRot(num)) * bearing;   // compass range[-1.0 .. 0.0 .. 1.0] 0.0 is wider  
            if ((quadrant > 0.7) && (compass > 0.95))            
            {   // when somebody found open the door and goto state door_open
                swing();
                state door_open;
            }
            
            // caveat: as this is calculated using dot.product the conditions (as wrote) get screwy when reallly
            // close to the sensor. So agent has to move back away from the sensor sometimes
            // credit: the dot.product compass bearing method is credit Dora Gustafson. The quadrant bearing I derived from this
        }
    }
}

state door_open
{
    state_entry()
    {
        // start sensor
        llSensorRepeat("", NULL_KEY, AGENT, 5.0, PI, 1.0);
    }
        
    no_sensor()
    {
        // when nobody found close the door and goto state door_closed
        swing();
        state door_closed;
    }
}

 

Edited by Mollymews
typs
Link to comment
Share on other sites

i tidied up the compass bearing method so that the math is little bit more consistent with the use case

main two things:

1) set pos.Z of agent and sensor to be the same Z. As when agent.Z and sensor.Z are on different levels, ie: sensor.Z is lower than agent.Z, the Z angle gets steeper as the agent gets closer to the sensor which affects the bearing calculation

2) scale by the magnitude of the bearing vector. This means that <0.5,0.5, 0> <1,1,0> <2,2,0>,<3,3,0>, etc return the same calculated bearing (give or take rounding errors)

sensor(integer num)
{       
   vector sensorpos = llGetPos();
   rotation sensorrot = llGetRot();
          
   while (!isOpen && ~--num)
   {
       // is agent within the diagonal quadrants in front of and behind the sensor ?
       // and when so is agent looking at the door ?
       vector agentpos = llDetectedPos(num);
       rotation agentrot = llDetectedRot(num);
       agentpos.z = sensorpos.z;  // set same Z to work in 2 dimensions XY
       vector bearing = llVecNorm(agentpos - sensorpos);
       float magnitude = llVecMag(bearing); // scale by magnitude so that bearing <1,1,0> = <2,2,0> = <3,3,0> etc
       float quadrant = llFabs(llRot2Fwd(sensorrot) * bearing / magnitude); // quadrant range [0.0 .. 1.0]. 0.0 is wider
       float compass = -llRot2Fwd(agentrot) * bearing / magnitude;   // compass range[-1.0 .. 0.0 .. 1.0] 0.0 is wider 
 
       if ((quadrant > 0.7) && (compass > 0.95))            
       {   // when somebody found open the door and goto state door_open
           swing();
           state door_open;
       }
            
       // credit: the dot.product compass bearing method is credit Dora Gustafson. The quadrant bearing I derived from this
   }
}

 

ps. while the tidy up can be used in the door case, I did it mostly because somebody asked me if could be used in a animesh kitten which stalks another animals or people. Like sneaks up behind them and if they turn around then the kitten  goes still and pretends is asleep. Then when they turn away, kitten sneaks up a little bit more until close enough then goes raaaaar!!!

Edited by Mollymews
  • Like 1
Link to comment
Share on other sites

2 hours ago, Mollymews said:

i tidied up the compass bearing method so that the math is little bit more consistent with the use case

main two things:

1) set pos.Z of agent and sensor to be the same Z. As when agent.Z and sensor.Z are on different levels, ie: sensor.Z is lower than agent.Z, the Z angle gets steeper as the agent gets closer to the sensor which affects the bearing calculation

2) scale by the magnitude of the bearing vector. This means that <0.5,0.5, 0> <1,1,0> <2,2,0>,<3,3,0>, etc return the same calculated bearing (give or take rounding errors)


sensor(integer num)
{       
   vector sensorpos = llGetPos();
   rotation sensorrot = llGetRot();
          
   while (!isOpen && ~--num)
   {
       // is agent within the diagonal quadrants in front of and behind the sensor ?
       // and when so is agent looking at the door ?
       vector agentpos = llDetectedPos(num);
       rotation agentrot = llDetectedRot(num);
       agentpos.z = sensorpos.z;  // set same Z to work in 2 dimensions XY
       vector bearing = llVecNorm(agentpos - sensorpos);
       float magnitude = llVecMag(bearing); // scale by magnitude so that bearing <1,1,0> = <2,2,0> = <3,3,0> etc
       float quadrant = llFabs(llRot2Fwd(sensorrot) * bearing / magnitude); // quadrant range [0.0 .. 1.0]. 0.0 is wider
       float compass = -llRot2Fwd(agentrot) * bearing / magnitude;   // compass range[-1.0 .. 0.0 .. 1.0] 0.0 is wider 
 
       if ((quadrant > 0.7) && (compass > 0.95))            
       {   // when somebody found open the door and goto state door_open
           swing();
           state door_open;
       }
            
       // credit: the dot.product compass bearing method is credit Dora Gustafson. The quadrant bearing I derived from this
   }
}

 

ps. while the tidy up can be used in the door case, I did it mostly because somebody asked me if could be used in a animesh kitten which stalks another animals or people. Like sneaks up behind them and if they turn around then the kitten  goes still and pretends is asleep. Then when they turn away, kitten sneaks up a little bit more until close enough then goes raaaaar!!!

such a cute use case! BUT also, thanks so much for the door script(s) AND explanations ❤️

Emma :)

 

  • Like 1
Link to comment
Share on other sites

On 12/3/2020 at 4:24 AM, Mollymews said:

i tidied up the compass bearing method so that the math is little bit more consistent with the use case

main two things:

1) set pos.Z of agent and sensor to be the same Z. As when agent.Z and sensor.Z are on different levels, ie: sensor.Z is lower than agent.Z, the Z angle gets steeper as the agent gets closer to the sensor which affects the bearing calculation

2) scale by the magnitude of the bearing vector. This means that <0.5,0.5, 0> <1,1,0> <2,2,0>,<3,3,0>, etc return the same calculated bearing (give or take rounding errors)


sensor(integer num)
{       
   vector sensorpos = llGetPos();
   rotation sensorrot = llGetRot();
          
   while (!isOpen && ~--num)
   {
       // is agent within the diagonal quadrants in front of and behind the sensor ?
       // and when so is agent looking at the door ?
       vector agentpos = llDetectedPos(num);
       rotation agentrot = llDetectedRot(num);
       agentpos.z = sensorpos.z;  // set same Z to work in 2 dimensions XY
       vector bearing = llVecNorm(agentpos - sensorpos);
       float magnitude = llVecMag(bearing); // scale by magnitude so that bearing <1,1,0> = <2,2,0> = <3,3,0> etc
       float quadrant = llFabs(llRot2Fwd(sensorrot) * bearing / magnitude); // quadrant range [0.0 .. 1.0]. 0.0 is wider
       float compass = -llRot2Fwd(agentrot) * bearing / magnitude;   // compass range[-1.0 .. 0.0 .. 1.0] 0.0 is wider 
 
       if ((quadrant > 0.7) && (compass > 0.95))            
       {   // when somebody found open the door and goto state door_open
           swing();
           state door_open;
       }
            
       // credit: the dot.product compass bearing method is credit Dora Gustafson. The quadrant bearing I derived from this
   }
}

 

ps. while the tidy up can be used in the door case, I did it mostly because somebody asked me if could be used in a animesh kitten which stalks another animals or people. Like sneaks up behind them and if they turn around then the kitten  goes still and pretends is asleep. Then when they turn away, kitten sneaks up a little bit more until close enough then goes raaaaar!!!

Thanks so much! I'll give this script a try next time I get a chance. :)

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

not sure how long it has been available but I just noticed that Linden have added llSetClickAction(CLICK_ACTION_DISABLED)

might have been them Belli building Moles who got it put thru. Is a real blessing for linked doors and windows which are linked to the building. The blessing is that can have just one script in the root prim to handle touches that open and close the doors/windows

how to use:

set all the prims (walls, floors, etc) other than the doors and windows to llSetClickAction(CLICK_ACTION_DISABLED) leaving only the doors/windows set to the default llSetClickAction(CLICK_ACTION_TOUCH)

so only the doors/windows will accept a Touch and pass it thru to the script in the root prim

even cooler is llSetClickAction() is a prim property. Once set the property is held by the prim and the script to set the property can be deleted. Example:

// set the prim click action property to disabled
// and then delete the script

// stick this in every prim in a linked build that we don't want to
// accept Touches and pass then thru to a root prim touch script

default
{
    state_entry()
    {
        llSetClickAction(CLICK_ACTION_DISABLED);
        llSleep(0.2); // give it a little time to take hold then
       llRemoveInventory(llGetScriptName()); // delete this script
    }
}

http://wiki.secondlife.com/wiki/LlSetClickAction

Link to comment
Share on other sites

  • 1 month later...
  • 1 month later...
On 6/13/2018 at 10:45 PM, Rolig Loon said:

touch_end( integer vIntNul ){
  llSetLocalRot( (gRotSwing = (ZERO_ROTATION / gRotSwing)) * llGetLocalRot() );
}

 

This compact method is great and works nicely for toggling a door open / closed with alternate touches.

One thing I don't understand: llSetLocalRot appears to animate the hinge motion but I can't see any parameters associated with the time it takes to reach the final angle.

I know there are keyframe-based methods to get more control over the animation – I’m not asking about that. I just want to understand this method specifically. Is there something about llSetLocalRot, or [the variable called here] gRotSwing (returned bv llEuler2Rot) that determines that it should animate?

Or does llSetLocalRot simply rotate objects at some hard-coded rate that cannot be changed?

Link to comment
Share on other sites

7 minutes ago, Rem Voxel said:

This compact method is great and works nicely for toggling a door open / closed with alternate touches.

One thing I don't understand: llSetLocalRot appears to animate the hinge motion but I can't see any parameters associated with the time it takes to reach the final angle.

I know there are keyframe-based methods to get more control over the animation – I’m not asking about that. I just want to understand this method specifically. Is there something about llSetLocalRot, or [the variable called here] gRotSwing (returned bv llEuler2Rot) that determines that it should animate?

Or does llSetLocalRot simply rotate objects at some hard-coded rate that cannot be changed?

The rotation change is instant, as far as the sim is concerned.

What you've noticed is the client-side interpolation, and it's done for all rotation/position/scale changes (for both, objects and avatars). You definitely can't adjust it through scripts at all.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 501 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...