Jump to content

Someone good in maths there?


Emma SecretSpy
 Share

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

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

Recommended Posts

Hello all,


I hope you will understand my strange english...

Well I am using a script, published few years ago in this forum, to make a locomotive turn a 90° corner. Link of he original thread :

uuMakeCurve(rotation rot, integer dir, float angle, float radius, float steps, float time)
{
    // dir: 1 = left, -1 = right
    // angle: in degrees
    // time = total time 
    //
    vector offset = <-radius, 0.0, 0.0> * (llEuler2Rot(<0.0, 0.0, dir * PI_BY_TWO>) * rot);
    // Offset from relative center of the arc of circle
    time = 10.0/45.0; // Time for each step
    //angle = (angle * DEG_TO_RAD * dir) / steps; // Arc of circle for each step
     angle = (angle * DEG_TO_RAD ) * (float)dir / steps; // Arc of circle for each step
    
    rot = llEuler2Rot(<0.0, 0.0, angle>); // Relative rotation for each step
    FrameList = [];
    integer i = 1; // Don't re-do step 0!
    for (; i <= (integer)steps; ++i)
    {
       // the offset is now defined as the precedent rotated vector
        vector move = offset ;
        offset = offset * llEuler2Rot(<0.0, 0.0, angle >) ;
        move = offset - move;
  
        FrameList += [move, rot, time];
    }
 
}

default
{
    state_entry()
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);
    }

    touch_end(integer num)
    {
        uuMakeCurve(llGetRot(), 1, 90.0, 10.0, 24.0, 12.0);
        llSetKeyframedMotion(FrameList, [KFM_MODE, KFM_FORWARD]);
    }
}

 The script works wonderfully. But it will work well only on a perfectly flat land and the rotation x and y must be = 0.

I would like to be able to inclinate the rotation X and Y of my curved track but I don't know what are the datas I must change.

Thank you very much for your help.

Emma

 

 

 

 

Link to comment
Share on other sites

Hello Emma!

 

Actually there is only one potential solution i can think of for this script.

In theory it will be like this:

The script may detect a specific prim of the track based on the offset positions computed in the uuMakeCurve method. Then it may gets the x and y rotation of that track prim by using llGetObjectDetails and OBJECT_ROT as parameter and applies it to the computed rotation for each step.

 

But that for there are a few requirements. The locomotive and track prims will need a proper/matching center of rotation and each track section will need something like a ground prim to asure the script is detecting anything when raycasting.

It also might need some testing and tweeking as i'm currently not sure if a raycast may detect a child prim of an object or the just the object.

 

Anyway as i'm also struggling with object rotations and its quite late here, i rather tend to wait if anyone else may come up with a better solution.

  • Like 1
Link to comment
Share on other sites

Well its late here (2am) but i came up with 2 more possible solution.

 

1) By having invisible and phantom path prims along the track. The locomotive may set its rotation based on those prims on collision and just has to move forward based on its local forward orientation.

2) With a second script containing in the track object which forwards the positions and rotations of each track section to the locomotive.

 

Especiall number one sounds promising as it might results in a much more dynamic track path.

 

(Yes, i better get some rest now befor i come up with more nutty ideas) :matte-motes-nerdy: :smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

Dear revochen,

 

Thank you very much for your answer.

I already use invisible prims for the path. I have one at the very beginning of the curved track, which is detected.

In fact, the locomotive is already inclinated by it (but i didn't see it before) but not enough: i mean the locomotive takes the rotation of this prim when it detects it and goes to it but doesn't continue to go upper, following the whole inclinated track. I'll send you pictures later (since I am at the end of my holiday :( , I need to take a... real train to go back home).

Good Dreams^^

Link to comment
Share on other sites

Description: I put the red triangle-root called "right" at the beginning of the curved track. I inclinate it on X=20 (instead of 0). The locomotive (my blue prim) detects the red triangle, reaches it and takes its rotation (X=20, Y=0, Z=0) then follows the curved track (child). Issue: if the rotation of the locomotive  is correct (X=20), the locomotive doesn't go up.

 

You can create my curved track with a Cylinder, Size X=10, Y=10, Z=0.5, Path Cut Begin=0, End= 0.250, hollow= 75

 

This my adaptation of the script for my curve movement:

//Based on uuMakeCurve by Kaluura Boa, Miranda Umino 

integer SensorTargetName;list SensorTargetNames = ["left", "right"];list FrameList;TurningRight(){llSleep(2.0) uuMakeCurve(llGetRot(), -1, 90.0, 3.90, 20.0, 12.0); llSetKeyframedMotion(FrameList, [KFM_MODE, KFM_FORWARD]); llResetScript(); } TurningLeft()llSleep(2.0); uuMakeCurve(llGetRot(), 1, 90.0, 4.350, 20.0, 12.0); llSetKeyframedMotion(FrameList, [KFM_MODE, KFM_FORWARD]); llResetScript(); } uuMakeCurve(rotation rot, integer dir, float angle, float radius, float steps, float time){ // dir: 1 = left, -1 = right // angle: in degrees // time = total time // vector offset = <-radius, 0.0, 0.0> * (llEuler2Rot(<0.0, 0.0, dir * PI_BY_TWO>) * rot); // Offset from relative center of the arc of circle // time = 5.0/45.0; // Time for each step time = 6.0 / llGetRegionFPS(); //angle = (angle * DEG_TO_RAD * dir) / steps; // Arc of circle for each step angle = (angle * DEG_TO_RAD ) * (float)dir / steps; // Arc of circle for each step rot = llEuler2Rot(<0.0, 0.0, angle>); // Relative rotation for each step FrameList = []; integer i = 1; // Don't re-do step 0! for (; i <= (integer)steps; ++i) { // the offset is now defined as the precedent rotated vector vector move = offset ; offset = offset * llEuler2Rot(<0.0, 0.0, angle >) ; move = offset - move; FrameList += [move, rot, time]; } } ObjectDetected(integer index) {vector pos = llDetectedPos(0); rotation rot =llDetectedRot(0); vector offset =<0,0,0>;offset = offset*llDetectedRot(0); pos+=offset; llSetKeyframedMotion( [ pos- llGetPos(), rot / llGetRot(),2], []); if(index == 0) { TurningLeft(); } else if (index ==1) { TurningRight(); } }default{ state_entry() { vector pos = llGetPos(); llSleep(0.1); llSetTimerEvent(0.5); }sensor(integer total_number) { ObjectDetected(SensorTargetName); } timer() { llSensor(llList2String(SensorTargetNames, SensorTargetName = !SensorTargetName), "", ACTIVE | PASSIVE, 10, PI/8); }}

 

Link to comment
Share on other sites

as already said in previous post you linked to that this method can result in a little bit of drift. Is possible to pretty much eliminate drift by using a different algo plotting the circumference of a circle. Basically:

px = X + radius * cos(A)
py = Y + radius * sin(A)

where X Y are the centre of the circle. A is the angle in radians

+

but anyways back to something you already comfortable with. Think of it kinda like a skateboard/snowboard. spin pitch angle

here is a example mod of the uuMakeCurve function to give you an idea of this. The coded settings give you an idea of what you are wanting to achieve with your locomotive. Can try/experiment other settings to see what other turns can be made

just drop it in a prim and Touch to go

can use or not as you like. Can mod/do whatever you want with my mods and dont need to give me any code credits. If you do use tho then be best to give a code credit in your own mods to Kaluura and Miranda. Is the gracious/right thing to do when a codey gives no indication either way

 

list uuMakeTurn(rotation rot, integer dir, vector turn, float radius, integer steps, float time){    // based on uuMakeCurve by Kaluura Boa, Miranda Umino     // rot   : start rotation    // dir   : 1 = left, -1 = right    // turn  : <spin, pitch, angle> in degrees    // radius: radius of turn    // steps : to complete turn      // time  : to complete in seconds     list result;    // Offset from relative center of the arc of circle    vector offset = <-radius, 0.0, 0.0> * (llEuler2Rot(<0.0, 0.0, (float)dir * PI_BY_TWO>) * rot);        // Arc for each step    turn *= DEG_TO_RAD;    turn.x *= (float)dir;    turn.y *= (float)(-dir);    turn.z *= (float)dir;     turn /= (float)steps;        // Time for each step    time /= 45; // can use div llGetRegionFPS() but I personal think is a bit flaky         // Relative rotation for each step       rot = llEuler2Rot(turn);    integer i;    for (i = 0; i < steps; i++)    {        // Relative movement from previous pos to current one        vector move = offset;        offset = offset * rot;        move = offset - move;              result += [move, rot, time];    }    return result;}default{    state_entry()    {        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);    }    touch_end(integer num_detected)    {          llSetRot(ZERO_ROTATION);        rotation rot    = llGetRot();        integer  dir    = 1;        vector   turn   = <0.0, 20.0, 90.0>; // <spin, pitch, angle>        // vector   turn   = <0.0, 0.0, 360.0> // a flat circle         float    radius = 6.0;        integer  steps  = 20;        float    time   = 10;            list frames = uuMakeTurn(rot, dir, turn, radius, steps, time);        llSetKeyframedMotion(frames, [KFM_MODE, KFM_FORWARD]);       }}

 

 

 

  • Like 1
Link to comment
Share on other sites

Dear irihapeti,

 

Many thanks for the script: I've just tested it and it works wonderfully. You are a genious :) I am very glad because the effect is perfect.

Yes, I will reedit my older post and will add  the missing information credits. I am an amateur and I ignored the usage.

 

Thank you again for your great help.

Take care and good evening :)

 

Link to comment
Share on other sites

yw (:

about being any kind of genius tho. I never invent any of these algos. Way more smarter people than me did. In these algo cases is some ancient Sumerians/Egyptians/Greeks who should get the genius credits. We all just coding on top of their works pretty much

Now that you on your way then I give you some tips for where to go next and take to the next level. Same for anyone else reading who might want to use

+


think about how to change dir from integer to vector. So that: dir = <1.0,1.0.1.0> .. <-1.0,-1.0,-1.0> where can be any combination of 1 | -1. Example: <1.0, -1.0, 1.0> <1.0, -1.0, -1.0>.  turn.x *= dir.x; turn.y *= dir.y; turn.z *= dir.z. You now into a more data-driven approach to the codes rather than a procedural coding approach

can do this also by direct applying negative and positive input values to <turn> itself. But making <dir> as a vector helps makes it a bit easier to think about the movement in the cube space when this is all new to you

+

in your case is a locomotive/train so the track is fixed/static. So can pre-calc and not have the locomotive recalc the sections every time as its moving. So less load at realtime runtime

after built all your tracks and work out all your movement settings then generate the frames list(s) and print it out. See llDumpList2String

then either direct include the printed frames list(s) in your final/production script or can put in a notecard and load from there. Can do this for your whole track, section by section. A dif frame list for each type of section. turns and straights

other advantage with this static approach is that can edit the printed frames list. For example the locomotive might not go/stop precisely where you want it to. So can mod/edit the list values by hand to get more precise if you need to 

  • Like 1
Link to comment
Share on other sites

"think about how to change dir from integer to vector. So that: dir = <1.0,1.0.1.0> .. <-1.0,-1.0,-1.0> where can be any combination of 1 | -1. Example: <1.0, -1.0, 1.0> <1.0, -1.0, -1.0>.  turn.x *= dir.x; turn.y *= dir.y; turn.z *= dir.z. You now into a more data-driven approach to the codes rather than a procedural coding approach"

 

Anyway, it's sure  I will make experimentations this week-end, playing with your (+ credited ancient Sumerians/Egyptians Greeks^^)  code.

I need, first, to understand totally your initial script and my head is is a bit flat and limited :) I am not an Einstein like you^^. For example, your suggestion about changing dir to vector, with positive and negative values, seems very complex for me:/

For now, my train detects, with a sensor, the name of the different tracks and its behaviour will depend on this name. It's ok for the right tracks but with the curved tracks, I'll need to pre-code every trajectory. I would like the script could detect automatically the rotation datas of the root-prim of the track (llDetectedRot), datas that I must write for now "manually" in the script.


About reading positions/rotations in a notecard: I tried first to save the datas with a SetKeyFramedMotion script adapted from an old physical "tour" script. My "train" was first moving with the sensor script detecting the tracks, and a second script was memorizing every detected points (with a timer). But since the positions were calculated relatively from a first point, I had always gap issues. And I noticed that the second script, the "reading saved positions" script was as laggy as the first with a "live" detection by sensor.

The notecard solution is more stable.

The inconvenient with a notecard:  if you want to modificate a part of your tour, you have to copy/paste again all the values. And don't you think a decoding notecard script is not laggy?

Link to comment
Share on other sites

i made a test script for you that moves a prim in a figure 8 that rises and falls. I made in 3 sections. 2 x 180 degrees + 1 x 360 degrees. Is quite a good way to learn how direction and rotation work together. At first glance rotations can be really confusing

Like for example why in section2 tell it to go up -1 +40deg and then it goes down (:

 look at turn.z = 180.0 and turn.z = -180.0. Is to keep the nose leading in the turn. If do what might seem logical and  -1 +40deg  180 then will go down backwards. Which is even more logical

just try putting in different combinations and make notes. After a bit then you will go bing!! and the light will go off in your head. Then you be an expert at rotations

+

about chaining sections together . I just done this test by sleeping the test script. Don't do this in production code. Use a timer

the basic principle is: Pre-generate all the sections first, save and then run. Dont generate on the fly. By pre-gen they are buffered

where they are saved (notecards or scripts) isnt the main thing. The main thing is that the next section is buffered. Either all buffered or JIT (just in time) buffering

E.g. JIT buffering. If saved in notecards (or other scripts) then while a section is playing then load the next section into the buffer, so that it will be ready to play when the current is finished

can worry about all this  tho when you got rotations working good in your head

+

also notice the slam stop. As mentioned this algo can produce drift bc of floating point rounding. So at critical sections then slam it. Is the easiest way to fix that. And also if for some reason is a big lag and the frameslist doesn't play then if dont slam it to where it supposed to be then your framelists train can go wandering off into the forest or go for a swim even (:

 

list uuMakeTurn(rotation rot, vector dir, vector turn, float radius, integer steps, float time){    // based on uuMakeCurve by Kaluura Boa, Miranda Umino     // rot   : start rotation    // dir   : <spinlr, updown, leftright>. 1 | -1    // turn  : <spin, pitch, angle> in degrees    // radius: radius of turn    // steps : to complete turn      // time  : to complete in seconds     list result;    // Offset from relative center of the arc of circle    vector offset = <-radius, 0.0, 0.0> * (llEuler2Rot(<0.0, 0.0, dir.z * PI_BY_TWO>) * rot);        // Arc for each step    turn *= DEG_TO_RAD;    turn.x *= dir.x;    turn.y *= dir.y;    turn.z *= dir.z;     turn /= (float)steps;        // Time for each step    time /= steps;        // Relative rotation for each step       rot = llEuler2Rot(turn);    integer i;    for (i = 0; i < steps; i++)    {        // Relative movement from previous pos to current one        vector move = offset;        offset = offset * rot;        move = offset - move;              result += [move, rot, time];    }    return result;}default{    state_entry()    {        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);    }    touch_end(integer num)    {          llSetRot(ZERO_ROTATION);        vector startpos = llGetPos();        rotation rot    = llGetLocalRot();        vector   dir    = <1.0, -1.0, 1.0>;        vector   turn   = <0.0, 40.0, 180.0>;         float    radius = 2.0;        integer  steps  = 10;        float    time1  = 6.0;            list section1 = uuMakeTurn(rot, dir, turn, radius, steps, time1);                rot    = llGetLocalRot();        rot.x  = 0.0; rot.y = 0.0;       // adjust rot if neccessary        dir    = <1.0, -1.0, -1.0>;      // direction indicators        turn   = <0.0, 40.0, -180.0>;    // <spin, pitch, angle>        steps  = 10;        float time2  = 6.0;           list section2 = uuMakeTurn(rot, dir, turn, radius, steps, time2);                   rot    = llGetLocalRot();        rot.x  = 0.0; rot.y = 0.0;        dir    = <1.0, -1.0, -1.0>;        turn   = <0.0, 40.0, 360.0>;        radius = 2.0;        steps  = 20;        float time3  = 12.0;           list section3 = uuMakeTurn(rot, dir, turn, radius, steps, time3);                  // test : do not use llSleep in production code - use a timer         llSetKeyframedMotion(section1, [KFM_MODE, KFM_FORWARD]);           llSleep(time1 * 0.99);             llSetKeyframedMotion(section2, [KFM_MODE, KFM_FORWARD]);           llSleep(time2 * 0.99);             llSetKeyframedMotion(section3, [KFM_MODE, KFM_FORWARD]);           llSleep(time3 * 0.99);             llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_STOP]);        llSetPos(startpos);        llSetRot(ZERO_ROTATION);             }}

 

 

 

Link to comment
Share on other sites

Wow, thank you very much irihapeti!

Because of my real world (+ my little family), I'll be able to make these experimental test and play with your new  script only  this week-end. But then I tell you all about it, I promise :)

Ok, I was ignoring this question of buffering.

PS: I like railway workers, but lifegards and woodcutters too :)

 

Link to comment
Share on other sites

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