Creating Your First Deformer Node

Now that we have gone through the exercise of creating some simple nodes, it’s time to create a more complex node. To this end a deformer would be a good example, as it’s a fairly common use case.

In the Node Description Editor, please click on File -> New Node to start the creation process for a new node:

../../_images/ext_omnigraph_deforming_text_03_08.png

Fill in the node details as follows:

../../_images/ext_omnigraph_deforming_text_04_01.png ../../_images/ext_omnigraph_deforming_text_04_02.png ../../_images/ext_omnigraph_deforming_text_04_03.png

Note that for the in_points attribute we’re tagging it with a tuple size of 3, and making it an array (it’s also of type float, as opposed to double, as that tends to be the default data for point arrays in the USD sample we have).

From here click on “Save Node” to save the ogn file as “OgnTestDeformer.ogn” in the default directory, and then click “Generate Blank Implementation” to generate a sample implementation file.

Click on “Edit Node” to open the OgnTestDeformer.py implementation file and fill in its contents like so:

"""
This is the implementation of the OGN node defined in OgnTestDeformer.ogn
"""

# Array or tuple values are accessed as numpy arrays so you probably need this import
import numpy

class OgnTestDeformer:
    """
    A sine wave deformer
    """
    @staticmethod
    def compute(db) -> bool:
        """Compute the outputs from the current input"""

        try:
            multiplier = db.inputs.multiplier

            points = db.inputs.in_points

            wavelength = 2
            offset = 3.14

            db.outputs.out_points_size = points.shape[0]
            # Nothing to evaluate if there are no input points
            if db.outputs.out_points_size == 0:
                return True

            pt = points.copy()  # we still need to do a copy here because we do not want to modify points
            tx = pt[:, 0]
            offset_tx = tx + offset
            ty = pt[:, 2]

            disp = (numpy.sin(offset_tx/wavelength) )
            pt[:, 1] += disp * multiplier

            db.outputs.out_points[:] = pt[:]  # we modify output_points in memory so we do not need to set the value again

        except Exception as error:
            # If anything causes your compute to fail report the error and return False
            db.log_error(str(error))
            return False

        # Even if inputs were edge cases like empty arrays, correct outputs mean success
        return True

Notice that arrays are bound to numpy - this allows us to have our internal buffers bound to Python without having to copy it, and also allows us to use numpy syntax and functionality for manipulating these arrays.

Now that the node is ready, let’s wire it up in the graph. Start with creating two nodes. Drag and drop PolyMeshPlane_in into the editor, and select “Read Attribute” to create a ReadPrimAttribute node. Set its Attribute Name to points. Drag and drop PolyMeshPlane_out into the editor, and select “Write Attribute” to create a WritePrimAttribute node. Also set its Attribute Name to points.

../../_images/ext_omnigraph_deforming_text_04_04.png

Proceed to place one of our TestDeformer nodes and wire it up like so:

../../_images/ext_omnigraph_deforming_text_04_05.png

Now, as you move the sphere around, the plane should deform, like so:

../../_images/ext_omnigraph_deforming_text_04_06.png

Finally, a note about the red “Clean Extension” button in the Node Description Editor that you may have noticed. As the ogn directory is a generated directory, it’s something akin to a build directory. It’s possible that as you add and remove nodes, extra stuff might accumulate in there, depending on your workflow. The button will scan the nodes directory and make sure what generated in the ogn directory matches up with it. You might try to use this button to do a “reset” if things are not working as you expect - first make sure the stuff in the nodes directory is good and up to date, then click this button to “reset” and clean things up.