View Full Version : Particle Goal via Texture?

10 October 2009, 08:16 PM
Is there a way to create a goal from a plane with a black & white texture? Or something similar? Basically I have a specific pattern I want the particles to form, but I'm not sure how to get them to that goal. Any help is appreciated.


10 October 2009, 07:15 AM
Way I see it, there are two ways you can do this:

1) (easy but expensive way) - when the particle goals are set (e.g. in the creation expression), initiate a black color and do a while loop which exits when that color is white. At each iteration set a random uv for the goal, then check the color of that point using colorAtPoint, and if it's white, exit the while loop.

// Seed the random seed for the first born particle
// Note this may not work if you're using texture rate emission
if (!particleShape1.particleId)
seed (3212);

float $goalU = particleShape1.parentU;
float $goalV = particleShape1.parentV;

vector $color = `colorAtPoint -u $goalU -v $goalV file1`;

while ($color.x < 0.5 || $color.y < 0.5 || $color.z < 0.5)
$goalU = rand (0,1);
$goalV = rand (0,1);
$color = `colorAtPoint -u $goalU -v $goalV file1`;

particleShape1.goalU = $goalU;
particleShape1.goalV = $goalV;

(scene attached)

2) (harder but cheaper way) This is a bit more complicated, but it involves baking a texture with the uv-coordinates which you actualy want to use as goals. I've created a ramp to which I've added the attribute calc (so I can turn the calculations off since it's very slow - but it only has to be done once) and a samplerInfo node and created the following expression for the ramp:

(set to render with maya software otherwise it won't work)

// get the incoming UV coordinates
float $u = samplerInfo1.uCoord;
float $v = samplerInfo1.vCoord;

if (ramp1.calc) // add a boolean attribute "calc" to be able to turn this off
vector $color = `colorAtPoint -u $u -v $v file1`;
while ($color.x < 0.5 || $color.y < 0.5 || $color.z < 0.5)
$u = rand (0,1);
$v = rand (0,1);
$color = `colorAtPoint -u $u -v $v file1`;
// set the ramp's color - note if we were inside the white area to begin with,
// the ramp just inherits the uv-coordinates it got from the samplerInfo
ramp1.colorEntryList[0].colorR = $u;
ramp1.colorEntryList[0].colorG = $v;
ramp1.colorEntryList[0].colorB = 0;

// just to be able to access the expression easier from the maya UI:
ramp1.noise = 0;

To bake it, select the ramp and open the Render Texture Range options from the hyperShade's Edit menu. Set x/y resolution low and start/end frame to the current frame.
Now, just before you click the Render Texture Range button, set calc to On for the ramp. Wait for the first calculation to finish, then click the Render Texture Range button. When it's finished, set calc to Off.

Now you can use that texture as a color texture for the emitter so the particles inherit that color (of course if you want to use rgbPP in rendering this doesn't work, so you'll have to use colorAtPoint in this case, but without the while-loop so a lot cheaper), then setting your goal value in the creation expression becomes a piece of cake:

vector $rgb = particleShape1.rgbPP;

particleShape1.goalU = $rgb.x;
particleShape1.goalV = $rgb.y;

Fortunately, it doesn't seem that maya's emitter's inherit color functionality does any interpolation of the texture, it just reads it as nearest neighbor, otherwise this second method wouldn't have worked.

Good luck.

07 July 2010, 06:47 AM
Hi anders,

Regarding your (Harder but cheaper method).
I am totally clear about you setup.
I have a doubt you have used ramp to color the surface and baking it along u v coordinates.

Suppose if i want to use my custom texture instead of ramp what will be my work around.

thanks in advance

CGTalk Moderation
07 July 2010, 06:47 AM
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.