Jump to content

water buoyancy and flotation script


Recommended Posts

1 hour ago, Mollymews said:

times r by the initial rotation of the object

I might be a bit dim today because of the heat but isn't a more appropriate way to get the current Z-rotation an apply that to whatever the X and X axes rotations are? As I understand it the Z-axis should be allowed to adopt various rotations to allow different headings but it's the Y and X axes that are going to be jiggling to and fro?

Link to comment
Share on other sites

1 hour ago, Profaitchikenz Haiku said:

isn't a more appropriate way to get the current Z-rotation an apply that to whatever the X and X axes rotations are?

possibly, depending on what else we might want to do

i went with the OP question. Using Wulfie's code snippet then how to apply it as wrote to the object's local rotation on script start

Link to comment
Share on other sites

2 hours ago, Mollymews said:

possibly, depending on what else we might want to do

Possibly we're at sixes and sevens here, my interpretation of what the OP is saying is "It's rocking fine, but it I turn it around it just snaps back to the original direction it was pointing".

This leads to an interesting challenge. At present, the only way once the boat has been rezzed to align it to a different direction is to stop the script, edit it to change the rotation, and then reset the script so that it reads the new Z-rotation, but here we hit on  problem. If we stop it when it is partway through a roll and a rise (oo-err missus) when we restart the script it's going to get those X and Y axis rotation as well as the vertical offset and take them as the new rezzed-rotation.

We can't use moving_end to detect when we have stopped turning the boat in edit mode because there's going to be a spate of moving_end events each time it rocks, rolls and rises.

The only kludge I can think of is to have a touch_event that detects if the user has touched it, and if it is in motion, returns to the no-pitch no-roll no-rise state and then stops the timer.

Once the owner has re-aligned the boat, they touch it again, and this time the script does a re-read of the basic position and rotation and starts all over again. (I prefer this approach to a full script reset).

I'm coming at this from a previous build of mine, the Sealey Punts that went to and fro across Lake Kness, and would be in a chaotic state after the monster from the deep had come up and swallowed punt and occupants and spat the punt back out, when in addition to rocking and pitching it had to spin slowly around before drifting back to shore. I used  a simpler method then Wulfie of getting a bobbing motion and because the punts went too and from from one jetty to another didn't have to worry about the alignment until the after-belch event. 

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

16 minutes ago, Profaitchikenz Haiku said:

The only kludge I can think of is to have a touch_event that detects if the user has touched it, and if it is in motion, returns to the no-pitch no-roll no-rise state and then stops the timer.

Once the owner has re-aligned the boat, they touch it again, and this time the script does a re-read of the basic position and rotation and starts all over again. (I prefer this approach to a full script reset)

yes agree. When testing this kind of project then I tend to go down the touch start/stop path as well

Link to comment
Share on other sites

1 hour ago, Profaitchikenz Haiku said:

"It's rocking fine, but it I turn it around it just snaps back to the original direction it was pointing".

My general approach to the problem -- setting some physics parameters in state_entry, along with some randomly or not so randomly applied rotational impulses -- would allow the boat to be freely turned and moved while it is 'rocking'.

  • Thanks 1
Link to comment
Share on other sites

18 hours ago, Profaitchikenz Haiku said:

I'm coming at this from a previous build of mine, the Sealey Punts that went to and fro across Lake Kness, and would be in a chaotic state after the monster from the deep had come up and swallowed punt and occupants and spat the punt back out, when in addition to rocking and pitching it had to spin slowly around before drifting back to shore. I used  a simpler method then Wulfie of getting a bobbing motion and because the punts went too and from from one jetty to another didn't have to worry about the alignment until the after-belch event. 

i had to think about this for a bit. This is a pretty ingenious solution

Link to comment
Share on other sites

Posted (edited)
On 6/16/2021 at 10:22 AM, Mollymews said:

times r by the initial rotation of the object



// global var rot
rotation rot;

state_entry()
{
   rot = llGetRot();
   ... other codes ...
}

timer()
{
  ...
  rotation r = llRotBetween(<0,0,1>, normal) * rot;
  ...
}

Ok tried that code but when I rotate the prim it still snaps back into original rotation.

Any example of how I could implement the solution?

Edited by Naiman Broome
Link to comment
Share on other sites

On 6/16/2021 at 5:44 PM, Quistessa said:

My general approach to the problem -- setting some physics parameters in state_entry, along with some randomly or not so randomly applied rotational impulses -- would allow the boat to be freely turned and moved while it is 'rocking'.

Didn't understand that :(.

Link to comment
Share on other sites

Related to this, there's a nice feature LL could implement to allow user-created water to be swimmable. Add a pathfinding type of "Water". You'd tag water in pools or small lakes with that. It would be treated as "Solid obstacle" for pathfinding purposes, but would affect the water height returned by llWater when over such an area. So boats and swim HUDs would automatically recognize water in a standard way.

Link to comment
Share on other sites

8 hours ago, Naiman Broome said:

Didn't understand that :(.

What is being suggested is not to explicitly move the boat up and down or rock it from side to side, but to set it to be a physical object and allow such region forces as the wind to disturb it. Because such forces would only move it around on the level of the water, some additional random impulses would have to be applied to make it rock and bob.

My past experiences with this were that it's very difficult t get subtle motions like this, the object either doesn't visibly move at all, or else it starts leaping everywhere like a gazelle with piles.

Edited by Profaitchikenz Haiku
Link to comment
Share on other sites

5 hours ago, Mollymews said:

be best if you post the code you have at the moment. Then we can suggest a way forward

Sorry I wronged quote, I actually did implement in the code, and simply when I go to rotate the position it snaps back , what I was thinking is if I could eventually add a touch me event , to stop the movement and so be able to rotate the item then relaunch the animation with anothertouch resetting it , would that work?

The one with physics thing is it needed? The animation I got now I pretty much like it , its smooth and good but I am wondering could it be too heavy for sims? what if I place like ten items like those around?

Link to comment
Share on other sites

34 minutes ago, Naiman Broome said:

Sorry I wronged quote, I actually did implement in the code, and simply when I go to rotate the position it snaps back.

The animation I got now I pretty much like it , its smooth and good but I am wondering could it be too heavy for sims? what if I place like ten items like those around?

on the first. As rot = llGetRot() is only performed when the script is started then as wrote you will need to:

1) stop the script from running.

2) Re-orient the object

3) Restart the script

on the second.  All scripts impact the region server to some degree. Regions can run 100s sometimes 1000s of scripts quite well without any noticeable degradation.  The major impact of multiple scripts manipulating objects on a fast timer is the amount of data that has to be sent to the visitors viewer.  Viewer-side lag is far more about data than it is about server script time. What is acceptable is something that only the person viewing your objects can determine as it affects them 

This said, if it was me I would do this kind of animation with looped keyframed motion. In state_entry event create the keyframe list one time, then start the animation. The script not running a timer will have minimal impact on the server.  The data to display the animation will only be sent once to the viewer. Thereafter the animation will play on the viewer without any further impact on the region server

Wulfie's sine wave function can be modified to create a keyframe list.  You will have to read up on this tho and how changes between frames are calculated from the current rotation/position of the last frame in the list.  When you work out how to do keyframed motion then you can achieve very smooth clientside (viewer) animation for minimal impact on the region server 

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

2 hours ago, Naiman Broome said:

if I could eventually add a touch me event , to stop the movement and so be able to rotate the item then relaunch the animation with anothertouch resetting it , would that work?

Yes, it's the simplest solution.

There is one slight complication as I mentioned in a post above. When you touch it and the motion stops, you must reset any small rotations or position variations, and then make the rotation, before touching it and starting again.

I suggest you post what you already have working and we can then suggest how to add such a touch event handler to it.

In passing, Molly's suggestion of using keyframed motion for this is both the most elegant and the most likely to give best visual effects, but from what you have indicated is your level of scripting knowledge, not the best one the start off with, I suggest you become comfortable with basic rotation and position manipulation first and then progress to the smooth stuff when you're happy.

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

On 6/19/2021 at 2:14 PM, Profaitchikenz Haiku said:

 

There is one slight complication as I mentioned in a post above. When you touch it and the motion stops, you must reset any small rotations or position variations, and then make the

How do you reset each single rotation etc?  Isn't enough just reset the script?

Link to comment
Share on other sites

When you reset the script it will read the current rotation of the object to get the starting point, and if you stopped it while it was in mid-rock, it will take that angle as the normal angle and then start rocking it side to side. You have to first remove any X and Y rotations that have been added by the oscillatory part of the script (and it isn't as simple as just setting the X and Y rotations to Zero, your object might be a strange mesh build that has to be rotated on the X or Y axis to assume a normal visible appearance).

Link to comment
Share on other sites

15 hours ago, Naiman Broome said:

How do you reset each single rotation etc?  Isn't enough just reset the script?

this is generally what I do with these kinds of moving things that I want to stop/start

rotation rot;   // starting rotation
vector pos;     // starting position

integer on; // on/off flag to move object

default
{
   state_entry()
   {
      rot = <0,60,0> * DEG_TO_RAD;
      pos = <0, 0,1> * DEG_TO_RAD;
      // <0,60,0> and <0,0,1> is copied directly (whichever they are) from the Build Edit tool
      // where I have manually set the starting rotation and position
      
      llSetRot(rot); // reset object to the starting rotation
      llSetPos(pos); // reset object to the starting position
   }

   touch_start(integer num)
   {
      if (llDetectedKey(0) == llGetOwner())
      {
          on = !on;
          if (!on) // stop
          {
               llSetRot(rot); // reset object to the starting rotation
               llSetPos(pos); // reset object to the starting position
          }
          llSetTimerEvent(1.0 * on);
          // 1.0 * 1 = 1.0. timer starts
          // 1.0 * 0 = 0.0. timer stops
          // change 1.0 to the time that suits your app

      }
   }
   
   timer()
   {
       
       // move/oscilate the object here

   }
}

edit gah

the line: rot =  should be rot = llEuler2Rot(<0,60,0> * DEG_TO_RAD); and pos should not be multiplied by DEG_TO_RAD

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

2 hours ago, Naiman Broome said:

Hi I noticed in the script I did that after a while the object tend either to sink or to float and rise in position with time, and I have to reset its water level manually , what can be the cause of that?

without seeing the part of the code that you think is causing the issue then we can only guess

assuming that the object is non-physical then my guess would be math rounding errors that accumulate over the duration of the movement/oscillation. The main culprit causing this typically is each movement/oscillation beginning with a read of the current position and/or rotation (llGetPos and/or llGetRot)

Edited by Mollymews
is
Link to comment
Share on other sites

7 hours ago, Naiman Broome said:

Hi I noticed in the script I did that after a while the object tend either to sink or to float and rise in position with time, and I have to reset its water level manually , what can be the cause of that?

This is particularly evident when using keyframe motion, as Molly said, rounding errors accumulating and moving_end lapses both cause this drift. It is particularly noticeable in regions where the %script run figure is 40% or less.

My own workaround is to keep a record of the centre height or rotation angle and use a counter : every 20 movements or swings, when it has returned to what is supposed to be the centre, I will issue a llSetPos or llSetRot to actually enforce that position. The counter is then reset and the slow creep away begins once more.

I find myself being forced reluctantly into a slow spiral downwards: adding defensive programming to try and cope with the region performance issues is actually making the problem worse in that it is yet more code to further load the region, and yet, there is no alternative.

Link to comment
Share on other sites

Posted (edited)

This is the script I been working on :
 


FindGroundOrWater()
{
    vector vTarget = llGetPos();
    vTarget.z = llGround( ZERO_VECTOR );
    float fWaterLevel = llWater( ZERO_VECTOR );
    if( vTarget.z < fWaterLevel )
        vTarget.z = fWaterLevel;
    llSetRegionPos(vTarget)+ 0.288;
}

default
{
    
    state_entry()
    {
        llSetTimerEvent(0.1);
    }
 touch_start(integer num_detected)
    {
FindGroundOrWater();
    }
    timer()
    {
vector pos = llGetPos();
float t = llGetTime();
float tilt = llCos(t) * 0.15;
float tilt2 = llSin(t/2) * 0.15;
float tilt3 = llSin(t/2) * 0.1;

vector normal = llVecNorm(<tilt,  tilt3, 2>);
rotation r = llRotBetween(<0,0,2>, normal);
float height = llCos(t) * 0.01;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [
             PRIM_ROTATION, r,
             PRIM_POSITION, pos + <0,0,height>]);
             llSetStatus(STATUS_PHYSICS,FALSE);
    }
    
}

 

Edited by Naiman Broome
Link to comment
Share on other sites

47 minutes ago, Naiman Broome said:

This is the script I been working on :
 

 

try making 'pos' a global and set it one time in state_entry 'pos = llGetPos()' so that the timer oscillation calculation always begins at a constant pos rather than a potentially variable pos

edit add: what Wulfie said

Edited by Mollymews
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...