Download - Utility Nodes in an Animation Pipeline
![Page 1: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/1.jpg)
Utility Nodes in an Animation Pipeline
Joe HarkinsCreature Technical DirectorTippett Studio
![Page 2: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/2.jpg)
WHAT IS A
UTILITY NODE? Definition: node
A construct that holds specific information, along with the actions associated with that information.
![Page 3: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/3.jpg)
WHAT IS A
UTILITY NODE?
Definition: utility node
A node that allows the creation of specific shading effects, most commonly used in shading networks. They are sometimes referred to as “math nodes”.
![Page 4: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/4.jpg)
WHAT IS A
UTILITY NODE?
Definition: attributes
a slot in a node that can hold a value or a connection to another node. Attributes control how a node works.
NODE
Attribute Attribute
![Page 5: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/5.jpg)
WHAT IS A
UTILITY NODE?
Definition: Input
two types of numerical inputs: static, dynamic.
dynamic input updates in real-time as the upstream connection changes.
static input does not change and is not connected to any other nodes
![Page 6: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/6.jpg)
WHAT IS A
UTILITY NODE?
Definition: Operator
operation: mathematical function
Usually determined by the type of node you have created. The process of combining inputs and performing a mathematical function.
![Page 7: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/7.jpg)
WHAT IS A
UTILITY NODE?
Definition: Output
output: dynamic result of the operation
An output attribute's job is to hold the result of the operation from the utility node. The real-time capability means that the output attribute is always accurate.
![Page 8: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/8.jpg)
WHAT IS A
UTILITY NODE?
Definition: Compute
compute: hidden function
Each node in Maya must take the attributes associated with it and compute them to give you an output. The output is the dynamic result of the operation, but the operation is the result of a computation that must be made within Maya.
output operator
input
compute
input
operator
output
![Page 9: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/9.jpg)
Advantages &
Disadvantages
disadvantage: no string inputs
No MEL commands
No text data
No variable storage
advantage: reliable evaluation
Updates with the dependency graph in real-time.Evaluation is reliable to upstream connections.
![Page 10: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/10.jpg)
Advantages &
Disadvantages
advantage: evaluation speed
using an expression with commands like "getAttr" and "setAttr" is going to be slower than using a utility node with direct connections to perform the same operation.
Expressions take longer to evaluate because they contain code. That code must then by parsed and evaluated by the processor. A node is a simple mathematical operation that has a specific function and requires no preprocessing.
![Page 11: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/11.jpg)
Advantages &
Disadvantages
disadvantage: MEL dependency
most utility nodes must be created manually using MEL.
Some nodes can be created within the Hypershade window.
![Page 12: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/12.jpg)
Advantages &
Disadvantages
advantage: flexibility
Utility nodes can be quickly edited with MEL.
advantage: technical control
Utility nodes can essentially be locked down and require a certain amount of effort to change.
![Page 13: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/13.jpg)
Advantages &
Disadvantages
disadvantage: archaic naming
What if you don't know what kind of node you need? Why is it called “addDoubleLinear”?
Why are there so many different nodes?
When in doubt - press F1
![Page 14: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/14.jpg)
Advantages &
Disadvantages
advantage: functionality
advantage: not name dependant
Unaffected by referencing, namespaces, script errors, or variables changes.
advantage: keyable dynamic attributes
Any input from a utility node can accept keyframe animation.
![Page 15: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/15.jpg)
Utility Nodes
and MEL
Utility Node Creation
MEL Commands you need to know…
createNode
the "createNode" command will allow you to create any type of node in Maya, for example, to create an "addDoubleLinear" type node, you would type the following into the script editor:
createNode "addDoubleLinear";
It would be better to name the node something besides the default name Maya gives it, add the -n flag as follows:
createNode "addDoubleLinear" -n "add1";
connectAttr
This command would connect objectA's translation in the X axis to the first input of the "add1" utility node that was created using the createNode command above:
connectAttr "objectA.translateX" "add1.input1";
setAttr
If the attribute is static you only need to set it initially at time of creation. Do this with the setAttr command on the utility node as follows:
setAttr "add1.input2" 5;
![Page 16: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/16.jpg)
Utility Nodes
and MEL
MEL Flow Control
for loops
MEL offers a very convenient way to parse through the selection list by using for loops to break the list of objects (ie: a string array) down to per-item manipulation.
$listOfThingsSelected=`ls -sl`;// Note that if listOfThingsSelected hasn't been declared yet,// it will be dynamically typed based on the result of the "ls" command.for ($i=0; $i < size($listOfThingsSelected); ++$i)
{ print $listOfThingsSelected[$i]; }
Alternatively, this does the exact same thing:
string $listOfThingsSelected[] =`ls -sl`;for ($thing in $listOfThingsSelected)
{ print $thing; }
![Page 17: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/17.jpg)
Utility Nodes
and MEL
MEL Flow Control
What is an array?
A list that can hold more than one value. The array assigns each value its own place in line which will allow you to call individual items from the array with ease.
string $listOfThingsSelected[] =`ls -sl`;for ($thing in $listOfThingsSelected)
{ createNode addDoubleLinear -n ($thing + "addMe"); }
![Page 18: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/18.jpg)
Utility Nodes
and MEL
MEL Flow Control
To connect the attributes for each item in the array to the node and vice versa let’s take the loop one step further:
string $listOfThingsSelected[] =`ls -sl`;for ($thing in $listOfThingsSelected)
{ createNode addDoubleLinear -n ($thing + "addMe");
connectAttr ($thing + ".translateX") ($thing + "addMe.input1");connectAttr ($thing + ".translateY") ($thing + "addMe.input2");connectAttr ($thing + "addMe.output") ($thing + ".translateZ"); }
select $listOfThingsSelected;
A procedure is a collection of MEL commands that can be accessed by executing the name of that procedure (and any associated arguments) .
proc createAddNode (){string $listOfThingsSelected[] =`ls -sl`;for ($thing in $listOfThingsSelected)
{ createNode addDoubleLinear -n ($thing + "addMe");
connectAttr ($thing + ".translateX") ($thing + "addMe.input1");connectAttr ($thing + ".translateY") ($thing + "addMe.input2");connectAttr ($thing + "addMe.output") ($thing + ".translateZ"); }
select $listOfThingsSelected;}
![Page 19: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/19.jpg)
Utility Nodes
and MEL
MEL Flow Control
If/else statements
Conditional statements allow you to choose which items in the array will be affected by the procedure.
proc createAddNode () {string $listOfThingsSelected[] =`ls -sl`;for ($thing in $listOfThingsSelected)
{if(`nodeType $thing` == "joint")
{ createNode addDoubleLinear -n ($thing + "addMe");
connectAttr ($thing + ".translateX") ($thing + "addMe.input1");connectAttr ($thing + ".translateY") ($thing + "addMe.input2");
connectAttr ($thing + "addMe.output") ($thing + ".translateZ"); }else print ($thing + " is not a joint, skipping! \n"); }
select $listOfThingsSelected; }
![Page 20: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/20.jpg)
Utility Nodes
and MEL
GUI Implementation
Combining commands
There are only three MEL commands needed to control the nodes during creation. Worry about the methodology used to create the nodes themselves.Goal is to have a script with procedures that are robust, easy to understand, and offer flexibility during use.
Interactive window
Avoid name specific scripting.Use input data from fields to define variables.Name all of your fields appropriately for querying data within the procedure.
![Page 21: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/21.jpg)
Utility Nodes
and MEL
GUI Implementation
Extracting data from the GUI
global proc createAddNode () {string $listOfThingsSelected[] =`ls -sl`;
string $input1 = `textField -q -tx adl_input1`;string $input2 = `textField -q -tx adl_input2`;string $output = `textField -q -tx adl_output`;
for ($thing in $listOfThingsSelected) {if(`nodeType $thing` == "joint")
{ createNode addDoubleLinear -n ($thing + "addMe");
connectAttr ($thing + "." + $input1) ($thing + "addMe.input1");connectAttr ($thing + "." + $input2) ($thing + "addMe.input2");
connectAttr ($thing + "addMe.output") ($thing + "." + $output); } else print ($thing + " is not a joint, skipping! \n"); }
select $listOfThingsSelected; }
![Page 22: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/22.jpg)
Utility Nodes
and MEL
Utility Creator MEL Script
GUI to help with the creation of utility nodes.Uses for loops and if/else statements.no MEL needed - create connections visually
Utility Nodes
addDoubleLinear: Adds the value from both of its inputs:
output = input(0) + input(1)
blendTwoAttr:
Blends the values of the input(0) and input(1)attributes of the node using a blending attribute:
output = (1 - attributesBlender) * input(0) + attributesBlender * input(1) multDoubleLinear: Multiplies the values from both of its inputs: output = input(0) * input(1)
reverse: used to reverse node attributes.
output = 1 – input
![Page 23: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/23.jpg)
Defining Areas
of Use
Rigging Solutions
Expression Replacement
An example of an expression that could be replaced with a utility node:
objectA.translateX = objectB.translateX * .75;
MEL code to create a multDoubleLinear node doing the equivelent would be:
string $mdl = `createNode multDoubleLinear`;connectAttr "objectB.translateX" ($mdl + ".input1");setAttr ($mdl + ".input2") .75;
This is another example, only slightly more complex; first the expression:
float $tx = `getAttr objectB.translateX`;float $ty = `getAttr objectB.translateY`;objectA.translateX = ($tx + $ty)* .75;
The MEL code for utility node conversion would be:
string $adl = `createNode addDoubleLinear`;string $mdl = `createNode multDoubleLinear`;connectAttr "objectB.translateX" ($adl + ".input1");connectAttr "objectB.translateY" ($adl + ".input2");connectAttr ($adl + ".output") ($mdl + ".input1") ;setAttr ($mdl + ".input2") .75;connectAttr ($mdl + ".output") "objectA.translateX";
![Page 24: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/24.jpg)
Defining Areas
of Use
Rigging Solutions
Joint Dampening – multDoubleLinear node
Joint’s rotation is multiplied by a driving joint for a final output.Output is then input to the hierarchy above the driven joint for indirect manipulation.Can be gradually dialed on, or turned off to have no effect.
![Page 25: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/25.jpg)
Defining Areas
of Use
Rigging Solutions
Joint Averaging
query the distance between two locators, then divide the distance by the number of joints and input into each joint’s translation using a multiplyDivide node.
joint.translate = locator.translate / number of joints
linearJointCreator MEL Script
1. input how many joints you want to create
2. multiplyDivide node gets translation inputs from the locator, then it divides that by the number of joints in the chain, and finally feeds the output to each joint's translation.
3. operator for the multiplyDivide node is set to "2", or divide, which will do the following operation:
multiplyDivide.outputX = multiplyDivide.input1x / multiplyDivide.input2x
![Page 26: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/26.jpg)
Defining Areas
of Use
Rigging Solutions
Custom Driven Attributes
Useful for driving blendShapes or changing the range of an existing attribute for greater control.
Output = Min + (((Value-OldMin)/(OldMax-OldMin)) * (Max-Min))
customAttributeDriver MEL Script
1. Uses a setRange node
2. Input driving node name, custom attribute that will Drive selected attribute will live on this node.
3. Min and max range must be set. Query the range of the attribute selected if it has a hard range or set it manually.
4. Set a new range that you would like the attribute to have by inputting the values into to fhe fields.
![Page 27: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/27.jpg)
Defining Areas
of Use
Rigging Solutions
FK/IK Switching
Requires 3 separate chains: driven, FK, IK
Connecting the driven skeleton to the driving FK and IK skeletons usinga blendTwoAttr node will allow animation blending between the two chains.
Use a custom attribute, connected to the attributeBlender of the node, as a driver.
blendTwoAttr
Blends the values of the input(0) and input(1)attributes of the node using a blending attribute:
output = (1 - attributesBlender) * input(0) + attributesBlender * input(1)
![Page 28: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/28.jpg)
Defining Areas
of Use
Rigging Solutions
FK/IK Switching
string $arms[] = `ls -sl`;string $fk, $ik, $driven, $arm, $blendAttr;$blendAttr = "blendObject.blendAttribute";
for ($arm in $arms){if (`gmatch $arm "*FK*"`) $fk = $arm;if (`gmatch $arm "*IK*"`) $ik = $arm;if (`gmatch $arm "*Driven*"`) $driven = $arm;}print ("this is the FK arm: " + $fk + "\n");print ("this is the IK arm: " + $ik + "\n");print ("this is the DRIVEN arm: " + $driven + "\n");
string $rot[] = {".rx",".ry",".rz"};string $r;
for ($r in $rot){string $bta = `createNode blendTwoAttr`;connectAttr ($fk + $r) ($bta + ".i[0]");connectAttr ($ik + $r) ($bta + ".i[1]");connectAttr $blendAttr ($bta + ".ab");connectAttr ($bta + ".o") ($driven + $r);}
![Page 29: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/29.jpg)
Defining Areas
of Use
Animation Solutions
Animation Blending
Able to be added nondestructively.
blendColors node is a good choice for this simple operation.
can take up to six inputs, two for each channel, R, G and B respectively. It also has one input called “blender”, which can be connected to a user added attribute to control the blending.
Here’s the code you would need to create the connections for channels that exist on selected objects:
string $all[] = `ls -sl`; string $each; string $blender = "blendObject.blendAttribute"; for ($each in $all) {string $blendColors = `createNode blendColors`; connectAttr $blender ($blendColors + ".blender"); connectAttr ($each + ".rx") ($blendColors + ".c1r"); connectAttr ($each + ".ry") ($blendColors + ".c2r"); connectAttr ($blendColors + ".opr") ($each + ".rz"); }
Here is the formula used for color blending:
output[i] = Color1[i] * Blender[i] + Color2[i] * (1.0 - Blender[i])
![Page 30: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/30.jpg)
Defining Areas
of Use
Animation Solutions
Noise Animation
Able to be added nondestructively.unlike blending - is mulitplied in an additive fashion.Uses a hierarchy based system to avoid locking off channels.
multDoubleLinear gives us ( A * B = C )A = noiseCurve (driving animation curve)B = noiseMult (to control input of noiseCurve)
C = output to an identical channel one node above in the hierarchy.
string $all[] = `ls -sl`;for ($each in $all){string $noiseNodes[] = `listRelatives -p -pa $each`;string $noiseNode = $noiseNodes[0];string $mdl = `createNode multDoubleLinear`;string $inChan[] = `channelBox -q -sma mainChannelBox`;for ($channel in $inChan){catch (`addAttr -ln ($channel + "_noiseCurve") -k 1 $each`);catch (`addAttr -ln ($channel + "_noiseMult") -k 1 $each`);connectAttr ($each+ "." + $channel + "_noiseCurve") ($mdl + ".i1");connectAttr ($each+ "." + $channel + "_noiseMult") ($mdl + ".i2");setAttr ($each+ "." + $channel + "_noiseMult") 1;connectAttr ($mdl + ".output") ($noiseNode + "." + $channel);}}
![Page 31: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/31.jpg)
Defining Areas
of Use
Animation Solutions
Noise Animation - noiseMaker MEL Script
node
noise
parent
![Page 32: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/32.jpg)
Defining Areas
of Use
Animation Solutions
Noise Animation - noiseMaker MEL Script
Randomly generated noise animation
for($frame=$start;$frame<=$end;$frame+=$step){currentTime $frame; $rand = `rand $min $max`;setAttr ($obj + "." + $channel + "_noiseCurve") $rand;$noise = `getAttr ($obj + "." + $channel + "_noiseCurve")`;setKeyframe -v $noise -at ($channel + "_noiseCurve") $obj; }
checks to see if you want the generated curve to cycle infintely and if you want it to be locked so you can't accidently set new keyframes on it:
if ($cycle == 1) setInfinity -poi cycle -at ($channel + "_noiseCurve") $obj;if ($lock == 1)setAttr ($obj + "." + $channel + "_noiseCurve") -lock 1;
![Page 33: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/33.jpg)
Complex
Situations
Cyclic Animation
Animation Cycles - noiseMaker MEL Script
if ($copy == 1){if (!`isConnected ($bta + ".output")($obj + "." + $channel) `)
{copyKey -attribute $channel -option curve $obj; CBdeleteConnection ($obj + "." + $channel);pasteKey -attribute ($channel + "_noiseCurve") $obj;}
}
You could combine the result with other cycles by using the blendColors or blendTwoAttr node, allowing you to blend between cycles quickly. The advantage, again, is the nondestructive additive nature of the multiplying and blending. Since we are not actively locking any attributes you can continue to animate normally.
If you are connecting two rigs together via constraints then the noise added to a loRes rig would transfer to the highRes rig without the need to add extra nodes to the highRes rig.
![Page 34: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/34.jpg)
Complex
Situations
Cyclic Animation
Offseting the Cycle - noiseMaker MEL Script
add time + user input to animation curve
addDoubleLinear.output = offsetAttr + time1.outTimeaddDoubleLinear.output is connected to driverAttrdriverAttr <-> animCurve.inputmultDoubleLinear.output = animCurve * noiseMultipliermultDoubleLinear.output <--> final result
Connection must be forced in Maya
The –f flag tells Maya to break any connection to the defined attribute and then force it to connect to the one we want:
connectAttr -f objectA.driver objectA _animCurve.input;
![Page 35: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/35.jpg)
Complex
Situations
Advanced MEL Discussion
Custom attribute noiseNon-hierarchy based noise animation
noiseMaker will check any user defined attributes on the loaded objects to find out if the loaded attribute is custom and needs a special setup. If the custom attribute query returns true then the script will copy your animation curve, if any exists, onto an attribute named "custom attribute name + old" which can be used to blend between the old animation and the noise curve.
Here's how it breaks down:
customAttrA_blendDriver = customAttrA_noiseCurve * customAttrA_noiseMultcustomAttrA_oldCurve is a copy of any existing animation on customAttrAcustomAttrA_oldCurve and blendDriver are then blended together with thecustomAttrA_blendOld attribute and finally output back to customAttrA
Here’s the code to show what’s going on in the script:
$mdl1 = `createNode multDoubleLinear`;$bta = `createNode blendTwoAttr`;addAttr -ln ($attr + "_oldCurve") -k 1 $obj;addAttr -ln ($attr + "_blendOld") -k 1 $obj;addAttr -ln ($attr + "_blendDriver") -k 1 $obj;catch (`copyKey -attribute $attr -option curve $obj`);catch (`CBdeleteConnection ($obj + "." + $attr)`);catch (`pasteKey -attribute ($attr + "_oldCurve") $obj`);connectAttr ($mdl1 + ".output") ($obj + "." + $attr + "_blendDriver");connectAttr ($obj + "." + $attr + "_blendDriver") ($bta + ".input[0]");connectAttr ($obj + "." + $attr + "_oldCurve") ($bta + ".input[1]");connectAttr ($obj + "." + $attr + "_blendOld") ($bta + ".ab");connectAttr ($bta + ".output") ($obj + "." + $attr);
![Page 36: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/36.jpg)
Complex
Situations
Advanced MEL Discussion
Replacing Math CyclesAdvanced expression replacement
1. Evaluate what the expression is doing
breathroot1.scaleX=1+cos(time/breathcontrol.translateY)/10;breathroot2.scaleX=1+cos(time/breathcontrol.translateY)/10;
In this case the expression is using the COS function to create rythmatic breathing by using inputs from translation of a locator.
2. Determine whether or not the function is cyclic
3. If cyclic returns true, create the cycle with an animation curve
4. Setup cycle animation with utility nodes to mimic math function
string $multDivide = `createNode multiplyDivide`;setAttr ($multDivide + ".operation") 2;connectAttr "time1.outTime" "breathCurve.time";connectAttr "breathCurve.time" ($multDivide + ".i1x");connectAttr "breathcontrol.translateY" ($multDivide + ".i2x");connectAttr -f ($multDivide + ".outputX") "breathCurve_scaleCurve.input";
string $mdl = `createNode multDoubleLinear`;string $adl = `createNode addDoubleLinear`;
connectAttr "breathCurve.scaleCurve" ($mdl + ".i1");setAttr ($mdl + ".i2") .1;connectAttr ($mdl + ".output") ($adl + ".i1");setAttr ($adl + ".i2") 1;connectAttr ($adl + ".output") "breathroot1.scaleX";connectAttr ($adl + ".output") "breathroot2.scaleX";
![Page 37: Utility Nodes in an Animation Pipeline](https://reader035.vdocument.in/reader035/viewer/2022081519/5681332d550346895d9a279c/html5/thumbnails/37.jpg)
Utility Nodes in an Animation Pipeline
Thank You!