How to Map and Fit Point Numbers to Custom Ranges in Houdini VEX
31 Aug 26 (2mo ago)
Remapping Point Indices in Houdini VEX
When working with geometry in Houdini, normalizing point numbers (@ptnum) against the total point count (@numpt) is a foundational technique for creating procedural gradients, controlling falloffs, and driving downstream attributes.
The Common Pitfall: Integer Division & Range Mappings
In VEX, @ptnum and @numpt are integers. Dividing two integers can cause precision errors if not cast to floating-point numbers. Additionally, manually scaling fractions can lead to syntax issues and calculation errors.
Here is how to properly normalize and remap point ranges in a Point Wrangle.
1. Basic Normalization (0 to 1)
To map point indices linearly from 0.0 (first point) to 1.0 (last point):
// Cast to float to avoid integer division truncation
float normalized = (float)@ptnum / (float)(@numpt - 1);
// Assign to a custom point attribute
@my_val = normalized;
2. Inverting the Range (1 to 0)
To make the first point @ptnum = 0 output 1.0 and the last point output 0.0:
float normalized = (float)@ptnum / (float)(@numpt - 1);
@my_val = 1.0 - normalized;
3. The Recommended Method: Using fit() or fit01()
Instead of manually multiplying and adding offsets, VEX provides built-in fitting functions that handle the interpolation safely and cleanly.
Mapping to an Arbitrary Range (e.g., 0.1 to 1.0)
// Using fit01 to remap a normalized 0-1 value to 0.1 - 1.0
float normalized = (float)@ptnum / (float)(@numpt - 1);
@my_val = fit01(normalized, 0.1, 1.0);
Alternative Direct fit() Syntax
// Remap directly from index domain [0, @numpt - 1] to target domain [0.1, 1.0]
@my_val = fit((float)@ptnum, 0.0, (float)(@numpt - 1), 0.1, 1.0);
Verification Example (5 Total Points)
When @numpt = 5, indices run from 0 to 4:
@ptnum | Normalized (ptnum / 4.0) | fit01(norm, 0.1, 1.0) |
|---|---|---|
| 0 | 0.00 | 0.100 |
| 1 | 0.25 | 0.325 |
| 2 | 0.50 | 0.550 |
| 3 | 0.75 | 0.775 |
| 4 | 1.00 | 1.000 |