Jump to content
AdamZadig

Need help with smooth rotating door script

Recommended Posts

I have the free open source smooth rotating door script. It works great. But how can I make it so when touching one door it opens two? Ive had this script in the past but seem to have lost it. 

 

So basically it creates double doors that both open when when is touched. 

 

Also, I've added a transparent textured mesh 'plane' as the hinge of one door, but when I flip it and use on the other the door opens but then flips upside down!! 

 

Anyone else experienced this?

 

 

Share this post


Link to post
Share on other sites

I've also tried changing the "float openingAngle=90.0;    // in degrees"

to... "float openingAngle=-90.0;    // in degrees" on the second door but it still opens in the wrong direction (although initially rotates the desired direction it fininshed up the wrong way! 

Share this post


Link to post
Share on other sites

Adam, show us a link to the script and we might find the culprit ;) right now it's guessing.

Share this post


Link to post
Share on other sites

I suggest starting at a different place.  Take a  look at the very clean formulation of Toy Wylie's Smooth Rotating Door script that Innula Zenovka posted here just last week in 

 Her script is the final entry in that thread. The OP's question was exactly the same as yours, only rotated by 90 degrees because she was interested in scripting two drawbridges to rotate smoothly together.  You should be able to use Innula's script with very small modifications to fit your situation.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks, Rolig.

One significant difference between my script and the original by Toy Wylie, which I didn't bother about, partly because my adaptation was for a bridge but mostly because I was doing a quick proof-of-concept rather than a full script, is that I wait until the llTargetOmega call has finished completely before rotating the door so that its actual rotation matches its visible appearance on the user's computer.  

This means that if you simply turn the assembly on its side and use it as a door, you won't actually be able to walk through it until it has completely opened.   Until then, the simulator thinks it's still shut.     Similarly, when it starts to close, you will will be able to walk though it until it's completely shut, because until the time it takes to close has elapsed, the simulator thinks it's still completely open.

Toy's script avoids that problem by opening and closing the door in stages -- 5, from memory -- so every time llTargetOmega has moved the visible door through n/5 degrees, it calls llSetRot actually to rotate the door prim through a similar angle.     

That would be easy enough to do with my script, of course, by fiddling with what happens in the timer event, and I might do it myself if I ever have time.  But people wanting use my example as a door should be aware it has that limitation.

  • Like 1

Share this post


Link to post
Share on other sites

There are several possible solutions to that problem:

1. Make the door phantom as soon as the process starts, and non-phantom when the process has ended. One small downside is that although llSetStatus doesn't have a built-in delay, it is not 100% reliable. An object can get stuck in phantom status.

2. Shrink the door to a narrow prim along its hinge line and then expand it again as you turn it at the end of the process. This has the somewhat larger downside that the math can be a bit tricky if you are using a cut prim door or one with a calculated hinge offset.

3. Start the llTargetOmega movement and then rotate the door's actual rotation in one single step after a very small delay.  This doesn't have much of a downside that I can see, although the door will actually be open/closed long before it actually appears to be.  Some people might be surprised by walking into a closed door (or elated by walking through one that's ajar).

4. Ignore it. This has the massive upside that it requires no extra scripting, although it shares the inverse of the downside of option #3. Unless I were scripting adoor that is meant to open/close exceedingly slowly, this is the option I would choose.  After all, most people are not so impatient that they are going to leap through a door in the time that it takes to rotate it visually.  It's a psychological thing.  9_9

EDIT:  I should probably mention another possible solution, which I once resorted to with an unusual "sphincter" door that was always impossible to walk through, whether it was actually open or closed (thanks to the physics of the door elements).  In that case, I made the visible door phantom and slid a transparent, non-phantom "real" door in front of it when it was closed.  You could do the same thing with a rotating door.  ;)

Edited by Rolig Loon
  • Like 1

Share this post


Link to post
Share on other sites

Here's my solution -- rotating the door in small increments while llTargetOmega is executing, rather than all in one go at the end.   It works pretty well.

This assumes a similar construction to that used in the bridge script Rolig linked to, only rotated through 90 degrees so it's a door, and resized appropriately.

integer iLeftBridge;
integer iRightBridge;
integer iMode;
integer iHowManySteps = 5;
integer iCounter;
string strLeft = "Left";
string strRight = "Right";

float fAutoCloseTime = 10.0;
float fOpeningTime= 5.0;      // in seconds
float fInterval;
float fOpeningAngle = 80.0;    // in degrees
float fAngleToTurn;
//float autocloseTime=30.0;   // in seconds
float fSpinRate;
float fY = 1.0;
integer iOpen;
rotation rArc;
rotation rLeftClosed;
rotation rRightClosed;
rotation rLeftLocal;
rotation rRightLocal;
findPrims(){//identify the two drawbridge prims
    integer counter = 2;
    integer max = llGetNumberOfPrims() + 1;
    do{
        list temp = llGetLinkPrimitiveParams(counter, [PRIM_DESC, PRIM_ROT_LOCAL]);//Examine the link description of each child prim and record the relevant link numbers and rotation in start position (bridge lowered) 
        string str = llList2String(temp, 0);
        rotation rot = llList2Rot(temp,1);
        if(strLeft == str){
            iLeftBridge = counter;
            rLeftClosed = rot;
        }
        else if (strRight == str){
            iRightBridge = counter;
            rRightClosed = rot;
        }
    }
    while (++counter < max);
}

default
{
    state_entry()
    {
        findPrims();
        fInterval = fOpeningTime/(float)iHowManySteps;
        llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_OMEGA, <0.0,0.0,0.0>,0.0,0.0]);

        fOpeningAngle *= DEG_TO_RAD;
        fAngleToTurn = fOpeningAngle / (float)iHowManySteps;
        fSpinRate = fOpeningAngle/fOpeningTime; //the spinrate in llTargetOmega is how many radians the object should appear to rotate in 1 second.
        rArc = llEuler2Rot(<0.0,fAngleToTurn,0.0>);
    }

    touch_start(integer num_detected)
    {
        if(!iOpen){ //only respond to touches if the bridge is down
            iOpen = TRUE;
            iMode = 0;
            iCounter = 0;
            rLeftLocal = llList2Rot(llGetLinkPrimitiveParams(iLeftBridge,[PRIM_ROT_LOCAL]),0);//equivalent to calling llGetLocalRot in the prim itself
            rRightLocal = llList2Rot(llGetLinkPrimitiveParams(iRightBridge,[PRIM_ROT_LOCAL]),0);//equivalent to calling llGetLocalRot in the prim itself
            rArc.y *= -1.0;//flip the value of the y axis of the arc through which the drawbridge must rotate
            fY *= -1.0;
            llSetTimerEvent(fInterval);
            llSetLinkPrimitiveParamsFast(LINK_SET, [
            PRIM_LINK_TARGET,iLeftBridge,PRIM_OMEGA,<0.0,fY,0.0> * rLeftLocal, fSpinRate, 0.1,
            PRIM_LINK_TARGET,iRightBridge,PRIM_OMEGA,<0.0,fY,0.0> * rRightLocal, fSpinRate, 0.1
                ]); 
        }
    }

    changed(integer change)
    {
        if(change & CHANGED_LINK){
            llResetScript();//in order to re-check the numbering
        }
    }

    timer()
    {
//    llOwnerSay("iMode is "+(string)iMode+", and iCounter is "+(string)iCounter);

       if(0==iMode){
            if(iCounter<iHowManySteps){

                llSetLinkPrimitiveParamsFast(LINK_SET, [
                PRIM_LINK_TARGET,iLeftBridge, PRIM_ROT_LOCAL, rArc * rLeftLocal,
                PRIM_LINK_TARGET,iRightBridge,PRIM_ROT_LOCAL,rArc * rRightLocal
               ]);//now raise it
                rLeftLocal = llList2Rot(llGetLinkPrimitiveParams(iLeftBridge,[PRIM_ROT_LOCAL]),0);//equivalent to calling llGetLocalRot in the prim itself
                rRightLocal = llList2Rot(llGetLinkPrimitiveParams(iRightBridge,[PRIM_ROT_LOCAL]),0);//equivalent to calling llGetLocalRot in the prim itself
               if(++iCounter == iHowManySteps){
                    iCounter = 0;
                    llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_OMEGA, <0.0,0.0,0.0>,0.0,0.0]);
                    rArc.y *= -1.0;//flip the value of the y axis of the arc through which the drawbridge must rotate, ready to close it
                    fY *= -1.0;
                    llSetTimerEvent(fAutoCloseTime);
                    ++iMode;
               }
            }
       }
       else if (1==iMode){//start target omega to make the bridge seem to lower
                llSetLinkPrimitiveParamsFast(LINK_SET, [
                PRIM_LINK_TARGET,iLeftBridge,PRIM_OMEGA,<0.0,fY,0.0> * rLeftLocal, fSpinRate, 0.1,
                PRIM_LINK_TARGET,iRightBridge,PRIM_OMEGA,<0.0,fY,0.0> * rRightLocal, fSpinRate, 0.1
                    ]);
                llSetTimerEvent(fInterval);
                ++iMode;
       }
       else if (2 == iMode){
            if(iCounter<iHowManySteps){
                llSetLinkPrimitiveParamsFast(LINK_SET, [
                PRIM_LINK_TARGET,iLeftBridge, PRIM_ROT_LOCAL, rArc * rLeftLocal,
                PRIM_LINK_TARGET,iRightBridge,PRIM_ROT_LOCAL,rArc * rRightLocal
               ]);//now raise it
                rLeftLocal = llList2Rot(llGetLinkPrimitiveParams(iLeftBridge,[PRIM_ROT_LOCAL]),0);//equivalent to calling llGetLocalRot in the prim itself
                rRightLocal = llList2Rot(llGetLinkPrimitiveParams(iRightBridge,[PRIM_ROT_LOCAL]),0);//equivalent to calling llGetLocalRot in the prim itself
               if(++iCounter == iHowManySteps){
                    llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_OMEGA, <0.0,0.0,0.0>,0.0,0.0]);
                    llSetTimerEvent(0.0);
                    iMode = 0;
                    iOpen = FALSE;
               }
            }

       }

    }
}

 

  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...