Jump to content

Particles Always facing Direction of Avatar?


duLuna Bosatsu
 Share

Recommended Posts

I would like a particle beam (already designed) attached to the av's chest to always face the direction of the chest- Is there a script already available for this? 

 

I tried making a separate object to make the particles "go to" that object, but whenever I detach it or rez it, the particles reset and default to returning to the original object :\

Link to comment
Share on other sites

duLuna, your original idea is correct, but is just missing one component.

Every time you rez a prim/object, it gets a new UUID (or key). So you need a mechanism to discover the new key of the target prim and relay that to the particle emitter script - which would update the particle system's parameters with the new target key every time you rez the object.

I forget, when you are wearing an object and drop it, does that count as rezzing a new copy (while simultaneously deleting the object from your inventory) ?

Link to comment
Share on other sites


Kwakkelde Kwak wrote:

Madelaine ment the particle itself always faces the screen. What you want is very possible. I think all you need is some extra communication between the two ends of the beam. Something with
on_rez
or
attach
to start the communication should work.

 

Yes, I did mean that the particles themselves always face the screen.

DuLuna, if your goal is to have a stream of particles emit from a space and always travel to the chest of the wearer, that can be done. I've sent you an example in-world (just wear it, then touch it to Start/Stop the particles). The script is below.

Particles usually travel outward from the emitting point or surface (as defined by the various emitting modes and angle specifications). You can make them return to the center of the emitting prim by setting the flag "TARGET_POS" true, and using llGetKey() to get the prim's UUID, which you'll then set as the TARGET. Enabling TARGET_POS will cause all particles to reach the target exactly at their end of life. This will interact with any velocity, acceleration and radius settings you choose.

The best way to think of this interaction is to simply imagine what your original particle system was doing, with the additional constraint that all those particles must end up at the center of target at the end of their life. So if you emit particles at a large radius with no initial velocity or acceleration, they're gonna scoot to the target faster than if you had a small radius. They've got a greater distance to travel and the same particle lifetime to get there. Unlike other emission modes, particle lifetime will affect particle speed, as regardless of how or where you launch the particles, they will reach the target at the end of their lives. If you want to slow down the flow, increase the particle lifetime (and adjust your velocities and accelerations if necessary).

I hope this helps!

ETA: Although any particle emitting prim you wear operates in your avatar's frame of reference (moves with you), particles are emitted into the world frame (their initial motion is relative to the world, not you). You'll see this clearly if you walk while wearing the example emitter I sent you in-world.

 

// Inward Particle Emission Demostring myState = "off";myParticles() {        string TEXTURE = "";    float AGE = 5;    float RATE = .1;    integer COUNT = 20;    vector ACCEL = < 0,0,0 >;    float  SPEED_MIN = 1;    float  SPEED_MAX = 1;        vector  START_SCALE = < .1, .1, 0 >;    vector  END_SCALE = < .01, .01, 0 >;    vector  START_COLOR = < 1, 1, 1 >;    vector  END_COLOR = < 1, 1, 1 >;    float   START_ALPHA = 1; // 1.00    float   END_ALPHA = 1;    integer INTERP_COLOR = TRUE;    integer INTERP_SCALE = TRUE;    integer EMISSIVE = TRUE;        integer PATTERN = PSYS_SRC_PATTERN_ANGLE_CONE;    float   RADIUS = 1;    float   ANGLE_BEGIN = PI/8;    float   ANGLE_END = 0.0;    vector  OMEGA = < 0.0, 0.0, 0.00 >;    float   LIFE = 0;    integer      FOLLOW_src=FALSE;    integer FOLLOW_VELOCITY = TRUE;    integer            WIND = FALSE;    integer          BOUNCE = FALSE;    integer   TARGET_LINEAR = FALSE;    integer      TARGET_POS = TRUE;    key              TARGET = llGetKey();                         list particle_parameters = [            PSYS_PART_FLAGS, (                 (        EMISSIVE * PSYS_PART_EMISSIVE_MASK ) |                 (          BOUNCE * PSYS_PART_BOUNCE_MASK ) |                 (    INTERP_COLOR * PSYS_PART_INTERP_COLOR_MASK ) |                 (    INTERP_SCALE * PSYS_PART_INTERP_SCALE_MASK ) |                 (            WIND * PSYS_PART_WIND_MASK ) |                 (      FOLLOW_SRC * PSYS_PART_FOLLOW_SRC_MASK ) |                 (   TARGET_LINEAR * PSYS_PART_TARGET_LINEAR_MASK ) |                 (      TARGET_POS * PSYS_PART_TARGET_POS_MASK ) |                 ( FOLLOW_VELOCITY * PSYS_PART_FOLLOW_VELOCITY_MASK ) |                 (      TARGET_POS * PSYS_PART_TARGET_POS_MASK ) ),            PSYS_PART_START_COLOR,     START_COLOR,            PSYS_PART_END_COLOR,       END_COLOR,            PSYS_PART_START_ALPHA,     START_ALPHA,            PSYS_PART_END_ALPHA,       END_ALPHA,            PSYS_PART_START_SCALE,     START_SCALE,            PSYS_PART_END_SCALE,       END_SCALE,             PSYS_SRC_PATTERN,          PATTERN,            PSYS_SRC_BURST_PART_COUNT, COUNT,            PSYS_SRC_BURST_RATE,       RATE,            PSYS_PART_MAX_AGE,         AGE,            PSYS_SRC_ACCEL,            ACCEL,            PSYS_SRC_BURST_RADIUS,     RADIUS,            PSYS_SRC_BURST_SPEED_MIN,  SPEED_MIN,            PSYS_SRC_BURST_SPEED_MAX,  SPEED_MAX,            PSYS_SRC_TARGET_KEY,       TARGET,            PSYS_SRC_ANGLE_BEGIN,      ANGLE_BEGIN,             PSYS_SRC_ANGLE_END,        ANGLE_END,            //PSYS_SRC_INNERANGLE,       INNERANGLE,             //PSYS_SRC_OUTERANGLE,       OUTERANGLE,            PSYS_SRC_OMEGA,            OMEGA,            PSYS_SRC_MAX_AGE,          LIFE,            PSYS_SRC_TEXTURE,          TEXTURE        ];            llParticleSystem( particle_parameters ); // Turns on the particle hose!            if ( (AGE/RATE)*COUNT > 4096) {        llOwnerSay( "Your emitter creates too many particles!"            + "Please decrease AGE and COUNT and/or increase RATE."            + "Give a hoot, don't pollute!");    }}default{        on_rez(integer param){        llResetScript();    }        state_entry() {        llParticleSystem([]);   // stop any running particle system        myState="off";    }        touch_start( integer num_detected ){        if(myState=="on"){            myState="off";            llParticleSystem([]);            llOwnerSay("Off");       }        else {            myState="on";            myParticles();            llOwnerSay("On");        }    }}

 

Link to comment
Share on other sites

20 particles every 1/10th second (burst rate, RATE = 0.1).  I've never tested the emission rate myself, either letting it go 'as fast as possible' (PSYS_SRC_BURST_RATE = 0.0) or doing very slow, individual, particles (eg; holo-projectors).

Is 200/s a lot, it's a good question?

PSYS_PART_FOLLOW_SRC_MASK makes particles follow the emitter.  Presumably that's an attachment so always 'follows' the avatar.  I haven't tried that in combination with the PSYS_PART_TARGET_* flags either but I would think there would be a conflict.

Link to comment
Share on other sites

Hmmm, no idea about the follow, that's why I asked:) ... But I really ment 20 at a time, not the amount per second. Min and Max speed are the same, the trajectory is the same, doesn't that mean it wouldn't matter if you create 1 or 50 in theory as far as looks go? If you set the amount to 1 and the rate to .01 you still only use half the particles...500 shown at all time sounds reasonable for one object, well depending on the lentgh of the beam.

Btw, I would really go with two prims, one emitter, one target, that way the particles don't cross, I think you can save on the number of them that way. That does require an extra script as far as i can think of though...so it's a tradeoff.

Link to comment
Share on other sites

The emission rate I used in the example was pulled from thin air, to give some sense for what the thing does. The rule of thumb I follow is to keep the number of live particles from an emitter as small as possible without compromizing the look. Total particle count is the product of the burst rate, burst count and particle lifetime. For my particular example, emitting 20 particles 10 times a second with a particle lifetime of 5 seconds yields a total particle count of 1000 for effect.

I do think PSYS_PART_TARGET and PSYS_PART_FOLLOW_SRC_MASK would conflict. It may well be that my method of setting and following the target is the same as following the source, which is also the target.

 

 

Link to comment
Share on other sites


Kwakkelde Kwak wrote:

Hmmm, no idea about the follow, that's why I asked:) ... But I really ment 20 at a time, not the amount per second. Min and Max speed are the same, the trajectory is the same, doesn't that mean it wouldn't matter if you create 1 or 50 in theory as far as looks go? If you set the amount to 1 and the rate to .01 you still only use half the particles...500 shown at all time sounds reasonable for one object, well depending on the lentgh of the beam.

Btw, I would really go with two prims, one emitter, one target, that way the particles don't cross, I think you can save on the number of them that way. That does require an extra script as far as i can think of though...so it's a tradeoff.

 

I wouldn't think you'd generally want a firing rate that's faster than a decent frame rate, as that bogs down the viewer without creating anything additional for you to see. A 0.01s emission rate would just emit multiple sets of particles into the same rendered frame. I don't think I've ever used a rate faster than 0.1s.

Maybe you'd want that to get a good looking trail of particles emitted from an object moving at high velocity, so the emission points of particles emitted within the same frame were different. That's the only reason I can think of to have an emission rate like 0.01s.

As far as emitting a burst of particles with same min and max velocity, remember that the particles are emitted randomly about the defined area of the emission. If that's effectively a point, then burst count should be one. If it's an arc or spherical section, the particles in the burst will be emitted randomly along the curve/surface and so burst count does indeed make a difference in the look.

Link to comment
Share on other sites

Thanks so much Madelaine! Sorry I misunderstood your first post, and that I wasnt more specific/clearer in my inquiry. Fenix is right though, I belive I would need something to reread the UUID when the object is placed on the ground (the thing Im making is for a friend who may want to edit sizes etc). Your script is nearly what I was looking for, only in reverse-- Here's a visual of what I was trying to describe:

particle direction.jpg

starts at the chest and ends at the prim further away- creating a beam. This is only part of the build, so they would both be child prims and part of the same linkset. Lower left is just a multi-directional turn around with it still facing the direction of the chest. 

Link to comment
Share on other sites


Madelaine McMasters wrote:

I wouldn't think you'd generally want a firing rate that's faster than a decent frame rate, as that bogs down the viewer without creating anything additional for you to see. A 0.01s emission rate would just emit multiple sets of particles into the same rendered frame. I don't think I've ever used a rate faster than 0.1s.

Maybe you'd want that to get a good looking trail of particles emitted from an object moving at high velocity, so the emission points of particles emitted within the same frame were different. That's the only reason I can think of to have an emission rate like 0.01s.

Yes I ment the 0.01 as an insane example where you'd still have less particles on screen, 500 rather than 1000. It was not an example on how to make a good beam, I understand I wasn't very clear.


Madelaine McMasters wrote:

If it's an arc or spherical section, the particles in the burst will be emitted randomly along the curve/surface and so burst count does indeed make a difference in the look.


I figured with a solid beam one would go for a point emitter. Ofcourse you can use a wider spread, but you could also go with a bigger particle.

 

 

 

Link to comment
Share on other sites

If this is all a single attachment you simply need to get the key of the prim acting as the target.  The easiest way to do that is to name that prim (eg; BeamTarget) and then add this to your state_entry()

 

		integer Counter;		for(Counter = llGetNumberOfPrims(); Counter > 0; Counter--){			if(llGetLinkName(Counter) == "BeamTarget"){				TARGET = llGetLinkKey(Counter);				Counter = 0;			}		}

 

@ Madelaine - sorry, I was just pondering how little I know about the effects that can be made with particles, not commenting on your code.

Link to comment
Share on other sites

// Target Particle Emission Demokey TARGET;string myState = "off";myParticles() {        string TEXTURE = "";    float AGE = 15;    float RATE = .1;    integer COUNT = 1;    vector ACCEL = < 0,0,0 >;    float  SPEED_MIN = 4;    float  SPEED_MAX = 4;        vector  START_SCALE = < .1, .1, 0 >;    vector  END_SCALE = < .1, .1, 0 >;    vector  START_COLOR = < 1, 0, 0 >;    vector  END_COLOR = < 0, 1, 0 >;    float   START_ALPHA = 1; // 1.00    float   END_ALPHA = 1;    integer INTERP_COLOR = TRUE;    integer INTERP_SCALE = TRUE;    integer EMISSIVE = TRUE;        integer PATTERN = PSYS_SRC_PATTERN_ANGLE_CONE;    float   RADIUS = 1;    float   ANGLE_BEGIN = PI/8;    float   ANGLE_END = 0.0;    vector  OMEGA = < 0.0, 0.0, 0.00 >;    float   LIFE = 0;    integer      FOLLOW_src=FALSE;    integer FOLLOW_VELOCITY = TRUE;    integer            WIND = FALSE;    integer          BOUNCE = FALSE;    integer   TARGET_LINEAR = FALSE;    integer      TARGET_POS = TRUE;    //key              TARGET = llGetKey();                         list particle_parameters = [            PSYS_PART_FLAGS, (                 PSYS_PART_EMISSIVE_MASK |                 //PSYS_PART_BOUNCE_MASK |                 PSYS_PART_INTERP_COLOR_MASK |                 PSYS_PART_INTERP_SCALE_MASK |                 //PSYS_PART_WIND_MASK |                 PSYS_PART_FOLLOW_SRC_MASK |                 PSYS_PART_TARGET_LINEAR_MASK |                 PSYS_PART_TARGET_POS_MASK |                 //PSYS_PART_FOLLOW_VELOCITY_MASK |                 PSYS_PART_TARGET_POS_MASK ),            PSYS_PART_START_COLOR,     START_COLOR,            PSYS_PART_END_COLOR,       END_COLOR,            PSYS_PART_START_ALPHA,     START_ALPHA,            PSYS_PART_END_ALPHA,       END_ALPHA,            PSYS_PART_START_SCALE,     START_SCALE,            PSYS_PART_END_SCALE,       END_SCALE,             PSYS_SRC_PATTERN,          PATTERN,            PSYS_SRC_BURST_PART_COUNT, COUNT,            PSYS_SRC_BURST_RATE,       RATE,            PSYS_PART_MAX_AGE,         AGE,            PSYS_SRC_ACCEL,            ACCEL,            PSYS_SRC_BURST_RADIUS,     RADIUS,            PSYS_SRC_BURST_SPEED_MIN,  SPEED_MIN,            PSYS_SRC_BURST_SPEED_MAX,  SPEED_MAX,            PSYS_SRC_TARGET_KEY,       TARGET,            PSYS_SRC_ANGLE_BEGIN,      ANGLE_BEGIN,             PSYS_SRC_ANGLE_END,        ANGLE_END,            //PSYS_SRC_INNERANGLE,       INNERANGLE,             //PSYS_SRC_OUTERANGLE,       OUTERANGLE,            PSYS_SRC_OMEGA,            OMEGA,            PSYS_SRC_MAX_AGE,          LIFE,            PSYS_SRC_TEXTURE,          TEXTURE        ];            llParticleSystem( particle_parameters ); // Turns on the particle hose!            if ( (AGE/RATE)*COUNT > 4096) {        llOwnerSay( "Your emitter creates too many particles!"            + "Please decrease AGE and COUNT and/or increase RATE."            + "Give a hoot, don't pollute!");    }}default{        on_rez(integer param){        llResetScript();    }        state_entry() {        //llSleep(2);        myState="on";        integer Counter;        for(Counter = llGetNumberOfPrims(); Counter > 0; Counter--){            if(llGetLinkName(Counter) == "BeamTarget"){                TARGET = llGetLinkKey(Counter);                Counter = 0;            }        myParticles();        }    }        touch_start( integer num_detected ){        if(myState=="on"){            myState="off";            llParticleSystem([]);            llOwnerSay("Off");       }        else {            myState="on";            myParticles();            llOwnerSay("On");        }    }}

 Ok, I hope you're not offended by me making the script, I'm sure you're very capable of doing it yourself with all the info given, but this seems to work fine. Name the linked target prim "BeamTarget", put this script in the main prim and you're good to go. I didn't optimize all the settings, so it can be improved I think, but it looks pretty solid at 150 particles.

Link to comment
Share on other sites


PeterCanessa Oh wrote:

If this is all a single attachment you simply need to get the key of the prim acting as the target.  The easiest way to do that is to name that prim (eg; BeamTarget) and then add this to your state_entry()

 
		integer Counter;		for(Counter = llGetNumberOfPrims(); Counter > 0; Counter--){			if(llGetLinkName(Counter) == "BeamTarget"){				TARGET = llGetLinkKey(Counter);				Counter = 0;			}		}

 

@ Madelaine - sorry, I was just pondering how little I know about the effects that can be made with particles, not commenting on your code.

No worries, Peter. llParticleSystem is perhaps the coolest call in LSL. My favorite use of it is at the Africa sim, where li'l termites leave the mound to forage, then return. That emitter makes very clever use of bounce to give the termites the sort of wiggly motion you'd expect from walking over the ground. It is a delightful use of a powerful tool.

Link to comment
Share on other sites


Madelaine McMasters wrote:

...llParticleSystem is perhaps the coolest call in LSL...


You're right there, the variety of effects that are possible is amazing.  We had someone on here quite a while ago making a boomerang and asking how he could calculate/update its trajectory.  I suggested he do it with a particle instead in a way similar to this: position an invisible, phantom 'target' prim out, fire a single 'boomerang' particle sideways and let the particle system do all the work.  Target prim does similar, with delay, for the return flight back to the source.  I never saw it in-world but he said it looked cool

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...