Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Particle play

BlueWillow Kipling
Registered User
Join date: 14 Sep 2005
Posts: 12
09-21-2005 11:38
I'm trying to get a star-shaped twinkle on a gold bangle bracelet. Well, mostly I'm trying to play around and get a gut level understanding of what the various parameters affecting particles really mean. Parameters may not be strictly, technically the right word, but you know what I mean.

What it does now is the particles burst out in a flattened oval in gold, and then the oval flips around its axis as the particles fade to white and age out. I like that part.

But the oval also moves along the axis perpendicular to its plane, and I don't want it to do that. I want the place where the center of the oval intersects the bracelet to stay the same throughout the cycle.

The other thing I tried to do to get a starburst instead of just a line, and this method is probably inefficient as hell, is to run a second script that's a clone of the first but just turns the second oval at a right angle to the first. Uh...I wasn't successful.

I know actually designing and coding the script *right* is the thing to do, and I don't intend to keep these scripts done this inefficiently on this object---I'm just trying to get a concrete understanding of what does what and using this as a learning project.

So how would I keep the oval from moving along the bracelet in a single script? And how would I get the second script to shoot out it's squished oval at a right angle to the first script's squished oval?

Anything anyone can tell me in plain English that helps me make sense of particles would be most welcome. Part of my problem is that I don't understand angle bursts--angle with respect to what? And I don't understand rotations, push, and vectors with respect to SL. I took plenty of college math and physics--I understand vectors themselves, I'm just having trouble making the connection. And the connection of cartesian coordinates WRT SL--which way are the x, y, and z axes and wrt what reference point?

I hoped I could sort it out by fooling around with an existing script, but I'm having limited luck.

Uh...help?

BlueWillow
BlueWillow Kipling
Registered User
Join date: 14 Sep 2005
Posts: 12
Scripts
09-21-2005 11:41
// Particle Script 0.5
// Created by Ama Omega
// 3-26-2004
// modded by BlueWillow Kipling 9-21-05
// renamed Particle 1 script

// Mask Flags - set to TRUE to enable
integer glow = TRUE; // Make the particles glow
integer bounce = FALSE; // Make particles bounce on Z plane of object
integer interpColor = TRUE; // Go from start to end color
integer interpSize = TRUE; // Go from start to end size
integer wind = TRUE; // Particles effected by wind
integer followSource = TRUE; // Particles follow the source
integer followVel = TRUE; // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner
// and "self" will target this object
// or put the key of an object for particles to go to
key target = "self";

// Particle paramaters
float age = 1; // Life of each particle
float maxSpeed = 1; // Max speed each particle is spit out at
float minSpeed = 1; // Min speed each particle is spit out at
string texture = ""; // Texture used for particles, default used if blank
float startAlpha = 1; // Start alpha (transparency) value
float endAlpha = 0.1; // End alpha (transparency) value
vector startColor = <1,1,0>; // Start color of particles <R,G,B>
vector endColor = <1,1,1>; // End color of particles <R,G,B> (if interpColor == TRUE)
vector startSize = <1,.2,1>; // Start size of particles
vector endSize = <1,0,1>; // End size of particles (if interpSize == TRUE)
vector push = <0,0,0>; // Force pushed on particles

// System paramaters
float rate = 1.5; // How fast (rate) to emit particles
float radius = 1; // Radius to emit particles for BURST pattern
integer count = 1; // How many particles to emit per BURST
float outerAngle = 1.54; // Outer angle for all ANGLE patterns
float innerAngle = 1.55; // Inner angle for all ANGLE patterns
vector omega = <0,0,0>; // Rotation of ANGLE patterns around the source
float life = 0; // Life in seconds for the system to make particles

// Script variables
integer pre = 2; //Adjust the precision of the generated list.

integer flags;
list sys;
integer type;
vector tempVector;
rotation tempRot;
string tempString;
integer i;

string float2String(float in)
{
return llGetSubString((string)in,0,pre - 7);
}

updateParticles()
{
flags = 0;
if (target == "owner";) target = llGetOwner();
if (target == "self";) target = llGetKey();
if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;
if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;
if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;
if (wind) flags = flags | PSYS_PART_WIND_MASK;
if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;
if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;
if (target != "";) flags = flags | PSYS_PART_TARGET_POS_MASK;
sys = [ PSYS_PART_MAX_AGE,age,
PSYS_PART_FLAGS,flags,
PSYS_PART_START_COLOR, startColor,
PSYS_PART_END_COLOR, endColor,
PSYS_PART_START_SCALE,startSize,
PSYS_PART_END_SCALE,endSize,
PSYS_SRC_PATTERN, pattern,
PSYS_SRC_BURST_RATE,rate,
PSYS_SRC_ACCEL, push,
PSYS_SRC_BURST_PART_COUNT,count,
PSYS_SRC_BURST_RADIUS,radius,
PSYS_SRC_BURST_SPEED_MIN,minSpeed,
PSYS_SRC_BURST_SPEED_MAX,maxSpeed,
PSYS_SRC_TARGET_KEY,target,
PSYS_SRC_INNERANGLE,innerAngle,
PSYS_SRC_OUTERANGLE,outerAngle,
PSYS_SRC_OMEGA, omega,
PSYS_SRC_MAX_AGE, life,
PSYS_SRC_TEXTURE, texture,
PSYS_PART_START_ALPHA, startAlpha,
PSYS_PART_END_ALPHA, endAlpha
];

llParticleSystem(sys);
}

default
{
state_entry()
{
updateParticles();
}

touch_start(integer num)
{
llWhisper(0,"...Generating List...";);
for (i=1;i<42;i+=2)
{
type = llGetListEntryType(sys,i);
if(type == TYPE_FLOAT)
{
tempString = float2String(llList2Float(sys,i));
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
else if (type == TYPE_VECTOR)
{
tempVector = llList2Vector(sys,i);
tempString = "<" + float2String(tempVector.x) + ","
+ float2String(tempVector.y) + ","
+ float2String(tempVector.z) + ">";
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
else if (type == TYPE_ROTATION)
{
tempRot = llList2Rot(sys,i);
tempString = "<" + float2String(tempRot.x) + ","
+ float2String(tempRot.y) + ","
+ float2String(tempRot.z) + ","
+ float2String(tempRot.s) + ">";
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
else if (type == TYPE_STRING || type == TYPE_KEY)
{
tempString = "\"" + llList2String(sys,i) + "\"";
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
}
sys = llListSort(sys,2,TRUE);
if (target == "";) sys = llDeleteSubList(sys,38,39);
else if (target == llGetKey() )
sys = llListInsertList(llDeleteSubList(sys,39,39),["llGetKey()"],39);
else if (target == llGetOwner() )
sys = llListInsertList(llDeleteSubList(sys,39,39),["llGetOwner()"],39);
if (texture == "";) sys = llDeleteSubList(sys,24,25);
if (!interpSize) sys = llDeleteSubList(sys,12,13);
if (!interpColor) sys = llDeleteSubList(sys,6,7);

llWhisper(0,"[" + llList2CSV(llList2List(sys,0,21)) + ",";);
llWhisper(0,llList2CSV(llList2List(sys,22,-1)) + "]";);
}
}


---------------------------------------------------------------------------------------------------

// Particle Script 0.5
// Created by Ama Omega
// 3-26-2004
// modded by BlueWillow Kipling 9-23-05
// renamed Particle 2 Script

// Mask Flags - set to TRUE to enable
integer glow = TRUE; // Make the particles glow
integer bounce = FALSE; // Make particles bounce on Z plane of object
integer interpColor = TRUE; // Go from start to end color
integer interpSize = TRUE; // Go from start to end size
integer wind = TRUE; // Particles effected by wind
integer followSource = TRUE; // Particles follow the source
integer followVel = TRUE; // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner
// and "self" will target this object
// or put the key of an object for particles to go to
key target = "self";

// Particle paramaters
float age = 1; // Life of each particle
float maxSpeed = 1; // Max speed each particle is spit out at
float minSpeed = 1; // Min speed each particle is spit out at
string texture = ""; // Texture used for particles, default used if blank
float startAlpha = 1; // Start alpha (transparency) value
float endAlpha = 0.1; // End alpha (transparency) value
vector startColor = <1,1,0>; // Start color of particles <R,G,B>
vector endColor = <1,1,1>; // End color of particles <R,G,B> (if interpColor == TRUE)
vector startSize = <1,.2,1>; // Start size of particles
vector endSize = <1,0,1>; // End size of particles (if interpSize == TRUE)
vector push = <1,1,1>; // Force pushed on particles

// System paramaters
float rate = 1.5; // How fast (rate) to emit particles
float radius = 1; // Radius to emit particles for BURST pattern
integer count = 1; // How many particles to emit per BURST
float outerAngle = 1.00; // Outer angle for all ANGLE patterns
float innerAngle = 1.01; // Inner angle for all ANGLE patterns
vector omega = <1,1,1>; // Rotation of ANGLE patterns around the source
float life = 0; // Life in seconds for the system to make particles

// Script variables
integer pre = 2; //Adjust the precision of the generated list.

integer flags;
list sys;
integer type;
vector tempVector;
rotation tempRot;
string tempString;
integer i;

string float2String(float in)
{
return llGetSubString((string)in,0,pre - 7);
}

updateParticles()
{
flags = 0;
if (target == "owner";) target = llGetOwner();
if (target == "self";) target = llGetKey();
if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;
if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;
if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;
if (wind) flags = flags | PSYS_PART_WIND_MASK;
if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;
if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;
if (target != "";) flags = flags | PSYS_PART_TARGET_POS_MASK;
sys = [ PSYS_PART_MAX_AGE,age,
PSYS_PART_FLAGS,flags,
PSYS_PART_START_COLOR, startColor,
PSYS_PART_END_COLOR, endColor,
PSYS_PART_START_SCALE,startSize,
PSYS_PART_END_SCALE,endSize,
PSYS_SRC_PATTERN, pattern,
PSYS_SRC_BURST_RATE,rate,
PSYS_SRC_ACCEL, push,
PSYS_SRC_BURST_PART_COUNT,count,
PSYS_SRC_BURST_RADIUS,radius,
PSYS_SRC_BURST_SPEED_MIN,minSpeed,
PSYS_SRC_BURST_SPEED_MAX,maxSpeed,
PSYS_SRC_TARGET_KEY,target,
PSYS_SRC_INNERANGLE,innerAngle,
PSYS_SRC_OUTERANGLE,outerAngle,
PSYS_SRC_OMEGA, omega,
PSYS_SRC_MAX_AGE, life,
PSYS_SRC_TEXTURE, texture,
PSYS_PART_START_ALPHA, startAlpha,
PSYS_PART_END_ALPHA, endAlpha
];

llParticleSystem(sys);
}

default
{
state_entry()
{
updateParticles();
}

touch_start(integer num)
{
llWhisper(0,"...Generating List...";);
for (i=1;i<42;i+=2)
{
type = llGetListEntryType(sys,i);
if(type == TYPE_FLOAT)
{
tempString = float2String(llList2Float(sys,i));
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
else if (type == TYPE_VECTOR)
{
tempVector = llList2Vector(sys,i);
tempString = "<" + float2String(tempVector.x) + ","
+ float2String(tempVector.y) + ","
+ float2String(tempVector.z) + ">";
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
else if (type == TYPE_ROTATION)
{
tempRot = llList2Rot(sys,i);
tempString = "<" + float2String(tempRot.x) + ","
+ float2String(tempRot.y) + ","
+ float2String(tempRot.z) + ","
+ float2String(tempRot.s) + ">";
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
else if (type == TYPE_STRING || type == TYPE_KEY)
{
tempString = "\"" + llList2String(sys,i) + "\"";
sys = llDeleteSubList(sys,i,i);
sys = llListInsertList(sys,[tempString],i);
}
}
sys = llListSort(sys,2,TRUE);
if (target == "";) sys = llDeleteSubList(sys,38,39);
else if (target == llGetKey() )
sys = llListInsertList(llDeleteSubList(sys,39,39),["llGetKey()"],39);
else if (target == llGetOwner() )
sys = llListInsertList(llDeleteSubList(sys,39,39),["llGetOwner()"],39);
if (texture == "";) sys = llDeleteSubList(sys,24,25);
if (!interpSize) sys = llDeleteSubList(sys,12,13);
if (!interpColor) sys = llDeleteSubList(sys,6,7);

llWhisper(0,"[" + llList2CSV(llList2List(sys,0,21)) + ",";);
llWhisper(0,llList2CSV(llList2List(sys,22,-1)) + "]";);
}
}
BlueWillow Kipling
Registered User
Join date: 14 Sep 2005
Posts: 12
Correction
09-21-2005 11:45
Okay, actually I got the squished oval *not* to move along the axis perpendicular to its plane. But I don't know how.

The playing around was a success in that I understand better how *some* things work, but I've clearly still got a long way to go.

BlueWillow
Chandra Page
Build! Code. Sleep?
Join date: 7 Oct 2004
Posts: 360
09-21-2005 12:11
One thing you're running into when you attempt to add a second particle with a second script is the fact that particle effects are actually a property of the prim in which they are placed, not the script. A single prim may only display a single particle effect at once. The llParticleSystem call updates the particle "property" (for lack of a better word) of the prim itself. If you want to overlap two different particle effects, you'll need two prims, each containing its own script.

Alternatively, you can use PSYS_SRC_PATTERN_EXPLODE instead of PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY for the pattern variable. Set minSpeed and maxSpeed to a really tiny value (like 0.1, but it must be greater than 0 or the particles won't emit) to prevent the particles from wandering too far from the particle emitter, and the target = "self" setting will make sure that the particles tumble back to the center of the emitter. You can't precisely control the angle of the emitted particles this way, but they'll usually spin nicely as they fall back to the center. For something that looks more like a star, you can increase the number of particles released per burst. Set the count variable to something more than just 1; I'd recommend somewhere from 3 to 5.

Probably the most visually effective way to achieve a star effect like you're looking for is to make a custom texture for the particle. Yes, you can squish the default orb-shaped particle and make something reasonably convincing, but you'll probably be much happier with the results if you start with a texture that looks like a star to begin with, and then apply particle system parameters such that it falls back on itself, providing a little spin and tumble in the process. You can tell your particle script to use a custom texture by dropping the texture in the same prim as the particle script, then setting the texture variable in your script to the name of the texture. For example:

CODE
string texture = "My sparkly texture";
_____________________
Come visit the In Effect main store and café
Drawbridge (160, 81)
Particle effects, fashion, accessories, and coffee!
On the Web at SL Exchange and SL Boutique
Keknehv Psaltery
Hacker
Join date: 11 Apr 2005
Posts: 1,185
09-21-2005 19:05
For God's sake BlueWillow, use the PHP tags. 200+ lines of code looks somewhat ugly with no indentation...

CODE
 //Code blah code [ /PHP] (take out the extra space)

The vectors aren't a direction and a speed, they're 3 speeds in fixed directions. X is east/west Y is north/south, and Z is up/down.

If you want to get a gut level understanding of the particle systems, I would recommend to use my script (located here ), because it's a much lower level of particle control (it's really just an llParticleSystem call nicely formatted) and to check the wiki page for each value. Know how each different parameter effects the system, and play with the patterns last.
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
09-22-2005 01:53
From: Keknehv Psaltery
...script (located here ), because it's a much lower level of particle control
I agree. I have seen quite a few llParticleSystem wrappers that were all, IMO, far more difficult to use than the actual function itself - especially for less advanced scripters.
BlueWillow Kipling
Registered User
Join date: 14 Sep 2005
Posts: 12
Thanks
09-25-2005 11:00
From: Ben Bacon
I agree. I have seen quite a few llParticleSystem wrappers that were all, IMO, far more difficult to use than the actual function itself - especially for less advanced scripters.

(there's an extra few characters in Keknehv's url, use the one in my quote instead. K: I'll edit this out if you have a chance to fix it)


Thank you *very* much. This is much easier for me to understand.

Now, for a question that is going to seem trivial---the UUID of the texture for the particles: If I've got the texture I want, where do I put it and how do I figure out what the UUID is so that the script knows where to get it from?

Thanks,
Blue
Keknehv Psaltery
Hacker
Join date: 11 Apr 2005
Posts: 1,185
09-25-2005 15:22
Wow, someone actually liked something I did for a change. That's always nice.

The texture setting could also be the name of a texture in the inventory, but that's not as easy to port. To find the asset id (UUID) of a texture, or any other object, right click on it in your inventory and click "Copy asset id". Then you can paste that in the right spot.