/ meshController v2.0.0 · Maya 2023–2024

meshController

Centralized data-only mesh controls, GPU-backed VP2 rendering, and production surface tools for Maya.

Author Zhenggang Deng
Version 2.0.0
Platform Windows · Maya 2023–2024
Node IDs 0x00140542–48
Viewport VP2 Geometry Override

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 localInverseMatrix input, 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 — meshControlDataOverlay stores compact patch topology and driver-vertex mappings, then draws every patch through retained VP2 GPU buffers. No duplicate hidden draw meshes are generated.
Plugin filename The compiled plugin registers under the filename meshController.mll. Load it via the Maya plug-in manager or with cmds.loadPlugin("meshController").

What's New in V2.0

architecture

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.

viewport 2.0

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.

interaction

Depth-aware Picking

Patches, tracked ShapeControls, other overlays, and visible scene geometry participate in depth arbitration so only the closest valid control receives hover.

acceleration

BVH Patch Picking

A top-level patch BVH rejects distant candidates before triangle tests, keeping mouse interaction responsive as patch counts grow.

workflow

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.

scenes

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.

Performance V2 reduces evaluation and draw overhead most clearly in patch-heavy scenes. Gains are scene-dependent; one production comparison improved from 145 fps to 183 fps (about 26%), with larger gains observed in other tested configurations. Benchmark your own rig in DG, EMS, and EMP modes. V2 reduces evaluation and draw overhead most clearly in patch-heavy scenes. In one production comparison, playback improved from 150 fps to 220 fps: approximately 47% faster, or roughly a 50% performance increase. Results remain scene-dependent, so benchmark your rig in DG, EMS, and EMP modes.

Node Summary

deformer node

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.

dependency node

surfacePin

Barycentric surface follower. Drives offsetParentMatrix or translate on any number of controls. TBB-parallelized.

dependency node

surfaceUVPin

UV-space variant of surfacePin. Pin positions are defined by UV coordinates and survive topology changes that preserve UV layout.

locator node

shapeControl

VP2 custom locator with mesh/curve display, hover highlighting, transform readout slider, and configurable draw style.

locator node

meshControlDataOverlay

Central data-only VP2 overlay. Reconstructs all bound patches from the animated driver, retains GPU buffers, and owns depth-aware hover and selection.

command

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. maintainOffset preserves the current world transform; inverse cancels 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.

Data overlay vs shapeControl — which to use
shapeControlmeshControlDataOverlay
What it isOne selectable VP2 locator per controlOne centralized VP2 geometry override per driver
Best forStandalone controls and unique baked or live shapesLarge groups of deforming mesh patches sharing a driver
InteractionStandalone hover unless assigned to an overlay's Shape Controls listDepth-aware picking across patches, tracked ShapeControls, overlays, and scene geometry
Draw costPer-locator draw preparationBatched 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()
Assigning the result to 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.

ColorMeaning
● RedPlugin commands unavailable — plugin not loaded
● GreyNo overlay exists, or the Active Driver overlay is disabled
● YellowOverlay exists but has no bound patches
● GreenActive — 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.

ButtonAction
New OverlaySelect 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.
RebindRebuilds the Active Driver using list-selected patches. With no rows selected, all listed patches are rebound. Maya selection is not used for the driver.
AddAdds selected patch meshes by rebuilding the Active Driver's compact binding data.
RemoveRemoves list-selected patches; deleting the final patch removes the overlay.
SelectSelects list-selected patch transforms in Maya.
Enable / DisableToggles overlay drawing and interaction without deleting binding data.
DeleteDeletes 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

ControlEffect
Select parent on clickFor selected patch rows, use the parent transform as the default click target instead of the patch transform.
WireframeDraw patch edges instead of solid triangles.
X-rayDraw patches through scene geometry.
Hover markerShow the viewport hit marker over the winning patch.
ReadoutFor one selected patch, show changed attributes from its connected control using the shared ShapeControl readout style.
Live drawRequest overlay position updates during timeline scrubbing and playback. Off by default to minimize playback overhead.
Base / Hover / SelectedIndependent 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 itemAction
Link to Selected ObjectConnects the selected Maya control as the click target for the selected patch rows.
Select Linked ControlSelects the controls currently linked to the chosen patch rows.
Clear Selection TargetRestores the patch transform or configured parent as the default target.
Batch Map TargetsLoads 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

ControlDescription
VertexWrapSelect driver first, then driven meshes. Creates only the vertexWrap deformer.
ShapeControl Baked / LiveCreates a standalone ShapeControl from the selected mesh or curve, either copied once or connected live.
Surface PinRuns surfacePinBind with the current option values.
Surface UV PinRuns surfaceUVPinBind using UV-space attachment data.
OutputFor Surface Pin, Matrix connects offsetParentMatrix; Translate connects translation only.
Maintain OffsetPreserves each control's current world transform at bind time. On by default.
InverseCancels 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).

No GPU override — and that's intentional 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 NameShortTypeDescription
inMeshimkMeshDriver mesh world geometry input.
mappingmpkIntArrayPer-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.

Use cases & limitations The primary use case is mesh-control snap: driving a set of split-topology control meshes so they conform precisely to the deforming surface without any sliding or interpolation. Because the deform loop is a plain indexed copy, it scales linearly with vertex count and parallelises trivially — the EMP (parallel evaluation) column shows a 1.73× throughput gain over DG on the same hardware, whereas 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.
Playback speed by evaluation mode — fps (higher is better)
Average evaluation time — ms / frame (lower is better)

Detailed results

Deformer Avg ms/frame Median ms/frame Avg fps DG fps EMS fps EMP fps
vertexWrap 10.8510.82 92.1 84.375.4 145.6
proximityWrap (snap) 14.0614.01 71.1 74.661.2 63.0
proximityWrap (surface) 15.8315.73 63.2 72.151.9 51.7
wrap 31.6531.46 31.6 30.724.7 57.5
⚠ proximityWrap parallel regression 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')
Topology requirement The driven mesh must have a matching or split vertex layout relative to the driver — each driven vertex is mapped to its spatially closest driver vertex at bind time. If the meshes have substantially different densities, use 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:

  1. Interpolate mesh position using stored barycentric weights over 3 triangle vertices → world position.
  2. Reconstruct a smooth normal by blending per-vertex local-topology normals (vertex ring averages) at the 3 triangle corners.
  3. 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.
  4. Compute bitangent as N × T. Assemble the 4×4 matrix.
  5. Optionally apply the stored bind offset (for -maintainOffset mode) via pre-/post-multiply of bind inverse and bind control matrices.
  6. 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 NameShortTypeR/WDescription
deformedGeometrydgkMeshinputConnect to meshShape.worldMesh[instance]. The deforming mesh positions read each frame.
geometryWorldMatrixgwmkMatrixinputConnect to meshShape.worldMatrix[instance]. Transforms barycentric-interpolated positions into world space. Required when the mesh has a non-identity world transform.
controlParentInverseMatrix[]cpimkMatrix[]inputArray of parent worldInverseMatrix per control, one entry per control index. Used to convert world-space output into parent space.
controlLocalInverseMatrix[]climkMatrix[]inputArray of the control's own inverseMatrix. Connected only in -inverse mode to cancel the control's own local transform.

Stored Bind Data (Storable)

Long NameShortTypeDescription
baryWeightsbwkDoubleArrayBarycentric weights, 3 per control, flat array of length N×3.
vertexIndicesvikIntArrayMesh vertex indices for the 3 triangle corners per control.
normalIndicesnikIntArrayFace-vertex normal IDs at the 3 triangle corners. Used for smooth normal reconstruction at runtime.
bindTangentsbtkDoubleArrayTwo edge-relative tangent coefficients per control [a, b] such that tangent = a·edge₀ + b·edge₁.
bindSurfaceMatricesbsmkMatrixArrayWorld-space surface matrix at bind time. Inverted and stored for offset computation in -maintainOffset mode.
bindControlMatricesbcmkMatrixArrayControl world matrix at bind time. Hidden. Used with bindSurfaceMatrices to reconstruct the bind offset.
bindMaintainOffsetbmokBooleanHidden flag, set true when bound with -maintainOffset. Persists bind mode across rebinds.
bindUseControlInversebuikBooleanHidden flag for -inverse bind mode. Persists across rebinds.

Outputs

Long NameShortTypeDescription
outputMatrix[]omkMatrix[]Per-control world-to-parent matrix. Connect to control.offsetParentMatrix.
outputTranslate[]otdouble3[]Per-control parent-space translation. Connect to control.translate for translate-only following.

Connection Diagram

head_GEOShape
→ worldMesh[0] →
surfacePin1
outputMatrix[i] →
ctrl_i.offsetParentMatrix
ctrl_i_parent
→ worldInverseMatrix[0] →
surfacePin1
controlParentInverseMatrix[i]
(inverse mode)
→ ctrl_i.inverseMatrix →
surfacePin1
controlLocalInverseMatrix[i]

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

ShortLongArgDescription
-n-nodestringName 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-inverseboolConnect 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-connectstringOutput mode: "matrix" (default) wires outputMatrix → offsetParentMatrix; "translate" wires outputTranslate → translate.
-to-translateOnlyboolAlias 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)
Note — rebind vs. recreate When controls are repositioned (e.g. after a rig sculpt pass), call 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

FeaturesurfacePinsurfaceUVPin
Pin storageVertex indices + barycentric weightsUV coordinates per pin
Survives retopologyNo (vertex indices change)Yes (if UVs are preserved)
UV set support—Named UV set via uvSet attribute
Bind commandsurfacePinBindsurfaceUVPinBind
Node schedulingkParallelkParallel
When to use surfaceUVPin Use 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 NameShortTypeDescription
pinUVspuvkDoubleArrayStored 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.
preferredTriangleIndicesptikIntArrayPer-pin preferred triangle index used to disambiguate UV seams. Written at bind time. Set to -1 when no preference is recorded.
uvSetuvskStringNamed UV set used for pin resolution. Defaults to the mesh's default UV set. Changing this triggers a full UV triangle rebuild.
bindTangentsbtkDoubleArrayEdge-relative tangent coefficients [a, b] per pin. Same storage format as surfacePin.
bindSurfaceMatricesbsmkMatrixArrayWorld-space surface matrix at bind time. Used for offset computation in -maintainOffset mode.
bindControlMatricesbcmkMatrixArrayControl world matrix at bind time. Hidden.
bindMaintainOffsetbmokBooleanHidden flag — set true when bound with -maintainOffset.
bindUseControlInversebuikBooleanHidden flag — set true when bound with -inverse.

surfaceUVPinBind Command

Creates a surfaceUVPin node and binds controls. Flags are a subset of surfacePinBind:

ShortLongArgDescription
-n-nodestringExisting 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

AttributeDescription
inGeometryMesh or curve shape to display. When connected, the locator draws the geometry in viewport.
color / hoverColor / selectedColorRGB display color per state.
transparency / hoverTransparency / selectedTransparencyAlpha per state.
drawInXrayIf true, renders the locator in the X-ray pass (draws through occluding geometry).
wireframeDraw as wireframe rather than filled.
enableHoverEnable per-frame hover testing.
lineStyle / lineWidthVP2 line style enum and width for wireframe drawing.
showTransformReadoutDisplay an in-viewport transform text readout with optional slider widget.
primitiveDraw primitive: Points, Lines, LineStrip, ClosedLine, Triangles, TriStrip.
paintStyleVP2 MUIDrawManager::PaintStyle (flat, stippled, etc.).
inverseWhen 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)
ModeBest forCost
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

AttributeDefaultDescription
enabletrueEnable drawing and interaction. Disabling keeps all binding data and message connections.
liveDrawfalseContinuously request VP2 position refreshes during timeline changes and playback. Leave off when maximum playback speed is more important than passive overlay animation.
colorblueBase patch color.
hoverColoryellowWinning hover color.
selectedColorgreenColor for patches whose effective controls are in Maya's active selection.
transparency1.0Base patch transparency.
hoverTransparency0.85Hover highlight transparency.
selectedTransparency0.85Selected highlight transparency.
drawInXrayfalseDraw patches through scene geometry.
drawWireframe / wireframeWidthfalse / 1.0Use bound patch edge data for wireframe drawing.
drawMarkerfalseShow the hover marker at the winning surface hit.
showTransformReadoutfalseShow changed attributes for the control connected to one selected patch.
readoutTextSize13Viewport readout text size.

Binding and Identity

AttributeDescription
inMeshConnected driver world mesh used for draw reconstruction and picking.
bindToleranceStored 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 arraysHidden implementation data containing compact vertex mappings, triangles, and edges. These attributes are not user-editable.
patchSourcePaths / patchSelectPathsDeprecated hidden compatibility attributes. V2 runtime and UI identity do not depend on saved path strings.
GPU-backed, not GPU-only VP2 rendering and retained vertex/index buffers run on the GPU. Mesh extraction, cache preparation, BVH traversal, depth arbitration, and Maya selection logic run on the CPU in their appropriate Maya evaluation or draw-preparation paths.

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)
ShortLongArgumentDescription
-n-namestringName of the overlay transform.
-hp-hidePatchesbooleanSet each patch transform's visibility to false after binding. Default is false.
-bt-bindTolerancedoubleMaximum world-space vertex matching distance. Must be finite and greater than zero; default is 0.0001.
Rebinding Running the command again for a driver replaces that driver's overlay binding while preserving its enable state, display settings, colors, transparency, readout options, and tracked ShapeControl list. The manager's Rebind action uses the Active Driver and selected list rows, so selecting the driver in Maya is unnecessary.

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.

Evaluation time — ms/frame vs. control count
Why surfacePin / surfaceUVPin Beyond raw evaluation speed, both nodes offer workflow advantages over Maya's built-in alternatives. Maintain Offset is handled automatically at bind time — each control's current world pose is preserved with no manual offset group setup required. The Inverse input cancels the control's own local transform to eliminate double-transformation in a facial rig hierarchy, without needing extra compensate nodes or additional connections.

Technical Notes

Node IDs

NodeType ID
shapeControl0x00140542
legacy meshControlOverlay (not registered in V2)0x00140543
vertexWrap0x00140544
surfacePin0x00140545
surfaceUVPin0x00140546
hoverMarker0x00140547
meshControlDataOverlay0x00140548

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.