A command-line tool for handling hair files.
Supported file formats:
- .bin
- .hair
- .data
- .ply
- .ma
- .abc
- .npy (write supports uniform number of per-strand segments only)
$ hairutil --help
hairutil COMMAND {OPTIONS}
OPTIONS:
Commands:
autofix Auto-fix issues
convert Convert file type
decompose Decompose into individual curves
filter Extract strands that pass given filter
findpenet Find penetration against head mesh
getcurvature Get discrete curvature & torsion
getroots Extract strand roots as point cloud in PLY
gettips Extract strand tips as point cloud in PLY
info Print information
resample Resample strands s.t. every segment is shorter than twice the target segment length
smooth Smooth strands
stats Generate statistics
subsample Subsample strands
transform Transform strand points, either by one of scale/translate/rotate, or by full 4x4
matrix
tubify Turn curves into tubes as triangle mesh
Common options:
-i[PATH], --input-file=[PATH]
(REQUIRED) Input file
-o[EXT], --output-ext=[EXT]
Output file extension (or extensions by comma-delimited list); when omitted, use input
file extension
--overwrite Overwrite when output file exists
-d[DIR], --output-dir=[DIR]
Output directory; if not specified, same as the input file
--extra-suffix=[STR] Extra suffix appended to the output filename in addition to the existing suffix
--ply-load-default-nsegs=[N]
Default number of segments per strand for PLY files [0]
--ply-save-ascii Save PLY files in ASCII format
-v[NAME], --verbosity=[NAME]
Verbosity level name {trace,debug,info,warn,error,critical,off} [info]
-j, --print-json Print log messages in JSON format, disabling standard logging
--seed=[N] Seed for random number generator (-1 for time-based seed) [0]
--no-autofix Do not auto-fix issues in input
-h, --help Show this help message
Enable bash subcommand completion:
source completions/hairutil-completion.bash
git clone --recursive https://github.com/kenshi84/hairutil
mkdir build && cd build
cmake ..
make -j
hairutil convert --input-file ~/CT2Hair/output/Bangs.bin --output-ext ma
# Output saved to ~/CT2Hair/output/Bangs.ma
hairutil decompose --input-file ~/CT2Hair/output/Bangs.bin --output-ext ply --confirm
# Output saved to ~/CT2Hair/output/Bangs_decomposed_ply/*.ply
$ hairutil filter --help
hairutil filter {OPTIONS}
Extract strands that pass given filter
OPTIONS:
-k[KEY], --key=[KEY] Filtering key chosen from:
length (Total length)
nsegs (Number of segments)
tasum (Turning angle sum)
maxseglength (Maximum of segment length)
minseglength (Minimum of segment length)
maxsegtadiff (Maximum of segment turning angle difference)
minsegtadiff (Minimum of segment turning angle difference)
maxptcrr (Maximum of point circumradius reciprocal)
minptcrr (Minimum of point circumradius reciprocal)
maxptta (Maximum of point turning angle)
minptta (Minimum of point turning angle)
maxptcurv (Maximum of point curvature)
minptcurv (Minimum of point curvature)
--lt=[R] Less-than threshold
--gt=[R] Greater-than threshold
--leq=[R] Less-than or equal-to threshold
--geq=[R] Greater-than or equal-to threshold
--output-indices Output selected strand indices as txt
--no-output Do not output filtered hair file, only show number of filtered strands
Example:
hairutil filter -i ~/CT2Hair/output/Bangs.bin -o ply --overwrite --key length --geq 174.96289
# Output saved to ~/CT2Hair/output/Bangs_filtered_length_geq_174.96289.ply
$ hairutil findpenet --help
hairutil findpenet {OPTIONS}
Find penetration against head mesh
OPTIONS:
-m[PATH], --mesh-path=[PATH] (REQUIRED) Path to triangle mesh
-d[RATIO],
--decimate-ratio=[RATIO] Ratio for decimating triangle mesh
[0.25]
-t[RATIO],
--threshold-ratio=[RATIO] Threshold ratio [0.3]; detect strand as
penetrating if #in-points is more than
this value times #total-points
--no-export Do not export result to txt
--no-print Do not print result to stdout
Extract the first / last point of every strand and save them as a point cloud in PLY format. The output is written next to the input file with _roots.ply / _tips.ply appended (regardless of --output-ext).
hairutil getroots --input-file ~/CT2Hair/output/Bangs.bin
# Output saved to ~/CT2Hair/output/Bangs_roots.ply
hairutil gettips --input-file ~/CT2Hair/output/Bangs.bin
# Output saved to ~/CT2Hair/output/Bangs_tips.ply
hairutil info --input-file ~/cemyuksel/wCurly.hair
[info] Number of strands: 50000
[info] Number of points: 3441580
[info] ================================================================
[info] Segments array: Yes
[info] Points array: Yes
[info] Thickness array: No
[info] Transparency array: No
[info] Colors array: No
[info] Default thickness: 0.1
[info] Default transparency: 0.4
[info] Default color: (0.28718513, 0.22646429, 0.14465585)
[info] ================================================================
$ hairutil resample --help
hairutil resample {OPTIONS}
Resample strands s.t. every segment is shorter than twice the target segment length
OPTIONS:
-l[R], --target-segment-length=[R]
(REQUIRED) Target segment length (0 uses per-strand average segment length)
--linear-subdiv Use linear subdivision
--catmull-rom Use centripetal Catmull-Rom interpolation
--cr-power=[R] Power parameter for Catmull-Rom (default: 0.5)
--c2-interp Use hybrid C2-interpolating spline
$ hairutil smooth --help
hairutil smooth {OPTIONS}
Smooth strands
OPTIONS:
--lambda=[R] Smoothness weight [1.0]
$ hairutil stats --help
hairutil stats {OPTIONS}
Generate statistics
OPTIONS:
--sort-size=[N] Print top-N sorted list of items [10]
--no-export Do not export result to a .xlsx file
--export-raw-strand Include raw strand data in exported file
--export-raw-segment Include raw segment data in exported
file
--export-raw-point Include raw point data in exported file
--no-print Do not print the stats
$ hairutil subsample --help
hairutil subsample {OPTIONS}
Subsample strands
OPTIONS:
--target-count=[N] (*)Target number of hair strands
--scale-factor=[R] Factor for scaling down the Poisson disk
radius [0.9]
--indices=[N,...] Comma-separated list of strand indices
to extract, or a path to .txt file
containing such a list
--exclude Exclude the specified strands instead of
including them
Example:
hairutil subsample --input-file ~/CT2Hair/output/Bangs.bin --output-ext bin --target-count 1000
# Output saved to ~/CT2Hair/output/Bangs_1000.bin
hairutil subsample -i test/data/Bangs_100.bin -o ply --indices 65,32,4,36,0
# Output saved to test/data/Bangs_100_indices_0_4_32_36_65.ply
$ hairutil transform --help
hairutil transform {OPTIONS}
Transform strand points, either by one of scale/translate/rotate, or by full
4x4 matrix
OPTIONS:
-s[R or R,R,R], --scale=[R or
R,R,R] Scaling factor; either a single number
of comma-separated 3-tuple for
non-uniform scaling
-t[R,R,R], --translate=[R,R,R] Comma-separated 3-vector for translation
-r[R,R,R,R,R,R,R,R,R],
--rotate=[R,R,R,R,R,R,R,R,R] Comma-separated row-major 3x3 matrix for
rotation
-f[R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R],
--full=[R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R]
Comma-separated row-major 4x4 matrix for
full transform
Example:
hairutil transform -i test/data/Bangs_100.bin -o ply --overwrite --scale 1.2 --translate 12.3,45.6,78.9 --rotate 0.407903582,-0.656201959,0.634833455,0.838385462,0.54454118,0.0241773129,-0.361558199,0
.52237314,0.77227056
# Output saved to test/data/Bangs_100_tfm_s_1.2_t_12.3_45.6_78.9_R_0.407904_-0.656202_0.634833_0.838385_0.544541_0.0241773_-0.361558_0.522373_0.772271.ply
$ hairutil tubify --help
hairutil tubify {OPTIONS}
Turn curves into tubes as triangle mesh
OPTIONS:
-r[R], --radius=[R] (REQUIRED) Tube radius
-n[N], --num-sides=[N] Number of sides of tubes [6]
--capped Cap tube ends
--colored Output colored vertices