Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Rainbow Particle Color Changing

Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
10-24-2007 11:36
Hiyas Everyone,

I would like to cycle PSYS_PART_END_COLOR, PartE (vector = PartE) thru the colors of the rainbow over a period of a minute or so. The colors I want to cycle thru are:

White <1.00, 1.00, 1.00>
Yellow<1.00, 1.00, 0.00>
Orange<1.00, 0.50, 0.00>
Red<1.00, 0.00, 0.00>
Green<0.00, 1.00, 0.00>
Blue<0.00, 0.00, 1.00>
Purple<0.50, 0.00, 1.00>
White<1.00, 1.00, 1.00>

I have broken the changes in between colors into 4 steps. Now, before I attempt it MY way... lol, I would like to know if someone has done anything similar or has a simplified the code to cycle thru these colors continuosly. All help is greatly appreciated! :-)
Anya Ristow
Vengeance Studio
Join date: 21 Sep 2006
Posts: 1,243
10-24-2007 11:55
If you want to smoothly transition between colors of the spectrum using the RGB color space, it's handy to think of the colors being vertexes on a cube, like this:

http://www.upvector.com/index.php?section=tutorials&subsection=tutorials/colorspace

Start at, say, red <1,0,0> and increase the green unti lyou get <1,1,0> (yellow). Then decrease the red until you get <0,1,0> (green), then increase the blue until you get <0,1,1> (cyan), then devrease the green until you get <0,0,1> (blue), then increase the red until you get <1,0,1> (magenta), then decrease the blue until you are back to <1,0,0> (red). You are traveling along the edges of the cube with three variables: red, green, blue.

There's probably a clever way to shorten it that'd be less readable, but I just implemented this with six for-loops. Put your particles call in a subroutine so there's only one of them or you'll go battty fine tuning the non-color parameters in six places.

You can include white in your sequence by moving to the <1,1,1> vertex.
Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
Thanx Anya!
10-24-2007 12:17
This is a great tutorial on colors. The sequence in color change seems to be more natural this way and easier to loop thru! Thanx for the help! :-)
Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
Snaps to Next
10-24-2007 16:14
Okies... no matter how many loops I try, this will just at one point snap to the next color. There is no smooth blending. The more loops I put in, the longer it takes to change to the next color but it's still a snap effect. Any ideas?

red = 1.00;
green = 0.00;
blue = 0.00;
x = 1;
ParticleStart();
while (x=1)
{
// Increase Green to Get Yellow
integer n;
for (n = 0; n<100; n++)
green = (green + .01);
ParticleStart();

// Decrease Red to Get Green
integer p;
for (p = 0; p<100; p++)
red = (red - .01);
ParticleStart();
//Increase Blue to Get to Cyan
integer q;
for (q = 0; q<100; q++)
blue = (blue + .01);
ParticleStart();
//Decrease Green to Get Blue
integer r;
for (r = 0; r<100; r++)
green = (green - .01);
ParticleStart();
//Increase Red to Get Magenta
integer b;
for (b = 0; b<100; b++)
red = (red + .01);
ParticleStart();
// Decrease Blue to Get Red
integer y;
for (y = 0; y<100; y++)
blue = (blue - .01);
ParticleStart();
Anya Ristow
Vengeance Studio
Join date: 21 Sep 2006
Posts: 1,243
10-24-2007 21:13
Your ParticleStart calls are not in your loops, so you are, for example, incrementing green 100 times, and then doing one ParticleStart.

Here's mine...

float red = 1.0;
float green = 0.0;
float blue = 0.0;

while ( 1)
{
for ( green = 0.0; green < 1.01; green += .05)
particlestuff( <red,green,blue>;);
green = 1.0;

for ( red = 1.0; red > -0.01; red -= .05)
particlestuff( <red,green,blue>;);
red=0.0;

for ( blue = 0.0; blue < 1.01; blue += .05)
particlestuff( <red,green,blue>;);
blue = 1.0;

for ( green = 1.0; green > -0.01; green -= .05)
particlestuff( <red,green,blue>;);
green = 0.0;

for ( red = 0.0; red < 1.01; red += .05)
particlestuff( <red,green,blue>;);
red = 1.0;

for ( blue = 1.0; blue > -0.01; blue -= .05)
particlestuff( <red,green,blue>;);
blue = 0.0;
}

I have a half second of sleep after the llParticleSystem calls.
Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
Ahhh.....
10-29-2007 04:40
Thanx again!

One of the reasons I like coming to the forums is that I find people so helpful and knowledgeable! :-)
Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
Stopping The "While" loop
11-14-2007 03:26
I placed the "while" loop in one script and have been trying to toggle the particles on/off from a diff script using messagelink. It seems that no matter how I set it up (states, if/else), the message to set the "while" false does does get thru. I always end up having to manually reset the script to get any kind of llParticleSystem([]). Any help on stopping the "while" loop from a diff script will be greatly appreciated. :-)
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-14-2007 04:00
From: Zena Juran
I placed the "while" loop in one script and have been trying to toggle the particles on/off from a diff script using messagelink. It seems that no matter how I set it up (states, if/else), the message to set the "while" false does does get thru. I always end up having to manually reset the script to get any kind of llParticleSystem([]). Any help on stopping the "while" loop from a diff script will be greatly appreciated. :-)

If the particle script has some kind of start(like touch_start for example) besides just jumping into the while in state_entry then you could try llResetOtherScript. If that doesn't work then look at llSetScriptState in the wiki.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
11-14-2007 04:11
Thanx Jesse, those would've been perfect except that my script is in a diff prim in a link_set. Still trying! :-)
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-14-2007 05:14
From: Zena Juran
Thanx Jesse, those would've been perfect except that my script is in a diff prim in a link_set. Still trying! :-)

Just create a small helper script in the prim with the particle script to listen for llSays or link messages. It can then use llResetOtherScript.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Debbie Trilling
Our Lady of Peenemünde
Join date: 17 Oct 2006
Posts: 434
11-14-2007 05:23
From: Zena Juran
toggle the particles on/off from a diff script using messagelink. It seems that no matter how I set it up (states, if/else), the message to set the "while" false does does get thru


Yep, had exact same situation using this rainbow-colour generator code (thanks for posting it Anya, the effect is wonderful!)

I got around it as follows:

1) Add TRUE/FALSE integer responding to touch (or however you want to control it; I use a dialog menu but same difference)
2) Place the rainbow-colour generator code in a relatively fast timer
3) Place the whole rainbow-colour generator code in an IF-ELSE statement, removing the outer WHILE loop entirely
3) Only execute the rainbow-colour generator code if integer = TRUE. Set llSetTimerEvent to zero if integer = FALSE
4) Only execute the llParticleSystem() function if integer = TRUE

Something like this...

CODE

timer()
{
if (Power)
{

for ( green = 0.0; green < 1.01; green += .05)
if (Power) {ParticlesStart();} else {llSetTimerEvent(0.0);llParticleSystem([]);}
green = 1.0;
for ( red = 1.0; red > -0.01; red -= .05)
if (Power) {ParticlesStart();} else {llSetTimerEvent(0.0);llParticleSystem([]);}
red=0.0;
for ( blue = 0.0; blue < 1.01; blue += .05)
if (Power) {ParticlesStart();} else {llSetTimerEvent(0.0);llParticleSystem([]);}
for ( green = 1.0; green > -0.01; green -= .05)
if (Power) {ParticlesStart();} else {llSetTimerEvent(0.0);llParticleSystem([]);}
green = 0.0;
for ( red = 0.0; red < 1.01; red += .05)
if (Power) {ParticlesStart();} else {llSetTimerEvent(0.0);llParticleSystem([]);}
red = 1.0;
for ( blue = 1.0; blue > -0.01; blue -= .05)
if (Power) {ParticlesStart();} else {llSetTimerEvent(0.0);llParticleSystem([]);}
blue = 0.0;
}
else
{
llSetTimerEvent(0.0);
llParticleSystem([]);
}
}


The timer gives enough time-gap for the script to receive the stop instruction (integer = FALSE) and set the timer to zero.

I found that by doing this I could control ON/OFF and also use llMessageLinked() to pass the colour generated in one of the scripts to all the other scripts, thus keeping the whole devise colour sync'ed.

I'm sure that there is a more efficient solution, and I'm working on that as we speak (feel sure someone will point me in the right direction after seeing the above!), but that solution does work.

One aside about this rainbow-colour generator-code ~ it is pretty intensive and when you switch it on you can see 'Script Perf' jump sky-high! So, I only use the rainbow-colour generating code in one script and pass that colour to the other scripts, rather than have each script have its own copy. Not only that, I also put in an AutoOff script which automatically switches the device off if nobody is in the vicinity after 15mins.

Hope that helps :)
Anya Ristow
Vengeance Studio
Join date: 21 Sep 2006
Posts: 1,243
11-14-2007 08:03
You can't interrupt it with your link messages because link messages don't interrupt the infinite loop. Infinite loops and sleeps are quick hacks. As has been said, timers are a better choice.

Here's a complete script that uses timers and uses touch as an on/off switch. You'd use link messages rather than touch, but the idea's the same.

If you use more than one particle source they will get out of sync, unless you make one script control the timer for all particle sources, as Debbie described.

CODE

float red;
float green;
float blue;

float loop = 0.;
integer stage = 0;

integer doStuff = FALSE;

particleStuff()
{
llParticleSystem([PSYS_PART_FLAGS,
PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_INTERP_COLOR_MASK,
PSYS_PART_START_ALPHA, 1.,
PSYS_PART_END_ALPHA, 0.,
PSYS_PART_START_SCALE, <.15,.6,0>,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE,
PSYS_PART_START_COLOR, <red, green, blue>,
PSYS_PART_END_COLOR, <red, green, blue>,
PSYS_SRC_BURST_SPEED_MIN, 0.01,
PSYS_SRC_BURST_SPEED_MAX, 0.01,
PSYS_SRC_BURST_RATE, 0.04,
PSYS_PART_MAX_AGE, 4.]);
}

colorChange()
{
if ( stage == 0)
{
red = 1.; green = loop; blue = 0.;
}
else if ( stage == 1)
{
red = 1. - loop; green = 1.; blue = 0.;
}
else if ( stage == 2)
{
red = 0.; green = 1.; blue = loop;
}
else if ( stage == 3)
{
red = 0.; green = 1. - loop; blue = 1.;
}
else if ( stage == 4)
{
red = loop; green = 0.; blue = 1.;
}
else if ( stage == 5)
{
red = 1.; green = 0.; blue = 1. - loop;
}
particleStuff();
}

default
{
state_entry()
{
llParticleSystem([]);
}

touch_start(integer total_number)
{
doStuff = !doStuff;
if ( doStuff)
llSetTimerEvent( .5);
else
{
llParticleSystem([]);
llSetTimerEvent( .0);
}
}

timer()
{
loop += .05;
if ( loop > 1.01)
{
loop = 0.;
stage++;
if ( stage > 5)
stage = 0;
}
colorChange();
}
}
Anya Ristow
Vengeance Studio
Join date: 21 Sep 2006
Posts: 1,243
11-14-2007 08:44
Oh, heck, this thread has convinced me to update my rave sticks. These are just a bar with a particle-spewing prim on each end that you attach to your hand.

The first script is the controller script. It goes in the bar and is controlled by touch on/off. Having just one timer fixed the drift problem I mentioned. It basically makes sure the two ends have different colors. Stage1 is for one end, stage2 is the other. The bar is the root prim. When turned off, a link message with stage=99 is sent to tell the linked prims to turn off particles. The link messages otherwise tell the prims which stage each should be in and what the current loop value is.

CODE

float loop = 0.;
integer stage1 = 0;
integer stage2 = 3;

integer doStuff = FALSE;

default
{
touch_start(integer total_number)
{
doStuff = !doStuff;
if ( doStuff)
llSetTimerEvent( .5);
else
{
llMessageLinked( 2, 99, "", NULL_KEY);
llMessageLinked( 3, 99, "", NULL_KEY);
llSetTimerEvent( .0);
}
}

timer()
{
loop += .05;
if ( loop > 1.01)
{
loop = 0.;
stage1++;
stage2++;
if ( stage1 > 5)
stage1 = 0;
if ( stage2 > 5)
stage2 = 0;
}
llMessageLinked( 2, stage1, (string) loop, NULL_KEY);
llMessageLinked( 3, stage2, (string) loop, NULL_KEY);
}
}


The second script goes in each end prim and receives the link messages for either turning off or changing the color. Note that since this is my rave stick, I'm also coloring the end prims and making them light sources (llSetPrimitiveParams).

CODE

float red;
float green;
float blue;

particleStuff()
{
llParticleSystem([PSYS_PART_FLAGS,
PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_INTERP_COLOR_MASK,
PSYS_PART_START_ALPHA, 1.,
PSYS_PART_END_ALPHA, 0.,
PSYS_PART_START_SCALE, <.15,.6,0>,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE,
PSYS_PART_START_COLOR, <red, green, blue>,
PSYS_PART_END_COLOR, <red, green, blue>,
PSYS_SRC_BURST_SPEED_MIN, 0.01,
PSYS_SRC_BURST_SPEED_MAX, 0.01,
PSYS_SRC_BURST_RATE, 0.04,
PSYS_PART_MAX_AGE, 4.]);
llSetPrimitiveParams( [PRIM_COLOR, ALL_SIDES, <red, green, blue>, 1.0,
PRIM_POINT_LIGHT, TRUE, <red, green, blue>, 1.0, 2.0, 0.75]);
}

colorChange( integer stage, float loop)
{
if ( stage == 0)
{
red = 1.; green = loop; blue = 0.;
}
else if ( stage == 1)
{
red = 1. - loop; green = 1.; blue = 0.;
}
else if ( stage == 2)
{
red = 0.; green = 1.; blue = loop;
}
else if ( stage == 3)
{
red = 0.; green = 1. - loop; blue = 1.;
}
else if ( stage == 4)
{
red = loop; green = 0.; blue = 1.;
}
else if ( stage == 5)
{
red = 1.; green = 0.; blue = 1. - loop;
}
particleStuff();
}

default
{
state_entry()
{
llParticleSystem([]);
}

link_message( integer sender_num, integer stage, string str, key id)
{
if ( stage == 99)
llParticleSystem([]);
else
colorChange( stage, (float) str);
}
}
Zena Juran
Registered User
Join date: 21 Jul 2007
Posts: 473
11-14-2007 11:17
Debbie and Anya... Big Thank You!

I didn't notice the script perf until you mentioned it Debbie... something to keep an eye on. Anya's newer version changes color a little more slowly and the IPS' are lower. I now have control... woo hooo! That infinite loop thru me for a loop, maybe I'll add that to the "If I Woulda Known Then..." list. Again, thanx to all. :-)