ZivaRT Command-Line Utilities

The utilities can be found in the Utils subfolder of the ZivaRT build.


Usage: zrtStats myZivaRTFile

This utility can identify the type of a file, based on the file’s contents:

  • Intermediate rig => it identifies it as such.

  • Production rig created on or after 12/03/2020 => it identifies it as such, and also identifies its version.

  • Production rig created before 12/03/2020 => it reports it as “un-identified”.

  • All other files => it reports them as “un-identified”.

For production rigs, the utility also prints out model information such as the number of vertices, triangles, memory sizes of various parts. It also performs performance benchmarking. It reports the “hot cache” and “cold cache” execution times of the production rig.


Usage: zrtTranscoder source.zif [destination.zrt]

This utility converts an intermediate rig (.zif) to a production rig (.zrt). Note that such a conversion can also be done using the ZivaRT Trainer (ZRTT), by loading an intermediate rig and saving it to a production rig. If the destination filename is absent, source.zrt is used.


zrtCombine is a command-line utility that allows one to combine one or more ZivaRT production (.zrt) rigs into a single .zrt rig, and apply it to a specified target mesh. Think of it as “adding” multiple rigs, each of which may be defined on their own mesh, into a single rig defined on a target mesh. The required assumption here is that all the input rigs are driven by the same joint hierarchy. Extra parameters, however, may vary across the input rigs. The zrtCombine utility combines them based on their names. Extra parameters from different input rigs that have the same name are fused into one extra parameter in the output rig, and their effect is superimposed.

Here are some example usages of zrtCombine:

  • Restrict a given zrt rig to a submesh (replacing the functionality available in the zrtVertexSubset utility in v1.0 and prior).

  • Combine multiple rigs generated separately into one “superrig” (driven by the same joint hierarchy). For example, suppose you have a ZivaRT rig for the left hand, right hand, body, and a face. Each of these rigs can be defined on its own mesh that is a subset of the mesh for the entire character. All rigs must be driven by the same joints. If the same vertex appears in multiple input meshes, the joint influences (=skinning weights) must be the same in all such input rigs. Suppose you also have a skinning-only rig for the entire human mesh, generated using ZivaRT’s “Train Skinning-Only” function. Then, you can combine all of these rigs into a single rig for the entire character, whereby the target mesh will be the entire human mesh. The combined rig is then driven by the same joint hierarchy. Each of the rigs may optionally also be driven by extra parameters, which do not need to be the same in all the rigs. Extra parameters in different rigs are identified based on their names: if two extra parameters have the same name, they will be merged into a single extra parameter in the output rig, and their contribution will be superimposed (i.e., added). The combined rig is then driven by the union of the unique extra parameters.

  • Suppose you have a .zrt rig for a human mesh, and a separate one for the clothing. The human mesh and the clothing mesh are separate meshes. You can then use zrtCombine to combine the two rigs into a “superrig” for the human + clothing.

The target mesh is not allowed to be an arbitrary mesh, but must be the union of the rig’s individual meshes, or its subset. The vertex positions in the target mesh must match those in the input meshes. To illustrate the concept of a target mesh, consider the meshes of each individual rig. Now, imagine performing a “combine” operation on them in Maya, using Maya’s “Mesh->Combine” tool, and then merging the co-located vertices. The target mesh for zrtCombine must be a subset of this mesh. If this is not the case, this will be detected in the matching process described below, and an error will be issued.

The input meshes and the target mesh.

The input rigs affect the target mesh using a vertex matching process. Each vertex v of each input mesh is matched to a vertex of the target mesh, based on spatial proximity. The proximity is thresholded: if v is too far away from all target mesh vertices, it is matched to nothing. This process will result in each vertex t of the target mesh being matched to 0, 1, 2 or more vertices in the input meshes. If it is matched to 0, zrtCombine will stop and print an error. This is because it is impossible to determine the skinning for such a vertex. Otherwise, the skinning and correctives at t are determined by combining the skinning and correctives at the matched vertices in the input meshes. To illustrate this, suppose that vertex v from input rig 2, v’ from input rig 5, and v’’ from input rig 7 are all matched to vertex t of the target mesh. The zrtCombine utility then requires that vertices v, v’, v’’ are influenced by the same joints and with equal skinning weights in rigs 2, 5 and 7. These influences and skinning weights are copied over to t, and so this determines the skinning of vertex t in the output rig. As per the correctives, they are added: the corrective in the output rig at t is the sum of the correctives calculated at v, v’ and v’’ with respect to their input rigs.

Specifically, the correctives in the output rig work as follows. The zrtCombine utility does not generate new patches, but merely concatenates the patches of the inputs rigs. For a patch in an input rig, some vertices are matched to vertices in the target mesh, but others are too far away and are not matched to anything. The patch is shrunk to the matched vertices, and then simply becomes a patch in the target mesh. The effect of this is that the correctives contributed by different patches, both from the same input mesh and across input meshes, are added together. The zrtCombine utility removes any empty patches that may be generated in this process. This occurs whenever no vertex from a patch in an input rig is matched to any target mesh vertex.

To make the usage clearer, this documentation covers several use cases, and potential pitfalls that may arise when using it.

The syntax to use zrtCombine is as follows. Note that the input meshes are not a part of the syntax because they are already stored inside the .zrt files. More specifically, only the vertex positions are needed; and those are already available inside the .zrt files.

zrtCombine.exe [-p vertexProximityThreshold] inputRig1.zrt inputRig2.zrt ... inputRigN.zrt targetMesh.obj outputRig.zrt

The arguments are:

  • inputRig1.zrt ... inputRigN.zrt

    These are paths to existing ZivaRT production rigs. There should always be at least one of them, and they should all be compatible with each other, i.e. they should have the same asset version as the zrtCombine utility, and the same joint hierarchy and skinning influences.

    A simple rule of thumb is that if the input rigs were created using the same version of ZivaRT software, and use the same joint hierarchy, they are compatible.

  • targetMesh.obj

    The mesh to which the combined deformation of all the input rigs will be applied. This argument should always be present. The output .zrt rig will be deforming this mesh.

    When processing an input rig, zrtCombine tries to spatially match the vertices in each input rig to the vertices of the target mesh. In this process, each target mesh vertex may be matched to 0, 1, 2 or more vertices in the input meshes. If it is matched to 0, an error is generated. If it is matched to 2 or more vertices, then all of them must be influenced by the same joints and with equal skinning weights. In other words, the different inputs must provide consistent skinning at each spatially co-located vertex.

  • vertexProximityThreshold

    (optional) Defines how close (relative to the bounding box of the target mesh) a mesh vertex in a source rig must be to a target mesh vertex for them to be considered co-located. The default value is 1e-5.

  • outputRig.zrt

    The output filename. It should always be present.

Let us now discuss three usages cases and warn against potential pitfalls.

Apply a Rig to a Subset of a Mesh

When you have a trained ZivaRT character rig, it is sometimes desirable to separate its subset into a separate rig. For example, you may want to obtain a rig that affects only the character’s head, a piece of costume, or some other separate part. To do that, use zrtCombine as follows:

zrtCombine.exe sourceRig.zrt meshSubset.obj outputRigOnMeshSubset.zrt


  • sourceRig.zrt is the ZivaRT rig that you already have and want to get a subset of.

  • meshSubset.obj is an obj file that contains only a part of the original mesh the source rig has been trained on.

  • outputRigOnMeshSubset.zrt is the name of the output file.

Below is an example of how to apply this to the cheetah asset. This is how the cheetah looks originally (neutral.obj):

Original cheetah asset

Let’s separate the front half of the cheetah into a file cheetah_front.obj:

A submesh of the cheetah containing only its front half

After running zrtCombine.exe trained.zrt cheetah_front.obj cheetah_front.zrt and loading the resulting .zrt, and the target cheetah_front.obj files into Maya, this is the result:

Cheetah rig applied to its submesh.

Enlarging a Rig to a Larger Mesh

Sometimes, you don’t want to restrict the rig to a smaller mesh, but rather you want to “enlarge” the rig from your mesh M to a larger mesh L. You can achieve this by utilizing zrtCombine with the “Train Skinning-Only Rig” functionality available in ZRTT since v1.1.0. The reason for why zrtCombine alone is not sufficient is that you need to define the skinning on the larger mesh L; this information is not available in the rig on mesh M. So, you would create a skeleton and skinning weights for the larger mesh L, and train a “skinning-only rig” for it. This rig has no correctives, only skinning. Then, under the assumption that the skinning on your original mesh M is consistent with its skinning in the larger rig L, you create a rig for your original mesh M that has both skinning and correctives. You can then zrt-combine the two rigs into one. In order to create the rig with correctives for M, you have two options. You can either generate training data for M directly and train the rig. Alternatively, you can just always work on L. You need to generate the training data on L. You either manually localize the training data onto M (as a subset of L), or you can use the ZRTT’s “Correctives mask” feature to localize the rig onto M.

The zrtCombine command is as follows:

zrtCombine.exe rigWithCorrectivesOnM.zrt skinningOnlyRigOnL.zrt L.obj outputRigOnL.zrt

Combine Multiple Rigs into a Single Rig

Sometimes you may have several rigs that each affect a smaller part of the entire mesh you’re working with. You want to create a single rig for the entire mesh out of those smaller rigs. A situation where this can be useful is when multiple TDs have been working on smaller parts of the mesh and now you need to fuse the work into a single combined rig for the entire character. To do that, use zrtCombine as follows:

zrtCombine.exe inputRig1.zrt ... inputRigN.zrt entireMesh.obj outputRigOnEntireMesh.zrt


  • inputRigX.zrt are the ZivaRT rigs that you already have. They each target some part of the master mesh. They don’t need to be defined on the master mesh; they can operate on a subset mesh; but the vertices of these subset meshes must match those in the master mesh. The input rigs must collectively cover the entire master mesh. If this is not the case, you need to make one of the inputs be the entire mesh with a skinning-only rig. All rigs must use the same joint hierarchy, and skinning influences (weights) at each vertex must be the same in all rigs.

  • entireMesh.obj is the target mesh that the output rig will be applied to.

  • outputRigOnEntireMesh.zrt is the name of the output file (a rig on the entire mesh)

We now give an example of how to apply this to a cylinder asset. The files for this example are available in the Demos folder in the ZivaRT distribution. Here is the cylinder:

The neutral cylinder shape with the joint hierarchy.

The cylinder has three joints, but only the middle one (elbow) is used. It deforms under skinning driven by the elbow. This is stored in a skinning-only rig skinning.zrt. This rig has no extra parameters. In addition, we have two localized rigs, called muscle.zrt and joint.zrt, each localized in a region of the mesh. The rig “muscle.zrt” is driven by a single extra parameter, which fires the muscle. As required by the zrtCombine compatibility rules, it also has the 3-joint skeleton, but this skeleton is not used in the rig. The rig “joint.zrt” is driven by the three joints, and again in practice we only actuate the elbow. It corrects the shape at the elbow based on training data generated using ZivaVFX’s elbow soft-tissue self-contact-resolving and volume-preserving simulation. This rig has no extra parameters. The command to perform the zrt-combination is:

zrtCombine.exe skinning.zrt joint.zrt muscle.zrt cylinder.obj combined.zrt

This is the output of “skinning.zrt” alone. It was created using the “Train Skinning Only Rig” functionality of ZRTT:

cylinder skinning rig

This is the output of “muscle.zrt”. This rig uses a smooth corrective mask to localize it just to the muscle region. This rig fires a muscle, but there are no correctives at the elbow.

Muscle rig on the cylinder.

And here is the output of “joint.zrt”. This rig uses a smooth corrective mask to localize it to the elbow. This rig produces a volume-preserving and self-contact-resolved elbow, but it cannot fire the muscle.

Joint rig on the cylinder.

Finally, here is the output of “combined.zrt”. This rig can independently actuate the muscle and the elbow. The elbow, when actuated, is volume-preserving and self-contact-resolved.

The zrt-combined rigs on the cylinder.

Potential Pitfalls

Failure to Spatially Match Vertices

The zrtCombine tool relies on being able to spatially match input rigs’ vertices to the target mesh. Failure to do so will cause data from the rigs not making it into the final result. For a completely absurd example, let us try to use zrtCombine to apply the cheetah ZivaRT rig to the cylinder asset. Cylinder asset is a small cylinder centered around the zero, whereas the cheetah is placed more arbitrarily in the 3d space. These assets are not close to one another in the 3d space:

Cylinder and cheetah assets imported into a Maya scene.

Running zrtCombine.exe trained.zrt cylinder.obj combined.zrt will fail because the cylinder vertices are not matched to the cheetah vertices.

Extra parameters that are named the same as a joint

With zrtCombine, you cannot have an extra parameter in a rig that has the same name as a joint (in the same, or in another rig). For example, you cannot a joint called “jaw” and also an extra parameter called “jaw”. In such cases, behavior is undefined.

Overlapping Patches

If there are overlapping patches in distinct input rigs, the overlapped vertices will receive a corrective from each such patch. The correctives originating from the distinct patches will simply be added up. This may not be desired. It is worth keeping this in mind when working with multiple rigs.

To illustrate this, let’s split the cheetah mesh in two, create separate rigs for both halves and then zrtCombine them. The rigs for the front and the back halves both affect the same vertices at the seam, and therefore, those vertices receive double correctives, resulting in a visible seam in the middle:

Combined cheetah rig.

The original rig for the complete cheetah has no such seam:

No seam in the rig for the entire cheetah.

Another demonstration of a similar artefact:

zrtCombine.exe trained.zrt trained.zrt neutral.obj cheetah_double.zrt. This command applies the cheetah rig to the mesh twice, resulting in each vertex using a double corrective. Observe how more pronounced the deformations are:

Cheetah rig's deformations applied twice.