Join us in Outworldz at www.outworldz.com:9000 or follow us:

How to make a realistic splash of spray in Second Life™

In this post, I'll show you how to script a realistic splash when your whale enters and leaves the water.

First, you need to add add another prim.   This prim will point the Z axis down.  Particles come out of the Z-axis in a prim. 

Add the following script to the new prim, and position it near the blow-hole of your whale. Click it first, then click the whale, and link them so you do not disturb the root prim.  The box with the main scripts in it must be Yellow.

splash

This script has several functions.  It has an on/off switch.  It sprays a water particle in a circle.   The circle spins rapidly so that you see a ring of water. The script decides how high the whale is above the water.  It then adjusts the spray position so that a ring of water spray rises up from the center of the whale that is always at water level. As the whale rises, the spray gets less.

Download

// particles constants
float maxsysage = 0.0;		// particles spray forever
float maxspeed = 0.3;		// max speed 0.3 meters a second
float minspeed = 0.15;		// and min is about half that.
float burstrad = 0.0;		// no radius at all
integer burstcount = 20;	// spray 20 of them
float burstrate = 0.01;		// really fast.. lets swamp the viewer with particles and spray.
float outangle = 0.075;		// make a wide cone
float inangle = 0;			
vector omega = <0.0,0.0,0.0>; // no rotation
float startalph = 0.75;			// start semi-transparent
float endalph = 0.015;			// end almost invisible
vector startscale = <2.0,2.0,2.0>;	// start at 2 X the size of the texture
vector endscale = <4.0,4.0,4.0>;	// and end up twice that
float maxage = 1.7;					// last for 1.7 seconds
vector accel = <0.0, 0.0, 1.0>;		// push in the Z axis
string texture = "";				

// global constants
vector pos;
vector vel;
vector up;
float ground = 0.0;
float water = 0.0;
float height = 0.0;
float oscillation = 1.25;
float start_mult = 0.1;		// when we start up, this makes the water 'rise' over time
float rad;
integer oscillate = TRUE;
integer started = FALSE;

This next subroutine will calculate the height of the water, the spew, oscillation, and size of the particles.

Particles(integer part_on)
{
    maxage = 0.001;
    if (!part_on) jump particles;
    vel = llGetVel() * 0.2;
    ground = llGround(vel);
    water = llWater(vel);
    if (ground < water) {
        maxspeed = 2.5;
        minspeed = 1.25;
        oscillation = 2.0;
        endscale = <3.0,3.0,3.0>;
        maxage = 2.0;
        ground = water;
        texture = "7f70a931-6300-8dbc-caca-8b09a9c2cf11";
    } else {
        maxspeed = 1.75;
        minspeed = 0.875;
        oscillation = 1.25;
        endscale = <4.0,4.0,4.0>;
        maxage = 1.75;
        texture = "Water Particle - Mist";
    }

    pos = llGetPos() + vel;
    up = llRot2Up(llGetRot());
    height = pos.z - ground - 0.5;
    height += (1.0 - up.z) * height;
    if (height < 6.0 && height > -1.0) {
        rad = 1.5 + (oscillate * oscillation);
        outangle = PI - llAtan2(rad, height);
        inangle = outangle + 0.15;
        burstrad = rad / llSin(outangle);
        startalph = ((llFabs(height) / -8.57) + 0.8 - (!oscillate * 0.15)) * start_mult;
        endalph = ((llFabs(height) / -200.0) + 0.04) * start_mult;
        maxsysage = 0.0;
        part_on = TRUE;
    } else {
        maxsysage = 0.01;
        part_on = FALSE;
    }
    
    @particles;

After the parameters have been calculated, we spray them from the Z-axis of the prim:

 


    llParticleSystem([PSYS_PART_FLAGS,
            PSYS_PART_INTERP_COLOR_MASK |
            PSYS_PART_INTERP_SCALE_MASK |
            //PSYS_PART_FOLLOW_VELOCITY_MASK |
            PSYS_PART_WIND_MASK,
            PSYS_SRC_PATTERN,
            PSYS_SRC_PATTERN_ANGLE_CONE,
            PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
            PSYS_PART_START_ALPHA, startalph,
            PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
            PSYS_PART_END_ALPHA, endalph,
            PSYS_PART_START_SCALE, startscale,
            PSYS_PART_END_SCALE, endscale,
            PSYS_PART_MAX_AGE, maxage,
            PSYS_SRC_ACCEL, accel,
            PSYS_SRC_TEXTURE, texture,
            PSYS_SRC_BURST_RATE, burstrate,
            PSYS_SRC_ANGLE_BEGIN, inangle,
            PSYS_SRC_ANGLE_END, outangle,
            PSYS_SRC_BURST_PART_COUNT, burstcount,
            PSYS_SRC_BURST_RADIUS, burstrad,
            PSYS_SRC_BURST_SPEED_MIN, minspeed,
            PSYS_SRC_BURST_SPEED_MAX, maxspeed,
            PSYS_SRC_MAX_AGE, maxsysage,
            PSYS_SRC_OMEGA, omega
            ]);
    
    if (!part_on) 
    {
        llParticleSystem([]);		// shut down, not on
    } else {
        if (started) 
        {
            if (start_mult < 1.0) 
                start_mult += 0.075;
        } else {
            if (start_mult > 0.0) 
                start_mult -= 0.05;
            else {
                llSetTimerEvent(0.0);
                llParticleSystem([]);
            }
        }
        oscillate = !oscillate;	// toggle this flag
    }
}
 

The default function is called at start-up. Here we turn off all particles.

 


default
{
    state_entry()
    {
        llSetTimerEvent(0.0);		// turn off particles and timers on boot up
        Particles(FALSE);
    }
    

Touching the whale will start up the water spout for testing purposes ( and for fun! )

 


    touch_start(integer n)
    {
        started = TRUE;			// if touched, start up
        start_mult = 0.1;
        llSetTimerEvent(0.01);		// rapidly jab the timer
        
    }

A  link message  is a prim-to-prim message.   They are generated by llMessageLinked commands in the main script.  When the main script runs the following code:

llMessageLinked(LINK_SET,0,"on",NULL_KEY);	// part of another script

The link_message will be executed in the child script, and the string 'msg' will become 'on'.

 


    link_message(integer sender, integer num, string str, key id)
    {
        if (str == "on") {
            started = TRUE;
            start_mult = 0.1;
            llSetTimerEvent(0.01);
        } else if (str == "off") {
            started = FALSE;
            llParticleSystem([]);
            Particles(FALSE);
        }
    }

    timer()
    {
        Particles(TRUE);
    }
}
				

Next - > Part 7 - Realistic movement script - make the tail and fins move

Back to the Best Free Tools in Second Life and OpenSim.