Jump to content

Catmull Rom or Bezier curves in game play animal movement


VirtualKitten
 Share

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

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

Recommended Posts

I can't confirm as I am testing just with a cube, you are using an animesh object which from previous experience I recall has a different default alignment? If so, you are going to have to apply a correction. If you look at the oneshot bezier script I posted you might catch sight of a statement that sets the default alignment and so you could try amending it to get the desired effect.

Link to comment
Share on other sites

23 hours ago, Profaitchikenz Haiku said:
rotation refFrame=<-0.5, -0.5, -0.5, 0.5>; // points Z forward

This has been included by Dora so that the textures emitted by the cube when demonstrating KFM are emitted in the required oriention. By changing the values of the rotation you could arrange it so the alingment is say 180 degrees reversed on the X-axis, or whatever is appropriate.

  • Haha 1
Link to comment
Share on other sites

14 minutes ago, Profaitchikenz Haiku said:
rotation refFrame=<-0.5, -0.5, -0.5, 0.5>; // points Z forward

Interesting. I believe that's the rotation that turns 120 about the intermediate axis, sending (with respect to SL default coordinates) z forward, y up, x left. Usually I see mesh objects uploaded with y-forward, z-up rotation which would be <0,0,-0.71,0.71>.

 

  • Confused 1
Link to comment
Share on other sites

51 minutes ago, Quistess Alpha said:

Interesting. I believe that's the rotation that turns 120 about the intermediate axis, sending (with respect to SL default coordinates) z forward, y up, x left.

What Dora's cube does is emit a series of square textures about the same size as the cube so that a sort of smoky trail is left behind as the cube progresses around the path, I had forgotten to remove it hen I slimmed the script to remove the KFM and textures. My guess is that VK needs to use a 180 degree rotation around the dragon's Z-axis to have it stick it's snout in the direction of travel.

Edited by Profaitchikenz Haiku
Damn Pi400 keyboard drops digits, 1s in particular, 180 degrees is my suggestion
  • Like 1
  • Sad 1
Link to comment
Share on other sites

Prof idk, this is what it does with qui's data<0,0,-0.71,0.71>. My mesh is    Z forward moving test  Y as usual for mesh as the animations have different orientation :D  I tried your fix  but it worked no better the dragon still spun about in a really weird trajectory sadly but thanks for trying 

video of what it does :

https://kapwi.ng/c/QHdbk37lez

Link to comment
Share on other sites

First thoughts are there's another script in your Dragon rotating it.

In your code, try putting in an llOwnerSay((string) lGetRot()) before anything else so that you know what the dragon's "normal" rotation is.

Second test is, chat out the intended position and rotation of each small move, as you are doing, but also chat out the resulting position/rotation after the small move, so that you can see if there is a difference to be accounted for.

If you see the dragon rotating to exactly where it was told to rotate but it is still facing the wrong way, then you have to work out a correction to apply to each rotation.

If however the resulting rotation differs from the commanded one then you re looking for some other script/instruction in a script in the dragon that is also happening unexpectedly.

  • Sad 1
Link to comment
Share on other sites

good idea. Prof on your first thoughts I have no other script enabled with running check box. I added a simple return in to my wander script as you can see below but have to inform you nothing then moved in model at all as it is all only the movement that comes through here  :

5570f548579b3c69f1054fe7b16ac72d.png

I have also sent you dumps of rotation you can see the code is producing this as it was output just after it was created  !

 

Hugs D

Link to comment
Share on other sites

18 hours ago, VirtualKitten said:

 

which is a little better but still spins about from report :

[08:11] Dragontest:<237.63450, 22.97095, 3510.29200>, newrot:<0.57888, -0.40607, 0.62622, 0.32841>, TYPE:9
[08:11] Dragontest:<237.83490, 22.55526, 3510.28100>, newrot:<-0.25646, -0.65896, 0.08918, 0.70146>, TYPE:9
[08:11] Dragontest:<237.83490, 22.55526, 3510.28100>, newrot:<-0.25646, -0.65896, 0.08918, 0.70146>, TYPE:9
[08:11] Dragontest:<237.83490, 22.55526, 3510.28100>, newrot:<-0.25646, -0.65896, 0.08918, 0.70146>, TYPE:9
[08:11] Dragontest:<237.83490, 22.55526, 3510.28100>, newrot:<-0.25646, -0.65896, 0.08918, 0.70146>, TYPE:9
[08:11] Dragontest:<237.83490, 22.55526, 3510.28100>, newrot:<-0.25646, -0.65896, 0.08918, 0.70146>, TYPE:9
[08:11] Dragontest:<238.47110, 23.02396, 3510.22000>, newrot:<0.36167, -0.60762, -0.10060, 0.69991>, TYPE:9
[08:11] Dragontest:<238.47110, 23.02396, 3510.22000>, newrot:<0.36167, -0.60762, -0.10060, 0.69991>, TYPE:9
[08:11] Dragontest:<238.47110, 23.02396, 3510.22000>, newrot:<0.36167, -0.60762, -0.10060, 0.69991>, TYPE:9
[08:11] Dragontest:<238.47110, 23.02396, 3510.22000>, newrot:<0.36167, -0.60762, -0.10060, 0.69991>, TYPE:9
[08:11] Dragontest:<238.47110, 23.02396, 3510.22000>, newrot:<0.36167, -0.60762, -0.10060, 0.69991>, TYPE:9
[08:11] Dragontest:<237.75390, 22.48861, 3510.29000>, newrot:<0.29117, -0.64438, 0.43022, 0.56117>, TYPE:9
[08:11] Dragontest:<237.75390, 22.48861, 3510.29000>, newrot:<0.29117, -0.64438, 0.43022, 0.56117>, TYPE:9

 

hugs Dx

Plenty of examples of it rotating in other posts Prof :) Hugs

Edited by VirtualKitten
Link to comment
Share on other sites

I don't want to wade through reams of debug output doing what you should be doing.

I have only just finished a mammoth debugging session on my own railway system involving rotations. I'll tell you the methods I used to track down where things were going wrong, but I am not going to do your work for you. Doing so will not help anybody else trying to deal with a similar situation, describing the techniques to find the error will add to the body of knowledge this forum contains.

 

TL;DR  Do one thing at a time, test on thing at a time. 

 

Modify your code so that instead of a timer or moving_end triggering a series of moves, you have to touch it for each movement.

Before each move, the script must chat out where it is, what it's rotation is, where it is told to go to, where it is told to turn to

Touch the object so it makes the first move

It must now chat out where it is and where it hs turned to.

Before you touch it again,compare the before and after outputs.

Did it go to where it was told and turn too where it was told?

IFF Yes, touch it and see what the next move does. IFF that''s OK, keep touching and observing.

Otherwise, stop, examine the figures for the single failed move, try to work out what happened, correct what you determined to be the probable cause of error.

 

Edited by Profaitchikenz Haiku
  • Like 1
  • Sad 1
Link to comment
Share on other sites

I can only suggest you make your box same size as mine x : 13.09988 y: 6.11964 z: 3.43326 and see if your bounces about left then right  not rotating I guess your small .5m cube doesn't show it as it is not large enough like Doras small box

 

Aso Prof you are not using    

at_target(integer tnum, vector targetpos, vector ourpos) {
        if(tnum == target_wander_id) {   
             target_wander_id = __llTargetRemove(target_wander_id);
         }
    }

Edited by VirtualKitten
Link to comment
Share on other sites

1 hour ago, VirtualKitten said:

Aso Prof you are not using    

at_target(integer tnum, vector targetpos, vector ourpos) {
        if(tnum == target_wander_id) {   
             target_wander_id = __llTargetRemove(target_wander_id);
         }
    }

This isn't necessary to investigate bezier curves, it's more specific to your intended end-application, but first, you have to get the curves. I have tried t suggest you remove timers/moving_end or at)target style controls and instead use touch_end to go through the curves one segment at a time.

In my railway work I had to step back from trying to make a wagon stick to the tracks at the entrance to and exit from curves because the complexity of the wagon added to the problem. I reduced the problem to that of making a single prim traverse the track and once I had accomplished that I then returned to the problem of the wagon with a better understanding of the principles.

 

1 hour ago, VirtualKitten said:

I have no clue what you are talking about Prof I don't think her  Bezier code works. I  put it in a box next week and bet it doesn't as its not same as mesh has no idea why qui liked your post as I cant understand any of it .

Dora's code works, but I could see it was more complicated that might be ideal for a beginner's introduction, so I simplified it as much as I could for both you and I to be able to tinker with in the one-shot bezier script I posted.

When you come to do side-by-side comparisons between it and your version there is one further trick you can use to enable a more direct comparison.

At present the method uses six random numbers to assist with the curve shaping. This means that each time you run the code six different random numbers will be produced, because in LSL there is no way to specify the initial seed to the random number generator to get a repeatable set of random numbers, but there is a way round this.

In the one-shot bezier, run it once and chat out the six number values P1, P2, P3, Q1, Q2, Q3 as well as the resulting positions and rotations.

Edit the code and replace the calls to generate random numbers for P1,2,3 Q1,2,3 with the actual values that were chatted out.

Do the same in your code.

Then, when you start off the dragon from the same start position and rotation as the test box, it should also get the same sets of positions and rotations for the bezier as the test box. You can therefore verify that your implementation of her code is accurate, or not, depending on the comparison of the positions and rotations.

If your code does not produce the same positions and rotations when given the same six P1-Q3 values and started from the same initial position and rotation then you have introduced something different or omitted something crucial in your script.

 

  • Confused 1
Link to comment
Share on other sites

Well I just put it in a box and now it returns nada ldest 0 which is subtraction of  nex_pos-iPos so the bezier code is producing complete dodo a big 0 .See told it was the bezier code it seems to be returning my current position go figure  as the index is incremented  b_i

vector nextCoordinates(integer p_TYPE) {
         if (b_i == liN || b_i == 0) { b_i = 0;  coefisFirst();}
         iPos = Bez( b_i/liN); 
         newrot = Vec2Rot(dBez( b_i/liN));
         b_i++;
         
 llInstantMessage(llGetOwner(),"ipos:"+(string)iPos+", newrot:"+(string)newrot+", TYPE:" +(string)p_TYPE+" b_i:"+(string)b_i);
    return iPos;
}

[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:1

_llWanderWithinKeyframe (vector home,  vector range, list c) {

...
   llInstantMessage(llGetOwner(),"_llWanderWithinKeyframe: Moving ipos: "+(string)iPos+"next"+ (string)nex_pos); 

...

}
[14:22] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>

integer __loadCoordinates(vector l_pos ,vector l_dest,rotation l_rot, float time , integer target) 
{
            //Debug("Load Points...");

           llInstantMessage(llGetOwner(),"lpos:"+(string)l_pos+", lDest:"+(string)l_dest);
           ....

}
[14:22] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>

etc.
[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:2
[14:22] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:22] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:3
[14:22] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:22] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:4
[14:22] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:22] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:5
[14:22] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:22] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:6
[14:22] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:23] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:23] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:7
[14:23] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:23] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:23] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:8
[14:23] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:23] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:23] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:9
[14:23] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:23] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:23] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:10
[14:23] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:23] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>
[14:23] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:11
[14:23] Object: _llWanderWithinKeyframe: Moving ipos: <225.24250, 34.08127, 3500.50600>next<225.24250, 34.08127, 3500.50600>
[14:23] Object: lpos:<225.24250, 34.08127, 3500.50600>, lDest:<0.00000, 0.00000, 0.00000>

 

I asked you which bits of Dora's code to use as I didn't understand it. You say its not Dora's code so did we not take the correct bit out? 

 

Hugs Dx

Edited by VirtualKitten
Link to comment
Share on other sites

20 minutes ago, VirtualKitten said:

Well I just put it in a box and now it returns nada ldest 0 which is subtraction of  nex_pos-iPos so the bezier code is producing complete dodo a big 0 .See told it was the bezier code it seems to be returning my current position go figure  as the index is incremented  b_i

There are other parts of your code you haven't posted which are involved in the calculations, since you have modified the parts you have posted, the chances are you have modified the parts you haven't posted as well.

Deja-vu 

  • Sad 1
Link to comment
Share on other sites

i didn't think I needed to show anything deja-vu ! Your not reading what I post as it goes wrong from first full script  i posted it should not return my current position . I am going to check something no its ok it doesn't show b_i as zero as its incremented just before instantMessage(

if your really not interested in helping please don't post Prof as I don't think you have read anything I posted  as you would not be saying daft things like  have modified parts by copy paste into new script !

 

Edited by VirtualKitten
Link to comment
Share on other sites

20 minutes ago, Profaitchikenz Haiku said:

There are other parts of your code you haven't posted which are involved in the calculations, since you have modified the parts you have posted, the chances are you have modified the parts you haven't posted as well.

Deja-vu 

This prints my current position eleven times maybe you don't understand this either like me  :
vector nextCoordinates(integer p_TYPE) {
         if (b_i == liN || b_i == 0) { b_i = 0;  coefisFirst();}
         iPos = Bez( b_i/liN); 
         newrot = Vec2Rot(dBez( b_i/liN));
         b_i++;
         
 llInstantMessage(llGetOwner(),"ipos:"+(string)iPos+", newrot:"+(string)newrot+", TYPE:" +(string)p_TYPE+" b_i:"+(string)b_i);
    return iPos;
}

[14:22] Object: ipos:<225.24250, 34.08127, 3500.50600>, newrot:<0.16394, -0.01097, -0.06611, 0.98835>, TYPE:9 b_i:1

 

sighs D

Edited by VirtualKitten
Link to comment
Share on other sites

10 hours ago, Profaitchikenz Haiku said:

random number generator to get a repeatable set of random numbers

 

just picking up on this part

is a number of ways to write our own pseudorandom number generator.  Probably the most simple is a galois linear feedback shift register

a example of this for the range -1.0 < 1.0 is


// galois lfsr pseudorandom number generator
// as wrote, returns a float in -1.0 < 1.0
// with 25 bits of uniform precision because LSL float type
integer lfsr;
float rnd()
{   
    lfsr = (lfsr >> 1) ^ (-(lfsr & 0x1) & 0xD0000001);  
    return lfsr / 2147483648.0;
}


/*  randomP would then go:
vector randomP()
{
    return llGetPos() + < range.x * rnd(), range.y * rnd(), range.z * rnd() > * homeRot;
}
*/

default
{
    state_entry()
    {

    }
    
    touch_start(integer num)
    {

        // seed the lfsr for a repeatable 'random' set. Change to any value not 0
        lfsr = 123456789;
        
        // for a random seed then
        // lfsr = ((integer)llFrand(65536) << 16) | (integer)llFrand(65536);
        
        llOwnerSay("begin");
        integer i;
        for (i = 0; i < 20; ++i)
        {
            llOwnerSay((string)rnd());    
        }  
        llOwnerSay("end");      
        
    }
}

 

  • Like 1
Link to comment
Share on other sites

54 minutes ago, Mollymews said:

is a number of ways to write our own pseudorandom number generator. 

I looked at a couple of user-written library examples but decided that it wasn't useful here for two reasons:

1) It would add yet more complexity to the situation where I feel some simplification is necessary to get out of the forest and have a clearer look.

2) The random numbers are only need once, at the very beginning. If they were required for each point along the bezier than I agree, your routine is nice and compact and would do the job nicely.

Is that the Galois who died in a duel?

At some point I think we're going to have to add to the other thread about diagnostics to show that a model is needed to provide the expected results against which the diagnostic output is compared, and that the more output you produce, the harder it becomes to home in on the first difference between the expected and actual results. Once one error has occurred, it is unclear whether the succession of errors that follow are directly attributable to the first error or are due to other ones.

The biggest problem we face in debugging LSL comes when rotations are involved. Positions and floats can be generated in a spreadsheet to provide the model results, but as yet I haven't found how to implement Quaternions and their associated functions in a spreadsheet, so the model itself has to be written in LSL, and then you're into the recursive path of debugging your model first...

Edited by Profaitchikenz Haiku
Link to comment
Share on other sites

1 minute ago, Profaitchikenz Haiku said:

Is that the Galois who died in a duel?

yes. Evariste Galois

and yes about stepping thru our code (printing/saying the values) to know exactly what are the values being produced at every given moment, and comparing them to what we know they should be

when we don't know what the values should be then we can never know if our script is performing correctly

Link to comment
Share on other sites

  • 2 weeks later...

Molly , thanks for your random code and I will let you know result  but I provided Prof all the steps and printouts . I just believe I am at the edge of knowledge  here  in second life and the only lovely script by Dora can be explained or employed as is .

The main reason for her crashes is that she and prof dump to lists which are not infinite in second life scripts and crash as they are memory hungry  and this is why Dora code crashes  With a 800 line script this is fatal. A simpler approach to this is to execute a single of few moves that don't eat memory . I really don't see why this example is not improved . I have been looking elsewhere for math's explanation, but have had no luck.

 

Hugs D 

 

Link to comment
Share on other sites

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