texture
triwarp.texture
Bake per-vertex attributes into UV-space textures and sample them back.
The four functions here operate on an existing UV map (from a disk parameterization or a
mesh file, e.g. loaded via load_mesh): they rasterize per-vertex
attributes into a square texture and sample a texture back to per-vertex values. They are a
Warp software-rasterizer replacement for an OpenGL/moderngl pipeline, keeping all data on the
input Warp device.
Computing a UV map from mesh connectivity (parameterization) is a separate concern and is not part of this module.
See rasterize_attribute,
rasterize_discrete_attribute,
remap_attribute_from_uv, and
remap_discrete_attribute_from_uv.
rasterize_attribute
rasterize_attribute(
uv: array[vec2],
faces: array[int32],
attribute: Array2dFloat32,
resolution: int,
) -> twt.Array3dFloat32
Rasterize a per-vertex attribute into a square UV-space texture.
Each triangle is rasterized in UV space and its per-vertex attribute is barycentrically
interpolated at every covered pixel center. Pixels not covered by any triangle stay 0.
Where triangles overlap (degenerate for a valid parameterization), the lowest-index face wins.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uv
|
array[vec2]
|
|
required |
faces
|
array[int32]
|
Flat length- |
required |
attribute
|
Array2dFloat32
|
|
required |
resolution
|
int
|
Output image size in pixels (square). |
required |
Returns:
| Type | Description |
|---|---|
Array3dFloat32
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
RuntimeError
|
If |
Source code in triwarp/texture.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
rasterize_discrete_attribute
rasterize_discrete_attribute(
uv: array[vec2],
faces: array[int32],
attribute: array[int32],
resolution: int,
) -> twt.Array2dInt32
Rasterize a per-vertex discrete label into a square UV-space class image.
At each covered pixel the label with the greatest barycentric weight is emitted (weights of
vertices sharing a label sum; ties resolve to the lowest label value). This is equivalent to
one-hot encoding the labels, interpolating, and taking the per-pixel argmax. Pixels not
covered by any triangle are set to -1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uv
|
array[vec2]
|
|
required |
faces
|
array[int32]
|
Flat length- |
required |
attribute
|
array[int32]
|
|
required |
resolution
|
int
|
Output image size in pixels (square). |
required |
Returns:
| Type | Description |
|---|---|
Array2dInt32
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If any entry of |
RuntimeError
|
If |
Source code in triwarp/texture.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
remap_attribute_from_uv
remap_attribute_from_uv(
uv: array[vec2],
image: Array2dFloat32 | Array3dFloat32,
*,
order: Literal[0, 1] = 1,
) -> twt.Array2dFloat32
Sample a UV-space texture back to per-vertex values.
Inverse of rasterize_attribute.
Sampling uses the same pixel-center convention as
rasterize_attribute (col = u * W - 0.5,
row = (1 - v) * H - 0.5) and clamps to the nearest edge pixel, so vertices on the
coverage boundary read the boundary value instead of blending toward 0. Vertices whose
UV is non-finite are not sampled; their output row is NaN on every channel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uv
|
array[vec2]
|
|
required |
image
|
Array2dFloat32 | Array3dFloat32
|
UV-space texture to sample, |
required |
order
|
Literal[0, 1]
|
Interpolation order: |
1
|
Returns:
| Type | Description |
|---|---|
Array2dFloat32
|
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
RuntimeError
|
If |
See Also
Source code in triwarp/texture.py
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | |
remap_discrete_attribute_from_uv
remap_discrete_attribute_from_uv(
uv: array[vec2], class_image: Array2dInt32
) -> twt.Array1dInt32
Sample a UV-space class image back to per-vertex labels.
Inverse of rasterize_discrete_attribute.
Nearest-neighbor sampling is used so labels are never blended, including the -1 uncovered
sentinel. Vertices whose UV is non-finite cannot be sampled and map to the same -1
sentinel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uv
|
array[vec2]
|
|
required |
class_image
|
Array2dInt32
|
|
required |
Returns:
| Type | Description |
|---|---|
Array1dInt32
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If any finite UV lies outside |
RuntimeError
|
If |
Source code in triwarp/texture.py
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 | |