meshController
Production-grade surface pinning, mesh surface binding, and VP2 control toolset for Maya.
Introduction
meshController is a Maya C++ plugin that provides high-performance surface pinning and mesh deformation tooling for production facial and character rigging. It ships six node types and five commands targeting two core workflows:
- 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.
- Viewport Tooling — a custom VP2 locator (
shapeControl), a mesh surface overlay (meshControlOverlay), and an interactive placement mode (meshControlMode).
meshController.mll. Load it via the Maya plug-in manager or with cmds.loadPlugin("meshController").
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.
meshControlOverlay
Draws a real-time mesh overlay and hover marker in the viewport, used as feedback during interactive meshControlMode.
meshControlMode
Activates interactive mesh-surface placement mode with Qt mouse-move hit testing and viewport overlay feedback.
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
meshControlMode — interactive viewport mode that tracks split-topology control meshes bound to a
vertexWrapnode. Select the driver and target meshes, then bind to the node to start tracking:cmds.select('driverA', 'a', 'b', r=True) cmds.meshControlMode(bind='driverA_vertexWrap')
# Primary on/off cmds.meshControlMode(enable=True) # enable / refresh tracking from mesh selection cmds.meshControlMode(enable=False) # disable mode
| shapeControl | meshControlMode | |
|---|---|---|
| What it is | Real selectable control shape, one node per control | Batched overlay system, single draw node for many controls |
| Best for | Final rig controls, static icons, individual controls needing unique appearance | Many live deforming mesh controls, hover detection, driver/driven setups |
| Live cost | Per-locator VP2 cost every frame — degrades with count | Single overlay node — no per-mesh draw call overhead |
⚠ Avoid using 50+ shapeControlCreate(live=True) controls. For large live sets, meshControlMode / meshControlOverlay is the correct performance path.
Manager UI
A single window that consolidates all plugin commands — tracking, display, binding, and pinning — without needing to run commands manually. Open it with:
import meshControlManagerUI
meshControlManagerUI.show()
meshControlMode on open if tracked meshes already exist in the
scene (e.g. after reopening Maya). The refresh button in the status bar refreshes the tracked mesh
list and status, and reactivates the viewport mode if tracked meshes exist.
Status Bar
A color-coded dot at the top of the window shows the current mode state at a glance:
| Color | Meaning |
|---|---|
| ● Red | Plugin commands unavailable — plugin not loaded |
| ● Grey | Not initialized — overlay node does not exist yet |
| ● Yellow | Enabled but no meshes tracked |
| ● Green | Active — shows count of currently tracked meshes |
Tracked Meshes
Lists all meshes currently tracked by meshControlMode. Double-clicking a row selects that mesh in the Maya viewport.
| Button | Action |
|---|---|
| Track Selected | Start tracking the current Maya mesh selection. Becomes Replace Tracking with a confirmation prompt when meshes are already tracked. |
| Add Tracking | Append currently selected Maya meshes to the tracked list. |
| Remove | Remove the list-selected rows from tracking. |
| Select | Select the list-selected meshes in the Maya viewport. |
| Clear Tracking | Stop tracking all meshes. Requires confirmation. |
| Disable | Turn off meshControlMode without removing mesh metadata — tracking can be restored with Track Selected or the refresh button. |
Click Target
Controls the meshControlSelectParent attribute on the meshes selected in the list.
When checked, clicking that mesh's overlay patch in the viewport selects its parent transform
instead of the mesh itself. Supports tristate when multiple rows with mixed values are selected.
meshControlSelectNode attribute via a
message connection, that connected transform is always selected on click —
regardless of whether meshControlSelectParent is on. meshControlSelectNode
takes priority in the resolution order.
Overlay Display
Three toggles that update the meshControlOverlay node draw attributes live:
| Toggle | Effect |
|---|---|
| X-Ray | Draw overlay patches in x-ray mode, visible through occluding geometry. |
| Wire | Draw overlay patches as wireframe instead of solid. |
| Marker | Show the hover hit marker where the ray-cast lands on the surface. |
Build
Shortcut buttons for creating nodes. All respect the current Maya selection.
| Button | Action |
|---|---|
| VertexWrap | Select driver first, then driven patches. Creates a vertexWrap deformer and immediately starts tracking the driven meshes. |
| ShapeControl Baked | Creates a baked shapeControl from the selected mesh or curve. Fastest — no live connection. |
| ShapeControl Live | Creates a live shapeControl that follows source deformation. Heavier — use sparingly. |
Pin
Creates surface pin binds from the current Maya selection (mesh first, then controls). Options apply to both pin types where supported:
| Control | Description |
|---|---|
| Surface Pin | Runs surfacePinBind with the current option values. |
| Surface UV Pin | Runs surfaceUVPinBind. Inverse and Output options do not apply. |
| Surface Pin Output | Dropdown — Matrix connects to offsetParentMatrix; Translate connects translate channels 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. Avoid for 50+ controls; use meshControlMode instead |
meshControlOverlay Node
A VP2 locator that draws a surface marker at a tracked hit position on a source mesh, with an
optional wireframe overlay and in-viewport transform readout. It receives hit-point and hit-normal
data (from meshControlMode) via the hitPosition and hitNormal
attributes, and renders a configurable marker at that location in real time.
The overlay caches the source mesh geometry (triangulated positions and face normals) with a serial
number invalidation strategy — geometry is only rebuilt when the source mesh changes shape or topology.
The draw override uses a precomputed MMatrix cache for world-to-overlay transforms.
Key attributes
| Attribute | Description |
|---|---|
| sourceMeshPaths | String array of DAG paths to the source meshes to test against and overlay. |
| enable | Enable or disable the overlay. When false the draw override skips all geometry and marker drawing. |
| inMesh | Optional direct mesh input. When connected, used as the draw source instead of resolving via sourceMeshPaths. |
| trackedMeshPaths | String array of DAG paths currently tracked by meshControlMode. Written by the command; read by the overlay to drive per-patch draw data. |
| hitPosition / hitNormal | World-space hit result from the interactive mode. Updated by meshControlMode callbacks. |
| surfaceOffsetScale | Scales the overlay offset along the surface normal (prevents z-fighting). |
| drawMarker | Show a circle/dot at the hit position. |
| drawWireframe / drawWireframeWidth | Draw the source mesh wireframe on top of the surface. |
| drawInXray | Render the overlay in the X-ray pass. |
meshControlMode Command
An interaction and overlay system for working with mesh-based controls. It tracks selected meshes,
draws hover and selection overlays via meshControlOverlay, and supports binding a driver
mesh to driven control meshes through vertexWrap. Internally, a Qt QObject
event filter intercepts mouse-move events in the active viewport and performs a ray-cast against the
tracked surface on each move, updating the overlay hit position in real time.
Using meshControlOverlay for batched drawing makes this significantly more efficient
than many separate live shapeControl nodes — all draw data goes through one overlay node
with no per-mesh VP2 draw call overhead.
# Bind driver + targets to a vertexWrap node and start tracking cmds.select('driverA', 'a', 'b', r=True) cmds.meshControlMode(bind='driverA_vertexWrap')
Selection Behavior
Clicking a hovered tracked patch selects its selection target. The target is resolved in order:
- If the patch has
meshControlSelectNodeconnected → selects that connected transform - Else if the attribute
meshControlSelectParenton the tracked mesh istrue→ selects the parent transform - Otherwise → selects the mesh transform itself (default)
Flags
# Tracking cmds.meshControlMode(enable=True) # enable / refresh tracking from mesh selection cmds.meshControlMode(enable=False) # disable mode cmds.meshControlMode(append=True) # append selected meshes to tracked list cmds.meshControlMode(remove=True) # remove selected meshes from tracked list cmds.meshControlMode(clear=True) # clear tracked meshes # Display cmds.meshControlMode(xray=True) # draw overlay in xray cmds.meshControlMode(wireframe=True) # draw wireframe overlay cmds.meshControlMode(marker=True) # draw hover marker # Utility cmds.meshControlMode(select=True) # select the overlay node cmds.meshControlMode(reactivate=True) # reinstall / reactivate viewport mouse filter
CUSTOM_LOCATOR_HAS_QT_SUPPORT 0).
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 |
| meshControlOverlay | 0x00140543 |
| vertexWrap | 0x00140544 |
| surfacePin | 0x00140545 |
| surfaceUVPin | 0x00140546 |
| hoverMarker | 0x00140547 |
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.