Skip to content

Houdini 21: Object-to-Object Instance/Particle Transformation Research

Procedural Workflow for Coin Morphing Effects


1. CORE WORKFLOW: Scatter Instances on Source Mesh → Morph to Target Mesh

Standard Procedural Pipeline

Step 1: Scatter points on both source and target meshes - Use Scatter SOP (v2.0) on each mesh to generate point distributions - Ensure both have the same point count (use Force Total Count or match densities) - Enable Prim Num Attribute and Prim UVW Attribute output options for later interpolation - For consistent point distributions across different meshes, consider scattering "In Texture Space" (if UVs are available and consistent)

Step 2: Match source points to target points - Several matching strategies (see Section 3 below for details): - Nearest-point matching: Use nearpoint() or nearpoints() in VEX - Surface-distance matching: Use xyzdist() for closest surface location - Random/staggered matching: Shuffle target point order for more organic transitions - Attribute-driven matching: Sort both point clouds by spatial position and match by index

Step 3: Animate the morph with VEX - Store both source (source_pos) and target (target_pos) positions on each point - Use lerp() for position interpolation: P = lerp(source_pos, target_pos, blend) - Use slerp() for quaternion orientation interpolation: orient = slerp(source_orient, target_orient, blend) - Drive the blend parameter with a ramp or noise for staggered/particle-like timing - Add intermediate "fly" positions using noise, curl noise, or offset paths

Step 4: Instance coins onto the morphing points - Use Copy to Points SOP (v2.0) to stamp coin geometry onto the animated points - For large point counts, use packed primitives or render-time instancing for performance - Key instance attributes on points: orient, pscale, scale, N, up, v, pivot, transform

Step 5: Add secondary motion (optional) - Point Jitter SOP (H21 now has mask parameter) for organic wobble - Noise-based offsets during flight phase - Spin/tumble via animated orient using dihedral() or qrotate()

VEX Code Example: Point Wrangle for Morphing

// Run over points - input 0 has both source_pos and target_pos attributes
// blend is driven by a ramp parameter or channel reference

float blend = chf("blend");  // 0 = source shape, 1 = target shape

// Per-point staggered timing using noise or ID
int ptid = @ptnum;
float stagger = noise(@ptnum * ch("stagger_freq")) * ch("stagger_amount");
float local_blend = clamp(blend - stagger, 0, 1);

// Smooth the blend curve
local_blend = chramp("blend_curve", local_blend);

// Position morph
vector src_P = v@source_pos;
vector tgt_P = v@target_pos;

// Optional: Add arc trajectory instead of straight line
vector mid_P = lerp(src_P, tgt_P, 0.5);
mid_P += curlnoise(@P * ch("curl_freq")) * ch("curl_amp") * sin(local_blend * M_PI);

@P = lerp(src_P, tgt_P, local_blend);
// With arc: @P = lerp(lerp(src_P, mid_P, local_blend), lerp(mid_P, tgt_P, local_blend), local_blend);

// Orientation morph
vector4 src_orient = p@source_orient;
vector4 tgt_orient = p@target_orient;
p@orient = slerp(src_orient, tgt_orient, local_blend);

// Scale pulse during flight
float scale_pulse = 1.0 + sin(local_blend * M_PI) * ch("scale_bulge");
f@pscale *= scale_pulse;

2. POINT MATCHING STRATEGIES (Critical for Quality)

Strategy A: Nearest Point (Simplest)

// Point Wrangle on source points, input 1 = target points
int target_pt = nearpoint(1, @P);
v@target_pos = point(1, "P", target_pt);
p@target_orient = point(1, "orient", target_pt);
- Pros: Simple, fast - Cons: Can create clumping (multiple source points → same target point)

Strategy B: Nearest Point with Exclusion (Better Distribution)

// Use nearpoints() to find multiple candidates, then use unique assignment
int targets[] = nearpoints(1, @P, ch("maxdist"), chi("maxpts"));
// Filter out already-assigned targets (requires tracking via attribute or array)
- Requires more complex logic (often a Solver or For-Each loop) - Best for organic, non-overlapping distributions

Strategy C: Sort-Based Matching

// Sort both source and target points by spatial position (e.g., by distance from centroid)
// Then match by index (ptnum)
// Use Attribute Sort SOP (new in Houdini 21!) or Sort SOP
- Good for shapes with similar spatial distributions - Predictable, no clumping

Strategy D: xyzdist Surface Matching

// For each source point, find closest surface location on target
int target_prim;
vector target_uv;
float dist = xyzdist(1, @P, target_prim, target_uv);
v@target_pos = primuv(1, "P", target_prim, target_uv);
- Projects source points onto target surface - Good for surface-constrained transitions

Strategy E: VDB/Volume-Based Transfer

  • Convert both meshes to SDF volumes (VDB from Polygons)
  • Scatter points on the target SDF surface using VDB analysis
  • Match using closest point in volume space
  • Best for very different topologies

3. KEY Houdini 21 NODES FOR THIS WORKFLOW

Scatter SOP (v2.0)

  • Scatters points across surfaces or through volumes
  • Critical feature: "Stick on deforming geometry" workflow using Attribute Interpolate
  • Scatter once on rest geometry → Attribute Interpolate deforms points with animated mesh
  • Output Prim Num Attribute and Prim UVW Attribute for tracking
  • Density can be controlled by attributes or texture maps
  • "In Texture Space" mode for consistent scattering across different meshes with same UVs

Copy to Points SOP (v2.0)

  • Copies geometry onto points with full instance attribute support
  • Piece Attribute: Copy different source geometry to different points
  • Supports orient, pscale, scale, N, up, v, rot, trans, pivot, transform attributes
  • For large counts: use packed primitives or render-time instancing

Attribute Interpolate SOP

  • Interpolates attributes between geometries using:
  • Primitive number + UVW weights
  • Point numbers + weights (array attributes)
  • Vertex numbers + weights
  • Key for scatter-to-deform workflows: Keep scattered points consistent on deforming geometry
  • Can compute weights from primitive UVW for reuse

Blend Shapes SOP (v2.0)

  • Computes 3D metamorphosis between shapes WITH THE SAME TOPOLOGY
  • Supports painted masks and per-blend mask options
  • Limitation: Requires matching topology — NOT suitable for different mesh shapes
  • Only useful if source and target have identical point/prim counts

Ray SOP

  • Projects points from one surface onto another
  • Houdini 21 addition: Bidirectional option (closest or farthest hit)
  • Methods: Ray projection along normals OR Minimum Distance (shrinkwrap)
  • Useful for initial target point placement

New Houdini 21 SOPs with Mask Support

  • Peak SOP, Soft Peak SOP, Inflate SOP, Flatten SOP, Point Jitter SOP — all now have mask parameters
  • Point Jitter with mask = great for adding organic variation to coin positions

Separate Pieces SOP (New in H21)

  • Offsets individual pieces of geometry by unique attribute
  • Useful for exploding/separating coins before reforming

4. APEX CAPABILITIES IN HOUDINI 21 FOR THIS WORKFLOW

APEX Overview

APEX is Houdini 21's rigging and character animation graph framework, deeply integrated with KineFX. It is designed for: - Building character rigs procedurally - Managing transform hierarchies (skeletons, controls) - Channel/animation manipulation - Procedural rigging via Autorig Builder/Components

APEX Nodes Available

Key APEX nodes include: - RunVex: Executes custom VEX snippets within APEX graphs — this is the bridge for custom geometry manipulation - TransformObject: Manages transform hierarchies, animation-friendly TRS inputs, constraints - Lerp/NLerp/Slerp: Built-in interpolation nodes (position/orientation blending) - Noise: Perlin-style noise for procedural variation - Math nodes: Add, Subtract, Multiply, Clamp, Fit, etc. - For/ForEach loops: Iteration within APEX graphs - If/Else: Conditional logic - RampLookup: Ramp evaluation for blend curves - Switch/SwitchByName: Conditional value selection

Can APEX Be Used for This Workflow?

Short answer: Not recommended as the primary approach.

Reasoning: 1. APEX is designed for character rig transforms, not point-cloud-level operations. APEX TransformObject manages a hierarchy of transforms (like skeleton joints), not thousands of scattered particle positions.

  1. APEX operates on a different abstraction level: It works with named transform objects (controls, joints) in a hierarchy, not with arbitrary point clouds. You would need one TransformObject per coin, which is impractical for thousands of instances.

  2. The RunVex node CAN execute custom VEX within an APEX graph, so technically you could implement point morphing logic there. But this essentially bypasses APEX's purpose — you'd just be writing VEX inside an APEX wrapper.

  3. No native point cloud or scatter operations exist in APEX. There are no equivalents of nearpoint(), xyzdist(), pcfind(), or Scatter SOP functionality.

  4. Where APEX could be useful: If you want to rig a single coin with articulation (bending, tumbling), or if you want to drive a small number of "hero" coins with rig-like controls, APEX could add value for those specific elements.

Recommendation: Use SOPs + VEX wrangles for the main coin morphing effect. APEX is the wrong tool for this specific job. Reserve APEX for character rigging tasks it was designed for.


5. BEST PRACTICES FOR POINT-BASED MORPHING

Point Count Management

  • Always match point counts between source and target scatter distributions
  • Use Scatter SOP's "Force Total Count" to ensure identical counts
  • Alternative: Scatter extra points, then use Point Generate SOP or Wrangle to add/remove to match

Staggered/Timed Transitions (Avoids "Boring" Uniform Morph)

// Per-point delay based on spatial position
float delay = fit(length(v@source_pos - getbbox_center(0)), ch("min_dist"), ch("max_dist"), 0, ch("max_delay"));
float local_time = max(0, @Time - delay);
float blend = chramp("transition", fit(local_time, 0, ch("duration"), 0, 1));
- Radial propagation: delay based on distance from center - Wave propagation: delay based on one axis - Noise-based: delay based on 3D noise for organic feel - Random per-point: delay based on rand(@ptnum)

Orientation Handling

  • Always use orient (quaternion) attribute — NOT N/up vectors for animated instances
  • slerp() for quaternion interpolation preserves shortest path
  • For tumbling coins: add incremental rotation during flight:
    vector4 flight_rot = quaternion(radians(ch("tumble_deg")) * local_blend, normalize(v@flight_axis));
    p@orient = qmultiply(slerp(src_orient, tgt_orient, local_blend), flight_rot);
    

Arc Trajectories (Coins Should Fly, Not Slide)

  • Simple arc: Use quadratic bezier between source → apex → target
    vector apex = lerp(src_P, tgt_P, 0.5) + ch("arc_height") * normalize(cross(tgt_P - src_P, {0,1,0}));
    vector a = lerp(src_P, apex, local_blend);
    vector b = lerp(apex, tgt_P, local_blend);
    @P = lerp(a, b, local_blend);
    
  • More complex: Use curl noise or custom curve paths
  • Alternative: Use POP VOP/POP Wrangle in a DOP network for physics-based flight

Scale and "Pop" Effects

  • Coins can scale down to 0 at departure, fly as small, scale up at arrival
  • Or pulse scale during flight for energy feel
  • pscale attribute drives this per-point

Performance Tips

  • Render-time instancing for >10K coins (create packed primitives, not real geometry)
  • Use instancefile or instance attribute for disk-based instances
  • If real geometry needed (for collisions/sim): limit coin count or use LOD
  • VEX Wrangles are significantly faster than VOPs for this kind of per-point logic
  • Cache the scatter points to disk if geometry is static

[Source Mesh] → Scatter SOP → [Source Points]
[Target Mesh] → Scatter SOP → [Target Points]
                    Point Wrangle (match + store target_pos/target_orient)
                    Point Wrangle (animated morph with lerp/slerp + stagger)
[Coin Geometry] ────────→ Copy to Points SOP → [Output]
                              (or Instance SOP for render-time)

Alternative with POP Solvers for Physics

[Source Mesh] → Scatter SOP → [Source Points]
[Target Mesh] → Scatter SOP → [Target Points]
              Attribute Create (v = target_pos - source_pos)
              POP VOP / POP Wrangle in DOP Network
              (use v@v as attraction force toward target)
              Copy to Points / Instance

Alternative with Vellum for Coin Physics

Same scatter setup → Vellum Grains (with target attraction)
                    → Pin to Target with stiffness
                    → Add wind/turbulence for flight path variation

7. KEY VEX FUNCTIONS REFERENCE

Function Purpose Usage
lerp(a, b, t) Linear interpolation of positions/vectors P = lerp(src, tgt, blend)
slerp(q1, q2, t) Spherical interpolation of quaternions/matrices orient = slerp(src_q, tgt_q, blend)
nearpoint(geo, pos) Find closest point index Point matching
nearpoints(geo, pos, rad, max) Find N closest points Better point matching
pcfind(geo, channel, pos, rad, max) Find close points in radius Proximity queries
xyzdist(geo, pos, prim, uv) Closest surface location + prim/UV Surface matching
primuv(geo, attr, prim, uvw) Sample attribute at parametric UV Attribute transfer
dihedral(v1, v2) Quaternion rotating v1 to v2 Orientation alignment
qrotate(angle, axis) Quaternion from axis-angle Coin tumbling
qmultiply(q1, q2) Quaternion multiplication Combine rotations
pointtransform(geo, ptnum) Get instance transform matrix from point attributes Read instance transforms
curlnoise(pos) Curl noise for organic displacement Flight path variation
rand(seed) Random number generation Per-point variation
fit(val, src_min, src_max, dst_min, dst_max) Remap values Timing/spatial remapping

8. INSTANCING POINT ATTRIBUTES (Complete Reference)

These attributes on points control Copy to Points / instance behavior:

Attribute Type Description
orient float4 (quaternion) Orientation of the copy
pscale float Uniform scale
scale float3 Non-uniform scale
N vector Normal (+Z axis if no orient)
up vector Up vector (+Y axis if no orient)
v vector Velocity (motion blur, +Z if no orient/N)
rot float4 (quaternion) Additional rotation after orient
P vector Translation of the copy
trans vector Additional translation
pivot vector Local pivot point
transform 3×3 or 4×4 matrix Override transform (except P/pivot/trans)

Priority order: If transform exists, it overrides orient/scale/rot. If orient exists, it overrides N/up alignment. If neither, N and up define orientation.


SOURCES

  • SideFX Houdini 21.0 Official Documentation (sidefx.com/docs/houdini21.0/)
  • Scatter SOP 2.0 docs (sidefx.com/docs/houdini/nodes/sop/scatter.html)
  • Copy to Points SOP 2.0 docs (sidefx.com/docs/houdini/nodes/sop/copytoanchors.html)
  • Attribute Interpolate SOP docs
  • Blend Shapes SOP 2.0 docs
  • Ray SOP docs (with new H21 bidirectional feature)
  • APEX nodes index (sidefx.com/docs/houdini/nodes/apex/index.html)
  • RunVex APEX node docs
  • TransformObject APEX node docs
  • Copying and Instancing point attributes docs
  • VEX functions: lerp, slerp, nearpoint, xyzdist, primuv, pcfind, pointtransform
  • Houdini 21 What's New - Modeling, Geometry, and Terrains
  • Houdini 21 What's New - APEX, KineFX, and Animation
  • Houdini 21 What's New - VEX and OpenCL