Transform¶
This page contains classes defined in hakowan.transform module.
Composable geometry and attribute transform models.
Transform
dataclass
¶
Transform is the base class of all transforms.
Source code in hakowan/grammar/transform/transform.py
__imul__(other)
¶
In place update by applying another transform after the current transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Transform
|
The transform to apply after the current transform. |
required |
Source code in hakowan/grammar/transform/transform.py
__mul__(other)
¶
Apply another transform, other, after the current transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Transform
|
The other transform. |
required |
Returns: A new transform that is the composition of the current transform and other.
Source code in hakowan/grammar/transform/transform.py
Filter
dataclass
¶
Bases: Transform
Filter data based on a condition.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
AttributeLike | None
|
The attribute to filter on. If None, the vertex position is used. |
condition |
Callable
|
A callable that takes a single argument, the value of the attribute, and returns a boolean indicating whether the data should be kept. |
Source code in hakowan/grammar/transform/transform.py
Clip
dataclass
¶
Bases: Transform
Clip the mesh against a plane, keeping only the half-space the normal points into.
Unlike :class:Filter, which keeps or drops whole facets, Clip slices
through triangles: facets straddling the plane are cut so that only the part
on the positive side of the plane is kept (partial triangles are produced).
The exposed cross-section is left open (it is not capped).
The plane is defined in the data/object coordinate space (the same space the
raw mesh lives in, before any layer-level :class:Affine transform), keeping
its meaning consistent with :class:Filter.
Attributes:
| Name | Type | Description |
|---|---|---|
point |
ArrayLike
|
A point lying on the clipping plane. |
normal |
ArrayLike
|
The plane normal. The half-space where
|
Source code in hakowan/grammar/transform/transform.py
UVMesh
dataclass
¶
Bases: Transform
Extract UV mesh from data.
Attributes:
| Name | Type | Description |
|---|---|---|
uv |
AttributeLike | None
|
The attribute defining the UV coordinates. If None, automatically deetect the UV attribute from the data. |
Source code in hakowan/grammar/transform/transform.py
Affine
dataclass
¶
Bases: Transform
Apply affine transformation to data.
Attributes:
| Name | Type | Description |
|---|---|---|
matrix |
ArrayLike
|
The 4x4 affine matrix to apply. |
Source code in hakowan/grammar/transform/transform.py
PrincipalAxes
dataclass
¶
Bases: Transform
Align PCA principal directions of vertex positions with a target orthonormal frame.
Covariance is computed from the current data-frame vertex positions. Principal
axes are ordered by descending eigenvalue (largest variance first). The rotation and
translation match those directions to the columns of frame: column 0 is the
direction for the largest-variance axis, column 1 for the second, column 2 for the third.
The resulting affine is pre-composed with any prior global transform on the layer, so
earlier Affine transforms (translate / rotate / scale) are preserved and applied
before this PCA-based alignment.
Attributes:
| Name | Type | Description |
|---|---|---|
frame |
ArrayLike
|
3x3 matrix whose columns are the target orthonormal axes (see above). |
orthonormalize_frame |
bool
|
If True (default), orthonormalize |
Source code in hakowan/grammar/transform/transform.py
Normalize
dataclass
¶
Bases: Transform
Recenter and uniformly scale the mesh to fit a unit box centered at the origin.
Vertex positions are translated so the bounding-box center sits at the origin and
uniformly scaled so the bounding-box diagonal is 2 (i.e. the geometry fits inside
the unit sphere). Use it to bring meshes from unrelated coordinate systems to a
comparable on-screen size — for example when laying several meshes side by side
with :meth:Layer.juxtapose.
Unlike a layer-level :class:Affine, this mutates the data-frame vertices in
place, so it normalizes the geometry as it currently stands (after any earlier
mesh-mutating transforms) and ignores prior global affine transforms — matching
how :class:PrincipalAxes reads object-space positions.
Attributes:
| Name | Type | Description |
|---|---|---|
normalize_normals |
bool
|
Re-normalize normal attributes to unit length. Default True. |
normalize_tangents_bitangents |
bool
|
Re-normalize tangent/bitangent attributes to unit length. Default True. |
Source code in hakowan/grammar/transform/transform.py
Compute
dataclass
¶
Bases: Transform
Compute new attributes from the current data frame.
Attributes:
| Name | Type | Description |
|---|---|---|
x |
str | None
|
Extract the x coordinate as an attribute. |
y |
str | None
|
Extract the y coordinate as an attribute. |
z |
str | None
|
Extract the z coordinate as an attribute. |
normal |
str | None
|
Compute the normal vector field as an attribute. |
vertex_normal |
str | None
|
Compute the vertex normal vector field as an attribute. |
facet_normal |
str | None
|
Compute the facet normal vector field as an attribute. |
component |
str | None
|
Compute connected component ids. |
Source code in hakowan/grammar/transform/transform.py
Explode
dataclass
¶
Bases: Transform
Explode data into multiple pieces.
Attributes:
| Name | Type | Description |
|---|---|---|
pieces |
AttributeLike
|
The attribute defining the pieces. |
magnitude |
float
|
The magnitude of the displacement. |
Source code in hakowan/grammar/transform/transform.py
Norm
dataclass
¶
Bases: Transform
Compute the row-wise norm of a given vector attribute.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
AttributeLike
|
The vector attribute to compute the norm on. |
norm_attr_name |
str
|
The name of the output norm attribute. |
order |
int
|
The order of the norm. Default is 2, which is the L2 norm. |
Source code in hakowan/grammar/transform/transform.py
Boundary
dataclass
¶
Bases: Transform
Compute the boundary of a mesh.
Attributes:
| Name | Type | Description |
|---|---|---|
attributes |
list[str]
|
The attributes to take into account when computing the boundary. i.e. discontinuities in these attributes will be considered as boundaries. |
Source code in hakowan/grammar/transform/transform.py
Streamline
dataclass
¶
Bases: Transform
Replace a triangular surface with traced vector- or cross-field curves.
Hakowan resolves facet, vertex, corner, and indexed three-channel fields to one tangent direction per facet. Vertex fields use Levi-Civita transport and symmetry-aware averaging (1-RoSy for vectors, 4-RoSy for cross fields); corner and indexed fields use arithmetic facet averaging. Traces cross triangle edges exactly and parallel-transport directions between facets.
The output mesh stores streamline points as vertices and consecutive line
segments as two-vertex facets. A per-vertex int32 attribute named by
id_attr_name identifies each streamline.
Attributes:
| Name | Type | Description |
|---|---|---|
vec_field |
AttributeLike
|
Three-channel vector attribute. Facet values are used directly; other supported domains are converted to facets. |
n |
int
|
Number of blue-noise seed facets. Default 50. Ordinary fields produce
up to |
cross_field |
bool
|
Treat the field as 4-RoSy. Default True. |
length |
float | None
|
Maximum object-space length per half-trace, measured before
layer-level affine transforms. A complete bidirectional trace can
approach twice this length. |
seed |
int
|
RNG seed passed to blue-noise sampling. Default 0. |
min_length |
int
|
Minimum retained sample-point count. Default 3. |
max_steps |
int | None
|
Edge-crossing cap per half-trace. |
id_attr_name |
str
|
Output per-vertex streamline-ID attribute name. Default
|
Source code in hakowan/grammar/transform/transform.py
Fur
dataclass
¶
Bases: Transform
Replace a surface with tapered strands flowing along a vector field.
Each strand is a short, tapered curve that grows from the surface, leans in
the direction of the vector field, and curls toward the surface flow — so a
dense collection of them reads as realistic fur combed along the field. The
output is a vertex-only mesh whose 2-vertex polygonal faces encode the line
segments of every strand, suitable for the curve mark paired with a
Hair material.
Two internal per-vertex attributes are written on the output mesh:
_hakowan_strand_id (int32) identifies which strand each point
belongs to, and _hakowan_strand_radius (float64) carries the
root-to-tip taper radius. The Blender backend groups points by strand id
into continuous tapered hair curves (rendered with the Principled Hair BSDF
when a Hair material is used); the Mitsuba and WebGL backends render the
same strands as tapered tubes, using the strand radius as the curve size
when no size channel is set.
All lengths below are measured in object space on the data-frame mesh (before any layer-level affine transforms).
Attributes:
| Name | Type | Description |
|---|---|---|
vec_field |
AttributeLike
|
The per-facet vector field attribute name. Vertex- or corner-domain attributes are averaged to per-facet first. |
n |
int
|
Number of fur strands to grow. Seed points are drawn area-uniformly over the surface. Default 2000. |
length |
float | None
|
Strand length. |
lift |
float
|
Angle in degrees by which each strand rises off the surface at its root (0 = lies flat along the field, 90 = stands straight up). Default 30. |
curl |
float
|
How strongly the strand curls back toward the surface flow direction as it grows (0 = straight, larger = more droop). Default 0.35. |
segments |
int
|
Number of segments per strand (points per strand is
|
root_radius |
float | None
|
Strand radius at the root. |
tip_radius |
float
|
Strand radius at the tip. Default 0 (pointed hair tip). |
randomness |
float
|
Amount of natural per-strand variation in length, lift,
direction and curl, in |
follow_surface |
bool
|
When True, trace each strand as a short streamline on the
surface (following the field and the surface curvature) and give it
only a gentle lift/curl, so it hugs the surface instead of standing
off it. When False (default), strands are analytic and lean off the
surface by |
children |
int
|
Number of child hairs grown around each guide strand for dense,
clumped fur. |
clump |
float
|
How strongly child-hair tips converge onto their guide strand, in
|
spread |
float | None
|
Radius over which child-hair roots scatter around each guide
root. |
seed |
int
|
RNG seed for seed-point sampling and per-strand variation. Default 0. |
Source code in hakowan/grammar/transform/transform.py
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | |