Jump to content

Mistake or bug? Script moves object unexplainably along the z axis


Handarido Optera
 Share

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

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

Recommended Posts


This script was intended to make an object moving along a quarter circle. The object does move that way but unexplainably the last waypoints also a significant distance along the z axis without any obvious reason defined in the script. Can anyone tell where my mistake is, or is this a bug?

float distance;
float unit;
float r = 0.5;
vector home;
vector travel;

default
{
     touch_start(integer total_number)
     {
          home = llGetPos();
          distance = 2*llSqrt(r*r/2);
          integer i;
          for(i=1; i<=20; ++i)
          {
               unit = distance/20*i;
               travel.x = home.x + llSqrt((llPow(r, 2.0) - llPow(unit, 2.0)));
               travel.y = home.y - unit;
               travel.z = home.z; // <-- the z axis remains unaltered during the loop runs
               llSetPos(travel);
               llOwnerSay("waypoint = " + (string)llGetPos()); // <-- to describe what happens in-world
          }
     }
}

waypoint = <134.47880, 114.89070, 3901.00000>
waypoint = <134.47500, 114.85540, 3901.00000>
waypoint = <134.46870, 114.82000, 3901.00000>
waypoint = <134.45960, 114.78470, 3901.00000>
waypoint = <134.44780, 114.74930, 3901.00000>
waypoint = <134.43280, 114.71400, 3901.00000>
waypoint = <134.41450, 114.67860, 3901.00000>
waypoint = <134.39230, 114.64330, 3901.00000>
waypoint = <134.36570, 114.60790, 3901.00000>
waypoint = <134.33360, 114.57250, 3901.00000>
waypoint = <134.29430, 114.53720, 3901.00000>
waypoint = <134.24460, 114.50180, 3901.00000>
waypoint = <134.17690, 114.46650, 3901.00000>
waypoint = <134.05080, 114.43110, 3901.00000>
waypoint = <133.70750, 114.13810, 3891.01000> // <--- from here the object moves
waypoint = <133.36420, 113.84510, 3881.02100> //        in steps of about 10m!
waypoint = <133.02090, 113.55200, 3871.03100>
waypoint = <132.67760, 113.25900, 3861.04100>
waypoint = <132.33440, 112.96590, 3851.05100>
waypoint = <131.99110, 112.67290, 3841.06200>

Link to comment
Share on other sites

i'm no scripter but the points stated for the last 6 waypoints indicate a 10m move on the z axis....3901 to 3891 etc. is a 10m hop.  I'm also not sure if that's what you mean that the problem is, but those points would be pretty 'explainable' to me.  If that's not the issue, then excuse my reply.

Link to comment
Share on other sites

Interesting.  When I run your script, travel.z remains constant as it should, but there's an interesting math problem that might explain your positioning error.  Run this slightly modified version and see....

float distance;float unit;float r = 0.5;vector home;vector travel;default{     touch_start(integer total_number)     {          home = llGetPos();          distance = 2*llSqrt(r*r/2.0);          float a = llPow(r, 2.0);  // r*r does not change with i          integer i;          for(i=1; i<=20; ++i)          {               unit = (distance/20.0)*i;  // Use 20.0, not 20               float b = llPow(unit, 2.0);               llOwnerSay("r*r = " + (string)a + "   unit*unit = " + (string)b);               travel.x = home.x + llSqrt(a - b);               travel.y = home.y - unit;               travel.z = home.z; // <-- the z axis remains unaltered during the loop runs               llOwnerSay("waypoint = " + (string)travel); // <-- to describe what happens in-world          }     }}

 What I find interesting is that in the past, llSqrt (-1) would crash a script.  Now it seems to throw a NaN and keep on going. 

  • Like 1
Link to comment
Share on other sites

Ah yes thank you very much for pinning the problem. Brillant. Yes, if a math error occurs, a script can go crazy anywhere. And yes, I should not use integers when floats are around. They dont like each other, and integers tend to drag floats to their side. Floats below zero get nasty then and take revenge with the other famous math error, the division by zero.

Link to comment
Share on other sites

And I figured my mistake by realizing that the negative value would happen with any given radius. I did not consider for the calculation of the x axis that the prim travels. Here comes the version which works. I still had a short disappearance of the prim when the loop started. So instead llSetPos(...) I used llSetLinkPrimitiveParamsFast(...). That was, however, too fast. The prim took a quick direct way instead of the circle route. So I ended up with llSetPrimitiveParams(...). Got it!

float distance;
float unit;
float r = 0.5;
vector home;
vector travel;

default
{
    touch_start(integer total_number)
    {
         home = llGetPos();
         distance = 2*llSqrt(r*r/2.0);
         float a = llPow(r, 2.0);
         integer i;
         for(i=1; i<=20; ++i)
         {
             unit = (distance/20.0)*i;
             float b = llPow((distance-unit), 2.0); // <-- the distance decreases
             travel.x = home.x + llSqrt(a - b);
             travel.y = home.y - unit;
             travel.z = home.z;
             llSetPrimitiveParams([PRIM_POSITION, travel]);
        }
    }
}

Link to comment
Share on other sites

There is an old bug that treats NaN as a legitimate number for moving prims. This was used to impliment the old PosJump function before llSetRegionPos() was available. It looks like your prim is trying to move to NaN an being prevented from doing so by the 10 meter maximum distance that llSetPos is allowed to go.

Several comments on your script: (Intended to be constructive!!!)

  • There are better ways to move a non-physical prim, I recommend llSetKeyframedMotion();
  • Moving prims in a for loop is very bad form, you should find an event-driven way to do this, such as moving in a timer event.
  • llSetPos() has a built-in delay, you can use llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION,[traveled]); with no delay.
  • You are calculating your positions using Cartesian math, which has sigularities as you discovered with the NaN values. There are ways of calculating points around a circle that do not have this problem. One way would be to use the rotation data type to rotate a vector around in a circle.

 

Link to comment
Share on other sites

Yeah, that bug has been there for a long time.  It still interests me, though, that the script can even get that far.  There's still a caveat in the wiki at llSqrt that says the script will not only throw a math error message but will actually crash if you feed it a negative number.  That's apparently not true any more, which is too bad.  I'd rather have the script lock up than appear to function and leave me wondering about odd results.

Your general suggestions about the OP's script are right on target.  I might add that if the OP does want to move the prim farther than 10m for some reason and is determined to do it with something like llSetPos, the llSetRegionPos function is a better choice.  It has no 10m limit

Link to comment
Share on other sites

Thank you for your comment and help. I understand now why it moved 10m.

I am sorry but I cannot find llSetKeyframedMotion() on the list of functions.

Perhaps my long search was bad but I have not found even any hint not to speak about an example script about moving a prim along a circle. So I tried it today with the for loop and the old Pythagoras. Going for the roation thing next after I managed to understand  the functions. 

I mentioned that I did try first with llSetLinkPrimitiveParamsFast(...) but the result was that the prim traveled quickly to the end point and not along a circle. So I used llSetPrimitiveParams(...).

Yes to the timer unless it is not occupied otherwise. Timer needs the llSetLinkPrimitiveParamsFast(...) of course.

Link to comment
Share on other sites

The "secret" behind this first try is to find a way for a door script where you dont cut a prim in half and move it around its axis. You can do that with a prim but not with a sculpted or mesh door. There is a trick to make half of the sculpted door invisible but it is still there and in the way. 

Door scripts with an axis do move a prim properly, but those dont work as intended when linked to the main object. If you want a linked door of a sculpted or mesh prim then this prim needs to travel along a quarter circle and, of course, needs to change the angle as well. So as a beginning to understand what is going on I started with the quarter circle.

Link to comment
Share on other sites

http://wiki.secondlife.com/wiki/LlSetKeyframedMotion

There are a couple of easy ways to move a prim around a circle, provided that you are willing to let the prim have a hidden "companion".  Link your prim to another prim, which you set as the root of the link set and make 100% transparent.  Then use llTargetOmega to rotate the linset around the invisible root.  It's quick to script, although it takes a little extra magic to stop it at a predictable point.  The other way is what Kayaker was suggesting (other than llSetKeyframedMotion, which is much smoother):

integer gStep;default{    state_entry()    {        llSetRot(ZERO_ROTATION);    }    touch_start(integer num)    {        llSetTimerEvent(1.0);        gStep = 0;    }    timer()    {        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROTATION,gHome + llEuler2Rot(<0.0,0.0,PI/20.0>)*(++gStep)]);        if (gStep >= 20)        {            llSetTimerEvent(0.0);        }    }}

 

Link to comment
Share on other sites

Oh!  The common way to make a mesh door work properly with a simple door script like Void's is to make the mesh door properly with a very tiny invisible face that's on the opposite side of the hinge from the rest of the visible door.  See

ETA:  If you use that method, I suggest putting that little invisilbe face at floor level (or below) so that it doesn't whack you in the face as the door opens.  If I remember, that YouTube video haas you put it at the top of the door.

Link to comment
Share on other sites

Yes that is the trick I referred to. I had tried that not knowing that this was common knowledge.To make sure what I say here I went back and made a simple mesh door with jass-magic-1.1.4 and Collada File 1.4. There is the door, and there is the one face on the very bottom. But you cant step over the bottom face, the prim takes the whole bounding box. And therefore eventually pushing people with the invisible part when rotating. I will look at the video if there is an option to avoid this.

Link to comment
Share on other sites

Set the door to Physics Shape type PRIM when you're done so that the door itself and the tiny invisible face are both solid but you can walk through the rest of the bounding box.  It's the same thing that you do, for example, if you are building a mesh house and want to be able to walk through door openings.  Make the whole building shape type PRIM and the openings that you left for doorways will be navigable.

BTW, if you are using Blender, you don't need the extra step of using JASS.  You create your mesh model in Blender and export it directly as a Collada file.

Link to comment
Share on other sites

Awesome, it works when the door's physics shape is Prim. Then the method explained in the video with creating a temporary mirror door, creating a triangle, adjusting it, creating another box aligning it to the door aso aso is  w a y  too complicate and not necessary: Just design the vertices of the door in that you have got an extra vertex at the bottom of the door. All you need is one simple step then: Drag the vertex into the opposite direction of the door until the distance is equal with the width of the door. Then the extension is just an edge and there is no need to take care of faces of this extension. The lonesome edge is invisible.

I had used Blender until it was recommended to use Jass which I use since then. Ok, got now Blender again ... will take some time to become familiar with it.

Link to comment
Share on other sites

Yeah, now that I look back at the video myself, I think it was a little overkill too.  I had forgotten the bit about making a mirror door, which I never do.  The basic idea is straightforward, though, and each creator is likely to put his own personal style into it.  As long as you remember to place your small, invisible piece so that the "hinge" of the door is at the right place on the door's edge, it doesn't matter how you get it there.  To the point of this forum, anyway, you can script a well-made mesh door just as easily as you can script a standard cut-prim door.  No need for fancy math.

Link to comment
Share on other sites

  • 1 month later...

I finally succeeded in moving a prim around the side axis, or to be more precise, around the middle of the smaller side of a prim. The door script is available on marketplace now, with automatic detection of the smaller x or y side, it works at any angle around the z axis, in both directions.

No menu, no notecard, no setup, no second axis prim, and foremost, no cut prim, no mesh tricks, no tutorials, just drop the script into a full prim or mesh object, linked child or unlinked single / root. Any amount of combinations of doors / windows simultaneously working gridwide is possible. Whoever is interested, contact me in-world, I am glad to pass on free examples for testing. 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3513 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...