meshController
Centralized data-only mesh controls, GPU-backed VP2 rendering, and production surface tools for Maya.
Introduction
meshController 2.0.0 is a Maya C++ plugin for high-performance mesh controls,
surface pinning, and deformation workflows in production facial and character rigs. V2 replaces
the legacy mesh tracking design with one centralized, data-only overlay per driver while retaining
the established shapeControl, vertexWrap, and surface pin tools.
- Surface Pin — bind any number of rig controls to a deforming mesh surface so that they track position, orientation, and twist precisely, with full undo/redo and parallel evaluation via TBB. A core advantage is the
localInverseMatrixinput, which solves the double-transform problem inline — no extra utility nodes required when the pin drives offset controls in a facial rig hierarchy. The node also preserves the current transform offset at bind time, so controls retain their authored pose. - vertexWrap — a lightweight deformer that snaps split or matching-topology meshes directly to a driver mesh via one-to-one vertex mapping. Designed for large numbers of small individual control shapes; benefits significantly from Maya's parallel evaluation manager.
- Data-only mesh controls —
meshControlDataOverlaystores compact patch topology and driver-vertex mappings, then draws every patch through retained VP2 GPU buffers. No duplicate hidden draw meshes are generated.
meshController.mll. Load it via the Maya plug-in manager or with cmds.loadPlugin("meshController").
What's New in V2.0
Centralized Data-only
One overlay node owns the binding, drawing, and interaction data for all patches attached to a driver. Patch identity is maintained with message connections and survives DAG renaming and namespaces.
GPU-backed Overlay
Geometry extraction runs during normal VP2 draw preparation while retained GPU vertex and index buffers handle rendering. Static topology buffers are reused when only positions change.
Depth-aware Picking
Patches, tracked ShapeControls, other overlays, and visible scene geometry participate in depth arbitration so only the closest valid control receives hover.
BVH Patch Picking
A top-level patch BVH rejects distant candidates before triangle tests, keeping mouse interaction responsive as patch counts grow.
Manipulator-aware Input
Move, rotate, scale, and universal manipulators take priority over patch hover and selection. Selection commits on left-button release, leaving drags and Maya camera navigation intact.
Multiple Overlays
Multiple referenced or imported rigs can coexist. Each driver resolves to its own overlay, and the manager exposes an Active Driver selector with an optional lock.
Node Summary
vertexWrap
Lightweight deformer for split or matching-topology meshes. One-to-one vertex mapping, no proximity search at eval time — driven vertices are directly snapped to their mapped driver positions.
surfacePin
Barycentric surface follower. Drives offsetParentMatrix or translate on any number of controls. TBB-parallelized.
surfaceUVPin
UV-space variant of surfacePin. Pin positions are defined by UV coordinates and survive topology changes that preserve UV layout.
shapeControl
VP2 custom locator with mesh/curve display, hover highlighting, transform readout slider, and configurable draw style.
meshControlDataOverlay
Central data-only VP2 overlay. Reconstructs all bound patches from the animated driver, retains GPU buffers, and owns depth-aware hover and selection.
meshControlDataBind
Binds patch vertices to matching driver vertices, stores patch topology, creates or replaces the driver's data overlay, and preserves overlay display settings during rebind.
Quick Start
-
1
Load the plugin. All nodes and commands become available immediately.
import maya.cmds as cmds cmds.loadPlugin("meshController")
-
2
vertexWrap — select the driver mesh first, then one or more split-topology target meshes, and run. Each target vertex snaps to its closest driver vertex at bind time.
cmds.select(['face_driver_GEO', 'ctrl_mesh_A', 'ctrl_mesh_B']) cmds.vertexWrap()
-
3
surfacePinBind — position your controls at bind pose, select the mesh followed by the controls, then bind.
maintainOffsetpreserves the current world transform;inversecancels the control's own local TRS to avoid double-transform in a facial rig hierarchy.cmds.select(['head_GEO'] + cmds.ls('lip_ctrl_*')) cmds.surfacePinBind(maintainOffset=True, inverse=True) # Append more controls to the same node later cmds.select(['head_GEO', 'brow_ctrl_L']) cmds.surfacePinBind(node='surfacePin1', maintainOffset=True, inverse=True)
-
4
surfaceUVPinBind — same workflow as surfacePinBind but pins are stored in UV space. Prefer this when the driver mesh topology may change during production but its UV layout stays stable.
cmds.select(['head_GEO'] + cmds.ls('cheek_ctrl_*')) cmds.surfaceUVPinBind(maintainOffset=True)
-
5
shapeControlCreate — select a mesh or curve to use as the control shape, then run. Baked mode copies the shape once (fastest); live mode keeps it connected to the source and follows deformation.
cmds.select('my_ctrl_curve') cmds.shapeControlCreate() # baked, fastest, does not follow deformation cmds.shapeControlCreate(live=True) # follows source deformation, heavier
-
6
meshControlDataBind — select the driver first, followed by one or more patch meshes. Every patch vertex must resolve to a driver vertex within the bind tolerance.
cmds.select(['face_driver_GEO', 'brow_A_proxy', 'brow_B_proxy'], r=True) overlay = cmds.meshControlDataBind( name='face_meshControlDataOverlay', bindTolerance=0.0001, hidePatches=False)
The manager provides the same workflow through New Overlay, and is recommended when a scene contains multiple rigs.
| shapeControl | meshControlDataOverlay | |
|---|---|---|
| What it is | One selectable VP2 locator per control | One centralized VP2 geometry override per driver |
| Best for | Standalone controls and unique baked or live shapes | Large groups of deforming mesh patches sharing a driver |
| Interaction | Standalone hover unless assigned to an overlay's Shape Controls list | Depth-aware picking across patches, tracked ShapeControls, overlays, and scene geometry |
| Draw cost | Per-locator draw preparation | Batched render items with retained GPU vertex/index buffers |
For large live control sets sharing one deforming surface, prefer meshControlDataOverlay. Use standalone shapeControl nodes where individual geometry and behavior are more important than batching.
Manager UI
Mesh Control Manager 2.0.0 provides the recommended workflow for data overlays, patch selection targets, tracked ShapeControls, creation utilities, and pinning. Open it from a Python tab in Maya's Script Editor:
import meshControlManagerUI
window = meshControlManagerUI.show()
window prevents Maya from printing the returned PySide object.
The UI is modeless, so the viewport and Maya selection remain available while it is open.
Active Driver and Status
The Active Driver menu chooses which overlay the manager edits. Selecting a patch, linked control, driver, or overlay can switch the active entry automatically; enable Lock to keep the current rig active while selecting elsewhere. This is the central control for scenes containing multiple imported or referenced rigs.
| Color | Meaning |
|---|---|
| ● Red | Plugin commands unavailable — plugin not loaded |
| ● Grey | No overlay exists, or the Active Driver overlay is disabled |
| ● Yellow | Overlay exists but has no bound patches |
| ● Green | Active — reports bound patch and tracked ShapeControl counts |
Mouse Tracking: Patches
The patch list displays transform names. Patch identity is resolved through the overlay's indexed
patchSourceMeshes message connections rather than saved DAG strings, so namespaces and
node renaming do not invalidate the binding. Use Refresh after an external rename to update a visible label.
| Button | Action |
|---|---|
| New Overlay | Select a new driver first and one or more patches after it. Creates a separate overlay; it will not replace an overlay already owned by another driver. |
| Rebind | Rebuilds the Active Driver using list-selected patches. With no rows selected, all listed patches are rebound. Maya selection is not used for the driver. |
| Add | Adds selected patch meshes by rebuilding the Active Driver's compact binding data. |
| Remove | Removes list-selected patches; deleting the final patch removes the overlay. |
| Select | Selects list-selected patch transforms in Maya. |
| Enable / Disable | Toggles overlay drawing and interaction without deleting binding data. |
| Delete | Deletes the Active Driver overlay and its stored patch data after confirmation. |
Bind tolerance
Bind tolerance is the maximum world-space distance between each patch vertex and its matched driver
vertex. The default is 0.0001. Increase it only when patches are not perfectly aligned;
binding fails if any patch vertex falls outside the threshold and warns if multiple patch vertices
map to the same driver vertex.
Mouse Tracking: Shape Controls
Add existing shapeControl nodes to this tab when they must depth-compete with data-overlay
patches. Tracked ShapeControls hand hover ownership to the Active Driver overlay; untracked
ShapeControls continue using their normal standalone hover. The tracked control does not need a
deformation or driver connection.
Patch Behavior
| Control | Effect |
|---|---|
| Select parent on click | For selected patch rows, use the parent transform as the default click target instead of the patch transform. |
| Wireframe | Draw patch edges instead of solid triangles. |
| X-ray | Draw patches through scene geometry. |
| Hover marker | Show the viewport hit marker over the winning patch. |
| Readout | For one selected patch, show changed attributes from its connected control using the shared ShapeControl readout style. |
| Live draw | Request overlay position updates during timeline scrubbing and playback. Off by default to minimize playback overhead. |
| Base / Hover / Selected | Independent transparency values. Fresh overlays default to 1.0, 0.85, and 0.85. |
Selection Targets
Right-click patch rows to assign animator-facing controls without adding one custom attribute per patch. Targets are persisted through message connections and used for viewport selection and readout.
| Menu item | Action |
|---|---|
| Link to Selected Object | Connects the selected Maya control as the click target for the selected patch rows. |
| Select Linked Control | Selects the controls currently linked to the chosen patch rows. |
| Clear Selection Target | Restores the patch transform or configured parent as the default target. |
| Batch Map Targets | Loads selected Maya controls, pairs by selection order, or matches transform names after removing editable patch and target tokens. Apply updates mappings without closing the modeless dialog. |
Create and Pin
| Control | Description |
|---|---|
| VertexWrap | Select driver first, then driven meshes. Creates only the vertexWrap deformer. |
| ShapeControl Baked / Live | Creates a standalone ShapeControl from the selected mesh or curve, either copied once or connected live. |
| Surface Pin | Runs surfacePinBind with the current option values. |
| Surface UV Pin | Runs surfaceUVPinBind using UV-space attachment data. |
| Output | For Surface Pin, Matrix connects offsetParentMatrix; Translate connects translation only. |
| Maintain Offset | Preserves each control's current world transform at bind time. On by default. |
| Inverse | Cancels the control's own local TRS to avoid double-transform in a facial rig hierarchy. |
vertexWrap Node
vertexWrap is a MPxDeformerNode designed for
split or matching-topology meshes. At bind time it computes a one-to-one
vertex mapping from each driven mesh to the driver. At evaluation time there is no proximity
search, no weight solve, and no barycentric interpolation — it reads the current driver points
and directly writes each driven vertex to its mapped driver position, scaled by the deformer
envelope. This makes it the minimal-cost option whenever topology correspondence already exists.
Driver point reads are cached per evaluation cycle behind a mutex; per-vertex write work is lockless, so the deformer scales cleanly under Maya's parallel evaluation manager (EMP).
vertexWrap does not implement MPxGPUDeformer. The typical use case is
a large number of small, individual meshes (e.g. split-topology face control
shapes) each snapping to a region of the main driver mesh. Uploading many tiny meshes to the GPU
per frame has more overhead than it saves. Instead, the deformer gets its performance win from
Maya's parallel evaluation manager — each target mesh is an independent output
that EMP can schedule concurrently, which is why the benchmark shows a
1.73× throughput gain in EMP mode vs. DG with no GPU involved at all.
Attributes
| Long Name | Short | Type | Description |
|---|---|---|---|
| inMesh | im | kMesh | Driver mesh world geometry input. |
| mapping | mp | kIntArray | Per-target-vertex driver vertex index. Computed at bind time; one integer per driven vertex. |
Performance
Evaluation-time comparison against Maya's built-in proximityWrap (surface and snap
modes) and the legacy wrap deformer. Test scene: split-topology mesh controls bound
to a deforming face geometry driver. Timing measured over multiple playback passes; DG, EMS, and
EMP modes recorded separately.
proximityWrap in surface mode actually regresses in EMP (51.7 vs 72.1 fps DG) due to
internal locking on its proximity structures. The trade-off is that
vertexWrap requires a fixed vertex correspondence and cannot handle arbitrary
topology or sliding offset deformation — for those cases proximityWrap is
the appropriate choice.
Detailed results
| Deformer | Avg ms/frame | Median ms/frame | Avg fps | DG fps | EMS fps | EMP fps |
|---|---|---|---|---|---|---|
| vertexWrap | 10.85 | 10.82 | 92.1 | 84.3 | 75.4 | 145.6 |
| proximityWrap (snap) | 14.06 | 14.01 | 71.1 | 74.6 | 61.2 | 63.0 |
| proximityWrap (surface) | 15.83 | 15.73 | 63.2 | 72.1 | 51.9 | 51.7 |
| wrap | 31.65 | 31.46 | 31.6 | 30.7 | 24.7 | 57.5 |
proximityWrap in surface mode drops from 72.1 fps (DG) to
51.7 fps (EMP) — a 28% regression under parallel scheduling. Snap mode shows
a smaller but similar pattern (74.6 → 63.0 fps). This indicates internal contention on
shared proximity data structures that prevents effective parallelism. In rigs with many
proximityWrap nodes, forcing DG evaluation may produce higher throughput than EMP.
vertexWrap Command
Creates a vertexWrap deformer and computes the vertex mapping for all selected target meshes. Select the driver mesh first, then one or more target meshes.
# Select driver first, then targets cmds.select(['driver_GEO', 'target_A', 'target_B']) cmds.vertexWrap() # Optional: name the node cmds.vertexWrap(name='face_vertexWrap')
proximityWrap instead.
surfacePin Node
surfacePin is a MPxNode that reads a deforming mesh each frame and outputs
a world-space 4×4 matrix per control, derived from the mesh surface at the control's stored bind position.
The orientation encodes the local TBN frame: X = tangent, Y = bitangent,
Z = surface normal.
Bind data (barycentric weights, vertex indices, tangent coefficients) is baked at bind time by
surfacePinBind and stored in storable attributes. At runtime, only the deformed mesh
positions are read — no closet-point searches occur per frame.
How the surface frame is built
For each control i per compute frame:
- Interpolate mesh position using stored barycentric weights over 3 triangle vertices → world position.
- Reconstruct a smooth normal by blending per-vertex local-topology normals (vertex ring averages) at the 3 triangle corners.
- Reconstruct the tangent from stored edge-relative coefficients (a·edge₀ + b·edge₁), projected onto the normal plane. This prevents world-space drift as the mesh deforms.
- Compute bitangent as N × T. Assemble the 4×4 matrix.
- Optionally apply the stored bind offset (for
-maintainOffsetmode) via pre-/post-multiply of bind inverse and bind control matrices. - Apply parent-inverse and/or control-inverse compensation if connected.
The TBB parallel_for loop runs over all N controls simultaneously when parallel evaluation is active.
Attributes
Per-Frame Inputs
| Long Name | Short | Type | R/W | Description |
|---|---|---|---|---|
| deformedGeometry | dg | kMesh | input | Connect to meshShape.worldMesh[instance]. The deforming mesh positions read each frame. |
| geometryWorldMatrix | gwm | kMatrix | input | Connect to meshShape.worldMatrix[instance]. Transforms barycentric-interpolated positions into world space. Required when the mesh has a non-identity world transform. |
| controlParentInverseMatrix[] | cpim | kMatrix[] | input | Array of parent worldInverseMatrix per control, one entry per control index. Used to convert world-space output into parent space. |
| controlLocalInverseMatrix[] | clim | kMatrix[] | input | Array of the control's own inverseMatrix. Connected only in -inverse mode to cancel the control's own local transform. |
Stored Bind Data (Storable)
| Long Name | Short | Type | Description |
|---|---|---|---|
| baryWeights | bw | kDoubleArray | Barycentric weights, 3 per control, flat array of length N×3. |
| vertexIndices | vi | kIntArray | Mesh vertex indices for the 3 triangle corners per control. |
| normalIndices | ni | kIntArray | Face-vertex normal IDs at the 3 triangle corners. Used for smooth normal reconstruction at runtime. |
| bindTangents | bt | kDoubleArray | Two edge-relative tangent coefficients per control [a, b] such that tangent = a·edge₀ + b·edge₁. |
| bindSurfaceMatrices | bsm | kMatrixArray | World-space surface matrix at bind time. Inverted and stored for offset computation in -maintainOffset mode. |
| bindControlMatrices | bcm | kMatrixArray | Control world matrix at bind time. Hidden. Used with bindSurfaceMatrices to reconstruct the bind offset. |
| bindMaintainOffset | bmo | kBoolean | Hidden flag, set true when bound with -maintainOffset. Persists bind mode across rebinds. |
| bindUseControlInverse | bui | kBoolean | Hidden flag for -inverse bind mode. Persists across rebinds. |
Outputs
| Long Name | Short | Type | Description |
|---|---|---|---|
| outputMatrix[] | om | kMatrix[] | Per-control world-to-parent matrix. Connect to control.offsetParentMatrix. |
| outputTranslate[] | ot | double3[] | Per-control parent-space translation. Connect to control.translate for translate-only following. |
Connection Diagram
surfacePinBind Command
Creates a surfacePin node (or appends to an existing one), bakes all bind data from the
mesh at its current deformed state, and wires the full connection graph. Fully undoable.
Syntax
# Create a new node surfacePinBind mesh ctrl0 ctrl1 ... [flags] # Append controls to an existing node surfacePinBind [mesh] ctrl0 ctrl1 ... -node surfacePin1 [flags] # Rebind all controls using stored mesh (no arguments) surfacePinBind -node surfacePin1
Returns the name of the surfacePin node.
Flags
| Short | Long | Arg | Description |
|---|---|---|---|
| -n | -node | string | Name of an existing surfacePin node to append controls to, or to rebind. If omitted, a new node is created. |
| -mo | -maintainOffset | — | Preserve each control's current world-space pose. Zeros local TRS, sets scale to 1.0, and stores the difference as a bind offset applied at runtime. |
| -iv | -inverse | bool | Connect the control's own inverseMatrix back into the node. Cancels the control's local TRS visually so it can drive shapes without double-transforming. |
| -c | -connect | string | Output mode: "matrix" (default) wires outputMatrix → offsetParentMatrix; "translate" wires outputTranslate → translate. |
| -to | -translateOnly | bool | Alias for -connect translate. Only translation follows the surface; orientation is not driven. |
Examples
// Basic bind: snap controls to mesh surface surfacePinBind head_GEO ctrl_0 ctrl_1 ctrl_2; // Maintain current world positions surfacePinBind head_GEO mouth_ctrl -maintainOffset; // Cancel local double-transform (inverse mode) surfacePinBind head_GEO lip_ctrl -inverse true; // Translate-only following surfacePinBind head_GEO brow_ctrl_L -connect translate; // Append to existing node surfacePinBind head_GEO new_ctrl_0 -node surfacePin1; // Rebind all controls after repositioning surfacePinBind -node surfacePin1;
import maya.cmds as cmds # Basic bind node = cmds.surfacePinBind('head_GEO', 'ctrl_0', 'ctrl_1') # Maintain offset node = cmds.surfacePinBind('head_GEO', 'mouth_ctrl', maintainOffset=True) # maintainOffset + inverse — creates a new surfacePin node node = cmds.surfacePinBind('head_GEO', 'lip_ctrl', maintainOffset=True, inverse=True) # maintainOffset + inverse — appends to an existing node node = cmds.surfacePinBind('head_GEO', 'brow_ctrl', node='surfacePin1', maintainOffset=True, inverse=True) # Translate-only node = cmds.surfacePinBind('head_GEO', 'cheek_ctrl', connect='translate') # Rebind in-place cmds.surfacePinBind(node=node)
surfacePinBind -node <node>
with no mesh/control arguments. The command reads the stored mesh connection and re-bakes all bind data.
The node identity and all outgoing connections are preserved.
surfaceUVPin Node
surfaceUVPin is a UV-space variant of surfacePin. Rather than storing vertex
indices at bind time, it stores the UV coordinates of each pin location. At runtime, those UVs are
resolved back to triangle barycentric coordinates within the current UV triangle set.
This makes pins stable across topology changes that preserve UV layout — a common workflow when sculpting or re-topo'ing a mesh while retaining its UV map. The trade-off is a one-time UV-triangle rebuild cost whenever the UV set changes.
Key differences from surfacePin
| Feature | surfacePin | surfaceUVPin |
|---|---|---|
| Pin storage | Vertex indices + barycentric weights | UV coordinates per pin |
| Survives retopology | No (vertex indices change) | Yes (if UVs are preserved) |
| UV set support | — | Named UV set via uvSet attribute |
| Bind command | surfacePinBind | surfaceUVPinBind |
| Node scheduling | kParallel | kParallel |
surfaceUVPin when your mesh is still being finalized (retopo, sculpt changes) but the
UV layout is locked. Use surfacePin for maximum runtime performance when topology is frozen.
Attributes
—deformedGeometry,
geometryWorldMatrix, controlParentInverseMatrix[], controlLocalInverseMatrix[],
outputMatrix[], and outputTranslate[] work the same way.
The UV-specific stored attributes are listed below.
UV Bind Data (Storable)
| Long Name | Short | Type | Description |
|---|---|---|---|
| pinUVs | puv | kDoubleArray | Stored UV coordinate per pin, flat array of length N×2. Written at bind time; resolved to barycentric coords each frame via the UV triangle set. |
| preferredTriangleIndices | pti | kIntArray | Per-pin preferred triangle index used to disambiguate UV seams. Written at bind time. Set to -1 when no preference is recorded. |
| uvSet | uvs | kString | Named UV set used for pin resolution. Defaults to the mesh's default UV set. Changing this triggers a full UV triangle rebuild. |
| bindTangents | bt | kDoubleArray | Edge-relative tangent coefficients [a, b] per pin. Same storage format as surfacePin. |
| bindSurfaceMatrices | bsm | kMatrixArray | World-space surface matrix at bind time. Used for offset computation in -maintainOffset mode. |
| bindControlMatrices | bcm | kMatrixArray | Control world matrix at bind time. Hidden. |
| bindMaintainOffset | bmo | kBoolean | Hidden flag — set true when bound with -maintainOffset. |
| bindUseControlInverse | bui | kBoolean | Hidden flag — set true when bound with -inverse. |
surfaceUVPinBind Command
Creates a surfaceUVPin node and binds controls. Flags are a subset of surfacePinBind:
| Short | Long | Arg | Description |
|---|---|---|---|
| -n | -node | string | Existing surfaceUVPin node to append controls to. |
| -mo | -maintainOffset | — | Preserve current world pose; stores bind offset. |
# Python node = cmds.surfaceUVPinBind('head_GEO', 'ctrl_0', 'ctrl_1') node = cmds.surfaceUVPinBind('head_GEO', 'mouth_ctrl', maintainOffset=True)
shapeControl Node
A VP2 MPxLocatorNode with a full MPxDrawOverride that renders in DX11/OpenGL/Metal.
It accepts an optional geometry input (inGeometry) and draws the connected mesh or NURBS
curve directly in the viewport using the locator's transform, with configurable draw style, line width,
color, transparency, and X-ray mode.
Key display attributes
| Attribute | Description |
|---|---|
| inGeometry | Mesh or curve shape to display. When connected, the locator draws the geometry in viewport. |
| color / hoverColor / selectedColor | RGB display color per state. |
| transparency / hoverTransparency / selectedTransparency | Alpha per state. |
| drawInXray | If true, renders the locator in the X-ray pass (draws through occluding geometry). |
| wireframe | Draw as wireframe rather than filled. |
| enableHover | Enable per-frame hover testing. |
| lineStyle / lineWidth | VP2 line style enum and width for wireframe drawing. |
| showTransformReadout | Display an in-viewport transform text readout with optional slider widget. |
| primitive | Draw primitive: Points, Lines, LineStrip, ClosedLine, Triangles, TriStrip. |
| paintStyle | VP2 MUIDrawManager::PaintStyle (flat, stippled, etc.). |
| inverse | When true, the locator cancels its own local transform, matching the self-compensating behaviour set up by -inverse in surfacePinBind. |
shapeControlCreate Command
Select a mesh or curve first, then run. By default the command bakes the source
geometry into the control at creation time — the result is lightweight because no live connection
to the original source is needed during playback. Use live=True to keep the source
connected so the control shape follows deformation.
# Baked — fastest, does not follow deformation cmds.select('my_ctrl_shape_GEO') cmds.shapeControlCreate() # Live — follows source deformation, heavier cmds.shapeControlCreate(live=True)
| Mode | Best for | Cost |
|---|---|---|
| Baked (default) | Final animator-facing controls, selectable rig controls, static custom icons | Very lightweight — no live geometry connection |
| Live | Controls that must follow a deforming source during layout or setup | Heavier — per-locator VP2 cost every frame. For large shared-driver sets, use meshControlDataOverlay |
meshControlDataOverlay Node
meshControlDataOverlay is a centralized VP2 MPxLocatorNode with an
MPxGeometryOverride. It stores each patch's topology and driver-vertex mapping as compact
arrays, evaluates the current driver geometry, and submits batched base, selected, hover, and wireframe
render items. GPU vertex/index buffers are retained and static index data is reused until topology changes.
The driver's worldMesh[instance] connects to inMesh. Driver transform changes,
animation time, geometry revisions, and topology revisions invalidate the appropriate caches. Picking
uses the same evaluated driver state as drawing, including animated frames and transformed drivers.
Display Attributes
| Attribute | Default | Description |
|---|---|---|
| enable | true | Enable drawing and interaction. Disabling keeps all binding data and message connections. |
| liveDraw | false | Continuously request VP2 position refreshes during timeline changes and playback. Leave off when maximum playback speed is more important than passive overlay animation. |
| color | blue | Base patch color. |
| hoverColor | yellow | Winning hover color. |
| selectedColor | green | Color for patches whose effective controls are in Maya's active selection. |
| transparency | 1.0 | Base patch transparency. |
| hoverTransparency | 0.85 | Hover highlight transparency. |
| selectedTransparency | 0.85 | Selected highlight transparency. |
| drawInXray | false | Draw patches through scene geometry. |
| drawWireframe / wireframeWidth | false / 1.0 | Use bound patch edge data for wireframe drawing. |
| drawMarker | false | Show the hover marker at the winning surface hit. |
| showTransformReadout | false | Show changed attributes for the control connected to one selected patch. |
| readoutTextSize | 13 | Viewport readout text size. |
Binding and Identity
| Attribute | Description |
|---|---|
| inMesh | Connected driver world mesh used for draw reconstruction and picking. |
| bindTolerance | Stored world-space threshold used by future manager rebinds. Hidden from the Channel Box and exposed in the manager. |
| patchSourceMeshes[] | Indexed message connections to patch shapes. This is the authoritative patch identity and is safe across renaming and namespaces. |
| patchControl[] | Indexed message connections to effective patch selection/readout targets. |
| trackedShapeControls[] | Message connections to ShapeControls that participate in patch-versus-control depth arbitration. |
| patchVertexCounts and topology arrays | Hidden implementation data containing compact vertex mappings, triangles, and edges. These attributes are not user-editable. |
| patchSourcePaths / patchSelectPaths | Deprecated hidden compatibility attributes. V2 runtime and UI identity do not depend on saved path strings. |
meshControlDataBind Command
Select the driver mesh first, then one or more patch meshes. At bind time, each patch vertex is mapped
to the closest driver vertex inside the bind tolerance. The command stores patch triangle/edge topology,
connects source and default control messages, and creates one meshControlDataOverlay for the driver.
meshControlDataBind driver patch0 [patch1 ...] [flags] # Selection-driven Python example cmds.select(['face_GEO', 'brow_A_proxy', 'brow_B_proxy'], r=True) overlay = cmds.meshControlDataBind( name='face_meshControlDataOverlay', bindTolerance=0.0001, hidePatches=False)
| Short | Long | Argument | Description |
|---|---|---|---|
| -n | -name | string | Name of the overlay transform. |
| -hp | -hidePatches | boolean | Set each patch transform's visibility to false after binding. Default is false. |
| -bt | -bindTolerance | double | Maximum world-space vertex matching distance. Must be finite and greater than zero; default is 0.0001. |
Viewport Interaction
A plug-in lifetime Qt event filter follows Maya model-panel viewports. For each mouse position it evaluates visible overlays, traverses their patch BVHs, tests tracked ShapeControls, and compares results with scene depth. Only the closest visible candidate receives hover.
Selection
- A patch selection commits on left-button release over the same patch, not on press.
- Dragging after press cancels patch selection, allowing manipulators to begin normally.
- Shift adds to the Maya selection; Ctrl removes from it.
- Alt bypasses overlay interaction so Maya camera orbit, pan, and zoom remain available.
- Custom
patchControl[]targets take priority; otherwise the patch transform or configured parent is selected.
Manipulator Priority
Move, scale, rotate, and universal manipulator regions suppress patch hover and click capture. The rotate tool reserves the full disc inside its outer ring. Returning from another patch to a handle clears the previous patch hover immediately, so the handle can be dragged on mouse press.
Multiple Viewports and Isolate Select
Viewport ownership follows the model panel receiving the event rather than one permanently active panel. Overlay picking therefore works across switched and newly used viewports. Isolate Select membership is resolved per panel so related drivers, patches, controls, and the hover marker can participate without leaking interaction from non-isolated rigs.
Multiple Overlays
All live meshControlDataOverlay nodes are considered during one mouse event. V2 compares
candidate depth globally, applies hover to the winning overlay, and clears stale hover and selected
visual state on the others. Imported and namespaced rigs therefore remain independent while sharing
the same viewport interaction service.
Performance Benchmarks
Evaluation time measured against Maya's built-in
uvPin and proximityPin nodes. Tests use a deforming animated sphere mesh
(80-subdivision, ~10K vertices) driven by a blendShape + animated transform group, with controls
distributed in a Fibonacci sphere pattern. Parallel evaluation enabled, 120 frames × 2 repeats.
Technical Notes
Node IDs
| Node | Type ID |
|---|---|
| shapeControl | 0x00140542 |
| legacy meshControlOverlay (not registered in V2) | 0x00140543 |
| vertexWrap | 0x00140544 |
| surfacePin | 0x00140545 |
| surfaceUVPin | 0x00140546 |
| hoverMarker | 0x00140547 |
| meshControlDataOverlay | 0x00140548 |
TBB Parallelism
Both surfacePin and surfaceUVPin use tbb::parallel_for over
the N-control loop in compute(). The node scheduling type is kParallel, so
Maya's parallel evaluation manager can also run multiple node evaluations concurrently across the DG.
Tangent Stability
Tangents are stored as two scalar coefficients [a, b] relative to the containing triangle's edge vectors, not as a world-space direction. At runtime: T = a·edge₀ + b·edge₁. This means the tangent deforms with the mesh geometry and never drifts due to world-space rotation or scale — a common artifact in UV-tangent or fixed-reference approaches.
Smooth Normal Reconstruction
Rather than using Maya's cached face-vertex normals (which can produce seams at hard edges),
surfacePin computes local topology normals at runtime: for each triangle corner vertex,
it averages the cross products of the surrounding edge pairs in a configurable vertex ring, then
barycentric-blends those three corner normals. This produces C⁰-continuous normals across the surface
and handles hard edges correctly.