Implementing a custom transform


When implementing a custom transform, you need to build the transform, configure its attributes, and so on.

Simple versus complex custom transform

Transforms have input and output attributes that are used to process and store the transformation information. The simplest type of custom transform is one that does not introduce any new attributes that can affect the transformation matrix. For example, the transform may limit the translate attribute to a certain world space volume using a predetermined calculation.

A more complex custom transform is one that introduces one or more attributes that affects the transformation matrix. For example, the transform may introduce a new type of rotation parameter that is taken and integrated into the final calculation of the transformation matrix. In this case, there are two types of rotation that the custom transform understands and the original rotation attribute (supplied by MPxTransform) is left untouched in the calculations of the new rotation.

World space attributes

Instancing an object saves system memory, and is useful to display an object multiple times while maintaining its exact properties. However, instancing an object opens up some interesting coding challenges since there are multiple paths to the same object. Maya handles this situation with array attributes that are classified as world space. An array is necessary for handling multiple paths.

A world space attribute is one that is dependent on the transformations of an object's parent(s) in addition to its own transformation. Marking an attribute as world space will cause the attribute to be recalculated (if it is requested) if one of its parents is transformed. World space attributes are arrays that handle the instancing scenario described above. An example of a world space attribute is worldMatrix. Configuring an attribute as an array and making it world space is done in the initialize() method of the custom transform node with the MFnAttribute class.

Given that world space attributes are arrays, the MArrayDataBuilder class can be used to create the information that will be placed in the attribute. It would then be necessary to configure the attribute with the MFnAttribute::setUsesArrayDataBuilder() in the initialize() method.

Affects world space attribute

An attribute marked as affects world space causes world space attributes to be recalculated (if world space is being requested) on the given node and the children DAGs of the node. There is no array requirement for this type of attribute. An example of an affects world space attribute is the translate attribute that is found on DAG nodes. Setting an attribute as world space is done in the initialize() method of the custom transform node with the MFnAttribute class.

Transform Limits

There are special attributes on the transform (and custom transform) node that are used for clamping values of associated attributes. Transform limits are available for translate, rotate and scale. Each operation includes three additional attributes: enabled, minimum and maximum. Custom transforms modifying these attributes can implement a node that restricts translate, rotate and scale to parts of world space. This is a simple implementation of a custom transform. A more complex version of this custom transform can change the minimum and maximum based on an external attribute input such as distance to another object.

Balancing a transform

In the Maya implementation of a transform node, it is possible to keep the transformation matrix the same while modifying the pivots (rotate and scale) and rotation order. This is referred to as balancing the transform. Balance is a parameter that is included in methods related to modifying pivot and rotation order information. The virtuals provided for MPxTransform and MPxTransformationMatrix will handle balancing correctly if the custom transform does not attempt to change the standard way that Maya handles pivots.

Validating and setting

Maya uses a standard validate and set mechanism for updating the attribute values of custom transforms. You are required to use this mechanism for any attributes that affect the matrix. The MPxTransform::mustCallValidateAndSet() must be called in the initialize() method for all attributes that affect the matrix of the transform. It ensures that the matrix is properly calculated when the attribute is changed and that the MPxTransform::validateAndSet() method is called for this attribute.

Returning the matrix

As a part of the DG updating process, Maya will ask a custom transform for its transformation matrix. This request goes directly to the MPxTransform::getMatrix() call. This virtual method in turn calls MPxTransformationMatrix::asMatrix(). It is very important to implement these two methods so that the custom transform will be returned to Maya.