Skip to content

Pivot Painter Lab (standalone)

UE 5.4–5.85/51.0.4

Fab product: EQLabs Pivot Painter Lab · Version: 1.0.1 · Engine: UE 5.4 – 5.8 Modules: 4 (3 Editor + 1 Runtime) · Requires: Niagara

Foliage sways by rotating each branch and leaf around its pivot — the point where it joins its parent. Pivot Painter stores each element’s pivot, rotation axis, size and parent link, either in lookup textures (PP2) or in the mesh’s own vertex data (PP1), and a wind material reads them in the vertex shader.

Authoring that data normally means a 3ds Max round-trip. Pivot Painter Lab computes all of it inside Unreal: it analyses the mesh, splits it into wind elements, builds the hierarchy, computes the pivots, bakes, and generates the wind materials. Bakes are drop-in compatible with Epic’s stock Pivot Painter 2 shader, or you can use the richer built-in EQLabs wind material.

The Pivot Painter Lab launcher: Auto-Wizard, Open Existing, Create New, Batch Bake, and Generate Falling-Leaves FX.
The Pivot Painter Lab launcher: Auto-Wizard, Open Existing, Create New, Batch Bake, and Generate Falling-Leaves FX.
A static tree split into a hierarchy, a pivot and axis computed for every piece, then baked: the source stands still while the baked copy moves in the wind.
  • You have static-mesh vegetation (bought, scanned, or modelled) and want it moving in wind without going back to a DCC.
  • You need a whole forest to sway believably: per-instance variation so trees don’t move in lockstep, and one global wind control for the scene.
  • You want seasons: a scene-wide, luminance-preserving leaf tint you can animate from Sequencer.
  • You want falling leaves or foliage that bends away from the player, both shipping in the packaged game.
  • Not for skeletal-mesh foliage. This bakes static meshes; a rigged plant belongs in an animation pipeline.
  • Not a substitute for good UVs and material work. It generates a wind material and harvests the mesh’s own textures — it does not author the look.
  • Interactive bending is for grass and bush height. On tall trees the root-planted weighting makes it negligible by design.
  1. Enable Pivot Painter Lab (Edit → Plugins → search “Pivot Painter”), restart the editor.
  2. The fastest possible result: right-click any tree Static Mesh in the Content Browser → Pivot Painter → Bake. The plugin analyses the mesh, splits it into wind elements, bakes, and drops a ready swaying mesh (<Name>_PP2) next to the original. Place it in a level — it is already moving.

That is the whole loop. Everything below is about getting better results and using the extra features.

Tools → Pivot Painter opens a launcher with five entry points:

ButtonWhat it does
Auto-Wizard — Guided BakeThe recommended five-step flow
Create New…A blank Pivot Painter project for the Full Lab
Open Existing…Reopen a saved project
Batch Bake…Run a saved preset across many meshes
Generate Falling-Leaves FX (Niagara)Build the leaf system

A guided five-step flow that gets a beginner to a good bake in a handful of clicks:

  1. Pick a mesh — your tree or bush.

  2. Assess — a plain-English complexity read-out (Simple / Moderate / Complex / Advanced) with the reasons: triangle count, connected pieces, leaf-versus-wood ratio.

  3. Four questions, all pre-filled from the analysis so you can click straight through:

    • What is this? Auto / Tree / Bush / Grass-cards / Rocks / Solid sculpt / Prop / Mechanical.
    • How much wind? Still / Gentle / Normal / Strong.
    • Quality vs Performance
    • Orientation. Auto Z-up, lying along X, lying along Y.

    An Advanced expander exposes the detection backbone, hierarchy algorithm and minimum element size.

  4. Preview the split — the mesh tints by detected element so you can see the segmentation before committing. Re-run if you change the backbone.

  5. Bake — watch the result sway live in the preview, then Save as Preset, open it in the Content Browser, or hand off to the Full Lab.

The bake step has four opt-in checkboxes: Generate impostor LOD, Prep for falling-leaf FX, Interactive bending, and Use Epic’s stock Pivot Painter 2 shader.

The Full Lab after detection: three elements at one hierarchy level with their triangle counts, and Bake still greyed out because pivots have not been computed yet.
The Full Lab after detection: three elements at one hierarchy level with their triangle counts, and Bake still greyed out because pivots have not been computed yet.

Right-click a Static Mesh (or a multi-selection) → Pivot Painter → Bake. Same intelligence as the wizard with default answers: probe the archetype, pick a detection + hierarchy recipe, bake, apply the wind material with the mesh’s own textures harvested automatically. Bake (Options…) gives the non-guided dialog. Good for batch-processing a folder of vegetation.

ArchetypeDetection + hierarchy
Complex treeIslands + Skeleton-First
BushIslands + Topology
Grass cards & scatterIslands + FlatRoots — every card its own level-0 root
Welded solidSmart-Cut + Skeleton or Topology
Single pieceWhole-mesh L0
Prop / assemblySections or Smart-Cut + Topology, near-still wind

The validation gate stays hard: a failed route falls back down the chain and the fallback is reported rather than hidden.

Double-click a Pivot Painter project, or Open in Lab from the wizard, for the complete editor: a 3D viewport, the element list, the hierarchy tree and manual tools.

  • Detect sub-elements with a chosen backbone:
    • Sections. Split by material section (artist-curated).
    • Islands. Split by connected geometry (separate leaf cards, modular kits).
    • Smart-Cut. Split a welded sculpt by surface angle and concavity (trunk vs branches).
    • Auto-Pick. Tries the above in order and keeps the best, cleaning up tiny fragments.
  • Paint roles. Mark elements as Support Wood / Leaf / Vine / Flower / Static / Ignore. The. classifier guesses from slot names and geometry; you correct where needed.
  • Build the hierarchy. Topology or Skeleton-First; pin a root, lock a parent link.
  • Compute pivots. Junction pivots and PCA rotation axes, computed automatically.
  • Bake PP1 or PP2, always to a non-destructive duplicate. Your source asset is never. modified.

Every manual choice (roles, locks, pinned root, backbone) can be saved as a Preset and reused in the Batch Bake window across many meshes.

The same project after the bake: two hierarchy levels, and the Output section now carrying the baked mesh, its two textures and the generated preview material instance.
The same project after the bake: two hierarchy levels, and the Output section now carrying the baked mesh, its two textures and the generated preview material instance.

After baking, select the mesh’s Material Instance (<Name>_PP2_MIC…). All wind controls live in the EQ Pivot Wind and EQ Foliage Surface parameter groups:

ParameterEffect
EQ Wind DirectionWorld-space direction the foliage leans
EQ Max Rotation L0…L3How far each hierarchy level (trunk → leaves) bends
EQ Speed Mul L0…L3Per-level sway speed
EQ Gust *Gust strength / scale / speed for the wandering gust layer
EQ Leaf Wander *Fine leaf flutter amount and speed
EQ Instance Variation0–2: how much each placed copy differs in phase, amplitude and speed, so a forest doesn’t sway in lockstep
EQ Bend Falloff, EQ ShelterStiffness shaping
EQ Manual Time + EQ Use Manual TimeDrive wind time from Sequencer or a synced render instead of game time

For animated normals (leaves catch light as they bend) enable the EQ Animate Normals static switch on the MIC.

One asset drives all foliage at once: Content/PivotPainterLab/Material/MPC_EQLabsWind, a Material Parameter Collection. Edit it directly, or drive it from a Blueprint or a WindDirectionalSource, and every baked mesh in the scene responds.

Global wind:

MPC parameterEffectDefault
GlobalWindStrengthMaster multiplier on all bend1
GlobalWindSpeedMaster multiplier on all speed1
GlobalWindDirectionScene-wide wind lean — supersedes per-mesh direction—

Seasonal colour:

MPC parameterEffect
GlobalSeasonTintTarget season colour
GlobalSeasonBlend0 = summer / off … 1 = full season
GlobalSeasonVariationPer-instance spread, so trees turn at slightly different times

The tint is luminance-preserving — it recolours leaves while keeping their light and dark detail — and applies to leaf slots only, so bark and trunks never tint. Animate GlobalSeasonBlend from a Blueprint or Sequencer for a live season transition across the scene.

Season quick-set (console). These set the MPC and preview immediately; save the MPC to keep it:

EQLabsSeason.Summer EQLabsSeason.Spring EQLabsSeason.Autumn EQLabsSeason.Winter

Seasonal colour needs the baked material to have EQ Enable Season Color on. New bakes enable it automatically on leaf slots; older bakes can toggle it on the MIC.

An octahedral impostor is a single camera-facing billboard that looks like the tree from any angle — the cheapest possible far-distance representation. Check Generate impostor LOD on the wizard’s bake step (or in the one-click options) and it is attached as the mesh’s final LOD, replacing any existing card LOD.

FieldWhat it controls
Frames (NxN)Atlas grid size. 12 is a good default; more = smoother angle transitions
Atlas (px)Texture resolution. 2048 suits ~12 frames; 4096 for 16+ frames or hero trees

The impostor is a camera-facing billboard driven by World Position Offset, and Unreal can disable WPO at distance, which flattens the card. On placed instances, set World Position Offset Disable Distance = 0 (Static Mesh Component → Rendering). This is a per-component setting — it cannot be baked into the asset.

Wind-driven leaves that spawn from the tree’s canopy and drift with the global wind, tinting with the season. This is a runtime feature — it ships in packaged games — built on Niagara.

Setup:

  1. Bake the tree with Prep for falling-leaf FX checked. This sets Allow CPU Access on the mesh (required — without it Niagara spawns zero particles in a cooked build) and records which section is the leaves.
  2. Place an EQLabs Foliage actor, or add a UEQLabsFoliageFXComponent to any actor with a Static Mesh Component. Assign your baked mesh and a leaf Niagara System.
  3. Play. Leaves spawn from the canopy, fall and drift along the wind. Run EQLabsSeason.Autumn and they fall orange.

The component reads MPC_EQLabsWind each frame and pushes wind and season into the emitter as User.* parameters, skipping off-screen trees automatically.

The plugin ships NS_EQLabs_FallingLeaves, but any Niagara system that exposes these System User parameters works. Names must match exactly; missing parameters are simply ignored by Niagara, so a partial implementation still runs — it just won’t react to that input.

User parameterTypeMeaningWritten
User.WindDirectionVectorWorld-space wind direction, from MPC_EQLabsWind.GlobalWindDirectionEvery tick, if Bind To Wind
User.WindStrengthFloatGlobal wind strength multiplierEvery tick
User.WindSpeedFloatGlobal wind speed multiplierEvery tick
User.SeasonTintLinear ColorSeason colour, from GlobalSeasonTintEvery tick, if Bind To Season
User.SeasonBlendFloat0 = summer / off … 1 = full seasonEvery tick
User.DensityFloatSpawn-rate multiplierOnce at spawn
User.LeafSectionIntLOD0 section index holding the leaves (-1 = whole mesh)Once at spawn

Generate Falling-Leaves FX (Niagara) on the launcher builds a system that satisfies the contract above and adds seven more User parameters you can tune directly in the Niagara editor:

User parameterTypeDefaultWhat it does
User.BaseSpawnRateFloat30Leaves per second before User.Density scales it
User.LeafLifetimeFloat6.0Seconds a leaf lives
User.LeafColorLinear Color(0.35, 0.50, 0.12)Base leaf colour, before the season lerp
User.GravityVector(0, 0, -180)Downward acceleration — deliberately far below real gravity so leaves flutter
User.DragFloat1.5Air resistance
User.FlutterStrengthFloat60Curl-noise amount driving the sideways drift and spin
User.WindPushScaleFloat300How hard User.WindDirection × User.WindStrength pushes a leaf

User.SeasonTint defaults to (1.0, 0.55, 0.15) — the autumn orange — with User.SeasonBlend at 0, so the system ships looking like summer until the MPC drives the blend up.

The generated falling-leaf Niagara system: emitter stack on the right, the User Parameters the component writes listed at the bottom left.
The generated falling-leaf Niagara system: emitter stack on the right, the User Parameters the component writes listed at the bottom left.

Authoring your own leaf system — the recipe the shipped one follows:

  • Emitter Spawn: a Static Mesh Location data interface with Source Mode: Attach Parent (samples whatever tree the component attached to — do not hard-assign a mesh). Drive the section filter from User.LeafSection so leaves emit from the canopy rather than the trunk. Sample the mesh surface, area-weighted, for spawn position and normal.
  • Update: spawn rate = base × User.Density; light downward acceleration plus drag so leaves flutter rather than drop; wind push adds normalize(User.WindDirection) × User.WindStrength × k to velocity; a Curl-Noise force scaled by User.WindSpeed gives the sideways drift; random initial rotation plus a slow spin. Kill below the tree’s base Z or on ground collision.
  • Render: sprite or low-poly leaf mesh; multiply leaf colour by lerp(1, User.SeasonTint, User.SeasonBlend) — the same maths the foliage master uses, so a falling leaf and the tree it left agree.

Performance. Assign a Niagara Effect Type to the system for distance culling and pooling. The component’s bOnlyWhenRendered already skips the MPC push for off-screen trees, but the Effect Type is what culls the simulation — both matter at forest scale. Instanced foliage (HISM) cannot carry a per-instance Niagara system economically, so gate the FX to hero trees.

Foliage that bends away from the player and anything you tag. Also runtime.

  1. Bake with Interactive bending checked, which enables the gated bend branch on the baked materials.
  2. In game or PIE the first player pawn automatically pushes nearby foliage. To add more pushers — a rolling boulder, an NPC, a vehicle — drop an EQLabs Foliage Interactor component on the actor and set its Radius.

Limit, stated plainly: interaction runs through four concurrent slots in the material parameter collection. With more than four interactors in range, the four nearest to the player win and the rest are ignored for that moment, picking back up as distances change. This is a design constraint of the 2-MPC / 4-slot material budget, not a bug. Dense-trample scenarios with hundreds of persistent trails are render-target territory, and are not what this does.

Tuning (on the MIC, EQ Interaction group):

ParameterEffect
EQ Interaction PushHow hard foliage is shoved aside, horizontally
EQ Interaction FlattenDownward press when very close
EQ Interaction Bend HeightBelow this height the bend fades to nothing, keeping roots planted. Lower = stiffer base

The bend adds on top of the wind — both animate together.

Chosen by the wizard’s Quality vs Performance question, or a preset’s Bake Texture Set:

  • Standard (2 textures). Pivot + Parent, Axis + Extent. Drop-in compatible with Epic’s stock. PivotPainter2FoliageShader and any third-party PP2 shader. Uses Epic’s top-left texture convention exactly. Pick this for maximum compatibility or to use your own PP2 material.
  • Extended (4 textures). Adds Origin/Order and Extents/Level, unlocking the full EQLabs wind. material: semantic wind buckets, per-instance variation, seasons, gusts, leaf wander, animated normals, interactive bending. This is the default.

Both come from the same pipeline; Extended is a superset.

“Use Epic’s stock Pivot Painter 2 shader” builds the baked materials on Epic’s engine PivotPainter2FoliageShader function itself. Your harvested textures (albedo / normal / ORM) and the seasonal colour still apply, and wind is tuned through Epic’s own MIC parameters (Animate Level 1–4, Wind Speed, custom range). EQLabs-only extras — per-instance variation, global MPC wind, gusts, leaf wander, interactive bending — are not available on that shader. Pick it when you need guaranteed interop with existing PP2 content or tools; otherwise the default EQLabs material gives richer motion. Generated assets use an _Epic name family (<Name>_EpicMIC…), so both variants can live side by side.

PP1 is the original Pivot Painter format. Instead of lookup textures it packs everything onto the mesh itself — vertex colour plus two UV channels. Choose it in the Lab’s Mode dropdown, or a preset’s Mode field.

ChannelContentsNotes
Vertex Colour RGBElement’s forward (X) axis, remapped [-1,1] → [0,1]sRGB pre-cancelled — see below
Vertex Colour AExtent.X / Extent Custom Range, clamped to [0,1]Stays linear; drives bend amplitude
UV2Pivot.X, Pivot.YCentimetres, mesh-local
UV3Pivot.Z, ShaderLevel / 3Same fixed /3 semantic scale as PP2’s Tex4.A

PP1 when you want zero texture samples per element, the asset needs only one level of rotation (grass tufts, scatter debris, small props, card foliage with a single sway), or you are targeting very constrained hardware or writing your own shader.

PP2 when (the default, and usually right) you need hierarchical motion — trunk → branch → twig → leaf. PP1 cannot traverse parents; that is exactly what the texture lookup buys. Also for every EQLabs extra: semantic wind buckets, per-instance variation, global MPC wind and seasons, gusts, leaf wander, animated normals, interactive bending. And past roughly 3000 elements, PP1’s per-vertex precision caps out around Epic’s documented sub-object limit — the Lab warns and you should switch.

PP1 covers LOD0; enable Propagate to all LODs to carry the payload down by nearest-vertex match.

Vertex colour and sRGB. The static-mesh build applies sRGB gamma encoding when it packs vertex colours for the GPU, but a material’s VertexColor node reads those bytes back without decoding. Left alone, that corrupts the axis data. The baker pre-applies the inverse curve so the build’s encoding cancels out and your shader receives what was authored. Alpha skips the gamma path and is stored linear. You don’t need to do anything — but if you write your own PP1 shader, read the vertex colour raw; do not decode it again.

Lightmap UVs can eat the payload. PP1 lives in UV2 and UV3. If the source mesh has Generate Lightmap UVs pointed at either channel, a rebuild would regenerate it and silently overwrite the pivot data — the mesh would then animate from packed lightmap coordinates. The baker detects this and moves the generated lightmap to a free higher channel (disabling generation if none is free), logging a warning either way. If you see that warning, nothing is wrong: it means the guard did its job.

“My foliage isn’t moving.” Confirm the placed mesh uses the baked _PP2 material instance, not the original material. The wind master rebuilds itself when the plugin updates — if you baked on an older version, re-bake so the mesh’s lookup UVs match the current material.

“The impostor card goes flat or white at distance.” Set World Position Offset Disable Distance = 0 on the placed component.

“No leaves spawn in my packaged build.” Re-bake with Prep for falling-leaf FX checked — it sets Allow CPU Access, which the Niagara mesh sampler needs in cooked builds.

“Seasons don’t do anything.” Raise GlobalSeasonBlend above 0 on MPC_EQLabsWind, and make sure the mesh was baked with season colour enabled on its leaf slots.

“The whole forest sways identically.” Raise EQ Instance Variation on the MIC (0–2) for per-instance phase, amplitude and speed offsets.

“Detection split my tree into one giant element.” Try the Smart-Cut backbone (welded sculpts) or Islands (separate cards) in the wizard’s Advanced expander, or add manual seams in the Full Lab.

“A leaf rotates around the wrong point.” Open the Full Lab, select the element, and lock its parent to the correct branch — the pivot follows the locked parent.

The plugin deliberately ships its regression suite (PivotPainterLabTests, editor-only — it never cooks into a game). If you suspect a broken install or a corrupted bake, run the same checks the releases are gated on, headlessly:

UnrealEditor-Cmd.exe <YourProject>.uproject -run=PivotPainterValidate -nullrhi

Exit code 0 means every case passed — the code is the number of failures, which is CI-friendly. The v1.0.1 release was cut with 44 of 44 cases passing.

It also bundles bake forensics: -DiagnoseBake=<path base> decodes a bake set on disk and reports element counts, parent sanity and dead texels — useful when a mesh animates strangely and you want to know whether the bake or the scene is stale.

  • Interactive bending is capped at four simultaneous interactors. See the section above. This. is a material-budget constraint, not a temporary limit.
  • Falling leaves need Allow CPU Access. If you bake without Prep for falling-leaf FX, the effect works in the editor and produces nothing in a cooked build.
  • The impostor needs a per-component setting (World Position Offset Disable Distance = 0) that cannot be baked into the asset.
  • Epic-shader bakes lose the EQLabs extras. That is the trade for stock-shader interop, and it is not recoverable by tweaking the MIC.
  • LeafFX.EditorUI.QAPass is unreliable in a cold clean host. The plugin’s own falling-leaf UI test passes on a warmed editor but not consistently on a first cold launch — a known weakness of the test, not of the feature, which the release gate handles by comparing against a recorded baseline rather than demanding green.

Pivot Painter Lab is a standalone-only product — it is not part of EQLabs Pro. Buying Pro does not include it.

Report an issue with this tool

Opens our feedback form in a new tab with the tool name pre-filled.