Here I will present some useful tips for Crowd Artists and VFX artists who use particles in their work. It will be mostly Houdini but some Maya in the older posts. Please feel free to comment or correct as appropriate.
Tuesday, 29 November 2011
Motion Vectors for hardware particles
I have not got very far before I came across some vector maths...
Here is the setup which works for a camera pointing exactly down the z-axis.
Here is the render loaded into Nuke. Notice the RGB values.
I now need to find a way to convert World Velocity to Screen Space Velocity.
In a MEL expression. Hmmm, time to ask the Forum
After some great advice from Zoharl, I grabbed some code which uses the camera's worldInverseMatrix to transform the velocity vector.
Here is the expression:
//multiplier
float $mult=0.5;
//get the particle's World Space velocity
vector $vel=particleShape1.worldVelocity;
float $xVel=$vel.x;
float $yVel=$vel.y;
float $zVel=$vel.z;
// create particle's velocity matrix which is in World Space
matrix $WSvel[1][4]=<<$xVel,$yVel,$zVel,1>>;
// get the camera's World Inverse Matrix
float $v[]=`getAttr camera1.worldInverseMatrix`;
matrix $camWIM[4][4]=<< $v[ 0], $v[ 1], $v[ 2], $v[ 3]; $v[ 4], $v[ 5], $v[ 6], $v[ 7]; $v[ 8], $v[ 9], $v[10], $v[11]; $v[12], $v[13], $v[14], $v[15] >>;
//multiply particle's velocity matrix by the camera's World Inverse Matrix to get the velocity in Screen Space
matrix $SSvel[1][4]=$WSvel * $camWIM;
vector $result = <<$SSvel[0][0],$SSvel[0][1],$SSvel[0][2]>>;
float $xResult = $mult * $result.x;
float $yResult = $mult * $result.y;
float $zResult = $mult * $result.z;
//rgbPP
particleShape1.rgbPP=<<$xResult,$yResult,0>>;
So far it seems to be working, but I will try to test it and see if it breaks down.
Thanks to Zoharl on the CGTalk forum and to xyz2.net and 185vfx who came up with the original matrix manipulation code.
Thursday, 10 November 2011
Emit particles upon the death of another particle
vector $pos = death_particleShape.position;
vector $vel = death_particleShape.velocity;
float $randVelMag=10;
float $randPosMag=1;
float $velMult=0.1;
float $emitNum = rand(1,3);
for ($i=0; $i<$emitNum; $i++) {
vector $randVel = <<$randVelMag*rand(-1,1),$randVelMag*rand(-1,1),$randVelMag*rand(-1,1)>>;
vector $randPos = <<$randPosMag*rand(-1,1),$randPosMag*rand(-1,1),$randPosMag*rand(-1,1)>>;
vector $newVel=<<($velMult*(($randVel.x)+($vel.x))),($velMult*(($randVel.y)+($vel.y))),($velMult*(($randVel.z)+($vel.z)))>>;
emit -o birth -position (($randPos.x)+($pos.x)) (($randPos.y)+($pos.y)) (($randPos.z)+($pos.z)) -at velocity -vv ($newVel.x) ($newVel.y) ($newVel.z);
};
};
basically it is an EMIT command with some randomness added to the position and velocity parameters.
$randVelMag is a multiplier for the randomness in the velocity of the birth_particle when it is emitted
$randPosMag is a multiplier for the emitted position of the birth_particle
I then applied some turbulence fields to the birth_particles to get them to wiggle a bit and tweaked the conserve on them and the trail_particles. Here is a rendered frame.