View Full Version : Emit circular (not spherical = omni) from a particle

 StefanAlbertz11-24-2009, 05:24 PMRecreating fireworks i came across this question: l launch particles from a emitter on the ground representing my rockets. They emit rocket exhaust, climb up and emit new particles at the end of their lives (the explosion). This last emission is currently set to omni, but this is a problem since i would like to have them fly away not along the surface of a sphere but as a circle (as those beautiful chinese fireworks often show). Mathematically, i would like to take the direction of the rocket-particle (itīs velocity gives that direction) and construct the velocity of the explosion particles around the vector that looks into the camera (worldSpace position rocket-particle minus worldSpace position camera). Is there a more direct way to do this?
stooch
11-25-2009, 06:53 PM
try using a different emitter shape, for example try the cylinder, and in the impulse settings make sure that away from center is 0 but away from axis is not.

Aikiman
11-25-2009, 08:36 PM
Recreating fireworks i came across this question:
l launch particles from a emitter on the ground representing my rockets. They emit rocket exhaust, climb up and emit new particles at the end of their lives (the explosion).
This last emission is currently set to omni, but this is a problem since i would like to have them fly away not along the surface of a sphere but as a circle (as those beautiful chinese fireworks often show).

Mathematically, i would like to take the direction of the rocket-particle (itīs velocity gives that direction) and construct the velocity of the explosion particles around the vector that looks into the camera (worldSpace position rocket-particle minus worldSpace position camera).

Is there a more direct way to do this?

Are you saying you would like more of a 2D circular explosion that expands outward and faces the camera rather than a 3D one that emits in all directions?

StefanAlbertz
11-26-2009, 12:41 PM
Yes, thats what i want to do. Since i shoot up a particle as emitter for that circular explosion, i cant use a specific surface like a cylinder to emit in that way.

What i currently do is:

-camera looking along -z axis
-creation expression:
store old velocity vector
store length of it
create new vector based on old vector but with z-component = 0
unit that new vector
multiply it by the length of the old vector

I would like to have that effect from any camera angle (of course with some "rotation" abilites for that circle for more natural look)

ctp
11-26-2009, 06:40 PM
Here's one way of doing it...

float \$discNoise = .1;
float \$numOfParticlesInDisc = floor(rand(16,33));
float \$twoPi = 6.283185; //radians equal to 360 degrees
vector \$axisNoise = sphrand(1);
float \$birthVelocity = rand(10,20);

if (particleShape1.age >= particleShape1.finalLifespanPP) {
vector \$particlePos = particleShape1.position;
vector \$cameraPos = `xform -q -ws -translation camera1`;
vector \$dirParticleToCam = \$cameraPos - \$particlePos;
vector \$cross = cross(<<0,-1,0>>, \$dirParticleToCam);
vector \$firstParticleOffset = unit(\$cross) * \$discRadius;
vector \$rotationAxis = unit(\$dirParticleToCam) + \$axisNoise;
string \$emitCmd = ("emit -object particle2 " + "\n");

for (\$i=0; \$i < \$numOfParticlesInDisc; \$i++) {
float \$rotation = \$twoPi / \$numOfParticlesInDisc * \$i;
vector \$nextParticleOffset = (`rot \$firstParticleOffset \$rotationAxis \$rotation`) + sphrand(\$discNoise*\$discRadius);
vector \$velocity = unit(\$nextParticleOffset) * (\$birthVelocity + \$birthVelocity*rand(.1));
float \$lifespanPP = rand(1,1.5);
\$emitCmd += "-pos " + (\$particlePos + \$nextParticleOffset) + " -at velocity -vv " + \$velocity + " -at lifespanPP -fv " + \$lifespanPP + "\n";
}
eval(\$emitCmd);
}

when particles in particleShape1 die, they emit into particleShape2, using the emit command. No particle events.
You need to set lifespan mode to "lifespanPP only" for particleShape2.

Hope it makes sense. There's an example scene here. (http://3dhotdog.com/fireworks_v001.zip)

Cheers, C

Aikiman
11-27-2009, 04:00 AM
How on earth did you code that stuff dude?! Nicely done.

ctp
11-27-2009, 01:31 PM
Thanks :) I'm just using the cross product of the vector pointing from the "rocket" (particle1) and a y-axis vector (assuming that your worlds up is in the y-axis direction). The cross product provides a vector to use for offsetting the newborn particles (particle2) around the axis looking down to the camera. The offsetting of the new particle points is done by using the rot command, which is fed with a point to rotate, an axis to rotate about, and a number of degrees (in radians) for the rotation.

However, in the above expression, the ring or disc of particles are created mainly to face camera1. I just realized that it's probably more natural or common that the explosion sends out a disc around the axis of the rocket.

The expression below will do just that. (Which is done without the cross product). If you grabbed the example scene from before, you can just replace the runtime-before-dyn expression with this here below.

float \$discNoise = .1;
float \$numOfParticlesInDisc = floor(rand(24,49));
float \$twoPi = 6.283185; //radians equal to 360 degrees
vector \$axisNoise = sphrand(.5);
float \$birthVelocity = rand(10,20);

if (particleShape1.age >= particleShape1.finalLifespanPP)
{
vector \$particlePos = particleShape1.position;
vector \$particleVel = particleShape1.velocity;
vector \$cameraPos = `xform -q -ws -translation camera1`;
vector \$dirParticleToCam = \$cameraPos - \$particlePos;
vector \$firstParticleOffset = unit(\$dirParticleToCam) * \$discRadius;
vector \$rotationAxis = unit(\$particleVel) + \$axisNoise;
string \$emitCmd = ("emit -object particle2 " + "\n");

for (\$i=0; \$i < \$numOfParticlesInDisc; \$i++)
{
float \$rotation = \$twoPi / \$numOfParticlesInDisc * \$i;
vector \$nextParticleOffset = (`rot \$firstParticleOffset \$rotationAxis \$rotation`) + sphrand(\$discNoise*\$discRadius);
vector \$discVelocity = unit(\$nextParticleOffset) * (\$birthVelocity + \$birthVelocity*rand(.1));
\$discVelocity += \$particleVel * .8; //inheriting some of the rockets velocity
float \$lifespanPP = rand(1,1.5);
\$emitCmd += "-pos " + (\$particlePos + \$nextParticleOffset) + " -at velocity -vv " + \$discVelocity + " -at lifespanPP -fv " + \$lifespanPP + "\n";
}
eval(\$emitCmd);
}

stooch
11-29-2009, 08:55 PM
instead of finding vector from particle to camera its better to find the vector between last position and current position. using a custom lasPosPP vector attribute. might make the code a little shorter :)

ctp
11-30-2009, 01:06 PM
Yeah, I submitted that last one too quickly... didn't clean up properly, leftovers from the first one. There's at least 3 lines you can remove, having to do with the camera, since it's not needed in that second version. And basically just use an arbitrary point for the rotation around the rocket axis. Something like