PDA

View Full Version : does setFluidAttr need a scriptJob?


Pixlmonky
02-24-2009, 01:18 AM
I am setting the fluid velocity in x, y, and z. When I execute the script, it changes the velocities for that frame, but then goes back to evaluating normally. When I replay the sim, my velocity values do nothing until I execute the script again. I even tried to use the -ad flag, but still the same.

I would like to add to the velocities already being simulated, hopefully injecting my own values into the mix.


cheers
Pixlmonky

Aikiman
02-24-2009, 01:30 AM
Sounds like you need to run a loop or condition for example if(frame<100) then setFluidAttr. If you use the -ad flag it just adds to the existing velocity but still will only calculate once unless you throw the if statement in.

Pixlmonky
02-24-2009, 02:01 AM
I have it in a for loop, within a for loop, within a for loop.

So if I put it in a condition, then it will continue to evaluate? I will try.


Edit>>>>>
I put the setFluidAttr in a condition....
float $time = `currentTime -q`;
if ($time > 1){

still the same results.

Aikiman
02-24-2009, 02:10 AM
Its pretty hard to see what you are doing without the code to be honest.

Pixlmonky
02-24-2009, 02:14 AM
The code.....


float $resX = `getAttr fluidShape1.resolutionW`;
float $resY = `getAttr fluidShape1.resolutionH`;
float $resZ = `getAttr fluidShape1.resolutionD`;
float $fMult = `getAttr fluid1.fluidMult`;

int $row, $column, $depth;


for ($row = 0; $row < $resX; $row++){
for ($column = 0; $column < $resY; $column++){
for ($depth = 0; $depth < $resZ; $depth++){

float $time = `currentTime -q`;

//float $gTemp[] = `getFluidAttr -at "temperature" -xi $row -yi $depth -zi $column fluid1`;
float $gVelX[] = `getFluidAttr -at "velocity" -x -xi $row -yi $depth -zi $column fluid1`;
float $gVelY[] = `getFluidAttr -at "velocity" -y -xi $row -yi $depth -zi $column fluid1`;
float $gVelZ[] = `getFluidAttr -at "velocity" -z -xi $row -yi $depth -zi $column fluid1`;

float $velX = $gVelX[$depth];
float $velY = $gVelY[$depth];
float $velZ = $gVelZ[$depth];

float $velX = $velX * $fMult;
float $minValueX = $velX + ($velX/2);
float $maxValueX = $velX - ($velX/2);
float $nVelX = (noise( $velX )) * ($maxValueX-$minValueX) + $minValueX;

float $velY = $velY * $fMult;
float $minValueY = $velY + ($velY/2);
float $maxValueY = $velY - ($velY/2);
float $nVelY = (noise( $velY )) * ($maxValueY-$minValueY) + $minValueY;

float $velZ = $velZ * $fMult;
float $minValueZ = $velZ + ($velZ/2);
float $maxValueZ = $velZ - ($velZ/2);
float $nVelZ = (noise( $velZ )) * ($maxValueZ-$minValueZ) + $minValueZ;

if ($time > 1){

setFluidAttr -at "velocity" -ad -x -xi $row -yi $depth -zi $column -fv $nVelX fluid1;
setFluidAttr -at "velocity" -ad -y -xi $row -yi $depth -zi $column -fv $nVelY fluid1;
setFluidAttr -at "velocity" -ad -z -xi $row -yi $depth -zi $column -fv $nVelZ fluid1;
}
}
}
}

Aikiman
02-24-2009, 02:31 AM
Perhaps your expression node needs Always Evaluate set to 1. Are you on a Mac? Ive found whenever I alter some code -ae always goes back to zero and I have to copy and paste the code into a new expression node for it to work again.

Ive never had a need to use a script job to setFluidAttrs

Pixlmonky
02-24-2009, 02:42 AM
on a PC.

Just to clarify... I am trying to get the velocities in x,y, and z. multiply that value by a variable. Then add noise to it. Then add it back into the velocity.



cheers
Pixlmonky

Aikiman
02-24-2009, 03:02 AM
I tested your code and it does seem to be evaluating every frame the only problem is its only doing the bottom voxels -yi 0 and nothing else.

Pixlmonky
02-24-2009, 03:20 AM
Wierd that it works for you. I play it thru and it does nothing after that frame that I executed it. Also not sure why it is only happening on the bottom.

I restarted Maya and still, only works on that frame, until I play it. Then it has no effect. If you rewind, does it still evaluate?


cheers
pixlmonky

Aikiman
02-24-2009, 04:51 AM
I just noticed something in your code though, you have your $column and $depth in the wrong indices.
Also I think where the main problem is when I go to print $nVelX, $nVelZ, $nVelY I get zeros so I think it has to do with this block of code somehow.

So having a another look try correcting your code as follows...

float $velX = $gVelX[0];
float $velY = $gVelY[0];
float $velZ = $gVelZ[0];

This would explain why I was only getting values on the bottom row of the fluid because using an increment value meant that it was returning a bunch of zeros except on the first pass whereas there should be no incrementer in the $gVelX array just $gVelX[0].

Hope that works for you.

Pixlmonky
02-24-2009, 09:00 PM
I see where it is breaking in the Y. You are right, it's in that statement. not sure why it works for x and z. I think it needs to be made with the [$depth]. The variable needs to be set differently for each voxel. A [0] would mean it only samples the first voxel. I think.

Aikiman
02-24-2009, 09:35 PM
No..

float $gVelX[] = `getFluidAttr -at "velocity" -x -xi $row -yi $depth -zi $column fluid1`;

returns all the x values in the first array indice [0]

From the way you have set it up you are only asking maya to return the velocity in the first array indice because you have three separate arrays for each of the axis. Therefore when the loop runs through the second time it is still the first indice that is used as the last one is overwritten, so all you need is $gVelX[0];

If you use an incrementer and have $gVelX[1]; in there it returns zero values.

Pixlmonky
02-24-2009, 09:47 PM
Having a hard time thinking that one thru. This is the first time I have worked with arrays within arrays.


EDIT>>>
I think I get it now. You can use [0] because the nested array is marching across the voxels in x,y, and z. So [0] is the next voxel in the array each time it progresses. Is that a correct assumption?

I was only using the 3 axis because the setFluidAttr only seemed to work if I used the -x, -y, -z flags. Is that needed when getting the velocities? Can I just get the velocities at each voxel in one variable?

I am printing the the values and it is taking so long. Is there a way to print just the highest and lowest value?

Aikiman
02-24-2009, 10:22 PM
Yeah thats right, all the x values fall into the [0] index one after the other and again in the next pass through the loop. Therefore nothing is kept in [1] or [2] which is why it was only working on the first pass.

I am printing the the values and it is taking so long. Is there a way to print just the highest and lowest value?

Well you could just query the value like

if ( $gVelX[0] < 0.05 || $gVelX[0]>2.0)
print $gVelX[0];

Im not aware of any function that may do that for you.

Pixlmonky
02-24-2009, 10:28 PM
Cool, Thanks. I am in the process of rethinking this.

I think that trying to print the values that way will still take a long time since it still has to parse thru all the arrays. Gggrrrr.

Pixlmonky
02-24-2009, 11:46 PM
I rewrote it and seems to evaluate thru all the voxels. It still seems to only evaluate when I execute and not after. WTF?


cheers
pixlmonky

Aikiman
02-24-2009, 11:55 PM
Can you share the scene? Delete everything but the fluid and code if you like.

Pixlmonky
02-25-2009, 12:10 AM
This may sound stupid...
I have been executing this as a script. Should I put in in an expression in the fluid node?

>>Edit...
I just tried it as an expression and it works, but it is SLOW. I guess as expected.
>>end edit

what is the best way to attach the maya file. it won't let me attach it.

float $resX = `getAttr fluidShape1.resolutionW`;
float $resY = `getAttr fluidShape1.resolutionH`;
float $resZ = `getAttr fluidShape1.resolutionD`;

int $row, $column, $depth;

float $fMult = `getAttr fluid1.fluidMult`; //adjustable multiplier attribute on the fluid node
for ($row = 0; $row < $resX; $row++){
for ($column = 0; $column < $resY; $column++){
for ($depth = 0; $depth < $resZ; $depth++){

float $nVelX;
float $nVelY;
float $nVelZ;

float $time = `currentTime -q`;

//float $gTemp[] = `getFluidAttr -at "temperature" -xi $row -yi $depth -zi $column fluid1`;
float $gVelX[] = `getFluidAttr -at "velocity" -x -xi $row -yi $depth -zi $column fluid1`;
float $gVelY[] = `getFluidAttr -at "velocity" -y -xi $row -yi $depth -zi $column fluid1`;
float $gVelZ[] = `getFluidAttr -at "velocity" -z -xi $row -yi $depth -zi $column fluid1`;

float $velX = $gVelX[0] * $fMult;
float $minValueX = $velX - ($velX/2);
float $maxValueX = $velX + ($velX);
if ($velX != 0){
$nVelX = (noise( $velX )) * ($maxValueX-$minValueX) + $minValueX;
}
else{
$nVelX = 0;
}

float $velY = $gVelY[0] * $fMult;
float $minValueY = $velY - ($velY/2);
float $maxValueY = $velY + ($velY);
if ($velY != 0){
$nVelY = (noise( $velY )) * ($maxValueY-$minValueY) + $minValueY;
}
else{
$nVelY = 0;
}


float $velZ = $gVelZ[0] * $fMult;
float $minValueZ = $velZ - ($velZ/2);
float $maxValueZ = $velZ + ($velZ);
if ($velZ != 0){
$nVelZ = (noise( $velZ )) * ($maxValueZ-$minValueZ) + $minValueZ;
}
else{
$nVelZ = 0;
}

if ($time > 1){

setFluidAttr -at "velocity" -ad -x -xi $row -yi $depth -zi $column -fv $nVelX fluid1;
setFluidAttr -at "velocity" -ad -y -xi $row -yi $depth -zi $column -fv $nVelY fluid1;
setFluidAttr -at "velocity" -ad -z -xi $row -yi $depth -zi $column -fv $nVelZ fluid1;
}
}
}
}






cheers
pixlmonky

Aikiman
02-25-2009, 12:58 AM
Yes it needs to be in an expression node, a script will only work once unless it writes out an expression node containing code.

Depending on the size of your fluid, doing stuff like this can take ages so its better to start off with a low res container until you are happy with everything then go to high res and cache it. Once cached dont forget to comment out the code otherwise it will still play really slow.

Pixlmonky
02-25-2009, 01:54 AM
Maybe this isn't the best way to tackle this. I just wanted to get a fluid explosion to not be so regular. It always seems to com out as a rounded sphere-like puff. Even with lots of turbulance and different emitter shapes. I just wanted the velocities to be a little more random. I want to recreate those little peaks that pop out of explosions. I even tried to use a couple different fluids together (rotated differently), they rendered weird where they shared space.



cheers
pixlmonky

Aikiman
02-25-2009, 02:03 AM
Let me share with you a little technique I use that does a pretty good job at doing that. Ive always had the same issue as well and came up with this solution.

Emit particles with random speeds from an emitter that die say between 1 second and 1.5 with a max count set to about 5-7. Then get the world positions and velocities of these particles and the voxels they fill. So you want the particle emission to happen inside a fluid container. From there setFluidAttr density, velocity and temperature at those voxels.

This creates a real nice random explosion with bits of debris flying off. The trick is to keep the lifespan of the particle really short so it doesnt start looking too much like a mutated explosion but rather something that is growing randomly then burns itself out.

http://forums.cgsociety.org/showthread.php?f=86&t=250802&highlight=particle+voxels

Pixlmonky
02-25-2009, 02:53 AM
Excellent. I will try that. I played with it a little bit before but it came out looking really blocky. And he fluid only solved where the particles were. Dose the fluid sim only where the particles flow, or do you use the particles to start off a reaction?


cheers
pixlmonky


since this discussion seems to be just you and I, let me know if you want to continue this discussion on IM or email.

Aikiman
02-25-2009, 03:04 AM
yeah the particles start off the reaction and the fluid shader takes over the rest.

CGTalk Moderation
02-25-2009, 03:04 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.