Taking notes on the math functions available in the expression editor, because the documentation uses circular descriptions.
Absolute
The value (decimal or whole) of a number converted into the positive axis.
Example: The absolute value of -5 is 5, of 5 is 5, of 1.2 is 1.2, of -1.2 is 1.2
Useful in rigging scenarios where you need to work with the magnitude regardless of direction or sign. Its particularly useful with symmetry and distance based effects.
Acos
This is helpful in rigging scenarios that involve angle calculations, especially with normalized vectors. Its commonly used in orientation constraints, calculating joint angles, and solving various geometric problems in 3D space, in combination with other trigonometric and vector operations.
Takes a value between -1 and 1, and returns an angle (in radians) whose cosine is the input value
Example:
float $value = 0.5;
float $angle = acos($value);
// $angle will be approximately 1.0472 radians (60 degrees)
This is used in rigging to:
Calculate angles between vectors
Creating arc based motions
Inverse trigonometric relationships
Practical - calculate the angle between two objects and stores it in a control attribute
vector $vector1 = <<object1.translateX, object1.translateY, object1.translateZ>>;
vector $vector2 = <<object2.translateX, object2.translateY, object2.translateZ>>;
vector $normalized1 = normalize($vector1);
vector $normalized2 = normalize($vector2);
float $dotProduct = dot($normalized1, $normalized2);
float $angle = acos($dotProduct);
// Convert to degrees for easier interpretation
control.angle = rad_to_deg($angle);
Notes:
The output is in radians, so convert to degrees if needed
Acos is often used in conjunction with dot product for angle calculations
Add
Adds two values together
Example
float $value1 = 5;
float $value2 = 3;
float $result = $value1 + $value2; // result is 8
AndBool
One of the logical operators, useful to ensure multiple criteria are met before triggering an action
There are two variants:
AndBool (for boolean values)
AndInt (for integer values, treating non-zero as true)
Syntax: &&
Example:
int $condition1 = control1.attribute > 0;
int $condition2 = control2.attribute < 10;
int $result = $condition1 && $condition2;
AngleBetweenVectors
Excellent for creating orientation aware behaviors in rigging. Its useful in scenarios involving aiming, constraint systems, or any situation where you need to understand or manipulate the relationship between directions in 3D space.
Syntax: anglebetween(vector1, vector2)
Functionality:
Takes two vectors as input
returns the angle between those vectors in radians
Example:
vector $vec1 = <<1, 0, 0>>;
vector $vec2 = <<0, 1, 0>>;
float $angle = anglebetween($vec1, $vec2);
// $angle will be approximately 1.5708 radians (90 degrees)
Usages:
Calculating joint angles
Creating orientation based constraints
Implementing aim or lookat behaviors
Designating rotation limits or angle based effects
Practical - a simple aim constraint that rotates an object to point at its target
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $upVector = <<0, 1, 0>>; // World up vector
vector $aimVector = normalize($targetPos - $objectPos);
vector $rightVector = normalize(cross($upVector, $aimVector));
vector $newUpVector = cross($aimVector, $rightVector);
float $yRotation = anglebetween(<<1, 0, 0>>, <<$aimVector.x, 0, $aimVector.z>>);
float $xRotation = anglebetween($aimVector, $newUpVector) - 90;
if ($aimVector.z < 0) $yRotation = -$yRotation;
object.rotateY = rad_to_deg($yRotation);
object.rotateX = rad_to_deg($xRotation);
Advanced Practical - Creating a join rotation limit system
vector $parentForward = <<1, 0, 0>>; // Assuming local X is forward
vector $childPosition = <<child.translateX, child.translateY, child.translateZ>>;
float $angle = anglebetween($parentForward, $childPosition);
float $maxAngle = deg_to_rad(45); // 45 degree limit
if ($angle > $maxAngle) {
vector $limitedVector = normalize($childPosition) * sin($maxAngle);
child.translateX = $limitedVector.x;
child.translateY = $limitedVector.y;
child.translateZ = $limitedVector.z;
}
Asin
Asin calculates the inverse sine (aka the arc sine) of a given value. It’s useful in rigging scenarios that involve calculating angles from normalized values or component ratios. Its used in creating arc-based motions, solving inverse kinematic problems, and any situation where you need to determine angle based on a sine value. Typically used concurrently with other trigonometric and vector operations.
Syntax: asin(value)
Functionality:
Takes a value between -1 and 1 as input
Returns the angle (in radians) whose sine is the input value
Output range is -90° to 90°
Example:
float $value = 0.5;
float $angle = asin($value);
// $angle will be approximately 0.5236 radians (30 degrees)
Practical - a rig that calculates the elevation angle of a object from the XZ plane and stores it in a control attribute
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $planeNormal = <<0, 1, 0>>; // Assuming XZ plane
vector $direction = normalize($objectPos);
float $dotProduct = dot($direction, $planeNormal);
float $elevationAngle = asin($dotProduct);
// Convert to degrees for easier interpretation
control.elevationAngle = rad_to_deg($elevationAngle);
Advanced Practical - create a semicircular motion path based on the input attribute
float $input = control.inputAttr; // Assume this ranges from -1 to 1
float $angle = asin($input);
float $radius = 5;
float $x = $radius * $input;
float $y = $radius * cos($angle);
object.translateX = $x;
object.translateY = $y;
Atan
Calculates the Arc Tangent function - it’s useful in rigging scenarios that involve calculating angles based on ratios or in situations where you need to determine orientation from positional data. Its often used in look at systems, dynamic rotation calculations, and in creating responsive rig elements that need to orient themselves based on spatial relationships.
Syntax: atan(value)
Functionality:
Takes any real number as an input
Returns the angle (in radians)
Output range is -90° to 90°
Example:
float $value = 1;
float $angle = atan($value);
// $angle will be approximately 0.7854 radians (45 degrees)
Practical - create a simple look at behavior for an object
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $direction = $targetPos - $objectPos;
float $yRotation = atan($direction.x / $direction.z);
float $xRotation = atan($direction.y / sqrt($direction.x * $direction.x + $direction.z * $direction.z));
// Adjust for quadrant
if ($direction.z < 0) $yRotation += 3.14159;
object.rotateY = rad_to_deg($yRotation);
object.rotateX = rad_to_deg($xRotation);
Advanced Practical - using for dynamic foot placement, this adjusts the foot’s rotation to match an angled floor surface.
float $floorHeight = 0;
float $toePos = toe.translateY;
float $heelPos = heel.translateY;
float $footLength = abs(toe.translateZ - heel.translateZ);
float $floorAngle = atan(($toePos - $heelPos) / $footLength);
foot.rotateX = rad_to_deg($floorAngle);
Atan2
Calculates the inverse tangent of y/x, taking into account the quadrant of the resulting angle. It is a more advanced system than the arc tangent, it’s valuable in scenarios where you need to calculate angles that cover all 360°, such as look-at systems, circular motions, or when dealing with local coordinate systems.
Syntax: atan(y,x)
Functionality
Takes two inputs, y and x (in that order)
Returns the angle (in radians) from positive x-axis to the point (x, y)
Output range is (-180° to 180°)
Example:
float $y = 1;
float $x = -1;
float $angle = atan($y, $x);
// $angle will be approximately 2.3562 radians (135 degrees)
Practical - an improved lookat behavior that handles all quadrants correctly, allowing the system to rotate a full 180°
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $direction = $targetPos - $objectPos;
float $yRotation = atan($direction.x, $direction.z);
float $xRotation = atan($direction.y, sqrt($direction.x * $direction.x + $direction.z * $direction.z));
object.rotateY = rad_to_deg($yRotation);
object.rotateX = -rad_to_deg($xRotation); // Negative because Maya's rotation is opposite
Advanced Practical - adjusts a foot’s rotation to match uneven terrain, considering both pitch and roll
vector $anklePos = <<ankle.translateX, ankle.translateY, ankle.translateZ>>;
vector $toePos = <<toe.translateX, toe.translateY, toe.translateZ>>;
vector $heelPos = <<heel.translateX, heel.translateY, heel.translateZ>>;
vector $footForward = $toePos - $heelPos;
vector $footUp = cross($footForward, <<1, 0, 0>>);
float $slopeAngle = atan($footUp.y, $footUp.z);
foot.rotateX = rad_to_deg($slopeAngle);
Average
Calculates the arithmetic mean of a set of values
Variants:
Average (float)
AverageInt (int)
AverageAngle (angle)
AverageVector (vector)
AverageMatrix (matrix)
Syntax: average([value1,value2,value3,…])g
Example:
float $values[] = {10, 20, 30, 40, 50};
float $result = average($values);
// $result will be 30
Practical - a control which centers itself at the average location of multiple objects:
vector $positions[];
$positions[0] = <<object1.translateX, object1.translateY, object1.translateZ>>;
$positions[1] = <<object2.translateX, object2.translateY, object2.translateZ>>;
$positions[2] = <<object3.translateX, object3.translateY, object3.translateZ>>;
vector $averagePos = average($positions);
control.translateX = $averagePos.x;
control.translateY = $averagePos.y;
control.translateZ = $averagePos.z;
Advanced Practical - Creates a camera that smoothly follows a target by averaging its positions over several frames
vector $targetPositions[];
int $numFrames = 10;
for ($i = 0; $i < $numFrames; $i++) {
float $time = `currentTime -q` - $i;
setAttr time1.outTime $time;
$targetPositions[$i] = <<target.translateX, target.translateY, target.translateZ>>;
}
vector $averagePos = average($targetPositions);
camera.translateX = $averagePos.x;
camera.translateY = $averagePos.y;
camera.translateZ = $averagePos.z;
AxisFromMatrix
Extracts a specific axis vector from a transformation matrix. You can use it to extract local or world space orientations, create aim up or vector constraints, implement space switching mechanisms, and analyze object orientations in complex hierarchies.
Syntax: axis(matrix,axis) //matrix is the input matrix and axis is an integer
Functionality
Takes a transformation matrix and an axis index as input
Returns a vector representing the axis from the matrix
Returns a normalized vector (unit length)
Example:
vector $matrix[4] = `object.worldMatrix`;
int $axisIndex = 0; // 0 for X-axis
vector $axisVector = axis($matrix, $axisIndex);
Practical - Simple aim constraint using the forward axis of an object:
vector $sourceMatrix[4] = `source.worldMatrix`;
vector $forwardAxis = axis($sourceMatrix, 0); // Assuming X is forward
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $sourcePos = <<source.translateX, source.translateY, source.translateZ>>;
vector $toTarget = normalize($targetPos - $sourcePos);
float $dotProduct = dot($forwardAxis, $toTarget);
vector $crossProduct = cross($forwardAxis, $toTarget);
float $angle = acos($dotProduct);
vector $rotationAxis = normalize($crossProduct);
// Convert to degrees and apply rotation
float $rotationAngle = rad_to_deg($angle);
setAttr("source.rotateX", $rotationAxis.x * $rotationAngle);
setAttr("source.rotateY", $rotationAxis.y * $rotationAngle);
setAttr("source.rotateZ", $rotationAxis.z * $rotationAngle);
Advanced Practical - Calculates a twist angle for an object based on its local up vector compared to the worlds up
vector $objectMatrix[4] = `object.worldMatrix`;
vector $upVector = axis($objectMatrix, 1); // Y-axis as up
vector $forwardVector = axis($objectMatrix, 0); // X-axis as forward
vector $worldUp = <<0, 1, 0>>;
vector $rightVector = normalize(cross($forwardVector, $worldUp));
vector $newUpVector = normalize(cross($rightVector, $forwardVector));
float $upDot = dot($upVector, $newUpVector);
vector $upCross = cross($upVector, $newUpVector);
float $twistAngle = atan2(dot($upCross, $forwardVector), $upDot);
object.twist = rad_to_deg($twistAngle);
Ceil
Rounds a floating point number up to the nearest integer.
Types:
Ceil (floats)
CeilAngle (for angles)
Syntax: ceil(value)
Example:
float $value1 = 3.2;
float $value2 = 3.8;
float $result1 = ceil($value1); // result1 will be 4
float $result2 = ceil($value2); // result2 will be 4
Practical - Snaps an object to the nearest integer grid point above its current position in all axes
float $rawX = control.translateX;
float $rawY = control.translateY;
float $rawZ = control.translateZ;
float $snappedX = ceil($rawX);
float $snappedY = ceil($rawY);
float $snappedZ = ceil($rawZ);
object.translateX = $snappedX;
object.translateY = $snappedY;
object.translateZ = $snappedZ;
Clamp
Restricts a value to stay within a specific range.
Variants:
Clamp (float)
ClampInt (int)
ClampAngle (angle)
Syntax: clamp(value, min, max)
Functionality:
Takes three inputs, the value to be clamped, the minimum allowed value, and the maximum allowed value.
Returns the input if its with range
Returns the max if its above the max, or the min if its below the min range.
Example:
float $value = 15;
float $min = 0;
float $max = 10;
float $result = clamp($value, $min, $max);
// $result will be 10
Practical - Create a control that limites an object’s scale between 0.5 and 2
float $scaleX = object.scaleX;
float $scaleY = object.scaleY;
float $scaleZ = object.scaleZ;
float $minScale = 0.5;
float $maxScale = 2.0;
object.scaleX = clamp($scaleX, $minScale, $maxScale);
object.scaleY = clamp($scaleY, $minScale, $maxScale);
object.scaleZ = clamp($scaleZ, $minScale, $maxScale);
Advanced Practical - creating a smooth falloff effect
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $centerPos = <<center.translateX, center.translateY, center.translateZ>>;
float $distance = mag($objectPos - $centerPos);
float $maxDistance = 10;
float $minDistance = 2;
float $falloff = 1 - clamp(($distance - $minDistance) / ($maxDistance - $minDistance), 0, 1);
object.scaleX = lerp(0.5, 1, $falloff);
object.scaleY = lerp(0.5, 1, $falloff);
object.scaleZ = lerp(0.5, 1, $falloff);
Compare
Evaluates the relationship between two values and returns an int indicating their relative order.
Variants:
Compare (float)
CompareInt (int)
CompareAngle (angle)
Syntax: compare(value1, value2)
Functionality:
Takes 2 values as an input
Returns -1 if value1 is less than value2
Returns 0 if value 1 is equal to value2
Returns 1 if value1 is greater than value2
Example:
float $value1 = 5;
float $value2 = 10;
int $result = compare($value1, $value2);
// $result will be -1
Practical - simple state machine based on an object’s position:
float $posX = object.translateX;
int $state = compare($posX, 0);
if ($state == -1) {
setAttr("leftLight.intensity", 1);
setAttr("rightLight.intensity", 0);
} else if ($state == 1) {
setAttr("leftLight.intensity", 0);
setAttr("rightLight.intensity", 1);
} else {
setAttr("leftLight.intensity", 0.5);
setAttr("rightLight.intensity", 0.5);
}
Practical Advanced - a dynamic parenting system
float $controlValue = control.parentingAttr;
vector $targets[] = {<<target1.translateX, target1.translateY, target1.translateZ>>,
<<target2.translateX, target2.translateY, target2.translateZ>>,
<<target3.translateX, target3.translateY, target3.translateZ>>};
int $index = 0;
for ($i = 1; $i < size($targets); $i++) {
if (compare($controlValue, $i) < 0) {
break;
}
$index = $i;
}
vector $parentPos = $targets[$index];
object.translateX = $parentPos.x;
object.translateY = $parentPos.y;
object.translateZ = $parentPos.z;
CosAngle
CosAngle calculates the cosine of an input angle. Its useful in generating wave-like behaviors, circular motions, and in solving trigonometric problems.
Syntax: cos(angle)
Functionality:
Takes an angle as input (in radians)
Returns the cosine of that angle (a value between -1 and 1)
Works with floats
Example:
float $angleInDegrees = 60;
float $angleInRadians = deg_to_rad($angleInDegrees);
float $result = cos($angleInRadians);
// $result will be approximately 0.5
Practical - creating a simple oscillating side-to-side motion:
float $time = `currentTime -q`;
float $frequency = 0.1; // Controls how fast the oscillation occurs
float $amplitude = 5; // Controls the range of the motion
float $xPosition = $amplitude * cos($time * $frequency);
object.translateX = $xPosition;
Advanced Practical - Creates a look-at behavior with an additional twist calculation using cosine
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $direction = normalize($targetPos - $objectPos);
float $yRotation = atan2($direction.x, $direction.z);
float $xRotation = asin(-$direction.y);
object.rotateY = rad_to_deg($yRotation);
object.rotateX = rad_to_deg($xRotation);
// Calculate twist
float $upDotX = dot(<<0,1,0>>, <<cos($yRotation), 0, -sin($yRotation)>>);
float $twist = acos($upDotX);
object.rotateZ = rad_to_deg($twist);
CrossProduct
Calculates the vector perpendicular to two input vectors. This is helpful in creating orientation matrices, calculating surface normals, and implementing various constraints.
Syntax: cross(vector1, vector2)
Functionality:
Takes two Vector3 values as input
Returns a new vector perpendicular to both input vectors
Resulting vector follows right hand rule
Example:
vector $vec1 = <<1, 0, 0>>; // X-axis
vector $vec2 = <<0, 1, 0>>; // Y-axis
vector $result = cross($vec1, $vec2);
// $result will be <<0, 0, 1>> (Z-axis)
Practical - a simple aim constraint with an automatic up-vector:
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $aimVector = normalize($targetPos - $objectPos);
vector $worldUp = <<0, 1, 0>>;
vector $rightVector = normalize(cross($aimVector, $worldUp));
vector $upVector = normalize(cross($rightVector, $aimVector));
float $aimMatrix[4][4] =
$aimVector.x, $aimVector.y, $aimVector.z, 0,
$upVector.x, $upVector.y, $upVector.z, 0,
$rightVector.x, $rightVector.y, $rightVector.z, 0,
$objectPos.x, $objectPos.y, $objectPos.z, 1
>>;
setAttr object.matrix $aimMatrix;
Advanced Practical - creating a ribbon-like deformation between two joints with a sinusoidal twist
vector $startPos = <<startJoint.translateX, startJoint.translateY, startJoint.translateZ>>;
vector $endPos = <<endJoint.translateX, endJoint.translateY, endJoint.translateZ>>;
vector $upVector = <<0, 1, 0>>;
vector $ribbonDir = normalize($endPos - $startPos);
vector $ribbonWidth = normalize(cross($ribbonDir, $upVector));
float $ribbonLength = mag($endPos - $startPos);
float $currentU = uCoordinate; // Assume we have a U coordinate from 0 to 1
vector $ribbonPoint = $startPos + $ribbonDir * ($currentU * $ribbonLength);
vector $offset = $ribbonWidth * sin($currentU * 2 * 3.14159) * 2;
point.translateX = $ribbonPoint.x + $offset.x;
point.translateY = $ribbonPoint.y + $offset.y;
point.translateZ = $ribbonPoint.z + $offset.z;
DebugLog
Prints a value to the Maya Script Editor
Variants:
DebugLog (float)
DebugLogInt (int)
DebugLogVector (vector)
DebugLogAngle (angles)
DebugLogMatrix (matrix)
Syntax: debuglog(value)
Example:
float $value = 3.14;
float $result = debuglog($value);
// Prints "3.14" to the Script Editor
// $result will be 3.14
Practical - monitor a simple IK stretching setup
vector $startPos = <<startJoint.translateX, startJoint.translateY, startJoint.translateZ>>;
vector $endPos = <<endJoint.translateX, endJoint.translateY, endJoint.translateZ>>;
float $currentLength = mag(debuglog($endPos - $startPos));
float $originalLength = 10; // Assume this is the original chain length
float $stretchFactor = debuglog($currentLength / $originalLength);
middleJoint.scaleX = $stretchFactor;
Divide
Classic division
Variants
Divide (float)
DivideAngle (angle)
DivideByInt (divides a float by an integer)
DivideAngleByInt (divides an angle by an integer)
Syntax: x / y
Example:
float $value1 = 10;
float $value2 = 2;
float $result = $value1 / $value2;
// $result will be 5
Practical - a simple stretch IK system
vector $startPos = <<startJoint.translateX, startJoint.translateY, startJoint.translateZ>>;
vector $endPos = <<endJoint.translateX, endJoint.translateY, endJoint.translateZ>>;
float $currentLength = mag($endPos - $startPos);
float $originalLength = 10; // Assume this is the original chain length
float $stretchFactor = $currentLength / $originalLength;
if ($stretchFactor > 1) {
middleJoint.scaleX = $stretchFactor;
} else {
middleJoint.scaleX = 1;
}
DotProduct
DotProduct calculates the scalar product of two vectors. It is useful for calculating angles, determining alignment, and creating direction-based effects.
Syntax: dot(vector1, vector2)
Example:
vector $vec1 = <<1, 0, 0>>;
vector $vec2 = <<0, 1, 0>>;
float $result = dot($vec1, $vec2);
// $result will be 0 (because the vectors are perpendicular)
Practical - create a simple look-at behavior with a falloff effect, this scales an object based on how well its aligned with its target:
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $toTarget = normalize($targetPos - $objectPos);
vector $objectForward = <<object.worldMatrix[0].x, object.worldMatrix[0].y, object.worldMatrix[0].z>>;
float $alignment = dot($toTarget, $objectForward);
// $alignment will be 1 when perfectly aligned, -1 when opposite, and 0 when perpendicular
float $falloff = ($alignment + 1) / 2; // Remap to 0-1 range
object.scaleX = lerp(0.5, 1, $falloff);
object.scaleY = lerp(0.5, 1, $falloff);
object.scaleZ = lerp(0.5, 1, $falloff);
Advanced Practical - create a surface sliding behavior, where an object slides along as urface, removing any movement in the direction of the surface normal
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $surfaceNormal = <<surface.normalX, surface.normalY, surface.normalZ>>;
vector $moveVector = <<control.translateX, control.translateY, control.translateZ>>;
float $normalComponent = dot($moveVector, $surfaceNormal);
vector $tangentVector = $moveVector - $surfaceNormal * $normalComponent;
object.translateX = $objectPos.x + $tangentVector.x;
object.translateY = $objectPos.y + $tangentVector.y;
object.translateZ = $objectPos.z + $tangentVector.z;
DistancePoints
Calculates the Euclidean distance between two points in 3D space. Useful for creating distance-based behaviors, implementing stretch systems, and designing proximity-based effects. Other usages might be calculating lengths of joints or limbs, implementing distance based constraints, or creating falloffs based on proximity, or measuring spatial relationships between objects.
Variants:
DistancePoints (for point to point distance)
DistanceTransforms (for distance between transform nodes)
Syntax: distance(point1,point2)
Functionality:
Takes two Vector3s as input
Returns a scalar value representing the strait line distance between the points
Example:
vector $point1 = <<0, 0, 0>>;
vector $point2 = <<3, 4, 0>>;
float $result = distance($point1, $point2);
// $result will be 5
Practical - a simple stretchy IK setup, in which the arm scales uniformly when extended beyond its original length
vector $shoulderPos = <<shoulder.translateX, shoulder.translateY, shoulder.translateZ>>;
vector $handPos = <<hand.translateX, hand.translateY, hand.translateZ>>;
float $currentLength = distance($shoulderPos, $handPos);
float $originalLength = 10; // Assume this is the original arm length
float $stretchFactor = $currentLength / $originalLength;
upperArm.scaleX = $stretchFactor;
lowerArm.scaleX = $stretchFactor;
Advanced Practical - Creating a proximity based blending system, where an object is influenced by multiple targets based on proximity
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $influences[];
float $weights[];
float $maxDistance = 10;
for ($i = 1; $i <= 3; $i++) {
$influences[$i] = <<(`target$i.translateX`), (`target$i.translateY`), (`target$i.translateZ`)>>;
float $dist = distance($objectPos, $influences[$i]);
$weights[$i] = 1 - clamp($dist / $maxDistance, 0, 1);
}
float $totalWeight = $weights[1] + $weights[2] + $weights[3];
if ($totalWeight > 0) {
vector $blendedPosition = <<0, 0, 0>>;
for ($i = 1; $i <= 3; $i++) {
$blendedPosition += $influences[$i] * ($weights[$i] / $totalWeight);
}
object.translateX = $blendedPosition.x;
object.translateY = $blendedPosition.y;
object.translateZ = $blendedPosition.z;
}
Floor
Floor rounds a floating point number down to the nearest integer
Variants:
Floor (float)
FloorAngle (angle)
Syntax: floor(value)
Example:
float $value1 = 3.7;
float $value2 = -2.1;
float $result1 = floor($value1); // result1 will be 3
float $result2 = floor($value2); // result2 will be -3
Practical - creates a stepped rotation system, which controls that step in 45° increments, always rounding down
float $rotationStep = 45; // Rotate in 45-degree increments
float $currentRotation = control.rotateY;
float $steppedRotation = floor($currentRotation / $rotationStep) * $rotationStep;
object.rotateY = $steppedRotation;
Inverse
Calculates the inverse of a given value or transformation. Useful for handling transformations and space conversions, like complex hierarchical relationships or space switching systems. It provides a way to invert values and transformations, allowing riggers to create more flexible control systems, and enabling objects to maintain their positions and orientations across different coordinate spaces.
Variants:
Inverse (float)
InverseMatrix (for matricies)
InverseQuaternion (for quaternions)
InverseRotation (for rotations)
Syntax: inverse(value)
Functionality:
For scalars: Returns 1 divided by the input
For matrices: Returns the inverse matrix
For quaternions and rotations: returns the inverse rotation
Example:
float $scalar = 2;
float $inverseScalar = inverse($scalar); // Result: 0.5
vector $matrix[4] = `object.worldMatrix`;
vector $inverseMatrix[4] = inverse($matrix);
Practical - a simple space switching system, which converts an object’s world space to local space relative to the parent object
vector $worldMatrix[4] = `object.worldMatrix`;
vector $parentMatrix[4] = `parent.worldMatrix`;
vector $localMatrix[4] = inverse($parentMatrix) * $worldMatrix;
setAttr object.matrix $localMatrix;
Practical Advanced - Creates a dynamic parent constraint, which creates a smooth transition between world space and parent space for a child object
vector $childWorldMatrix[4] = `child.worldMatrix`;
vector $parentWorldMatrix[4] = `parent.worldMatrix`;
float $parentInfluence = parent.influence; // Assume this ranges from 0 to 1
if ($parentInfluence > 0) {
vector $parentLocalMatrix[4] = inverse($parentWorldMatrix) * $childWorldMatrix;
vector $blendedLocalMatrix[4] = slerp(`child.matrix`, $parentLocalMatrix, $parentInfluence);
vector $newWorldMatrix[4] = $parentWorldMatrix * $blendedLocalMatrix;
setAttr child.matrix $newWorldMatrix;
}
Lerp
Lerp takes the input of one value, and then drives the output between two other given values. This is a classic way to create smooth transitions, and is particularly helpful when you need to interpolate between known states or values.
Variants:
Lerp (float)
LerpAngle (angle)
LerpVector (vector)
LerpMatrix (matrix)
Syntax: lerp(value1,value2,alpha)
Functionality
Takes three inputs, two values to interpolate between, and an alpha (how much they should blend between each other)
Returns a value linearly interpolated between value1 and value2
Alpha typically ranges between 0 (full value1) and 1 (full value2)
Example:
float $value1 = 0;
float $value2 = 10;
float $alpha = 0.3;
float $result = lerp($value1, $value2, $alpha);
// $result will be 3
Practical - a simple blend between two rotations, controlled by a single attribute
vector $rotation1 = <<0, 0, 0>>;
vector $rotation2 = <<90, 45, 30>>;
float $blendFactor = control.blendAttr; // Assume this ranges from 0 to 1
vector $blendedRotation = lerp($rotation1, $rotation2, $blendFactor);
object.rotateX = $blendedRotation.x;
object.rotateY = $blendedRotation.y;
object.rotateZ = $blendedRotation.z;
Advanced Practical - a multi-target blending system where an object can be blended between three different positions
vector $pos1 = <<target1.translateX, target1.translateY, target1.translateZ>>;
vector $pos2 = <<target2.translateX, target2.translateY, target2.translateZ>>;
vector $pos3 = <<target3.translateX, target3.translateY, target3.translateZ>>;
float $blend1 = control.blend1;
float $blend2 = control.blend2;
vector $intermediatPos = lerp($pos1, $pos2, $blend1);
vector $finalPos = lerp($intermediatPos, $pos3, $blend2);
object.translateX = $finalPos.x;
object.translateY = $finalPos.y;
object.translateZ = $finalPos.z;
MatrixFrom
Used to create a transformation matrix from various input components. This is useful in rigging for creating complex transformations, setting up space switching, or defining custom object orientations.
Syntax:
matrixFromRotation(rotateX, rotateY, rotateZ, rotationOrder)
matrixFrom(scale, rotation, translation)
matrixFromTranslation(translateX, translateY, translateZ)
matrixFromDirection(directionVector, upVector)
matrixFromElements(XX, XY, XZ, XW, YX, YY, YZ, YW, ZX, ZY, ZZ, ZW, WX, WY, WZ, WW)
Functionality:
Inputs: depends on which variant you are targeting
Output: a 4x4 transformation matrix
Example:
// Create a rotation matrix and apply it to an object
matrix $rotMatrix = matrixFromRotation(object1.rotateX, object1.rotateY, object1.rotateZ, "xyz");
object2.matrix = $rotMatrix;
Practical - Space Switching for IK Controls
// Switch between local and world space for an IK control
matrix $localMatrix = matrixFrom(<<1,1,1>>, <<ikControl.rotateX, ikControl.rotateY, ikControl.rotateZ>>, <<ikControl.translateX, ikControl.translateY, ikControl.translateZ>>);
matrix $parentMatrix = parent.worldMatrix;
matrix $worldMatrix = $localMatrix * $parentMatrix;
if (ikControl.space == 0) // Local space
ikHandle.matrix = $localMatrix;
else // World space
ikHandle.matrix = $worldMatrix;
Advanced Practical - Ribbon Spine System
// Create a ribbon-like spine system
vector $startPos = <<startJoint.translateX, startJoint.translateY, startJoint.translateZ>>;
vector $endPos = <<endJoint.translateX, endJoint.translateY, endJoint.translateZ>>;
vector $spineVector = unit($endPos - $startPos);
vector $upVector = <<0, 1, 0>>;
vector $sideVector = unit(cross($spineVector, $upVector));
matrix $spineMatrix = matrixFromDirection($spineVector, $upVector);
// Apply to middle joint
middleJoint.matrix = $spineMatrix;
MatrixFromDirection
Creates a rotation matrix that orients an object to face a specified direction. Useful when you need objects to face or align with specific directions while maintaining a stable up orientation. It simplifies the process of creating look at behaviors, aim constrains, and other direction-based orientation systems.
Syntax: direction(directionVector, upVector)
Functionality:
Takes two inputs, a direction vector and up vector
Returns a 4x4 matrix representing the rotation that aligns an object’s local forward axis with the direction vector.
Uses the up vector to determine the object’s local up direction.
Example:
vector $directionVec = <<1, 1, 1>>;
vector $upVec = <<0, 1, 0>>;
vector $resultMatrix[4] = direction($directionVec, $upVec);
Practical - orients an object to always face a target object
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $directionVec = normalize($targetPos - $objectPos);
vector $upVec = <<0, 1, 0>>; // World up vector
vector $lookAtMatrix[4] = direction($directionVec, $upVec);
// Extract rotation from matrix
vector $rotation = rot($lookAtMatrix, "xyz");
object.rotateX = rad_to_deg($rotation.x);
object.rotateY = rad_to_deg($rotation.y);
object.rotateZ = rad_to_deg($rotation.z);
Advanced Practical - creating a ribbon-like chain of objects
int $numObjects = 10;
vector $startPos = <<startObj.translateX, startObj.translateY, startObj.translateZ>>;
vector $endPos = <<endObj.translateX, endObj.translateY, endObj.translateZ>>;
vector $chainDir = normalize($endPos - $startPos);
vector $upVec = <<0, 1, 0>>;
vector $sideVec = normalize(cross($chainDir, $upVec));
$upVec = cross($sideVec, $chainDir);
for ($i = 0; $i < $numObjects; $i++) {
float $t = (float)$i / ($numObjects - 1);
vector $pos = $startPos + $chainDir * ($t * mag($endPos - $startPos));
vector $localUp = $upVec * sin($t * 2 * 3.14159) + $sideVec * cos($t * 2 * 3.14159);
vector $orientMatrix[4] = direction($chainDir, $localUp);
setAttr ("object" + ($i+1) + ".translateX") $pos.x;
setAttr ("object" + ($i+1) + ".translateY") $pos.y;
setAttr ("object" + ($i+1) + ".translateZ") $pos.z;
setAttr ("object" + ($i+1) + ".matrix") $orientMatrix;
}
MatrixfromTRS
Constructs a 4x4 transformation matrix from separate translation, rotation and scale components. It allows you to combine all these values into a single matrix, which is crucial for complex transformation operations, space switching, and advanced constraint systems.
Syntax: trs(translation, rotation, scale)
Functionality:
Takes three inputs, a translation vector, a rotation (euler or quaternion) and a scale vector
Returns a 4x4 matrix that represents the combined transformation
Applies the transformations in the order, scale, then rotate, then translate
Example:
vector $translation = <<10, 20, 30>>;
vector $rotation = <<0, 90, 0>>; // In degrees
vector $scale = <<2, 2, 2>>;
vector $resultMatrix[4] = trs($translation, deg_to_rad($rotation), $scale);
Practical - a simple space switching setup between local and parent space
vector $localTranslate = <<object.translateX, object.translateY, object.translateZ>>;
vector $localRotate = <<deg_to_rad(object.rotateX),
deg_to_rad(object.rotateY),
deg_to_rad(object.rotateZ)>>;
vector $localScale = <<object.scaleX, object.scaleY, object.scaleZ>>;
vector $localMatrix[4] = trs($localTranslate, $localRotate, $localScale);
int $spaceSwitch = control.spaceSwitch; // 0 for world, 1 for parent
vector $parentMatrix[4] = `parent.worldMatrix`;
if ($spaceSwitch == 1) {
vector $worldMatrix[4] = $parentMatrix * $localMatrix;
setAttr object.matrix $worldMatrix;
} else {
setAttr object.matrix $localMatrix;
}
Advanced Practical - an animated transformation combining oscillating translation, rotation, and scaling
float $time = `currentTime -q`;
vector $translation = <<sin($time * 0.1) * 10, cos($time * 0.2) * 5, 0>>;
vector $rotation = <<0, $time * 10, 0>>; // Rotate around Y-axis
vector $scale = <<1 + sin($time * 0.05) * 0.2,
1 + sin($time * 0.05) * 0.2,
1 + sin($time * 0.05) * 0.2>>;
vector $animMatrix[4] = trs($translation, deg_to_rad($rotation), $scale);
setAttr object.matrix $animMatrix;
Max
Returns the larger of two variables
Variants:
Max (float)
MaxInt (Int)
MaxAngle (Angle)
Syntax: max(value1, value2)
Functionality:
Takes two input values
Returns the larger of the two inputs
Example:
float $value1 = 5.3;
float $value2 = 7.8;
float $result = max($value1, $value2);
// $result will be 7.8
Practical - Creating a stretchy IK Limb with a minimum length:
def stretchy_ik(start_joint, end_joint, ik_handle, min_length):
current_length = distance(start_joint.worldMatrix[3], end_joint.worldMatrix[3])
original_length = ik_handle.poleVectorX # Assuming we stored the original length here
stretch_factor = max(current_length / original_length, 1)
start_joint.scaleX = stretch_factor
start_joint.scaleY = max(1 / sqrt(stretch_factor), min_length / original_length)
start_joint.scaleZ = max(1 / sqrt(stretch_factor), min_length / original_length)
in this example the limb never compresses below its original length and maintains a minimum thickness.
Advanced Practical - dynamic scaling system based on distance
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
float $distance = mag($targetPos - $objectPos);
float $minScale = 0.5;
float $scaleFactorPerUnit = 0.1;
float $dynamicScale = max($minScale, 1 + $distance * $scaleFactorPerUnit);
object.scaleX = $dynamicScale;
object.scaleY = $dynamicScale;
object.scaleZ = $dynamicScale;
MaxElement
Returns the largest value from an array of values
Variants
MaxElement (float)
MaxIntElement (Int)
MaxAngleElement (Angle)
Syntax: maxelement(array)
Functionality:
Takes an array of numeric values as an input
Returns the largest value in the array
Example:
float $values[] = {3.5, 7.2, 1.8, 9.1, 4.6};
float $result = maxelement($values);
// $result will be 9.1
Practical - Scales an object based on the largest scale factor from three different influences
float $scaleFactors[];
$scaleFactors[0] = influence1.scaleFactorAttr;
$scaleFactors[1] = influence2.scaleFactorAttr;
$scaleFactors[2] = influence3.scaleFactorAttr;
float $maxScaleFactor = maxelement($scaleFactors);
object.scaleX = $maxScaleFactor;
object.scaleY = $maxScaleFactor;
object.scaleZ = $maxScaleFactor;
Advanced Practical - orients a control object based on the maximum rotation values from multiple joints
vector $jointOrientations[];
$jointOrientations[0] = <<joint1.rotateX, joint1.rotateY, joint1.rotateZ>>;
$jointOrientations[1] = <<joint2.rotateX, joint2.rotateY, joint2.rotateZ>>;
$jointOrientations[2] = <<joint3.rotateX, joint3.rotateY, joint3.rotateZ>>;
float $maxRotationX = maxelement(<<$jointOrientations[0].x, $jointOrientations[1].x, $jointOrientations[2].x>>);
float $maxRotationY = maxelement(<<$jointOrientations[0].y, $jointOrientations[1].y, $jointOrientations[2].y>>);
float $maxRotationZ = maxelement(<<$jointOrientations[0].z, $jointOrientations[1].z, $jointOrientations[2].z>>);
control.rotateX = $maxRotationX;
control.rotateY = $maxRotationY;
control.rotateZ = $maxRotationZ;
Min
Min returns the smaller of two values. Its useful in scenarios where you need to ensure maximum values, implement clamping behjaviors, or create dynamic systems that respond to the samller of two values.
Variants
Min (float)
MinInt (int)
MinAngle (angle)
Syntax: min(value1, value2)
Functionality:
Takes two input values
Returns the smaller of the two inputs
Works with numeric values (floats, ints, angles)
Example:
float $value1 = 5.3;
float $value2 = 7.8;
float $result = min($value1, $value2);
// $result will be 5.3
Practical - Simple clamping system for a control’s translation, never exceeding 10 in any axis:
float $rawX = control.translateX;
float $rawY = control.translateY;
float $rawZ = control.translateZ;
float $maxValue = 10;
float $clampedX = min($rawX, $maxValue);
float $clampedY = min($rawY, $maxValue);
float $clampedZ = min($rawZ, $maxValue);
object.translateX = $clampedX;
object.translateY = $clampedY;
object.translateZ = $clampedZ;
Advanced Practical - a dynamic scaling system based on distance from a target, within a maximum scale of 2:
float $rawX = control.translateX;
float $rawY = control.translateY;
float $rawZ = control.translateZ;
float $maxValue = 10;
float $clampedX = min($rawX, $maxValue);
float $clampedY = min($rawY, $maxValue);
float $clampedZ = min($rawZ, $maxValue);
object.translateX = $clampedX;
object.translateY = $clampedY;
object.translateZ = $clampedZ;
MinElement
Returns the smallest value from an array of values.
Variants:
MinElement (float arrays)
MinIntElement (int arrays)
MinAngleElement (angle arrays)
Syntax: minelement(array)
Functionality:
Takes an array of numeric values as input
Returns the smallest value in the array
Works with arrays of floats, integers or angles
Example:
float $values[] = {3.5, 7.2, 1.8, 9.1, 4.6};
float $result = minelement($values);
// $result will be 1.8
Practical - A system that scales an object based on the smallest scale factor among multiple influences
float $scaleFactors[];
$scaleFactors[0] = influence1.scaleFactorAttr;
$scaleFactors[1] = influence2.scaleFactorAttr;
$scaleFactors[2] = influence3.scaleFactorAttr;
float $minScaleFactor = minelement($scaleFactors);
object.scaleX = $minScaleFactor;
object.scaleY = $minScaleFactor;
object.scaleZ = $minScaleFactor;
Advanced Usage - A dynamic multi-joint compression system, based on the minimum scale of multiple joints:
vector $jointScales[];
$jointScales[0] = <<joint1.scaleX, joint1.scaleY, joint1.scaleZ>>;
$jointScales[1] = <<joint2.scaleX, joint2.scaleY, joint2.scaleZ>>;
$jointScales[2] = <<joint3.scaleX, joint3.scaleY, joint3.scaleZ>>;
float $minScaleX = minelement(<<$jointScales[0].x, $jointScales[1].x, $jointScales[2].x>>);
float $minScaleY = minelement(<<$jointScales[0].y, $jointScales[1].y, $jointScales[2].y>>);
float $minScaleZ = minelement(<<$jointScales[0].z, $jointScales[1].z, $jointScales[2].z>>);
control.compressionX = 1 - $minScaleX;
control.compressionY = 1 - $minScaleY;
control.compressionZ = 1 - $minScaleZ;
ModulusInt
Calculates the remainder of integer divisions between two values
Syntax: x % y
Functionality:
Takes two integer values as input: a divident and a dividor
Returns the remainder after division of the first value by the second value
Example
value1 = 17
value2 = 5
result = value1 % value2
# result would be 2 (17 divided by 5 is 3 with remainder 2)
Practical - cucles an object’s color between red, green and blue every 24 frames
float $time = `currentTime -q`;
int $cycleLength = 24; // Change color every 24 frames
int $colorIndex = (int)$time % $cycleLength;
if ($colorIndex < 8) {
object.colorR = 1; object.colorG = 0; object.colorB = 0; // Red
} else if ($colorIndex < 16) {
object.colorR = 0; object.colorG = 1; object.colorB = 0; // Green
} else {
object.colorR = 0; object.colorG = 0; object.colorB = 1; // Blue
}
Advanced Practical - rotates multiple objects at the same speed but with evenly distributed offsets
int $numObjects = 5;
float $rotationSpeed = 5; // Degrees per frame
float $time = `currentTime -q`;
for ($i = 0; $i < $numObjects; $i++) {
int $offset = ($i * 360) / $numObjects;
float $rotation = ($time * $rotationSpeed + $offset) % 360;
setAttr ("object" + ($i+1) + ".rotateY") $rotation;
}
Multiply
Classic multiplication between two values
Syntax: x * y
Example:
float $value1 = 5;
float $value2 = 3;
float $result = $value1 * $value2;
// $result will be 15
Practical - a simple scaling system based on distance:
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
float $distance = mag($targetPos - $objectPos);
float $scaleFactor = 1 - ($distance / 10); // Assume 10 is the max distance
float $baseScale = 1;
object.scaleX = $baseScale * $scaleFactor;
object.scaleY = $baseScale * $scaleFactor;
object.scaleZ = $baseScale * $scaleFactor;
Negate
Returns the additive inverse of a value. Particularly useful for creating symmetrical behavior, toggle systems, and reciprocal relationships between attributes or objects. Allows riggers a more dynamic control system, especially with mirroring, balancing, or any scenario where you need to reverse the effect of a value or motion.
Variants:
Negate (float)
NegateAngle (Angle)
NegateInt (Int)
NegateVector (Vector)
Syntax: negate(value) or -value
Functionality:
Takes a value as an input
Returns the negative of that value
Multiplies the input by -1
Example:
float $value = 5.3;
float $result = negate($value);
// $result will be -5.3
// Alternatively:
float $result2 = -$value;
// $result2 will also be -5.3
Practical - mirrors the rotation of a source control to a target control across the YZ
float $sourceRotateX = sourceControl.rotateX;
float $sourceRotateY = sourceControl.rotateY;
float $sourceRotateZ = sourceControl.rotateZ;
targetControl.rotateX = negate($sourceRotateX);
targetControl.rotateY = $sourceRotateY; // Assuming Y is the up axis
targetControl.rotateZ = negate($sourceRotateZ);
Advanced Practicle - allows toggling between moving towards or away from an object
float $constraintToggle = control.constraintToggle; // Assume this is 0 or 1
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $offset = $targetPos - $objectPos;
vector $negatedOffset = negate($offset);
vector $finalOffset = $offset * $constraintToggle + $negatedOffset * (1 - $constraintToggle);
object.translateX += $finalOffset.x;
object.translateY += $finalOffset.y;
object.translateZ += $finalOffset.z;
NormalizeVector
Returns a unit vector (a vector with a magnitude of 1) in the same direction as the input vector. It is useful in creating aim constraints, calculating orientations, and designing systems that rely on direction information regardless of scale or distance.
Syntax: normalize(vector)
Functionality:
Takes a vector as input
Returns a vector pointing in the same direction but with a length of 1
If the input vector is 0, returns a 0 vector
Example:
vector $inputVector = <<3, 4, 0>>;
vector $normalizedVector = normalize($inputVector);
// $normalizedVector will be <<0.6, 0.8, 0>>
Practical - creates an aim constraint where the object always faces the target while maintaining a stable up oreintation
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $aimVector = normalize($targetPos - $objectPos);
vector $upVector = <<0, 1, 0>>; // World up vector
vector $rightVector = normalize(cross($aimVector, $upVector));
vector $newUpVector = normalize(cross($rightVector, $aimVector));
float $aimMatrix[4][4] =
$aimVector.x, $aimVector.y, $aimVector.z, 0,
$newUpVector.x, $newUpVector.y, $newUpVector.z, 0,
$rightVector.x, $rightVector.y, $rightVector.z, 0,
$objectPos.x, $objectPos.y, $objectPos.z, 1
>>;
setAttr object.matrix $aimMatrix;
Advanced Practical - creates a ribbon-like deformation between two joints
vector $startPos = <<startJoint.translateX, startJoint.translateY, startJoint.translateZ>>;
vector $endPos = <<endJoint.translateX, endJoint.translateY, endJoint.translateZ>>;
vector $ribbonDir = normalize($endPos - $startPos);
vector $upVector = <<0, 1, 0>>;
vector $ribbonSide = normalize(cross($ribbonDir, $upVector));
float $ribbonLength = mag($endPos - $startPos);
float $currentU = uCoordinate; // Assume we have a U coordinate from 0 to 1
float $currentV = vCoordinate; // Assume we have a V coordinate from -0.5 to 0.5
vector $ribbonPoint = $startPos + $ribbonDir * ($currentU * $ribbonLength);
vector $offset = $ribbonSide * $currentV * $ribbonLength * 0.1; // 10% of length for width
point.translateX = $ribbonPoint.x + $offset.x;
point.translateY = $ribbonPoint.y + $offset.y;
point.translateZ = $ribbonPoint.z + $offset.z;
NormalizeArray
Scales an array of values so they sum to 1, while maintaining their relative proportions. Useful in scenarios where you need to blend between multiple inputs or targets while ensuring that the total influence always remains constant.
Syntax: normalizearray(array)
Functionality:
Takes an array of numeric values as input
Returns an array of the same length where all values sum to 1
Maintains the relative proportions of the input values
If all input values are 0, it returns an array of equal values that sum to 1.
Example:
float $inputArray[] = {2, 3, 5};
float $normalizedArray[] = normalizearray($inputArray);
// $normalizedArray will be approximately {0.2, 0.3, 0.5}
Practical - creates a constant where an object is influenced by three targets with normalized weights
vector $target1Pos = <<target1.translateX, target1.translateY, target1.translateZ>>;
vector $target2Pos = <<target2.translateX, target2.translateY, target2.translateZ>>;
vector $target3Pos = <<target3.translateX, target3.translateY, target3.translateZ>>;
float $weights[] = {control.weight1, control.weight2, control.weight3};
float $normalizedWeights[] = normalizearray($weights);
vector $blendedPosition = $target1Pos * $normalizedWeights[0] +
$target2Pos * $normalizedWeights[1] +
$target3Pos * $normalizedWeights[2];
object.translateX = $blendedPosition.x;
object.translateY = $blendedPosition.y;
object.translateZ = $blendedPosition.z;
Advanced Practical - orients an object based on the weighted influence of multiple joints, with weights determined by proximity
vector $jointOrientations[];
$jointOrientations[0] = <<joint1.rotateX, joint1.rotateY, joint1.rotateZ>>;
$jointOrientations[1] = <<joint2.rotateX, joint2.rotateY, joint2.rotateZ>>;
$jointOrientations[2] = <<joint3.rotateX, joint3.rotateY, joint3.rotateZ>>;
float $distances[];
$distances[0] = mag(<<object.translateX - joint1.translateX, object.translateY - joint1.translateY, object.translateZ - joint1.translateZ>>);
$distances[1] = mag(<<object.translateX - joint2.translateX, object.translateY - joint2.translateY, object.translateZ - joint2.translateZ>>);
$distances[2] = mag(<<object.translateX - joint3.translateX, object.translateY - joint3.translateY, object.translateZ - joint3.translateZ>>);
float $weights[] = {1/$distances[0], 1/$distances[1], 1/$distances[2]};
float $normalizedWeights[] = normalizearray($weights);
vector $blendedOrientation = $jointOrientations[0] * $normalizedWeights[0] +
$jointOrientations[1] * $normalizedWeights[1] +
$jointOrientations[2] * $normalizedWeights[2];
object.rotateX = $blendedOrientation.x;
object.rotateY = $blendedOrientation.y;
object.rotateZ = $blendedOrientation.z;
NormalizeWeightsArray
Same as normalize array, but it treats any negative number as 0. Scales an array of values so that they sum to 1 while maintaining their relative proportions, with special handling for negative or 0 values.
Syntax: normalizeweights(array)
Functionality:
Takes an array of numeric values as an input
Returns an array the same length where all positive values sum to 1
Maintains the relative proportions of the positive input values
Treats negative values as 0
If all values are 0 or negative, returns an array of equal positive values that sum to 1
Example:
float $inputArray[] = {2, 3, -1, 5};
float $normalizedArray[] = normalizeweights($inputArray);
// $normalizedArray will be approximately {0.2, 0.3, 0, 0.5}
Practical - constraint where an object is influenced by three targets with normalized weights, safely handling negative or zero inputs
vector $target1Pos = <<target1.translateX, target1.translateY, target1.translateZ>>;
vector $target2Pos = <<target2.translateX, target2.translateY, target2.translateZ>>;
vector $target3Pos = <<target3.translateX, target3.translateY, target3.translateZ>>;
float $weights[] = {control.weight1, control.weight2, control.weight3};
float $normalizedWeights[] = normalizeweights($weights);
vector $blendedPosition = $target1Pos * $normalizedWeights[0] +
$target2Pos * $normalizedWeights[1] +
$target3Pos * $normalizedWeights[2];
object.translateX = $blendedPosition.x;
object.translateY = $blendedPosition.y;
object.translateZ = $blendedPosition.z;
Orients an object based on the weighted influence of multiple joints, safely handling cases where joints might coincide with the object.
vector $jointOrientations[];
$jointOrientations[0] = <<joint1.rotateX, joint1.rotateY, joint1.rotateZ>>;
$jointOrientations[1] = <<joint2.rotateX, joint2.rotateY, joint2.rotateZ>>;
$jointOrientations[2] = <<joint3.rotateX, joint3.rotateY, joint3.rotateZ>>;
float $distances[];
$distances[0] = mag(<<object.translateX - joint1.translateX, object.translateY - joint1.translateY, object.translateZ - joint1.translateZ>>);
$distances[1] = mag(<<object.translateX - joint2.translateX, object.translateY - joint2.translateY, object.translateZ - joint2.translateZ>>);
$distances[2] = mag(<<object.translateX - joint3.translateX, object.translateY - joint3.translateY, object.translateZ - joint3.translateZ>>);
float $weights[] = {1/$distances[0], 1/$distances[1], 1/$distances[2]};
float $normalizedWeights[] = normalizeweights($weights);
vector $blendedOrientation = $jointOrientations[0] * $normalizedWeights[0] +
$jointOrientations[1] * $normalizedWeights[1] +
$jointOrientations[2] * $normalizedWeights[2];
object.rotateX = $blendedOrientation.x;
object.rotateY = $blendedOrientation.y;
object.rotateZ = $blendedOrientation.z;
NotBool
Just checks to see if something is false
Syntax: x != y
Example:
value = 1 # true
result = !value
# result would be 0 (false)
OrBool
Logical “or” comparison node
Syntax: x || y
Example:
if (control1.active || control2.active) {
visibility = 1;
} else {
visibility = 0;
}
Power
Raises a base number to a specified exponent
Syntax: power(base,exponent)
Functionality:
Takes two inputs: the base and the exponent
Returns the result of base raised to the power of exponent
Example:
float $base = 2;
float $exponent = 3;
float $result = power($base, $exponent);
// $result would be 8 (2^3 = 2 * 2 * 2 = 8)
Practical - creates an object that scales down exponentially as it moves away from a target
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
float $distance = mag($targetPos - $objectPos);
float $maxDistance = 10;
float $minScale = 0.1;
float $falloffExponent = 2;
float $scaleFactor = power(1 - clamp($distance / $maxDistance, 0, 1), $falloffExponent);
float $finalScale = $minScale + (1 - $minScale) * $scaleFactor;
object.scaleX = $finalScale;
object.scaleY = $finalScale;
object.scaleZ = $finalScale;
Advanced Practical - creates a smooth easing-in-and-out animation using a custom power-based easing function
float $time = `currentTime -q`;
float $startTime = 1;
float $endTime = 120;
float $duration = $endTime - $startTime;
float $normalizedTime = ($time - $startTime) / $duration;
float $easedTime = power($normalizedTime, 3) * (1 - $normalizedTime) * 3 + power($normalizedTime, 3);
float $startValue = 0;
float $endValue = 10;
float $animatedValue = $startValue + ($endValue - $startValue) * $easedTime;
object.translateY = $animatedValue;
QuaternionFrom
Converts an Euler Rotation or a rotation matrix into a quaternion. Useful when dealing with complex rotation scenarios, continuous rotations, or when implementing smooth interpolations between orientations.
Variants:
QuaternionFromRotation (Euler angles)
QuaternionFromMatrix (from a rotation matrix)
Syntaxes:
quat(rotation, rotation order) // for Euler
quat(matrix) for matrices
Functionality:
Takes rotation data as input (Euler with rotation order or a rotation matrix)
Returns a quaternion
Provides a gimbal-lock free representation of rotation
Example
vector $eulerRotation = <<30, 45, 60>>; // In degrees
string $rotOrder = "xyz";
vector $quaternion = quat(deg_to_rad($eulerRotation), $rotOrder);
// $quaternion will be a 4D vector representing the quaternion
Practical - Create a smooth interpolation between two rotations using quaternions
vector $startRotation = <<object1.rotateX, object1.rotateY, object1.rotateZ>>;
vector $endRotation = <<object2.rotateX, object2.rotateY, object2.rotateZ>>;
vector $startQuat = quat(deg_to_rad($startRotation), "xyz");
vector $endQuat = quat(deg_to_rad($endRotation), "xyz");
float $blendFactor = control.blendAttr; // Assume this ranges from 0 to 1
vector $resultQuat = slerp($startQuat, $endQuat, $blendFactor);
vector $finalRotation = rad_to_deg(rot($resultQuat, "xyz"));
object.rotateX = $finalRotation.x;
object.rotateY = $finalRotation.y;
object.rotateZ = $finalRotation.z;
Advanced Practical - Create a weighted blend between three different orientation targets using quaternions
vector $target1Rot = <<target1.rotateX, target1.rotateY, target1.rotateZ>>;
vector $target2Rot = <<target2.rotateX, target2.rotateY, target2.rotateZ>>;
vector $target3Rot = <<target3.rotateX, target3.rotateY, target3.rotateZ>>;
vector $quat1 = quat(deg_to_rad($target1Rot), "xyz");
vector $quat2 = quat(deg_to_rad($target2Rot), "xyz");
vector $quat3 = quat(deg_to_rad($target3Rot), "xyz");
float $weight1 = control.weight1;
float $weight2 = control.weight2;
float $weight3 = 1 - $weight1 - $weight2;
vector $blendQuat1 = slerp($quat1, $quat2, $weight2 / ($weight1 + $weight2));
vector $finalQuat = slerp($blendQuat1, $quat3, $weight3);
vector $finalRotation = rad_to_deg(rot($finalQuat, "xyz"));
object.rotateX = $finalRotation.x;
object.rotateY = $finalRotation.y;
object.rotateZ = $finalRotation.z;
Remap
Scales a value from one range to another, maintaining the relative position of the value within the range.
Variants:
Remap (float)
RemapInt (Int)
RemapAngle (Angle)
Syntax: remap(value, oldMin, oldMax, newMin, newMax)
Functionality:
Takes five inputs, the value to remap, the old range (min and max), the new range (min and max)
Returns the input value scaled to the new range
Performs linear interpolation between the ranges
Example:
float $input = 5;
float $result = remap($input, 0, 10, -1, 1);
// $result will be 0 (5 is halfway between 0 and 10, so it maps to halfway between -1 and 1)
Practical - create a foot roll system where a single control attribute drives multiple joint rotations with appropriate ranges
float $footRoll = foot_ctrl.roll; // Assume this ranges from -1 to 1
// Heel rotation (active from -1 to 0)
heel.rotateX = remap($footRoll, -1, 0, -45, 0);
// Ball rotation (active from 0 to 0.5)
ball.rotateX = remap($footRoll, 0, 0.5, 0, 60);
// Toe rotation (active from 0.5 to 1)
toe.rotateX = remap($footRoll, 0.5, 1, 0, 30);
Advanced Practical - Create a dynamic falloff effect where objects scale based on their distance from an effector.
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $effectorPos = <<effector.translateX, effector.translateY, effector.translateZ>>;
float $distance = mag($objectPos - $effectorPos);
float $innerRadius = effector.innerRadius;
float $outerRadius = effector.outerRadius;
float $falloff = 1 - remap($distance, $innerRadius, $outerRadius, 0, 1);
$falloff = clamp($falloff, 0, 1);
object.scaleX = lerp(1, 2, $falloff);
object.scaleY = lerp(1, 2, $falloff);
object.scaleZ = lerp(1, 2, $falloff);
Round
Rounds a floating point value to the nearest integer, with anything above 0.5 going up and anything below 0.5 going down
Variants:
Round (float)
RoundAngle (Angle)
Syntax: round(value)
Functionality:
Takes a floating point input
Returns the nearest integer value
Example:
float $value1 = 3.2;
float $value2 = 3.7;
float $result1 = round($value1); // result1 will be 3
float $result2 = round($value2); // result2 will be 4
RotateVectorBy
Rotates a vector by a specified rotation (euler angles, quaternion or matrix)
Variants:
RotateVectorByRotation (Euler)
RotateVectorByQuaternion (Quaternion)
RotateVectorByMatrix (Rotation Matrix)
Syntax:
rotate(vector,rotation,rotationOrder) //Euler
rotate(vector,quaternion) //Quaternion
rotate(vector,matrix) //Matricies
Functionality
Takes a vector and a rotation as an input
Returns the rotated vector
Allows precise control over vector orientation
Example:
vector $inputVector = <<1, 0, 0>>; // Vector pointing along X-axis
vector $rotation = <<0, 90, 0>>; // 90 degrees around Y-axis
vector $rotatedVector = rotate($inputVector, deg_to_rad($rotation), "xyz");
// $rotatedVector will be approximately <<0, 0, -1>>
Practical - Simple aim constraint with an up vector
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $upVector = <<0, 1, 0>>; // World up vector
vector $aimVector = normalize($targetPos - $objectPos);
vector $rightVector = normalize(cross($aimVector, $upVector));
vector $newUpVector = cross($rightVector, $aimVector);
vector $forwardAxis = <<1, 0, 0>>; // Local X-axis as forward
vector $upAxis = <<0, 1, 0>>; // Local Y-axis as up
vector $rotationQuat = quatFromTwoVectors($forwardAxis, $aimVector) * quatFromTwoVectors($upAxis, $newUpVector);
vector $rotatedForward = rotate($forwardAxis, $rotationQuat);
vector $rotatedUp = rotate($upAxis, $rotationQuat);
vector $finalRotation = rot(rotationFromTwoVectors($rotatedForward, $rotatedUp), "xyz");
object.rotateX = rad_to_deg($finalRotation.x);
object.rotateY = rad_to_deg($finalRotation.y);
object.rotateZ = rad_to_deg($finalRotation.z);
RotationFrom
Converts a Quaternion or Matrix into Euler. Its useful in scenarios where you need to convert between different rotation representations, implement space switching systems, or analyze the orientation of objects in complex hierarchies.
Variants:
RotationFromMatrix (converts a matrix to euler angles)
RotationFromQuaternion (converts a quaternion to euler angles)
Syntax:
rot(matrix, rotationOrder)
rot(quaternion, rotationOrder)
Functionality:
Takes a matrix or quaternion as input
Returns a vector representing euler angles (in radians)
Allows specifying the desired rotation order
Example:
vector $matrix[4] = `object.worldMatrix`;
vector $eulerAngles = rot($matrix, "xyz");
// $eulerAngles will contain the rotation in radians
Practical - Extracts the rotation from the target’s world matrix and applies it to the object in a simple orientation matching system:
vector $targetMatrix[4] = `target.worldMatrix`;
vector $targetRotation = rot($targetMatrix, "xyz");
// Convert radians to degrees for Maya's rotate attributes
object.rotateX = rad_to_deg($targetRotation.x);
object.rotateY = rad_to_deg($targetRotation.y);
object.rotateZ = rad_to_deg($targetRotation.z);
Practical Advanced - creating a space switching setup using matrix multiplication and rotation extraction
vector $localMatrix[4] = `object.matrix`;
vector $parentWorldMatrix[4] = `parent.worldMatrix`;
vector $worldMatrix[4] = $parentWorldMatrix * $localMatrix;
int $spaceSwitch = control.spaceSwitch; // Assume 0 for world, 1 for local
vector $resultMatrix[4];
if ($spaceSwitch == 0) $resultMatrix = $worldMatrix;
else $resultMatrix = $localMatrix;
vector $resultRotation = rot($resultMatrix, "xyz");
control.rotateX = rad_to_deg($resultRotation.x);
control.rotateY = rad_to_deg($resultRotation.y);
control.rotateZ = rad_to_deg($resultRotation.z);
ScaleFromMatrix
Extracts the scale components from a transform matrix. This is useful where you need to understand or compensate for scaling effects in a transformation hierarchy. It’s a component in making scale-aware systems, maintaining consistent sizing across hierarchies, or implementing advanced constraint systems that need to account for parent scaling.
Syntax: scale(matrix)
Functionality:
Takes a 4x4 transformation matrix as input
Returns a vector representing the X, Y, and Z scale
Extracts scale even if the matrix includes rotation and scale
Example:
vector $localMatrix[4] = `object.matrix`;
vector $parentWorldMatrix[4] = `parent.worldMatrix`;
vector $worldMatrix[4] = $parentWorldMatrix * $localMatrix;
int $spaceSwitch = control.spaceSwitch; // Assume 0 for world, 1 for local
vector $resultMatrix[4];
if ($spaceSwitch == 0) $resultMatrix = $worldMatrix;
else $resultMatrix = $localMatrix;
vector $resultRotation = rot($resultMatrix, "xyz");
control.rotateX = rad_to_deg($resultRotation.x);
control.rotateY = rad_to_deg($resultRotation.y);
control.rotateZ = rad_to_deg($resultRotation.z);
Practical - a scale compensation system for a child object:
vector $parentMatrix[4] = `parent.worldMatrix`;
vector $parentScale = scale($parentMatrix);
child.scaleX = 1 / $parentScale.x;
child.scaleY = 1 / $parentScale.y;
child.scaleZ = 1 / $parentScale.z;
Advanced Practical - Creating a world-space scale indicator, taking into account all parent transformations:
vector $localMatrix[4] = `object.matrix`;
vector $parentWorldMatrix[4] = `object.parentMatrix`;
vector $worldMatrix[4] = $parentWorldMatrix * $localMatrix;
vector $worldScale = scale($worldMatrix);
scaleIndicator.scaleX = $worldScale.x;
scaleIndicator.scaleY = $worldScale.y;
scaleIndicator.scaleZ = $worldScale.z;
Select
Chooses between two values based on a conditional input. Its useful for implementing logic-based systems, creating toggles between different states of behaviors, and designing more complex decision-making structures in your rigs.
Variants:
Select (float)
SelectInt(Int)
SelectAngle (Angle)
SelectVector (Vector)
SelectMatrix (Matrix)
Syntax: select(value1, value2, condition)
Functionality:
Takes three inputs: two values and a condition
If the condition is true (non-zero) it returns a value 1
If the condition is false (zero) it returns value 2
Example:
float $control = node.control; // Assume this is a 0 or 1 value
float $value1 = 5;
float $value2 = 10;
float $result = select($value1, $value2, $control);
// If $control is 1, $result will be 5
// If $control is 0, $result will be 10
Practical - Switch the Y-rotation of the driven object between two different drivers:
float $switch = control.switch; // Assume this is a 0 or 1 value
float $rotation1 = driver1.rotateY;
float $rotation2 = driver2.rotateY;
driven.rotateY = select($rotation1, $rotation2, $switch);
Advanced Practical - Creates a system where an object moves between four positions based on a single state control:
float $state = control.state; // Assume this ranges from 0 to 3
vector $pos1 = <<0, 0, 0>>;
vector $pos2 = <<10, 0, 0>>;
vector $pos3 = <<0, 10, 0>>;
vector $pos4 = <<0, 0, 10>>;
vector $selectedPos = select(
select(
select($pos1, $pos2, $state > 0),
$pos3,
$state > 1
),
$pos4,
$state > 2
);
object.translateX = $selectedPos.x;
object.translateY = $selectedPos.y;
object.translateZ = $selectedPos.z;
SelectArray
Chooses between two arrays of values based on a conditional input - essentially the same as select but dealing with arrays. This is useful when you need to switch between multiple related values simultaneously. It allows for cleaner expressions when dealint with data sets, such as poses, transformations, or any multi-attribute states.
Variants:
SelectArray (float array)
SelectIntArray (int array)
SelectVectorArray (vector array)
SelectMatrixArray (matrix array)
Syntax: selectarray(array1,array2,condition)
Functionality:
Takes three inputs: two arrays of the same type and length, and a condition
If the condition is true (non-zero) it returns array 1
If the condition is false (zero), it returns array 2
Example:
float $control = node.control; // Assume this is a 0 or 1 value
float $array1[] = {1, 2, 3, 4};
float $array2[] = {5, 6, 7, 8};
float $result[] = selectarray($array1, $array2, $control);
// If $control is 1, $result will be {1, 2, 3, 4}
// If $control is 0, $result will be {5, 6, 7, 8}
Practical - Switches the rotation of three joints between two predefined poses based on the switch value
float $switch = control.switch; // Assume this is a 0 or 1 value
vector $pose1[] = {<<0,0,0>>, <<30,0,0>>, <<-30,0,0>>};
vector $pose2[] = {<<0,30,0>>, <<0,-30,0>>, <<0,0,30>>};
vector $selectedPose[] = selectarray($pose1, $pose2, $switch);
joint1.rotate = $selectedPose[0];
joint2.rotate = $selectedPose[1];
joint3.rotate = $selectedPose[2];
Advanced Practical - Creates an FK/IK switch system for a chain of joints, switching between FK and IK positions based on a blend attribute
float $ikFkBlend = control.ikFkBlend; // Assume this ranges from 0 to 1
vector $fkPositions[] = {<<fk1.translateX, fk1.translateY, fk1.translateZ>>,
<<fk2.translateX, fk2.translateY, fk2.translateZ>>,
<<fk3.translateX, fk3.translateY, fk3.translateZ>>};
vector $ikPositions[] = {<<ik1.translateX, ik1.translateY, ik1.translateZ>>,
<<ik2.translateX, ik2.translateY, ik2.translateZ>>,
<<ik3.translateX, ik3.translateY, ik3.translateZ>>};
vector $blendedPositions[] = selectarray($ikPositions, $fkPositions, $ikFkBlend > 0.5);
for ($i = 0; $i < size($blendedPositions); $i++) {
setAttr ("joint" + ($i+1) + ".translateX") $blendedPositions[$i].x;
setAttr ("joint" + ($i+1) + ".translateY") $blendedPositions[$i].y;
setAttr ("joint" + ($i+1) + ".translateZ") $blendedPositions[$i].z;
}
SinAngle
Calculates the sine of an input angle. Its useful in generating wave-like behaviors, circular movements, and in solving various trigonometric problems.
Syntax: sin(angle)
Functionality:
Takes an angle as input (in radians)
Returns the sine of that angle (a value between -1 and 1)
Works with float values
Example:
float $angleInDegrees = 30;
float $angleInRadians = deg_to_rad($angleInDegrees);
float $result = sin($angleInRadians);
// $result will be approximately 0.5
Practical - Creates a smooth, sinusoidal up-and-down motion for an object
float $time = `currentTime -q`;
float $frequency = 0.1; // Controls how fast the oscillation occurs
float $amplitude = 5; // Controls the height of the oscillation
float $yPosition = $amplitude * sin($time * $frequency);
object.translateY = $yPosition;
Advanced Practical - Creates a spiral motion that combines circular movement in the XZ plane with a steady upward motion:
float $time = `currentTime -q`;
float $speed = 0.1;
float $radius = 5;
float $height = 0.1;
float $angle = $time * $speed;
float $xPosition = $radius * sin($angle);
float $zPosition = $radius * cos($angle);
float $yPosition = $height * $angle;
object.translateX = $xPosition;
object.translateY = $yPosition;
object.translateZ = $zPosition;
SlerpQuaternion
Performs Spherical Linear Interpolation between two quaternions. Useful where smooth and predictable rotation interpolations are crucial. It blends between orientations in a way that avoids the problems associated with linear interpolation of euler angles, such as gimbal lock and non-uniform angular velocities.
Syntax: slerp(quaternion1,quaternion2,weight)
Functionality:
Takes two quaternions and an interpolation weight as input
Returns a quaternion that represents a smooth interpolation between the two input quaternions
The weight determines the blend between the two quaternions.
Example:
vector $quat1 = <<0, 0, 0, 1>>; // Identity quaternion
vector $quat2 = <<0, 0.7071, 0, 0.7071>>; // 90-degree rotation around Y
float $blend = 0.5; // Halfway between the two rotations
vector $resultQuat = slerp($quat1, $quat2, $blend);
Practical - Creates a smooth rotation from one object’s orientation to another as the blend attribute goes from 0 to 1
vector $startRot = <<object1.rotateX, object1.rotateY, object1.rotateZ>>;
vector $endRot = <<object2.rotateX, object2.rotateY, object2.rotateZ>>;
vector $startQuat = quat(deg_to_rad($startRot), "xyz");
vector $endQuat = quat(deg_to_rad($endRot), "xyz");
float $blend = control.blendAttr; // Assume this is a 0-1 slider
vector $interpolatedQuat = slerp($startQuat, $endQuat, $blend);
// Convert back to Euler angles for Maya's rotate attributes
vector $resultRotation = rad_to_deg(rot($interpolatedQuat, "xyz"));
object.rotateX = $resultRotation.x;
object.rotateY = $resultRotation.y;
object.rotateZ = $resultRotation.z;
Advanced Practical - Creates a weighted blend between three different orientation targets using SLERP:
vector $target1Rot = <<target1.rotateX, target1.rotateY, target1.rotateZ>>;
vector $target2Rot = <<target2.rotateX, target2.rotateY, target2.rotateZ>>;
vector $target3Rot = <<target3.rotateX, target3.rotateY, target3.rotateZ>>;
vector $quat1 = quat(deg_to_rad($target1Rot), "xyz");
vector $quat2 = quat(deg_to_rad($target2Rot), "xyz");
vector $quat3 = quat(deg_to_rad($target3Rot), "xyz");
float $weight1 = control.weight1;
float $weight2 = control.weight2;
float $weight3 = 1 - $weight1 - $weight2;
vector $blendQuat1 = slerp($quat1, $quat2, $weight2 / ($weight1 + $weight2));
vector $finalQuat = slerp($blendQuat1, $quat3, $weight3);
vector $finalRotation = rad_to_deg(rot($finalQuat, "xyz"));
object.rotateX = $finalRotation.x;
object.rotateY = $finalRotation.y;
object.rotateZ = $finalRotation.z;
SmoothStep
Performs smooth Hermite interpolation between 0 and 1, creating an S-shaped curve. Useful for creating natural-feeling transitions and easing effects. It adds an organic feeling to linear inputs, making controls and animations feel less mechanical and more fluid. Often used in user interface elements, blend shapes, constraint weights, and any scenario where a smooth, S-curved transition between two states is desirable.
Syntax: smoothstep(x)
Functionality:
Takes a value between 0 and 1 as an input
Returns a smoothly interpolated value between 0 and 1
Provides an S-shaped curve that starts slow, accelerates in the middle, and slows down at the end.
Example:
float $input = 0.5;
float $result = smoothstep($input);
// $result will be 0.5, but with a different rate of change compared to the input
Practical - Creates a visibility fade that starts and ends gradually, with a faster transition in the middle
float $fadeControl = control.fade; // Assume this ranges from 0 to 1
float $smoothFade = smoothstep($fadeControl);
object.visibility = $smoothFade;
Advanced Practical - Creates a smooth animation that eases in and out over the specified duration:
float $time = `currentTime -q`;
float $duration = 120; // Animation duration in frames
float $normalizedTime = clamp($time / $duration, 0, 1);
float $smoothProgress = smoothstep($normalizedTime);
float $startValue = 0;
float $endValue = 10;
float $animatedValue = $startValue + ($endValue - $startValue) * $smoothProgress;
object.translateY = $animatedValue;
Subtract
Subtracts one value from another
Syntax: x - y
Example:
float $value1 = 10;
float $value2 = 3;
float $result = $value1 - $value2;
// $result will be 7
Practical - a simple follow behavior with an offset
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $offsetVector = <<offset.translateX, offset.translateY, offset.translateZ>>;
vector $followPos = $targetPos - $offsetVector;
object.translateX = $followPos.x;
object.translateY = $followPos.y;
object.translateZ = $followPos.z;
Sum
Used to add multiple values (more than two) stored in an array’
Syntax: sum([x,y,z,…])
Example:
float $values[] = {1, 2, 3, 4, 5};
float $result = sum($values);
// $result will be 15
Practical - multi-influence blending system from multiple targets
float $weights[] = {control1.weight, control2.weight, control3.weight};
float $totalWeight = sum($weights);
if ($totalWeight > 0) {
vector $targetPos1 = <<target1.translateX, target1.translateY, target1.translateZ>>;
vector $targetPos2 = <<target2.translateX, target2.translateY, target2.translateZ>>;
vector $targetPos3 = <<target3.translateX, target3.translateY, target3.translateZ>>;
vector $blendedPos = ($targetPos1 * $weights[0] + $targetPos2 * $weights[1] + $targetPos3 * $weights[2]) / $totalWeight;
object.translateX = $blendedPos.x;
object.translateY = $blendedPos.y;
object.translateZ = $blendedPos.z;
}
TanAngle
Calculates the tangent of an input angle. It is used less frequently but has applications in creating certain types of motion curves, solving angular problems, and designing specialized mathematical relationships to rigs. Its tendency to produce extreme values near certain angles can be either a challenge or a feature, depending on the desired behavior.
Syntax: tan(angle)
Functionality:
Takes an angle as input (in radians)
Returns the tangent of that angle
Works with float values
Example:
float $time = `currentTime -q`;
float $duration = 120; // Animation duration in frames
float $normalizedTime = clamp($time / $duration, 0, 1);
float $smoothProgress = smoothstep($normalizedTime);
float $startValue = 0;
float $endValue = 10;
float $animatedValue = $startValue + ($endValue - $startValue) * $smoothProgress;
object.translateY = $animatedValue;
Practical - Creates a control that rotates faster as it approaches 90°, due to the nature of the tangent function:
float $inputRotation = joint.rotateX; // Assume this is in degrees
float $inputRadians = deg_to_rad($inputRotation);
float $exaggeratedRotation = rad_to_deg(atan(tan($inputRadians) * 2));
control.rotateX = $exaggeratedRotation;
Advanced Practical - Creates a rotation behavior that snaps to the nearest 15° increment, with a smooth transition between snaps:
float $inputRotation = joint.rotateX; // Assume this is in degrees
float $inputRadians = deg_to_rad($inputRotation);
float $exaggeratedRotation = rad_to_deg(atan(tan($inputRadians) * 2));
control.rotateX = $exaggeratedRotation;
TranslationFromMatrix
Extracts the translation component from a transformation matrix, making it possible to create rigs that can adapt to different coordinate spaces and parent-child relationships. This fucntion is particularly useful in creating advanced constraints, space switching systems and any rig component that needs to understand and respond to the positions of the objects in various coordinate spaces.
Syntax: translation(matrix)
Functionality:
Takes a 4x4 transformation matrix as input
Returns a vector representing the X, Y, and Z translation components
Extracts translation even if the matrix includes rotation and scale
Example:
vector $matrix[4] = `object.worldMatrix`;
vector $position = translation($matrix);
// $position will contain the X, Y, and Z world space position
Practical - Makes an object follow the world space position of a target:
vector $targetMatrix[4] = `target.worldMatrix`;
vector $targetPosition = translation($targetMatrix);
object.translateX = $targetPosition.x;
object.translateY = $targetPosition.y;
object.translateZ = $targetPosition.z;
Advanced Practical - Offsets an object’s position in its local space, regardless of parent transformations
vector $objectMatrix[4] = `object.matrix`;
vector $parentWorldMatrix[4] = `object.parentMatrix`;
vector $offsetVector = <<5, 0, 0>>; // 5 units offset in X
vector $localOffset = inverse($parentWorldMatrix) * $offsetVector;
vector $currentPosition = translation($objectMatrix);
vector $newPosition = $currentPosition + $localOffset;
object.translateX = $newPosition.x;
object.translateY = $newPosition.y;
object.translateZ = $newPosition.z;
TwistFrom
Extracts the twist rotation around a specific axis from a rotation or matrix output. Allows riggers to isolate and manipulate specific aspects of rotation, which is crucial for creating natural-looking deformations in areas like arms, legs, and spines. By extracting and redistributing twist, riggers can create more nuanced and anatomically correct motion in their character rigs.
Variants:
TwistFromRotation (Extracts twist from euler angles)
TwistFromMatrix (Extracts twist from a transformation matrix)
Syntax:
twist(rotation, axis, rotationOrder) // for euler angles
twist(matrix, axis) // for matrices
Functionality:
Takes a rotation (euler angles or matrix) as input
Requires specification of the twist axis (0 for X, 1 for Y, 2 for Z)
Returns the angle of twist around the specified axis
For Euler angles, also requires the rotation order
Example:
vector $rotation = <<30, 45, 60>>; // Rotation in degrees
float $twistAngle = twist(deg_to_rad($rotation), 1, "xyz"); // Extract twist around Y-axis
// $twistAngle will be in radians
Practical - Extracts the twist of the hand relative to the upper arm and applies half of it to the forearm
vector $upperArmMatrix[4] = `upperArm.worldMatrix`;
vector $handMatrix[4] = `hand.worldMatrix`;
float $twistAngle = twist($handMatrix, 0); // Assuming X is the twist axis
// Apply a portion of the twist to the forearm
forearm.rotateX = rad_to_deg($twistAngle * 0.5); // 50% of the twist
Advanced Practical - Creates a multi-segment twist distribution for the spine evenly across multiple joints:
vector $hipsMatrix[4] = `hips.worldMatrix`;
vector $chestMatrix[4] = `chest.worldMatrix`;
float $totalTwist = twist($chestMatrix, 1); // Assuming Y is up
int $numSegments = 5;
float $twistPerSegment = $totalTwist / $numSegments;
for ($i = 1; $i <= $numSegments; $i++) {
float $segmentTwist = $twistPerSegment * $i;
setAttr ("spineJoint" + $i + ".rotateY") rad_to_deg($segmentTwist);
}
VectorLength
Caluculates the magnitude (length) of a vector
Example:
vector $myVector = <<3, 4, 0>>;
float $magnitude = length($myVector);
// $magnitude will be 5
In rigging you can
Calculate the distance between objects
Normalize vectors
Implement scale based behaviors
create radius based effects or constraints
Practical - Create a distance based scaling effect, where the scale decreases as the distance increases
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $difference = $targetPos - $objectPos;
float $distance = length($difference);
float $maxDistance = 10;
float $scale = 1 - clamp($distance / $maxDistance, 0, 1);
object.scaleX = $scale;
object.scaleY = $scale;
object.scaleZ = $scale;
Advanced Practical - this creates a simple stretch effect for a middle joint based on a the overall length of a three joint chain
vector $startPos = <<joint1.translateX, joint1.translateY, joint1.translateZ>>;
vector $endPos = <<joint3.translateX, joint3.translateY, joint3.translateZ>>;
float $currentLength = length($endPos - $startPos);
float $originalLength = joint2.originalLength; // Assume we stored this somewhere
float $stretchFactor = $currentLength / $originalLength;
joint2.scaleX = $stretchFactor;
VectorLengthSquared
Calculates the sqared magnitude of a given vector without taking the square root. This is useful in situations where you need to work with distance based effects, but don’t need the exact linear distance. By avoiding square root calculations, you can improve performance in rigs that involve many distance based calculations.
Syntax: lengthsquared(vector)
Functionality:
Takes a vector as an input
Returns a float representing the squared length of the vector
Calculates the sum of the squares of the vector components
Example:
vector $myVector = <<3, 4, 0>>;
float $magnitudeSquared = lengthsquared($myVector);
// $magnitudeSquared will be 25
Practical - Toggles an object’s visibility based on its proximity to a target, using squared distance for efficiency
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
vector $targetPos = <<target.translateX, target.translateY, target.translateZ>>;
vector $difference = $targetPos - $objectPos;
float $distanceSquared = lengthsquared($difference);
float $thresholdSquared = 100; // 10 units squared
if ($distanceSquared < $thresholdSquared) {
object.visibility = 1;
} else {
object.visibility = 0;
}
Advanced Practical - Creates a scaling effect that falls off based on distance from a center point, using squared distances for better performance
vector $centerPos = <<center.translateX, center.translateY, center.translateZ>>;
vector $objectPos = <<object.translateX, object.translateY, object.translateZ>>;
float $maxDistanceSquared = 400; // 20 units squared
float $distanceSquared = lengthsquared($objectPos - $centerPos);
float $falloff = 1 - clamp($distanceSquared / $maxDistanceSquared, 0, 1);
object.scaleX = lerp(1, 2, $falloff);
object.scaleY = lerp(1, 2, $falloff);
object.scaleZ = lerp(1, 2, $falloff);
WeightedAverage
Calculates the average of a set of values, with each value having its own weight. It allows sophisticated multi-target constraints, smooth transitions between multiple states, and can be used to create dynamic, responsive rigs that adapt to multiple influences.
Variants:
WeightedAverage (float)
WeightedAverageAngle (angle)
WeightedAverageInt (integer)
WeightedAverageVector (vector)
WeightedAverageMatrix (matrix)
Syntax: weightedaverage(value1, weight1, value2, weight2, …)
Functionality:
Takes pairs of values and weights
Returns the weighted average of the input values
Calculates (value1 * weight1 + value2 * weight2 + …) / (weight1 + weight2 + …)
Example:
float $value1 = 10;
float $weight1 = 2;
float $value2 = 20;
float $weight2 = 1;
float $result = weightedaverage($value1, $weight1, $value2, $weight2);
// $result will be 13.333... (40 / 3)
Practical - Creates a position that’s a weighted blend of three target positions:
vector $pos1 = <<target1.translateX, target1.translateY, target1.translateZ>>;
vector $pos2 = <<target2.translateX, target2.translateY, target2.translateZ>>;
vector $pos3 = <<target3.translateX, target3.translateY, target3.translateZ>>;
float $weight1 = control.weight1;
float $weight2 = control.weight2;
float $weight3 = control.weight3;
vector $blendedPos = weightedaverage($pos1, $weight1, $pos2, $weight2, $pos3, $weight3);
object.translateX = $blendedPos.x;
object.translateY = $blendedPos.y;
object.translateZ = $blendedPos.z;
Advanced - A dynamic multi-joint orient constraint, where the influcence of each target is based on its distance from the object.
vector $targetRot1 = <<target1.rotateX, target1.rotateY, target1.rotateZ>>;
vector $targetRot2 = <<target2.rotateX, target2.rotateY, target2.rotateZ>>;
vector $targetRot3 = <<target3.rotateX, target3.rotateY, target3.rotateZ>>;
float $distance1 = mag(<<object.translateX - target1.translateX,
object.translateY - target1.translateY,
object.translateZ - target1.translateZ>>);
float $distance2 = mag(<<object.translateX - target2.translateX,
object.translateY - target2.translateY,
object.translateZ - target2.translateZ>>);
float $distance3 = mag(<<object.translateX - target3.translateX,
object.translateY - target3.translateY,
object.translateZ - target3.translateZ>>);
float $weight1 = 1 / ($distance1 * $distance1);
float $weight2 = 1 / ($distance2 * $distance2);
float $weight3 = 1 / ($distance3 * $distance3);
vector $blendedRot = weightedaverage($targetRot1, $weight1, $targetRot2, $weight2, $targetRot3, $weight3);
object.rotateX = $blendedRot.x;
object.rotateY = $blendedRot.y;
object.rotateZ = $blendedRot.z;
XorBool
Performs a logical XOR (exclusive OR) operation between two boolean values. It is useful in rigging scenarios where you need to create mutually exclusive behaviors or states. Its handy when you need to trigger an action or state change based on the difference between two conditions, rather than their similarity. It performs a logical XOR (exclusive or) operation between two boolean values.
Variants:
XorBool (for bools)
XorInt (for int values, treating non zero as true)
Syntax: x ^ y (where ‘x’ and ‘y’ are boolean or int values to be compared)
Functionality:
Takes two inputs
Returns true (1) if exactly one of the inputs is true, false (0) otherwise
Truth table:
false XOR false = false
false XOR true = true
true XOR false = true
true XOR true = false
Example:
int $value1 = control1.attribute > 0;
int $value2 = control2.attribute > 0;
int $result = $value1 ^ $value2;
Practical - visibility toggle that’s on only when exactly one of the two controls is active:
int $control1Active = control1.active;
int $control2Active = control2.active;
object.visibility = $control1Active ^ $control2Active;
Advanced Practical - two-switch state machine, where three objects are exclusively visible based on the combination of two switches
int $switch1 = control1.switch;
int $switch2 = control2.switch;
int $state1 = !$switch1 && !$switch2;
int $state2 = $switch1 ^ $switch2;
int $state3 = $switch1 && $switch2;
object1.visibility = $state1;
object2.visibility = $state2;
object3.visibility = $state3;