View Full Version : Emit circular (not spherical = omni) from a particle
StefanAlbertz 11 November 2009, 05:24 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 rocketparticle (itīs velocity gives that direction) and construct the velocity of the explosion particles around the vector that looks into the camera (worldSpace position rocketparticle minus worldSpace position camera).
Is there a more direct way to do this?


stooch
11 November 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 November 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 rocketparticle (itīs velocity gives that direction) and construct the velocity of the explosion particles around the vector that looks into the camera (worldSpace position rocketparticle 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 November 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 zcomponent = 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 November 2009, 06:40 PM
Here's one way of doing it...
float $discRadius = rand(.1,1);
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 November 2009, 04:00 AM
How on earth did you code that stuff dude?! Nicely done.
ctp
11 November 2009, 01:31 PM
Thanks :) I'm just using the cross product of the vector pointing from the "rocket" (particle1) and a yaxis vector (assuming that your worlds up is in the yaxis 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 runtimebeforedyn expression with this here below.
float $discRadius = rand(.1,1);
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 November 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 November 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
(`rot (<<($discRadius),0,0>>) $rotationAxis $rotation`) + sphrand($discNoise*$discRadius)
But anyway... :)
StefanAlbertz
12 December 2009, 05:04 PM
wow, i was on vacation and now .. well THANK YOU ;)
CGTalk Moderation
12 December 2009, 05:04 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.